diff --git a/app/assets/javascripts/wizard/components/scheme-preview.js.es6 b/app/assets/javascripts/wizard/components/theme-preview.js.es6 similarity index 95% rename from app/assets/javascripts/wizard/components/scheme-preview.js.es6 rename to app/assets/javascripts/wizard/components/theme-preview.js.es6 index 484dafab5..2e676e296 100644 --- a/app/assets/javascripts/wizard/components/scheme-preview.js.es6 +++ b/app/assets/javascripts/wizard/components/theme-preview.js.es6 @@ -68,7 +68,7 @@ export default Ember.Component.extend({ loaded: false, logo: null, - colorScheme: Ember.computed.alias('step.fieldsById.color_scheme.value'), + themeId: Ember.computed.alias('step.fieldsById.theme_id.value'), didInsertElement() { this._super(); @@ -84,7 +84,7 @@ export default Ember.Component.extend({ }); }, - @observes('colorScheme') + @observes('themeId') triggerRepaint() { Ember.run.scheduleOnce('afterRender', this, 'repaint'); }, @@ -95,10 +95,10 @@ export default Ember.Component.extend({ const { ctx } = this; const headerHeight = HEIGHT * 0.15; - const colorScheme = this.get('colorScheme'); - const options = this.get('step.fieldsById.color_scheme.options'); - const option = options.findProperty('id', colorScheme); - if (!option) { return; } + const themeId = this.get('themeId'); + const choices = this.get('step.fieldsById.theme_id.choices'); + if (!choices) { return; } + const option = choices.findProperty('id', themeId); const colors = option.data.colors; if (!colors) { return; } diff --git a/app/assets/javascripts/wizard/components/wizard-step.js.es6 b/app/assets/javascripts/wizard/components/wizard-step.js.es6 index 026c4b671..079b333cf 100644 --- a/app/assets/javascripts/wizard/components/wizard-step.js.es6 +++ b/app/assets/javascripts/wizard/components/wizard-step.js.es6 @@ -48,20 +48,6 @@ export default Ember.Component.extend({ }); }, - saveStep() { - const step = this.get('step'); - step.save() - .then(() => this.sendAction('goNext')) - .catch(response => { - const errors = response.responseJSON.errors; - if (errors && errors.length) { - errors.forEach(err => { - step.fieldError(err.field, err.description); - }); - } - }); - }, - actions: { backStep() { if (this.get('saving')) { return; } @@ -77,7 +63,7 @@ export default Ember.Component.extend({ if (step.get('valid')) { this.set('saving', true); step.save() - .then(() => this.sendAction('goNext')) + .then(response => this.sendAction('goNext', response)) .catch(() => null) // we can swallow because the form is already marked as invalid .finally(() => this.set('saving', false)); } else { diff --git a/app/assets/javascripts/wizard/controllers/step.js.es6 b/app/assets/javascripts/wizard/controllers/step.js.es6 index e9bd4bce6..3a66e82d9 100644 --- a/app/assets/javascripts/wizard/controllers/step.js.es6 +++ b/app/assets/javascripts/wizard/controllers/step.js.es6 @@ -3,8 +3,13 @@ export default Ember.Controller.extend({ step: null, actions: { - goNext() { - this.transitionToRoute('step', this.get('step.next')); + goNext(response) { + const next = this.get('step.next'); + if (response.refresh_required) { + document.location = `/wizard/steps/${next}`; + } else { + this.transitionToRoute('step', next); + } }, goBack() { this.transitionToRoute('step', this.get('step.previous')); diff --git a/app/assets/javascripts/wizard/router.js.es6 b/app/assets/javascripts/wizard/router.js.es6 index 31d4aa861..57cea9cf6 100644 --- a/app/assets/javascripts/wizard/router.js.es6 +++ b/app/assets/javascripts/wizard/router.js.es6 @@ -1,9 +1,10 @@ const Router = Ember.Router.extend({ - location: Ember.testing ? 'none': 'hash' + rootURL: '/wizard', + location: Ember.testing ? 'none': 'history' }); -Router.map(function () { - this.route('step', { path: '/step/:step_id' }); +Router.map(function() { + this.route('step', { path: '/steps/:step_id' }); }); export default Router; diff --git a/app/assets/javascripts/wizard/templates/components/scheme-preview.hbs b/app/assets/javascripts/wizard/templates/components/theme-preview.hbs similarity index 100% rename from app/assets/javascripts/wizard/templates/components/scheme-preview.hbs rename to app/assets/javascripts/wizard/templates/components/theme-preview.hbs diff --git a/app/assets/javascripts/wizard/templates/components/wizard-field-dropdown.hbs b/app/assets/javascripts/wizard/templates/components/wizard-field-dropdown.hbs index 4f843aa3e..85dd971b0 100644 --- a/app/assets/javascripts/wizard/templates/components/wizard-field-dropdown.hbs +++ b/app/assets/javascripts/wizard/templates/components/wizard-field-dropdown.hbs @@ -1 +1 @@ -{{combo-box class=inputClassName value=field.value content=field.options nameProperty="label" width="400px"}} +{{combo-box class=inputClassName value=field.value content=field.choices nameProperty="label" width="400px"}} diff --git a/app/assets/javascripts/wizard/test/acceptance/wizard-test.js.es6 b/app/assets/javascripts/wizard/test/acceptance/wizard-test.js.es6 index af59f65dd..2e5c9d4f8 100644 --- a/app/assets/javascripts/wizard/test/acceptance/wizard-test.js.es6 +++ b/app/assets/javascripts/wizard/test/acceptance/wizard-test.js.es6 @@ -9,7 +9,7 @@ test("Wizard starts", assert => { }); test("Going back and forth in steps", assert => { - visit("/step/hello-world"); + visit("/steps/hello-world"); andThen(() => { assert.ok(exists('.wizard-step')); assert.ok(exists('.wizard-step-hello-world'), 'it adds a class for the step id'); diff --git a/app/assets/javascripts/wizard/test/wizard-pretender.js.es6 b/app/assets/javascripts/wizard/test/wizard-pretender.js.es6 index 546f61fd7..c85aceb0a 100644 --- a/app/assets/javascripts/wizard/test/wizard-pretender.js.es6 +++ b/app/assets/javascripts/wizard/test/wizard-pretender.js.es6 @@ -51,7 +51,7 @@ export default function() { index: 1, fields: [ { id: 'snack', type: 'dropdown', required: true }, - { id: 'scheme-preview', type: 'component' } + { id: 'theme-preview', type: 'component' } ], previous: 'hello-world' }] diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index f2c62bb52..0a13fde1d 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -11,7 +11,9 @@ class StepsController < ApplicationController updater.update(params[:fields]) if updater.success? - render json: success_json + result = { success: 'OK' } + result[:refresh_required] = true if updater.refresh_required? + render json: result else errors = [] updater.errors.messages.each do |field, msg| diff --git a/app/models/locale_site_setting.rb b/app/models/locale_site_setting.rb index b1e983abe..1cd924641 100644 --- a/app/models/locale_site_setting.rb +++ b/app/models/locale_site_setting.rb @@ -8,12 +8,21 @@ class LocaleSiteSetting < EnumSiteSetting def self.values supported_locales.map do |l| - {name: l, value: l} + lang = language_names[l] || language_names[l[0..1]] + {name: lang ? lang['nativeName'] : l, value: l} end end @lock = Mutex.new + def self.language_names + return @language_names if @language_names + + @lock.synchronize do + @language_names ||= YAML.load(File.read(File.join(Rails.root, 'config', 'locales', 'names.yml'))) + end + end + def self.supported_locales @lock.synchronize do @supported_locales ||= Dir.glob( File.join(Rails.root, 'config', 'locales', 'client.*.yml') ).map {|x| x.split('.')[-2]}.sort diff --git a/app/serializers/wizard_field_choice_serializer.rb b/app/serializers/wizard_field_choice_serializer.rb new file mode 100644 index 000000000..d364f0bdd --- /dev/null +++ b/app/serializers/wizard_field_choice_serializer.rb @@ -0,0 +1,26 @@ +class WizardFieldChoiceSerializer < ApplicationSerializer + attributes :id, :label, :data + + def id + object.id + end + + def label + return object.label if object.label.present? + + # Try getting one from a translation + field = object.field + step = field.step + I18n.t("wizard.step.#{step.id}.fields.#{field.id}.options.#{id}", default: id) + end + + def data + result = object.data.dup + result.delete(:id) + result + end + + def include_data? + object.data.present? + end +end diff --git a/app/serializers/wizard_field_serializer.rb b/app/serializers/wizard_field_serializer.rb index 7f69605ee..4a70098a5 100644 --- a/app/serializers/wizard_field_serializer.rb +++ b/app/serializers/wizard_field_serializer.rb @@ -1,6 +1,7 @@ class WizardFieldSerializer < ApplicationSerializer - attributes :id, :type, :required, :value, :label, :placeholder, :description, :options + attributes :id, :type, :required, :value, :label, :placeholder, :description + has_many :choices, serializer: WizardFieldChoiceSerializer, embed: :objects def id object.id @@ -50,24 +51,4 @@ class WizardFieldSerializer < ApplicationSerializer description.present? end - def options - object.options.map do |o| - - result = {id: o, label: I18n.t("#{i18n_key}.options.#{o}")} - - data = object.option_data[o] - if data.present? - as_json = data.dup - as_json.delete(:id) - result[:data] = as_json - end - - result - end - end - - def include_options? - object.options.present? - end - end diff --git a/app/services/color_scheme_revisor.rb b/app/services/color_scheme_revisor.rb index 1e864843f..5db7bb79d 100644 --- a/app/services/color_scheme_revisor.rb +++ b/app/services/color_scheme_revisor.rb @@ -21,6 +21,7 @@ class ColorSchemeRevisor @color_scheme.name = @params[:name] if @params.has_key?(:name) @color_scheme.enabled = @params[:enabled] if @params.has_key?(:enabled) + @color_scheme.theme_id = @params[:theme_id] if @params.has_key?(:theme_id) new_version = false if @params[:colors] @@ -30,7 +31,7 @@ class ColorSchemeRevisor end if new_version - old_version = ColorScheme.create( + ColorScheme.create( name: @color_scheme.name, enabled: false, colors: @color_scheme.colors_hashes, diff --git a/config/locales/names.yml b/config/locales/names.yml new file mode 100644 index 000000000..60e992501 --- /dev/null +++ b/config/locales/names.yml @@ -0,0 +1,559 @@ +--- +aa: + name: Afar + nativeName: Afaraf +ab: + name: Abkhaz + nativeName: аҧсуа бызшәа +ae: + name: Avestan + nativeName: avesta +af: + name: Afrikaans + nativeName: Afrikaans +ak: + name: Akan + nativeName: Akan +am: + name: Amharic + nativeName: አማርኛ +an: + name: Aragonese + nativeName: aragonés +ar: + name: Arabic + nativeName: اللغة العربية +as: + name: Assamese + nativeName: অসমীয়া +av: + name: Avaric + nativeName: авар мацӀ +ay: + name: Aymara + nativeName: aymar aru +az: + name: Azerbaijani + nativeName: azərbaycan dili +ba: + name: Bashkir + nativeName: башҡорт теле +be: + name: Belarusian + nativeName: беларуская мова +bg: + name: Bulgarian + nativeName: български език +bh: + name: Bihari + nativeName: भोजपुरी +bi: + name: Bislama + nativeName: Bislama +bm: + name: Bambara + nativeName: bamanankan +bn: + name: Bengali + nativeName: বাংলা +bo: + name: Tibetan Standard + nativeName: བོད་ཡིག +br: + name: Breton + nativeName: brezhoneg +bs: + name: Bosnian + nativeName: bosanski jezik +ca: + name: Catalan + nativeName: català +ce: + name: Chechen + nativeName: нохчийн мотт +ch: + name: Chamorro + nativeName: Chamoru +co: + name: Corsican + nativeName: corsu +cr: + name: Cree + nativeName: ᓀᐦᐃᔭᐍᐏᐣ +cs: + name: Czech + nativeName: čeština +cu: + name: Old Church Slavonic + nativeName: ѩзыкъ словѣньскъ +cv: + name: Chuvash + nativeName: чӑваш чӗлхи +cy: + name: Welsh + nativeName: Cymraeg +da: + name: Danish + nativeName: dansk +de: + name: German + nativeName: Deutsch +dv: + name: Divehi + nativeName: Dhivehi +dz: + name: Dzongkha + nativeName: རྫོང་ཁ +ee: + name: Ewe + nativeName: Eʋegbe +el: + name: Greek + nativeName: ελληνικά +en: + name: English + nativeName: English +eo: + name: Esperanto + nativeName: Esperanto +es: + name: Spanish + nativeName: Español +et: + name: Estonian + nativeName: eesti +eu: + name: Basque + nativeName: euskara +fa: + name: Persian + nativeName: فارسی +ff: + name: Fula + nativeName: Fulfulde +fi: + name: Finnish + nativeName: suomi +fj: + name: Fijian + nativeName: Vakaviti +fo: + name: Faroese + nativeName: føroyskt +fr: + name: French + nativeName: Français +fy: + name: Western Frisian + nativeName: Frysk +ga: + name: Irish + nativeName: Gaeilge +gd: + name: Scottish Gaelic + nativeName: Gàidhlig +gl: + name: Galician + nativeName: galego +gn: + name: Guaraní + nativeName: Avañe'ẽ +gu: + name: Gujarati + nativeName: ગુજરાતી +gv: + name: Manx + nativeName: Gaelg +ha: + name: Hausa + nativeName: هَوُسَ +he: + name: Hebrew + nativeName: עברית +hi: + name: Hindi + nativeName: हिन्दी +ho: + name: Hiri Motu + nativeName: Hiri Motu +hr: + name: Croatian + nativeName: hrvatski jezik +ht: + name: Haitian + nativeName: Kreyòl ayisyen +hu: + name: Hungarian + nativeName: magyar +hy: + name: Armenian + nativeName: Հայերեն +hz: + name: Herero + nativeName: Otjiherero +ia: + name: Interlingua + nativeName: Interlingua +id: + name: Indonesian + nativeName: Indonesian +ie: + name: Interlingue + nativeName: Interlingue +ig: + name: Igbo + nativeName: Asụsụ Igbo +ii: + name: Nuosu + nativeName: ꆈꌠ꒿ Nuosuhxop +ik: + name: Inupiaq + nativeName: Iñupiaq +io: + name: Ido + nativeName: Ido +is: + name: Icelandic + nativeName: Íslenska +it: + name: Italian + nativeName: Italiano +iu: + name: Inuktitut + nativeName: ᐃᓄᒃᑎᑐᑦ +ja: + name: Japanese + nativeName: 日本語 +jv: + name: Javanese + nativeName: basa Jawa +ka: + name: Georgian + nativeName: ქართული +kg: + name: Kongo + nativeName: Kikongo +ki: + name: Kikuyu + nativeName: Gĩkũyũ +kj: + name: Kwanyama + nativeName: Kuanyama +kk: + name: Kazakh + nativeName: қазақ тілі +kl: + name: Kalaallisut + nativeName: kalaallisut +km: + name: Khmer + nativeName: ខេមរភាសា +kn: + name: Kannada + nativeName: ಕನ್ನಡ +ko: + name: Korean + nativeName: 한국어 +kr: + name: Kanuri + nativeName: Kanuri +ks: + name: Kashmiri + nativeName: कश्मीरी +ku: + name: Kurdish + nativeName: Kurdî +kv: + name: Komi + nativeName: коми кыв +kw: + name: Cornish + nativeName: Kernewek +ky: + name: Kyrgyz + nativeName: Кыргызча +la: + name: Latin + nativeName: latine +lb: + name: Luxembourgish + nativeName: Lëtzebuergesch +lg: + name: Ganda + nativeName: Luganda +li: + name: Limburgish + nativeName: Limburgs +ln: + name: Lingala + nativeName: Lingála +lo: + name: Lao + nativeName: ພາສາ +lt: + name: Lithuanian + nativeName: lietuvių kalba +lu: + name: Luba-Katanga + nativeName: Tshiluba +lv: + name: Latvian + nativeName: latviešu valoda +mg: + name: Malagasy + nativeName: fiteny malagasy +mh: + name: Marshallese + nativeName: Kajin M̧ajeļ +mi: + name: Māori + nativeName: te reo Māori +mk: + name: Macedonian + nativeName: македонски јазик +ml: + name: Malayalam + nativeName: മലയാളം +mn: + name: Mongolian + nativeName: Монгол хэл +mr: + name: Marathi + nativeName: मराठी +ms: + name: Malay + nativeName: هاس ملايو +mt: + name: Maltese + nativeName: Malti +my: + name: Burmese + nativeName: ဗမာစာ +na: + name: Nauru + nativeName: Ekakairũ Naoero +nb: + name: Norwegian Bokmål + nativeName: Norsk bokmål +nd: + name: Northern Ndebele + nativeName: isiNdebele +ne: + name: Nepali + nativeName: नेपाली +ng: + name: Ndonga + nativeName: Owambo +nl: + name: Dutch + nativeName: Nederlands +nn: + name: Norwegian Nynorsk + nativeName: Norsk nynorsk +'no': + name: Norwegian + nativeName: Norsk +nr: + name: Southern Ndebele + nativeName: isiNdebele +nv: + name: Navajo + nativeName: Diné bizaad +ny: + name: Chichewa + nativeName: chiCheŵa +oc: + name: Occitan + nativeName: occitan +oj: + name: Ojibwe + nativeName: ᐊᓂᔑᓈᐯᒧᐎᓐ +om: + name: Oromo + nativeName: Afaan Oromoo +or: + name: Oriya + nativeName: ଓଡ଼ିଆ +os: + name: Ossetian + nativeName: ирон æвзаг +pa: + name: Panjabi + nativeName: ਪੰਜਾਬੀ +pi: + name: Pāli + nativeName: पाऴि +pl: + name: Polish + nativeName: język polski +ps: + name: Pashto + nativeName: پښتو +pt: + name: Portuguese + nativeName: Português +pt_BR: + name: Portuguese + nativeName: Português (BR) +qu: + name: Quechua + nativeName: Runa Simi +rm: + name: Romansh + nativeName: rumantsch grischun +rn: + name: Kirundi + nativeName: Ikirundi +ro: + name: Romanian + nativeName: limba română +ru: + name: Russian + nativeName: Русский +rw: + name: Kinyarwanda + nativeName: Ikinyarwanda +sa: + name: Sanskrit + nativeName: संस्कृतम् +sc: + name: Sardinian + nativeName: sardu +sd: + name: Sindhi + nativeName: सिन्धी +se: + name: Northern Sami + nativeName: Davvisámegiella +sg: + name: Sango + nativeName: yângâ tî sängö +si: + name: Sinhala + nativeName: සිංහල +sk: + name: Slovak + nativeName: slovenčina +sl: + name: Slovene + nativeName: slovenski jezik +sm: + name: Samoan + nativeName: gagana fa'a Samoa +sn: + name: Shona + nativeName: chiShona +so: + name: Somali + nativeName: Soomaaliga +sq: + name: Albanian + nativeName: Shqip +sr: + name: Serbian + nativeName: српски језик +ss: + name: Swati + nativeName: SiSwati +st: + name: Southern Sotho + nativeName: Sesotho +su: + name: Sundanese + nativeName: Basa Sunda +sv: + name: Swedish + nativeName: svenska +sw: + name: Swahili + nativeName: Kiswahili +ta: + name: Tamil + nativeName: தமிழ் +te: + name: Telugu + nativeName: తెలుగు +tg: + name: Tajik + nativeName: тоҷикӣ +th: + name: Thai + nativeName: ไทย +ti: + name: Tigrinya + nativeName: ትግርኛ +tk: + name: Turkmen + nativeName: Türkmen +tl: + name: Tagalog + nativeName: Wikang Tagalog +tn: + name: Tswana + nativeName: Setswana +to: + name: Tonga + nativeName: faka Tonga +tr: + name: Turkish + nativeName: Türkçe +ts: + name: Tsonga + nativeName: Xitsonga +tt: + name: Tatar + nativeName: татар теле +tw: + name: Twi + nativeName: Twi +ty: + name: Tahitian + nativeName: Reo Tahiti +ug: + name: Uyghur + nativeName: ئۇيغۇرچە +uk: + name: Ukrainian + nativeName: українська мова +ur: + name: Urdu + nativeName: اردو +uz: + name: Uzbek + nativeName: Ўзбек +ve: + name: Venda + nativeName: Tshivenḓa +vi: + name: Vietnamese + nativeName: Việt Nam +vo: + name: Volapük + nativeName: Volapük +wa: + name: Walloon + nativeName: walon +wo: + name: Wolof + nativeName: Wollof +xh: + name: Xhosa + nativeName: isiXhosa +yi: + name: Yiddish + nativeName: ייִדיש +yo: + name: Yoruba + nativeName: Yorùbá +za: + name: Zhuang + nativeName: Saɯ cueŋƅ +zh: + name: Chinese + nativeName: 中文 +zh_TW: + name: Chinese + nativeName: 中文 (TW) +zu: + name: Zulu + nativeName: isiZulu diff --git a/config/locales/server.en.yml b/config/locales/server.en.yml index c3be14d8a..97ec50c98 100644 --- a/config/locales/server.en.yml +++ b/config/locales/server.en.yml @@ -3216,10 +3216,19 @@ en: wizard: title: "Discourse Setup Wizard" step: - forum_title: + locale: title: "Welcome to your Discourse forum!" description: "There are a few things you'll need to configure before inviting more people to the party. Don't worry, you can come back and change these settings at any time, so don't overthink it." + fields: + default_locale: + label: "Language" + description: "The default language for users browsing your forum" + + forum_title: + title: "The Basics" + description: "Tell us a little bit about yourself." + fields: title: label: "Enter a title for your forum" @@ -3242,10 +3251,10 @@ en: label: "Site Contact Username" description: "All automated messages will be sent from this user." colors: - title: "Choose a Color Scheme" + title: "Choose a Theme" fields: - color_scheme: - label: "Color Scheme" + theme_id: + label: "Theme" options: default: "Simple" dark: "Dark" diff --git a/config/routes.rb b/config/routes.rb index e86c43efe..af169723d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -56,6 +56,7 @@ Discourse::Application.routes.draw do get "wizard" => "wizard#index" get "wizard/qunit" => "wizard#qunit" get 'wizard/steps' => 'steps#index' + get 'wizard/steps/:id' => "wizard#index" put 'wizard/steps/:id' => "steps#update" namespace :admin, constraints: StaffConstraint.new do diff --git a/db/migrate/20160906200439_add_via_wizard_to_color_schemes.rb b/db/migrate/20160906200439_add_via_wizard_to_color_schemes.rb index 40c69d416..1fc1881f5 100644 --- a/db/migrate/20160906200439_add_via_wizard_to_color_schemes.rb +++ b/db/migrate/20160906200439_add_via_wizard_to_color_schemes.rb @@ -1,5 +1,6 @@ class AddViaWizardToColorSchemes < ActiveRecord::Migration def change add_column :color_schemes, :via_wizard, :boolean, default: false, null: false + add_column :color_schemes, :theme_id, :string, null: true end end diff --git a/lib/wizard.rb b/lib/wizard.rb index 7e8d46a00..ba0685aea 100644 --- a/lib/wizard.rb +++ b/lib/wizard.rb @@ -9,11 +9,15 @@ class Wizard @steps = [] end - def create_step(args) - Step.new(args) + def create_step(step_name) + Step.new(step_name) end def append_step(step) + step = create_step(step) if step.is_a?(String) + + yield step if block_given? + last_step = @steps.last @steps << step @@ -31,26 +35,40 @@ class Wizard def self.build wizard = Wizard.new - title = wizard.create_step('forum-title') - title.add_field(id: 'title', type: 'text', required: true, value: SiteSetting.title) - title.add_field(id: 'site_description', type: 'text', required: true, value: SiteSetting.site_description) - wizard.append_step(title) - contact = wizard.create_step('contact') - contact.add_field(id: 'contact_email', type: 'text', required: true, value: SiteSetting.contact_email) - contact.add_field(id: 'contact_url', type: 'text', value: SiteSetting.contact_url) - contact.add_field(id: 'site_contact_username', type: 'text', value: SiteSetting.site_contact_username) - wizard.append_step(contact) + wizard.append_step('locale') do |step| + languages = step.add_field(id: 'default_locale', + type: 'dropdown', + required: true, + value: SiteSetting.default_locale) - theme = wizard.create_step('colors') - scheme = theme.add_field(id: 'color_scheme', type: 'dropdown', required: true) - ColorScheme.themes.each {|t| scheme.add_option(t[:id], t) } + LocaleSiteSetting.values.each do |locale| + languages.add_choice(locale[:value], label: locale[:name]) + end + end - theme.add_field(id: 'scheme_preview', type: 'component') - wizard.append_step(theme) + wizard.append_step('forum-title') do |step| + step.add_field(id: 'title', type: 'text', required: true, value: SiteSetting.title) + step.add_field(id: 'site_description', type: 'text', required: true, value: SiteSetting.site_description) + end - finished = wizard.create_step('finished') - wizard.append_step(finished); + wizard.append_step('contact') do |step| + step.add_field(id: 'contact_email', type: 'text', required: true, value: SiteSetting.contact_email) + step.add_field(id: 'contact_url', type: 'text', value: SiteSetting.contact_url) + step.add_field(id: 'site_contact_username', type: 'text', value: SiteSetting.site_contact_username) + end + + wizard.append_step('colors') do |step| + + theme_id = ColorScheme.where(via_wizard: true).pluck(:theme_id) + theme_id = theme_id.present? ? theme_id[0] : 'default' + + themes = step.add_field(id: 'theme_id', type: 'dropdown', required: true, value: theme_id) + ColorScheme.themes.each {|t| themes.add_choice(t[:id], data: t) } + step.add_field(id: 'theme_preview', type: 'component') + end + + wizard.append_step('finished') wizard end diff --git a/lib/wizard/field.rb b/lib/wizard/field.rb index 70afc2df8..5b8faf8fc 100644 --- a/lib/wizard/field.rb +++ b/lib/wizard/field.rb @@ -1,7 +1,18 @@ class Wizard - class Field - attr_reader :id, :type, :required, :value, :options, :option_data + class Choice + attr_reader :id, :label, :data + attr_accessor :field + + def initialize(id, opts) + @id = id + @data = opts[:data] + @label = opts[:label] + end + end + + class Field + attr_reader :id, :type, :required, :value, :choices attr_accessor :step def initialize(attrs) @@ -11,13 +22,15 @@ class Wizard @type = attrs[:type] @required = !!attrs[:required] @value = attrs[:value] - @options = [] - @option_data = {} + @choices = [] end - def add_option(id, data=nil) - @options << id - @option_data[id] = data + def add_choice(id, opts=nil) + choice = Choice.new(id, opts || {}) + choice.field = self + + @choices << choice + choice end end diff --git a/lib/wizard/step_updater.rb b/lib/wizard/step_updater.rb index 543f55eff..fe0c0278a 100644 --- a/lib/wizard/step_updater.rb +++ b/lib/wizard/step_updater.rb @@ -5,6 +5,7 @@ class Wizard def initialize(current_user, id) @current_user = current_user @id = id + @refresh_required = false end def update(fields) @@ -12,6 +13,12 @@ class Wizard send(updater_method, fields.symbolize_keys) if respond_to?(updater_method) end + def update_locale(fields) + old_locale = SiteSetting.default_locale + update_setting(:default_locale, fields, :default_locale) + @refresh_required = true if old_locale != fields[:default_locale] + end + def update_forum_title(fields) update_setting(:title, fields, :title) update_setting(:site_description, fields, :site_description) @@ -24,7 +31,7 @@ class Wizard end def update_colors(fields) - scheme_name = fields[:color_scheme] + scheme_name = fields[:theme_id] theme = ColorScheme.themes.find {|s| s[:id] == scheme_name } @@ -36,7 +43,8 @@ class Wizard attrs = { enabled: true, name: I18n.t("wizard.step.colors.fields.color_scheme.options.#{scheme_name}"), - colors: colors + colors: colors, + theme_id: scheme_name } scheme = ColorScheme.where(via_wizard: true).first @@ -55,6 +63,10 @@ class Wizard @errors.blank? end + def refresh_required? + @refresh_required + end + protected def update_setting(id, fields, field_id) diff --git a/spec/components/step_updater_spec.rb b/spec/components/step_updater_spec.rb index 336c9fe33..b61e3a288 100644 --- a/spec/components/step_updater_spec.rb +++ b/spec/components/step_updater_spec.rb @@ -4,6 +4,24 @@ require_dependency 'wizard/step_updater' describe Wizard::StepUpdater do let(:user) { Fabricate(:admin) } + context "locale" do + let(:updater) { Wizard::StepUpdater.new(user, 'locale') } + + it "does not require refresh when the language stays the same" do + updater.update(default_locale: 'en') + expect(updater.refresh_required?).to eq(false) + end + + it "updates the locale and requires refresh when it does change" do + updater.update(default_locale: 'ru') + expect(SiteSetting.default_locale).to eq('ru') + expect(updater.refresh_required?).to eq(true) + end + end + + it "updates the locale" do + end + it "updates the forum title step" do updater = Wizard::StepUpdater.new(user, 'forum_title') updater.update(title: 'new forum title', site_description: 'neat place') @@ -30,7 +48,7 @@ describe Wizard::StepUpdater do it "doesn't update when there are errors" do updater.update(contact_email: 'not-an-email', site_contact_username: 'not-a-username') - expect(updater).to be_success + expect(updater).to_not be_success expect(updater.errors).to be_present end end diff --git a/spec/components/wizard_spec.rb b/spec/components/wizard_spec.rb index 610eff92e..72987de69 100644 --- a/spec/components/wizard_spec.rb +++ b/spec/components/wizard_spec.rb @@ -15,6 +15,14 @@ describe Wizard do let(:step1) { wizard.create_step('first-step') } let(:step2) { wizard.create_step('second-step') } + it "works with a block format" do + wizard.append_step('wat') do |step| + expect(step).to be_present + end + + expect(wizard.steps.size).to eq(1) + end + it "adds the step correctly" do expect(step1.index).to be_blank diff --git a/spec/components/wizard_step_spec.rb b/spec/components/wizard_step_spec.rb index 0d6f1df40..54f950722 100644 --- a/spec/components/wizard_step_spec.rb +++ b/spec/components/wizard_step_spec.rb @@ -12,12 +12,12 @@ describe Wizard::Step do expect(step.fields).to eq([text]) dropdown = step.add_field(id: 'snacks', type: 'dropdown') - dropdown.add_option(id: 'candy') - dropdown.add_option(id: 'nachos') - dropdown.add_option(id: 'pizza') + dropdown.add_choice('candy') + dropdown.add_choice('nachos', data: {color: 'yellow'}) + dropdown.add_choice('pizza', label: 'Pizza!') expect(step.fields).to eq([text, dropdown]) - expect(dropdown.options.size).to eq(3) + expect(dropdown.choices.size).to eq(3) end end diff --git a/spec/integrity/i18n_spec.rb b/spec/integrity/i18n_spec.rb index 20b69dfa3..1d99795ed 100644 --- a/spec/integrity/i18n_spec.rb +++ b/spec/integrity/i18n_spec.rb @@ -44,7 +44,8 @@ describe "i18n integrity checks" do end it "does not overwrite another language" do - Dir["#{Rails.root}/config/locales/*.yml"].each do |f| + all = Dir["#{Rails.root}/config/locales/client.*.yml"] + Dir["#{Rails.root}/config/locales/server.*.yml"] + all.each do |f| locale = /.*\.([^.]{2,})\.yml$/.match(f)[1] + ':' IO.foreach(f) do |line| line.strip! diff --git a/spec/services/color_scheme_revisor_spec.rb b/spec/services/color_scheme_revisor_spec.rb index 8db267690..d9f8a3519 100644 --- a/spec/services/color_scheme_revisor_spec.rb +++ b/spec/services/color_scheme_revisor_spec.rb @@ -18,6 +18,11 @@ describe ColorSchemeRevisor do expect(color_scheme.reload.name).to eq("Changed Name") end + it "can update the theme_id" do + described_class.revise(color_scheme, valid_params.merge(theme_id: 'test')) + expect(color_scheme.reload.theme_id).to eq('test') + end + it "can enable and disable" do described_class.revise(color_scheme, valid_params.merge(enabled: true)) expect(color_scheme.reload).to be_enabled