1
0
Fork 0
Dieser Commit ist enthalten in:
Faizaan Gagan 2021-04-21 03:32:31 +05:30
Commit fb8cdab0fd
174 geänderte Dateien mit 3526 neuen und 2192 gelöschten Zeilen

3
.eslintrc Normale Datei
Datei anzeigen

@ -0,0 +1,3 @@
{
"extends": "eslint-config-discourse"
}

53
.github/workflows/plugin-linting.yml gevendort Normale Datei
Datei anzeigen

@ -0,0 +1,53 @@
name: Linting
on:
push:
branches:
- master
- main
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v1
with:
node-version: 12
- name: Set up ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
- name: Setup bundler
run: gem install bundler -v 2.1.4 --no-doc
- name: Setup gems
run: bundle install --jobs 4
- name: Yarn install
run: yarn install --dev
- name: ESLint
run: yarn eslint --ext .js,.js.es6 --no-error-on-unmatched-pattern {test,assets}/javascripts
- name: Prettier
run: |
yarn prettier -v
if [ -d "assets" ]; then \
yarn prettier --list-different "assets/**/*.{scss,js,es6}" ; \
fi
if [ -d "test" ]; then \
yarn prettier --list-different "test/**/*.{js,es6}" ; \
fi
- name: Ember template lint
run: yarn ember-template-lint assets/javascripts
- name: Rubocop
run: bundle exec rubocop .

137
.github/workflows/plugin-tests.yml gevendort Normale Datei
Datei anzeigen

@ -0,0 +1,137 @@
name: Plugin Tests
on:
push:
branches:
- master
- main
pull_request:
jobs:
build:
name: ${{ matrix.build_type }}
runs-on: ubuntu-latest
timeout-minutes: 60
env:
DISCOURSE_HOSTNAME: www.example.com
RUBY_GLOBAL_METHOD_CACHE_SIZE: 131072
RAILS_ENV: test
PGHOST: localhost
PGUSER: discourse
PGPASSWORD: discourse
strategy:
fail-fast: false
matrix:
build_type: ["backend", "frontend"]
ruby: ["2.7"]
postgres: ["12"]
redis: ["4.x"]
services:
postgres:
image: postgres:${{ matrix.postgres }}
ports:
- 5432:5432
env:
POSTGRES_USER: discourse
POSTGRES_PASSWORD: discourse
options: >-
--mount type=tmpfs,destination=/var/lib/postgresql/data
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- uses: actions/checkout@v2
with:
repository: discourse/discourse
fetch-depth: 1
- name: Install plugin
uses: actions/checkout@v2
with:
path: plugins/${{ github.event.repository.name }}
fetch-depth: 1
- name: Check spec existence
id: check_spec
uses: andstor/file-existence-action@v1
with:
files: "plugins/${{ github.event.repository.name }}/spec"
- name: Check qunit existence
id: check_qunit
uses: andstor/file-existence-action@v1
with:
files: "plugins/${{ github.event.repository.name }}/test/javascripts"
- name: Setup Git
run: |
git config --global user.email "ci@ci.invalid"
git config --global user.name "Discourse CI"
- name: Setup packages
run: |
sudo apt-get update
sudo apt-get -yqq install postgresql-client libpq-dev gifsicle jpegoptim optipng jhead
wget -qO- https://raw.githubusercontent.com/discourse/discourse_docker/master/image/base/install-pngquant | sudo sh
- name: Update imagemagick
if: matrix.build_type == 'backend'
run: |
wget https://raw.githubusercontent.com/discourse/discourse_docker/master/image/base/install-imagemagick
chmod +x install-imagemagick
sudo ./install-imagemagick
- name: Setup redis
uses: shogo82148/actions-setup-redis@v1
with:
redis-version: ${{ matrix.redis }}
- name: Setup ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true
- name: Lint English locale
if: matrix.build_type == 'backend'
run: bundle exec ruby script/i18n_lint.rb "plugins/${{ github.event.repository.name }}/locales/{client,server}.en.yml"
- name: Get yarn cache directory
id: yarn-cache-dir
run: echo "::set-output name=dir::$(yarn cache dir)"
- name: Yarn cache
uses: actions/cache@v2
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-${{ matrix.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-${{ matrix.os }}-yarn-
- name: Yarn install
run: yarn install --dev
- name: Migrate database
run: |
bin/rake db:create
bin/rake db:migrate
- name: Plugin RSpec
if: matrix.build_type == 'backend' && steps.check_spec.outputs.files_exists == 'true'
run: bin/rake plugin:spec[${{ github.event.repository.name }}]
- name: Plugin QUnit
if: matrix.build_type == 'frontend' && steps.check_qunit.outputs.files_exists == 'true'
run: bundle exec rake plugin:qunit['${{ github.event.repository.name }}','1200000']
timeout-minutes: 30
- name: Simplecov Report
if: matrix.build_type == 'backend'
run: COVERAGE=1 bin/rake plugin:spec[${{ github.event.repository.name }}]

7
.gitignore gevendort
Datei anzeigen

@ -1,2 +1,7 @@
coverage/* coverage/*
!coverage/.last_run.json !coverage/.last_run.json
gems/
.bundle/
auto_generated
.DS_Store
node_modules/

1
.prettierrc Normale Datei
Datei anzeigen

@ -0,0 +1 @@
{}

2
.rubocop.yml Normale Datei
Datei anzeigen

@ -0,0 +1,2 @@
inherit_gem:
rubocop-discourse: default.yml

4
.template-lintrc.js Normale Datei
Datei anzeigen

@ -0,0 +1,4 @@
module.exports = {
plugins: ["ember-template-lint-plugin-discourse"],
extends: "discourse:recommended",
};

7
Gemfile Normale Datei
Datei anzeigen

@ -0,0 +1,7 @@
# frozen_string_literal: true
source 'https://rubygems.org'
group :development do
gem 'rubocop-discourse'
end

38
Gemfile.lock Normale Datei
Datei anzeigen

@ -0,0 +1,38 @@
GEM
remote: https://rubygems.org/
specs:
ast (2.4.2)
parallel (1.20.1)
parser (3.0.1.0)
ast (~> 2.4.1)
rainbow (3.0.0)
regexp_parser (2.1.1)
rexml (3.2.5)
rubocop (1.12.1)
parallel (~> 1.10)
parser (>= 3.0.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml
rubocop-ast (>= 1.2.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.4.1)
parser (>= 2.7.1.5)
rubocop-discourse (2.4.1)
rubocop (>= 1.1.0)
rubocop-rspec (>= 2.0.0)
rubocop-rspec (2.2.0)
rubocop (~> 1.0)
rubocop-ast (>= 1.1.0)
ruby-progressbar (1.11.0)
unicode-display_width (2.0.0)
PLATFORMS
ruby
DEPENDENCIES
rubocop-discourse
BUNDLED WITH
2.2.16

Datei anzeigen

@ -1,6 +1,7 @@
import Component from "@ember/component"; import Component from "@ember/component";
import discourseComputed, { observes } from "discourse-common/utils/decorators"; import discourseComputed, { observes } from "discourse-common/utils/decorators";
import { or, alias } from "@ember/object/computed"; import { alias, or } from "@ember/object/computed";
import I18n from "I18n";
const generateContent = function (array, type) { const generateContent = function (array, type) {
return array.map((key) => ({ return array.map((key) => ({
@ -34,7 +35,7 @@ export default Component.extend({
}, },
@discourseComputed("field.klass") @discourseComputed("field.klass")
serializerContent(klass, p2) { serializerContent(klass) {
const serializers = this.get(`${klass}Serializers`); const serializers = this.get(`${klass}Serializers`);
if (serializers) { if (serializers) {
@ -66,21 +67,27 @@ export default Component.extend({
"field.serializers" "field.serializers"
) )
saveDisabled(saving) { saveDisabled(saving) {
if (saving) return true; if (saving) {
return true;
}
const originalField = this.originalField; const originalField = this.originalField;
if (!originalField) return false; if (!originalField) {
return false;
}
return ["name", "klass", "type", "serializers"].every((attr) => { return ["name", "klass", "type", "serializers"].every((attr) => {
let current = this.get(attr); let current = this.get(attr);
let original = originalField[attr]; let original = originalField[attr];
if (!current) return false; if (!current) {
return false;
}
if (attr == "serializers") { if (attr === "serializers") {
return this.compareArrays(current, original); return this.compareArrays(current, original);
} else { } else {
return current == original; return current === original;
} }
}); });
}, },

Datei anzeigen

@ -7,7 +7,9 @@ export default Component.extend({
@discourseComputed("showAdvanced") @discourseComputed("showAdvanced")
toggleClass(showAdvanced) { toggleClass(showAdvanced) {
let classes = "btn"; let classes = "btn";
if (showAdvanced) classes += " btn-primary"; if (showAdvanced) {
classes += " btn-primary";
}
return classes; return classes;
}, },

Datei anzeigen

@ -1,11 +1,10 @@
import { default as discourseComputed } from "discourse-common/utils/decorators"; import { default as discourseComputed } from "discourse-common/utils/decorators";
import { equal, empty, or, and } from "@ember/object/computed"; import { and, empty, equal, or } from "@ember/object/computed";
import { generateName, selectKitContent } from "../lib/wizard"; import { notificationLevels, selectKitContent } from "../lib/wizard";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import wizardSchema from "../lib/wizard-schema"; import wizardSchema from "../lib/wizard-schema";
import UndoChanges from "../mixins/undo-changes"; import UndoChanges from "../mixins/undo-changes";
import Component from "@ember/component"; import Component from "@ember/component";
import { notificationLevels } from "../lib/wizard";
import I18n from "I18n"; import I18n from "I18n";
export default Component.extend(UndoChanges, { export default Component.extend(UndoChanges, {
@ -43,7 +42,7 @@ export default Component.extend(UndoChanges, {
name: I18n.t(`admin.wizard.action.${type}.label`), name: I18n.t(`admin.wizard.action.${type}.label`),
}; };
}), }),
availableNotificationLevels: notificationLevels.map((type, index) => { availableNotificationLevels: notificationLevels.map((type) => {
return { return {
id: type, id: type,
name: I18n.t( name: I18n.t(
@ -92,7 +91,9 @@ export default Component.extend(UndoChanges, {
@discourseComputed("apis", "action.api") @discourseComputed("apis", "action.api")
availableEndpoints(apis, api) { availableEndpoints(apis, api) {
if (!api) return []; if (!api) {
return [];
}
return apis.find((a) => a.name === api).endpoints; return apis.find((a) => a.name === api).endpoints;
}, },
}); });

Datei anzeigen

@ -1,5 +1,5 @@
import { default as discourseComputed } from "discourse-common/utils/decorators"; import { default as discourseComputed } from "discourse-common/utils/decorators";
import { equal, or, alias } from "@ember/object/computed"; import { alias, equal, or } from "@ember/object/computed";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { selectKitContent } from "../lib/wizard"; import { selectKitContent } from "../lib/wizard";
import UndoChanges from "../mixins/undo-changes"; import UndoChanges from "../mixins/undo-changes";
@ -107,6 +107,40 @@ export default Component.extend(UndoChanges, {
return this.setupTypeOutput(fieldType, options); return this.setupTypeOutput(fieldType, options);
}, },
@discourseComputed("step.index")
fieldConditionOptions(stepIndex) {
const options = {
inputTypes: "validation",
context: "field",
textSelection: "value",
userFieldSelection: true,
groupSelection: true,
};
if (stepIndex > 0) {
options.wizardFieldSelection = true;
options.wizardActionSelection = true;
}
return options;
},
@discourseComputed("step.index")
fieldIndexOptions(stepIndex) {
const options = {
context: "field",
userFieldSelection: true,
groupSelection: true,
};
if (stepIndex > 0) {
options.wizardFieldSelection = true;
options.wizardActionSelection = true;
}
return options;
},
actions: { actions: {
imageUploadDone(upload) { imageUploadDone(upload) {
this.set("field.image", upload.url); this.set("field.image", upload.url);

Datei anzeigen

@ -1,9 +1,27 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { default as discourseComputed } from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
export default Component.extend({ export default Component.extend({
classNames: "wizard-custom-step", classNames: "wizard-custom-step",
@discourseComputed("step.index")
stepConditionOptions(stepIndex) {
const options = {
inputTypes: "validation",
context: "step",
textSelection: "value",
userFieldSelection: true,
groupSelection: true,
};
if (stepIndex > 0) {
options["wizardFieldSelection"] = true;
options["wizardActionSelection"] = true;
}
return options;
},
actions: { actions: {
bannerUploadDone(upload) { bannerUploadDone(upload) {
this.set("step.banner", upload.url); this.set("step.banner", upload.url);

Datei anzeigen

@ -1,15 +1,15 @@
import { import {
default as discourseComputed, default as discourseComputed,
on,
observes, observes,
on,
} from "discourse-common/utils/decorators"; } from "discourse-common/utils/decorators";
import { generateName } from "../lib/wizard"; import { generateName } from "../lib/wizard";
import { import {
default as wizardSchema,
setWizardDefaults, setWizardDefaults,
default as wizardSchema,
} from "../lib/wizard-schema"; } from "../lib/wizard-schema";
import { notEmpty } from "@ember/object/computed"; import { notEmpty } from "@ember/object/computed";
import { scheduleOnce, bind } from "@ember/runloop"; import { scheduleOnce } from "@ember/runloop";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
import { A } from "@ember/array"; import { A } from "@ember/array";
@ -38,6 +38,7 @@ export default Component.extend({
const items = this.items; const items = this.items;
const item = items.findBy("id", itemId); const item = items.findBy("id", itemId);
items.removeObject(item); items.removeObject(item);
item.set("index", newIndex);
items.insertAt(newIndex, item); items.insertAt(newIndex, item);
scheduleOnce("afterRender", this, () => this.applySortable()); scheduleOnce("afterRender", this, () => this.applySortable());
}, },
@ -53,7 +54,9 @@ export default Component.extend({
"items.@each.title" "items.@each.title"
) )
links(current, items) { links(current, items) {
if (!items) return; if (!items) {
return;
}
return items.map((item) => { return items.map((item) => {
if (item) { if (item) {
@ -88,22 +91,14 @@ export default Component.extend({
params.isNew = true; params.isNew = true;
let next = 1; let index = 0;
if (items.length) { if (items.length) {
next = index = items.length;
Math.max.apply(
Math,
items.map((i) => {
let parts = i.id.split("_");
let lastPart = parts[parts.length - 1];
return isNaN(lastPart) ? 0 : lastPart;
})
) + 1;
} }
let id = `${itemType}_${next}`; params.index = index;
let id = `${itemType}_${index + 1}`;
if (itemType === "field") { if (itemType === "field") {
id = `${this.parentId}_${id}`; id = `${this.parentId}_${id}`;
} }

Datei anzeigen

@ -3,7 +3,6 @@ import { gt } from "@ember/object/computed";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { defaultConnector } from "../lib/wizard-mapper"; import { defaultConnector } from "../lib/wizard-mapper";
import { later } from "@ember/runloop"; import { later } from "@ember/runloop";
import { observes } from "discourse-common/utils/decorators";
import I18n from "I18n"; import I18n from "I18n";
export default Component.extend({ export default Component.extend({

Datei anzeigen

@ -1,11 +1,11 @@
import { computed, set } from "@ember/object"; import { computed, set } from "@ember/object";
import { alias, equal, or, not } from "@ember/object/computed"; import { alias, equal, not, or } from "@ember/object/computed";
import { import {
newPair,
connectorContent, connectorContent,
inputTypesContent,
defaultSelectionType,
defaultConnector, defaultConnector,
defaultSelectionType,
inputTypesContent,
newPair,
} from "../lib/wizard-mapper"; } from "../lib/wizard-mapper";
import Component from "@ember/component"; import Component from "@ember/component";
import { observes } from "discourse-common/utils/decorators"; import { observes } from "discourse-common/utils/decorators";

Datei anzeigen

@ -1,6 +1,6 @@
import { connectorContent } from "../lib/wizard-mapper"; import { connectorContent } from "../lib/wizard-mapper";
import { gt, or, alias } from "@ember/object/computed"; import { alias, gt } from "@ember/object/computed";
import { computed, observes } from "@ember/object"; import { computed } from "@ember/object";
import Component from "@ember/component"; import Component from "@ember/component";
export default Component.extend({ export default Component.extend({

Datei anzeigen

@ -1,13 +1,12 @@
import { alias, or, gt } from "@ember/object/computed"; import { alias, gt, or } from "@ember/object/computed";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import { import {
default as discourseComputed, default as discourseComputed,
observes, observes,
on,
} from "discourse-common/utils/decorators"; } from "discourse-common/utils/decorators";
import { getOwner } from "discourse-common/lib/get-owner"; import { getOwner } from "discourse-common/lib/get-owner";
import { defaultSelectionType, selectionTypes } from "../lib/wizard-mapper"; import { defaultSelectionType, selectionTypes } from "../lib/wizard-mapper";
import { snakeCase, generateName, userProperties } from "../lib/wizard"; import { generateName, snakeCase, userProperties } from "../lib/wizard";
import Component from "@ember/component"; import Component from "@ember/component";
import { bind, later } from "@ember/runloop"; import { bind, later } from "@ember/runloop";
import I18n from "I18n"; import I18n from "I18n";
@ -135,7 +134,9 @@ export default Component.extend({
}, },
documentClick(e) { documentClick(e) {
if (this._state == "destroying") return; if (this._state === "destroying") {
return;
}
let $target = $(e.target); let $target = $(e.target);
if (!$target.parents(".type-selector").length && this.showTypes) { if (!$target.parents(".type-selector").length && this.showTypes) {
@ -249,7 +250,7 @@ export default Component.extend({
}, },
@discourseComputed("activeType", "inputType") @discourseComputed("activeType", "inputType")
placeholderKey(activeType, inputType) { placeholderKey(activeType) {
if ( if (
activeType === "text" && activeType === "text" &&
this.options[`${this.selectorType}Placeholder`] this.options[`${this.selectorType}Placeholder`]
@ -275,14 +276,20 @@ export default Component.extend({
optionEnabled(type) { optionEnabled(type) {
const options = this.options; const options = this.options;
if (!options) return false; if (!options) {
return false;
}
const option = options[type]; const option = options[type];
if (option === true) return true; if (option === true) {
if (typeof option !== "string") return false; return true;
}
if (typeof option !== "string") {
return false;
}
return option.split(",").filter((option) => { return option.split(",").filter((o) => {
return [this.selectorType, this.inputType].indexOf(option) !== -1; return [this.selectorType, this.inputType].indexOf(o) !== -1;
}).length; }).length;
}, },

Datei anzeigen

@ -1,10 +1,5 @@
import { getOwner } from "discourse-common/lib/get-owner";
import { newInput, selectionTypes } from "../lib/wizard-mapper"; import { newInput, selectionTypes } from "../lib/wizard-mapper";
import { import discourseComputed from "discourse-common/utils/decorators";
default as discourseComputed,
observes,
on,
} from "discourse-common/utils/decorators";
import { later } from "@ember/runloop"; import { later } from "@ember/runloop";
import Component from "@ember/component"; import Component from "@ember/component";
import { A } from "@ember/array"; import { A } from "@ember/array";

Datei anzeigen

@ -19,7 +19,9 @@ export default Component.extend({
init() { init() {
this._super(...arguments); this._super(...arguments);
if (!this.validations) return; if (!this.validations) {
return;
}
if (!this.field.validations) { if (!this.field.validations) {
const validations = {}; const validations = {};

Datei anzeigen

@ -1,7 +1,4 @@
import { import discourseComputed from "discourse-common/utils/decorators";
default as discourseComputed,
on,
} from "discourse-common/utils/decorators";
import { notEmpty } from "@ember/object/computed"; import { notEmpty } from "@ember/object/computed";
import { userProperties } from "../lib/wizard"; import { userProperties } from "../lib/wizard";
import { scheduleOnce } from "@ember/runloop"; import { scheduleOnce } from "@ember/runloop";

Datei anzeigen

@ -1,3 +1,3 @@
{{#if currentUser.admin}} {{#if currentUser.admin}}
{{nav-item route='adminWizards' label='admin.wizard.nav_label'}} {{nav-item route="adminWizards" label="admin.wizard.nav_label"}}
{{/if}} {{/if}}

Datei anzeigen

@ -1,7 +1,7 @@
{{#each site.complete_custom_wizard as |wizard|}} {{#each site.complete_custom_wizard as |wizard|}}
<div class='row'> <div class="row">
<div class='alert alert-info alert-wizard'> <div class="alert alert-info alert-wizard">
<a href="{{wizard.url}}">{{i18n 'wizard.complete_custom' name=wizard.name}}</a> <a href={{wizard.url}}>{{i18n "wizard.complete_custom" name=wizard.name}}</a>
</div> </div>
</div> </div>
{{/each}} {{/each}}

Datei anzeigen

@ -2,7 +2,7 @@ import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
import CustomWizardApi from "../models/custom-wizard-api"; import CustomWizardApi from "../models/custom-wizard-api";
import { default as discourseComputed } from "discourse-common/utils/decorators"; import { default as discourseComputed } from "discourse-common/utils/decorators";
import { not, and, equal } from "@ember/object/computed"; import { and, equal, not } from "@ember/object/computed";
import { selectKitContent } from "../lib/wizard"; import { selectKitContent } from "../lib/wizard";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import I18n from "I18n"; import I18n from "I18n";
@ -63,9 +63,12 @@ export default Controller.extend({
clientSecret, clientSecret,
threeLeggedOauth threeLeggedOauth
) { ) {
if (saveDisabled || !authType || !tokenUrl || !clientId || !clientSecret) if (saveDisabled || !authType || !tokenUrl || !clientId || !clientSecret) {
return true; return true;
if (threeLeggedOauth) return !authUrl; }
if (threeLeggedOauth) {
return !authUrl;
}
return false; return false;
}, },
@ -146,16 +149,20 @@ export default Controller.extend({
const api = this.get("api"); const api = this.get("api");
const name = api.name; const name = api.name;
const authType = api.authType; const authType = api.authType;
let refreshList = false; let refreshList = false; // eslint-disable-line
let error; let error;
if (!name || !authType) return; if (!name || !authType) {
return;
}
let data = { let data = {
auth_type: authType, auth_type: authType,
}; };
if (api.title) data["title"] = api.title; if (api.title) {
data["title"] = api.title;
}
const originalTitle = this.get("api.originalTitle"); const originalTitle = this.get("api.originalTitle");
if (api.get("isNew") || (originalTitle && api.title !== originalTitle)) { if (api.get("isNew") || (originalTitle && api.title !== originalTitle)) {
@ -232,7 +239,9 @@ export default Controller.extend({
remove() { remove() {
const name = this.get("api.name"); const name = this.get("api.name");
if (!name) return; if (!name) {
return;
}
this.set("updating", true); this.set("updating", true);
@ -250,7 +259,9 @@ export default Controller.extend({
clearLogs() { clearLogs() {
const name = this.get("api.name"); const name = this.get("api.name");
if (!name) return; if (!name) {
return;
}
ajax(`/admin/wizards/api/${name.underscore()}/logs`, { ajax(`/admin/wizards/api/${name.underscore()}/logs`, {
type: "DELETE", type: "DELETE",

Datei anzeigen

@ -1,9 +1,5 @@
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import EmberObject from "@ember/object";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import CustomWizardCustomField from "../models/custom-wizard-custom-field"; import CustomWizardCustomField from "../models/custom-wizard-custom-field";
import { default as discourseComputed } from "discourse-common/utils/decorators";
export default Controller.extend({ export default Controller.extend({
messageKey: "create", messageKey: "create",
@ -49,7 +45,7 @@ export default Controller.extend({
}, },
removeField(field) { removeField(field) {
return CustomWizardCustomField.destroyField(field).then((result) => { return CustomWizardCustomField.destroyField(field).then(() => {
this.get("customFields").removeObject(field); this.get("customFields").removeObject(field);
}); });
}, },

Datei anzeigen

@ -1,6 +1,4 @@
import { default as computed } from "discourse-common/utils/decorators"; import discourseComputed from "discourse-common/utils/decorators";
import { popupAjaxError } from "discourse/lib/ajax-error";
import { ajax } from "discourse/lib/ajax";
import { notEmpty } from "@ember/object/computed"; import { notEmpty } from "@ember/object/computed";
import CustomWizardLogs from "../models/custom-wizard-logs"; import CustomWizardLogs from "../models/custom-wizard-logs";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
@ -13,7 +11,9 @@ export default Controller.extend({
logs: [], logs: [],
loadLogs() { loadLogs() {
if (!this.canLoadMore) return; if (!this.canLoadMore) {
return;
}
this.set("refreshing", true); this.set("refreshing", true);
@ -27,7 +27,7 @@ export default Controller.extend({
.finally(() => this.set("refreshing", false)); .finally(() => this.set("refreshing", false));
}, },
@computed("hasLogs", "refreshing") @discourseComputed("hasLogs", "refreshing")
noResults(hasLogs, refreshing) { noResults(hasLogs, refreshing) {
return !hasLogs && !refreshing; return !hasLogs && !refreshing;
}, },

Datei anzeigen

@ -1,8 +1,5 @@
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import { import { observes } from "discourse-common/utils/decorators";
default as discourseComputed,
observes,
} from "discourse-common/utils/decorators";
import { empty } from "@ember/object/computed"; import { empty } from "@ember/object/computed";
import CustomWizardManager from "../models/custom-wizard-manager"; import CustomWizardManager from "../models/custom-wizard-manager";
import { A } from "@ember/array"; import { A } from "@ember/array";
@ -196,7 +193,7 @@ export default Controller.extend({
}, },
destroy() { destroy() {
const destroyWizards = this.get("destroyWizards"); let destroyWizards = this.get("destroyWizards");
if (!destroyWizards.length) { if (!destroyWizards.length) {
this.setMessage("error", "none_selected"); this.setMessage("error", "none_selected");
@ -227,7 +224,7 @@ export default Controller.extend({
if (result.destroyed.length) { if (result.destroyed.length) {
const destroyedIds = result.destroyed.map((d) => d.id); const destroyedIds = result.destroyed.map((d) => d.id);
const destroyWizards = this.get("destroyWizards"); destroyWizards = this.get("destroyWizards");
const wizards = this.get("wizards"); const wizards = this.get("wizards");
wizards.removeObjects( wizards.removeObjects(

Datei anzeigen

@ -1,18 +1,14 @@
import { import {
default as discourseComputed, default as discourseComputed,
observes, observes,
on,
} from "discourse-common/utils/decorators"; } from "discourse-common/utils/decorators";
import { notEmpty, alias } from "@ember/object/computed"; import { notEmpty } from "@ember/object/computed";
import showModal from "discourse/lib/show-modal"; import showModal from "discourse/lib/show-modal";
import { generateId, wizardFieldList } from "../lib/wizard"; import { generateId, wizardFieldList } from "../lib/wizard";
import { buildProperties } from "../lib/wizard-json";
import { dasherize } from "@ember/string"; import { dasherize } from "@ember/string";
import EmberObject from "@ember/object"; import { later, scheduleOnce } from "@ember/runloop";
import { scheduleOnce, later } from "@ember/runloop";
import Controller from "@ember/controller"; import Controller from "@ember/controller";
import copyText from "discourse/lib/copy-text"; import copyText from "discourse/lib/copy-text";
import CustomWizard from "../models/custom-wizard";
import I18n from "I18n"; import I18n from "I18n";
export default Controller.extend({ export default Controller.extend({

Datei anzeigen

@ -1,4 +1,3 @@
import { withPluginApi } from "discourse/lib/plugin-api";
import DiscourseURL from "discourse/lib/url"; import DiscourseURL from "discourse/lib/url";
export default { export default {
@ -6,7 +5,9 @@ export default {
initialize(container) { initialize(container) {
const siteSettings = container.lookup("site-settings:main"); const siteSettings = container.lookup("site-settings:main");
if (!siteSettings.custom_wizard_enabled) return; if (!siteSettings.custom_wizard_enabled) {
return;
}
const existing = DiscourseURL.routeTo; const existing = DiscourseURL.routeTo;
DiscourseURL.routeTo = function (path, opts) { DiscourseURL.routeTo = function (path, opts) {

Datei anzeigen

@ -8,7 +8,9 @@ export default {
const messageBus = container.lookup("message-bus:main"); const messageBus = container.lookup("message-bus:main");
const siteSettings = container.lookup("site-settings:main"); const siteSettings = container.lookup("site-settings:main");
if (!siteSettings.custom_wizard_enabled || !messageBus) return; if (!siteSettings.custom_wizard_enabled || !messageBus) {
return;
}
messageBus.subscribe("/redirect_to_wizard", function (wizardId) { messageBus.subscribe("/redirect_to_wizard", function (wizardId) {
const wizardUrl = window.location.origin + "/w/" + wizardId; const wizardUrl = window.location.origin + "/w/" + wizardId;

Datei anzeigen

@ -1,4 +1,4 @@
import { listProperties, camelCase, snakeCase } from "../lib/wizard"; import { camelCase, listProperties } from "../lib/wizard";
import wizardSchema from "../lib/wizard-schema"; import wizardSchema from "../lib/wizard-schema";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { A } from "@ember/array"; import { A } from "@ember/array";
@ -23,54 +23,69 @@ function castCase(property, value) {
return property.indexOf("_type") > -1 ? camelCase(value) : value; return property.indexOf("_type") > -1 ? camelCase(value) : value;
} }
function buildProperty(json, property, type) { function buildMappedProperty(value) {
let value = json[property]; let inputs = [];
if (mapped(property, type) && present(value) && value.constructor === Array) { value.forEach((inputJson) => {
let inputs = []; let input = {};
value.forEach((inputJson) => { Object.keys(inputJson).forEach((inputKey) => {
let input = {}; if (inputKey === "pairs") {
let pairs = [];
let pairCount = inputJson.pairs.length;
Object.keys(inputJson).forEach((inputKey) => { inputJson.pairs.forEach((pairJson) => {
if (inputKey === "pairs") { let pair = {};
let pairs = [];
let pairCount = inputJson.pairs.length;
inputJson.pairs.forEach((pairJson) => { Object.keys(pairJson).forEach((pairKey) => {
let pair = {}; pair[pairKey] = castCase(pairKey, pairJson[pairKey]);
Object.keys(pairJson).forEach((pairKey) => {
pair[pairKey] = castCase(pairKey, pairJson[pairKey]);
});
pair.pairCount = pairCount;
pairs.push(EmberObject.create(pair));
}); });
input.pairs = pairs; pair.pairCount = pairCount;
} else {
input[inputKey] = castCase(inputKey, inputJson[inputKey]);
}
});
inputs.push(EmberObject.create(input)); pairs.push(EmberObject.create(pair));
});
input.pairs = pairs;
} else {
input[inputKey] = castCase(inputKey, inputJson[inputKey]);
}
}); });
return A(inputs); inputs.push(EmberObject.create(input));
} else { });
return value;
} return A(inputs);
} }
function buildObject(json, type) { function buildProperty(json, property, type, objectIndex) {
let value = json[property];
if (
property === "index" &&
(value === null || value === undefined) &&
(objectIndex !== null || objectIndex !== undefined)
) {
return objectIndex;
}
if (
!mapped(property, type) ||
!present(value) ||
!value.constructor === Array
) {
return value;
}
return buildMappedProperty(value);
}
function buildObject(json, type, objectIndex) {
let props = { let props = {
isNew: false, isNew: false,
}; };
Object.keys(json).forEach((prop) => { Object.keys(json).forEach((prop) => {
props[prop] = buildProperty(json, prop, type); props[prop] = buildProperty(json, prop, type, objectIndex);
}); });
return EmberObject.create(props); return EmberObject.create(props);
@ -80,8 +95,8 @@ function buildObjectArray(json, type) {
let array = A(); let array = A();
if (present(json)) { if (present(json)) {
json.forEach((objJson) => { json.forEach((objJson, objectIndex) => {
let object = buildObject(objJson, type); let object = buildObject(objJson, type, objectIndex);
if (hasAdvancedProperties(object, type)) { if (hasAdvancedProperties(object, type)) {
object.set("showAdvanced", true); object.set("showAdvanced", true);
@ -94,9 +109,9 @@ function buildObjectArray(json, type) {
return array; return array;
} }
function buildBasicProperties(json, type, props) { function buildBasicProperties(json, type, props, objectIndex = null) {
listProperties(type).forEach((p) => { listProperties(type).forEach((p) => {
props[p] = buildProperty(json, p, type); props[p] = buildProperty(json, p, type, objectIndex);
if (hasAdvancedProperties(json, type)) { if (hasAdvancedProperties(json, type)) {
props.showAdvanced = true; props.showAdvanced = true;
@ -142,12 +157,17 @@ function buildProperties(json) {
props = buildBasicProperties(json, "wizard", props); props = buildBasicProperties(json, "wizard", props);
if (present(json.steps)) { if (present(json.steps)) {
json.steps.forEach((stepJson) => { json.steps.forEach((stepJson, objectIndex) => {
let stepProps = { let stepProps = {
isNew: false, isNew: false,
}; };
stepProps = buildBasicProperties(stepJson, "step", stepProps); stepProps = buildBasicProperties(
stepJson,
"step",
stepProps,
objectIndex
);
stepProps.fields = buildObjectArray(stepJson.fields, "field"); stepProps.fields = buildObjectArray(stepJson.fields, "field");
props.steps.pushObject(EmberObject.create(stepProps)); props.steps.pushObject(EmberObject.create(stepProps));

Datei anzeigen

@ -4,6 +4,13 @@ import I18n from "I18n";
// Inputs // Inputs
const selectableInputTypes = [
"conditional",
"assignment",
"association",
"validation",
];
function defaultInputType(options = {}) { function defaultInputType(options = {}) {
return options.inputTypes.split(",")[0]; return options.inputTypes.split(",")[0];
} }
@ -43,13 +50,23 @@ function defaultConnector(connectorType, inputType, options = {}) {
return defaultInputType(options); return defaultInputType(options);
} }
if (connectorType === "pair") { if (connectorType === "pair") {
if (inputType === "conditional") return "equal"; if (inputType === "conditional") {
if (inputType === "association") return "association"; return "equal";
if (inputType === "validation") return "equal"; }
if (inputType === "association") {
return "association";
}
if (inputType === "validation") {
return "equal";
}
} }
if (connectorType === "output") { if (connectorType === "output") {
if (inputType === "conditional") return "then"; if (inputType === "conditional") {
if (inputType === "assignment") return "set"; return "then";
}
if (inputType === "assignment") {
return "set";
}
} }
return "equal"; return "equal";
} }

Datei anzeigen

@ -1,4 +1,4 @@
import { set, get } from "@ember/object"; import { get, set } from "@ember/object";
const wizard = { const wizard = {
basic: { basic: {
@ -37,6 +37,7 @@ const wizard = {
const step = { const step = {
basic: { basic: {
id: null, id: null,
index: null,
title: null, title: null,
key: null, key: null,
banner: null, banner: null,
@ -44,9 +45,11 @@ const step = {
required_data: null, required_data: null,
required_data_message: null, required_data_message: null,
permitted_params: null, permitted_params: null,
condition: null,
force_final: false,
}, },
mapped: ["required_data", "permitted_params"], mapped: ["required_data", "permitted_params", "condition", "index"],
advanced: ["required_data", "permitted_params"], advanced: ["required_data", "permitted_params", "condition", "index"],
required: ["id"], required: ["id"],
dependent: {}, dependent: {},
objectArrays: { objectArrays: {
@ -60,16 +63,18 @@ const step = {
const field = { const field = {
basic: { basic: {
id: null, id: null,
index: null,
label: null, label: null,
image: null, image: null,
description: null, description: null,
required: null, required: null,
key: null, key: null,
type: null, type: null,
condition: null,
}, },
types: {}, types: {},
mapped: ["prefill", "content"], mapped: ["prefill", "content", "condition", "index"],
advanced: ["property", "key"], advanced: ["property", "key", "condition", "index"],
required: ["id", "type"], required: ["id", "type"],
dependent: {}, dependent: {},
objectArrays: {}, objectArrays: {},
@ -225,7 +230,7 @@ if (Discourse.SiteSettings.wizard_apis_enabled) {
}; };
} }
export function setWizardDefaults(obj, itemType, opts = {}) { export function setWizardDefaults(obj, itemType) {
const objSchema = wizardSchema[itemType]; const objSchema = wizardSchema[itemType];
const basicDefaults = objSchema.basic; const basicDefaults = objSchema.basic;

Datei anzeigen

@ -9,7 +9,7 @@ function generateName(id) {
return id ? sentenceCase(id) : ""; return id ? sentenceCase(id) : "";
} }
function generateId(name, opts = {}) { function generateId(name) {
return name ? snakeCase(name) : ""; return name ? snakeCase(name) : "";
} }
@ -60,10 +60,10 @@ const notificationLevels = [
"muted", "muted",
]; ];
function listProperties(type, opts = {}) { function listProperties(itemType, opts = {}) {
let properties = Object.keys(wizardSchema[type].basic); let properties = Object.keys(wizardSchema[itemType].basic);
const types = wizardSchema[type].types; const types = wizardSchema[itemType].types;
if (types) { if (types) {
let typeProperties = []; let typeProperties = [];

Datei anzeigen

@ -1,8 +1,7 @@
import { listProperties } from "../lib/wizard"; import { listProperties } from "../lib/wizard";
import { default as wizardSchema } from "../lib/wizard-schema"; import { default as wizardSchema } from "../lib/wizard-schema";
import { set, get } from "@ember/object"; import { get, set } from "@ember/object";
import Mixin from "@ember/object/mixin"; import Mixin from "@ember/object/mixin";
import { observes } from "discourse-common/utils/decorators";
import { deepEqual } from "discourse-common/lib/object"; import { deepEqual } from "discourse-common/lib/object";
export default Mixin.create({ export default Mixin.create({
@ -97,7 +96,6 @@ export default Mixin.create({
actions: { actions: {
undoChanges() { undoChanges() {
const componentType = this.componentType; const componentType = this.componentType;
const original = this.get("originalObject");
const obj = this.get(componentType); const obj = this.get(componentType);
this.removeObservers(obj.type); this.removeObservers(obj.type);
@ -118,6 +116,7 @@ export default Mixin.create({
this.setupObservers(type); this.setupObservers(type);
}, },
// eslint-disable-next-line
mappedFieldUpdated(property, mappedComponent, type) { mappedFieldUpdated(property, mappedComponent, type) {
const obj = this.get(this.componentType); const obj = this.get(this.componentType);
obj.notifyPropertyChange(property); obj.notifyPropertyChange(property);

Datei anzeigen

@ -1,7 +1,7 @@
import { ajax } from "discourse/lib/ajax"; import { ajax } from "discourse/lib/ajax";
import EmberObject from "@ember/object"; import EmberObject from "@ember/object";
import { buildProperties, present, mapped } from "../lib/wizard-json"; import { buildProperties, mapped, present } from "../lib/wizard-json";
import { listProperties, camelCase, snakeCase } from "../lib/wizard"; import { listProperties, snakeCase } from "../lib/wizard";
import wizardSchema from "../lib/wizard-schema"; import wizardSchema from "../lib/wizard-schema";
import { Promise } from "rsvp"; import { Promise } from "rsvp";
import { popupAjaxError } from "discourse/lib/ajax-error"; import { popupAjaxError } from "discourse/lib/ajax-error";
@ -131,9 +131,15 @@ const CustomWizard = EmberObject.extend({
return result; return result;
}, },
buildMappedJson(inputs) { buildMappedJson(value) {
if (!inputs || !inputs.length) return false; if (typeof value === "string" || Number.isInteger(value)) {
return value;
}
if (!value || !value.length) {
return false;
}
let inputs = value;
let result = []; let result = [];
inputs.forEach((inpt) => { inputs.forEach((inpt) => {

Datei anzeigen

@ -8,7 +8,7 @@ export default DiscourseRoute.extend({
setupController(controller, model) { setupController(controller, model) {
const showParams = this.paramsFor("adminWizardsApiShow"); const showParams = this.paramsFor("adminWizardsApiShow");
const apiName = showParams.name == "create" ? null : showParams.name; const apiName = showParams.name === "create" ? null : showParams.name;
const apiList = (model || []).map((api) => { const apiList = (model || []).map((api) => {
return { return {
id: api.name, id: api.name,

Datei anzeigen

@ -1,5 +1,5 @@
<div class="wizard-api-header page"> <div class="wizard-api-header page">
<div class='buttons'> <div class="buttons">
{{#if updating}} {{#if updating}}
{{loading-spinner size="small"}} {{loading-spinner size="small"}}
{{else}} {{else}}
@ -23,7 +23,7 @@
<div class="wizard-header"> <div class="wizard-header">
{{#if api.isNew}} {{#if api.isNew}}
{{i18n 'admin.wizard.api.new'}} {{i18n "admin.wizard.api.new"}}
{{else}} {{else}}
{{api.title}} {{api.title}}
{{/if}} {{/if}}
@ -31,14 +31,14 @@
<div class="metadata"> <div class="metadata">
<div class="title"> <div class="title">
<label>{{i18n 'admin.wizard.api.title'}}</label> <label>{{i18n "admin.wizard.api.title"}}</label>
{{input value=api.title placeholder=(i18n 'admin.wizard.api.title_placeholder')}} {{input value=api.title placeholder=(i18n "admin.wizard.api.title_placeholder")}}
</div> </div>
<div class="name"> <div class="name">
<label>{{i18n 'admin.wizard.api.name'}}</label> <label>{{i18n "admin.wizard.api.name"}}</label>
{{#if api.isNew}} {{#if api.isNew}}
{{input value=api.name placeholder=(i18n 'admin.wizard.api.name_placeholder')}} {{input value=api.name placeholder=(i18n "admin.wizard.api.name_placeholder")}}
{{else}} {{else}}
{{api.name}} {{api.name}}
{{/if}} {{/if}}
@ -64,7 +64,7 @@
</div> </div>
<div class="wizard-header"> <div class="wizard-header">
{{i18n 'admin.wizard.api.auth.label'}} {{i18n "admin.wizard.api.auth.label"}}
</div> </div>
</div> </div>
@ -72,13 +72,13 @@
<div class="settings"> <div class="settings">
<div class="wizard-header medium"> <div class="wizard-header medium">
{{i18n 'admin.wizard.api.auth.settings'}} {{i18n "admin.wizard.api.auth.settings"}}
</div> </div>
{{#if showRedirectUri}} {{#if showRedirectUri}}
<div class="control-group redirect-uri"> <div class="control-group redirect-uri">
<div class="control-label"> <div class="control-label">
<label>{{i18n 'admin.wizard.api.auth.redirect_uri'}}</label> <label>{{i18n "admin.wizard.api.auth.redirect_uri"}}</label>
<div class="controls"> <div class="controls">
{{api.redirectUri}} {{api.redirectUri}}
</div> </div>
@ -87,14 +87,14 @@
{{/if}} {{/if}}
<div class="control-group auth-type"> <div class="control-group auth-type">
<label>{{i18n 'admin.wizard.api.auth.type'}}</label> <label>{{i18n "admin.wizard.api.auth.type"}}</label>
<div class="controls"> <div class="controls">
{{combo-box {{combo-box
value=api.authType value=api.authType
content=authorizationTypes content=authorizationTypes
onChange=(action (mut api.authType)) onChange=(action (mut api.authType))
options=(hash options=(hash
none='admin.wizard.api.auth.type_none' none="admin.wizard.api.auth.type_none"
)}} )}}
</div> </div>
</div> </div>
@ -102,7 +102,7 @@
{{#if isOauth}} {{#if isOauth}}
{{#if threeLeggedOauth}} {{#if threeLeggedOauth}}
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.auth.url'}}</label> <label>{{i18n "admin.wizard.api.auth.url"}}</label>
<div class="controls"> <div class="controls">
{{input value=api.authUrl}} {{input value=api.authUrl}}
</div> </div>
@ -110,51 +110,51 @@
{{/if}} {{/if}}
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.auth.token_url'}}</label> <label>{{i18n "admin.wizard.api.auth.token_url"}}</label>
<div class="controls"> <div class="controls">
{{input value=api.tokenUrl}} {{input value=api.tokenUrl}}
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.auth.client_id'}}</label> <label>{{i18n "admin.wizard.api.auth.client_id"}}</label>
<div class="controls"> <div class="controls">
{{input value=api.clientId}} {{input value=api.clientId}}
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.auth.client_secret'}}</label> <label>{{i18n "admin.wizard.api.auth.client_secret"}}</label>
<div class="controls"> <div class="controls">
{{input value=api.clientSecret}} {{input value=api.clientSecret}}
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.auth.params.label'}}</label> <label>{{i18n "admin.wizard.api.auth.params.label"}}</label>
<div class="controls"> <div class="controls">
{{#each api.authParams as |param|}} {{#each api.authParams as |param|}}
<div class="param"> <div class="param">
{{input value=param.key placeholder=(i18n 'admin.wizard.key')}} {{input value=param.key placeholder=(i18n "admin.wizard.key")}}
{{input value=param.value placeholder=(i18n 'admin.wizard.value')}} {{input value=param.value placeholder=(i18n "admin.wizard.value")}}
{{d-button action=(action "removeParam") actionParam=param icon='times'}} {{d-button action=(action "removeParam") actionParam=param icon="times"}}
</div> </div>
{{/each}} {{/each}}
{{d-button label='admin.wizard.api.auth.params.new' icon='plus' action=(action "addParam")}} {{d-button label="admin.wizard.api.auth.params.new" icon="plus" action=(action "addParam")}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if isBasicAuth}} {{#if isBasicAuth}}
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.auth.username'}}</label> <label>{{i18n "admin.wizard.api.auth.username"}}</label>
<div class="controls"> <div class="controls">
{{input value=api.username}} {{input value=api.username}}
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.auth.password'}}</label> <label>{{i18n "admin.wizard.api.auth.password"}}</label>
<div class="controls"> <div class="controls">
{{input value=api.password}} {{input value=api.password}}
</div> </div>
@ -175,12 +175,12 @@
</div> </div>
<div class="wizard-header medium"> <div class="wizard-header medium">
{{i18n 'admin.wizard.api.status.label'}} {{i18n "admin.wizard.api.status.label"}}
</div> </div>
{{#if threeLeggedOauth}} {{#if threeLeggedOauth}}
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.status.code'}}</label> <label>{{i18n "admin.wizard.api.status.code"}}</label>
<div class="controls"> <div class="controls">
{{api.code}} {{api.code}}
</div> </div>
@ -188,7 +188,7 @@
{{/if}} {{/if}}
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.status.access_token'}}</label> <label>{{i18n "admin.wizard.api.status.access_token"}}</label>
<div class="controls"> <div class="controls">
{{api.accessToken}} {{api.accessToken}}
</div> </div>
@ -196,7 +196,7 @@
{{#if threeLeggedOauth}} {{#if threeLeggedOauth}}
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.status.refresh_token'}}</label> <label>{{i18n "admin.wizard.api.status.refresh_token"}}</label>
<div class="controls"> <div class="controls">
{{api.refreshToken}} {{api.refreshToken}}
</div> </div>
@ -204,14 +204,14 @@
{{/if}} {{/if}}
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.status.expires_at'}}</label> <label>{{i18n "admin.wizard.api.status.expires_at"}}</label>
<div class="controls"> <div class="controls">
{{api.tokenExpiresAt}} {{api.tokenExpiresAt}}
</div> </div>
</div> </div>
<div class="control-group"> <div class="control-group">
<label>{{i18n 'admin.wizard.api.status.refresh_at'}}</label> <label>{{i18n "admin.wizard.api.status.refresh_at"}}</label>
<div class="controls"> <div class="controls">
{{api.tokenRefreshAt}} {{api.tokenRefreshAt}}
</div> </div>
@ -221,11 +221,11 @@
</div> </div>
<div class="wizard-header"> <div class="wizard-header">
{{i18n 'admin.wizard.api.endpoint.label'}} {{i18n "admin.wizard.api.endpoint.label"}}
</div> </div>
<div class="wizard-api-endpoints"> <div class="wizard-api-endpoints">
{{d-button action=(action "addEndpoint") label='admin.wizard.api.endpoint.add' icon='plus'}} {{d-button action=(action "addEndpoint") label="admin.wizard.api.endpoint.add" icon="plus"}}
{{#if api.endpoints}} {{#if api.endpoints}}
<div class="endpoint-list"> <div class="endpoint-list">
@ -236,14 +236,14 @@
<div class="endpoint-"> <div class="endpoint-">
<div class="top"> <div class="top">
{{input value=endpoint.name {{input value=endpoint.name
placeholder=(i18n 'admin.wizard.api.endpoint.name')}} placeholder=(i18n "admin.wizard.api.endpoint.name")}}
{{input value=endpoint.url {{input value=endpoint.url
placeholder=(i18n 'admin.wizard.api.endpoint.url') placeholder=(i18n "admin.wizard.api.endpoint.url")
class='endpoint-url'}} class="endpoint-url"}}
{{d-button action=(action "removeEndpoint") {{d-button action=(action "removeEndpoint")
actionParam=endpoint actionParam=endpoint
icon='times' icon="times"
class='remove-endpoint'}} class="remove-endpoint"}}
</div> </div>
<div class="bottom"> <div class="bottom">
{{combo-box {{combo-box
@ -278,33 +278,37 @@
</div> </div>
<div class="wizard-header"> <div class="wizard-header">
{{i18n 'admin.wizard.api.log.label'}} {{i18n "admin.wizard.api.log.label"}}
{{d-button action=(action "clearLogs") {{d-button action=(action "clearLogs")
icon='trash-alt' icon="trash-alt"
class='clear-logs'}} class="clear-logs"}}
</div> </div>
<div class="wizard-api-log"> <div class="wizard-api-log">
<div class="log-list"> <div class="log-list">
<table class="wizard-api-log-table"> <table class="wizard-api-log-table">
<th>Datetime</th> <thead>
<th>User</th> <th>Datetime</th>
<th>Status</th> <th>User</th>
<th>URL</th> <th>Status</th>
<th>Error</th> <th>URL</th>
{{#each api.log as |logentry|}} <th>Error</th>
<tr> </thead>
<td>{{logentry.time}}</td> <tbody>
<td class="user-image"> {{#each api.log as |logentry|}}
<div class="user-image-inner"> <tr>
<a href="{{unbound logentry.userpath}}" data-user-card="{{unbound logentry.username}}">{{avatar logentry imageSize="large"}}</a> <td>{{logentry.time}}</td>
</div> <td class="user-image">
</td> <div class="user-image-inner">
<td>{{logentry.status}}</td> <a href={{logentry.userpath}} data-user-card={{logentry.username}}>{{avatar logentry imageSize="large"}}</a>
<td>{{logentry.url}}</td> </div>
<td>{{logentry.error}}</td> </td>
</tr> <td>{{logentry.status}}</td>
{{/each}} <td>{{logentry.url}}</td>
<td>{{logentry.error}}</td>
</tr>
{{/each}}
</tbody>
</table> </table>
</div> </div>
</div> </div>

Datei anzeigen

@ -2,11 +2,11 @@
{{combo-box {{combo-box
value=apiName value=apiName
content=apiList content=apiList
onChange=(route-action 'changeApi') onChange=(route-action "changeApi")
options=(hash options=(hash
none='admin.wizard.api.select' none="admin.wizard.api.select"
)}} )}}
{{d-button {{d-button
action="createApi" action="createApi"
label="admin.wizard.api.create" label="admin.wizard.api.create"

Datei anzeigen

@ -1,6 +1,6 @@
<div class="admin-wizard-controls"> <div class="admin-wizard-controls">
<h3>{{i18n 'admin.wizard.custom_field.nav_label'}}</h3> <h3>{{i18n "admin.wizard.custom_field.nav_label"}}</h3>
<div class="buttons"> <div class="buttons">
{{d-button {{d-button
label="admin.wizard.custom_field.add" label="admin.wizard.custom_field.add"
@ -14,23 +14,27 @@
opts=messageOpts opts=messageOpts
type=messageType type=messageType
url=documentationUrl url=documentationUrl
component='custom_fields'}} component="custom_fields"}}
<div class="admin-wizard-container"> <div class="admin-wizard-container">
{{#if customFields}} {{#if customFields}}
<table> <table>
<tr> <thead>
{{#each fieldKeys as |key|}} <tr>
<th>{{i18n (concat "admin.wizard.custom_field." key ".label")}}</th> {{#each fieldKeys as |key|}}
<th>{{i18n (concat "admin.wizard.custom_field." key ".label")}}</th>
{{/each}}
<th></th>
</tr>
</thead>
<tbody>
{{#each customFields as |field|}}
{{custom-field-input
field=field
removeField=(action "removeField")
saveField=(action "saveField")}}
{{/each}} {{/each}}
<th></th> </tbody>
</tr>
{{#each customFields as |field|}}
{{custom-field-input
field=field
removeField=(action 'removeField')
saveField=(action 'saveField')}}
{{/each}}
</table> </table>
{{/if}} {{/if}}
</div> </div>

Datei anzeigen

@ -1,6 +1,6 @@
<div class="admin-wizard-controls"> <div class="admin-wizard-controls">
<h3>{{i18n 'admin.wizard.log.nav_label'}}</h3> <h3>{{i18n "admin.wizard.log.nav_label"}}</h3>
{{d-button {{d-button
label="refresh" label="refresh"
icon="refresh" icon="refresh"
@ -10,7 +10,7 @@
{{#load-more selector=".log-list tr" action=(action "loadMore") class="wizard-logs"}} {{#load-more selector=".log-list tr" action=(action "loadMore") class="wizard-logs"}}
{{#if noResults}} {{#if noResults}}
<p>{{i18n 'search.no_results'}}</p> <p>{{i18n "search.no_results"}}</p>
{{else}} {{else}}
<table class="table grid"> <table class="table grid">
<thead> <thead>
@ -27,8 +27,8 @@
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>
</table> </table>
{{/if}} {{/if}}
{{conditional-loading-spinner condition=refreshing}} {{conditional-loading-spinner condition=refreshing}}
{{/load-more}} {{/load-more}}

Datei anzeigen

@ -1,18 +1,18 @@
<div class="admin-wizard-controls"> <div class="admin-wizard-controls">
<h3>{{i18n 'admin.wizard.manager.title'}}</h3> <h3>{{i18n "admin.wizard.manager.title"}}</h3>
<div class="buttons"> <div class="buttons">
{{#if filename}} {{#if filename}}
<div class="filename"> <div class="filename">
<a {{action 'clearFile'}}> <a role="button" {{action "clearFile"}}>
{{d-icon 'times'}} {{d-icon "times"}}
</a> </a>
<span>{{filename}}</span> <span>{{filename}}</span>
</div> </div>
{{/if}} {{/if}}
{{input {{input
id='file-upload' id="file-upload"
type="file" type="file"
accept="application/json" accept="application/json"
change=(action "setFile")}} change=(action "setFile")}}
@ -45,15 +45,15 @@
opts=messageOpts opts=messageOpts
items=messageItems items=messageItems
loading=loading loading=loading
component='manager'}} component="manager"}}
<div class="admin-wizard-container"> <div class="admin-wizard-container">
<table class="table grid"> <table class="table grid">
<thead> <thead>
<tr> <tr>
<th>{{i18n 'admin.wizard.label'}}</th> <th>{{i18n "admin.wizard.label"}}</th>
<th class="control-column">{{i18n 'admin.wizard.manager.export'}}</th> <th class="control-column">{{i18n "admin.wizard.manager.export"}}</th>
<th class="control-column">{{i18n 'admin.wizard.manager.destroy'}}</th> <th class="control-column">{{i18n "admin.wizard.manager.destroy"}}</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -65,19 +65,19 @@
{{/link-to}} {{/link-to}}
</td> </td>
<td class="control-column"> <td class="control-column">
{{input {{input
type="checkbox" type="checkbox"
class="export" class="export"
change=(action 'selectWizard')}} change=(action "selectWizard")}}
</td> </td>
<td class="control-column"> <td class="control-column">
{{input {{input
type="checkbox" type="checkbox"
class="destroy" class="destroy"
change=(action 'selectWizard')}} change=(action "selectWizard")}}
</td> </td>
</tr> </tr>
{{/each}} {{/each}}
</tbody> </tbody>
</table> </table>
</div> </div>

Datei anzeigen

@ -1,29 +1,33 @@
{{#if submissions}} {{#if submissions}}
<div class="wizard-header large"> <div class="wizard-header large">
<label>{{i18n 'admin.wizard.submissions.title' name=wizard.name}}</label> <label>{{i18n "admin.wizard.submissions.title" name=wizard.name}}</label>
<a class="btn btn-default download-link" href="{{downloadUrl}}" target="_blank"> <a class="btn btn-default download-link" href={{downloadUrl}} target="_blank" rel="noopener noreferrer">
{{d-icon 'download'}} {{d-icon "download"}}
<span class="d-button-label"> <span class="d-button-label">
{{i18n "admin.wizard.submissions.download"}} {{i18n "admin.wizard.submissions.download"}}
</span> </span>
</a> </a>
</div> </div>
<div class="wizard-submissions"> <div class="wizard-submissions">
<table> <table>
<tr> <thead>
{{#each fields as |f|}}
<th>{{f}}</th>
{{/each}}
</tr>
{{#each submissions as |s|}}
<tr> <tr>
{{#each-in s as |k v|}} {{#each fields as |f|}}
<td>{{v}}</td> <th>{{f}}</th>
{{/each-in}} {{/each}}
</tr> </tr>
{{/each}} </thead>
<tbody>
{{#each submissions as |s|}}
<tr>
{{#each-in s as |k v|}}
<td>{{v}}</td>
{{/each-in}}
</tr>
{{/each}}
</tbody>
</table> </table>
</div> </div>
{{/if}} {{/if}}

Datei anzeigen

@ -2,9 +2,9 @@
{{combo-box {{combo-box
value=wizardId value=wizardId
content=wizardList content=wizardList
onChange=(route-action 'changeWizard') onChange=(route-action "changeWizard")
options=(hash options=(hash
none='admin.wizard.select' none="admin.wizard.select"
)}} )}}
</div> </div>

Datei anzeigen

@ -1,10 +1,10 @@
{{#if wizard}} {{#if wizard}}
<div class="wizard-header large"> <div class="wizard-header large">
{{input {{input
name="name" name="name"
value=wizard.name value=wizard.name
placeholderKey="admin.wizard.name_placeholder"}} placeholderKey="admin.wizard.name_placeholder"}}
<div class="wizard-url"> <div class="wizard-url">
{{#if wizard.name}} {{#if wizard.name}}
{{#if copiedUrl}} {{#if copiedUrl}}
@ -12,15 +12,15 @@
{{else}} {{else}}
{{d-button action=(action "copyUrl") class="pull-right no-text" icon="copy"}} {{d-button action=(action "copyUrl") class="pull-right no-text" icon="copy"}}
{{/if}} {{/if}}
<a href="{{wizardUrl}}" target="_blank">{{wizardUrl}}</a> <a href={{wizardUrl}} target="_blank" rel="noopener noreferrer">{{wizardUrl}}</a>
{{/if}} {{/if}}
</div> </div>
</div> </div>
<div class="wizard-basic-details"> <div class="wizard-basic-details">
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.background'}}</label> <label>{{i18n "admin.wizard.background"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input {{input
@ -30,127 +30,127 @@
class="small"}} class="small"}}
</div> </div>
</div> </div>
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.theme_id'}}</label> <label>{{i18n "admin.wizard.theme_id"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
content=themes content=themes
valueProperty='id' valueProperty="id"
value=wizard.theme_id value=wizard.theme_id
onChange=(action (mut wizard.theme_id)) onChange=(action (mut wizard.theme_id))
options=(hash options=(hash
none='admin.wizard.no_theme' none="admin.wizard.no_theme"
)}} )}}
</div> </div>
</div> </div>
</div> </div>
<div class="wizard-header medium"> <div class="wizard-header medium">
{{i18n 'admin.wizard.label'}} {{i18n "admin.wizard.label"}}
</div> </div>
<div class="wizard-settings"> <div class="wizard-settings">
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.required'}}</label> <label>{{i18n "admin.wizard.required"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input type='checkbox' checked=wizard.required}} {{input type="checkbox" checked=wizard.required}}
<span>{{i18n 'admin.wizard.required_label'}}</span> <span>{{i18n "admin.wizard.required_label"}}</span>
</div> </div>
</div> </div>
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.after_signup'}}</label> <label>{{i18n "admin.wizard.after_signup"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input type='checkbox' checked=wizard.after_signup}} {{input type="checkbox" checked=wizard.after_signup}}
<span>{{i18n 'admin.wizard.after_signup_label'}}</span> <span>{{i18n "admin.wizard.after_signup_label"}}</span>
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n 'admin.wizard.multiple_submissions'}}</label>
</div>
<div class="setting-value">
{{input type='checkbox' checked=wizard.multiple_submissions}}
<span>{{i18n 'admin.wizard.multiple_submissions_label'}}</span>
</div> </div>
</div> </div>
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.prompt_completion'}}</label> <label>{{i18n "admin.wizard.multiple_submissions"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input type='checkbox' checked=wizard.prompt_completion}} {{input type="checkbox" checked=wizard.multiple_submissions}}
<span>{{i18n 'admin.wizard.prompt_completion_label'}}</span> <span>{{i18n "admin.wizard.multiple_submissions_label"}}</span>
</div> </div>
</div> </div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.prompt_completion"}}</label>
</div>
<div class="setting-value">
{{input type="checkbox" checked=wizard.prompt_completion}}
<span>{{i18n "admin.wizard.prompt_completion_label"}}</span>
</div>
</div>
<div class="setting full-inline"> <div class="setting full-inline">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.after_time'}}</label> <label>{{i18n "admin.wizard.after_time"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input type='checkbox' checked=wizard.after_time}} {{input type="checkbox" checked=wizard.after_time}}
<span>{{i18n 'admin.wizard.after_time_label'}}</span> <span>{{i18n "admin.wizard.after_time_label"}}</span>
{{d-button {{d-button
action='setNextSessionScheduled' action="setNextSessionScheduled"
translatedLabel=nextSessionScheduledLabel translatedLabel=nextSessionScheduledLabel
class="btn-after-time" class="btn-after-time"
icon='far-calendar'}} icon="far-calendar"}}
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.permitted'}}</label> <label>{{i18n "admin.wizard.permitted"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=wizard.permitted inputs=wizard.permitted
options=(hash options=(hash
context='wizard' context="wizard"
inputTypes='assignment,validation' inputTypes="assignment,validation"
groupSelection='output' groupSelection="output"
userFieldSelection='key' userFieldSelection="key"
textSelection='value' textSelection="value"
inputConnector='and' inputConnector="and"
)}} )}}
</div> </div>
</div> </div>
{{wizard-advanced-toggle showAdvanced=wizard.showAdvanced}} {{wizard-advanced-toggle showAdvanced=wizard.showAdvanced}}
{{#if wizard.showAdvanced}} {{#if wizard.showAdvanced}}
<div class="advanced-settings"> <div class="advanced-settings">
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.save_submissions'}}</label> <label>{{i18n "admin.wizard.save_submissions"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input type='checkbox' checked=wizard.save_submissions}} {{input type="checkbox" checked=wizard.save_submissions}}
<span>{{i18n 'admin.wizard.save_submissions_label'}}</span> <span>{{i18n "admin.wizard.save_submissions_label"}}</span>
</div> </div>
</div> </div>
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.restart_on_revisit'}}</label> <label>{{i18n "admin.wizard.restart_on_revisit"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input type='checkbox' checked=wizard.restart_on_revisit}} {{input type="checkbox" checked=wizard.restart_on_revisit}}
<span>{{i18n 'admin.wizard.restart_on_revisit_label'}}</span> <span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
</div> </div>
</div> </div>
</div> </div>
{{/if}} {{/if}}
</div> </div>
@ -185,19 +185,19 @@
wizardFields=wizardFields}} wizardFields=wizardFields}}
{{/each}} {{/each}}
<div class='admin-wizard-buttons'> <div class="admin-wizard-buttons">
<button {{action "save"}} disabled={{disableSave}} class='btn btn-primary'> <button {{action "save"}} disabled={{disableSave}} class="btn btn-primary" type="button">
{{i18n 'admin.wizard.save'}} {{i18n "admin.wizard.save"}}
</button> </button>
{{#unless creating}} {{#unless creating}}
<button {{action "remove"}} class='btn btn-danger remove'> <button {{action "remove"}} class="btn btn-danger remove" type="button">
{{d-icon "far-trash-alt"}}{{i18n 'admin.wizard.remove'}} {{d-icon "far-trash-alt"}}{{i18n "admin.wizard.remove"}}
</button> </button>
{{/unless}} {{/unless}}
{{conditional-loading-spinner condition=saving size='small'}} {{conditional-loading-spinner condition=saving size="small"}}
{{#if error}} {{#if error}}
<span class="error">{{d-icon "times"}}{{error}}</span> <span class="error">{{d-icon "times"}}{{error}}</span>
{{/if}} {{/if}}

Datei anzeigen

@ -2,11 +2,11 @@
{{combo-box {{combo-box
value=wizardListVal value=wizardListVal
content=wizardList content=wizardList
onChange=(route-action 'changeWizard') onChange=(route-action "changeWizard")
options=(hash options=(hash
none='admin.wizard.select' none="admin.wizard.select"
)}} )}}
{{d-button {{d-button
action="createWizard" action="createWizard"
label="admin.wizard.create" label="admin.wizard.create"
@ -16,8 +16,8 @@
{{wizard-message {{wizard-message
key=messageKey key=messageKey
url=messageUrl url=messageUrl
component='wizard'}} component="wizard"}}
<div class="admin-wizard-container settings"> <div class="admin-wizard-container settings">
{{outlet}} {{outlet}}
</div> </div>

Datei anzeigen

@ -1,12 +1,12 @@
{{#admin-nav}} {{#admin-nav}}
{{nav-item route='adminWizardsWizard' label='admin.wizard.nav_label'}} {{nav-item route="adminWizardsWizard" label="admin.wizard.nav_label"}}
{{nav-item route='adminWizardsCustomFields' label='admin.wizard.custom_field.nav_label'}} {{nav-item route="adminWizardsCustomFields" label="admin.wizard.custom_field.nav_label"}}
{{nav-item route='adminWizardsSubmissions' label='admin.wizard.submissions.nav_label'}} {{nav-item route="adminWizardsSubmissions" label="admin.wizard.submissions.nav_label"}}
{{#if siteSettings.wizard_apis_enabled}} {{#if siteSettings.wizard_apis_enabled}}
{{nav-item route='adminWizardsApi' label='admin.wizard.api.nav_label'}} {{nav-item route="adminWizardsApi" label="admin.wizard.api.nav_label"}}
{{/if}} {{/if}}
{{nav-item route='adminWizardsLogs' label='admin.wizard.log.nav_label'}} {{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}}
{{nav-item route='adminWizardsManager' label='admin.wizard.manager.nav_label'}} {{nav-item route="adminWizardsManager" label="admin.wizard.manager.nav_label"}}
{{/admin-nav}} {{/admin-nav}}
<div class="admin-container"> <div class="admin-container">

Datei anzeigen

@ -60,4 +60,4 @@
<td class="actions"> <td class="actions">
{{d-button action="edit" icon="pencil-alt"}} {{d-button action="edit" icon="pencil-alt"}}
</td> </td>
{{/if}} {{/if}}

Datei anzeigen

@ -1,4 +1,4 @@
{{d-button {{d-button
action="toggleAdvanced" action="toggleAdvanced"
label='admin.wizard.advanced' label="admin.wizard.advanced"
class=toggleClass}} class=toggleClass}}

Datei anzeigen

@ -10,7 +10,7 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.type"}}</label> <label>{{i18n "admin.wizard.type"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
value=action.type value=action.type
@ -26,7 +26,7 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.run_after.label"}}</label> <label>{{i18n "admin.wizard.action.run_after.label"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
value=action.run_after value=action.run_after
@ -38,23 +38,23 @@
{{wizard-message {{wizard-message
key=messageKey key=messageKey
url=messageUrl url=messageUrl
component='action'}} component="action"}}
{{#if basicTopicFields}} {{#if basicTopicFields}}
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.title"}}</label> <label>{{i18n "admin.wizard.action.title"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.title inputs=action.title
property='title' property="title"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -63,21 +63,21 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.post"}}</label> <label>{{i18n "admin.wizard.action.post"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
value=action.post value=action.post
content=wizardFields content=wizardFields
nameProperty='label' nameProperty="label"
onChange=(action (mut action.post)) onChange=(action (mut action.post))
options=(hash options=(hash
none='admin.wizard.selector.placeholder.wizard_field' none="admin.wizard.selector.placeholder.wizard_field"
isDisabled=showPostBuilder isDisabled=showPostBuilder
)}} )}}
<div class="setting-gutter"> <div class="setting-gutter">
{{input type='checkbox' checked=action.post_builder}} {{input type="checkbox" checked=action.post_builder}}
<span>{{i18n 'admin.wizard.action.post_builder.checkbox'}}</span> <span>{{i18n "admin.wizard.action.post_builder.checkbox"}}</span>
</div> </div>
</div> </div>
</div> </div>
@ -85,9 +85,9 @@
{{#if action.post_builder}} {{#if action.post_builder}}
<div class="setting full"> <div class="setting full">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.action.post_builder.label'}}</label> <label>{{i18n "admin.wizard.action.post_builder.label"}}</label>
</div> </div>
<div class="setting-value editor"> <div class="setting-value editor">
{{wizard-text-editor {{wizard-text-editor
value=action.post_template value=action.post_template
@ -102,83 +102,83 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_topic.category"}}</label> <label>{{i18n "admin.wizard.action.create_topic.category"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.category inputs=action.category
property='category' property="category"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection='key,value' textSelection="key,value"
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
categorySelection='output' categorySelection="output"
wizardActionSelection='output' wizardActionSelection="output"
outputDefaultSelection='category' outputDefaultSelection="category"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_topic.tags"}}</label> <label>{{i18n "admin.wizard.action.create_topic.tags"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.tags inputs=action.tags
property='tags' property="tags"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
tagSelection='output' tagSelection="output"
outputDefaultSelection='tag' outputDefaultSelection="tag"
listSelection='output' listSelection="output"
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_topic.visible"}}</label> <label>{{i18n "admin.wizard.action.create_topic.visible"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.visible inputs=action.visible
property='visible' property="visible"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if sendMessage}} {{#if sendMessage}}
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.send_message.recipient"}}</label> <label>{{i18n "admin.wizard.action.send_message.recipient"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.recipient inputs=action.recipient
property='recipient' property="recipient"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection='value,output' textSelection="value,output"
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
groupSelection='key,value' groupSelection="key,value"
userSelection='output' userSelection="output"
outputDefaultSelection='user' outputDefaultSelection="user"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -187,21 +187,21 @@
{{#if updateProfile}} {{#if updateProfile}}
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.action.update_profile.setting'}}</label> <label>{{i18n "admin.wizard.action.update_profile.setting"}}</label>
</div> </div>
{{wizard-mapper {{wizard-mapper
inputs=action.profile_updates inputs=action.profile_updates
property='profile_updates' property="profile_updates"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
inputTypes='association' inputTypes="association"
textSelection='value' textSelection="value"
userFieldSelection='key' userFieldSelection="key"
wizardFieldSelection='value' wizardFieldSelection="value"
wizardActionSelection='value' wizardActionSelection="value"
keyDefaultSelection='userField' keyDefaultSelection="userField"
context='action' context="action"
)}} )}}
</div> </div>
{{/if}} {{/if}}
@ -211,7 +211,7 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.send_to_api.api"}}</label> <label>{{i18n "admin.wizard.action.send_to_api.api"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
value=action.api value=action.api
@ -219,7 +219,7 @@
onChange=(action (mut action.api)) onChange=(action (mut action.api))
options=(hash options=(hash
isDisabled=action.custom_title_enabled isDisabled=action.custom_title_enabled
none='admin.wizard.action.send_to_api.select_an_api' none="admin.wizard.action.send_to_api.select_an_api"
)}} )}}
</div> </div>
</div> </div>
@ -228,7 +228,7 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.send_to_api.endpoint"}}</label> <label>{{i18n "admin.wizard.action.send_to_api.endpoint"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
value=action.api_endpoint value=action.api_endpoint
@ -236,7 +236,7 @@
onChange=(action (mut action.api_endpoint)) onChange=(action (mut action.api_endpoint))
options=(hash options=(hash
isDisabled=apiEmpty isDisabled=apiEmpty
none='admin.wizard.action.send_to_api.select_an_endpoint' none="admin.wizard.action.send_to_api.select_an_endpoint"
)}} )}}
</div> </div>
</div> </div>
@ -245,14 +245,14 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.send_to_api.body"}}</label> <label>{{i18n "admin.wizard.action.send_to_api.body"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-text-editor {{wizard-text-editor
value=action.api_body value=action.api_body
previewEnabled=false previewEnabled=false
barEnabled=false barEnabled=false
wizardFields=wizardFields wizardFields=wizardFields
placeholder='admin.wizard.action.send_to_api.body_placeholder'}} placeholder="admin.wizard.action.send_to_api.body_placeholder"}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
@ -262,20 +262,20 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.group"}}</label> <label>{{i18n "admin.wizard.group"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.group inputs=action.group
property='group' property="group"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection='value,output' textSelection="value,output"
wizardFieldSelection='key,value,assignment' wizardFieldSelection="key,value,assignment"
userFieldSelection='key,value,assignment' userFieldSelection="key,value,assignment"
wizardActionSelection=true wizardActionSelection=true
groupSelection='value,output' groupSelection="value,output"
outputDefaultSelection='group' outputDefaultSelection="group"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -286,19 +286,19 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.route_to.url"}}</label> <label>{{i18n "admin.wizard.action.route_to.url"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.url inputs=action.url
property='url' property="url"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
context='action' context="action"
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
groupSelection='key,value' groupSelection="key,value"
categorySelection='key,value' categorySelection="key,value"
userSelection='key,value' userSelection="key,value"
)}} )}}
</div> </div>
</div> </div>
@ -309,19 +309,19 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.watch_categories.categories"}}</label> <label>{{i18n "admin.wizard.action.watch_categories.categories"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.categories inputs=action.categories
property='categories' property="categories"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection='key,value' textSelection="key,value"
wizardFieldSelection=true wizardFieldSelection=true
wizardActionSelection=true wizardActionSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
categorySelection='output' categorySelection="output"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -334,12 +334,12 @@
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.mute_remainder inputs=action.mute_remainder
property='mute_remainder' property="mute_remainder"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
context='action' context="action"
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
)}} )}}
</div> </div>
</div> </div>
@ -356,11 +356,11 @@
onChange=(action (mut action.notification_level)) onChange=(action (mut action.notification_level))
options=(hash options=(hash
isDisabled=action.custom_title_enabled isDisabled=action.custom_title_enabled
none='admin.wizard.action.watch_categories.select_a_notification_level' none="admin.wizard.action.watch_categories.select_a_notification_level"
)}} )}}
</div> </div>
</div> </div>
<div class="setting full"> <div class="setting full">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.watch_categories.wizard_user"}}</label> <label>{{i18n "admin.wizard.action.watch_categories.wizard_user"}}</label>
@ -370,7 +370,7 @@
{{input type="checkbox" checked=action.wizard_user}} {{input type="checkbox" checked=action.wizard_user}}
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.watch_categories.usernames"}}</label> <label>{{i18n "admin.wizard.action.watch_categories.usernames"}}</label>
@ -379,13 +379,13 @@
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.usernames inputs=action.usernames
property='usernames' property="usernames"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
context='action' context="action"
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
userSelection='output' userSelection="output"
)}} )}}
</div> </div>
</div> </div>
@ -396,17 +396,17 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.name"}}</label> <label>{{i18n "admin.wizard.action.create_group.name"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.name inputs=action.name
property='name' property="name"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -414,17 +414,17 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.full_name"}}</label> <label>{{i18n "admin.wizard.action.create_group.full_name"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.full_name inputs=action.full_name
property='full_name' property="full_name"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -432,17 +432,17 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.title"}}</label> <label>{{i18n "admin.wizard.action.create_group.title"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.title inputs=action.title
property='title' property="title"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -450,17 +450,17 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.bio_raw"}}</label> <label>{{i18n "admin.wizard.action.create_group.bio_raw"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.bio_raw inputs=action.bio_raw
property='bio_raw' property="bio_raw"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -468,18 +468,18 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.owner_usernames"}}</label> <label>{{i18n "admin.wizard.action.create_group.owner_usernames"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.owner_usernames inputs=action.owner_usernames
property='owner_usernames' property="owner_usernames"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
userSelection='output' userSelection="output"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -487,18 +487,18 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.usernames"}}</label> <label>{{i18n "admin.wizard.action.create_group.usernames"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.usernames inputs=action.usernames
property='usernames' property="usernames"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
userSelection='output' userSelection="output"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -506,17 +506,17 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.grant_trust_level"}}</label> <label>{{i18n "admin.wizard.action.create_group.grant_trust_level"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.grant_trust_level inputs=action.grant_trust_level
property='grant_trust_level' property="grant_trust_level"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -524,17 +524,17 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.mentionable_level"}}</label> <label>{{i18n "admin.wizard.action.create_group.mentionable_level"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.mentionable_level inputs=action.mentionable_level
property='mentionable_level' property="mentionable_level"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -542,17 +542,17 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.messageable_level"}}</label> <label>{{i18n "admin.wizard.action.create_group.messageable_level"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.messageable_level inputs=action.messageable_level
property='messageable_level' property="messageable_level"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -560,35 +560,35 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.visibility_level"}}</label> <label>{{i18n "admin.wizard.action.create_group.visibility_level"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.visibility_level inputs=action.visibility_level
property='visibility_level' property="visibility_level"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_group.members_visibility_level"}}</label> <label>{{i18n "admin.wizard.action.create_group.members_visibility_level"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.members_visibility_level inputs=action.members_visibility_level
property='members_visibility_level' property="members_visibility_level"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -599,116 +599,116 @@
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_category.name"}}</label> <label>{{i18n "admin.wizard.action.create_category.name"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.name inputs=action.name
property='name' property="name"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection='key,value' textSelection="key,value"
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_category.slug"}}</label> <label>{{i18n "admin.wizard.action.create_category.slug"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.slug inputs=action.slug
property='slug' property="slug"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_category.color"}}</label> <label>{{i18n "admin.wizard.action.create_category.color"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.color inputs=action.color
property='color' property="color"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_category.text_color"}}</label> <label>{{i18n "admin.wizard.action.create_category.text_color"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.text_color inputs=action.text_color
property='text_color' property="text_color"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_category.parent_category"}}</label> <label>{{i18n "admin.wizard.action.create_category.parent_category"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.parent_category_id inputs=action.parent_category_id
property='parent_category_id' property="parent_category_id"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection='key,value' textSelection="key,value"
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection='key,value' userFieldSelection="key,value"
categorySelection='output' categorySelection="output"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.create_category.permissions"}}</label> <label>{{i18n "admin.wizard.action.create_category.permissions"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.permissions inputs=action.permissions
property='permissions' property="permissions"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
inputTypes='association' inputTypes="association"
textSelection=true textSelection=true
wizardFieldSelection=true wizardFieldSelection=true
wizardActionSelection='key' wizardActionSelection="key"
userFieldSelection=true userFieldSelection=true
groupSelection='key' groupSelection="key"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
@ -719,89 +719,89 @@
{{#if action.showAdvanced}} {{#if action.showAdvanced}}
<div class="advanced-settings"> <div class="advanced-settings">
{{#if hasCustomFields}} {{#if hasCustomFields}}
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.action.custom_fields.label'}}</label> <label>{{i18n "admin.wizard.action.custom_fields.label"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.custom_fields inputs=action.custom_fields
property='custom_fields' property="custom_fields"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
inputTypes='association' inputTypes="association"
customFieldSelection='key' customFieldSelection="key"
wizardFieldSelection='value' wizardFieldSelection="value"
wizardActionSelection='value' wizardActionSelection="value"
userFieldSelection='value' userFieldSelection="value"
keyPlaceholder='admin.wizard.action.custom_fields.key' keyPlaceholder="admin.wizard.action.custom_fields.key"
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if sendMessage}} {{#if sendMessage}}
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.required'}}</label> <label>{{i18n "admin.wizard.required"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=action.required inputs=action.required
property='required' property="required"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=(hash options=(hash
textSelection='value' textSelection="value"
wizardFieldSelection=true wizardFieldSelection=true
userFieldSelection=true userFieldSelection=true
groupSelection=true groupSelection=true
context='action' context="action"
)}} )}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if showPostAdvanced}} {{#if showPostAdvanced}}
<div class="setting full"> <div class="setting full">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.skip_redirect.label"}}</label> <label>{{i18n "admin.wizard.action.skip_redirect.label"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input type='checkbox' checked=action.skip_redirect}} {{input type="checkbox" checked=action.skip_redirect}}
<span> <span>
{{i18n 'admin.wizard.action.skip_redirect.description' type='topic'}} {{i18n "admin.wizard.action.skip_redirect.description" type="topic"}}
</span> </span>
</div> </div>
</div> </div>
<div class="setting full"> <div class="setting full">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.suppress_notifications.label"}}</label> <label>{{i18n "admin.wizard.action.suppress_notifications.label"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input type='checkbox' checked=action.suppress_notifications}} {{input type="checkbox" checked=action.suppress_notifications}}
<span> <span>
{{i18n 'admin.wizard.action.suppress_notifications.description' type='topic'}} {{i18n "admin.wizard.action.suppress_notifications.description" type="topic"}}
</span> </span>
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if routeTo}} {{#if routeTo}}
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.action.route_to.code"}}</label> <label>{{i18n "admin.wizard.action.route_to.code"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input value=action.code}} {{input value=action.code}}
</div> </div>

Datei anzeigen

@ -1,227 +1,251 @@
{{#if showUndo}} {{#if showUndo}}
{{d-button {{d-button
action="undoChanges" action="undoChanges"
icon=undoIcon icon=undoIcon
label=undoKey label=undoKey
class="undo-changes"}} class="undo-changes"}}
{{/if}} {{/if}}
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.label'}}</label> <label>{{i18n "admin.wizard.field.label"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input name="label" value=field.label}} {{input name="label" value=field.label}}
</div> </div>
</div> </div>
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.required'}}</label> <label>{{i18n "admin.wizard.field.required"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
<span>{{i18n 'admin.wizard.field.required_label'}}</span> <span>{{i18n "admin.wizard.field.required_label"}}</span>
{{input type='checkbox' checked=field.required}} {{input type="checkbox" checked=field.required}}
</div> </div>
</div> </div>
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.description'}}</label> <label>{{i18n "admin.wizard.field.description"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{textarea name="description" value=field.description}} {{textarea name="description" value=field.description}}
</div> </div>
</div> </div>
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.image'}}</label> <label>{{i18n "admin.wizard.field.image"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{image-uploader {{image-uploader
imageUrl=field.image imageUrl=field.image
onUploadDone=(action "imageUploadDone") onUploadDone=(action "imageUploadDone")
onUploadDeleted=(action "imageUploadDeleted") onUploadDeleted=(action "imageUploadDeleted")
type="wizard-step" type="wizard-step"
class="no-repeat contain-image"}} class="no-repeat contain-image"}}
</div> </div>
</div> </div>
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.type'}}</label> <label>{{i18n "admin.wizard.type"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{combo-box {{combo-box
value=field.type value=field.type
content=fieldTypes content=fieldTypes
onChange=(action "changeType") onChange=(action "changeType")
options=(hash options=(hash
none="admin.wizard.select_type" none="admin.wizard.select_type"
)}} )}}
</div> </div>
</div> </div>
{{wizard-message {{wizard-message
key=messageKey key=messageKey
url=messageUrl url=messageUrl
component='field'}} component="field"}}
{{#if isTextType}} {{#if isTextType}}
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.min_length'}}</label> <label>{{i18n "admin.wizard.field.min_length"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input {{input
type="number" type="number"
name="min_length" name="min_length"
value=field.min_length value=field.min_length
class="small"}} class="small"}}
</div> </div>
</div> </div>
<div class="setting full"> <div class="setting full">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.max_length'}}</label> <label>{{i18n "admin.wizard.field.max_length"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input {{input
type="number" type="number"
name="max_length" name="max_length"
value=field.max_length value=field.max_length
class="small"}} class="small"}}
</div> </div>
</div> </div>
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.char_counter'}}</label> <label>{{i18n "admin.wizard.field.char_counter"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
<span>{{i18n 'admin.wizard.field.char_counter_placeholder'}}</span> <span>{{i18n "admin.wizard.field.char_counter_placeholder"}}</span>
{{input {{input
type="checkbox" type="checkbox"
checked=field.char_counter}} checked=field.char_counter}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if isUpload}} {{#if isUpload}}
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.file_types'}}</label> <label>{{i18n "admin.wizard.field.file_types"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input value=field.file_types class="medium"}} {{input value=field.file_types class="medium"}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if showLimit}} {{#if showLimit}}
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.limit'}}</label> <label>{{i18n "admin.wizard.field.limit"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input type="number" value=field.limit class="small"}} {{input type="number" value=field.limit class="small"}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if isDateTime}} {{#if isDateTime}}
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{{i18n 'admin.wizard.field.date_time_format.label'}}}</label> <label>{{html-safe (i18n "admin.wizard.field.date_time_format.label")}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input value=field.format class="medium"}} {{input value=field.format class="medium"}}
<label>{{{i18n 'admin.wizard.field.date_time_format.instructions'}}}</label> <label>{{html-safe (i18n "admin.wizard.field.date_time_format.instructions")}}</label>
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if showPrefill}} {{#if showPrefill}}
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.prefill'}}</label> <label>{{i18n "admin.wizard.field.prefill"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=field.prefill inputs=field.prefill
property='prefill' property="prefill"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=prefillOptions}} options=prefillOptions}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if showContent}} {{#if showContent}}
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.content'}}</label> <label>{{i18n "admin.wizard.field.content"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
inputs=field.content inputs=field.content
property='content' property="content"
onUpdate=(action 'mappedFieldUpdated') onUpdate=(action "mappedFieldUpdated")
options=contentOptions}} options=contentOptions}}
</div> </div>
</div> </div>
{{/if}} {{/if}}
{{#if showAdvanced}} {{#if showAdvanced}}
{{wizard-advanced-toggle showAdvanced=field.showAdvanced}} {{wizard-advanced-toggle showAdvanced=field.showAdvanced}}
{{#if field.showAdvanced}} {{#if field.showAdvanced}}
<div class="advanced-settings"> <div class="advanced-settings">
{{#if isCategory}} <div class="setting full field-mapper-setting">
<div class="setting"> <div class="setting-label">
<div class="setting-label"> <label>{{i18n "admin.wizard.condition"}}</label>
<label>{{i18n 'admin.wizard.field.property'}}</label> </div>
</div>
<div class="setting-value">
<div class="setting-value"> {{wizard-mapper
{{combo-box inputs=field.condition
value=field.property options=fieldConditionOptions}}
content=categoryPropertyTypes </div>
onChange=(action (mut field.property)) </div>
options=(hash
none='admin.wizard.selector.placeholder.property' <div class="setting full field-mapper-setting">
)}} <div class="setting-label">
</div> <label>{{i18n "admin.wizard.index"}}</label>
</div> </div>
{{/if}}
<div class="setting-value">
<div class="setting"> {{wizard-mapper
<div class="setting-label"> inputs=field.index
<label>{{i18n 'admin.wizard.translation'}}</label> options=fieldIndexOptions}}
</div> </div>
<div class="setting-value medium"> </div>
{{input
name="key" {{#if isCategory}}
value=field.key <div class="setting">
class="medium" <div class="setting-label">
placeholderKey="admin.wizard.translation_placeholder"}} <label>{{i18n "admin.wizard.field.property"}}</label>
</div> </div>
</div>
<div class="setting-value">
{{#if validations}} {{combo-box
{{wizard-realtime-validations field=field validations=validations}} value=field.property
{{/if}} content=categoryPropertyTypes
</div> onChange=(action (mut field.property))
{{/if}} options=(hash
{{/if}} none="admin.wizard.selector.placeholder.property"
)}}
</div>
</div>
{{/if}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.translation"}}</label>
</div>
<div class="setting-value medium">
{{input
name="key"
value=field.key
class="medium"
placeholderKey="admin.wizard.translation_placeholder"}}
</div>
</div>
{{#if validations}}
{{wizard-realtime-validations field=field validations=validations}}
{{/if}}
</div>
{{/if}}
{{/if}}

Datei anzeigen

@ -1,112 +1,133 @@
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.step.title'}}</label> <label>{{i18n "admin.wizard.step.title"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input {{input
name="title" name="title"
value=step.title}} value=step.title}}
</div> </div>
</div> </div>
<div class="setting full"> <div class="setting full">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.step.banner'}}</label> <label>{{i18n "admin.wizard.step.banner"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{image-uploader {{image-uploader
imageUrl=step.banner imageUrl=step.banner
onUploadDone=(action "bannerUploadDone") onUploadDone=(action "bannerUploadDone")
onUploadDeleted=(action "bannerUploadDeleted") onUploadDeleted=(action "bannerUploadDeleted")
type="wizard-banner" type="wizard-banner"
class="no-repeat contain-image"}} class="no-repeat contain-image"}}
</div> </div>
</div> </div>
<div class="setting full"> <div class="setting full">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.step.description'}}</label> <label>{{i18n "admin.wizard.step.description"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-text-editor {{wizard-text-editor
value=step.raw_description}} value=step.raw_description}}
</div> </div>
</div> </div>
{{wizard-advanced-toggle showAdvanced=step.showAdvanced}} {{wizard-advanced-toggle showAdvanced=step.showAdvanced}}
{{#if step.showAdvanced}} {{#if step.showAdvanced}}
<div class="advanced-settings"> <div class="advanced-settings">
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.step.required_data.label'}}</label> <label>{{i18n "admin.wizard.condition"}}</label>
</div> </div>
<div class="setting-value">
{{wizard-mapper <div class="setting-value">
inputs=step.required_data {{wizard-mapper
options=(hash inputs=step.condition
inputTypes='validation' options=stepConditionOptions}}
inputConnector='and' </div>
wizardFieldSelection='value' </div>
userFieldSelection='value'
keyPlaceholder="admin.wizard.submission_key" <div class="setting full">
context='step' <div class="setting-label"></div>
)}} <div class="setting-value force-final">
{{#if step.required_data}} <h4>{{i18n "admin.wizard.step.force_final.label"}}</h4>
<div class="required-data-message"> {{input type="checkbox" checked=step.force_final}}
<div class="label"> <span>{{i18n "admin.wizard.step.force_final.description"}}</span>
{{i18n 'admin.wizard.step.required_data.not_permitted_message'}} </div>
</div> </div>
{{input value=step.required_data_message}}
</div> <div class="setting full field-mapper-setting">
{{/if}} <div class="setting-label">
</div> <label>{{i18n "admin.wizard.step.required_data.label"}}</label>
</div> </div>
<div class="setting-value">
<div class="setting full field-mapper-setting"> {{wizard-mapper
<div class="setting-label"> inputs=step.required_data
<label>{{i18n 'admin.wizard.step.permitted_params.label'}}</label> options=(hash
</div> inputTypes="validation"
<div class="setting-value"> inputConnector="and"
{{wizard-mapper wizardFieldSelection="value"
inputs=step.permitted_params userFieldSelection="value"
options=(hash keyPlaceholder="admin.wizard.submission_key"
pairConnector='set' context="step"
inputTypes='association' )}}
keyPlaceholder='admin.wizard.param_key' {{#if step.required_data}}
valuePlaceholder='admin.wizard.submission_key' <div class="required-data-message">
context='step' <div class="label">
)}} {{i18n "admin.wizard.step.required_data.not_permitted_message"}}
</div> </div>
</div> {{input value=step.required_data_message}}
</div>
<div class="setting"> {{/if}}
<div class="setting-label"> </div>
<label>{{i18n 'admin.wizard.translation'}}</label> </div>
</div>
<div class="setting-value"> <div class="setting full field-mapper-setting">
{{input <div class="setting-label">
name="key" <label>{{i18n "admin.wizard.step.permitted_params.label"}}</label>
value=step.key </div>
placeholderKey="admin.wizard.translation_placeholder"}} <div class="setting-value">
</div> {{wizard-mapper
</div> inputs=step.permitted_params
options=(hash
</div> pairConnector="set"
{{/if}} inputTypes="association"
keyPlaceholder="admin.wizard.param_key"
{{wizard-links valuePlaceholder="admin.wizard.submission_key"
itemType="field" context="step"
current=currentField )}}
items=step.fields </div>
parentId=step.id}} </div>
{{#each step.fields as |field|}} <div class="setting">
{{wizard-custom-field <div class="setting-label">
field=field <label>{{i18n "admin.wizard.translation"}}</label>
currentFieldId=currentField.id </div>
fieldTypes=fieldTypes <div class="setting-value">
removeField="removeField" {{input
wizardFields=wizardFields}} name="key"
{{/each}} value=step.key
placeholderKey="admin.wizard.translation_placeholder"}}
</div>
</div>
</div>
{{/if}}
{{wizard-links
itemType="field"
current=currentField
items=step.fields
parentId=step.id}}
{{#each step.fields as |field|}}
{{wizard-custom-field
field=field
step=step
currentFieldId=currentField.id
fieldTypes=fieldTypes
removeField="removeField"
wizardFields=wizardFields}}
{{/each}}

Datei anzeigen

@ -1,14 +1,14 @@
<div class="wizard-header medium">{{{i18n header}}}</div> <div class="wizard-header medium">{{html-safe (i18n header)}}</div>
<div class="link-list"> <div class="link-list">
{{#if anyLinks}} {{#if anyLinks}}
{{#each links as |l|}} {{#each links as |l|}}
<div data-id='{{l.id}}'> <div data-id={{l.id}}>
{{d-button action="change" actionParam=l.id translatedLabel=l.label class=l.classes}} {{d-button action="change" actionParam=l.id translatedLabel=l.label class=l.classes}}
{{d-button action='remove' actionParam=l.id icon='times' class='remove'}} {{d-button action="remove" actionParam=l.id icon="times" class="remove"}}
</div> </div>
{{/each}} {{/each}}
{{/if}} {{/if}}
{{d-button action='add' label='admin.wizard.add' icon='plus'}} {{d-button action="add" label="admin.wizard.add" icon="plus"}}
</div> </div>

Datei anzeigen

@ -9,4 +9,4 @@
{{connectorLabel}} {{connectorLabel}}
</span> </span>
{{/if}} {{/if}}
{{/if}} {{/if}}

Datei anzeigen

@ -15,13 +15,13 @@
last=pair.last last=pair.last
inputType=inputType inputType=inputType
options=options options=options
removePair=(action 'removePair') removePair=(action "removePair")
onUpdate=onUpdate}} onUpdate=onUpdate}}
{{/each}} {{/each}}
{{#if canAddPair}} {{#if canAddPair}}
<a {{action 'addPair'}} class="add-pair"> <a role="button" {{action "addPair"}} class="add-pair">
{{d-icon 'plus'}} {{d-icon "plus"}}
</a> </a>
{{/if}} {{/if}}
</div> </div>
@ -40,7 +40,7 @@
<div class="output mapper-block"> <div class="output mapper-block">
{{wizard-mapper-selector {{wizard-mapper-selector
selectorType='output' selectorType="output"
inputType=input.type inputType=input.type
value=input.output value=input.output
activeType=input.output_type activeType=input.output_type
@ -49,6 +49,6 @@
</div> </div>
{{/if}} {{/if}}
<a class="remove-input" {{action remove input}}> <a role="button" class="remove-input" {{action remove input}}>
{{d-icon 'times'}} {{d-icon "times"}}
</a> </a>

Datei anzeigen

@ -1,6 +1,6 @@
<div class="key mapper-block"> <div class="key mapper-block">
{{wizard-mapper-selector {{wizard-mapper-selector
selectorType='key' selectorType="key"
inputType=inputType inputType=inputType
value=pair.key value=pair.key
activeType=pair.key_type activeType=pair.key_type
@ -18,7 +18,7 @@
<div class="value mapper-block"> <div class="value mapper-block">
{{wizard-mapper-selector {{wizard-mapper-selector
selectorType='value' selectorType="value"
inputType=inputType inputType=inputType
value=pair.value value=pair.value
activeType=pair.value_type activeType=pair.value_type
@ -31,5 +31,5 @@
{{/if}} {{/if}}
{{#if showRemove}} {{#if showRemove}}
<a {{action removePair pair}} class="remove-pair">{{d-icon 'times'}}</a> <a role="button" {{action removePair pair}} class="remove-pair">{{d-icon "times"}}</a>
{{/if}} {{/if}}

Datei anzeigen

@ -1 +1 @@
{{item.label}} {{item.label}}

Datei anzeigen

@ -1,16 +1,16 @@
<div class="type-selector"> <div class="type-selector">
{{#if hasTypes}} {{#if hasTypes}}
<a {{action "toggleTypes"}} class="active"> <a role="button" {{action "toggleTypes"}} class="active">
{{activeTypeLabel}} {{activeTypeLabel}}
</a> </a>
{{#if showTypes}} {{#if showTypes}}
<div class="selector-types"> <div class="selector-types">
{{#each selectorTypes as |item|}} {{#each selectorTypes as |item|}}
{{wizard-mapper-selector-type {{wizard-mapper-selector-type
activeType=activeType activeType=activeType
item=item item=item
toggle=(action 'toggleType')}} toggle=(action "toggleType")}}
{{/each}} {{/each}}
</div> </div>
{{/if}} {{/if}}
@ -38,7 +38,7 @@
allowAny=comboBoxAllowAny allowAny=comboBoxAllowAny
)}} )}}
{{/if}} {{/if}}
{{#if showMultiSelect}} {{#if showMultiSelect}}
{{multi-select {{multi-select
content=multiSelectContent content=multiSelectContent
@ -46,14 +46,14 @@
onChange=(action "changeValue") onChange=(action "changeValue")
options=multiSelectOptions}} options=multiSelectOptions}}
{{/if}} {{/if}}
{{#if showList}} {{#if showList}}
{{wizard-value-list {{wizard-value-list
values=value values=value
addKey=placeholderKey addKey=placeholderKey
onChange=(action "changeValue")}} onChange=(action "changeValue")}}
{{/if}} {{/if}}
{{#if showTag}} {{#if showTag}}
{{tag-chooser {{tag-chooser
tags=value tags=value
@ -63,13 +63,13 @@
filterable=true filterable=true
)}} )}}
{{/if}} {{/if}}
{{#if showUser}} {{#if showUser}}
{{user-selector {{user-selector
includeMessageableGroups='true' includeMessageableGroups="true"
placeholderKey=placeholderKey placeholderKey=placeholderKey
usernames=value usernames=value
autocomplete="discourse" autocomplete="discourse"
onChangeCallback=(action "changeUserValue")}} onChangeCallback=(action "changeUserValue")}}
{{/if}} {{/if}}
</div> </div>

Datei anzeigen

@ -3,18 +3,18 @@
{{wizard-mapper-connector {{wizard-mapper-connector
connector=input.connector connector=input.connector
connectorType="input" connectorType="input"
onUpdate=(action 'inputUpdated')}} onUpdate=(action "inputUpdated")}}
{{/if}} {{/if}}
{{wizard-mapper-input {{wizard-mapper-input
input=input input=input
options=inputOptions options=inputOptions
remove=(action 'remove') remove=(action "remove")
onUpdate=(action 'inputUpdated')}} onUpdate=(action "inputUpdated")}}
{{/each}} {{/each}}
{{#if canAdd}} {{#if canAdd}}
<span class="add-mapper-input"> <span class="add-mapper-input">
{{d-button action='add' label='admin.wizard.add' icon='plus'}} {{d-button action="add" label="admin.wizard.add" icon="plus"}}
</span> </span>
{{/if}} {{/if}}

Datei anzeigen

@ -2,13 +2,13 @@
{{#if showIcon}} {{#if showIcon}}
{{d-icon icon}} {{d-icon icon}}
{{/if}} {{/if}}
<span class="message-content">{{{message}}}</span> <span class="message-content">{{html-safe message}}</span>
{{#if hasItems}} {{#if hasItems}}
<ul> <ul>
{{#each items as |item|}} {{#each items as |item|}}
<li> <li>
<span>{{d-icon item.icon}}</span> <span>{{d-icon item.icon}}</span>
<span>{{{item.html}}}</span> <span>{{html-safe item.html}}</span>
</li> </li>
{{/each}} {{/each}}
</ul> </ul>
@ -17,10 +17,10 @@
{{#if showDocumentation}} {{#if showDocumentation}}
<div class="message-block"> <div class="message-block">
{{d-icon 'question-circle'}} {{d-icon "question-circle"}}
<a href={{url}} target="_blank"> <a href={{url}} target="_blank" rel="noopener noreferrer">
{{documentation}} {{documentation}}
</a> </a>
</div> </div>
{{/if}} {{/if}}

Datei anzeigen

@ -1,28 +1,28 @@
<h3>{{i18n 'admin.wizard.field.validations.header'}}</h3> <h3>{{i18n "admin.wizard.field.validations.header"}}</h3>
<ul> <ul>
{{#each-in field.validations as |type props|}} {{#each-in field.validations as |type props|}}
<li> <li>
<span class="setting-title"> <span class="setting-title">
<h4>{{i18n (concat 'admin.wizard.field.validations.' type)}}</h4> <h4>{{i18n (concat "admin.wizard.field.validations." type)}}</h4>
{{input type="checkbox" checked=props.status}} {{input type="checkbox" checked=props.status}}
{{i18n 'admin.wizard.field.validations.enabled'}} {{i18n "admin.wizard.field.validations.enabled"}}
</span> </span>
<div class="validation-container"> <div class="validation-container">
<div class="validation-section"> <div class="validation-section">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.validations.categories'}}</label> <label>{{i18n "admin.wizard.field.validations.categories"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{category-selector {{category-selector
categories=(get this (concat 'validationBuffer.' type '.categories')) categories=(get this (concat "validationBuffer." type ".categories"))
onChange=(action 'updateValidationCategories' type props) onChange=(action "updateValidationCategories" type props)
class="wizard"}} class="wizard"}}
</div> </div>
</div> </div>
<div class="validation-section"> <div class="validation-section">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.validations.max_topic_age'}}</label> <label>{{i18n "admin.wizard.field.validations.max_topic_age"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input type="number" class="time-n-value" value=props.time_n_value}} {{input type="number" class="time-n-value" value=props.time_n_value}}
@ -35,13 +35,13 @@
</div> </div>
<div class="validation-section"> <div class="validation-section">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n 'admin.wizard.field.validations.position'}}</label> <label>{{i18n "admin.wizard.field.validations.position"}}</label>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{radio-button name=(concat type field.id) value="above" selection=props.position}} {{radio-button name=(concat type field.id) value="above" selection=props.position}}
{{i18n 'admin.wizard.field.validations.above'}} {{i18n "admin.wizard.field.validations.above"}}
{{radio-button name=(concat type field.id) value="below" selection=props.position}} {{radio-button name=(concat type field.id) value="below" selection=props.position}}
{{i18n 'admin.wizard.field.validations.below'}} {{i18n "admin.wizard.field.validations.below"}}
</div> </div>
</div> </div>
</div> </div>

Datei anzeigen

@ -9,33 +9,33 @@
action="togglePreview" action="togglePreview"
translatedLabel=previewLabel}} translatedLabel=previewLabel}}
{{/if}} {{/if}}
{{#if fieldsEnabled}} {{#if fieldsEnabled}}
{{d-button {{d-button
action="togglePopover" action="togglePopover"
translatedLabel=popoverLabel}} translatedLabel=popoverLabel}}
{{#if showPopover}} {{#if showPopover}}
<div class="wizard-editor-gutter-popover"> <div class="wizard-editor-gutter-popover">
<label> <label>
{{i18n 'admin.wizard.action.post_builder.user_properties'}} {{i18n "admin.wizard.action.post_builder.user_properties"}}
{{userPropertyList}} {{userPropertyList}}
</label> </label>
{{#if hasWizardFields}} {{#if hasWizardFields}}
<label> <label>
{{i18n 'admin.wizard.action.post_builder.wizard_fields'}} {{i18n "admin.wizard.action.post_builder.wizard_fields"}}
{{wizardFieldList}} {{wizardFieldList}}
</label> </label>
{{/if}} {{/if}}
{{#if hasWizardActions}} {{#if hasWizardActions}}
<label> <label>
{{i18n 'admin.wizard.action.post_builder.wizard_actions'}} {{i18n "admin.wizard.action.post_builder.wizard_actions"}}
{{wizardActionList}} {{wizardActionList}}
</label> </label>
{{/if}} {{/if}}
</div> </div>
{{/if}} {{/if}}
{{/if}} {{/if}}
</div> </div>

Datei anzeigen

@ -1,5 +1,6 @@
window.Discourse = {} /* eslint no-undef: 0*/
window.Discourse = {};
window.Wizard = {}; window.Wizard = {};
Wizard.SiteSettings = {}; Wizard.SiteSettings = {};
Discourse.__widget_helpers = {}; Discourse.__widget_helpers = {};
Discourse.SiteSettings = Wizard.SiteSettings; Discourse.SiteSettings = Wizard.SiteSettings;

Datei anzeigen

@ -1,4 +1,4 @@
(function () { (function () {
document.cookie = 'destination_url=' + window.location.href + ';path=/'; document.cookie = "destination_url=" + window.location.href + ";path=/";
window.location.href = '/login' window.location.href = "/login";
})() })();

Datei anzeigen

@ -1,4 +1,4 @@
(function() { (function () {
var wizard = require('discourse/plugins/discourse-custom-wizard/wizard/custom-wizard').default.create(); let wizard = require("discourse/plugins/discourse-custom-wizard/wizard/custom-wizard").default.create();
wizard.start(); wizard.start();
})(); })();

Datei anzeigen

@ -5,6 +5,8 @@ import {
import { renderAvatar } from "discourse/helpers/user-avatar"; import { renderAvatar } from "discourse/helpers/user-avatar";
import userSearch from "../lib/user-search"; import userSearch from "../lib/user-search";
import WizardI18n from "../lib/wizard-i18n"; import WizardI18n from "../lib/wizard-i18n";
import Handlebars from "handlebars";
import { isEmpty } from "@ember/utils";
const template = function (params) { const template = function (params) {
const options = params.options; const options = params.options;
@ -43,13 +45,14 @@ export default Ember.TextField.extend({
@observes("usernames") @observes("usernames")
_update() { _update() {
if (this.get("canReceiveUpdates") === "true") if (this.get("canReceiveUpdates") === "true") {
this.didInsertElement({ updateData: true }); this.didInsertElement({ updateData: true });
}
}, },
didInsertElement(opts) { didInsertElement(opts) {
this._super(); this._super();
var self = this, let self = this,
selected = [], selected = [],
groups = [], groups = [],
currentUser = this.currentUser, currentUser = this.currentUser,
@ -82,7 +85,7 @@ export default Ember.TextField.extend({
dataSource(term) { dataSource(term) {
const termRegex = /[^a-zA-Z0-9_\-\.@\+]/; const termRegex = /[^a-zA-Z0-9_\-\.@\+]/;
var results = userSearch({ let results = userSearch({
term: term.replace(termRegex, ""), term: term.replace(termRegex, ""),
topicId: self.get("topicId"), topicId: self.get("topicId"),
exclude: excludedUsernames(), exclude: excludedUsernames(),
@ -102,7 +105,7 @@ export default Ember.TextField.extend({
} }
return v.username || v.name; return v.username || v.name;
} else { } else {
var excludes = excludedUsernames(); let excludes = excludedUsernames();
return v.usernames.filter(function (item) { return v.usernames.filter(function (item) {
return excludes.indexOf(item) === -1; return excludes.indexOf(item) === -1;
}); });
@ -110,7 +113,7 @@ export default Ember.TextField.extend({
}, },
onChangeItems(items) { onChangeItems(items) {
var hasGroups = false; let hasGroups = false;
items = items.map(function (i) { items = items.map(function (i) {
if (groups.indexOf(i) > -1) { if (groups.indexOf(i) > -1) {
hasGroups = true; hasGroups = true;
@ -121,7 +124,9 @@ export default Ember.TextField.extend({
self.set("hasGroups", hasGroups); self.set("hasGroups", hasGroups);
selected = items; selected = items;
if (self.get("onChangeCallback")) self.sendAction("onChangeCallback"); if (self.get("onChangeCallback")) {
self.sendAction("onChangeCallback");
}
}, },
reverseTransform(i) { reverseTransform(i) {
@ -139,7 +144,7 @@ export default Ember.TextField.extend({
@observes("usernames") @observes("usernames")
_clearInput: function () { _clearInput: function () {
if (arguments.length > 1) { if (arguments.length > 1) {
if (Em.isEmpty(this.get("usernames"))) { if (isEmpty(this.get("usernames"))) {
$(this.element).parent().find("a").click(); $(this.element).parent().find("a").click();
} }
} }

Datei anzeigen

@ -1,5 +1,4 @@
import Component from "@ember/component"; import Component from "@ember/component";
import { observes } from "discourse-common/utils/decorators";
export default Component.extend({ export default Component.extend({
actions: { actions: {
perform() { perform() {

Datei anzeigen

@ -1,11 +1,10 @@
import WizardFieldValidator from "../../wizard/components/validator"; import WizardFieldValidator from "../../wizard/components/validator";
import { deepMerge } from "discourse-common/lib/object"; import { deepMerge } from "discourse-common/lib/object";
import { observes } from "discourse-common/utils/decorators"; import discourseComputed, { observes } from "discourse-common/utils/decorators";
import { cancel, later } from "@ember/runloop"; import { cancel, later } from "@ember/runloop";
import { A } from "@ember/array"; import { A } from "@ember/array";
import EmberObject, { computed } from "@ember/object"; import EmberObject, { computed } from "@ember/object";
import { notEmpty, and, equal, empty } from "@ember/object/computed"; import { and, equal, notEmpty } from "@ember/object/computed";
import discourseComputed from "discourse-common/utils/decorators";
import { categoryBadgeHTML } from "discourse/helpers/category-link"; import { categoryBadgeHTML } from "discourse/helpers/category-link";
import { dasherize } from "@ember/string"; import { dasherize } from "@ember/string";
@ -16,7 +15,7 @@ export default WizardFieldValidator.extend({
hasSimilarTopics: notEmpty("similarTopics"), hasSimilarTopics: notEmpty("similarTopics"),
hasNotSearched: equal("similarTopics", null), hasNotSearched: equal("similarTopics", null),
noSimilarTopics: computed("similarTopics", function () { noSimilarTopics: computed("similarTopics", function () {
return this.similarTopics !== null && this.similarTopics.length == 0; return this.similarTopics !== null && this.similarTopics.length === 0;
}), }),
showSimilarTopics: computed("typing", "hasSimilarTopics", function () { showSimilarTopics: computed("typing", "hasSimilarTopics", function () {
return this.hasSimilarTopics && !this.typing; return this.hasSimilarTopics && !this.typing;
@ -35,8 +34,9 @@ export default WizardFieldValidator.extend({
@discourseComputed("validation.categories") @discourseComputed("validation.categories")
validationCategories(categoryIds) { validationCategories(categoryIds) {
if (categoryIds) if (categoryIds) {
return categoryIds.map((id) => this.site.categoriesById[id]); return categoryIds.map((id) => this.site.categoriesById[id]);
}
return A(); return A();
}, },
@ -78,15 +78,18 @@ export default WizardFieldValidator.extend({
@discourseComputed("currentState") @discourseComputed("currentState")
currentStateClass(currentState) { currentStateClass(currentState) {
if (currentState) return `similar-topics-${dasherize(currentState)}`; if (currentState) {
return `similar-topics-${dasherize(currentState)}`;
}
return "similar-topics"; return "similar-topics";
}, },
@discourseComputed("currentState") @discourseComputed("currentState")
currentStateKey(currentState) { currentStateKey(currentState) {
if (currentState) if (currentState) {
return `realtime_validations.similar_topics.${currentState}`; return `realtime_validations.similar_topics.${currentState}`;
}
return false; return false;
}, },

Datei anzeigen

@ -4,22 +4,18 @@ import {
on, on,
} from "discourse-common/utils/decorators"; } from "discourse-common/utils/decorators";
import { findRawTemplate } from "discourse-common/lib/raw-templates"; import { findRawTemplate } from "discourse-common/lib/raw-templates";
import { throttle } from "@ember/runloop"; import { next, scheduleOnce, throttle } from "@ember/runloop";
import { scheduleOnce, next } from "@ember/runloop"; import { caretPosition, inCodeBlock } from "discourse/lib/utilities";
import {
safariHacksDisabled,
caretPosition,
inCodeBlock,
} from "discourse/lib/utilities";
import highlightSyntax from "discourse/lib/highlight-syntax"; import highlightSyntax from "discourse/lib/highlight-syntax";
import { getToken } from "wizard/lib/ajax"; import { getToken } from "wizard/lib/ajax";
import { import {
validateUploadedFiles, displayErrorForUpload,
getUploadMarkdown, getUploadMarkdown,
uploadIcon,
validateUploadedFiles,
} from "discourse/lib/uploads"; } from "discourse/lib/uploads";
import { cacheShortUploadUrl } from "pretty-text/upload-short-url"; import { cacheShortUploadUrl } from "pretty-text/upload-short-url";
import { alias } from "@ember/object/computed"; import { alias } from "@ember/object/computed";
import { uploadIcon } from "discourse/lib/uploads";
import WizardI18n from "../lib/wizard-i18n"; import WizardI18n from "../lib/wizard-i18n";
const uploadMarkdownResolvers = []; const uploadMarkdownResolvers = [];
@ -78,8 +74,8 @@ export default ComposerEditor.extend({
.join(","); .join(",");
}, },
@discourseComputed("currentUser") @discourseComputed()
uploadIcon(currentUser) { uploadIcon() {
return uploadIcon(false, this.siteSettings); return uploadIcon(false, this.siteSettings);
}, },
@ -295,7 +291,7 @@ export default ComposerEditor.extend({
shortcut: "K", shortcut: "K",
trimLeading: true, trimLeading: true,
unshift: true, unshift: true,
sendAction: (event) => component.set("showHyperlinkBox", true), sendAction: () => component.set("showHyperlinkBox", true),
}); });
}, },

Datei anzeigen

@ -12,7 +12,9 @@ export default Ember.Component.extend({
[...value].reduce((result, v) => { [...value].reduce((result, v) => {
let val = let val =
property === "id" ? Category.findById(v) : Category.findBySlug(v); property === "id" ? Category.findById(v) : Category.findBySlug(v);
if (val) result.push(val); if (val) {
result.push(val);
}
return result; return result;
}, []) }, [])
); );

Datei anzeigen

@ -2,6 +2,7 @@ import CustomWizard from "../models/custom";
export default Ember.Component.extend({ export default Ember.Component.extend({
siteName: function () { siteName: function () {
/*eslint no-undef:0*/
return Wizard.SiteSettings.title; return Wizard.SiteSettings.title;
}.property(), }.property(),

Datei anzeigen

@ -15,7 +15,9 @@ export default Component.extend({
}, },
documentClick(e) { documentClick(e) {
if (this._state == "destroying") return; if (this._state === "destroying") {
return;
}
let $target = $(e.target); let $target = $(e.target);
if (!$target.hasClass("show-topics")) { if (!$target.hasClass("show-topics")) {

Datei anzeigen

@ -1,7 +1,7 @@
/* eslint no-undef: 0 */ /* eslint no-undef: 0*/
import computed from "discourse-common/utils/decorators"; import computed from "discourse-common/utils/decorators";
import { siteDir, isRTL, isLTR } from "discourse/lib/text-direction"; import { isLTR, isRTL, siteDir } from "discourse/lib/text-direction";
import WizardI18n from "../lib/wizard-i18n"; import WizardI18n from "../lib/wizard-i18n";
export default Ember.TextField.extend({ export default Ember.TextField.extend({

Datei anzeigen

@ -4,14 +4,15 @@ import getUrl from "discourse-common/lib/get-url";
export default StepController.extend({ export default StepController.extend({
actions: { actions: {
goNext(response) { goNext(response) {
const next = this.get("step.next"); let nextStepId = response["next_step_id"];
if (response.redirect_on_next) { if (response.redirect_on_next) {
window.location.href = response.redirect_on_next; window.location.href = response.redirect_on_next;
} else if (response.refresh_required) { } else if (response.refresh_required) {
const id = this.get("wizard.id"); const wizardId = this.get("wizard.id");
window.location.href = getUrl(`/w/${id}/steps/${next}`); window.location.href = getUrl(`/w/${wizardId}/steps/${nextStepId}`);
} else { } else {
this.transitionToRoute("custom.step", next); this.transitionToRoute("custom.step", nextStepId);
} }
}, },

Datei anzeigen

@ -1,5 +1,6 @@
import { registerUnbound } from "discourse-common/lib/helpers"; import { registerUnbound } from "discourse-common/lib/helpers";
import I18n from "I18n"; import I18n from "I18n";
import Handlebars from "handlebars";
export default registerUnbound("char-counter", function (body, maxLength) { export default registerUnbound("char-counter", function (body, maxLength) {
let bodyLength = body ? body.length : 0; let bodyLength = body ? body.length : 0;
@ -9,11 +10,11 @@ export default registerUnbound("char-counter", function (body, maxLength) {
let isOverMax = bodyLength > maxLength ? "true" : "false"; let isOverMax = bodyLength > maxLength ? "true" : "false";
finalString = `<div class="body-length" data-length=${bodyLength} data-over-max=${isOverMax}>${bodyLength} / ${I18n.t( finalString = `<div class="body-length" data-length=${bodyLength} data-over-max=${isOverMax}>${bodyLength} / ${I18n.t(
"wizard.x_characters", "wizard.x_characters",
{ count: parseInt(maxLength) } { count: parseInt(maxLength, 10) }
)}</div>`; )}</div>`;
} else { } else {
finalString = `<div class="body-length">${I18n.t("wizard.x_characters", { finalString = `<div class="body-length">${I18n.t("wizard.x_characters", {
count: parseInt(bodyLength), count: parseInt(bodyLength, 10),
})}</div>`; })}</div>`;
} }

Datei anzeigen

@ -1,5 +1,6 @@
import { registerUnbound } from "discourse-common/lib/helpers"; import { registerUnbound } from "discourse-common/lib/helpers";
import { longDate, number, relativeAge } from "discourse/lib/formatter"; import { longDate, relativeAge } from "discourse/lib/formatter";
import Handlebars from "handlebars";
export default registerUnbound("date-node", function (dt) { export default registerUnbound("date-node", function (dt) {
if (typeof dt === "string") { if (typeof dt === "string") {

Datei anzeigen

@ -1,4 +1,5 @@
import { registerUnbound } from "discourse-common/lib/helpers"; import { registerUnbound } from "discourse-common/lib/helpers";
import Handlebars from "handlebars";
export default registerUnbound("dir-span", function (str) { export default registerUnbound("dir-span", function (str) {
return new Handlebars.SafeString(str); return new Handlebars.SafeString(str);

Datei anzeigen

@ -1,15 +1,17 @@
import { htmlHelper } from 'discourse-common/lib/helpers'; import { htmlHelper } from "discourse-common/lib/helpers";
function renderSpinner(cssClass) { function renderSpinner(cssClass) {
var html = "<div class='spinner"; var html = "<div class='spinner";
if (cssClass) { html += ' ' + cssClass; } if (cssClass) {
html += " " + cssClass;
}
return html + "'></div>"; return html + "'></div>";
} }
var spinnerHTML = renderSpinner(); var spinnerHTML = renderSpinner();
export default htmlHelper(params => { export default htmlHelper((params) => {
const hash = params.hash; const hash = params.hash;
return renderSpinner((hash && hash.size) ? hash.size : undefined); return renderSpinner(hash && hash.size ? hash.size : undefined);
}); });
export { spinnerHTML, renderSpinner }; export { spinnerHTML, renderSpinner };

Datei anzeigen

@ -1,5 +1,6 @@
import { registerUnbound } from "discourse-common/lib/helpers"; import { registerUnbound } from "discourse-common/lib/helpers";
import Handlebars from "handlebars";
export default registerUnbound("plugin-outlet", function (attrs) { export default registerUnbound("plugin-outlet", function () {
return new Handlebars.SafeString(""); return new Handlebars.SafeString("");
}); });

Datei anzeigen

@ -3,8 +3,10 @@ import discourseComputed from "discourse-common/utils/decorators";
export default { export default {
name: "custom-wizard-field", name: "custom-wizard-field",
initialize(app) { initialize() {
if (window.location.pathname.indexOf("/w/") < 0) return; if (window.location.pathname.indexOf("/w/") < 0) {
return;
}
const FieldComponent = requirejs("wizard/components/wizard-field").default; const FieldComponent = requirejs("wizard/components/wizard-field").default;
const FieldModel = requirejs("wizard/models/wizard-field").default; const FieldModel = requirejs("wizard/models/wizard-field").default;
@ -30,7 +32,9 @@ export default {
inputComponentName: function () { inputComponentName: function () {
const type = this.get("field.type"); const type = this.get("field.type");
const id = this.get("field.id"); const id = this.get("field.id");
if (["text_only"].includes(type)) return false; if (["text_only"].includes(type)) {
return false;
}
return dasherize(type === "component" ? id : `wizard-field-${type}`); return dasherize(type === "component" ? id : `wizard-field-${type}`);
}.property("field.type", "field.id"), }.property("field.type", "field.id"),
}); });

Datei anzeigen

@ -1,11 +1,16 @@
export default { export default {
name: "custom-wizard-step", name: "custom-wizard-step",
initialize(app) { initialize() {
if (window.location.pathname.indexOf("/w/") < 0) return; if (window.location.pathname.indexOf("/w/") < 0) {
return;
}
const CustomWizard = requirejs( const CustomWizard = requirejs(
"discourse/plugins/discourse-custom-wizard/wizard/models/custom" "discourse/plugins/discourse-custom-wizard/wizard/models/custom"
).default; ).default;
const updateCachedWizard = requirejs(
"discourse/plugins/discourse-custom-wizard/wizard/models/custom"
).updateCachedWizard;
const StepModel = requirejs("wizard/models/step").default; const StepModel = requirejs("wizard/models/step").default;
const StepComponent = requirejs("wizard/components/wizard-step").default; const StepComponent = requirejs("wizard/components/wizard-step").default;
const ajax = requirejs("wizard/lib/ajax").ajax; const ajax = requirejs("wizard/lib/ajax").ajax;
@ -16,6 +21,7 @@ export default {
"discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite" "discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite"
).cook; ).cook;
const { schedule } = requirejs("@ember/runloop"); const { schedule } = requirejs("@ember/runloop");
const { alias, not } = requirejs("@ember/object/computed");
StepModel.reopen({ StepModel.reopen({
save() { save() {
@ -132,7 +138,9 @@ export default {
bannerImage: function () { bannerImage: function () {
const src = this.get("step.banner"); const src = this.get("step.banner");
if (!src) return; if (!src) {
return;
}
return getUrl(src); return getUrl(src);
}.property("step.banner"), }.property("step.banner"),
@ -151,12 +159,17 @@ export default {
this.sendAction("showMessage", message); this.sendAction("showMessage", message);
}.observes("step.message"), }.observes("step.message"),
showNextButton: not("step.final"),
showDoneButton: alias("step.final"),
advance() { advance() {
this.set("saving", true); this.set("saving", true);
this.get("step") this.get("step")
.save() .save()
.then((response) => { .then((response) => {
if (this.get("finalStep")) { updateCachedWizard(CustomWizard.build(response["wizard"]));
if (response["final"]) {
CustomWizard.finished(response); CustomWizard.finished(response);
} else { } else {
this.sendAction("goNext", response); this.sendAction("goNext", response);
@ -166,7 +179,7 @@ export default {
.finally(() => this.set("saving", false)); .finally(() => this.set("saving", false));
}, },
keyPress(key) {}, keyPress() {},
actions: { actions: {
quit() { quit() {
@ -174,7 +187,6 @@ export default {
}, },
done() { done() {
this.set("finalStep", true);
this.send("nextStep"); this.send("nextStep");
}, },

Datei anzeigen

@ -1,14 +1,13 @@
export default { export default {
name: "custom-routes", name: "custom-routes",
initialize(app) { initialize(app) {
if (window.location.pathname.indexOf("/w/") < 0) return; if (window.location.pathname.indexOf("/w/") < 0) {
return;
}
const EmberObject = requirejs("@ember/object").default; const EmberObject = requirejs("@ember/object").default;
const Router = requirejs("wizard/router").default; const Router = requirejs("wizard/router").default;
const ApplicationRoute = requirejs("wizard/routes/application").default; const ApplicationRoute = requirejs("wizard/routes/application").default;
const CustomWizard = requirejs(
"discourse/plugins/discourse-custom-wizard/wizard/models/custom"
).default;
const getUrl = requirejs("discourse-common/lib/get-url").default; const getUrl = requirejs("discourse-common/lib/get-url").default;
const Store = requirejs("discourse/models/store").default; const Store = requirejs("discourse/models/store").default;
const registerRawHelpers = requirejs( const registerRawHelpers = requirejs(
@ -18,6 +17,7 @@ export default {
.createHelperContext; .createHelperContext;
const RawHandlebars = requirejs("discourse-common/lib/raw-handlebars") const RawHandlebars = requirejs("discourse-common/lib/raw-handlebars")
.default; .default;
const Handlebars = requirejs("handlebars").default;
const Site = requirejs( const Site = requirejs(
"discourse/plugins/discourse-custom-wizard/wizard/models/site" "discourse/plugins/discourse-custom-wizard/wizard/models/site"
).default; ).default;
@ -36,10 +36,12 @@ export default {
// IE11 Polyfill - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Polyfill // IE11 Polyfill - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries#Polyfill
if (!Object.entries) { if (!Object.entries) {
Object.entries = function (obj) { Object.entries = function (obj) {
var ownProps = Object.keys(obj), let ownProps = Object.keys(obj),
i = ownProps.length, i = ownProps.length,
resArray = new Array(i); // preallocate the Array resArray = new Array(i); // preallocate the Array
while (i--) resArray[i] = [ownProps[i], obj[ownProps[i]]]; while (i--) {
resArray[i] = [ownProps[i], obj[ownProps[i]]];
}
return resArray; return resArray;
}; };
@ -53,7 +55,7 @@ export default {
}); });
const targets = ["controller", "component", "route", "model", "adapter"]; const targets = ["controller", "component", "route", "model", "adapter"];
/*eslint no-undef: 0*/
const siteSettings = Wizard.SiteSettings; const siteSettings = Wizard.SiteSettings;
app.register("site-settings:main", siteSettings, { instantiate: false }); app.register("site-settings:main", siteSettings, { instantiate: false });
createHelperContext({ siteSettings }); createHelperContext({ siteSettings });

Dateidiff unterdrückt, weil mindestens eine Zeile zu lang ist

Datei anzeigen

@ -1,5 +1,6 @@
import loadScript from "./load-script"; import loadScript from "./load-script";
import { default as PrettyText } from "pretty-text/pretty-text"; import { default as PrettyText } from "pretty-text/pretty-text";
import Handlebars from "handlebars";
export function cook(text, options) { export function cook(text, options) {
return new Handlebars.SafeString(new PrettyText(options).cook(text)); return new Handlebars.SafeString(new PrettyText(options).cook(text));

Datei anzeigen

@ -2,7 +2,7 @@ import { CANCELLED_STATUS } from "discourse/lib/autocomplete";
import { debounce } from "@ember/runloop"; import { debounce } from "@ember/runloop";
import getUrl from "discourse-common/lib/get-url"; import getUrl from "discourse-common/lib/get-url";
var cache = {}, let cache = {},
cacheTopicId, cacheTopicId,
cacheTime, cacheTime,
currentTerm, currentTerm,
@ -18,7 +18,7 @@ function performSearch(
group, group,
resultsFn resultsFn
) { ) {
var cached = cache[term]; let cached = cache[term];
if (cached) { if (cached) {
resultsFn(cached); resultsFn(cached);
return; return;
@ -37,7 +37,7 @@ function performSearch(
}, },
}); });
var returnVal = CANCELLED_STATUS; let returnVal = CANCELLED_STATUS;
oldSearch oldSearch
.then(function (r) { .then(function (r) {
@ -59,7 +59,7 @@ function organizeResults(r, options) {
return r; return r;
} }
var exclude = options.exclude || [], let exclude = options.exclude || [],
limit = options.limit || 5, limit = options.limit || 5,
users = [], users = [],
emails = [], emails = [],
@ -87,8 +87,9 @@ function organizeResults(r, options) {
if ( if (
results.length > limit && results.length > limit &&
options.term.toLowerCase() !== g.name.toLowerCase() options.term.toLowerCase() !== g.name.toLowerCase()
) ) {
return false; return false;
}
if (exclude.indexOf(g.name) === -1) { if (exclude.indexOf(g.name) === -1) {
groups.push(g); groups.push(g);
results.push(g); results.push(g);
@ -104,7 +105,7 @@ function organizeResults(r, options) {
} }
export default function userSearch(options) { export default function userSearch(options) {
var term = options.term || "", let term = options.term || "",
includeGroups = options.includeGroups, includeGroups = options.includeGroups,
includeMentionableGroups = options.includeMentionableGroups, includeMentionableGroups = options.includeMentionableGroups,
includeMessageableGroups = options.includeMessageableGroups, includeMessageableGroups = options.includeMessageableGroups,
@ -131,7 +132,7 @@ export default function userSearch(options) {
cacheTopicId = topicId; cacheTopicId = topicId;
var clearPromise = setTimeout(function () { let clearPromise = setTimeout(function () {
resolve(CANCELLED_STATUS); resolve(CANCELLED_STATUS);
}, 5000); }, 5000);

Datei anzeigen

@ -19,7 +19,9 @@ const translationExists = (key) => {
const WizardI18n = (key, params = {}) => { const WizardI18n = (key, params = {}) => {
const themeId = getThemeId(); const themeId = getThemeId();
if (!themeId) return I18n.t(key, params); if (!themeId) {
return I18n.t(key, params);
}
const themeKey = `theme_translations.${themeId}.${key}`; const themeKey = `theme_translations.${themeId}.${key}`;

Datei anzeigen

@ -10,7 +10,9 @@ const CustomWizard = EmberObject.extend({
totalSteps: (length) => length, totalSteps: (length) => length,
skip() { skip() {
if (this.required && !this.completed && this.permitted) return; if (this.required && !this.completed && this.permitted) {
return;
}
CustomWizard.skip(this.id); CustomWizard.skip(this.id);
}, },
}); });
@ -29,59 +31,45 @@ CustomWizard.reopenClass({
} }
window.location.href = getUrl(url); window.location.href = getUrl(url);
}, },
});
export function findCustomWizard(wizardId, params = {}) { build(wizardJson) {
let url = `/w/${wizardId}`; if (!wizardJson) {
return null;
let paramKeys = Object.keys(params).filter((k) => {
if (k === "wizard_id") return false;
return !!params[k];
});
if (paramKeys.length) {
url += "?";
paramKeys.forEach((k, i) => {
if (i > 0) {
url += "&";
}
url += `${k}=${params[k]}`;
});
}
return ajax({ url, cache: false, dataType: "json" }).then((result) => {
const wizard = result;
if (!wizard) return null;
if (!wizard.completed) {
wizard.steps = wizard.steps.map((step) => {
const stepObj = Step.create(step);
stepObj.fields.sort((a, b) => {
return parseFloat(a.number) - parseFloat(b.number);
});
let tabindex = 1;
stepObj.fields.forEach((f, i) => {
f.tabindex = tabindex;
if (["date_time"].includes(f.type)) {
tabindex = tabindex + 2;
} else {
tabindex++;
}
});
stepObj.fields = stepObj.fields.map((f) => WizardField.create(f));
return stepObj;
});
} }
if (wizard.categories) { if (!wizardJson.completed && wizardJson.steps) {
wizardJson.steps = wizardJson.steps
.map((step) => {
const stepObj = Step.create(step);
stepObj.fields.sort((a, b) => {
return parseFloat(a.number) - parseFloat(b.number);
});
let tabindex = 1;
stepObj.fields.forEach((f) => {
f.tabindex = tabindex;
if (["date_time"].includes(f.type)) {
tabindex = tabindex + 2;
} else {
tabindex++;
}
});
stepObj.fields = stepObj.fields.map((f) => WizardField.create(f));
return stepObj;
})
.sort((a, b) => {
return parseFloat(a.index) - parseFloat(b.index);
});
}
if (wizardJson.categories) {
let subcatMap = {}; let subcatMap = {};
let categoriesById = {}; let categoriesById = {};
let categories = wizard.categories.map((c) => { let categories = wizardJson.categories.map((c) => {
if (c.parent_category_id) { if (c.parent_category_id) {
subcatMap[c.parent_category_id] = subcatMap[c.parent_category_id] =
subcatMap[c.parent_category_id] || []; subcatMap[c.parent_category_id] || [];
@ -110,12 +98,47 @@ export function findCustomWizard(wizardId, params = {}) {
Discourse.Site.currentProp("categoriesById", categoriesById); Discourse.Site.currentProp("categoriesById", categoriesById);
Discourse.Site.currentProp( Discourse.Site.currentProp(
"uncategorized_category_id", "uncategorized_category_id",
wizard.uncategorized_category_id wizardJson.uncategorized_category_id
); );
} }
return CustomWizard.create(wizard); return CustomWizard.create(wizardJson);
},
});
export function findCustomWizard(wizardId, params = {}) {
let url = `/w/${wizardId}`;
let paramKeys = Object.keys(params).filter((k) => {
if (k === "wizard_id") {
return false;
}
return !!params[k];
});
if (paramKeys.length) {
url += "?";
paramKeys.forEach((k, i) => {
if (i > 0) {
url += "&";
}
url += `${k}=${params[k]}`;
});
}
return ajax({ url, cache: false, dataType: "json" }).then((result) => {
return CustomWizard.build(result);
}); });
} }
let _wizard_store;
export function updateCachedWizard(wizard) {
_wizard_store = wizard;
}
export function getCachedWizard() {
return _wizard_store;
}
export default CustomWizard; export default CustomWizard;

Datei anzeigen

@ -1,22 +1,19 @@
import { getCachedWizard } from "../models/custom";
export default Ember.Route.extend({ export default Ember.Route.extend({
beforeModel() { beforeModel() {
const appModel = this.modelFor("custom"); const wizard = getCachedWizard();
if ( if (wizard && wizard.permitted && !wizard.completed && wizard.start) {
appModel && this.replaceWith("custom.step", wizard.start);
appModel.permitted &&
!appModel.completed &&
appModel.start
) {
this.replaceWith("custom.step", appModel.start);
} }
}, },
model() { model() {
return this.modelFor("custom"); return getCachedWizard();
}, },
setupController(controller, model) { setupController(controller, model) {
if (model) { if (model && model.id) {
const completed = model.get("completed"); const completed = model.get("completed");
const permitted = model.get("permitted"); const permitted = model.get("permitted");
const wizardId = model.get("id"); const wizardId = model.get("id");

Datei anzeigen

@ -1,26 +1,33 @@
import WizardI18n from "../lib/wizard-i18n"; import WizardI18n from "../lib/wizard-i18n";
import { getCachedWizard } from "../models/custom";
export default Ember.Route.extend({ export default Ember.Route.extend({
model(params) { beforeModel() {
const appModel = this.modelFor("custom"); this.set("wizard", getCachedWizard());
const allSteps = appModel.steps; },
if (allSteps) {
const step = allSteps.findBy("id", params.step_id);
return step ? step : allSteps[0];
}
return appModel; model(params) {
const wizard = this.wizard;
if (wizard && wizard.steps) {
const step = wizard.steps.findBy("id", params.step_id);
return step ? step : wizard.steps[0];
} else {
return wizard;
}
}, },
afterModel(model) { afterModel(model) {
if (model.completed) return this.transitionTo("index"); if (model.completed) {
return model.set("wizardId", this.modelFor("custom").id); return this.transitionTo("index");
}
return model.set("wizardId", this.wizard.id);
}, },
setupController(controller, model) { setupController(controller, model) {
let props = { let props = {
step: model, step: model,
wizard: this.modelFor("custom"), wizard: this.wizard,
}; };
if (!model.permitted) { if (!model.permitted) {

Datei anzeigen

@ -1,6 +1,6 @@
/* eslint no-undef: 0 */ /* eslint no-undef: 0*/
import { findCustomWizard } from "../models/custom"; import { findCustomWizard, updateCachedWizard } from "../models/custom";
import { ajax } from "wizard/lib/ajax"; import { ajax } from "wizard/lib/ajax";
export default Ember.Route.extend({ export default Ember.Route.extend({
@ -12,7 +12,9 @@ export default Ember.Route.extend({
return findCustomWizard(params.wizard_id, this.get("queryParams")); return findCustomWizard(params.wizard_id, this.get("queryParams"));
}, },
afterModel() { afterModel(model) {
updateCachedWizard(model);
return ajax({ return ajax({
url: `/site/settings`, url: `/site/settings`,
type: "GET", type: "GET",
@ -25,11 +27,11 @@ export default Ember.Route.extend({
const background = model ? model.get("background") : "AliceBlue"; const background = model ? model.get("background") : "AliceBlue";
Ember.run.scheduleOnce("afterRender", this, function () { Ember.run.scheduleOnce("afterRender", this, function () {
$("body.custom-wizard").css("background", background); $("body.custom-wizard").css("background", background);
if (model) {
$("#custom-wizard-main").addClass(model.get("id").dasherize()); if (model && model.id) {
$("#custom-wizard-main").addClass(model.id.dasherize());
} }
}); });
controller.setProperties({ controller.setProperties({
customWizard: true, customWizard: true,
logoUrl: Wizard.SiteSettings.logo_small, logoUrl: Wizard.SiteSettings.logo_small,

Datei anzeigen

@ -1,13 +1,13 @@
{{#if field.validations}} {{#if field.validations}}
{{#each-in field.validations.above as |type validation|}} {{#each-in field.validations.above as |type validation|}}
{{component validation.component field=field type=type validation=validation}} {{component validation.component field=field type=type validation=validation}}
{{/each-in}} {{/each-in}}
{{yield (hash perform=(action 'perform') autocomplete="off")}} {{yield (hash perform=(action "perform") autocomplete="off")}}
{{#each-in field.validations.below as |type validation|}} {{#each-in field.validations.below as |type validation|}}
{{component validation.component field=field type=type validation=validation}} {{component validation.component field=field type=type validation=validation}}
{{/each-in}} {{/each-in}}
{{else}} {{else}}
{{yield}} {{yield}}
{{/if}} {{/if}}

Datei anzeigen

@ -1,9 +1,9 @@
<label class={{currentStateClass}}> <label class={{currentStateClass}}>
{{#if currentState}} {{#if currentState}}
{{#if insufficientCharactersCategories}} {{#if insufficientCharactersCategories}}
{{html-safe (i18n currentStateKey catLinks=catLinks)}} {{html-safe (wizard-i18n currentStateKey catLinks=catLinks)}}
{{else}} {{else}}
{{i18n currentStateKey}} {{wizard-i18n currentStateKey}}
{{/if}} {{/if}}
{{/if}} {{/if}}
</label> </label>

Datei anzeigen

@ -1,5 +1,5 @@
{{#if isValid}} {{#if isValid}}
{{i18n validMessageKey}} {{wizard-i18n validMessageKey}}
{{else}} {{else}}
{{i18n invalidMessageKey}} {{wizard-i18n invalidMessageKey}}
{{/if}} {{/if}}

Datei anzeigen

@ -25,8 +25,8 @@
{{#if showHyperlinkBox}} {{#if showHyperlinkBox}}
{{wizard-composer-hyperlink {{wizard-composer-hyperlink
addLink=(action 'addLink') addLink=(action "addLink")
hideBox=(action 'hideBox')}} hideBox=(action "hideBox")}}
{{/if}} {{/if}}
{{#if isUploading}} {{#if isUploading}}

Datei anzeigen

@ -2,20 +2,20 @@
<h3>{{wizard-i18n "composer.link_dialog_title"}}</h3> <h3>{{wizard-i18n "composer.link_dialog_title"}}</h3>
{{input {{input
class="composer-link-name" class="composer-link-name"
placeholder=(wizard-i18n 'composer.link_optional_text') placeholder=(wizard-i18n "composer.link_optional_text")
type="text" type="text"
value=linkName}} value=linkName}}
{{input {{input
class="composer-link-url" class="composer-link-url"
placeholder=(wizard-i18n 'composer.link_url_placeholder') placeholder=(wizard-i18n "composer.link_url_placeholder")
type="text" type="text"
value=linkUrl}} value=linkUrl}}
{{d-button {{d-button
label="wizard_composer.modal_ok" label="wizard_composer.modal_ok"
class="add-link btn-primary" class="add-link btn-primary"
click=(action 'addLink')}} click=(action "addLink")}}
{{d-button {{d-button
label="wizard_composer.modal_cancel" label="wizard_composer.modal_cancel"
class="hide-hyperlink-box btn-danger" class="hide-hyperlink-box btn-danger"
click=(action 'hideBox')}} click=(action "hideBox")}}
</div> </div>

Datei anzeigen

@ -1,15 +1,15 @@
<div class='d-editor-overlay hidden'></div> <div class="d-editor-overlay hidden"></div>
<div class='d-editor-container'> <div class="d-editor-container">
{{#if showPreview}} {{#if showPreview}}
<div class="d-editor-preview-wrapper {{if forcePreview 'force-preview'}}"> <div class="d-editor-preview-wrapper {{if forcePreview "force-preview"}}">
<div class="d-editor-preview"> <div class="d-editor-preview">
{{{preview}}} {{html-safe preview}}
</div> </div>
</div> </div>
{{else}} {{else}}
<div class="d-editor-textarea-wrapper"> <div class="d-editor-textarea-wrapper">
<div class='d-editor-button-bar'> <div class="d-editor-button-bar">
{{#each toolbar.groups as |group|}} {{#each toolbar.groups as |group|}}
{{#each group.buttons as |b|}} {{#each group.buttons as |b|}}
{{#if b.popupMenu}} {{#if b.popupMenu}}
@ -24,7 +24,7 @@
)}} )}}
{{else}} {{else}}
<div>{{d.icon}}</div> <div>{{d.icon}}</div>
<button class='wizard-btn {{b.className}}' {{action b.action b}} title="{{b.title}}"> <button class="wizard-btn {{b.className}}" {{action b.action b}} title={{b.title}} type="button">
{{d-icon b.icon}} {{d-icon b.icon}}
{{#if b.label}} {{#if b.label}}
<span class="d-button-label">{{wizard-i18n b.label}}</span> <span class="d-button-label">{{wizard-i18n b.label}}</span>
@ -34,7 +34,7 @@
{{/each}} {{/each}}
{{#unless group.lastGroup}} {{#unless group.lastGroup}}
<div class='d-editor-spacer'></div> <div class="d-editor-spacer"></div>
{{/unless}} {{/unless}}
{{/each}} {{/each}}
</div> </div>

Datei anzeigen

@ -1 +1 @@
{{input type='checkbox' id=field.id checked=field.value tabindex=field.tabindex}} {{input type="checkbox" id=field.id checked=field.value tabindex=field.tabindex}}

Datei anzeigen

@ -8,11 +8,11 @@
afterRefresh=(action "afterRefresh")}} afterRefresh=(action "afterRefresh")}}
<div class="bottom-bar"> <div class="bottom-bar">
<button class='wizard-btn toggle-preview' {{action 'togglePreview'}}> <button class="wizard-btn toggle-preview" {{action "togglePreview"}} type="button">
<span class="d-button-label">{{wizard-i18n togglePreviewLabel}}</span> <span class="d-button-label">{{wizard-i18n togglePreviewLabel}}</span>
</button> </button>
{{#if field.char_counter}} {{#if field.char_counter}}
{{char-counter field.value field.max_length}} {{char-counter field.value field.max_length}}
{{/if}} {{/if}}
</div> </div>

Datei anzeigen

@ -2,4 +2,4 @@
date=dateTime date=dateTime
onChange=(action "onChange") onChange=(action "onChange")
tabindex=field.tabindex tabindex=field.tabindex
}} }}

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen