parent
1912fc3766
commit
906692e78f
1
Gemfile
1
Gemfile
|
@ -40,6 +40,7 @@ gem 'fog-aws'
|
||||||
gem 'momentjs-rails', '>= 2.9.0'
|
gem 'momentjs-rails', '>= 2.9.0'
|
||||||
gem 'bootstrap3-datetimepicker-rails', '~> 4.7.14'
|
gem 'bootstrap3-datetimepicker-rails', '~> 4.7.14'
|
||||||
gem 'tiny-color-rails'
|
gem 'tiny-color-rails'
|
||||||
|
gem 'jquery-minicolors-rails'
|
||||||
|
|
||||||
gem 'twemoji-rails'
|
gem 'twemoji-rails'
|
||||||
|
|
||||||
|
|
|
@ -231,6 +231,9 @@ GEM
|
||||||
jbuilder (2.2.13)
|
jbuilder (2.2.13)
|
||||||
activesupport (>= 3.0.0, < 5)
|
activesupport (>= 3.0.0, < 5)
|
||||||
multi_json (~> 1.2)
|
multi_json (~> 1.2)
|
||||||
|
jquery-minicolors-rails (2.1.4.0)
|
||||||
|
jquery-rails
|
||||||
|
rails (>= 3.2.8)
|
||||||
jquery-rails (4.0.3)
|
jquery-rails (4.0.3)
|
||||||
rails-dom-testing (~> 1.0)
|
rails-dom-testing (~> 1.0)
|
||||||
railties (>= 4.2.0)
|
railties (>= 4.2.0)
|
||||||
|
@ -513,6 +516,7 @@ DEPENDENCIES
|
||||||
haml
|
haml
|
||||||
i18n-js
|
i18n-js
|
||||||
jbuilder (~> 2.2.4)
|
jbuilder (~> 2.2.4)
|
||||||
|
jquery-minicolors-rails
|
||||||
jquery-rails
|
jquery-rails
|
||||||
jquery-turbolinks
|
jquery-turbolinks
|
||||||
letter_opener
|
letter_opener
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#= require i18n
|
#= require i18n
|
||||||
#= require i18n/translations
|
#= require i18n/translations
|
||||||
#= require tinycolor-min
|
#= require tinycolor-min
|
||||||
|
#= require jquery.minicolors
|
||||||
# local requires to be seen by everyone:
|
# local requires to be seen by everyone:
|
||||||
#= require_tree ./answerbox
|
#= require_tree ./answerbox
|
||||||
#= require_tree ./questionbox
|
#= require_tree ./questionbox
|
||||||
|
|
|
@ -99,3 +99,57 @@ if window.URL? or window.webkitURL?
|
||||||
($ '#profile-header-crop-controls').slideDown()
|
($ '#profile-header-crop-controls').slideDown()
|
||||||
|
|
||||||
cropper.attr 'src', src
|
cropper.attr 'src', src
|
||||||
|
|
||||||
|
# theming
|
||||||
|
|
||||||
|
previewStyle = document.createElement 'style'
|
||||||
|
document.head.appendChild previewStyle
|
||||||
|
|
||||||
|
previewTimeout = null
|
||||||
|
|
||||||
|
previewTheme = ->
|
||||||
|
payload = {}
|
||||||
|
|
||||||
|
$('#update_theme').find('.color').each ->
|
||||||
|
n = this.name.substr 6, this.name.length - 7
|
||||||
|
payload[n] = parseInt this.value.substr(1, 6), 16
|
||||||
|
|
||||||
|
$.post '/settings/theme/preview.css', payload, (data) ->
|
||||||
|
previewStyle.innerHTML = data
|
||||||
|
, 'text'
|
||||||
|
|
||||||
|
null
|
||||||
|
|
||||||
|
themePresets = {
|
||||||
|
rs: [0x5E35B1, 0xFFFFFF, 0xFF0039, 0xFFFFFF, 0x3FB618, 0xFFFFFF, 0xFF7518, 0xFFFFFF, 0x9954BB, 0xFFFFFF, 0x222222, 0xEEEEEE, 0xF9F9F9, 0x151515, 0x5E35B1, 0xFFFFFF, 0x222222, 0xbbbbbb],
|
||||||
|
dc: [0x222222, 0xeeeeee, 0x222222, 0xeeeeee, 0x222222, 0xeeeeee, 0x222222, 0xeeeeee, 0x222222, 0xeeeeee, 0x222222, 0xeeeeee, 0x222222, 0xeeeeee, 0x111111, 0x555555, 0xeeeeee, 0xbbbbbb],
|
||||||
|
lc: [0xdddddd, 0x111111, 0xdddddd, 0x111111, 0xdddddd, 0x111111, 0xdddddd, 0x111111, 0xdddddd, 0x111111, 0xdddddd, 0x111111, 0xdddddd, 0x111111, 0xeeeeee, 0xaaaaaa, 0x111111, 0x444444]
|
||||||
|
}
|
||||||
|
|
||||||
|
$(document).on 'submit', '#update_theme', (event) ->
|
||||||
|
$this = $ this
|
||||||
|
$this.find('.color').each ->
|
||||||
|
this.value = parseInt this.value.substr(1, 6), 16
|
||||||
|
true
|
||||||
|
|
||||||
|
$(document).ready ->
|
||||||
|
$('#update_theme .color').each ->
|
||||||
|
$this = $ this
|
||||||
|
this.value = '#' + ('000000' + parseInt(this.value).toString(16)).substr(-6, 6)
|
||||||
|
|
||||||
|
$this.minicolors
|
||||||
|
control: 'hue'
|
||||||
|
defaultValue: this.value
|
||||||
|
letterCase: 'lowercase'
|
||||||
|
position: 'bottom left'
|
||||||
|
theme: 'bootstrap'
|
||||||
|
inline: false
|
||||||
|
change: ->
|
||||||
|
clearTimeout previewTimeout
|
||||||
|
previewTimeout = setTimeout(previewTheme, 1000)
|
||||||
|
true
|
||||||
|
|
||||||
|
$(document).on 'click', 'a.theme_preset', (event) ->
|
||||||
|
preset = [].concat themePresets[this.dataset.preset]
|
||||||
|
$('#update_theme .color').each ->
|
||||||
|
$(this).minicolors 'value', '#' + ('000000' + parseInt(preset.shift()).toString(16)).substr(-6, 6)
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*= require growl
|
*= require growl
|
||||||
*= require jquery.guillotine
|
*= require jquery.guillotine
|
||||||
*= require sweet-alert
|
*= require sweet-alert
|
||||||
|
*= require jquery.minicolors
|
||||||
*= require flags
|
*= require flags
|
||||||
*= require_self
|
*= require_self
|
||||||
*/
|
*/
|
||||||
|
@ -63,3 +64,11 @@ body { padding-top: $navbar-height; }
|
||||||
$nprogress-color: lighten($navbar-inverse-bg, 25%);
|
$nprogress-color: lighten($navbar-inverse-bg, 25%);
|
||||||
@import 'nprogress';
|
@import 'nprogress';
|
||||||
@import 'nprogress-bootstrap';
|
@import 'nprogress-bootstrap';
|
||||||
|
|
||||||
|
.minicolors-theme-bootstrap .minicolors-swatch {
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 42px;
|
||||||
|
height: 42px;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ class UserController < ApplicationController
|
||||||
|
|
||||||
def update
|
def update
|
||||||
user_attributes = params.require(:user).permit(:display_name, :profile_picture, :profile_header, :motivation_header, :website,
|
user_attributes = params.require(:user).permit(:display_name, :profile_picture, :profile_header, :motivation_header, :website,
|
||||||
:location, :bio, :crop_x, :crop_y, :crop_w, :crop_h, :crop_h_x, :crop_h_y, :crop_h_w, :crop_h_h)
|
:location, :bio, :crop_x, :crop_y, :crop_w, :crop_h, :crop_h_x, :crop_h_y, :crop_h_w, :crop_h_h, :show_foreign_themes)
|
||||||
if current_user.update_attributes(user_attributes)
|
if current_user.update_attributes(user_attributes)
|
||||||
text = t('flash.user.update.text')
|
text = t('flash.user.update.text')
|
||||||
text += t('flash.user.update.avatar') if user_attributes[:profile_picture]
|
text += t('flash.user.update.avatar') if user_attributes[:profile_picture]
|
||||||
|
@ -97,6 +97,27 @@ class UserController < ApplicationController
|
||||||
def edit_theme
|
def edit_theme
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# NOTE: Yes, I am storing and transmitting values as 3 byte numbers because false sense of security.
|
||||||
|
def preview_theme
|
||||||
|
attrib = params.permit([
|
||||||
|
:primary_color, :primary_text,
|
||||||
|
:danger_color, :danger_text,
|
||||||
|
:success_color, :success_text,
|
||||||
|
:warning_color, :warning_text,
|
||||||
|
:info_color, :info_text,
|
||||||
|
:default_color, :default_text,
|
||||||
|
:panel_color, :panel_text,
|
||||||
|
:link_color, :background_color,
|
||||||
|
:background_text, :background_muted
|
||||||
|
])
|
||||||
|
|
||||||
|
attrib.each do |k ,v|
|
||||||
|
attrib[k] = v.to_i
|
||||||
|
end
|
||||||
|
|
||||||
|
render plain: render_theme_with_context(attrib)
|
||||||
|
end
|
||||||
|
|
||||||
def update_theme
|
def update_theme
|
||||||
update_attributes = params.require(:theme).permit([
|
update_attributes = params.require(:theme).permit([
|
||||||
:primary_color, :primary_text,
|
:primary_color, :primary_text,
|
||||||
|
@ -115,14 +136,14 @@ class UserController < ApplicationController
|
||||||
current_user.theme.user_id = current_user.id
|
current_user.theme.user_id = current_user.id
|
||||||
|
|
||||||
if current_user.theme.save
|
if current_user.theme.save
|
||||||
flash[:success] = t('flash.user.update_theme.success')
|
flash[:success] = 'Theme saved.'
|
||||||
else
|
else
|
||||||
flash[:error] = t('flash.user.update_theme.error')
|
flash[:error] = 'Theme saving failed.'
|
||||||
end
|
end
|
||||||
elsif current_user.theme.update_attributes(user_attributes)
|
elsif current_user.theme.update_attributes(update_attributes)
|
||||||
flash[:success] = t('flash.user.update_theme.success')
|
flash[:success] = 'Theme saved.'
|
||||||
else
|
else
|
||||||
flash[:error] = t('flash.user.update_theme.error')
|
flash[:error] = 'Theme saving failed.'
|
||||||
end
|
end
|
||||||
redirect_to edit_user_theme_path
|
redirect_to edit_user_theme_path
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,13 +15,13 @@ module ThemeHelper
|
||||||
|
|
||||||
x.each do |v|
|
x.each do |v|
|
||||||
next if hash[v].nil?
|
next if hash[v].nil?
|
||||||
self.instance_variable_set "@#{v}", hash[v].to_s(16)[-6, 6]
|
self.instance_variable_set "@#{v}", ('#' + ('0000000' + hash[v].to_s(16))[-6, 6])
|
||||||
end
|
end
|
||||||
elsif hash.is_a? Hash
|
elsif hash.is_a? Hash
|
||||||
hash.each do |k, v|
|
hash.each do |k, v|
|
||||||
next unless v.is_a? Fixnum
|
next unless v.is_a? Fixnum
|
||||||
|
|
||||||
self.instance_variable_set "@#{k}", v.to_s(16)[-6, 6]
|
self.instance_variable_set "@#{k}", ('#' + ('0000000' + hash[k].to_s(16))[-6, 6])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -15,14 +15,19 @@ class Theme < ActiveRecord::Base
|
||||||
greater_than_or_equal_to: 0, less_than_or_equal_to: 0xFFFFFF,
|
greater_than_or_equal_to: 0, less_than_or_equal_to: 0xFFFFFF,
|
||||||
allow_nil: true, only_integer: true
|
allow_nil: true, only_integer: true
|
||||||
|
|
||||||
|
has_attached_file :css, use_timestamp: false
|
||||||
|
validates_attachment_content_type :css, content_type: 'text/x-c'
|
||||||
|
|
||||||
before_save do
|
before_save do
|
||||||
style = StringIO.new(render_theme_with_context(self).render)
|
self.css = nil
|
||||||
|
|
||||||
|
style = StringIO.new(render_theme_with_context(self))
|
||||||
|
|
||||||
style.class.class_eval {
|
style.class.class_eval {
|
||||||
attr_accessor :original_filename, :content_type
|
attr_accessor :original_filename, :content_type
|
||||||
}
|
}
|
||||||
|
|
||||||
style.content_type = 'text/stylesheet'
|
style.content_type = 'text/x-c'
|
||||||
style.original_filename = 'theme.css'
|
style.original_filename = 'theme.css'
|
||||||
|
|
||||||
self.css = style
|
self.css = style
|
||||||
|
|
|
@ -12,10 +12,10 @@
|
||||||
%title= yield(:title)
|
%title= yield(:title)
|
||||||
= javascript_include_tag 'i18n', 'data-turbolinks-track' => true
|
= javascript_include_tag 'i18n', 'data-turbolinks-track' => true
|
||||||
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
|
= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track' => true
|
||||||
- if user_signed_in? and current_user.theme.present?
|
- if @user.present? and @user.theme.present? and (user_signed_in? and current_user.show_foreign_themes?)
|
||||||
%link{rel: 'stylesheet', href: current_user.theme.css.url, media: :all, 'data-turbolinks-track' => true}
|
|
||||||
- elsif @user.present? and @user.theme.present?
|
|
||||||
%link{rel: 'stylesheet', href: @user.theme.css.url, media: :all, 'data-turbolinks-track' => true}
|
%link{rel: 'stylesheet', href: @user.theme.css.url, media: :all, 'data-turbolinks-track' => true}
|
||||||
|
- elsif user_signed_in? and current_user.theme.present?
|
||||||
|
%link{rel: 'stylesheet', href: current_user.theme.css.url, media: :all, 'data-turbolinks-track' => true}
|
||||||
- else
|
- else
|
||||||
= javascript_include_tag 'application', 'data-turbolinks-track' => true
|
= javascript_include_tag 'application', 'data-turbolinks-track' => true
|
||||||
- if user_signed_in?
|
- if user_signed_in?
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
= list_group_item t('views.settings.tabs.profile'), edit_user_profile_path
|
= list_group_item t('views.settings.tabs.profile'), edit_user_profile_path
|
||||||
= list_group_item t('views.settings.tabs.privacy'), edit_user_privacy_path
|
= list_group_item t('views.settings.tabs.privacy'), edit_user_privacy_path
|
||||||
= list_group_item t('views.settings.tabs.sharing'), services_path
|
= list_group_item t('views.settings.tabs.sharing'), services_path
|
||||||
|
= list_group_item 'Theme', edit_user_theme_path
|
||||||
= list_group_item "Your Data", user_data_path
|
= list_group_item "Your Data", user_data_path
|
||||||
|
|
||||||
.hidden-xs= render "shared/links"
|
.hidden-xs= render "shared/links"
|
||||||
|
|
|
@ -51,6 +51,8 @@
|
||||||
|
|
||||||
= f.text_area :bio, label: t('views.settings.profile.bio'), placeholder: t('views.settings.profile.placeholder.bio')
|
= f.text_area :bio, label: t('views.settings.profile.bio'), placeholder: t('views.settings.profile.placeholder.bio')
|
||||||
|
|
||||||
|
= f.check_box :show_foreign_themes, label: 'Render other user themes when visiting their profile'
|
||||||
|
|
||||||
- for attrib in %i(crop_x crop_y crop_w crop_h)
|
- for attrib in %i(crop_x crop_y crop_w crop_h)
|
||||||
= f.hidden_field attrib, id: attrib
|
= f.hidden_field attrib, id: attrib
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
- provide(:title, generate_title("Theme Settings"))
|
||||||
|
.container.j2-page
|
||||||
|
= render 'settings_tabs'
|
||||||
|
.col-md-9.col-xs-12.col-sm-9
|
||||||
|
= render 'layouts/messages'
|
||||||
|
.panel.panel-default
|
||||||
|
.panel-body
|
||||||
|
%b Presets:
|
||||||
|
%a{href: '#', class: 'theme_preset', data: {preset: 'rs'}} Retrospring Purple,
|
||||||
|
%a{href: '#', class: 'theme_preset', data: {preset: 'dc'}} Dark Copycat,
|
||||||
|
%a{href: '#', class: 'theme_preset', data: {preset: 'lc'}} Light Copycat
|
||||||
|
= bootstrap_form_for(current_user.theme || Theme.new, url: {action: "update_theme"}, html: {id: 'update_theme'}, method: "patch") do |f|
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :primary_color, class: 'color', data: {default: 0x5E35B1}
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :primary_text, class: 'color', data: {default: 0xFFFFFF}
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :danger_color, class: 'color', data: {default: 0xFF0039}
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :danger_text, class: 'color', data: {default: 0xFFFFFF}
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :success_color, class: 'color', data: {default: 0x3FB618}
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :success_text, class: 'color', data: {default: 0xFFFFFF}
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :warning_color, class: 'color', data: {default: 0xFF7518}
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :warning_text, class: 'color', data: {default: 0xFFFFFF}
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :info_color, class: 'color', data: {default: 0x9954BB}
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :info_text, class: 'color', data: {default: 0xFFFFFF}
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :default_color, class: 'color', data: {default: 0x222222}
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :default_text, class: 'color', data: {default: 0xEEEEEE}
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :panel_color, class: 'color', data: {default: 0xF9F9F9}
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :panel_text, class: 'color', data: {default: 0x151515}
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :link_color, class: 'color', data: {default: 0x5E35B1}
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :background_color, class: 'color', data: {default: 0xFFFFFF}
|
||||||
|
.row
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :background_text, class: 'color', data: {default: 0x222222}
|
||||||
|
.col-md-6
|
||||||
|
= f.text_field :background_muted, class: 'color', data: {default: 0xBBBBBB}
|
||||||
|
|
||||||
|
= f.submit t('views.actions.save'), class: 'btn btn-primary'
|
|
@ -56,6 +56,7 @@ Rails.application.routes.draw do
|
||||||
|
|
||||||
match '/settings/theme', to: 'user#edit_theme', via: 'get', as: :edit_user_theme
|
match '/settings/theme', to: 'user#edit_theme', via: 'get', as: :edit_user_theme
|
||||||
match '/settings/theme', to: 'user#update_theme', via: 'patch', as: :update_user_theme
|
match '/settings/theme', to: 'user#update_theme', via: 'patch', as: :update_user_theme
|
||||||
|
match '/settings/theme/preview.css', to: 'user#preview_theme', via: 'post', as: :preview_user_theme
|
||||||
|
|
||||||
# resources :services, only: [:index, :destroy]
|
# resources :services, only: [:index, :destroy]
|
||||||
match '/settings/services', to: 'services#index', via: 'get', as: :services
|
match '/settings/services', to: 'services#index', via: 'get', as: :services
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
class AddShowForeignThemesToUsers < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :users, :show_foreign_themes, :boolean, default: true, null: false
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in New Issue