UX: Preview multiple color schemes in wizard (#6151)

It was a dropdown to provide choices of color schemes,
and only one scheme could be shown.
With this commit, multiple color scheme previews can be displayed on
one page at the same time, making admins choose color schemes more
easily.

Theme preview windows are shrinked.

Imported default color schemes.

Co-Authored-By: Misaka 0x4e21 <misaka4e21@gmail.com>
This commit is contained in:
Joffrey JAFFEUX
2018-07-24 09:00:20 -04:00
committed by GitHub
parent c3b6811651
commit 7a3c541077
12 changed files with 243 additions and 87 deletions

View File

@@ -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

View File

@@ -0,0 +1,7 @@
export default Ember.Component.extend({
actions: {
changed(value) {
this.set("field.value", value);
}
}
});

View File

@@ -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);

View File

@@ -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;
}

View File

@@ -0,0 +1,13 @@
<ul class="grid">
{{#each field.choices as |choice|}}
<li>
{{theme-preview colorsId=choice.id
wizard=wizard
onChange="changed"}}
{{radio-button radioValue=choice.id
label=choice.id
value=field.value
onChange="changed"}}
</li>
{{/each}}
</ul>