Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-25 18:50:27 +01:00
Merge pull request #191 from paviliondev/add_acceptance_tests
Add acceptance tests
Dieser Commit ist enthalten in:
Commit
c0b93fc166
102 geänderte Dateien mit 3027 neuen und 781 gelöschten Zeilen
18
.github/workflows/plugin-tests.yml
gevendort
18
.github/workflows/plugin-tests.yml
gevendort
|
@ -73,18 +73,6 @@ jobs:
|
|||
ref: "${{ github.base_ref }}"
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Check spec existence
|
||||
id: check_spec
|
||||
uses: andstor/file-existence-action@v1
|
||||
with:
|
||||
files: "plugins/${{ steps.repo-name.outputs.value }}/spec"
|
||||
|
||||
- name: Check qunit existence
|
||||
id: check_qunit
|
||||
uses: andstor/file-existence-action@v1
|
||||
with:
|
||||
files: "plugins/${{ steps.repo-name.outputs.value }}/test/javascripts"
|
||||
|
||||
- name: Setup Git
|
||||
run: |
|
||||
git config --global user.email "ci@ci.invalid"
|
||||
|
@ -140,7 +128,7 @@ jobs:
|
|||
bin/rake db:migrate
|
||||
|
||||
- name: Plugin RSpec with Coverage
|
||||
if: matrix.build_type == 'backend' && steps.check_spec.outputs.files_exists == 'true'
|
||||
if: matrix.build_type == 'backend'
|
||||
run: |
|
||||
if [ -e plugins/${{ steps.repo-name.outputs.value }}/.simplecov ]
|
||||
then
|
||||
|
@ -150,6 +138,6 @@ jobs:
|
|||
bin/rake plugin:spec[${{ steps.repo-name.outputs.value }}]
|
||||
|
||||
- name: Plugin QUnit
|
||||
if: matrix.build_type == 'frontend' && steps.check_qunit.outputs.files_exists == 'true'
|
||||
run: bundle exec rake plugin:qunit['${{ steps.repo-name.outputs.value }}','1200000']
|
||||
if: matrix.build_type == 'frontend'
|
||||
run: QUNIT_SKIP_CORE=1 LOAD_PLUGINS=1 QUNIT_EMBER_CLI=0 bin/rake "qunit:test['600000','/w/qunit']"
|
||||
timeout-minutes: 30
|
||||
|
|
|
@ -1,55 +1,40 @@
|
|||
# frozen_string_literal: true
|
||||
class CustomWizard::WizardController < ::ApplicationController
|
||||
include ApplicationHelper
|
||||
prepend_view_path(Rails.root.join('plugins', 'discourse-custom-wizard', 'app', 'views'))
|
||||
layout 'wizard'
|
||||
class CustomWizard::WizardController < ::ActionController::Base
|
||||
helper ApplicationHelper
|
||||
|
||||
include CurrentUser
|
||||
include CanonicalURL::ControllerExtensions
|
||||
include GlobalPath
|
||||
|
||||
prepend_view_path(Rails.root.join('plugins', 'discourse-custom-wizard', 'app', 'views'))
|
||||
layout :set_wizard_layout
|
||||
|
||||
before_action :preload_wizard_json
|
||||
before_action :ensure_plugin_enabled
|
||||
before_action :update_subscription, only: [:index]
|
||||
before_action :ensure_logged_in, only: [:skip]
|
||||
|
||||
helper_method :wizard_page_title
|
||||
helper_method :wizard_theme_id
|
||||
helper_method :wizard_theme_lookup
|
||||
helper_method :wizard_theme_translations_lookup
|
||||
|
||||
def wizard
|
||||
@builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user)
|
||||
@wizard ||= @builder.build
|
||||
@wizard
|
||||
end
|
||||
|
||||
def wizard_page_title
|
||||
wizard ? (wizard.name || wizard.id) : I18n.t('wizard.custom_title')
|
||||
end
|
||||
|
||||
def wizard_theme_id
|
||||
wizard ? wizard.theme_id : nil
|
||||
end
|
||||
|
||||
def wizard_theme_lookup(name)
|
||||
Theme.lookup_field(wizard_theme_id, mobile_view? ? :mobile : :desktop, name)
|
||||
end
|
||||
|
||||
def wizard_theme_translations_lookup
|
||||
Theme.lookup_field(wizard_theme_id, :translations, I18n.locale)
|
||||
def set_wizard_layout
|
||||
action_name === 'qunit' ? 'qunit' : 'wizard'
|
||||
end
|
||||
|
||||
def index
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user)
|
||||
|
||||
if builder.wizard.present?
|
||||
builder_opts = {}
|
||||
builder_opts[:reset] = params[:reset]
|
||||
built_wizard = builder.build(builder_opts, params)
|
||||
|
||||
render_serialized(built_wizard, ::CustomWizard::WizardSerializer, root: false)
|
||||
if wizard.present?
|
||||
render json: CustomWizard::WizardSerializer.new(wizard, scope: guardian, root: false).as_json, status: 200
|
||||
else
|
||||
render json: { error: I18n.t('wizard.none') }
|
||||
end
|
||||
end
|
||||
format.html {}
|
||||
format.html do
|
||||
render "default/empty"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -73,6 +58,64 @@ class CustomWizard::WizardController < ::ApplicationController
|
|||
render json: result
|
||||
end
|
||||
|
||||
def qunit
|
||||
raise Discourse::InvalidAccess.new if Rails.env.production?
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
render "default/empty"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def ensure_logged_in
|
||||
raise Discourse::NotLoggedIn.new unless current_user.present?
|
||||
end
|
||||
|
||||
def guardian
|
||||
@guardian ||= Guardian.new(current_user, request)
|
||||
end
|
||||
|
||||
def wizard
|
||||
@wizard ||= begin
|
||||
builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user)
|
||||
return nil unless builder.present?
|
||||
opts = {}
|
||||
opts[:reset] = params[:reset]
|
||||
builder.build(opts, params)
|
||||
end
|
||||
end
|
||||
|
||||
def wizard_page_title
|
||||
wizard ? (wizard.name || wizard.id) : I18n.t('wizard.custom_title')
|
||||
end
|
||||
|
||||
def wizard_theme_id
|
||||
wizard ? wizard.theme_id : nil
|
||||
end
|
||||
|
||||
def wizard_theme_lookup(name)
|
||||
Theme.lookup_field(wizard_theme_id, view_context.mobile_view? ? :mobile : :desktop, name)
|
||||
end
|
||||
|
||||
def wizard_theme_translations_lookup
|
||||
Theme.lookup_field(wizard_theme_id, :translations, I18n.locale)
|
||||
end
|
||||
|
||||
def preload_wizard_json
|
||||
return if request.xhr? || request.format.json?
|
||||
return if request.method != "GET"
|
||||
|
||||
store_preloaded("siteSettings", SiteSetting.client_settings_json)
|
||||
end
|
||||
|
||||
def store_preloaded(key, json)
|
||||
@preloaded ||= {}
|
||||
@preloaded[key] = json.gsub("</", "<\\/")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def ensure_plugin_enabled
|
||||
|
|
28
app/views/layouts/qunit.html.erb
Normale Datei
28
app/views/layouts/qunit.html.erb
Normale Datei
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Custom Wizard QUnit Test Runner</title>
|
||||
<%= discourse_stylesheet_link_tag(:test_helper, theme_id: nil) %>
|
||||
<%= discourse_stylesheet_link_tag :wizard, theme_id: nil %>
|
||||
<%= discourse_stylesheet_link_tag :wizard_custom %>
|
||||
<%= preload_script "locales/en" %>
|
||||
<%= preload_script "ember_jquery" %>
|
||||
<%= preload_script "wizard-vendor" %>
|
||||
<%= preload_script "wizard-custom" %>
|
||||
<%= preload_script "wizard-raw-templates" %>
|
||||
<%= preload_script "wizard-plugin" %>
|
||||
<%= preload_script "pretty-text-bundle" %>
|
||||
<%= preload_script "wizard-qunit" %>
|
||||
<%= csrf_meta_tags %>
|
||||
|
||||
<script src="<%= ExtraLocalesController.url("wizard") %>"></script>
|
||||
|
||||
<%= tag.meta id: 'data-discourse-setup', data: client_side_setup_data %>
|
||||
<meta name="discourse_theme_id" content="">
|
||||
<meta name="discourse-base-uri" content="<%= Discourse.base_path %>">
|
||||
</head>
|
||||
<body class="custom-wizard">
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -11,10 +11,8 @@
|
|||
<%= preload_script "locales/#{I18n.locale}" %>
|
||||
<%= preload_script "ember_jquery" %>
|
||||
<%= preload_script "wizard-vendor" %>
|
||||
<%= preload_script "wizard-application" %>
|
||||
<%= preload_script "wizard-custom-globals" %>
|
||||
<%= preload_script "wizard-raw-templates" %>
|
||||
<%= preload_script "wizard-custom" %>
|
||||
<%= preload_script "wizard-raw-templates" %>
|
||||
<%= preload_script "wizard-plugin" %>
|
||||
<%= preload_script "pretty-text-bundle" %>
|
||||
<script src="<%= ExtraLocalesController.url("wizard") %>"></script>
|
||||
|
@ -58,5 +56,7 @@
|
|||
<%= raw SvgSprite.bundle %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hidden" id="data-preloaded-wizard" data-preloaded-wizard="<%= preloaded_json %>"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -64,7 +64,7 @@ export default {
|
|||
this.set("customWizardCriticalNotices", criticalNotices);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
api.modifyClass("component:d-navigation", {
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
/* eslint no-undef: 0*/
|
||||
window.Discourse = {};
|
||||
window.Wizard = {};
|
||||
Wizard.SiteSettings = {};
|
||||
Discourse.__widget_helpers = {};
|
||||
Discourse.SiteSettings = Wizard.SiteSettings;
|
|
@ -1,4 +1,4 @@
|
|||
(function () {
|
||||
let wizard = require("discourse/plugins/discourse-custom-wizard/wizard/custom-wizard").default.create();
|
||||
let wizard = require("discourse/plugins/discourse-custom-wizard/wizard/application").default.create();
|
||||
wizard.start();
|
||||
})();
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
//= require_tree_discourse truth-helpers/addon
|
||||
//= require_tree_discourse discourse-common/addon
|
||||
//= require_tree_discourse select-kit/addon
|
||||
//= require_tree_discourse wizard/lib
|
||||
//= require_tree_discourse wizard/mixins
|
||||
//= require_tree_discourse discourse/app/lib
|
||||
//= require_tree_discourse discourse/app/mixins
|
||||
|
||||
//= require discourse/app/adapters/rest
|
||||
|
||||
//= require message-bus
|
||||
|
||||
//= require_tree_discourse discourse/app/models
|
||||
|
||||
//= require discourse/app/helpers/category-link
|
||||
|
@ -12,9 +15,6 @@
|
|||
//= require discourse/app/helpers/format-username
|
||||
//= require discourse/app/helpers/share-url
|
||||
//= require discourse/app/helpers/decorate-username-selector
|
||||
//= require discourse-common/addon/helpers/component-for-collection
|
||||
//= require discourse-common/addon/helpers/component-for-row
|
||||
//= require discourse-common/addon/lib/raw-templates
|
||||
//= require discourse/app/helpers/discourse-tag
|
||||
|
||||
//= require discourse/app/services/app-events
|
||||
|
@ -70,11 +70,11 @@
|
|||
//= require bootbox.js
|
||||
//= require discourse-shims
|
||||
|
||||
//= require ./wizard/custom-wizard
|
||||
//= require ./wizard/application
|
||||
//= require ./wizard/router
|
||||
//= require_tree ./wizard/components
|
||||
//= require_tree ./wizard/controllers
|
||||
//= require_tree ./wizard/helpers
|
||||
//= require_tree ./wizard/initializers
|
||||
//= require_tree ./wizard/lib
|
||||
//= require_tree ./wizard/models
|
||||
//= require_tree ./wizard/routes
|
||||
|
|
16
assets/javascripts/wizard-qunit.js
Normale Datei
16
assets/javascripts/wizard-qunit.js
Normale Datei
|
@ -0,0 +1,16 @@
|
|||
//= require route-recognizer
|
||||
//= require fake_xml_http_request
|
||||
//= require pretender
|
||||
//= require qunit
|
||||
//= require ember-qunit
|
||||
//= require test-shims
|
||||
//= require jquery.debug
|
||||
//= require ember.debug
|
||||
//= require ember-template-compiler
|
||||
|
||||
//= require_tree ./wizard/tests/fixtures
|
||||
//= require ./wizard/tests/pretender
|
||||
//= require_tree ./wizard/tests/helpers
|
||||
//= require_tree ./wizard/tests/acceptance
|
||||
|
||||
//= require ./wizard/tests/bootstrap
|
19
assets/javascripts/wizard/application.js.es6
Normale Datei
19
assets/javascripts/wizard/application.js.es6
Normale Datei
|
@ -0,0 +1,19 @@
|
|||
import { buildResolver } from "discourse-common/resolver";
|
||||
import Application from "@ember/application";
|
||||
import WizardInitializer from "./lib/initialize/wizard";
|
||||
import { isTesting } from "discourse-common/config/environment";
|
||||
|
||||
export default Application.extend({
|
||||
rootElement: "#custom-wizard-main",
|
||||
Resolver: buildResolver("discourse/plugins/discourse-custom-wizard/wizard"),
|
||||
|
||||
customEvents: {
|
||||
paste: "paste",
|
||||
},
|
||||
|
||||
start() {
|
||||
if (!isTesting()) {
|
||||
this.initializer(WizardInitializer);
|
||||
}
|
||||
},
|
||||
});
|
|
@ -7,6 +7,7 @@ import userSearch from "../lib/user-search";
|
|||
import WizardI18n from "../lib/wizard-i18n";
|
||||
import Handlebars from "handlebars";
|
||||
import { isEmpty } from "@ember/utils";
|
||||
import TextField from "@ember/component/text-field";
|
||||
|
||||
const template = function (params) {
|
||||
const options = params.options;
|
||||
|
@ -31,7 +32,7 @@ const template = function (params) {
|
|||
return new Handlebars.SafeString(html).string;
|
||||
};
|
||||
|
||||
export default Ember.TextField.extend({
|
||||
export default TextField.extend({
|
||||
attributeBindings: ["autofocus", "maxLength"],
|
||||
autocorrect: false,
|
||||
autocapitalize: false,
|
||||
|
@ -55,7 +56,6 @@ export default Ember.TextField.extend({
|
|||
let self = this,
|
||||
selected = [],
|
||||
groups = [],
|
||||
currentUser = this.currentUser,
|
||||
includeMentionableGroups =
|
||||
this.get("includeMentionableGroups") === "true",
|
||||
includeMessageableGroups =
|
||||
|
@ -66,13 +66,8 @@ export default Ember.TextField.extend({
|
|||
function excludedUsernames() {
|
||||
// hack works around some issues with allowAny eventing
|
||||
const usernames = self.get("single") ? [] : selected;
|
||||
|
||||
if (currentUser && self.get("excludeCurrentUser")) {
|
||||
return usernames.concat([currentUser.get("username")]);
|
||||
}
|
||||
return usernames;
|
||||
}
|
||||
|
||||
$(this.element)
|
||||
.val(this.get("usernames"))
|
||||
.autocomplete({
|
||||
|
@ -84,7 +79,6 @@ export default Ember.TextField.extend({
|
|||
|
||||
dataSource(term) {
|
||||
const termRegex = /[^a-zA-Z0-9_\-\.@\+]/;
|
||||
|
||||
let results = userSearch({
|
||||
term: term.replace(termRegex, ""),
|
||||
topicId: self.get("topicId"),
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/field-validators",
|
||||
|
||||
actions: {
|
||||
perform() {
|
||||
this.appEvents.trigger("custom-wizard:validate");
|
||||
|
|
|
@ -10,6 +10,7 @@ import { dasherize } from "@ember/string";
|
|||
|
||||
export default WizardFieldValidator.extend({
|
||||
classNames: ["similar-topics-validator"],
|
||||
layoutName: "wizard/templates/components/similar-topics-validator",
|
||||
similarTopics: null,
|
||||
hasInput: notEmpty("field.value"),
|
||||
hasSimilarTopics: notEmpty("similarTopics"),
|
||||
|
|
|
@ -6,11 +6,11 @@ import { getToken } from "wizard/lib/ajax";
|
|||
export default Component.extend({
|
||||
classNames: ["validator"],
|
||||
classNameBindings: ["isValid", "isInvalid"],
|
||||
layoutName: "wizard/templates/components/validator",
|
||||
validMessageKey: null,
|
||||
invalidMessageKey: null,
|
||||
isValid: null,
|
||||
isInvalid: equal("isValid", false),
|
||||
layoutName: "components/validator", // useful for sharing the template with extending components
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
|
|
@ -13,6 +13,7 @@ import { uploadIcon } from "discourse/lib/uploads";
|
|||
import { dasherize } from "@ember/string";
|
||||
|
||||
export default ComposerEditor.extend({
|
||||
layoutName: "wizard/templates/components/wizard-composer-editor",
|
||||
classNameBindings: ["fieldClass"],
|
||||
allowUpload: true,
|
||||
showLink: false,
|
||||
|
|
|
@ -2,6 +2,7 @@ import Component from "@ember/component";
|
|||
|
||||
export default Component.extend({
|
||||
classNames: ["wizard-composer-hyperlink"],
|
||||
layoutName: "wizard/templates/components/wizard-composer-hyperlink",
|
||||
|
||||
actions: {
|
||||
addLink() {
|
||||
|
|
|
@ -3,6 +3,7 @@ import discourseComputed from "discourse-common/utils/decorators";
|
|||
|
||||
export default DateInput.extend({
|
||||
useNativePicker: false,
|
||||
layoutName: "wizard/templates/components/wizard-date-input",
|
||||
|
||||
@discourseComputed()
|
||||
placeholder() {
|
||||
|
|
|
@ -2,6 +2,8 @@ import DateTimeInput from "discourse/components/date-time-input";
|
|||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default DateTimeInput.extend({
|
||||
layoutName: "wizard/templates/components/wizard-date-time-input",
|
||||
|
||||
@discourseComputed("timeFirst", "tabindex")
|
||||
timeTabindex(timeFirst, tabindex) {
|
||||
return timeFirst ? tabindex : tabindex + 1;
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
import { observes } from "discourse-common/utils/decorators";
|
||||
import Category from "discourse/models/category";
|
||||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-category",
|
||||
|
||||
export default Ember.Component.extend({
|
||||
didInsertElement() {
|
||||
const property = this.field.property || "id";
|
||||
const value = this.field.value;
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-checkbox",
|
||||
});
|
|
@ -7,6 +7,8 @@ import { ajax } from "discourse/lib/ajax";
|
|||
import { on } from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-composer-preview",
|
||||
|
||||
@on("init")
|
||||
updatePreview() {
|
||||
if (this.isDestroyed) {
|
||||
|
|
|
@ -3,8 +3,11 @@ import {
|
|||
observes,
|
||||
} from "discourse-common/utils/decorators";
|
||||
import EmberObject from "@ember/object";
|
||||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-composer",
|
||||
|
||||
export default Ember.Component.extend({
|
||||
showPreview: false,
|
||||
classNameBindings: [
|
||||
":wizard-field-composer",
|
||||
|
|
|
@ -2,6 +2,8 @@ import Component from "@ember/component";
|
|||
import { observes } from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-date-time",
|
||||
|
||||
@observes("dateTime")
|
||||
setValue() {
|
||||
this.set("field.value", this.dateTime.format(this.field.format));
|
||||
|
|
|
@ -2,6 +2,8 @@ import Component from "@ember/component";
|
|||
import { observes } from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-date",
|
||||
|
||||
@observes("date")
|
||||
setValue() {
|
||||
this.set("field.value", this.date.format(this.field.format));
|
||||
|
|
15
assets/javascripts/wizard/components/wizard-field-dropdown.js.es6
Normale Datei
15
assets/javascripts/wizard/components/wizard-field-dropdown.js.es6
Normale Datei
|
@ -0,0 +1,15 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-dropdown",
|
||||
|
||||
keyPress(e) {
|
||||
e.stopPropagation();
|
||||
},
|
||||
|
||||
actions: {
|
||||
onChangeValue(value) {
|
||||
this.set("field.value", value);
|
||||
},
|
||||
},
|
||||
});
|
5
assets/javascripts/wizard/components/wizard-field-group.js.es6
Normale Datei
5
assets/javascripts/wizard/components/wizard-field-group.js.es6
Normale Datei
|
@ -0,0 +1,5 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-group",
|
||||
});
|
5
assets/javascripts/wizard/components/wizard-field-number.js.es6
Normale Datei
5
assets/javascripts/wizard/components/wizard-field-number.js.es6
Normale Datei
|
@ -0,0 +1,5 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-number",
|
||||
});
|
5
assets/javascripts/wizard/components/wizard-field-tag.js.es6
Normale Datei
5
assets/javascripts/wizard/components/wizard-field-tag.js.es6
Normale Datei
|
@ -0,0 +1,5 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-tag",
|
||||
});
|
9
assets/javascripts/wizard/components/wizard-field-text.js.es6
Normale Datei
9
assets/javascripts/wizard/components/wizard-field-text.js.es6
Normale Datei
|
@ -0,0 +1,9 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-text",
|
||||
|
||||
keyPress(e) {
|
||||
e.stopPropagation();
|
||||
},
|
||||
});
|
|
@ -0,0 +1,9 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-textarea",
|
||||
|
||||
keyPress(e) {
|
||||
e.stopPropagation();
|
||||
},
|
||||
});
|
|
@ -2,6 +2,8 @@ import Component from "@ember/component";
|
|||
import { observes } from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-time",
|
||||
|
||||
@observes("time")
|
||||
setValue() {
|
||||
this.set("field.value", this.time.format(this.field.format));
|
||||
|
|
|
@ -3,12 +3,16 @@ import Component from "@ember/component";
|
|||
import { computed } from "@ember/object";
|
||||
|
||||
export default Component.extend(UppyUploadMixin, {
|
||||
layoutName: "wizard/templates/components/wizard-field-upload",
|
||||
classNames: ["wizard-field-upload"],
|
||||
classNameBindings: ["isImage"],
|
||||
uploading: false,
|
||||
type: computed(function () {
|
||||
return `wizard_${this.field.id}`;
|
||||
}),
|
||||
id: computed(function () {
|
||||
return `wizard_field_upload_${this.field.id}`;
|
||||
}),
|
||||
isImage: computed("field.value.extension", function () {
|
||||
return (
|
||||
this.field.value &&
|
||||
|
|
5
assets/javascripts/wizard/components/wizard-field-url.js.es6
Normale Datei
5
assets/javascripts/wizard/components/wizard-field-url.js.es6
Normale Datei
|
@ -0,0 +1,5 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-url",
|
||||
});
|
|
@ -0,0 +1,5 @@
|
|||
import Component from "@ember/component";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field-user-selector",
|
||||
});
|
39
assets/javascripts/wizard/components/wizard-field.js.es6
Normale Datei
39
assets/javascripts/wizard/components/wizard-field.js.es6
Normale Datei
|
@ -0,0 +1,39 @@
|
|||
import Component from "@ember/component";
|
||||
import { dasherize } from "@ember/string";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { cook } from "discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite";
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-field",
|
||||
classNameBindings: [
|
||||
":wizard-field",
|
||||
"typeClasses",
|
||||
"field.invalid",
|
||||
"field.id",
|
||||
],
|
||||
|
||||
@discourseComputed("field.type", "field.id")
|
||||
typeClasses: (type, id) =>
|
||||
`${dasherize(type)}-field ${dasherize(type)}-${dasherize(id)}`,
|
||||
|
||||
@discourseComputed("field.id")
|
||||
fieldClass: (id) => `field-${dasherize(id)} wizard-focusable`,
|
||||
|
||||
@discourseComputed("field.type", "field.id")
|
||||
inputComponentName(type, id) {
|
||||
if (["text_only"].includes(type)) {
|
||||
return false;
|
||||
}
|
||||
return dasherize(type === "component" ? id : `wizard-field-${type}`);
|
||||
},
|
||||
|
||||
@discourseComputed("field.translatedDescription")
|
||||
cookedDescription(description) {
|
||||
return cook(description);
|
||||
},
|
||||
|
||||
@discourseComputed("field.type")
|
||||
textType(fieldType) {
|
||||
return ["text", "textarea"].includes(fieldType);
|
||||
},
|
||||
});
|
|
@ -3,6 +3,7 @@ import { computed } from "@ember/object";
|
|||
import { makeArray } from "discourse-common/lib/helpers";
|
||||
|
||||
export default ComboBox.extend({
|
||||
layoutName: "wizard/templates/components/wizard-group-selector",
|
||||
content: computed("groups.[]", "field.content.[]", function () {
|
||||
const whitelist = makeArray(this.field.content);
|
||||
return this.groups
|
||||
|
|
|
@ -1,10 +1,21 @@
|
|||
import CustomWizard from "../models/custom";
|
||||
import CustomWizard from "../models/wizard";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import Component from "@ember/component";
|
||||
import { dasherize } from "@ember/string";
|
||||
|
||||
export default Ember.Component.extend({
|
||||
siteName: function () {
|
||||
/*eslint no-undef:0*/
|
||||
return Wizard.SiteSettings.title;
|
||||
}.property(),
|
||||
export default Component.extend({
|
||||
classNameBindings: [":wizard-no-access", "reasonClass"],
|
||||
layoutName: "wizard/templates/components/wizard-no-access",
|
||||
|
||||
@discourseComputed("reason")
|
||||
reasonClass(reason) {
|
||||
return dasherize(reason);
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
siteName() {
|
||||
return this.siteSettings.title || "";
|
||||
},
|
||||
|
||||
actions: {
|
||||
skip() {
|
||||
|
|
|
@ -4,6 +4,7 @@ import { observes } from "discourse-common/utils/decorators";
|
|||
|
||||
export default Component.extend({
|
||||
classNames: ["wizard-similar-topics"],
|
||||
layoutName: "wizard/templates/components/wizard-similar-topics",
|
||||
showTopics: true,
|
||||
|
||||
didInsertElement() {
|
||||
|
|
9
assets/javascripts/wizard/components/wizard-step-form.js.es6
Normale Datei
9
assets/javascripts/wizard/components/wizard-step-form.js.es6
Normale Datei
|
@ -0,0 +1,9 @@
|
|||
import Component from "@ember/component";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default Component.extend({
|
||||
classNameBindings: [":wizard-step-form", "customStepClass"],
|
||||
|
||||
@discourseComputed("step.id")
|
||||
customStepClass: (stepId) => `wizard-step-${stepId}`,
|
||||
});
|
245
assets/javascripts/wizard/components/wizard-step.js.es6
Normale Datei
245
assets/javascripts/wizard/components/wizard-step.js.es6
Normale Datei
|
@ -0,0 +1,245 @@
|
|||
import discourseComputed, { observes } from "discourse-common/utils/decorators";
|
||||
import Component from "@ember/component";
|
||||
import I18n from "I18n";
|
||||
import getUrl from "discourse-common/lib/get-url";
|
||||
import { htmlSafe } from "@ember/template";
|
||||
import { schedule } from "@ember/runloop";
|
||||
import { cook } from "discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite";
|
||||
import { updateCachedWizard } from "discourse/plugins/discourse-custom-wizard/wizard/models/wizard";
|
||||
import { alias, not } from "@ember/object/computed";
|
||||
import CustomWizard from "../models/wizard";
|
||||
|
||||
const alreadyWarned = {};
|
||||
|
||||
export default Component.extend({
|
||||
layoutName: "wizard/templates/components/wizard-step",
|
||||
classNameBindings: [":wizard-step", "step.id"],
|
||||
saving: null,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
this.set("stylingDropdown", {});
|
||||
},
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
this.autoFocus();
|
||||
},
|
||||
|
||||
@discourseComputed("step.index", "wizard.required")
|
||||
showQuitButton: (index, required) => index === 0 && !required,
|
||||
|
||||
showNextButton: not("step.final"),
|
||||
showDoneButton: alias("step.final"),
|
||||
|
||||
@discourseComputed("step.translatedTitle")
|
||||
cookedTitle(title) {
|
||||
return cook(title);
|
||||
},
|
||||
|
||||
@discourseComputed("step.translatedDescription")
|
||||
cookedDescription(description) {
|
||||
return cook(description);
|
||||
},
|
||||
|
||||
@discourseComputed(
|
||||
"step.index",
|
||||
"step.displayIndex",
|
||||
"wizard.totalSteps",
|
||||
"wizard.completed"
|
||||
)
|
||||
showFinishButton: (index, displayIndex, total, completed) => {
|
||||
return index !== 0 && displayIndex !== total && completed;
|
||||
},
|
||||
|
||||
@discourseComputed("step.index")
|
||||
showBackButton: (index) => index > 0,
|
||||
|
||||
@discourseComputed("step.banner")
|
||||
bannerImage(src) {
|
||||
if (!src) {
|
||||
return;
|
||||
}
|
||||
return getUrl(src);
|
||||
},
|
||||
|
||||
@discourseComputed("step.id")
|
||||
bannerAndDescriptionClass(id) {
|
||||
return `wizard-banner-and-description wizard-banner-and-description-${id}`;
|
||||
},
|
||||
|
||||
@discourseComputed("step.fields.[]")
|
||||
primaryButtonIndex(fields) {
|
||||
return fields.length + 1;
|
||||
},
|
||||
|
||||
@discourseComputed("step.fields.[]")
|
||||
secondaryButtonIndex(fields) {
|
||||
return fields.length + 2;
|
||||
},
|
||||
|
||||
@observes("step.id")
|
||||
_stepChanged() {
|
||||
this.set("saving", false);
|
||||
this.autoFocus();
|
||||
},
|
||||
|
||||
@observes("step.message")
|
||||
_handleMessage: function () {
|
||||
const message = this.get("step.message");
|
||||
this.showMessage(message);
|
||||
},
|
||||
|
||||
keyPress(event) {
|
||||
if (event.key === "Enter") {
|
||||
if (this.showDoneButton) {
|
||||
this.send("quit");
|
||||
} else {
|
||||
this.send("nextStep");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@discourseComputed("step.index", "wizard.totalSteps")
|
||||
barStyle(displayIndex, totalSteps) {
|
||||
let ratio = parseFloat(displayIndex) / parseFloat(totalSteps - 1);
|
||||
if (ratio < 0) {
|
||||
ratio = 0;
|
||||
}
|
||||
if (ratio > 1) {
|
||||
ratio = 1;
|
||||
}
|
||||
|
||||
return htmlSafe(`width: ${ratio * 200}px`);
|
||||
},
|
||||
|
||||
@discourseComputed("step.fields")
|
||||
includeSidebar(fields) {
|
||||
return !!fields.findBy("show_in_sidebar");
|
||||
},
|
||||
|
||||
autoFocus() {
|
||||
schedule("afterRender", () => {
|
||||
const $invalid = $(
|
||||
".wizard-field.invalid:nth-of-type(1) .wizard-focusable"
|
||||
);
|
||||
|
||||
if ($invalid.length) {
|
||||
return $invalid.focus();
|
||||
}
|
||||
|
||||
$(".wizard-focusable:first").focus();
|
||||
});
|
||||
},
|
||||
|
||||
animateInvalidFields() {
|
||||
schedule("afterRender", () => {
|
||||
let $element = $(
|
||||
".invalid input[type=text],.invalid textarea,.invalid input[type=checkbox],.invalid .select-kit"
|
||||
);
|
||||
|
||||
if ($element.length) {
|
||||
$([document.documentElement, document.body]).animate(
|
||||
{
|
||||
scrollTop: $element.offset().top - 200,
|
||||
},
|
||||
400,
|
||||
function () {
|
||||
$element.wiggle(2, 100);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
advance() {
|
||||
this.set("saving", true);
|
||||
this.get("step")
|
||||
.save()
|
||||
.then((response) => {
|
||||
updateCachedWizard(CustomWizard.build(response["wizard"]));
|
||||
|
||||
if (response["final"]) {
|
||||
CustomWizard.finished(response);
|
||||
} else {
|
||||
this.goNext(response);
|
||||
}
|
||||
})
|
||||
.catch(() => this.animateInvalidFields())
|
||||
.finally(() => this.set("saving", false));
|
||||
},
|
||||
|
||||
actions: {
|
||||
quit() {
|
||||
this.get("wizard").skip();
|
||||
},
|
||||
|
||||
done() {
|
||||
this.send("nextStep");
|
||||
},
|
||||
|
||||
showMessage(message) {
|
||||
this.sendAction(message);
|
||||
},
|
||||
|
||||
stylingDropdownChanged(id, value) {
|
||||
this.set("stylingDropdown", { id, value });
|
||||
},
|
||||
|
||||
exitEarly() {
|
||||
const step = this.step;
|
||||
step.validate();
|
||||
|
||||
if (step.get("valid")) {
|
||||
this.set("saving", true);
|
||||
|
||||
step
|
||||
.save()
|
||||
.then(() => this.send("quit"))
|
||||
.finally(() => this.set("saving", false));
|
||||
} else {
|
||||
this.autoFocus();
|
||||
}
|
||||
},
|
||||
|
||||
backStep() {
|
||||
if (this.saving) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.goBack();
|
||||
},
|
||||
|
||||
nextStep() {
|
||||
if (this.saving) {
|
||||
return;
|
||||
}
|
||||
|
||||
const step = this.step;
|
||||
const result = step.validate();
|
||||
|
||||
if (result.warnings.length) {
|
||||
const unwarned = result.warnings.filter((w) => !alreadyWarned[w]);
|
||||
if (unwarned.length) {
|
||||
unwarned.forEach((w) => (alreadyWarned[w] = true));
|
||||
return window.bootbox.confirm(
|
||||
unwarned.map((w) => I18n.t(`wizard.${w}`)).join("\n"),
|
||||
I18n.t("no_value"),
|
||||
I18n.t("yes_value"),
|
||||
(confirmed) => {
|
||||
if (confirmed) {
|
||||
this.advance();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (step.get("valid")) {
|
||||
this.advance();
|
||||
} else {
|
||||
this.autoFocus();
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
|
@ -1,10 +1,9 @@
|
|||
/* eslint no-undef: 0*/
|
||||
|
||||
import computed from "discourse-common/utils/decorators";
|
||||
import { isLTR, isRTL, siteDir } from "discourse/lib/text-direction";
|
||||
import WizardI18n from "../lib/wizard-i18n";
|
||||
import TextField from "@ember/component/text-field";
|
||||
|
||||
export default Ember.TextField.extend({
|
||||
export default TextField.extend({
|
||||
attributeBindings: [
|
||||
"autocorrect",
|
||||
"autocapitalize",
|
||||
|
@ -15,7 +14,7 @@ export default Ember.TextField.extend({
|
|||
|
||||
@computed
|
||||
dir() {
|
||||
if (Wizard.SiteSettings.support_mixed_text_direction) {
|
||||
if (this.siteSettings.support_mixed_text_direction) {
|
||||
let val = this.value;
|
||||
if (val) {
|
||||
return isRTL(val) ? "rtl" : "ltr";
|
||||
|
@ -26,7 +25,7 @@ export default Ember.TextField.extend({
|
|||
},
|
||||
|
||||
keyUp() {
|
||||
if (Wizard.SiteSettings.support_mixed_text_direction) {
|
||||
if (this.siteSettings.support_mixed_text_direction) {
|
||||
let val = this.value;
|
||||
if (isRTL(val)) {
|
||||
this.set("dir", "rtl");
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import TimeInput from "discourse/components/time-input";
|
||||
|
||||
export default TimeInput.extend();
|
||||
export default TimeInput.extend({
|
||||
layoutName: "wizard/templates/components/wizard-time-input",
|
||||
});
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
export default Ember.Controller.extend({
|
||||
queryParams: ["reset"],
|
||||
});
|
|
@ -1,7 +1,10 @@
|
|||
import StepController from "wizard/controllers/step";
|
||||
import Controller from "@ember/controller";
|
||||
import getUrl from "discourse-common/lib/get-url";
|
||||
|
||||
export default StepController.extend({
|
||||
export default Controller.extend({
|
||||
wizard: null,
|
||||
step: null,
|
||||
|
||||
actions: {
|
||||
goNext(response) {
|
||||
let nextStepId = response["next_step_id"];
|
||||
|
@ -12,12 +15,12 @@ export default StepController.extend({
|
|||
const wizardId = this.get("wizard.id");
|
||||
window.location.href = getUrl(`/w/${wizardId}/steps/${nextStepId}`);
|
||||
} else {
|
||||
this.transitionToRoute("custom.step", nextStepId);
|
||||
this.transitionToRoute("step", nextStepId);
|
||||
}
|
||||
},
|
||||
|
||||
goBack() {
|
||||
this.transitionToRoute("custom.step", this.get("step.previous"));
|
||||
this.transitionToRoute("step", this.get("step.previous"));
|
||||
},
|
||||
|
||||
showMessage(message) {
|
24
assets/javascripts/wizard/controllers/wizard-index.js.es6
Normale Datei
24
assets/javascripts/wizard/controllers/wizard-index.js.es6
Normale Datei
|
@ -0,0 +1,24 @@
|
|||
import Controller from "@ember/controller";
|
||||
import { or } from "@ember/object/computed";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
const reasons = {
|
||||
noWizard: "none",
|
||||
requiresLogin: "requires_login",
|
||||
notPermitted: "not_permitted",
|
||||
completed: "completed",
|
||||
};
|
||||
|
||||
export default Controller.extend({
|
||||
noAccess: or("noWizard", "requiresLogin", "notPermitted", "completed"),
|
||||
|
||||
@discourseComputed("noAccessReason")
|
||||
noAccessI18nKey(reason) {
|
||||
return reason ? `wizard.${reasons[reason]}` : "wizard.none";
|
||||
},
|
||||
|
||||
@discourseComputed
|
||||
noAccessReason() {
|
||||
return Object.keys(reasons).find((reason) => this.get(reason));
|
||||
},
|
||||
});
|
5
assets/javascripts/wizard/controllers/wizard.js.es6
Normale Datei
5
assets/javascripts/wizard/controllers/wizard.js.es6
Normale Datei
|
@ -0,0 +1,5 @@
|
|||
import Controller from "@ember/controller";
|
||||
|
||||
export default Controller.extend({
|
||||
queryParams: ["reset"],
|
||||
});
|
|
@ -1,39 +0,0 @@
|
|||
import { buildResolver } from "discourse-common/resolver";
|
||||
|
||||
export default Ember.Application.extend({
|
||||
rootElement: "#custom-wizard-main",
|
||||
Resolver: buildResolver("wizard"),
|
||||
|
||||
customEvents: {
|
||||
paste: "paste",
|
||||
},
|
||||
|
||||
start() {
|
||||
Object.keys(requirejs._eak_seen).forEach((key) => {
|
||||
if (/\/pre\-initializers\//.test(key)) {
|
||||
const module = requirejs(key, null, null, true);
|
||||
if (!module) {
|
||||
throw new Error(key + " must export an initializer.");
|
||||
}
|
||||
|
||||
const init = module.default;
|
||||
const oldInitialize = init.initialize;
|
||||
init.initialize = () => {
|
||||
oldInitialize.call(this, this.__container__, this);
|
||||
};
|
||||
|
||||
this.initializer(init);
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(requirejs._eak_seen).forEach((key) => {
|
||||
if (/\/initializers\//.test(key)) {
|
||||
const module = requirejs(key, null, null, true);
|
||||
if (!module) {
|
||||
throw new Error(key + " must export an initializer.");
|
||||
}
|
||||
this.initializer(module.default);
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
|
@ -1,219 +0,0 @@
|
|||
export default {
|
||||
name: "custom-wizard-step",
|
||||
initialize() {
|
||||
if (window.location.pathname.indexOf("/w/") < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const CustomWizard = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/models/custom"
|
||||
).default;
|
||||
const updateCachedWizard = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/models/custom"
|
||||
).updateCachedWizard;
|
||||
const StepModel = requirejs("wizard/models/step").default;
|
||||
const StepComponent = requirejs("wizard/components/wizard-step").default;
|
||||
const ajax = requirejs("wizard/lib/ajax").ajax;
|
||||
const getUrl = requirejs("discourse-common/lib/get-url").default;
|
||||
const discourseComputed = requirejs("discourse-common/utils/decorators")
|
||||
.default;
|
||||
const cook = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite"
|
||||
).cook;
|
||||
const { schedule } = requirejs("@ember/runloop");
|
||||
const { alias, not } = requirejs("@ember/object/computed");
|
||||
const { translatedText } = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/lib/wizard-i18n"
|
||||
);
|
||||
|
||||
StepModel.reopen({
|
||||
@discourseComputed("wizardId", "id")
|
||||
i18nKey(wizardId, stepId) {
|
||||
return `${wizardId}.${stepId}`;
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey", "title")
|
||||
translatedTitle(i18nKey, title) {
|
||||
return translatedText(`${i18nKey}.title`, title);
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey", "description")
|
||||
translatedDescription(i18nKey, description) {
|
||||
return translatedText(`${i18nKey}.description`, description);
|
||||
},
|
||||
|
||||
save() {
|
||||
const wizardId = this.get("wizardId");
|
||||
const fields = {};
|
||||
|
||||
this.get("fields").forEach((f) => {
|
||||
if (f.type !== "text_only") {
|
||||
fields[f.id] = f.value;
|
||||
}
|
||||
});
|
||||
|
||||
return ajax({
|
||||
url: `/w/${wizardId}/steps/${this.get("id")}`,
|
||||
type: "PUT",
|
||||
data: { fields },
|
||||
}).catch((response) => {
|
||||
if (
|
||||
response &&
|
||||
response.responseJSON &&
|
||||
response.responseJSON.errors
|
||||
) {
|
||||
let wizardErrors = [];
|
||||
response.responseJSON.errors.forEach((err) => {
|
||||
if (err.field === wizardId) {
|
||||
wizardErrors.push(err.description);
|
||||
} else if (err.field) {
|
||||
this.fieldError(err.field, err.description);
|
||||
} else if (err) {
|
||||
wizardErrors.push(err);
|
||||
}
|
||||
});
|
||||
if (wizardErrors.length) {
|
||||
this.handleWizardError(wizardErrors.join("\n"));
|
||||
}
|
||||
this.animateInvalidFields();
|
||||
throw response;
|
||||
}
|
||||
|
||||
if (response && response.responseText) {
|
||||
const responseText = response.responseText;
|
||||
const start = responseText.indexOf(">") + 1;
|
||||
const end = responseText.indexOf("plugins");
|
||||
const message = responseText.substring(start, end);
|
||||
this.handleWizardError(message);
|
||||
throw message;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
handleWizardError(message) {
|
||||
this.set("message", {
|
||||
state: "error",
|
||||
text: message,
|
||||
});
|
||||
Ember.run.later(() => this.set("message", null), 6000);
|
||||
},
|
||||
});
|
||||
|
||||
StepComponent.reopen({
|
||||
classNameBindings: ["step.id"],
|
||||
|
||||
autoFocus() {
|
||||
schedule("afterRender", () => {
|
||||
const $invalid = $(
|
||||
".wizard-field.invalid:nth-of-type(1) .wizard-focusable"
|
||||
);
|
||||
|
||||
if ($invalid.length) {
|
||||
return $invalid.focus();
|
||||
}
|
||||
|
||||
$(".wizard-focusable:first").focus();
|
||||
});
|
||||
},
|
||||
|
||||
animateInvalidFields() {
|
||||
schedule("afterRender", () => {
|
||||
let $element = $(
|
||||
".invalid input[type=text],.invalid textarea,.invalid input[type=checkbox],.invalid .select-kit"
|
||||
);
|
||||
|
||||
if ($element.length) {
|
||||
$([document.documentElement, document.body]).animate(
|
||||
{
|
||||
scrollTop: $element.offset().top - 200,
|
||||
},
|
||||
400,
|
||||
function () {
|
||||
$element.wiggle(2, 100);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
ensureStartsAtTop: function () {
|
||||
window.scrollTo(0, 0);
|
||||
}.observes("step.id"),
|
||||
|
||||
showQuitButton: function () {
|
||||
const index = this.get("step.index");
|
||||
const required = this.get("wizard.required");
|
||||
return index === 0 && !required;
|
||||
}.property("step.index", "wizard.required"),
|
||||
|
||||
@discourseComputed("step.translatedTitle")
|
||||
cookedTitle(title) {
|
||||
return cook(title);
|
||||
},
|
||||
|
||||
@discourseComputed("step.translatedDescription")
|
||||
cookedDescription(description) {
|
||||
return cook(description);
|
||||
},
|
||||
|
||||
bannerImage: function () {
|
||||
const src = this.get("step.banner");
|
||||
if (!src) {
|
||||
return;
|
||||
}
|
||||
return getUrl(src);
|
||||
}.property("step.banner"),
|
||||
|
||||
@discourseComputed("step.fields.[]")
|
||||
primaryButtonIndex(fields) {
|
||||
return fields.length + 1;
|
||||
},
|
||||
|
||||
@discourseComputed("step.fields.[]")
|
||||
secondaryButtonIndex(fields) {
|
||||
return fields.length + 2;
|
||||
},
|
||||
|
||||
handleMessage: function () {
|
||||
const message = this.get("step.message");
|
||||
this.sendAction("showMessage", message);
|
||||
}.observes("step.message"),
|
||||
|
||||
showNextButton: not("step.final"),
|
||||
showDoneButton: alias("step.final"),
|
||||
|
||||
advance() {
|
||||
this.set("saving", true);
|
||||
this.get("step")
|
||||
.save()
|
||||
.then((response) => {
|
||||
updateCachedWizard(CustomWizard.build(response["wizard"]));
|
||||
|
||||
if (response["final"]) {
|
||||
CustomWizard.finished(response);
|
||||
} else {
|
||||
this.sendAction("goNext", response);
|
||||
}
|
||||
})
|
||||
.catch(() => this.animateInvalidFields())
|
||||
.finally(() => this.set("saving", false));
|
||||
},
|
||||
|
||||
keyPress() {},
|
||||
|
||||
actions: {
|
||||
quit() {
|
||||
this.get("wizard").skip();
|
||||
},
|
||||
|
||||
done() {
|
||||
this.send("nextStep");
|
||||
},
|
||||
|
||||
showMessage(message) {
|
||||
this.sendAction("showMessage", message);
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,126 +0,0 @@
|
|||
export default {
|
||||
name: "custom-routes",
|
||||
initialize(app) {
|
||||
if (window.location.pathname.indexOf("/w/") < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const EmberObject = requirejs("@ember/object").default;
|
||||
const Router = requirejs("wizard/router").default;
|
||||
const ApplicationRoute = requirejs("wizard/routes/application").default;
|
||||
const getUrl = requirejs("discourse-common/lib/get-url").default;
|
||||
const Store = requirejs("discourse/services/store").default;
|
||||
const registerRawHelpers = requirejs(
|
||||
"discourse-common/lib/raw-handlebars-helpers"
|
||||
).registerRawHelpers;
|
||||
const createHelperContext = requirejs("discourse-common/lib/helpers")
|
||||
.createHelperContext;
|
||||
const RawHandlebars = requirejs("discourse-common/lib/raw-handlebars")
|
||||
.default;
|
||||
const Handlebars = requirejs("handlebars").default;
|
||||
const Site = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/models/site"
|
||||
).default;
|
||||
const RestAdapter = requirejs("discourse/adapters/rest").default;
|
||||
const Session = requirejs("discourse/models/session").default;
|
||||
const setDefaultOwner = requirejs("discourse-common/lib/get-owner")
|
||||
.setDefaultOwner;
|
||||
const messageBus = requirejs("message-bus-client").default;
|
||||
const getToken = requirejs("wizard/lib/ajax").getToken;
|
||||
const setEnvironment = requirejs("discourse-common/config/environment")
|
||||
.setEnvironment;
|
||||
const container = app.__container__;
|
||||
Discourse.Model = EmberObject.extend();
|
||||
Discourse.__container__ = container;
|
||||
setDefaultOwner(container);
|
||||
registerRawHelpers(RawHandlebars, Handlebars);
|
||||
|
||||
// IE11 Polyfill - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Polyfill
|
||||
if (!Object.entries) {
|
||||
Object.entries = function (obj) {
|
||||
let ownProps = Object.keys(obj),
|
||||
i = ownProps.length,
|
||||
resArray = new Array(i); // preallocate the Array
|
||||
while (i--) {
|
||||
resArray[i] = [ownProps[i], obj[ownProps[i]]];
|
||||
}
|
||||
|
||||
return resArray;
|
||||
};
|
||||
}
|
||||
|
||||
Object.keys(Ember.TEMPLATES).forEach((k) => {
|
||||
if (k.indexOf("select-kit") === 0) {
|
||||
let template = Ember.TEMPLATES[k];
|
||||
define(k, () => template);
|
||||
}
|
||||
});
|
||||
|
||||
const targets = ["controller", "component", "route", "model", "adapter"];
|
||||
/*eslint no-undef: 0*/
|
||||
const siteSettings = Wizard.SiteSettings;
|
||||
app.register("site-settings:main", siteSettings, { instantiate: false });
|
||||
createHelperContext({ siteSettings });
|
||||
targets.forEach((t) => app.inject(t, "siteSettings", "site-settings:main"));
|
||||
|
||||
app.register("message-bus:main", messageBus, { instantiate: false });
|
||||
targets.forEach((t) => app.inject(t, "messageBus", "message-bus:main"));
|
||||
|
||||
app.register("service:store", Store);
|
||||
targets.forEach((t) => app.inject(t, "store", "service:store"));
|
||||
targets.forEach((t) => app.inject(t, "appEvents", "service:app-events"));
|
||||
|
||||
app.register("adapter:rest", RestAdapter);
|
||||
|
||||
const site = Site.current();
|
||||
app.register("site:main", site, { instantiate: false });
|
||||
targets.forEach((t) => app.inject(t, "site", "site:main"));
|
||||
|
||||
site.set("can_create_tag", false);
|
||||
app.register("session:main", Session.current(), { instantiate: false });
|
||||
targets.forEach((t) => app.inject(t, "session", "session:main"));
|
||||
|
||||
createHelperContext({
|
||||
siteSettings: container.lookup("site-settings:main"),
|
||||
currentUser: container.lookup("current-user:main"),
|
||||
site: container.lookup("site:main"),
|
||||
session: container.lookup("session:main"),
|
||||
capabilities: container.lookup("capabilities:main"),
|
||||
});
|
||||
|
||||
const session = container.lookup("session:main");
|
||||
const setupData = document.getElementById("data-discourse-setup").dataset;
|
||||
session.set("highlightJsPath", setupData.highlightJsPath);
|
||||
setEnvironment(setupData.environment);
|
||||
|
||||
Router.reopen({
|
||||
rootURL: getUrl("/w/"),
|
||||
});
|
||||
|
||||
Router.map(function () {
|
||||
this.route("custom", { path: "/:wizard_id" }, function () {
|
||||
this.route("steps");
|
||||
this.route("step", { path: "/steps/:step_id" });
|
||||
});
|
||||
});
|
||||
|
||||
ApplicationRoute.reopen({
|
||||
redirect() {
|
||||
this.transitionTo("custom");
|
||||
},
|
||||
model() {},
|
||||
});
|
||||
|
||||
// Add a CSRF token to all AJAX requests
|
||||
let token = getToken();
|
||||
session.set("csrfToken", token);
|
||||
let callbacks = $.Callbacks();
|
||||
$.ajaxPrefilter(callbacks.fire);
|
||||
|
||||
callbacks.add(function (options, originalOptions, xhr) {
|
||||
if (!options.crossDomain) {
|
||||
xhr.setRequestHeader("X-CSRF-Token", session.get("csrfToken"));
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
12
assets/javascripts/wizard/lib/initialize/create-contexts.js.es6
Normale Datei
12
assets/javascripts/wizard/lib/initialize/create-contexts.js.es6
Normale Datei
|
@ -0,0 +1,12 @@
|
|||
export default {
|
||||
run(app, container) {
|
||||
const { createHelperContext } = requirejs("discourse-common/lib/helpers");
|
||||
|
||||
createHelperContext({
|
||||
siteSettings: container.lookup("site-settings:main"),
|
||||
site: container.lookup("site:main"),
|
||||
session: container.lookup("session:main"),
|
||||
capabilities: container.lookup("capabilities:main"),
|
||||
});
|
||||
},
|
||||
};
|
58
assets/javascripts/wizard/lib/initialize/inject-objects.js.es6
Normale Datei
58
assets/javascripts/wizard/lib/initialize/inject-objects.js.es6
Normale Datei
|
@ -0,0 +1,58 @@
|
|||
export default {
|
||||
run(app) {
|
||||
// siteSettings must always be registered first
|
||||
if (!app.hasRegistration("site-settings:main")) {
|
||||
const siteSettings = app.SiteSettings;
|
||||
app.register("site-settings:main", siteSettings, { instantiate: false });
|
||||
}
|
||||
|
||||
const Store = requirejs("discourse/services/store").default;
|
||||
const Site = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/models/site"
|
||||
).default;
|
||||
const Session = requirejs("discourse/models/session").default;
|
||||
const RestAdapter = requirejs("discourse/adapters/rest").default;
|
||||
const messageBus = requirejs("message-bus-client").default;
|
||||
const sniffCapabilites = requirejs(
|
||||
"discourse/pre-initializers/sniff-capabilities"
|
||||
).default;
|
||||
|
||||
const site = Site.current();
|
||||
const session = Session.current();
|
||||
const registrations = [
|
||||
["message-bus:main", messageBus, false],
|
||||
["site:main", site, false],
|
||||
["session:main", session, false],
|
||||
["service:store", Store, true],
|
||||
["adapter:rest", RestAdapter, true],
|
||||
];
|
||||
|
||||
registrations.forEach((registration) => {
|
||||
if (!app.hasRegistration(registration[0])) {
|
||||
app.register(registration[0], registration[1], {
|
||||
instantiate: registration[2],
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const targets = ["controller", "component", "route", "model", "adapter"];
|
||||
|
||||
targets.forEach((t) => {
|
||||
app.inject(t, "appEvents", "service:app-events");
|
||||
app.inject(t, "store", "service:store");
|
||||
app.inject(t, "site", "site:main");
|
||||
});
|
||||
|
||||
targets.concat("service").forEach((t) => {
|
||||
app.inject(t, "session", "session:main");
|
||||
app.inject(t, "messageBus", "message-bus:main");
|
||||
app.inject(t, "siteSettings", "site-settings:main");
|
||||
});
|
||||
|
||||
if (!app.hasRegistration("capabilities:main")) {
|
||||
sniffCapabilites.initialize(null, app);
|
||||
}
|
||||
|
||||
site.set("can_create_tag", false);
|
||||
},
|
||||
};
|
|
@ -1,117 +1,32 @@
|
|||
import { dasherize } from "@ember/string";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default {
|
||||
name: "custom-wizard-field",
|
||||
initialize() {
|
||||
if (window.location.pathname.indexOf("/w/") < 0) {
|
||||
return;
|
||||
run(app, container) {
|
||||
const getToken = requirejs("wizard/lib/ajax").getToken;
|
||||
const isTesting = requirejs("discourse-common/config/environment")
|
||||
.isTesting;
|
||||
|
||||
if (!isTesting()) {
|
||||
// Add a CSRF token to all AJAX requests
|
||||
let token = getToken();
|
||||
const session = container.lookup("session:main");
|
||||
session.set("csrfToken", token);
|
||||
let callbacks = $.Callbacks();
|
||||
$.ajaxPrefilter(callbacks.fire);
|
||||
|
||||
callbacks.add(function (options, originalOptions, xhr) {
|
||||
if (!options.crossDomain) {
|
||||
xhr.setRequestHeader("X-CSRF-Token", session.get("csrfToken"));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const FieldComponent = requirejs("wizard/components/wizard-field").default;
|
||||
const FieldModel = requirejs("wizard/models/wizard-field").default;
|
||||
const { cook } = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite"
|
||||
);
|
||||
const DEditor = requirejs("discourse/components/d-editor").default;
|
||||
const { clipboardHelpers } = requirejs("discourse/lib/utilities");
|
||||
const toMarkdown = requirejs("discourse/lib/to-markdown").default;
|
||||
const { translatedText } = requirejs(
|
||||
const discourseComputed = requirejs("discourse-common/utils/decorators")
|
||||
.default;
|
||||
const WizardI18n = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/lib/wizard-i18n"
|
||||
);
|
||||
|
||||
FieldComponent.reopen({
|
||||
classNameBindings: ["field.id"],
|
||||
|
||||
@discourseComputed("field.translatedDescription")
|
||||
cookedDescription(description) {
|
||||
return cook(description);
|
||||
},
|
||||
|
||||
@discourseComputed("field.type")
|
||||
textType(fieldType) {
|
||||
return ["text", "textarea"].includes(fieldType);
|
||||
},
|
||||
|
||||
inputComponentName: function () {
|
||||
const type = this.get("field.type");
|
||||
const id = this.get("field.id");
|
||||
if (["text_only"].includes(type)) {
|
||||
return false;
|
||||
}
|
||||
return dasherize(type === "component" ? id : `wizard-field-${type}`);
|
||||
}.property("field.type", "field.id"),
|
||||
});
|
||||
|
||||
const StandardFieldValidation = [
|
||||
"text",
|
||||
"number",
|
||||
"textarea",
|
||||
"dropdown",
|
||||
"tag",
|
||||
"image",
|
||||
"user_selector",
|
||||
"text_only",
|
||||
"composer",
|
||||
"category",
|
||||
"group",
|
||||
"date",
|
||||
"time",
|
||||
"date_time",
|
||||
];
|
||||
|
||||
FieldModel.reopen({
|
||||
@discourseComputed("wizardId", "stepId", "id")
|
||||
i18nKey(wizardId, stepId, id) {
|
||||
return `${wizardId}.${stepId}.${id}`;
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey", "label")
|
||||
translatedLabel(i18nKey, label) {
|
||||
return translatedText(`${i18nKey}.label`, label);
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey", "placeholder")
|
||||
translatedPlaceholder(i18nKey, placeholder) {
|
||||
return translatedText(`${i18nKey}.placeholder`, placeholder);
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey", "description")
|
||||
translatedDescription(i18nKey, description) {
|
||||
return translatedText(`${i18nKey}.description`, description);
|
||||
},
|
||||
|
||||
check() {
|
||||
if (this.customCheck) {
|
||||
return this.customCheck();
|
||||
}
|
||||
|
||||
let valid = this.valid;
|
||||
|
||||
if (!this.required) {
|
||||
this.setValid(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
const val = this.get("value");
|
||||
const type = this.get("type");
|
||||
|
||||
if (type === "checkbox") {
|
||||
valid = val;
|
||||
} else if (type === "upload") {
|
||||
valid = val && val.id > 0;
|
||||
} else if (StandardFieldValidation.indexOf(type) > -1) {
|
||||
valid = val && val.toString().length > 0;
|
||||
} else if (type === "url") {
|
||||
valid = true;
|
||||
}
|
||||
|
||||
this.setValid(valid);
|
||||
|
||||
return valid;
|
||||
},
|
||||
});
|
||||
|
||||
).default;
|
||||
const isInside = (text, regex) => {
|
||||
const matches = text.match(regex);
|
||||
return matches && matches.length % 2;
|
||||
|
@ -136,6 +51,17 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
@discourseComputed("placeholder", "placeholderOverride")
|
||||
placeholderTranslated(placeholder, placeholderOverride) {
|
||||
if (placeholderOverride) {
|
||||
return placeholderOverride;
|
||||
}
|
||||
if (placeholder) {
|
||||
return WizardI18n(placeholder);
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
_wizardInsertText(args = {}) {
|
||||
if (args.fieldId === this.fieldId) {
|
||||
this._insertText(args.text, args.options);
|
||||
|
@ -218,5 +144,19 @@ export default {
|
|||
}
|
||||
},
|
||||
});
|
||||
|
||||
// IE11 Polyfill - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Polyfill
|
||||
if (!Object.entries) {
|
||||
Object.entries = function (obj) {
|
||||
let ownProps = Object.keys(obj),
|
||||
i = ownProps.length,
|
||||
resArray = new Array(i); // preallocate the Array
|
||||
while (i--) {
|
||||
resArray[i] = [ownProps[i], obj[ownProps[i]]];
|
||||
}
|
||||
|
||||
return resArray;
|
||||
};
|
||||
}
|
||||
},
|
||||
};
|
30
assets/javascripts/wizard/lib/initialize/register-files.js.es6
Normale Datei
30
assets/javascripts/wizard/lib/initialize/register-files.js.es6
Normale Datei
|
@ -0,0 +1,30 @@
|
|||
export default {
|
||||
run(app, container) {
|
||||
const RawHandlebars = requirejs("discourse-common/lib/raw-handlebars")
|
||||
.default;
|
||||
const Handlebars = requirejs("handlebars").default;
|
||||
const registerRawHelpers = requirejs(
|
||||
"discourse-common/lib/raw-handlebars-helpers"
|
||||
).registerRawHelpers;
|
||||
const { registerHelpers } = requirejs("discourse-common/lib/helpers");
|
||||
const jqueryPlugins = requirejs("discourse/initializers/jquery-plugins")
|
||||
.default;
|
||||
|
||||
Object.keys(Ember.TEMPLATES).forEach((k) => {
|
||||
if (k.indexOf("select-kit") === 0) {
|
||||
let template = Ember.TEMPLATES[k];
|
||||
define(k, () => template);
|
||||
}
|
||||
});
|
||||
|
||||
Object.keys(requirejs.entries).forEach((entry) => {
|
||||
if (/\/helpers\//.test(entry)) {
|
||||
requirejs(entry, null, null, true);
|
||||
}
|
||||
});
|
||||
|
||||
registerRawHelpers(RawHandlebars, Handlebars);
|
||||
registerHelpers(app);
|
||||
jqueryPlugins.initialize(container, app);
|
||||
},
|
||||
};
|
57
assets/javascripts/wizard/lib/initialize/wizard.js.es6
Normale Datei
57
assets/javascripts/wizard/lib/initialize/wizard.js.es6
Normale Datei
|
@ -0,0 +1,57 @@
|
|||
export default {
|
||||
name: "custom-wizard",
|
||||
initialize(app) {
|
||||
const isTesting = requirejs("discourse-common/config/environment")
|
||||
.isTesting;
|
||||
const isWizard = window.location.pathname.indexOf("/w/") > -1;
|
||||
|
||||
if (!isWizard && !isTesting()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const container = app.__container__;
|
||||
const setDefaultOwner = requirejs("discourse-common/lib/get-owner")
|
||||
.setDefaultOwner;
|
||||
setDefaultOwner(container);
|
||||
|
||||
if (!isTesting()) {
|
||||
const PreloadStore = requirejs("discourse/lib/preload-store").default;
|
||||
|
||||
let preloaded;
|
||||
const preloadedDataElement = document.getElementById(
|
||||
"data-preloaded-wizard"
|
||||
);
|
||||
if (preloadedDataElement) {
|
||||
preloaded = JSON.parse(preloadedDataElement.dataset.preloadedWizard);
|
||||
}
|
||||
|
||||
Object.keys(preloaded).forEach(function (key) {
|
||||
PreloadStore.store(key, JSON.parse(preloaded[key]));
|
||||
});
|
||||
|
||||
app.SiteSettings = PreloadStore.get("siteSettings");
|
||||
}
|
||||
|
||||
const setEnvironment = requirejs("discourse-common/config/environment")
|
||||
.setEnvironment;
|
||||
const setupData = document.getElementById("data-discourse-setup").dataset;
|
||||
setEnvironment(setupData.environment);
|
||||
|
||||
const Session = requirejs("discourse/models/session").default;
|
||||
const session = Session.current();
|
||||
session.set("highlightJsPath", setupData.highlightJsPath);
|
||||
session.set("markdownItUrl", setupData.markdownItUrl);
|
||||
|
||||
[
|
||||
"register-files",
|
||||
"inject-objects",
|
||||
"create-contexts",
|
||||
"patch-components",
|
||||
].forEach((fileName) => {
|
||||
const initializer = requirejs(
|
||||
`discourse/plugins/discourse-custom-wizard/wizard/lib/initialize/${fileName}`
|
||||
).default;
|
||||
initializer.run(app, container);
|
||||
});
|
||||
},
|
||||
};
|
|
@ -1,5 +1,7 @@
|
|||
import { ajax } from "wizard/lib/ajax";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import getURL, { getURLWithCDN } from "discourse-common/lib/get-url";
|
||||
import { run } from "@ember/runloop";
|
||||
import { Promise } from "rsvp";
|
||||
|
||||
const _loaded = {};
|
||||
const _loading = {};
|
||||
|
@ -25,7 +27,7 @@ function loadWithTag(path, cb) {
|
|||
) {
|
||||
s = s.onload = s.onreadystatechange = null;
|
||||
if (!abort) {
|
||||
Ember.run(null, cb);
|
||||
run(null, cb);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -38,7 +40,7 @@ export function loadCSS(url) {
|
|||
export default function loadScript(url, opts) {
|
||||
// TODO: Remove this once plugins have been updated not to use it:
|
||||
if (url === "defer/html-sanitizer-bundle") {
|
||||
return Ember.RSVP.Promise.resolve();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
opts = opts || {};
|
||||
|
@ -51,7 +53,7 @@ export default function loadScript(url, opts) {
|
|||
}
|
||||
});
|
||||
|
||||
return new Ember.RSVP.Promise(function (resolve) {
|
||||
return new Promise(function (resolve) {
|
||||
url = getURL(url);
|
||||
|
||||
// If we already loaded this url
|
||||
|
@ -63,7 +65,7 @@ export default function loadScript(url, opts) {
|
|||
}
|
||||
|
||||
let done;
|
||||
_loading[url] = new Ember.RSVP.Promise(function (_done) {
|
||||
_loading[url] = new Promise(function (_done) {
|
||||
done = _done;
|
||||
});
|
||||
|
||||
|
@ -84,8 +86,8 @@ export default function loadScript(url, opts) {
|
|||
|
||||
// Scripts should always load from CDN
|
||||
// CSS is type text, to accept it from a CDN we would need to handle CORS
|
||||
if (!opts.css && Discourse.CDN && url[0] === "/" && url[1] !== "/") {
|
||||
cdnUrl = Discourse.CDN.replace(/\/$/, "") + url;
|
||||
if (!opts.css) {
|
||||
cdnUrl = getURLWithCDN(url);
|
||||
}
|
||||
|
||||
// Some javascript depends on the path of where it is loaded (ace editor)
|
||||
|
|
|
@ -3,6 +3,8 @@ import { default as PrettyText, buildOptions } from "pretty-text/pretty-text";
|
|||
import Handlebars from "handlebars";
|
||||
import getURL from "discourse-common/lib/get-url";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
import { Promise } from "rsvp";
|
||||
import Session from "discourse/models/session";
|
||||
|
||||
export function cook(text, options) {
|
||||
if (!options) {
|
||||
|
@ -18,11 +20,15 @@ export function cook(text, options) {
|
|||
// everything should eventually move to async API and this should be renamed
|
||||
// cook
|
||||
export function cookAsync(text, options) {
|
||||
if (Discourse.MarkdownItURL) {
|
||||
return loadScript(Discourse.MarkdownItURL)
|
||||
let markdownItURL = Session.currentProp("markdownItURL");
|
||||
if (markdownItURL) {
|
||||
return (
|
||||
loadScript(markdownItURL)
|
||||
.then(() => cook(text, options))
|
||||
.catch((e) => Ember.Logger.error(e));
|
||||
// eslint-disable-next-line no-console
|
||||
.catch((e) => console.error(e))
|
||||
);
|
||||
} else {
|
||||
return Ember.RSVP.Promise.resolve(cook(text));
|
||||
return Promise.resolve(cook(text));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { CANCELLED_STATUS } from "discourse/lib/autocomplete";
|
||||
import { debounce } from "@ember/runloop";
|
||||
import getUrl from "discourse-common/lib/get-url";
|
||||
import { Promise } from "rsvp";
|
||||
|
||||
let cache = {},
|
||||
cacheTopicId,
|
||||
|
@ -120,7 +121,7 @@ export default function userSearch(options) {
|
|||
|
||||
currentTerm = term;
|
||||
|
||||
return new Ember.RSVP.Promise(function (resolve) {
|
||||
return new Promise(function (resolve) {
|
||||
// TODO site setting for allowed regex in username
|
||||
if (term.match(/[^\w_\-\.@\+]/)) {
|
||||
resolve([]);
|
||||
|
|
|
@ -1,71 +0,0 @@
|
|||
// lite version of discourse/lib/utilities
|
||||
|
||||
export function determinePostReplaceSelection({
|
||||
selection,
|
||||
needle,
|
||||
replacement,
|
||||
}) {
|
||||
const diff =
|
||||
replacement.end - replacement.start - (needle.end - needle.start);
|
||||
|
||||
if (selection.end <= needle.start) {
|
||||
// Selection ends (and starts) before needle.
|
||||
return { start: selection.start, end: selection.end };
|
||||
} else if (selection.start <= needle.start) {
|
||||
// Selection starts before needle...
|
||||
if (selection.end < needle.end) {
|
||||
// ... and ends inside needle.
|
||||
return { start: selection.start, end: needle.start };
|
||||
} else {
|
||||
// ... and spans needle completely.
|
||||
return { start: selection.start, end: selection.end + diff };
|
||||
}
|
||||
} else if (selection.start < needle.end) {
|
||||
// Selection starts inside needle...
|
||||
if (selection.end <= needle.end) {
|
||||
// ... and ends inside needle.
|
||||
return { start: replacement.end, end: replacement.end };
|
||||
} else {
|
||||
// ... and spans end of needle.
|
||||
return { start: replacement.end, end: selection.end + diff };
|
||||
}
|
||||
} else {
|
||||
// Selection starts (and ends) behind needle.
|
||||
return { start: selection.start + diff, end: selection.end + diff };
|
||||
}
|
||||
}
|
||||
|
||||
const toArray = (items) => {
|
||||
items = items || [];
|
||||
|
||||
if (!Array.isArray(items)) {
|
||||
return Array.from(items);
|
||||
}
|
||||
|
||||
return items;
|
||||
};
|
||||
|
||||
export function clipboardData(e, canUpload) {
|
||||
const clipboard =
|
||||
e.clipboardData ||
|
||||
e.originalEvent.clipboardData ||
|
||||
e.delegatedEvent.originalEvent.clipboardData;
|
||||
|
||||
const types = toArray(clipboard.types);
|
||||
let files = toArray(clipboard.files);
|
||||
|
||||
if (types.includes("Files") && files.length === 0) {
|
||||
// for IE
|
||||
files = toArray(clipboard.items).filter((i) => i.kind === "file");
|
||||
}
|
||||
|
||||
canUpload = files && canUpload && !types.includes("text/plain");
|
||||
const canUploadImage =
|
||||
canUpload && files.filter((f) => f.type.match("^image/"))[0];
|
||||
const canPasteHtml =
|
||||
Discourse.SiteSettings.enable_rich_text_paste &&
|
||||
types.includes("text/html") &&
|
||||
!canUploadImage;
|
||||
|
||||
return { clipboard, types, canUpload, canPasteHtml };
|
||||
}
|
79
assets/javascripts/wizard/models/field.js.es6
Normale Datei
79
assets/javascripts/wizard/models/field.js.es6
Normale Datei
|
@ -0,0 +1,79 @@
|
|||
import EmberObject from "@ember/object";
|
||||
import ValidState from "wizard/mixins/valid-state";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { translatedText } from "discourse/plugins/discourse-custom-wizard/wizard/lib/wizard-i18n";
|
||||
|
||||
const StandardFieldValidation = [
|
||||
"text",
|
||||
"number",
|
||||
"textarea",
|
||||
"dropdown",
|
||||
"tag",
|
||||
"image",
|
||||
"user_selector",
|
||||
"text_only",
|
||||
"composer",
|
||||
"category",
|
||||
"group",
|
||||
"date",
|
||||
"time",
|
||||
"date_time",
|
||||
];
|
||||
|
||||
export default EmberObject.extend(ValidState, {
|
||||
id: null,
|
||||
type: null,
|
||||
value: null,
|
||||
required: null,
|
||||
warning: null,
|
||||
|
||||
@discourseComputed("wizardId", "stepId", "id")
|
||||
i18nKey(wizardId, stepId, id) {
|
||||
return `${wizardId}.${stepId}.${id}`;
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey", "label")
|
||||
translatedLabel(i18nKey, label) {
|
||||
return translatedText(`${i18nKey}.label`, label);
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey", "placeholder")
|
||||
translatedPlaceholder(i18nKey, placeholder) {
|
||||
return translatedText(`${i18nKey}.placeholder`, placeholder);
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey", "description")
|
||||
translatedDescription(i18nKey, description) {
|
||||
return translatedText(`${i18nKey}.description`, description);
|
||||
},
|
||||
|
||||
check() {
|
||||
if (this.customCheck) {
|
||||
return this.customCheck();
|
||||
}
|
||||
|
||||
let valid = this.valid;
|
||||
|
||||
if (!this.required) {
|
||||
this.setValid(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
const val = this.get("value");
|
||||
const type = this.get("type");
|
||||
|
||||
if (type === "checkbox") {
|
||||
valid = val;
|
||||
} else if (type === "upload") {
|
||||
valid = val && val.id > 0;
|
||||
} else if (StandardFieldValidation.indexOf(type) > -1) {
|
||||
valid = val && val.toString().length > 0;
|
||||
} else if (type === "url") {
|
||||
valid = true;
|
||||
}
|
||||
|
||||
this.setValid(valid);
|
||||
|
||||
return valid;
|
||||
},
|
||||
});
|
|
@ -1,10 +1,11 @@
|
|||
import Site from "discourse/models/site";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
|
||||
export default Site.reopenClass({
|
||||
// There is no site data actually loaded by the CW yet. This placeholder is
|
||||
// needed by imported classes
|
||||
createCurrent() {
|
||||
const store = Discourse.__container__.lookup("service:store");
|
||||
const store = getOwner(this).lookup("service:store");
|
||||
return store.createRecord("site", {});
|
||||
},
|
||||
});
|
||||
|
|
111
assets/javascripts/wizard/models/step.js.es6
Normale Datei
111
assets/javascripts/wizard/models/step.js.es6
Normale Datei
|
@ -0,0 +1,111 @@
|
|||
import EmberObject from "@ember/object";
|
||||
import ValidState from "wizard/mixins/valid-state";
|
||||
import { ajax } from "wizard/lib/ajax";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
import { translatedText } from "discourse/plugins/discourse-custom-wizard/wizard/lib/wizard-i18n";
|
||||
import { later } from "@ember/runloop";
|
||||
|
||||
export default EmberObject.extend(ValidState, {
|
||||
id: null,
|
||||
|
||||
@discourseComputed("wizardId", "id")
|
||||
i18nKey(wizardId, stepId) {
|
||||
return `${wizardId}.${stepId}`;
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey", "title")
|
||||
translatedTitle(i18nKey, title) {
|
||||
return translatedText(`${i18nKey}.title`, title);
|
||||
},
|
||||
|
||||
@discourseComputed("i18nKey", "description")
|
||||
translatedDescription(i18nKey, description) {
|
||||
return translatedText(`${i18nKey}.description`, description);
|
||||
},
|
||||
|
||||
@discourseComputed("index")
|
||||
displayIndex: (index) => index + 1,
|
||||
|
||||
@discourseComputed("fields.[]")
|
||||
fieldsById(fields) {
|
||||
const lookup = {};
|
||||
fields.forEach((field) => (lookup[field.get("id")] = field));
|
||||
return lookup;
|
||||
},
|
||||
|
||||
validate() {
|
||||
let allValid = true;
|
||||
const result = { warnings: [] };
|
||||
|
||||
this.fields.forEach((field) => {
|
||||
allValid = allValid && field.check();
|
||||
const warning = field.get("warning");
|
||||
if (warning) {
|
||||
result.warnings.push(warning);
|
||||
}
|
||||
});
|
||||
|
||||
this.setValid(allValid);
|
||||
|
||||
return result;
|
||||
},
|
||||
|
||||
fieldError(id, description) {
|
||||
const field = this.fields.findBy("id", id);
|
||||
if (field) {
|
||||
field.setValid(false, description);
|
||||
}
|
||||
},
|
||||
|
||||
save() {
|
||||
const wizardId = this.get("wizardId");
|
||||
const fields = {};
|
||||
|
||||
this.get("fields").forEach((f) => {
|
||||
if (f.type !== "text_only") {
|
||||
fields[f.id] = f.value;
|
||||
}
|
||||
});
|
||||
|
||||
return ajax({
|
||||
url: `/w/${wizardId}/steps/${this.get("id")}`,
|
||||
type: "PUT",
|
||||
data: { fields },
|
||||
}).catch((response) => {
|
||||
if (response && response.responseJSON && response.responseJSON.errors) {
|
||||
let wizardErrors = [];
|
||||
response.responseJSON.errors.forEach((err) => {
|
||||
if (err.field === wizardId) {
|
||||
wizardErrors.push(err.description);
|
||||
} else if (err.field) {
|
||||
this.fieldError(err.field, err.description);
|
||||
} else if (err) {
|
||||
wizardErrors.push(err);
|
||||
}
|
||||
});
|
||||
if (wizardErrors.length) {
|
||||
this.handleWizardError(wizardErrors.join("\n"));
|
||||
}
|
||||
this.animateInvalidFields();
|
||||
throw response;
|
||||
}
|
||||
|
||||
if (response && response.responseText) {
|
||||
const responseText = response.responseText;
|
||||
const start = responseText.indexOf(">") + 1;
|
||||
const end = responseText.indexOf("plugins");
|
||||
const message = responseText.substring(start, end);
|
||||
this.handleWizardError(message);
|
||||
throw message;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
handleWizardError(message) {
|
||||
this.set("message", {
|
||||
state: "error",
|
||||
text: message,
|
||||
});
|
||||
later(() => this.set("message", null), 6000);
|
||||
},
|
||||
});
|
|
@ -1,9 +1,9 @@
|
|||
import { default as computed } from "discourse-common/utils/decorators";
|
||||
import getUrl from "discourse-common/lib/get-url";
|
||||
import WizardField from "wizard/models/wizard-field";
|
||||
import Field from "./field";
|
||||
import { ajax } from "wizard/lib/ajax";
|
||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||
import Step from "wizard/models/step";
|
||||
import Step from "./step";
|
||||
import EmberObject from "@ember/object";
|
||||
import Site from "./site";
|
||||
|
||||
|
@ -77,7 +77,7 @@ CustomWizard.reopenClass({
|
|||
stepObj.fields = stepObj.fields.map((f) => {
|
||||
f.wizardId = wizardJson.id;
|
||||
f.stepId = stepObj.id;
|
||||
return WizardField.create(f);
|
||||
return Field.create(f);
|
||||
});
|
||||
|
||||
return stepObj;
|
||||
|
@ -113,8 +113,7 @@ CustomWizard.reopenClass({
|
|||
}
|
||||
});
|
||||
|
||||
Site.currentProp("categoriesList", categories);
|
||||
Site.currentProp("sortedCategories", categories);
|
||||
Site.currentProp("categories", categories);
|
||||
Site.currentProp("listByActivity", categories);
|
||||
Site.currentProp("categoriesById", categoriesById);
|
||||
Site.currentProp(
|
17
assets/javascripts/wizard/router.js.es6
Normale Datei
17
assets/javascripts/wizard/router.js.es6
Normale Datei
|
@ -0,0 +1,17 @@
|
|||
import EmberRouter from "@ember/routing/router";
|
||||
import getUrl from "discourse-common/lib/get-url";
|
||||
import { isTesting } from "discourse-common/config/environment";
|
||||
|
||||
const Router = EmberRouter.extend({
|
||||
rootURL: isTesting() ? getUrl("/") : getUrl("/w/"),
|
||||
location: isTesting() ? "none" : "history",
|
||||
});
|
||||
|
||||
Router.map(function () {
|
||||
this.route("wizard", { path: "/:wizard_id" }, function () {
|
||||
this.route("steps", { path: "/steps", resetNamespace: true });
|
||||
this.route("step", { path: "/steps/:step_id", resetNamespace: true });
|
||||
});
|
||||
});
|
||||
|
||||
export default Router;
|
3
assets/javascripts/wizard/routes/application.js.es6
Normale Datei
3
assets/javascripts/wizard/routes/application.js.es6
Normale Datei
|
@ -0,0 +1,3 @@
|
|||
import Route from "@ember/routing/route";
|
||||
|
||||
export default Route.extend();
|
|
@ -1,35 +0,0 @@
|
|||
import { getCachedWizard } from "../models/custom";
|
||||
|
||||
export default Ember.Route.extend({
|
||||
beforeModel() {
|
||||
const wizard = getCachedWizard();
|
||||
if (wizard && wizard.permitted && !wizard.completed && wizard.start) {
|
||||
this.replaceWith("custom.step", wizard.start);
|
||||
}
|
||||
},
|
||||
|
||||
model() {
|
||||
return getCachedWizard();
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
if (model && model.id) {
|
||||
const completed = model.get("completed");
|
||||
const permitted = model.get("permitted");
|
||||
const wizardId = model.get("id");
|
||||
const user = model.get("user");
|
||||
const name = model.get("name");
|
||||
|
||||
controller.setProperties({
|
||||
requiresLogin: !user,
|
||||
user,
|
||||
name,
|
||||
completed,
|
||||
notPermitted: !permitted,
|
||||
wizardId,
|
||||
});
|
||||
} else {
|
||||
controller.set("noWizard", true);
|
||||
}
|
||||
},
|
||||
});
|
|
@ -1,5 +0,0 @@
|
|||
export default Ember.Route.extend({
|
||||
redirect() {
|
||||
this.transitionTo("custom.index");
|
||||
},
|
||||
});
|
9
assets/javascripts/wizard/routes/index.js.es6
Normale Datei
9
assets/javascripts/wizard/routes/index.js.es6
Normale Datei
|
@ -0,0 +1,9 @@
|
|||
import Route from "@ember/routing/route";
|
||||
|
||||
export default Route.extend({
|
||||
beforeModel(transition) {
|
||||
if (transition.intent.params) {
|
||||
this.transitionTo("wizard");
|
||||
}
|
||||
},
|
||||
});
|
|
@ -1,7 +1,8 @@
|
|||
import WizardI18n from "../lib/wizard-i18n";
|
||||
import { getCachedWizard } from "../models/custom";
|
||||
import { getCachedWizard } from "../models/wizard";
|
||||
import Route from "@ember/routing/route";
|
||||
|
||||
export default Ember.Route.extend({
|
||||
export default Route.extend({
|
||||
beforeModel() {
|
||||
this.set("wizard", getCachedWizard());
|
||||
},
|
||||
|
@ -19,11 +20,15 @@ export default Ember.Route.extend({
|
|||
|
||||
afterModel(model) {
|
||||
if (model.completed) {
|
||||
return this.transitionTo("index");
|
||||
return this.transitionTo("wizard.index");
|
||||
}
|
||||
return model.set("wizardId", this.wizard.id);
|
||||
},
|
||||
|
||||
renderTemplate() {
|
||||
this.render("wizard/templates/step");
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
let props = {
|
||||
step: model,
|
7
assets/javascripts/wizard/routes/steps.js.es6
Normale Datei
7
assets/javascripts/wizard/routes/steps.js.es6
Normale Datei
|
@ -0,0 +1,7 @@
|
|||
import Route from "@ember/routing/route";
|
||||
|
||||
export default Route.extend({
|
||||
redirect() {
|
||||
this.transitionTo("wizard.index");
|
||||
},
|
||||
});
|
49
assets/javascripts/wizard/routes/wizard-index.js.es6
Normale Datei
49
assets/javascripts/wizard/routes/wizard-index.js.es6
Normale Datei
|
@ -0,0 +1,49 @@
|
|||
import { getCachedWizard } from "../models/wizard";
|
||||
import Route from "@ember/routing/route";
|
||||
|
||||
export default Route.extend({
|
||||
beforeModel() {
|
||||
const wizard = getCachedWizard();
|
||||
if (
|
||||
wizard &&
|
||||
wizard.user &&
|
||||
wizard.permitted &&
|
||||
!wizard.completed &&
|
||||
wizard.start
|
||||
) {
|
||||
this.replaceWith("step", wizard.start);
|
||||
}
|
||||
},
|
||||
|
||||
model() {
|
||||
return getCachedWizard();
|
||||
},
|
||||
|
||||
renderTemplate() {
|
||||
this.render("wizard/templates/wizard-index");
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
if (model && model.id) {
|
||||
const completed = model.get("completed");
|
||||
const permitted = model.get("permitted");
|
||||
const wizardId = model.get("id");
|
||||
const user = model.get("user");
|
||||
const name = model.get("name");
|
||||
const requiresLogin = !user;
|
||||
const notPermitted = !permitted;
|
||||
|
||||
const props = {
|
||||
requiresLogin,
|
||||
user,
|
||||
name,
|
||||
completed,
|
||||
notPermitted,
|
||||
wizardId,
|
||||
};
|
||||
controller.setProperties(props);
|
||||
} else {
|
||||
controller.set("noWizard", true);
|
||||
}
|
||||
},
|
||||
});
|
|
@ -1,32 +1,20 @@
|
|||
/* eslint no-undef: 0*/
|
||||
|
||||
import { findCustomWizard, updateCachedWizard } from "../models/custom";
|
||||
import { ajax } from "wizard/lib/ajax";
|
||||
import { findCustomWizard, updateCachedWizard } from "../models/wizard";
|
||||
import WizardI18n from "../lib/wizard-i18n";
|
||||
import Route from "@ember/routing/route";
|
||||
import { scheduleOnce } from "@ember/runloop";
|
||||
import { getOwner } from "discourse-common/lib/get-owner";
|
||||
|
||||
export default Ember.Route.extend({
|
||||
export default Route.extend({
|
||||
beforeModel(transition) {
|
||||
if (transition.intent.queryParams) {
|
||||
this.set("queryParams", transition.intent.queryParams);
|
||||
}
|
||||
},
|
||||
|
||||
model(params) {
|
||||
return findCustomWizard(params.wizard_id, this.get("queryParams"));
|
||||
},
|
||||
|
||||
renderTemplate() {
|
||||
this.render("custom");
|
||||
const wizardModel = this.modelFor("custom");
|
||||
const stepModel = this.modelFor("custom.step");
|
||||
|
||||
if (
|
||||
wizardModel.resume_on_revisit &&
|
||||
wizardModel.submission_last_updated_at &&
|
||||
stepModel.index > 0
|
||||
) {
|
||||
this.showDialog(wizardModel);
|
||||
}
|
||||
},
|
||||
|
||||
showDialog(wizardModel) {
|
||||
const title = WizardI18n("wizard.incomplete_submission.title", {
|
||||
date: moment(wizardModel.submission_last_updated_at).format(
|
||||
|
@ -57,28 +45,36 @@ export default Ember.Route.extend({
|
|||
|
||||
afterModel(model) {
|
||||
updateCachedWizard(model);
|
||||
},
|
||||
|
||||
return ajax({
|
||||
url: `/site/settings`,
|
||||
type: "GET",
|
||||
}).then((result) => {
|
||||
$.extend(Wizard.SiteSettings, result);
|
||||
});
|
||||
renderTemplate() {
|
||||
this.render("wizard/templates/wizard");
|
||||
},
|
||||
|
||||
setupController(controller, model) {
|
||||
const background = model ? model.get("background") : "AliceBlue";
|
||||
Ember.run.scheduleOnce("afterRender", this, function () {
|
||||
$("body.custom-wizard").css("background", background);
|
||||
const background = model ? model.get("background") : "";
|
||||
|
||||
scheduleOnce("afterRender", this, function () {
|
||||
$("body").css("background", background);
|
||||
|
||||
if (model && model.id) {
|
||||
$("#custom-wizard-main").addClass(model.id.dasherize());
|
||||
$(getOwner(this).rootElement).addClass(model.id.dasherize());
|
||||
}
|
||||
});
|
||||
|
||||
controller.setProperties({
|
||||
customWizard: true,
|
||||
logoUrl: Wizard.SiteSettings.logo_small,
|
||||
logoUrl: this.siteSettings.logo_small,
|
||||
reset: null,
|
||||
});
|
||||
|
||||
const stepModel = this.modelFor("step");
|
||||
if (
|
||||
model.resume_on_revisit &&
|
||||
model.submission_last_updated_at &&
|
||||
stepModel.index > 0
|
||||
) {
|
||||
this.showDialog(model);
|
||||
}
|
||||
},
|
||||
});
|
|
@ -1,7 +1,7 @@
|
|||
{{d-editor
|
||||
tabindex=field.tabindex
|
||||
value=composer.reply
|
||||
placeholderTranslated=replyPlaceholder
|
||||
placeholderOverride=replyPlaceholder
|
||||
previewUpdated=(action "previewUpdated")
|
||||
markdownOptions=markdownOptions
|
||||
extraButtons=(action "extraButtons")
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
value=field.value
|
||||
content=field.content
|
||||
tabindex=field.tabindex
|
||||
onChange=(action "onChangeValue")
|
||||
options=(hash
|
||||
none="select_kit.default_header_text"
|
||||
)}}
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
{{#if noWizard}}
|
||||
{{wizard-no-access text=(wizard-i18n "wizard.none") wizardId=wizardId}}
|
||||
{{else}}
|
||||
{{#if requiresLogin}}
|
||||
{{wizard-no-access text=(wizard-i18n "wizard.requires_login") wizardId=wizardId}}
|
||||
{{else}}
|
||||
{{#if notPermitted}}
|
||||
{{wizard-no-access text=(wizard-i18n "wizard.not_permitted") wizardId=wizardId}}
|
||||
{{else}}
|
||||
{{#if completed}}
|
||||
{{wizard-no-access text=(wizard-i18n "wizard.completed") wizardId=wizardId}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{/if}}
|
1
assets/javascripts/wizard/templates/index.hbs
Normale Datei
1
assets/javascripts/wizard/templates/index.hbs
Normale Datei
|
@ -0,0 +1 @@
|
|||
{{outlet}}
|
|
@ -13,8 +13,7 @@
|
|||
{{#if step.permitted}}
|
||||
{{wizard-step step=step
|
||||
wizard=wizard
|
||||
goNext="goNext"
|
||||
goNext=(action "goNext")
|
||||
goBack=(action "goBack")
|
||||
finished="finished"
|
||||
showMessage="showMessage"}}
|
||||
showMessage=(action "showMessage")}}
|
||||
{{/if}}
|
3
assets/javascripts/wizard/templates/wizard-index.hbs
Normale Datei
3
assets/javascripts/wizard/templates/wizard-index.hbs
Normale Datei
|
@ -0,0 +1,3 @@
|
|||
{{#if noAccess}}
|
||||
{{wizard-no-access text=(wizard-i18n noAccessI18nKey) wizardId=wizardId reason=noAccessReason}}
|
||||
{{/if}}
|
|
@ -1,7 +1,3 @@
|
|||
{{#if showCanvas}}
|
||||
{{wizard-canvas}}
|
||||
{{/if}}
|
||||
|
||||
<div class="wizard-column">
|
||||
<div class="wizard-column-contents">
|
||||
{{outlet}}
|
173
assets/javascripts/wizard/tests/acceptance/field-test.js.es6
Normale Datei
173
assets/javascripts/wizard/tests/acceptance/field-test.js.es6
Normale Datei
|
@ -0,0 +1,173 @@
|
|||
import { click, fillIn, triggerKeyEvent, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { exists } from "../helpers/test";
|
||||
import acceptance, {
|
||||
count,
|
||||
query,
|
||||
server,
|
||||
visible,
|
||||
} from "../helpers/acceptance";
|
||||
import { allFieldsWizard, getWizard } from "../helpers/wizard";
|
||||
import tagsJson from "../fixtures/tags";
|
||||
import usersJson from "../fixtures/users";
|
||||
import { response } from "../pretender";
|
||||
|
||||
acceptance("Field | Fields", [getWizard(allFieldsWizard)], function () {
|
||||
test("Text", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(exists(".wizard-field.text-field input.wizard-focusable"));
|
||||
});
|
||||
|
||||
test("Textarea", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(
|
||||
visible(".wizard-field.textarea-field textarea.wizard-focusable")
|
||||
);
|
||||
});
|
||||
|
||||
test("Composer", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(
|
||||
visible(".wizard-field.composer-field .wizard-field-composer textarea")
|
||||
);
|
||||
assert.strictEqual(
|
||||
count(".wizard-field.composer-field .d-editor-button-bar button"),
|
||||
8
|
||||
);
|
||||
assert.ok(visible(".wizard-btn.toggle-preview"));
|
||||
|
||||
await fillIn(
|
||||
".wizard-field.composer-field .wizard-field-composer textarea",
|
||||
"Input in composer"
|
||||
);
|
||||
await click(".wizard-btn.toggle-preview");
|
||||
assert.strictEqual(
|
||||
query(
|
||||
".wizard-field.composer-field .wizard-field-composer .d-editor-preview-wrapper p"
|
||||
).textContent.trim(),
|
||||
"Input in composer"
|
||||
);
|
||||
});
|
||||
|
||||
test("Text Only", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-field.text-only-field label.field-label"));
|
||||
});
|
||||
|
||||
test("Date", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-field.date-field input.date-picker"));
|
||||
await click(".wizard-field.date-field input.date-picker");
|
||||
assert.ok(visible(".wizard-field.date-field .pika-single"));
|
||||
});
|
||||
|
||||
test("Time", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-field.time-field .d-time-input .select-kit"));
|
||||
await click(
|
||||
".wizard-field.time-field .d-time-input .select-kit .select-kit-header"
|
||||
);
|
||||
assert.ok(visible(".wizard-field.time-field .select-kit-collection"));
|
||||
});
|
||||
|
||||
test("Date Time", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(
|
||||
visible(".wizard-field.date-time-field .d-date-time-input .select-kit")
|
||||
);
|
||||
await click(
|
||||
".wizard-field.date-time-field .d-date-input input.date-picker"
|
||||
);
|
||||
assert.ok(
|
||||
visible(".wizard-field.date-time-field .d-date-input .pika-single")
|
||||
);
|
||||
await click(
|
||||
".wizard-field.date-time-field .d-time-input .select-kit .select-kit-header"
|
||||
);
|
||||
assert.ok(visible(".wizard-field.date-time-field .select-kit-collection"));
|
||||
});
|
||||
|
||||
test("Number", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-field.number-field input[type='number']"));
|
||||
});
|
||||
|
||||
test("Checkbox", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-field.checkbox-field input[type='checkbox']"));
|
||||
});
|
||||
|
||||
test("Url", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-field.url-field input[type='text']"));
|
||||
});
|
||||
|
||||
test("Upload", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(
|
||||
visible(".wizard-field.upload-field label.wizard-btn-upload-file")
|
||||
);
|
||||
assert.ok(exists(".wizard-field.upload-field input.hidden-upload-field"));
|
||||
});
|
||||
|
||||
test("Dropdown", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-field.dropdown-field .single-select-header"));
|
||||
await click(".wizard-field.dropdown-field .select-kit-header");
|
||||
assert.strictEqual(
|
||||
count(".wizard-field.dropdown-field .select-kit-collection li"),
|
||||
3
|
||||
);
|
||||
});
|
||||
|
||||
test("Tag", async function (assert) {
|
||||
server.get("/tags/filter/search", () =>
|
||||
response(200, { results: tagsJson["tags"] })
|
||||
);
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-field.tag-field .multi-select-header"));
|
||||
await click(".wizard-field.tag-field .select-kit-header");
|
||||
assert.strictEqual(
|
||||
count(".wizard-field.tag-field .select-kit-collection li"),
|
||||
2
|
||||
);
|
||||
});
|
||||
|
||||
test("Category", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-field.category-field .multi-select-header"));
|
||||
await click(".wizard-field.category-field .select-kit-header");
|
||||
assert.strictEqual(
|
||||
count(".wizard-field.category-field .select-kit-collection li"),
|
||||
5
|
||||
);
|
||||
});
|
||||
|
||||
test("Group", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-field.group-field .single-select-header"));
|
||||
await click(".wizard-field.group-field .select-kit-header");
|
||||
assert.strictEqual(
|
||||
count(".wizard-field.group-field .select-kit-collection li"),
|
||||
10
|
||||
);
|
||||
});
|
||||
|
||||
test("User", async function (assert) {
|
||||
server.get("/u/search/users", () => response(200, usersJson));
|
||||
|
||||
await visit("/wizard");
|
||||
await fillIn(
|
||||
".wizard-field.user-selector-field input.ember-text-field",
|
||||
"a"
|
||||
);
|
||||
await triggerKeyEvent(
|
||||
".wizard-field.user-selector-field input.ember-text-field",
|
||||
"keyup",
|
||||
"a".charCodeAt(0)
|
||||
);
|
||||
|
||||
assert.ok(visible(".wizard-field.user-selector-field .ac-wrap"));
|
||||
// TODO: add assertion for ac results. autocomplete does not appear in time.
|
||||
});
|
||||
});
|
41
assets/javascripts/wizard/tests/acceptance/step-test.js.es6
Normale Datei
41
assets/javascripts/wizard/tests/acceptance/step-test.js.es6
Normale Datei
|
@ -0,0 +1,41 @@
|
|||
import { click, visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { exists } from "../helpers/test";
|
||||
import acceptance, { count, query, visible } from "../helpers/acceptance";
|
||||
import { getWizard, stepNotPermitted, wizard } from "../helpers/wizard";
|
||||
import { saveStep, update } from "../helpers/step";
|
||||
|
||||
acceptance("Step | Not permitted", [getWizard(stepNotPermitted)], function () {
|
||||
test("Shows not permitted message", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(exists(".step-message.not-permitted"));
|
||||
});
|
||||
});
|
||||
|
||||
acceptance("Step | Step", [getWizard(wizard), saveStep(update)], function () {
|
||||
test("Renders the step", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.strictEqual(
|
||||
query(".wizard-step-title p").textContent.trim(),
|
||||
"Text"
|
||||
);
|
||||
assert.strictEqual(
|
||||
query(".wizard-step-description p").textContent.trim(),
|
||||
"Text inputs!"
|
||||
);
|
||||
assert.strictEqual(
|
||||
query(".wizard-step-description p").textContent.trim(),
|
||||
"Text inputs!"
|
||||
);
|
||||
assert.strictEqual(count(".wizard-step-form .wizard-field"), 6);
|
||||
assert.ok(visible(".wizard-step-footer .wizard-progress"), true);
|
||||
assert.ok(visible(".wizard-step-footer .wizard-buttons"), true);
|
||||
});
|
||||
|
||||
test("Goes to the next step", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-step.step_1"), true);
|
||||
await click(".wizard-btn.next");
|
||||
assert.ok(visible(".wizard-step.step_2"), true);
|
||||
});
|
||||
});
|
73
assets/javascripts/wizard/tests/acceptance/wizard-test.js.es6
Normale Datei
73
assets/javascripts/wizard/tests/acceptance/wizard-test.js.es6
Normale Datei
|
@ -0,0 +1,73 @@
|
|||
import { visit } from "@ember/test-helpers";
|
||||
import { test } from "qunit";
|
||||
import { exists } from "../helpers/test";
|
||||
import acceptance, { count, query, visible } from "../helpers/acceptance";
|
||||
import {
|
||||
getWizard,
|
||||
wizard,
|
||||
wizardCompleted,
|
||||
wizardNoUser,
|
||||
wizardNotPermitted,
|
||||
} from "../helpers/wizard";
|
||||
|
||||
acceptance("Wizard | Not logged in", [getWizard(wizardNoUser)], function () {
|
||||
test("Wizard no access requires login", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(exists(".wizard-no-access.requires-login"));
|
||||
});
|
||||
});
|
||||
|
||||
acceptance(
|
||||
"Wizard | Not permitted",
|
||||
[getWizard(wizardNotPermitted)],
|
||||
function () {
|
||||
test("Wizard no access not permitted", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(exists(".wizard-no-access.not-permitted"));
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
acceptance("Wizard | Completed", [getWizard(wizardCompleted)], function () {
|
||||
test("Wizard no access completed", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(exists(".wizard-no-access.completed"));
|
||||
});
|
||||
});
|
||||
|
||||
acceptance("Wizard | Wizard", [getWizard(wizard)], function () {
|
||||
test("Starts", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(query(".wizard-column"), true);
|
||||
});
|
||||
|
||||
test("Applies the body background color", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok($("body")[0].style.background);
|
||||
});
|
||||
|
||||
test("Renders the wizard form", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.ok(visible(".wizard-column-contents .wizard-step"), true);
|
||||
assert.ok(visible(".wizard-footer img"), true);
|
||||
});
|
||||
|
||||
test("Renders the first step", async function (assert) {
|
||||
await visit("/wizard");
|
||||
assert.strictEqual(
|
||||
query(".wizard-step-title p").textContent.trim(),
|
||||
"Text"
|
||||
);
|
||||
assert.strictEqual(
|
||||
query(".wizard-step-description p").textContent.trim(),
|
||||
"Text inputs!"
|
||||
);
|
||||
assert.strictEqual(
|
||||
query(".wizard-step-description p").textContent.trim(),
|
||||
"Text inputs!"
|
||||
);
|
||||
assert.strictEqual(count(".wizard-step-form .wizard-field"), 6);
|
||||
assert.ok(visible(".wizard-step-footer .wizard-progress"), true);
|
||||
assert.ok(visible(".wizard-step-footer .wizard-buttons"), true);
|
||||
});
|
||||
});
|
17
assets/javascripts/wizard/tests/bootstrap.js.es6
Normale Datei
17
assets/javascripts/wizard/tests/bootstrap.js.es6
Normale Datei
|
@ -0,0 +1,17 @@
|
|||
// discourse-skip-module
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
document.body.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
`
|
||||
<div id="ember-testing-container"><div id="ember-testing"></div></div>
|
||||
<style>#ember-testing-container { position: absolute; background: white; bottom: 0; right: 0; width: 640px; height: 384px; overflow: auto; z-index: 9999; border: 1px solid #ccc; } #ember-testing { zoom: 50%; }</style>
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
Object.keys(requirejs.entries).forEach(function (entry) {
|
||||
if (/\-test/.test(entry)) {
|
||||
requirejs(entry);
|
||||
}
|
||||
});
|
221
assets/javascripts/wizard/tests/fixtures/categories.js.es6
gevendort
Normale Datei
221
assets/javascripts/wizard/tests/fixtures/categories.js.es6
gevendort
Normale Datei
|
@ -0,0 +1,221 @@
|
|||
export default {
|
||||
categories: [
|
||||
{
|
||||
id: 1,
|
||||
name: "Uncategorized",
|
||||
color: "0088CC",
|
||||
text_color: "FFFFFF",
|
||||
slug: "uncategorized",
|
||||
topic_count: 1,
|
||||
post_count: 1,
|
||||
position: 0,
|
||||
description:
|
||||
"Topics that don't need a category, or don't fit into any other existing category.",
|
||||
description_text:
|
||||
"Topics that don't need a category, or don't fit into any other existing category.",
|
||||
description_excerpt:
|
||||
"Topics that don't need a category, or don't fit into any other existing category.",
|
||||
topic_url: "/t/",
|
||||
read_restricted: false,
|
||||
permission: 1,
|
||||
notification_level: 0,
|
||||
topic_template: null,
|
||||
has_children: false,
|
||||
sort_order: null,
|
||||
sort_ascending: null,
|
||||
show_subcategory_list: false,
|
||||
num_featured_topics: 3,
|
||||
default_view: null,
|
||||
subcategory_list_style: "rows_with_featured_topics",
|
||||
default_top_period: "all",
|
||||
default_list_filter: "all",
|
||||
minimum_required_tags: 0,
|
||||
navigate_to_first_post_after_read: false,
|
||||
custom_fields: {
|
||||
create_topic_wizard: null,
|
||||
},
|
||||
allowed_tags: [],
|
||||
allowed_tag_groups: [],
|
||||
allow_global_tags: false,
|
||||
min_tags_from_required_group: 1,
|
||||
required_tag_group_name: null,
|
||||
read_only_banner: null,
|
||||
uploaded_logo: null,
|
||||
uploaded_background: null,
|
||||
can_edit: true,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Site Feedback",
|
||||
color: "808281",
|
||||
text_color: "FFFFFF",
|
||||
slug: "site-feedback",
|
||||
topic_count: 20,
|
||||
post_count: 21,
|
||||
position: 1,
|
||||
description:
|
||||
"<p>Discussion about this site, its organization, how it works, and how we can improve it.</p>",
|
||||
description_text:
|
||||
"Discussion about this site, its organization, how it works, and how we can improve it.",
|
||||
description_excerpt:
|
||||
"Discussion about this site, its organization, how it works, and how we can improve it.",
|
||||
topic_url: "/t/about-the-site-feedback-category/1",
|
||||
read_restricted: false,
|
||||
permission: 1,
|
||||
notification_level: 0,
|
||||
topic_template: null,
|
||||
has_children: false,
|
||||
sort_order: null,
|
||||
sort_ascending: null,
|
||||
show_subcategory_list: false,
|
||||
num_featured_topics: 3,
|
||||
default_view: null,
|
||||
subcategory_list_style: "rows_with_featured_topics",
|
||||
default_top_period: "all",
|
||||
default_list_filter: "all",
|
||||
minimum_required_tags: 0,
|
||||
navigate_to_first_post_after_read: false,
|
||||
custom_fields: {
|
||||
create_topic_wizard: null,
|
||||
},
|
||||
allowed_tags: [],
|
||||
allowed_tag_groups: [],
|
||||
allow_global_tags: false,
|
||||
min_tags_from_required_group: 1,
|
||||
required_tag_group_name: null,
|
||||
read_only_banner: null,
|
||||
uploaded_logo: null,
|
||||
uploaded_background: null,
|
||||
can_edit: true,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Staff",
|
||||
color: "E45735",
|
||||
text_color: "FFFFFF",
|
||||
slug: "staff",
|
||||
topic_count: 4,
|
||||
post_count: 7,
|
||||
position: 2,
|
||||
description:
|
||||
"<p>Private category for staff discussions. Topics are only visible to admins and moderators.</p>",
|
||||
description_text:
|
||||
"Private category for staff discussions. Topics are only visible to admins and moderators.",
|
||||
description_excerpt:
|
||||
"Private category for staff discussions. Topics are only visible to admins and moderators.",
|
||||
topic_url: "/t/about-the-staff-category/2",
|
||||
read_restricted: true,
|
||||
permission: 1,
|
||||
notification_level: 0,
|
||||
topic_template: null,
|
||||
has_children: false,
|
||||
sort_order: null,
|
||||
sort_ascending: null,
|
||||
show_subcategory_list: false,
|
||||
num_featured_topics: 3,
|
||||
default_view: null,
|
||||
subcategory_list_style: "rows_with_featured_topics",
|
||||
default_top_period: "all",
|
||||
default_list_filter: "all",
|
||||
minimum_required_tags: 0,
|
||||
navigate_to_first_post_after_read: false,
|
||||
custom_fields: {
|
||||
create_topic_wizard: null,
|
||||
},
|
||||
allowed_tags: [],
|
||||
allowed_tag_groups: [],
|
||||
allow_global_tags: false,
|
||||
min_tags_from_required_group: 1,
|
||||
required_tag_group_name: null,
|
||||
read_only_banner: null,
|
||||
uploaded_logo: null,
|
||||
uploaded_background: null,
|
||||
can_edit: true,
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "Lounge",
|
||||
color: "A461EF",
|
||||
text_color: "652D90",
|
||||
slug: "lounge",
|
||||
topic_count: 1,
|
||||
post_count: 1,
|
||||
position: 3,
|
||||
description:
|
||||
"<p>A category exclusive to members with trust level 3 and higher.</p>",
|
||||
description_text:
|
||||
"A category exclusive to members with trust level 3 and higher.",
|
||||
description_excerpt:
|
||||
"A category exclusive to members with trust level 3 and higher.",
|
||||
topic_url: "/t/about-the-lounge-category/3",
|
||||
read_restricted: true,
|
||||
permission: 1,
|
||||
notification_level: 0,
|
||||
topic_template: null,
|
||||
has_children: false,
|
||||
sort_order: null,
|
||||
sort_ascending: null,
|
||||
show_subcategory_list: false,
|
||||
num_featured_topics: 3,
|
||||
default_view: null,
|
||||
subcategory_list_style: "rows_with_featured_topics",
|
||||
default_top_period: "all",
|
||||
default_list_filter: "all",
|
||||
minimum_required_tags: 0,
|
||||
navigate_to_first_post_after_read: false,
|
||||
custom_fields: {
|
||||
create_topic_wizard: null,
|
||||
},
|
||||
allowed_tags: [],
|
||||
allowed_tag_groups: [],
|
||||
allow_global_tags: false,
|
||||
min_tags_from_required_group: 1,
|
||||
required_tag_group_name: null,
|
||||
read_only_banner: null,
|
||||
uploaded_logo: null,
|
||||
uploaded_background: null,
|
||||
can_edit: true,
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
name: "Custom Categories",
|
||||
color: "0088CC",
|
||||
text_color: "FFFFFF",
|
||||
slug: "custom-category",
|
||||
topic_count: 0,
|
||||
post_count: 0,
|
||||
position: 10,
|
||||
description: "Description of custom category",
|
||||
description_text: "Description of custom category",
|
||||
description_excerpt: "Description of custom category",
|
||||
topic_url: "/t/about-the-custom-category/5",
|
||||
read_restricted: false,
|
||||
permission: 1,
|
||||
notification_level: 0,
|
||||
topic_template: null,
|
||||
has_children: false,
|
||||
sort_order: null,
|
||||
sort_ascending: null,
|
||||
show_subcategory_list: false,
|
||||
num_featured_topics: 3,
|
||||
default_view: null,
|
||||
subcategory_list_style: "rows_with_featured_topics",
|
||||
default_top_period: "all",
|
||||
default_list_filter: "all",
|
||||
minimum_required_tags: 0,
|
||||
navigate_to_first_post_after_read: false,
|
||||
custom_fields: {
|
||||
create_topic_wizard: null,
|
||||
},
|
||||
allowed_tags: [],
|
||||
allowed_tag_groups: [],
|
||||
allow_global_tags: false,
|
||||
min_tags_from_required_group: 1,
|
||||
required_tag_group_name: null,
|
||||
read_only_banner: null,
|
||||
uploaded_logo: null,
|
||||
uploaded_background: null,
|
||||
can_edit: true,
|
||||
},
|
||||
],
|
||||
};
|
313
assets/javascripts/wizard/tests/fixtures/groups.js.es6
gevendort
Normale Datei
313
assets/javascripts/wizard/tests/fixtures/groups.js.es6
gevendort
Normale Datei
|
@ -0,0 +1,313 @@
|
|||
export default {
|
||||
groups: [
|
||||
{
|
||||
id: 1,
|
||||
automatic: true,
|
||||
name: "admins",
|
||||
display_name: "admins",
|
||||
user_count: 1,
|
||||
mentionable_level: 0,
|
||||
messageable_level: 0,
|
||||
visibility_level: 1,
|
||||
primary_group: false,
|
||||
title: null,
|
||||
grant_trust_level: null,
|
||||
incoming_email: null,
|
||||
has_messages: false,
|
||||
flair_url: null,
|
||||
flair_bg_color: null,
|
||||
flair_color: null,
|
||||
bio_raw: null,
|
||||
bio_cooked: null,
|
||||
bio_excerpt: null,
|
||||
public_admission: false,
|
||||
public_exit: false,
|
||||
allow_membership_requests: false,
|
||||
full_name: null,
|
||||
default_notification_level: 3,
|
||||
membership_request_template: null,
|
||||
members_visibility_level: 0,
|
||||
can_see_members: true,
|
||||
can_admin_group: true,
|
||||
publish_read_state: false,
|
||||
},
|
||||
{
|
||||
id: 0,
|
||||
automatic: true,
|
||||
name: "everyone",
|
||||
display_name: "everyone",
|
||||
user_count: 0,
|
||||
mentionable_level: 0,
|
||||
messageable_level: 0,
|
||||
visibility_level: 3,
|
||||
primary_group: false,
|
||||
title: null,
|
||||
grant_trust_level: null,
|
||||
incoming_email: null,
|
||||
has_messages: false,
|
||||
flair_url: null,
|
||||
flair_bg_color: null,
|
||||
flair_color: null,
|
||||
bio_raw: null,
|
||||
bio_cooked: null,
|
||||
bio_excerpt: null,
|
||||
public_admission: false,
|
||||
public_exit: false,
|
||||
allow_membership_requests: false,
|
||||
full_name: null,
|
||||
default_notification_level: 3,
|
||||
membership_request_template: null,
|
||||
members_visibility_level: 0,
|
||||
can_see_members: true,
|
||||
can_admin_group: true,
|
||||
publish_read_state: false,
|
||||
},
|
||||
{
|
||||
id: 15,
|
||||
automatic: false,
|
||||
name: "custom_group",
|
||||
user_count: 1,
|
||||
mentionable_level: 1,
|
||||
messageable_level: 2,
|
||||
visibility_level: 3,
|
||||
primary_group: false,
|
||||
title: "Custom Group",
|
||||
grant_trust_level: 3,
|
||||
incoming_email: null,
|
||||
has_messages: false,
|
||||
flair_url: null,
|
||||
flair_bg_color: null,
|
||||
flair_color: null,
|
||||
bio_raw: null,
|
||||
bio_cooked: null,
|
||||
bio_excerpt: null,
|
||||
public_admission: false,
|
||||
public_exit: false,
|
||||
allow_membership_requests: false,
|
||||
full_name: "I am prefilled",
|
||||
default_notification_level: 3,
|
||||
membership_request_template: null,
|
||||
members_visibility_level: 99,
|
||||
can_see_members: true,
|
||||
can_admin_group: true,
|
||||
publish_read_state: false,
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
automatic: true,
|
||||
name: "moderators",
|
||||
display_name: "moderators",
|
||||
user_count: 0,
|
||||
mentionable_level: 0,
|
||||
messageable_level: 99,
|
||||
visibility_level: 1,
|
||||
primary_group: false,
|
||||
title: null,
|
||||
grant_trust_level: null,
|
||||
incoming_email: null,
|
||||
has_messages: false,
|
||||
flair_url: null,
|
||||
flair_bg_color: null,
|
||||
flair_color: null,
|
||||
bio_raw: null,
|
||||
bio_cooked: null,
|
||||
bio_excerpt: null,
|
||||
public_admission: false,
|
||||
public_exit: false,
|
||||
allow_membership_requests: false,
|
||||
full_name: null,
|
||||
default_notification_level: 2,
|
||||
membership_request_template: null,
|
||||
members_visibility_level: 0,
|
||||
can_see_members: true,
|
||||
can_admin_group: true,
|
||||
publish_read_state: false,
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
automatic: true,
|
||||
name: "staff",
|
||||
display_name: "staff",
|
||||
user_count: 1,
|
||||
mentionable_level: 0,
|
||||
messageable_level: 0,
|
||||
visibility_level: 1,
|
||||
primary_group: false,
|
||||
title: null,
|
||||
grant_trust_level: null,
|
||||
incoming_email: null,
|
||||
has_messages: false,
|
||||
flair_url: null,
|
||||
flair_bg_color: null,
|
||||
flair_color: null,
|
||||
bio_raw: null,
|
||||
bio_cooked: null,
|
||||
bio_excerpt: null,
|
||||
public_admission: false,
|
||||
public_exit: false,
|
||||
allow_membership_requests: false,
|
||||
full_name: null,
|
||||
default_notification_level: 3,
|
||||
membership_request_template: null,
|
||||
members_visibility_level: 0,
|
||||
can_see_members: true,
|
||||
can_admin_group: true,
|
||||
publish_read_state: false,
|
||||
},
|
||||
{
|
||||
id: 10,
|
||||
automatic: true,
|
||||
name: "trust_level_0",
|
||||
display_name: "trust_level_0",
|
||||
user_count: 2,
|
||||
mentionable_level: 0,
|
||||
messageable_level: 0,
|
||||
visibility_level: 1,
|
||||
primary_group: false,
|
||||
title: null,
|
||||
grant_trust_level: null,
|
||||
incoming_email: null,
|
||||
has_messages: false,
|
||||
flair_url: null,
|
||||
flair_bg_color: null,
|
||||
flair_color: null,
|
||||
bio_raw: null,
|
||||
bio_cooked: null,
|
||||
bio_excerpt: null,
|
||||
public_admission: false,
|
||||
public_exit: false,
|
||||
allow_membership_requests: false,
|
||||
full_name: null,
|
||||
default_notification_level: 3,
|
||||
membership_request_template: null,
|
||||
members_visibility_level: 0,
|
||||
can_see_members: true,
|
||||
can_admin_group: true,
|
||||
publish_read_state: false,
|
||||
},
|
||||
{
|
||||
id: 11,
|
||||
automatic: true,
|
||||
name: "trust_level_1",
|
||||
display_name: "trust_level_1",
|
||||
user_count: 2,
|
||||
mentionable_level: 0,
|
||||
messageable_level: 0,
|
||||
visibility_level: 1,
|
||||
primary_group: false,
|
||||
title: null,
|
||||
grant_trust_level: null,
|
||||
incoming_email: null,
|
||||
has_messages: false,
|
||||
flair_url: null,
|
||||
flair_bg_color: null,
|
||||
flair_color: null,
|
||||
bio_raw: null,
|
||||
bio_cooked: null,
|
||||
bio_excerpt: null,
|
||||
public_admission: false,
|
||||
public_exit: false,
|
||||
allow_membership_requests: false,
|
||||
full_name: null,
|
||||
default_notification_level: 3,
|
||||
membership_request_template: null,
|
||||
members_visibility_level: 0,
|
||||
can_see_members: true,
|
||||
can_admin_group: true,
|
||||
publish_read_state: false,
|
||||
},
|
||||
{
|
||||
id: 12,
|
||||
automatic: true,
|
||||
name: "trust_level_2",
|
||||
display_name: "trust_level_2",
|
||||
user_count: 1,
|
||||
mentionable_level: 0,
|
||||
messageable_level: 0,
|
||||
visibility_level: 1,
|
||||
primary_group: false,
|
||||
title: null,
|
||||
grant_trust_level: null,
|
||||
incoming_email: null,
|
||||
has_messages: false,
|
||||
flair_url: null,
|
||||
flair_bg_color: null,
|
||||
flair_color: null,
|
||||
bio_raw: null,
|
||||
bio_cooked: null,
|
||||
bio_excerpt: null,
|
||||
public_admission: false,
|
||||
public_exit: false,
|
||||
allow_membership_requests: false,
|
||||
full_name: null,
|
||||
default_notification_level: 3,
|
||||
membership_request_template: null,
|
||||
members_visibility_level: 0,
|
||||
can_see_members: true,
|
||||
can_admin_group: true,
|
||||
publish_read_state: false,
|
||||
},
|
||||
{
|
||||
id: 13,
|
||||
automatic: true,
|
||||
name: "trust_level_3",
|
||||
display_name: "trust_level_3",
|
||||
user_count: 1,
|
||||
mentionable_level: 0,
|
||||
messageable_level: 0,
|
||||
visibility_level: 1,
|
||||
primary_group: false,
|
||||
title: null,
|
||||
grant_trust_level: null,
|
||||
incoming_email: null,
|
||||
has_messages: false,
|
||||
flair_url: null,
|
||||
flair_bg_color: null,
|
||||
flair_color: null,
|
||||
bio_raw: null,
|
||||
bio_cooked: null,
|
||||
bio_excerpt: null,
|
||||
public_admission: false,
|
||||
public_exit: false,
|
||||
allow_membership_requests: false,
|
||||
full_name: null,
|
||||
default_notification_level: 3,
|
||||
membership_request_template: null,
|
||||
members_visibility_level: 0,
|
||||
can_see_members: true,
|
||||
can_admin_group: true,
|
||||
publish_read_state: false,
|
||||
},
|
||||
{
|
||||
id: 14,
|
||||
automatic: true,
|
||||
name: "trust_level_4",
|
||||
display_name: "trust_level_4",
|
||||
user_count: 0,
|
||||
mentionable_level: 0,
|
||||
messageable_level: 0,
|
||||
visibility_level: 1,
|
||||
primary_group: false,
|
||||
title: null,
|
||||
grant_trust_level: null,
|
||||
incoming_email: null,
|
||||
has_messages: false,
|
||||
flair_url: null,
|
||||
flair_bg_color: null,
|
||||
flair_color: null,
|
||||
bio_raw: null,
|
||||
bio_cooked: null,
|
||||
bio_excerpt: null,
|
||||
public_admission: false,
|
||||
public_exit: false,
|
||||
allow_membership_requests: false,
|
||||
full_name: null,
|
||||
default_notification_level: 3,
|
||||
membership_request_template: null,
|
||||
members_visibility_level: 0,
|
||||
can_see_members: true,
|
||||
can_admin_group: true,
|
||||
publish_read_state: false,
|
||||
},
|
||||
],
|
||||
};
|
294
assets/javascripts/wizard/tests/fixtures/site-settings.js.es6
gevendort
Normale Datei
294
assets/javascripts/wizard/tests/fixtures/site-settings.js.es6
gevendort
Normale Datei
|
@ -0,0 +1,294 @@
|
|||
export default {
|
||||
default_locale: "en",
|
||||
title: "Discourse",
|
||||
short_site_description: "",
|
||||
exclude_rel_nofollow_domains: "",
|
||||
logo: "/images/discourse-logo-sketch.png",
|
||||
logo_small: "/images/discourse-logo-sketch-small.png",
|
||||
digest_logo: "",
|
||||
mobile_logo: "",
|
||||
logo_dark: "",
|
||||
logo_small_dark: "",
|
||||
mobile_logo_dark: "",
|
||||
large_icon: "",
|
||||
favicon: "",
|
||||
apple_touch_icon: "",
|
||||
display_local_time_in_user_card: false,
|
||||
allow_user_locale: false,
|
||||
set_locale_from_accept_language_header: false,
|
||||
support_mixed_text_direction: false,
|
||||
suggested_topics: 5,
|
||||
ga_universal_tracking_code: "",
|
||||
ga_universal_domain_name: "auto",
|
||||
gtm_container_id: "",
|
||||
top_menu: "categories|latest",
|
||||
post_menu: "read|like|share|flag|edit|bookmark|delete|admin|reply",
|
||||
post_menu_hidden_items: "flag|bookmark|edit|delete|admin",
|
||||
share_links: "twitter|facebook|email",
|
||||
share_quote_visibility: "anonymous",
|
||||
share_quote_buttons: "twitter|email",
|
||||
desktop_category_page_style: "categories_and_latest_topics",
|
||||
category_colors:
|
||||
"BF1E2E|F1592A|F7941D|9EB83B|3AB54A|12A89D|25AAE2|0E76BD|652D90|92278F|ED207B|8C6238|231F20|808281|B3B5B4|E45735",
|
||||
category_style: "bullet",
|
||||
max_category_nesting: 2,
|
||||
enable_mobile_theme: true,
|
||||
enable_direct_s3_uploads: false,
|
||||
enable_upload_debug_mode: false,
|
||||
default_dark_mode_color_scheme_id: 1,
|
||||
relative_date_duration: 30,
|
||||
fixed_category_positions: false,
|
||||
fixed_category_positions_on_create: false,
|
||||
enable_badges: true,
|
||||
enable_badge_sql: true,
|
||||
max_favorite_badges: 2,
|
||||
enable_whispers: false,
|
||||
enable_bookmarks_with_reminders: true,
|
||||
push_notifications_prompt: true,
|
||||
vapid_public_key_bytes:
|
||||
"4|29|219|88|202|66|198|62|182|204|66|176|229|200|131|26|141|21|178|231|150|161|2|128|228|200|179|126|118|232|196|19|232|76|108|189|54|211|210|155|55|228|173|112|38|158|114|127|18|95|7|56|110|183|192|92|43|0|243|249|233|89|9|207|255",
|
||||
invite_only: false,
|
||||
login_required: false,
|
||||
must_approve_users: false,
|
||||
enable_local_logins: true,
|
||||
enable_local_logins_via_email: true,
|
||||
allow_new_registrations: true,
|
||||
enable_signup_cta: true,
|
||||
facebook_app_id: "",
|
||||
auth_skip_create_confirm: false,
|
||||
auth_overrides_email: false,
|
||||
enable_discourse_connect: true,
|
||||
discourse_connect_overrides_avatar: false,
|
||||
hide_email_address_taken: false,
|
||||
min_username_length: 3,
|
||||
max_username_length: 20,
|
||||
unicode_usernames: false,
|
||||
min_password_length: 10,
|
||||
min_admin_password_length: 15,
|
||||
email_editable: true,
|
||||
logout_redirect: "",
|
||||
full_name_required: false,
|
||||
enable_names: true,
|
||||
invite_expiry_days: 90,
|
||||
invites_per_page: 40,
|
||||
delete_user_max_post_age: 60,
|
||||
delete_all_posts_max: 15,
|
||||
prioritize_username_in_ux: true,
|
||||
enable_user_directory: true,
|
||||
allow_anonymous_posting: false,
|
||||
anonymous_posting_min_trust_level: 1,
|
||||
allow_users_to_hide_profile: true,
|
||||
hide_user_profiles_from_public: false,
|
||||
allow_featured_topic_on_user_profiles: true,
|
||||
hide_suspension_reasons: false,
|
||||
ignored_users_count_message_threshold: 5,
|
||||
ignored_users_message_gap_days: 365,
|
||||
user_selected_primary_groups: false,
|
||||
gravatar_name: "Gravatar",
|
||||
gravatar_base_url: "www.gravatar.com",
|
||||
gravatar_login_url: "/emails",
|
||||
enable_group_directory: true,
|
||||
enable_category_group_moderation: false,
|
||||
min_post_length: 20,
|
||||
min_first_post_length: 20,
|
||||
min_personal_message_post_length: 10,
|
||||
max_post_length: 32000,
|
||||
topic_featured_link_enabled: true,
|
||||
min_topic_views_for_delete_confirm: 5000,
|
||||
min_topic_title_length: 15,
|
||||
max_topic_title_length: 255,
|
||||
enable_filtered_replies_view: false,
|
||||
min_personal_message_title_length: 2,
|
||||
allow_uncategorized_topics: true,
|
||||
min_title_similar_length: 10,
|
||||
enable_personal_messages: true,
|
||||
edit_history_visible_to_public: true,
|
||||
delete_removed_posts_after: 24,
|
||||
traditional_markdown_linebreaks: false,
|
||||
enable_markdown_typographer: true,
|
||||
enable_markdown_linkify: true,
|
||||
markdown_linkify_tlds:
|
||||
"com|net|org|io|onion|co|tv|ru|cn|us|uk|me|de|fr|fi|gov",
|
||||
markdown_typographer_quotation_marks: "“|”|‘|’",
|
||||
enable_rich_text_paste: true,
|
||||
suppress_reply_directly_below: true,
|
||||
suppress_reply_directly_above: true,
|
||||
max_reply_history: 1,
|
||||
enable_mentions: true,
|
||||
here_mention: "here",
|
||||
newuser_max_embedded_media: 1,
|
||||
newuser_max_attachments: 0,
|
||||
show_pinned_excerpt_mobile: true,
|
||||
show_pinned_excerpt_desktop: true,
|
||||
display_name_on_posts: false,
|
||||
show_time_gap_days: 7,
|
||||
short_progress_text_threshold: 10000,
|
||||
default_code_lang: "auto",
|
||||
autohighlight_all_code: false,
|
||||
highlighted_languages:
|
||||
"apache|bash|cs|cpp|css|coffeescript|diff|xml|http|ini|json|java|javascript|makefile|markdown|nginx|objectivec|ruby|perl|php|python|sql|handlebars",
|
||||
show_copy_button_on_codeblocks: false,
|
||||
enable_emoji: true,
|
||||
enable_emoji_shortcuts: true,
|
||||
emoji_set: "twitter",
|
||||
emoji_autocomplete_min_chars: 0,
|
||||
enable_inline_emoji_translation: false,
|
||||
code_formatting_style: "code-fences",
|
||||
allowed_href_schemes: "",
|
||||
watched_words_regular_expressions: false,
|
||||
enable_diffhtml_preview: false,
|
||||
enable_fast_edit: true,
|
||||
old_post_notice_days: 14,
|
||||
blur_tl0_flagged_posts_media: true,
|
||||
email_time_window_mins: 10,
|
||||
disable_digest_emails: false,
|
||||
email_in: false,
|
||||
enable_imap: false,
|
||||
enable_smtp: false,
|
||||
disable_emails: "no",
|
||||
bounce_score_threshold: 4,
|
||||
enable_secondary_emails: true,
|
||||
max_image_size_kb: 4096,
|
||||
max_attachment_size_kb: 4096,
|
||||
authorized_extensions: "jpg|jpeg|png|gif|heic|heif|webp",
|
||||
authorized_extensions_for_staff: "",
|
||||
max_image_width: 690,
|
||||
max_image_height: 500,
|
||||
prevent_anons_from_downloading_files: false,
|
||||
secure_media: false,
|
||||
enable_s3_uploads: false,
|
||||
allow_profile_backgrounds: true,
|
||||
allow_uploaded_avatars: "0",
|
||||
default_avatars: "",
|
||||
external_system_avatars_enabled: true,
|
||||
external_system_avatars_url:
|
||||
"/letter_avatar_proxy/v4/letter/{first_letter}/{color}/{size}.png",
|
||||
external_emoji_url: "",
|
||||
selectable_avatars_mode: "disabled",
|
||||
selectable_avatars: "",
|
||||
allow_staff_to_upload_any_file_in_pm: true,
|
||||
simultaneous_uploads: 5,
|
||||
composer_media_optimization_image_enabled: true,
|
||||
composer_media_optimization_image_bytes_optimization_threshold: 524288,
|
||||
composer_media_optimization_image_resize_dimensions_threshold: 1920,
|
||||
composer_media_optimization_image_resize_width_target: 1920,
|
||||
composer_media_optimization_image_resize_pre_multiply: false,
|
||||
composer_media_optimization_image_resize_linear_rgb: false,
|
||||
composer_media_optimization_image_encode_quality: 75,
|
||||
composer_media_optimization_debug_mode: false,
|
||||
min_trust_level_to_allow_profile_background: 0,
|
||||
min_trust_level_to_allow_user_card_background: 0,
|
||||
min_trust_level_to_allow_ignore: 2,
|
||||
tl1_requires_read_posts: 30,
|
||||
tl3_links_no_follow: false,
|
||||
enforce_second_factor: "no",
|
||||
moderators_change_post_ownership: false,
|
||||
moderators_view_emails: false,
|
||||
use_admin_ip_allowlist: false,
|
||||
allowed_iframes:
|
||||
"https://www.google.com/maps/embed?|https://www.openstreetmap.org/export/embed.html?|https://calendar.google.com/calendar/embed?|https://codepen.io/|https://www.instagram.com|http://localhost:3000/discobot/certificate.svg",
|
||||
can_permanently_delete: false,
|
||||
max_oneboxes_per_post: 50,
|
||||
reviewable_claiming: "disabled",
|
||||
reviewable_default_topics: false,
|
||||
reviewable_default_visibility: "low",
|
||||
alert_admins_if_errors_per_minute: 0,
|
||||
alert_admins_if_errors_per_hour: 0,
|
||||
max_prints_per_hour_per_user: 5,
|
||||
invite_link_max_redemptions_limit: 5000,
|
||||
invite_link_max_redemptions_limit_users: 10,
|
||||
enable_long_polling: true,
|
||||
enable_chunked_encoding: true,
|
||||
long_polling_base_url: "/",
|
||||
background_polling_interval: 60000,
|
||||
polling_interval: 3000,
|
||||
anon_polling_interval: 25000,
|
||||
flush_timings_secs: 60,
|
||||
verbose_localization: false,
|
||||
max_new_topics: 500,
|
||||
enable_safe_mode: true,
|
||||
tos_url: "",
|
||||
privacy_policy_url: "",
|
||||
faq_url: "",
|
||||
enable_backups: true,
|
||||
backup_location: "local",
|
||||
maximum_backups: 5,
|
||||
use_pg_headlines_for_excerpt: false,
|
||||
min_search_term_length: 3,
|
||||
log_search_queries: true,
|
||||
version_checks: true,
|
||||
suppress_uncategorized_badge: true,
|
||||
header_dropdown_category_count: 8,
|
||||
slug_generation_method: "ascii",
|
||||
summary_timeline_button: false,
|
||||
topic_views_heat_low: 1000,
|
||||
topic_views_heat_medium: 2000,
|
||||
topic_views_heat_high: 3500,
|
||||
topic_post_like_heat_low: 0.5,
|
||||
topic_post_like_heat_medium: 1,
|
||||
topic_post_like_heat_high: 2,
|
||||
history_hours_low: 12,
|
||||
history_hours_medium: 24,
|
||||
history_hours_high: 48,
|
||||
cold_age_days_low: 14,
|
||||
cold_age_days_medium: 90,
|
||||
cold_age_days_high: 180,
|
||||
global_notice: "",
|
||||
show_create_topics_notice: true,
|
||||
bootstrap_mode_min_users: 50,
|
||||
bootstrap_mode_enabled: true,
|
||||
automatically_unpin_topics: true,
|
||||
read_time_word_count: 500,
|
||||
topic_page_title_includes_category: true,
|
||||
svg_icon_subset: "",
|
||||
allow_bulk_invite: true,
|
||||
disable_mailing_list_mode: true,
|
||||
default_topics_automatic_unpin: true,
|
||||
mute_all_categories_by_default: false,
|
||||
tagging_enabled: true,
|
||||
tag_style: "simple",
|
||||
max_tags_per_topic: 5,
|
||||
max_tag_length: 20,
|
||||
min_trust_level_to_tag_topics: "0",
|
||||
max_tag_search_results: 5,
|
||||
max_tags_in_filter_list: 30,
|
||||
tags_sort_alphabetically: false,
|
||||
tags_listed_by_group: false,
|
||||
suppress_overlapping_tags_in_list: false,
|
||||
remove_muted_tags_from_latest: "always",
|
||||
force_lowercase_tags: true,
|
||||
dashboard_hidden_reports: "",
|
||||
dashboard_visible_tabs: "moderation|security|reports",
|
||||
dashboard_general_tab_activity_metrics:
|
||||
"page_view_total_reqs|visits|time_to_first_response|likes|flags|user_to_user_private_messages_with_replies",
|
||||
discourse_narrative_bot_enabled: true,
|
||||
details_enabled: true,
|
||||
custom_wizard_enabled: true,
|
||||
wizard_redirect_exclude_paths: "admin",
|
||||
wizard_recognised_image_upload_formats: "jpg|jpeg|png|gif",
|
||||
wizard_important_notices_on_dashboard: true,
|
||||
discourse_local_dates_email_format: "YYYY-MM-DDTHH:mm:ss[Z]",
|
||||
discourse_local_dates_enabled: true,
|
||||
discourse_local_dates_default_formats: "LLL|LTS|LL|LLLL",
|
||||
discourse_local_dates_default_timezones: "Europe/Paris|America/Los_Angeles",
|
||||
poll_enabled: true,
|
||||
poll_maximum_options: 20,
|
||||
poll_minimum_trust_level_to_create: 1,
|
||||
poll_groupable_user_fields: "",
|
||||
poll_export_data_explorer_query_id: -16,
|
||||
presence_enabled: true,
|
||||
presence_max_users_shown: 5,
|
||||
available_locales:
|
||||
'[{"name":"اللغة العربية","value":"ar"},{"name":"беларуская мова","value":"be"},{"name":"български език","value":"bg"},{"name":"bosanski jezik","value":"bs_BA"},{"name":"català","value":"ca"},{"name":"čeština","value":"cs"},{"name":"dansk","value":"da"},{"name":"Deutsch","value":"de"},{"name":"ελληνικά","value":"el"},{"name":"English (US)","value":"en"},{"name":"English (UK)","value":"en_GB"},{"name":"Español","value":"es"},{"name":"eesti","value":"et"},{"name":"فارسی","value":"fa_IR"},{"name":"suomi","value":"fi"},{"name":"Français","value":"fr"},{"name":"galego","value":"gl"},{"name":"עברית","value":"he"},{"name":"magyar","value":"hu"},{"name":"Հայերեն","value":"hy"},{"name":"Indonesian","value":"id"},{"name":"Italiano","value":"it"},{"name":"日本語","value":"ja"},{"name":"한국어","value":"ko"},{"name":"lietuvių kalba","value":"lt"},{"name":"latviešu valoda","value":"lv"},{"name":"Norsk bokmål","value":"nb_NO"},{"name":"Nederlands","value":"nl"},{"name":"polski","value":"pl_PL"},{"name":"Português","value":"pt"},{"name":"Português (BR)","value":"pt_BR"},{"name":"limba română","value":"ro"},{"name":"Русский","value":"ru"},{"name":"slovenčina","value":"sk"},{"name":"slovenščina","value":"sl"},{"name":"Shqip","value":"sq"},{"name":"српски језик","value":"sr"},{"name":"svenska","value":"sv"},{"name":"Kiswahili","value":"sw"},{"name":"తెలుగు","value":"te"},{"name":"ไทย","value":"th"},{"name":"Türkçe","value":"tr_TR"},{"name":"українська мова","value":"uk"},{"name":"اردو","value":"ur"},{"name":"Việt Nam","value":"vi"},{"name":"简体中文","value":"zh_CN"},{"name":"繁體中文","value":"zh_TW"}]',
|
||||
require_invite_code: false,
|
||||
site_logo_url: "http://localhost:3000/images/discourse-logo-sketch.png",
|
||||
site_logo_small_url:
|
||||
"http://localhost:3000/images/discourse-logo-sketch-small.png",
|
||||
site_mobile_logo_url:
|
||||
"http://localhost:3000/images/discourse-logo-sketch.png",
|
||||
site_favicon_url:
|
||||
"http://localhost:3000/uploads/default/optimized/1X/_129430568242d1b7f853bb13ebea28b3f6af4e7_2_32x32.png",
|
||||
site_logo_dark_url: "",
|
||||
site_logo_small_dark_url: "",
|
||||
site_mobile_logo_dark_url: "",
|
||||
};
|
22
assets/javascripts/wizard/tests/fixtures/tags.js.es6
gevendort
Normale Datei
22
assets/javascripts/wizard/tests/fixtures/tags.js.es6
gevendort
Normale Datei
|
@ -0,0 +1,22 @@
|
|||
export default {
|
||||
tags: [
|
||||
{
|
||||
id: "tag1",
|
||||
text: "tag1",
|
||||
name: "tag1",
|
||||
description: null,
|
||||
count: 1,
|
||||
pm_count: 0,
|
||||
target_tag: null,
|
||||
},
|
||||
{
|
||||
id: "tag2",
|
||||
text: "tag2",
|
||||
name: "tag2",
|
||||
description: null,
|
||||
count: 1,
|
||||
pm_count: 0,
|
||||
target_tag: null,
|
||||
},
|
||||
],
|
||||
};
|
5
assets/javascripts/wizard/tests/fixtures/update.js.es6
gevendort
Normale Datei
5
assets/javascripts/wizard/tests/fixtures/update.js.es6
gevendort
Normale Datei
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
final: false,
|
||||
next_step_id: "step_2",
|
||||
wizard: {},
|
||||
};
|
34
assets/javascripts/wizard/tests/fixtures/user.js.es6
gevendort
Normale Datei
34
assets/javascripts/wizard/tests/fixtures/user.js.es6
gevendort
Normale Datei
|
@ -0,0 +1,34 @@
|
|||
export default {
|
||||
id: 19,
|
||||
username: "angus",
|
||||
uploaded_avatar_id: 5275,
|
||||
avatar_template: "/user_avatar/localhost/angus/{size}/5275.png",
|
||||
name: "Angus McLeod",
|
||||
unread_notifications: 0,
|
||||
unread_private_messages: 0,
|
||||
unread_high_priority_notifications: 0,
|
||||
admin: true,
|
||||
notification_channel_position: null,
|
||||
site_flagged_posts_count: 1,
|
||||
moderator: true,
|
||||
staff: true,
|
||||
can_create_group: true,
|
||||
title: "",
|
||||
reply_count: 859,
|
||||
topic_count: 36,
|
||||
enable_quoting: true,
|
||||
external_links_in_new_tab: false,
|
||||
dynamic_favicon: true,
|
||||
trust_level: 4,
|
||||
can_edit: true,
|
||||
can_invite_to_forum: true,
|
||||
should_be_redirected_to_top: false,
|
||||
custom_fields: {},
|
||||
muted_category_ids: [],
|
||||
dismissed_banner_key: null,
|
||||
akismet_review_count: 0,
|
||||
title_count_mode: "notifications",
|
||||
timezone: "Australia/Perth",
|
||||
skip_new_user_tips: false,
|
||||
can_review: true,
|
||||
};
|
14
assets/javascripts/wizard/tests/fixtures/users.js.es6
gevendort
Normale Datei
14
assets/javascripts/wizard/tests/fixtures/users.js.es6
gevendort
Normale Datei
|
@ -0,0 +1,14 @@
|
|||
export default {
|
||||
users: [
|
||||
{
|
||||
username: "angus",
|
||||
name: "Angus",
|
||||
avatar_template: "/user_avatar/localhost/angus/{size}/12_2.png",
|
||||
},
|
||||
{
|
||||
username: "angus_2",
|
||||
name: "Angus 2",
|
||||
avatar_template: "/letter_avatar_proxy/v4/letter/a/e9a140/{size}.png",
|
||||
},
|
||||
],
|
||||
};
|
471
assets/javascripts/wizard/tests/fixtures/wizard.js.es6
gevendort
Normale Datei
471
assets/javascripts/wizard/tests/fixtures/wizard.js.es6
gevendort
Normale Datei
|
@ -0,0 +1,471 @@
|
|||
export default {
|
||||
id: "wizard",
|
||||
name: "Wizard",
|
||||
start: "step_1",
|
||||
background: "#333333",
|
||||
submission_last_updated_at: "2022-03-15T21:11:01+01:00",
|
||||
theme_id: 2,
|
||||
required: false,
|
||||
permitted: true,
|
||||
uncategorized_category_id: 1,
|
||||
categories: [],
|
||||
subscribed: false,
|
||||
resume_on_revisit: false,
|
||||
steps: [
|
||||
{
|
||||
id: "step_1",
|
||||
index: 0,
|
||||
next: "step_2",
|
||||
description: "<p>Text inputs!</p>",
|
||||
title: "Text",
|
||||
permitted: true,
|
||||
permitted_message: null,
|
||||
final: false,
|
||||
fields: [
|
||||
{
|
||||
id: "step_1_field_1",
|
||||
index: 0,
|
||||
type: "text",
|
||||
required: false,
|
||||
value: "I am prefilled",
|
||||
label: "<p>Text</p>",
|
||||
description: "Text field description.",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 1,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_1",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_1_field_2",
|
||||
index: 0,
|
||||
type: "textarea",
|
||||
required: false,
|
||||
value: "",
|
||||
label: "<p>Textarea</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 2,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_1",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_1_field_3",
|
||||
index: 2,
|
||||
type: "composer",
|
||||
required: false,
|
||||
value: "",
|
||||
label: "<p>Composer</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 3,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_1",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_1_field_4",
|
||||
index: 3,
|
||||
type: "text_only",
|
||||
required: false,
|
||||
value: null,
|
||||
label: "<p>I’m only text</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 4,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_1",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_1_field_5",
|
||||
index: 4,
|
||||
type: "composer_preview",
|
||||
required: false,
|
||||
value: "",
|
||||
label: "<p>I’m a preview</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: "<p>I am prefilled</p>",
|
||||
tabindex: 5,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_1",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_1_field_6",
|
||||
index: 5,
|
||||
type: "composer_preview",
|
||||
required: false,
|
||||
value: "",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: "<p>This is the preview of the composer</p>",
|
||||
tabindex: 6,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_1",
|
||||
_validState: 0,
|
||||
},
|
||||
],
|
||||
_validState: 0,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
},
|
||||
{
|
||||
id: "step_2",
|
||||
index: 1,
|
||||
next: "step_3",
|
||||
previous: "step_1",
|
||||
description:
|
||||
'<p>Because I couldn’t think of another name for this step <img src="/images/emoji/twitter/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20"></p>',
|
||||
title: "Values",
|
||||
permitted: true,
|
||||
permitted_message: null,
|
||||
final: false,
|
||||
fields: [
|
||||
{
|
||||
id: "step_2_field_1",
|
||||
index: 0,
|
||||
type: "date",
|
||||
required: false,
|
||||
value: "",
|
||||
label: "<p>Date</p>",
|
||||
file_types: null,
|
||||
format: "YYYY-MM-DD",
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 1,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_2",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_2_field_2",
|
||||
index: 0,
|
||||
type: "time",
|
||||
required: false,
|
||||
value: "",
|
||||
label: "<p>Time</p>",
|
||||
file_types: null,
|
||||
format: "HH:mm",
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 2,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_2",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_2_field_3",
|
||||
index: 2,
|
||||
type: "date_time",
|
||||
required: false,
|
||||
value: "",
|
||||
label: "<p>Date & Time</p>",
|
||||
file_types: null,
|
||||
format: "",
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 3,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_2",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_2_field_4",
|
||||
index: 3,
|
||||
type: "number",
|
||||
required: false,
|
||||
value: "",
|
||||
label: "<p>Number</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 5,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_2",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_2_field_5",
|
||||
index: 4,
|
||||
type: "checkbox",
|
||||
required: false,
|
||||
value: false,
|
||||
label: "<p>Checkbox</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 6,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_2",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_2_field_6",
|
||||
index: 5,
|
||||
type: "url",
|
||||
required: false,
|
||||
value: "",
|
||||
label: "<p>Url</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 7,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_2",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_2_field_7",
|
||||
index: 6,
|
||||
type: "upload",
|
||||
required: false,
|
||||
value: "",
|
||||
label: "<p>Upload</p>",
|
||||
file_types: ".jpg,.jpeg,.png",
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 8,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_2",
|
||||
_validState: 0,
|
||||
},
|
||||
],
|
||||
_validState: 0,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
},
|
||||
{
|
||||
id: "step_3",
|
||||
index: 2,
|
||||
previous: "step_2",
|
||||
description:
|
||||
'<p>Unfortunately not the edible type <img src="/images/emoji/twitter/sushi.png?v=12" title=":sushi:" class="emoji" alt=":sushi:" loading="lazy" width="20" height="20"></p>',
|
||||
title: "Combo-boxes",
|
||||
permitted: true,
|
||||
permitted_message: null,
|
||||
final: true,
|
||||
fields: [
|
||||
{
|
||||
id: "step_3_field_1",
|
||||
index: 0,
|
||||
type: "dropdown",
|
||||
required: false,
|
||||
value: "choice1",
|
||||
label: "<p>Custom Dropdown</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: [
|
||||
{
|
||||
id: "one",
|
||||
name: "One",
|
||||
},
|
||||
{
|
||||
id: "two",
|
||||
name: "Two",
|
||||
},
|
||||
],
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 1,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_3",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_3_field_2",
|
||||
index: 0,
|
||||
type: "tag",
|
||||
required: false,
|
||||
value: null,
|
||||
label: "<p>Tag</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 2,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_3",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_3_field_3",
|
||||
index: 2,
|
||||
type: "category",
|
||||
required: false,
|
||||
value: null,
|
||||
label: "<p>Category</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: 1,
|
||||
property: "id",
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 3,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_3",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_3_field_4",
|
||||
index: 3,
|
||||
type: "group",
|
||||
required: false,
|
||||
value: null,
|
||||
label: "<p>Group</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 4,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_3",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_3_field_5",
|
||||
index: 4,
|
||||
type: "user_selector",
|
||||
required: false,
|
||||
value: null,
|
||||
label: "<p>User Selector</p>",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 5,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_3",
|
||||
_validState: 0,
|
||||
},
|
||||
{
|
||||
id: "step_3_field_6",
|
||||
index: 5,
|
||||
type: "user_selector",
|
||||
required: false,
|
||||
value: null,
|
||||
label: "<p>Conditional User Selector</p>",
|
||||
description: "Shown when checkbox in step_2_field_5 is true",
|
||||
file_types: null,
|
||||
format: null,
|
||||
limit: null,
|
||||
property: null,
|
||||
content: null,
|
||||
validations: {},
|
||||
max_length: null,
|
||||
char_counter: null,
|
||||
preview_template: null,
|
||||
tabindex: 6,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
stepId: "step_3",
|
||||
_validState: 0,
|
||||
},
|
||||
],
|
||||
_validState: 0,
|
||||
wizardId: "super_mega_fun_wizard",
|
||||
},
|
||||
],
|
||||
groups: [],
|
||||
};
|
53
assets/javascripts/wizard/tests/helpers/acceptance.js.es6
Normale Datei
53
assets/javascripts/wizard/tests/helpers/acceptance.js.es6
Normale Datei
|
@ -0,0 +1,53 @@
|
|||
import { module } from "qunit";
|
||||
import setupPretender, { response } from "../pretender";
|
||||
import startApp from "../helpers/start-app";
|
||||
|
||||
let server;
|
||||
let app;
|
||||
|
||||
function acceptance(name, requests, cb) {
|
||||
module(`Acceptance: ${name}`, function (hooks) {
|
||||
hooks.beforeEach(function () {
|
||||
server = setupPretender(function (pretender) {
|
||||
requests.forEach((req) => {
|
||||
pretender[req.verb](req.path, () =>
|
||||
response(req.status, req.response)
|
||||
);
|
||||
});
|
||||
return pretender;
|
||||
});
|
||||
app = startApp();
|
||||
});
|
||||
|
||||
hooks.afterEach(function () {
|
||||
app.destroy();
|
||||
server.shutdown();
|
||||
});
|
||||
|
||||
cb(hooks);
|
||||
});
|
||||
}
|
||||
|
||||
export default acceptance;
|
||||
|
||||
export { server };
|
||||
|
||||
// The discourse/test/helpers/qunit-helpers file has many functions and imports
|
||||
// we don't need, so there will be some duplciation here.
|
||||
|
||||
export function queryAll(selector, context) {
|
||||
context = context || "#ember-testing";
|
||||
return $(selector, context);
|
||||
}
|
||||
|
||||
export function query() {
|
||||
return document.querySelector("#ember-testing").querySelector(...arguments);
|
||||
}
|
||||
|
||||
export function visible(selector) {
|
||||
return queryAll(selector + ":visible").length > 0;
|
||||
}
|
||||
|
||||
export function count(selector) {
|
||||
return queryAll(selector).length;
|
||||
}
|
25
assets/javascripts/wizard/tests/helpers/start-app.js.es6
Normale Datei
25
assets/javascripts/wizard/tests/helpers/start-app.js.es6
Normale Datei
|
@ -0,0 +1,25 @@
|
|||
const CustomWizard = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/application"
|
||||
).default;
|
||||
const initializer = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/lib/initialize/wizard"
|
||||
).default;
|
||||
const siteSettings = requirejs(
|
||||
"discourse/plugins/discourse-custom-wizard/wizard/tests/fixtures/site-settings"
|
||||
).default;
|
||||
const { cloneJSON } = requirejs("discourse-common/lib/object").default;
|
||||
|
||||
let app;
|
||||
|
||||
export default function () {
|
||||
app = CustomWizard.create({ rootElement: "#ember-testing" });
|
||||
app.start();
|
||||
|
||||
app.SiteSettings = cloneJSON(siteSettings);
|
||||
initializer.initialize(app);
|
||||
|
||||
app.setupForTesting();
|
||||
app.injectTestHelpers();
|
||||
|
||||
return app;
|
||||
}
|
17
assets/javascripts/wizard/tests/helpers/step.js.es6
Normale Datei
17
assets/javascripts/wizard/tests/helpers/step.js.es6
Normale Datei
|
@ -0,0 +1,17 @@
|
|||
import updateJson from "../fixtures/update";
|
||||
import { cloneJSON } from "discourse-common/lib/object";
|
||||
import wizardJson from "../fixtures/wizard";
|
||||
|
||||
const update = cloneJSON(updateJson);
|
||||
update.wizard = cloneJSON(wizardJson);
|
||||
|
||||
const saveStep = function (response) {
|
||||
return {
|
||||
verb: "put",
|
||||
path: "/w/wizard/steps/:step_id",
|
||||
status: 200,
|
||||
response,
|
||||
};
|
||||
};
|
||||
|
||||
export { saveStep, update };
|
5
assets/javascripts/wizard/tests/helpers/test.js.es6
Normale Datei
5
assets/javascripts/wizard/tests/helpers/test.js.es6
Normale Datei
|
@ -0,0 +1,5 @@
|
|||
function exists(selector) {
|
||||
return document.querySelector(selector) !== null;
|
||||
}
|
||||
|
||||
export { exists };
|
52
assets/javascripts/wizard/tests/helpers/wizard.js.es6
Normale Datei
52
assets/javascripts/wizard/tests/helpers/wizard.js.es6
Normale Datei
|
@ -0,0 +1,52 @@
|
|||
import wizardJson from "../fixtures/wizard";
|
||||
import userJson from "../fixtures/user";
|
||||
import categoriesJson from "../fixtures/categories";
|
||||
import groupsJson from "../fixtures/groups";
|
||||
import { cloneJSON } from "discourse-common/lib/object";
|
||||
|
||||
const wizardNoUser = cloneJSON(wizardJson);
|
||||
const wizard = cloneJSON(wizardJson);
|
||||
wizard.user = cloneJSON(userJson);
|
||||
|
||||
const wizardNotPermitted = cloneJSON(wizard);
|
||||
wizardNotPermitted.permitted = false;
|
||||
|
||||
const wizardCompleted = cloneJSON(wizard);
|
||||
wizardCompleted.completed = true;
|
||||
|
||||
wizard.start = "step_1";
|
||||
wizard.resume_on_revisit = false;
|
||||
wizard.submission_last_updated_at = "2022-03-11T20:00:18+01:00";
|
||||
wizard.subscribed = false;
|
||||
|
||||
const stepNotPermitted = cloneJSON(wizard);
|
||||
stepNotPermitted.steps[0].permitted = false;
|
||||
|
||||
const allFieldsWizard = cloneJSON(wizard);
|
||||
allFieldsWizard.steps[0].fields = [
|
||||
...allFieldsWizard.steps[0].fields,
|
||||
...allFieldsWizard.steps[1].fields,
|
||||
...allFieldsWizard.steps[2].fields,
|
||||
];
|
||||
allFieldsWizard.steps = [cloneJSON(allFieldsWizard.steps[0])];
|
||||
allFieldsWizard.categories = cloneJSON(categoriesJson["categories"]);
|
||||
allFieldsWizard.groups = cloneJSON(groupsJson["groups"]);
|
||||
|
||||
const getWizard = function (response) {
|
||||
return {
|
||||
verb: "get",
|
||||
path: "/w/wizard",
|
||||
status: 200,
|
||||
response,
|
||||
};
|
||||
};
|
||||
|
||||
export {
|
||||
getWizard,
|
||||
wizardNoUser,
|
||||
wizardNotPermitted,
|
||||
wizardCompleted,
|
||||
stepNotPermitted,
|
||||
allFieldsWizard,
|
||||
wizard,
|
||||
};
|
35
assets/javascripts/wizard/tests/pretender.js.es6
Normale Datei
35
assets/javascripts/wizard/tests/pretender.js.es6
Normale Datei
|
@ -0,0 +1,35 @@
|
|||
import Pretender from "pretender";
|
||||
|
||||
function response(code, obj) {
|
||||
if (typeof code === "object") {
|
||||
obj = code;
|
||||
code = 200;
|
||||
}
|
||||
return [code, { "Content-Type": "application/json" }, obj];
|
||||
}
|
||||
|
||||
export { response };
|
||||
|
||||
export default function (cb) {
|
||||
let server = new Pretender();
|
||||
|
||||
if (cb) {
|
||||
server = cb(server);
|
||||
}
|
||||
|
||||
server.prepareBody = function (body) {
|
||||
if (body && typeof body === "object") {
|
||||
return JSON.stringify(body);
|
||||
}
|
||||
return body;
|
||||
};
|
||||
|
||||
server.unhandledRequest = function (verb, path) {
|
||||
const error =
|
||||
"Unhandled request in test environment: " + path + " (" + verb + ")";
|
||||
window.console.error(error);
|
||||
throw error;
|
||||
};
|
||||
|
||||
return server;
|
||||
}
|
|
@ -46,7 +46,7 @@
|
|||
position: relative;
|
||||
}
|
||||
|
||||
.wizard-field-composer.show-preview .d-editor-textarea-wrapper {
|
||||
.wizard-field-composer.show-preview .d-editor-textarea-column {
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# frozen_string_literal: true
|
||||
CustomWizard::Engine.routes.draw do
|
||||
get 'qunit' => 'wizard#qunit'
|
||||
get ':wizard_id' => 'wizard#index'
|
||||
put ':wizard_id/skip' => 'wizard#skip'
|
||||
get ':wizard_id/steps' => 'wizard#index'
|
||||
|
|
|
@ -6,6 +6,7 @@ module ExtraLocalesControllerCustomWizard
|
|||
path = URI(request.referer).path
|
||||
wizard_path = path.split('/w/').last
|
||||
wizard_id = wizard_path.split('/').first
|
||||
return true if wizard_id == "qunit"
|
||||
CustomWizard::Template.exists?(wizard_id.underscore)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -20,7 +20,7 @@ class ::CustomWizard::UpdateValidator
|
|||
field_id = field.id.to_s
|
||||
value = @updater.submission[field_id]
|
||||
min_length = false
|
||||
label = field.raw[:label] || I18n.t("#{field.key}.label")
|
||||
label = field.raw[:label]
|
||||
type = field.type
|
||||
required = field.required
|
||||
min_length = field.min_length if is_text_type(field)
|
||||
|
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden …
In neuem Issue referenzieren