diff --git a/app/assets/javascripts/wizard/components/theme-preview.js.es6 b/app/assets/javascripts/wizard/components/theme-preview.js.es6
index 23045e5675a..738be14f695 100644
--- a/app/assets/javascripts/wizard/components/theme-preview.js.es6
+++ b/app/assets/javascripts/wizard/components/theme-preview.js.es6
@@ -3,14 +3,18 @@ import { observes } from "ember-addons/ember-computed-decorators";
import {
createPreviewComponent,
darkLightDiff,
- chooseBrighter,
+ chooseDarker,
LOREM
} from "wizard/lib/preview";
-export default createPreviewComponent(659, 320, {
+export default createPreviewComponent(225, 120, {
logo: null,
avatar: null,
+ click() {
+ this.sendAction("onChange", this.get("colorsId"));
+ },
+
@observes("step.fieldsById.base_scheme_id.value")
themeChanged() {
this.triggerRepaint();
@@ -24,19 +28,19 @@ export default createPreviewComponent(659, 320, {
},
paint(ctx, colors, width, height) {
- const headerHeight = height * 0.15;
+ const headerHeight = height * 0.3;
this.drawFullHeader(colors);
- const margin = width * 0.02;
- const avatarSize = height * 0.1;
- const lineHeight = height / 19.0;
+ const margin = width * 0.04;
+ const avatarSize = height * 0.2;
+ const lineHeight = height / 9.5;
// Draw a fake topic
this.scaleImage(
this.avatar,
margin,
- headerHeight + height * 0.17,
+ headerHeight + height * 0.085,
avatarSize,
avatarSize
);
@@ -46,33 +50,48 @@ export default createPreviewComponent(659, 320, {
ctx.beginPath();
ctx.fillStyle = colors.primary;
ctx.font = `bold ${titleFontSize}em 'Arial'`;
- ctx.fillText("Welcome to Discourse", margin, height * 0.25);
+ ctx.fillText(I18n.t("wizard.previews.topic_title"), margin, height * 0.3);
- const bodyFontSize = height / 440.0;
+ const bodyFontSize = height / 220.0;
ctx.font = `${bodyFontSize}em 'Arial'`;
let line = 0;
const lines = LOREM.split("\n");
- for (let i = 0; i < 10; i++) {
- line = height * 0.3 + i * lineHeight;
+ for (let i = 0; i < 4; i++) {
+ line = height * 0.35 + i * lineHeight;
ctx.fillText(lines[i], margin + avatarSize + margin, line);
}
+ // Share Button
+ ctx.beginPath();
+ ctx.rect(margin, line + lineHeight, width * 0.14, height * 0.14);
+ ctx.fillStyle = darkLightDiff(colors.primary, colors.secondary, 90, 65);
+ ctx.fill();
+ ctx.fillStyle = chooseDarker(colors.primary, colors.secondary);
+ ctx.font = `${bodyFontSize}em 'Arial'`;
+ ctx.fillText(
+ I18n.t("wizard.previews.share_button"),
+ margin + width / 55,
+ line + lineHeight * 1.85
+ );
+
// Reply Button
ctx.beginPath();
- ctx.rect(width * 0.57, line + lineHeight, width * 0.1, height * 0.07);
+ ctx.rect(
+ margin * 2 + width * 0.14,
+ line + lineHeight,
+ width * 0.14,
+ height * 0.14
+ );
ctx.fillStyle = colors.tertiary;
ctx.fill();
- ctx.fillStyle = chooseBrighter(colors.primary, colors.secondary);
+ ctx.fillStyle = colors.secondary;
ctx.font = `${bodyFontSize}em 'Arial'`;
- ctx.fillText("Reply", width * 0.595, line + lineHeight * 1.85);
-
- // Icons
- ctx.font = `${bodyFontSize}em FontAwesome`;
- ctx.fillStyle = colors.love;
- ctx.fillText("\uf004", width * 0.48, line + lineHeight * 1.8);
- ctx.fillStyle = darkLightDiff(colors.primary, colors.secondary, 65, 55);
- ctx.fillText("\uf040", width * 0.525, line + lineHeight * 1.8);
+ ctx.fillText(
+ I18n.t("wizard.previews.reply_button"),
+ margin * 2 + width * 0.14 + width / 55,
+ line + lineHeight * 1.85
+ );
// Draw Timeline
const timelineX = width * 0.8;
@@ -80,7 +99,7 @@ export default createPreviewComponent(659, 320, {
ctx.strokeStyle = colors.tertiary;
ctx.lineWidth = 0.5;
ctx.moveTo(timelineX, height * 0.3);
- ctx.lineTo(timelineX, height * 0.6);
+ ctx.lineTo(timelineX, height * 0.7);
ctx.stroke();
// Timeline
diff --git a/app/assets/javascripts/wizard/components/theme-previews.js.es6 b/app/assets/javascripts/wizard/components/theme-previews.js.es6
new file mode 100644
index 00000000000..57c74ccab27
--- /dev/null
+++ b/app/assets/javascripts/wizard/components/theme-previews.js.es6
@@ -0,0 +1,7 @@
+export default Ember.Component.extend({
+ actions: {
+ changed(value) {
+ this.set("field.value", value);
+ }
+ }
+});
diff --git a/app/assets/javascripts/wizard/lib/preview.js.es6 b/app/assets/javascripts/wizard/lib/preview.js.es6
index f3aee2439ac..887a72ba186 100644
--- a/app/assets/javascripts/wizard/lib/preview.js.es6
+++ b/app/assets/javascripts/wizard/lib/preview.js.es6
@@ -2,17 +2,14 @@
import getUrl from "discourse-common/lib/get-url";
export const LOREM = `
-Lorem ipsum dolor sit amet, consectetur adipiscing elit.
-Nullam eget sem non elit tincidunt rhoncus. Fusce velit nisl,
-porttitor sed nisl ac, consectetur interdum metus. Fusce in
-consequat augue, vel facilisis felis. Nunc tellus elit, and
-semper vitae orci nec, blandit pharetra enim. Aenean a ebus
-posuere nunc. Maecenas ultrices viverra enim ac commodo
-Vestibulum nec quam sit amet libero ultricies sollicitudin.
-Nulla quis scelerisque sem, eget volutpat velit. Fusce eget
-accumsan sapien, nec feugiat quam. Quisque non risus.
-placerat lacus vitae, lacinia nisi. Sed metus arcu, iaculis
-sit amet cursus nec, sodales at eros.`;
+Lorem ipsum dolor sit amet,
+consectetur adipiscing elit.
+Nullam eget sem non elit
+tincidunt rhoncus. Fusce
+velit nisl, porttitor sed
+nisl ac, consectetur interdum
+metus. Fusce in consequat
+augue, vel facilisis felis.`;
const scaled = {};
@@ -75,7 +72,9 @@ export function createPreviewComponent(width, height, obj) {
return false;
}
- const colors = this.get("wizard").getCurrentColors();
+ const colors = this.get("wizard").getCurrentColors(
+ this.get("colorsId")
+ );
if (!colors) {
return;
}
@@ -137,16 +136,10 @@ export function createPreviewComponent(width, height, obj) {
const headerMargin = headerHeight * 0.2;
const logoHeight = headerHeight - headerMargin * 2;
- if (this.logo) {
- const logoWidth = (logoHeight / this.logo.height) * this.logo.width;
- this.scaleImage(
- this.logo,
- headerMargin,
- headerMargin,
- logoWidth,
- logoHeight
- );
- }
+ ctx.beginPath();
+ ctx.fillStyle = colors.header_primary;
+ ctx.font = `bold ${logoHeight}px 'Arial'`;
+ ctx.fillText("Discourse", headerMargin, headerHeight - headerMargin);
// Top right menu
this.scaleImage(
@@ -370,6 +363,14 @@ export function chooseBrighter(primary, secondary) {
: primary;
}
+export function chooseDarker(primary, secondary) {
+ if (chooseBrighter(primary, secondary) === primary) {
+ return secondary;
+ } else {
+ return primary;
+ }
+}
+
export function darkLightDiff(adjusted, comparison, lightness, darkness) {
const adjustedCol = parseColor(adjusted);
const comparisonCol = parseColor(comparison);
diff --git a/app/assets/javascripts/wizard/models/wizard.js.es6 b/app/assets/javascripts/wizard/models/wizard.js.es6
index 28dc9f02973..95fa48bfb03 100644
--- a/app/assets/javascripts/wizard/models/wizard.js.es6
+++ b/app/assets/javascripts/wizard/models/wizard.js.es6
@@ -23,18 +23,18 @@ const Wizard = Ember.Object.extend({
},
// A bit clunky, but get the current colors from the appropriate step
- getCurrentColors() {
+ getCurrentColors(schemeId) {
const colorStep = this.get("steps").findBy("id", "colors");
if (!colorStep) {
return;
}
- const themeChoice = colorStep.get("fieldsById.base_scheme_id");
+ const themeChoice = colorStep.get("fieldsById.theme_previews");
if (!themeChoice) {
return;
}
- const themeId = themeChoice.get("value");
+ const themeId = schemeId ? schemeId : themeChoice.get("value");
if (!themeId) {
return;
}
diff --git a/app/assets/javascripts/wizard/templates/components/theme-previews.hbs b/app/assets/javascripts/wizard/templates/components/theme-previews.hbs
new file mode 100644
index 00000000000..34e5ea8e32f
--- /dev/null
+++ b/app/assets/javascripts/wizard/templates/components/theme-previews.hbs
@@ -0,0 +1,13 @@
+
+ {{#each field.choices as |choice|}}
+ -
+ {{theme-preview colorsId=choice.id
+ wizard=wizard
+ onChange="changed"}}
+ {{radio-button radioValue=choice.id
+ label=choice.id
+ value=field.value
+ onChange="changed"}}
+
+ {{/each}}
+
diff --git a/app/assets/stylesheets/wizard.scss b/app/assets/stylesheets/wizard.scss
index ef006c48d1a..ce145bb11b3 100644
--- a/app/assets/stylesheets/wizard.scss
+++ b/app/assets/stylesheets/wizard.scss
@@ -40,7 +40,9 @@ body.wizard {
}
.wizard-warning {
- font-family: sans-serif, p {
+ font-family: sans-serif;
+
+ p {
margin-top: 0;
}
@@ -71,6 +73,11 @@ body.wizard {
font-weight: bold;
}
+.wizard-step-form {
+ max-height: 500px;
+ overflow-y: auto;
+}
+
.wizard-step-emoji {
.radio-area {
display: flex;
@@ -106,6 +113,29 @@ body.wizard {
}
}
+.wizard-step-colors {
+ .grid {
+ margin: 0 auto;
+ list-style-type: none;
+ text-align: center;
+
+ li {
+ display: inline-block;
+ vertical-align: top;
+ margin: 15px;
+ .radio-area {
+ text-align: left;
+ font-size: 14px;
+ font-weight: bold;
+ & > * {
+ position: relative;
+ right: 7px;
+ }
+ }
+ }
+ }
+}
+
.wizard-column {
position: relative;
z-index: 11;
@@ -483,6 +513,9 @@ body.wizard {
.wizard-column {
margin: auto !important;
}
+ .wizard-step-form {
+ max-height: auto;
+ }
.wizard-step-contents {
min-height: auto !important;
}
diff --git a/app/models/color_scheme.rb b/app/models/color_scheme.rb
index d03b865c7ea..22dcd2c92fe 100644
--- a/app/models/color_scheme.rb
+++ b/app/models/color_scheme.rb
@@ -5,7 +5,7 @@ require_dependency 'distributed_cache'
class ColorScheme < ActiveRecord::Base
CUSTOM_SCHEMES = {
- dark: {
+ 'Dark': {
"primary" => 'dddddd',
"secondary" => '222222',
"tertiary" => '0f82af',
@@ -16,6 +16,84 @@ class ColorScheme < ActiveRecord::Base
"danger" => 'e45735',
"success" => '1ca551',
"love" => 'fa6c8d'
+ },
+ # By @itsbhanusharma
+ 'Neutral': {
+ "primary" => '000000',
+ "secondary" => 'ffffff',
+ "tertiary" => '51839b',
+ "quaternary" => 'b85e48',
+ "header_background" => '333333',
+ "header_primary" => 'f3f3f3',
+ "highlight" => 'ecec70',
+ "danger" => 'b85e48',
+ "success" => '518751',
+ "love" => 'fa6c8d'
+ },
+ # By @Flower_Child
+ 'Grey Amber': {
+ "primary" => 'd9d9d9',
+ "secondary" => '3d4147',
+ "tertiary" => 'fdd459',
+ "quaternary" => 'fdd459',
+ "header_background" => '36393e',
+ "header_primary" => 'd9d9d9',
+ "highlight" => 'fdd459',
+ "danger" => 'e45735',
+ "success" => 'fdd459',
+ "love" => 'fdd459'
+ },
+ # By @awesomerobot
+ 'Shades of Blue': {
+ "primary" => '203243',
+ "secondary" => 'eef4f7',
+ "tertiary" => '416376',
+ "quaternary" => '5e99b9',
+ "header_background" => '86bddb',
+ "header_primary" => 'ffffff',
+ "highlight" => '86bddb',
+ "danger" => 'bf3c3c',
+ "success" => '70db82',
+ "love" => 'fc94cb'
+ },
+ # By @mikechristopher
+ 'Latte': {
+ "primary" => 'f2e507',
+ "secondary" => '262322',
+ "tertiary" => 'f7f2ed',
+ "quaternary" => 'd7c9aa',
+ "header_background" => 'd7c9aa',
+ "header_primary" => '262322',
+ "highlight" => 'd7c9aa',
+ "danger" => 'db9584',
+ "success" => '78be78',
+ "love" => '8f6201'
+ },
+ # By @Flower_Child
+ 'Summer': {
+ "primary" => '874342',
+ "secondary" => 'fffff4',
+ "tertiary" => 'fe9896',
+ "quaternary" => 'fcc9d0',
+ "header_background" => '96ccbf',
+ "header_primary" => 'fff1e7',
+ "highlight" => 'f3c07f',
+ "danger" => 'cfebdc',
+ "success" => 'fcb4b5',
+ "love" => 'f3c07f'
+ },
+ # By @Flower_Child
+ 'Dark Rose': {
+ "primary" => 'ca9cb2',
+ "secondary" => '3a2a37',
+ "tertiary" => 'fdd459',
+ "quaternary" => '7e566a',
+ "header_background" => 'a97189',
+ "header_primary" => 'd9b2bb',
+ "highlight" => '6c3e63',
+ "danger" => '6c3e63',
+ "success" => 'd9b2bb',
+ "love" => 'd9b2bb'
}
}
@@ -26,7 +104,7 @@ class ColorScheme < ActiveRecord::Base
end
list = [
- { id: 'default', colors: base_with_hash }
+ { id: 'Light', colors: base_with_hash }
]
CUSTOM_SCHEMES.each do |k, v|
@@ -71,7 +149,7 @@ class ColorScheme < ActiveRecord::Base
def self.base_color_schemes
base_color_scheme_colors.map do |hash|
- scheme = new(name: I18n.t("color_schemes.#{hash[:id]}"), base_scheme_id: hash[:id])
+ scheme = new(name: I18n.t("color_schemes.#{hash[:id].downcase.gsub(' ', '_')}"), base_scheme_id: hash[:id])
scheme.colors = hash[:colors].map { |k, v| { name: k.to_s, hex: v.sub("#", "") } }
scheme.is_base = true
scheme
@@ -140,7 +218,7 @@ class ColorScheme < ActiveRecord::Base
def base_colors
colors = nil
- if base_scheme_id && base_scheme_id != "default"
+ if base_scheme_id && base_scheme_id != "Light"
colors = CUSTOM_SCHEMES[base_scheme_id.to_sym]
end
colors || ColorScheme.base_colors
@@ -148,7 +226,7 @@ class ColorScheme < ActiveRecord::Base
def resolved_colors
resolved = ColorScheme.base_colors.dup
- if base_scheme_id && base_scheme_id != "default"
+ if base_scheme_id && base_scheme_id != "Light"
if scheme = CUSTOM_SCHEMES[base_scheme_id.to_sym]
scheme.each do |name, value|
resolved[name] = value
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 111713f7735..edb33eda8f0 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -3995,3 +3995,8 @@ en:
admin: "Admin"
moderator: "Moderator"
regular: "Regular User"
+
+ previews:
+ topic_title: "Discussion topic"
+ share_button: "Share"
+ reply_button: "Reply"
diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml
index 2e07af6bd18..7ec50e083a7 100644
--- a/config/locales/server.en.yml
+++ b/config/locales/server.en.yml
@@ -3185,11 +3185,23 @@ en:
color_schemes:
base_theme_name: "Base"
- default: "Light Scheme"
+ light: "Light Scheme"
dark: "Dark Scheme"
- default_theme_name: "Default"
- dark_theme_name: "Dark"
+ neutral: "Neutral Scheme"
+ grey_amber: "Grey Amber Scheme"
+ shades_of_blue: "Shades of Blue Scheme"
+ latte: "Latte Scheme"
+ summer: "Summer Scheme"
+ dark_rose: "Dark Rose Scheme"
+ default_theme_name: "Light"
light_theme_name: "Light"
+ dark_theme_name: "Dark"
+ neutral_theme_name: "Neutral"
+ grey_amber_theme_name: "Grey Amber"
+ shades_of_blue_theme_name: "Shades of Blue"
+ latte_theme_name: "Latte"
+ summer_theme_name: "Summer"
+ dark_rose_theme_name: "Dark Rose"
about: "About"
guidelines: "Guidelines"
diff --git a/db/fixtures/600_themes.rb b/db/fixtures/600_themes.rb
index 0575e1ea29d..be8ee222a84 100644
--- a/db/fixtures/600_themes.rb
+++ b/db/fixtures/600_themes.rb
@@ -2,9 +2,9 @@
if !Theme.exists?
STDERR.puts "> Seeding dark and light themes"
- name = I18n.t("wizard.step.colors.fields.theme_id.choices.dark.label")
- dark_scheme = ColorScheme.find_by(base_scheme_id: "dark")
- dark_scheme ||= ColorScheme.create_from_base(name: name, via_wizard: true, base_scheme_id: "dark")
+ name = I18n.t("color_schemes.dark_theme_name")
+ dark_scheme = ColorScheme.find_by(base_scheme_id: "Dark")
+ dark_scheme ||= ColorScheme.create_from_base(name: name, via_wizard: true, base_scheme_id: "Dark")
name = I18n.t('color_schemes.dark_theme_name')
_dark_theme = Theme.create(name: name, user_id: -1,
diff --git a/lib/wizard/builder.rb b/lib/wizard/builder.rb
index eb5f7d04b1e..1d7a2e5a4b0 100644
--- a/lib/wizard/builder.rb
+++ b/lib/wizard/builder.rb
@@ -118,39 +118,27 @@ class Wizard
@wizard.append_step('colors') do |step|
default_theme = Theme.find_by(id: SiteSetting.default_theme_id)
- scheme_id = default_theme&.color_scheme&.base_scheme_id || 'default'
+ scheme_id = default_theme&.color_scheme&.base_scheme_id || 'Light'
- themes = step.add_field(id: 'base_scheme_id', type: 'dropdown', required: true, value: scheme_id)
+ themes = step.add_field(id: 'theme_previews', type: 'component', required: true, value: scheme_id)
ColorScheme.base_color_scheme_colors.each do |t|
with_hash = t[:colors].dup
with_hash.map { |k, v| with_hash[k] = "##{v}" }
themes.add_choice(t[:id], data: { colors: with_hash })
end
- step.add_field(id: 'theme_preview', type: 'component')
step.on_update do |updater|
- scheme_name = updater.fields[:base_scheme_id]
+ scheme_name = updater.fields[:theme_previews] || 'Light'
+ name = I18n.t("color_schemes.#{scheme_name.downcase.gsub(' ', '_')}_theme_name")
theme = nil
+ scheme = ColorScheme.find_by(base_scheme_id: scheme_name, via_wizard: true)
+ scheme ||= ColorScheme.create_from_base(name: name, via_wizard: true, base_scheme_id: scheme_name)
+ themes = Theme.where(color_scheme_id: scheme.id).order(:id).to_a
+ theme = themes.find(&:default?)
+ theme ||= themes.first
- if scheme_name == "dark"
- scheme = ColorScheme.find_by(base_scheme_id: 'dark', via_wizard: true)
-
- name = I18n.t("wizard.step.colors.fields.theme_id.choices.dark.label")
- scheme ||= ColorScheme.create_from_base(name: name, via_wizard: true, base_scheme_id: "dark")
-
- theme = Theme.find_by(color_scheme_id: scheme.id)
- name = I18n.t('color_schemes.dark_theme_name')
- theme ||= Theme.create(name: name, color_scheme_id: scheme.id, user_id: @wizard.user.id)
- else
- themes = Theme.where(color_scheme_id: nil).order(:id).to_a
- theme = themes.find(&:default?)
- theme ||= themes.first
-
- name = I18n.t('color_schemes.light_theme_name')
- theme ||= Theme.create(name: name, user_id: @wizard.user.id)
- end
-
+ theme ||= Theme.create(name: name, user_id: @wizard.user.id, color_scheme_id: scheme.id)
theme.set_default!
end
end
diff --git a/spec/components/wizard/step_updater_spec.rb b/spec/components/wizard/step_updater_spec.rb
index d10c2120e9e..0a858c8b888 100644
--- a/spec/components/wizard/step_updater_spec.rb
+++ b/spec/components/wizard/step_updater_spec.rb
@@ -151,12 +151,12 @@ describe Wizard::StepUpdater do
let!(:color_scheme) { Fabricate(:color_scheme, name: 'existing', via_wizard: true) }
it "updates the scheme" do
- updater = wizard.create_updater('colors', base_scheme_id: 'dark')
+ updater = wizard.create_updater('colors', theme_previews: 'Dark')
updater.update
expect(updater.success?).to eq(true)
expect(wizard.completed_steps?('colors')).to eq(true)
theme = Theme.find_by(id: SiteSetting.default_theme_id)
- expect(theme.color_scheme.base_scheme_id).to eq('dark')
+ expect(theme.color_scheme.base_scheme_id).to eq('Dark')
end
end
@@ -167,14 +167,14 @@ describe Wizard::StepUpdater do
context 'dark theme' do
it "creates the theme" do
- updater = wizard.create_updater('colors', base_scheme_id: 'dark', allow_dark_light_selection: true)
+ updater = wizard.create_updater('colors', theme_previews: 'Dark', allow_dark_light_selection: true)
expect { updater.update }.to change { Theme.count }.by(1)
theme = Theme.last
expect(theme.user_id).to eq(wizard.user.id)
- expect(theme.color_scheme.base_scheme_id).to eq('dark')
+ expect(theme.color_scheme.base_scheme_id).to eq('Dark')
end
end
@@ -187,14 +187,14 @@ describe Wizard::StepUpdater do
theme = Theme.last
expect(theme.user_id).to eq(wizard.user.id)
- expect(theme.color_scheme).to eq(nil)
+ expect(theme.color_scheme).to eq(ColorScheme.find_by(name: 'Light'))
end
end
end
context "without an existing scheme" do
it "creates the scheme" do
- updater = wizard.create_updater('colors', base_scheme_id: 'dark', allow_dark_light_selection: true)
+ updater = wizard.create_updater('colors', theme_previews: 'Dark', allow_dark_light_selection: true)
updater.update
expect(updater.success?).to eq(true)
expect(wizard.completed_steps?('colors')).to eq(true)