0
0
Fork 1
Spiegel von https://github.com/paviliondev/discourse-custom-wizard.git synchronisiert 2024-11-10 04:12:53 +01:00

Merge branch 'stable' of github.com:paviliondev/discourse-custom-wizard into stable

Dieser Commit ist enthalten in:
merefield 2024-02-01 08:26:20 +00:00
Commit 48d651c89a
180 geänderte Dateien mit 7927 neuen und 2481 gelöschten Zeilen

Datei anzeigen

@ -1,2 +1,3 @@
3.1.999: 1f35b80f85e5fd1efb7f4851f0845700432febdc
2.7.99: e07a57e398b6b1676ab42a7e34467556fca5416b
2.5.1: bb85b3a0d2c0ab6b59bcb405731c39089ec6731c

13
.github/workflows/discourse-plugin.yml gevendort Normale Datei
Datei anzeigen

@ -0,0 +1,13 @@
name: Discourse Plugin
on:
push:
branches:
- main
pull_request:
schedule:
- cron: "0 0 * * *"
jobs:
ci:
uses: discourse/.github/.github/workflows/discourse-plugin.yml@v1

Datei anzeigen

@ -1,54 +0,0 @@
name: Linting
on:
push:
branches:
- main
- stable
pull_request:
concurrency:
group: plugin-linting-${{ format('{0}-{1}', github.head_ref || github.run_number, github.job) }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: 16
cache: yarn
- name: Yarn install
run: yarn install
- name: Set up ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
bundler-cache: true
- name: ESLint
if: ${{ always() }}
run: yarn eslint --ext .js,.js.es6 --no-error-on-unmatched-pattern {test,assets}/javascripts
- name: Prettier
if: ${{ always() }}
shell: bash
run: |
yarn prettier -v
if [ 0 -lt $(find assets -type f \( -name "*.scss" -or -name "*.js" -or -name "*.es6" \) 2> /dev/null | wc -l) ]; then
yarn prettier --list-different "assets/**/*.{scss,js,es6}"
fi
if [ 0 -lt $(find test -type f \( -name "*.js" -or -name "*.es6" \) 2> /dev/null | wc -l) ]; then
yarn prettier --list-different "test/**/*.{js,es6}"
fi
- name: Rubocop
if: ${{ always() }}
run: bundle exec rubocop .

Datei anzeigen

@ -1,136 +0,0 @@
name: Plugin Tests
on:
push:
branches:
- main
- stable
pull_request:
concurrency:
group: tests-${{ format('{0}-{1}', github.head_ref || github.run_number, github.job) }}
cancel-in-progress: true
jobs:
build:
name: ${{ matrix.build_type }}
runs-on: ubuntu-latest
container: discourse/discourse_test:slim${{ startsWith(matrix.build_type, 'frontend') && '-browsers' || '' }}
timeout-minutes: 30
env:
DISCOURSE_HOSTNAME: www.example.com
RUBY_GLOBAL_METHOD_CACHE_SIZE: 131072
RAILS_ENV: test
PGUSER: discourse
PGPASSWORD: discourse
strategy:
fail-fast: false
matrix:
build_type: ["backend", "frontend"]
steps:
- uses: actions/checkout@v3
with:
repository: discourse/discourse
fetch-depth: 1
- name: Install plugin
uses: actions/checkout@v3
with:
path: plugins/${{ github.event.repository.name }}
fetch-depth: 1
- name: Setup Git
run: |
git config --global user.email "ci@ci.invalid"
git config --global user.name "Discourse CI"
- name: Start redis
run: |
redis-server /etc/redis/redis.conf &
- name: Start Postgres
run: |
chown -R postgres /var/run/postgresql
sudo -E -u postgres script/start_test_db.rb
sudo -u postgres psql -c "CREATE ROLE $PGUSER LOGIN SUPERUSER PASSWORD '$PGPASSWORD';"
- name: Bundler cache
uses: actions/cache@v3
with:
path: vendor/bundle
key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
restore-keys: |
${{ runner.os }}-gem-
- name: Setup gems
run: |
gem install bundler --conservative -v $(awk '/BUNDLED WITH/ { getline; gsub(/ /,""); print $0 }' Gemfile.lock)
bundle config --local path vendor/bundle
bundle config --local deployment true
bundle config --local without development
bundle install --jobs 4
bundle clean
- 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@v3
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Yarn install
run: yarn install
- name: Fetch app state cache
uses: actions/cache@v3
id: app-cache
with:
path: tmp/app-cache
key: >-
${{ hashFiles('.github/workflows/tests.yml') }}-
${{ hashFiles('db/**/*', 'plugins/**/db/**/*') }}-
- name: Restore database from cache
if: steps.app-cache.outputs.cache-hit == 'true'
run: psql -f tmp/app-cache/cache.sql postgres
- name: Restore uploads from cache
if: steps.app-cache.outputs.cache-hit == 'true'
run: rm -rf public/uploads && cp -r tmp/app-cache/uploads public/uploads
- name: Create and migrate database
if: steps.app-cache.outputs.cache-hit != 'true'
run: |
bin/rake db:create
bin/rake db:migrate
- name: Dump database for cache
if: steps.app-cache.outputs.cache-hit != 'true'
run: mkdir -p tmp/app-cache && pg_dumpall > tmp/app-cache/cache.sql
- name: Dump uploads for cache
if: steps.app-cache.outputs.cache-hit != 'true'
run: rm -rf tmp/app-cache/uploads && cp -r public/uploads tmp/app-cache/uploads
- name: Plugin RSpec
if: matrix.build_type == 'backend'
run: bin/rake plugin:spec[${{ github.event.repository.name }}]
- name: Plugin QUnit
if: matrix.build_type == 'frontend'
run: QUNIT_EMBER_CLI=1 bundle exec rake plugin:qunit['${{ github.event.repository.name }}','1200000']
timeout-minutes: 10

Datei anzeigen

@ -1,4 +1,4 @@
All code in this repository is Copyright 2018 by Angus McLeod.
All code in this repository is Copyright 2023 by Angus McLeod.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by

Datei anzeigen

@ -4,22 +4,24 @@ The Custom Wizard Plugin lets you make forms for your Discourse forum. Better us
<img src="https://camo.githubusercontent.com/593432f1fc9658ffca104065668cc88fa21dffcd3002cb78ffd50c71f33a2523/68747470733a2f2f706176696c696f6e2d6173736574732e6e7963332e63646e2e6469676974616c6f6365616e7370616365732e636f6d2f706c7567696e732f77697a6172642d7265706f7369746f72792d62616e6e65722e706e67" alt="" data-canonical-src="https://pavilion-assets.nyc3.cdn.digitaloceanspaces.com/plugins/wizard-repository-banner.png" style="max-width: 100%;" width="400">
👋 Looking to report an issue? We're managing issues for this plugin using our [bug report wizard](https://coop.pavilion.tech/w/bug-report).
## Install
If you're not sure how to install a plugin in Discourse, please follow the [plugin installation guide](https://meta.discourse.org/t/install-a-plugin/19157) or contact your Discourse hosting provider.
## Documentation
[Read the full documentation here](https://discourse.pluginmanager.org/c/discourse-custom-wizard/documentation), or go directly to the relevant section
[Read the full documentation here](https://coop.pavilion.tech/c/82), or go directly to the relevant section
- [Wizard Administration](https://discourse.pluginmanager.org/t/wizard-administration)
- [Wizard Settings](https://discourse.pluginmanager.org/t/wizard-settings)
- [Step Settings](https://discourse.pluginmanager.org/t/step-settings)
- [Field Settings](https://discourse.pluginmanager.org/t/field-settings)
- [Conditional Settings](https://discourse.pluginmanager.org/t/conditional-settings)
- [Field Interpolation](https://discourse.pluginmanager.org/t/field-interpolation)
- [Wizard Examples and Templates](https://discourse.pluginmanager.org/t/wizard-examples-and-templates)
- [Wizard Administration](https://coop.pavilion.tech/t/1602)
- [Wizard Settings](https://coop.pavilion.tech/t/1614)
- [Step Settings](https://coop.pavilion.tech/t/1735)
- [Field Settings](https://coop.pavilion.tech/t/1580)
- [Conditional Settings](https://coop.pavilion.tech/t/1673)
- [Field Interpolation](https://coop.pavilion.tech/t/1557)
- [Handling Dates and Times](https://coop.pavilion.tech/t/1708)
## Support
- [Report a bug](https://discourse.pluginmanager.org/w/bug-report)
- [Report an issue](https://coop.pavilion.tech/w/bug-report)

Datei anzeigen

@ -8,7 +8,7 @@ class CustomWizard::AdminController < ::Admin::AdminController
subscribed: subcription.subscribed?,
subscription_type: subcription.type,
subscription_attributes: CustomWizard::Subscription.attributes,
subscription_client_installed: subcription.client_installed?
subscription_client_installed: CustomWizard::Subscription.client_installed?
)
end

Datei anzeigen

@ -1,6 +1,5 @@
# frozen_string_literal: true
class CustomWizard::StepsController < ::ApplicationController
before_action :ensure_logged_in
class CustomWizard::StepsController < ::CustomWizard::WizardClientController
before_action :ensure_can_update
def update
@ -22,7 +21,7 @@ class CustomWizard::StepsController < ::ApplicationController
if updater.success?
wizard_id = update_params[:wizard_id]
builder = CustomWizard::Builder.new(wizard_id, current_user)
builder = CustomWizard::Builder.new(wizard_id, current_user, guest_id)
@wizard = builder.build(force: true)
current_step = @wizard.find_step(update[:step_id])
@ -85,7 +84,6 @@ class CustomWizard::StepsController < ::ApplicationController
private
def ensure_can_update
@builder = CustomWizard::Builder.new(update_params[:wizard_id], current_user)
raise Discourse::InvalidParameters.new(:wizard_id) if @builder.template.nil?
raise Discourse::InvalidAccess.new if !@builder.wizard || !@builder.wizard.can_access?

Datei anzeigen

@ -1,8 +1,5 @@
# frozen_string_literal: true
class CustomWizard::WizardController < ::ApplicationController
before_action :ensure_plugin_enabled
before_action :ensure_logged_in, only: [:skip]
class CustomWizard::WizardController < ::CustomWizard::WizardClientController
def show
if wizard.present?
render json: CustomWizard::WizardSerializer.new(wizard, scope: guardian, root: false).as_json, status: 200
@ -35,19 +32,8 @@ class CustomWizard::WizardController < ::ApplicationController
def wizard
@wizard ||= begin
builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user)
return nil unless builder.present?
opts = {}
opts[:reset] = params[:reset]
builder.build(opts, params)
end
end
private
def ensure_plugin_enabled
unless SiteSetting.custom_wizard_enabled
redirect_to path("/")
return nil unless @builder.present?
@builder.build({ reset: params[:reset] }, params)
end
end
end

Datei anzeigen

@ -0,0 +1,23 @@
# frozen_string_literal: true
class CustomWizard::WizardClientController < ::ApplicationController
before_action :ensure_plugin_enabled
before_action :set_builder
private
def ensure_plugin_enabled
unless SiteSetting.custom_wizard_enabled
redirect_to path("/")
end
end
def guest_id
return nil if current_user.present?
cookies[:custom_wizard_guest_id] ||= CustomWizard::Wizard.generate_guest_id
cookies[:custom_wizard_guest_id]
end
def set_builder
@builder = CustomWizard::Builder.new(params[:wizard_id].underscore, current_user, guest_id)
end
end

Datei anzeigen

@ -2,12 +2,15 @@
class CustomWizard::SubmissionSerializer < ApplicationSerializer
attributes :id,
:fields,
:submitted_at
has_one :user, serializer: ::BasicUserSerializer, embed: :objects
:submitted_at,
:user
def include_user?
object.user.present?
object.wizard.user.present?
end
def user
::BasicUserSerializer.new(object.wizard.user, root: false).as_json
end
def fields

Datei anzeigen

@ -7,7 +7,7 @@ import userSearch from "discourse/lib/user-search";
import I18n from "I18n";
import Handlebars from "handlebars";
import { isEmpty } from "@ember/utils";
import TextField from "@ember/component/text-field";
import TextField from "discourse/components/text-field";
const template = function (params) {
const options = params.options;

Datei anzeigen

@ -12,14 +12,16 @@ import { alias } from "@ember/object/computed";
import Site from "discourse/models/site";
import { uploadIcon } from "discourse/lib/uploads";
import { dasherize } from "@ember/string";
import showModal from "discourse/lib/show-modal";
const IMAGE_MARKDOWN_REGEX = /!\[(.*?)\|(\d{1,4}x\d{1,4})(,\s*\d{1,3}%)?(.*?)\]\((upload:\/\/.*?)\)(?!(.*`))/g;
const IMAGE_MARKDOWN_REGEX =
/!\[(.*?)\|(\d{1,4}x\d{1,4})(,\s*\d{1,3}%)?(.*?)\]\((upload:\/\/.*?)\)(?!(.*`))/g;
export default ComposerEditor.extend({
classNameBindings: ["fieldClass"],
allowUpload: true,
showLink: false,
showHyperlinkBox: false,
topic: null,
showToolbar: true,
focusTarget: "reply",
@ -29,6 +31,7 @@ export default ComposerEditor.extend({
draftStatus: "null",
replyPlaceholder: alias("field.translatedPlaceholder"),
wizardEventFieldId: null,
composerEventPrefix: "wizard-editor",
@on("didInsertElement")
_composerEditorInit() {
@ -77,24 +80,13 @@ export default ComposerEditor.extend({
$input.on("scroll", this._throttledSyncEditorAndPreviewScroll);
this._bindUploadTarget();
const wizardEventNames = ["insert-text", "replace-text"];
const eventPrefix = this.eventPrefix;
this.appEvents.reopen({
trigger(name, ...args) {
let eventParts = name.split(":");
let currentEventPrefix = eventParts[0];
let currentEventName = eventParts[1];
const field = this.field;
this.editorInputClass = `.${dasherize(field.type)}-${dasherize(
field.id
)} .d-editor-input`;
if (
currentEventPrefix !== "wizard-editor" &&
wizardEventNames.some((wen) => wen === currentEventName)
) {
let wizardEventName = name.replace(eventPrefix, "wizard-editor");
return this._super(wizardEventName, ...args);
} else {
return this._super(name, ...args);
}
},
this._uppyInstance.on("file-added", () => {
this.session.set("wizardEventFieldId", field.id);
});
},
@ -116,12 +108,6 @@ export default ComposerEditor.extend({
return uploadIcon(false, this.siteSettings);
},
click(e) {
if ($(e.target).hasClass("wizard-composer-hyperlink")) {
this.set("showHyperlinkBox", false);
}
},
@bind
_handleImageDeleteButtonClick(event) {
if (!event.target.classList.contains("delete-image-button")) {
@ -132,9 +118,8 @@ export default ComposerEditor.extend({
event.target.closest(".button-wrapper").dataset.imageIndex,
10
);
const matchingPlaceholder = this.get("composer.reply").match(
IMAGE_MARKDOWN_REGEX
);
const matchingPlaceholder =
this.get("composer.reply").match(IMAGE_MARKDOWN_REGEX);
this.session.set("wizardEventFieldId", this.field.id);
this.appEvents.trigger(
@ -165,7 +150,7 @@ export default ComposerEditor.extend({
shortcut: "K",
trimLeading: true,
unshift: true,
sendAction: () => component.set("showHyperlinkBox", true),
sendAction: (event) => component.send("showLinkModal", event),
});
if (this.siteSettings.mentionables_enabled) {
@ -206,17 +191,17 @@ export default ComposerEditor.extend({
this._super(...arguments);
},
addLink(linkName, linkUrl) {
let link = `[${linkName}](${linkUrl})`;
this.appEvents.trigger("wizard-editor:insert-text", {
fieldId: this.field.id,
text: link,
});
this.set("showHyperlinkBox", false);
},
showLinkModal(toolbarEvent) {
let linkText = "";
this._lastSel = toolbarEvent.selected;
hideBox() {
this.set("showHyperlinkBox", false);
if (this._lastSel) {
linkText = this._lastSel.value;
}
showModal("insert-hyperlink").setProperties({
linkText,
toolbarEvent,
});
},
showUploadModal() {

Datei anzeigen

@ -1,15 +0,0 @@
import Component from "@ember/component";
export default Component.extend({
classNames: ["wizard-composer-hyperlink"],
actions: {
addLink() {
this.addLink(this.linkName, this.linkUrl);
},
hideBox() {
this.hideBox();
},
},
});

Datei anzeigen

@ -3,6 +3,7 @@ import discourseComputed from "discourse-common/utils/decorators";
export default DateInput.extend({
useNativePicker: false,
classNameBindings: ["fieldClass"],
@discourseComputed()
placeholder() {

Datei anzeigen

@ -2,6 +2,8 @@ import DateTimeInput from "discourse/components/date-time-input";
import discourseComputed from "discourse-common/utils/decorators";
export default DateTimeInput.extend({
classNameBindings: ["fieldClass"],
@discourseComputed("timeFirst", "tabindex")
timeTabindex(timeFirst, tabindex) {
return timeFirst ? tabindex : tabindex + 1;

Datei anzeigen

@ -2,6 +2,8 @@ import Component from "@ember/component";
import { observes } from "discourse-common/utils/decorators";
export default Component.extend({
classNameBindings: ["fieldClass"],
@observes("time")
setValue() {
this.set("field.value", this.time.format(this.field.format));

Datei anzeigen

@ -4,7 +4,7 @@ import { computed } from "@ember/object";
export default Component.extend(UppyUploadMixin, {
classNames: ["wizard-field-upload"],
classNameBindings: ["isImage"],
classNameBindings: ["isImage", "fieldClass"],
uploading: false,
type: computed(function () {
return `wizard_${this.field.id}`;

Datei anzeigen

@ -1,3 +1,5 @@
import Component from "@ember/component";
export default Component.extend({});
export default Component.extend({
classNameBindings: ["fieldClass"],
});

Datei anzeigen

@ -9,6 +9,7 @@ import CustomWizard, {
updateCachedWizard,
} from "discourse/plugins/discourse-custom-wizard/discourse/models/custom-wizard";
import { alias, not } from "@ember/object/computed";
import discourseLater from "discourse-common/lib/later";
const alreadyWarned = {};
@ -110,29 +111,22 @@ export default Component.extend({
},
autoFocus() {
schedule("afterRender", () => {
const $invalid = $(
".wizard-field.invalid:nth-of-type(1) .wizard-focusable"
);
if ($invalid.length) {
return $invalid.focus();
}
$(".wizard-focusable:first").focus();
discourseLater(() => {
schedule("afterRender", () => {
if ($(".invalid .wizard-focusable").length) {
this.animateInvalidFields();
}
});
});
},
animateInvalidFields() {
schedule("afterRender", () => {
let $element = $(
".invalid input[type=text],.invalid textarea,.invalid input[type=checkbox],.invalid .select-kit"
);
if ($element.length) {
let $invalid = $(".invalid .wizard-focusable");
if ($invalid.length) {
$([document.documentElement, document.body]).animate(
{
scrollTop: $element.offset().top - 200,
scrollTop: $invalid.offset().top - 200,
},
400
);

Datei anzeigen

@ -4,7 +4,10 @@ export default TagChooser.extend({
searchTags(url, data, callback) {
if (this.tagGroups) {
let tagGroupsString = this.tagGroups.join(",");
data.tag_groups = tagGroupsString;
data.filterForInput = {
name: "custom-wizard-tag-chooser",
groups: tagGroupsString,
};
}
return this._super(url, data, callback);

Datei anzeigen

@ -1,7 +1,7 @@
import computed from "discourse-common/utils/decorators";
import { isLTR, isRTL, siteDir } from "discourse/lib/text-direction";
import I18n from "I18n";
import TextField from "@ember/component/text-field";
import TextField from "discourse/components/text-field";
export default TextField.extend({
attributeBindings: [

Datei anzeigen

@ -15,6 +15,7 @@ import {
import Component from "@ember/component";
import { bind, later } from "@ember/runloop";
import I18n from "I18n";
import Subscription from "../mixins/subscription";
const customFieldActionMap = {
topic: ["create_topic", "send_message"],
@ -26,7 +27,7 @@ const customFieldActionMap = {
const values = ["present", "true", "false"];
export default Component.extend({
export default Component.extend(Subscription, {
classNameBindings: [":mapper-selector", "activeType"],
showText: computed("activeType", function () {
@ -116,6 +117,9 @@ export default Component.extend({
groupEnabled: computed("options.groupSelection", "inputType", function () {
return this.optionEnabled("groupSelection");
}),
guestGroup: computed("options.guestGroup", "inputType", function () {
return this.optionEnabled("guestGroup");
}),
userEnabled: computed("options.userSelection", "inputType", function () {
return this.optionEnabled("userSelection");
}),
@ -126,7 +130,29 @@ export default Component.extend({
return this.connector === "is";
}),
groups: alias("site.groups"),
@discourseComputed("site.groups", "guestGroup", "subscriptionType")
groups(groups, guestGroup, subscriptionType) {
let result = groups;
if (!guestGroup) {
return result;
}
if (["standard", "business"].includes(subscriptionType)) {
let guestIndex;
result.forEach((r, index) => {
if (r.id === 0) {
r.name = I18n.t("admin.wizard.selector.label.users");
guestIndex = index;
}
});
result.splice(guestIndex, 0, {
id: -1,
name: I18n.t("admin.wizard.selector.label.guests"),
});
}
return result;
},
categories: alias("site.categories"),
showComboBox: or(
"showWizardField",

Datei anzeigen

@ -32,6 +32,7 @@ export default Component.extend({
pairConnector: options.pairConnector || null,
outputConnector: options.outputConnector || null,
context: options.context || null,
guestGroup: options.guestGroup || false,
};
let inputTypes = ["key", "value", "output"];

Datei anzeigen

@ -7,7 +7,7 @@ export default Component.extend(Subscription, {
@discourseComputed("subscribed")
subscribedIcon(subscribed) {
return subscribed ? "check" : "dash";
return subscribed ? "check" : "times";
},
@discourseComputed("subscribed")

Datei anzeigen

@ -1,6 +1,6 @@
import SingleSelectComponent from "select-kit/components/single-select";
import Subscription from "../mixins/subscription";
import wizardSchema from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema";
import { filterValues } from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema";
import discourseComputed from "discourse-common/utils/decorators";
import I18n from "I18n";
@ -40,9 +40,9 @@ export default SingleSelectComponent.extend(Subscription, {
return allowedTypes;
},
@discourseComputed("feature", "attribute")
@discourseComputed("feature", "attribute", "wizard.allowGuests")
content(feature, attribute) {
return wizardSchema[feature][attribute]
return filterValues(this.wizard, feature, attribute)
.map((value) => {
let allowedSubscriptionTypes = this.allowedSubscriptionTypes(
feature,

Datei anzeigen

@ -4,4 +4,4 @@
{{#if wizardErrorNotice}}
{{d-icon "exclaimation-circle"}}
{{/if}}
{{/if}}
{{/if}}

Datei anzeigen

@ -9,8 +9,7 @@
value=wizardListVal
content=wizardList
onChange=(action "changeWizard")
options=(hash
none="admin.wizard.select"
)}}
options=(hash none="admin.wizard.select")
}}
</div>
</section>
</section>

Datei anzeigen

@ -1,7 +1,10 @@
{{#each site.complete_custom_wizard as |wizard|}}
<div class="row">
<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>
{{/each}}
{{/each}}

Datei anzeigen

@ -4,6 +4,7 @@ import CustomWizardApi from "../models/custom-wizard-api";
import { default as discourseComputed } from "discourse-common/utils/decorators";
import { and, equal, not } from "@ember/object/computed";
import { selectKitContent } from "../lib/wizard";
import { underscore } from "@ember/string";
import Controller from "@ember/controller";
import I18n from "I18n";
@ -20,29 +21,8 @@ export default Controller.extend({
"application/x-www-form-urlencoded",
]),
successCodes: selectKitContent([
100,
101,
102,
200,
201,
202,
203,
204,
205,
206,
207,
208,
226,
300,
301,
302,
303,
303,
304,
305,
306,
307,
308,
100, 101, 102, 200, 201, 202, 203, 204, 205, 206, 207, 208, 226, 300, 301,
302, 303, 303, 304, 305, 306, 307, 308,
]),
@discourseComputed(
@ -118,7 +98,7 @@ export default Controller.extend({
if (authType === "oauth_2") {
this.set("authorizing", true);
ajax(`/admin/wizards/apis/${name.underscore()}/authorize`)
ajax(`/admin/wizards/apis/${underscore(name)}/authorize`)
.catch(popupAjaxError)
.then((result) => {
if (result.success) {
@ -187,11 +167,11 @@ export default Controller.extend({
if (!api[rp]) {
let key = rp.replace("auth", "");
error = `${I18n.t(
`admin.wizard.api.auth.${key.underscore()}`
`admin.wizard.api.auth.${underscore(key)}`
)} is required for ${authType}`;
break;
}
data[rp.underscore()] = api[rp];
data[underscore(rp)] = api[rp];
}
}
@ -221,7 +201,7 @@ export default Controller.extend({
this.set("updating", true);
ajax(`/admin/wizards/api/${name.underscore()}`, {
ajax(`/admin/wizards/api/${underscore(name)}`, {
type: "PUT",
data,
})
@ -244,7 +224,7 @@ export default Controller.extend({
this.set("updating", true);
ajax(`/admin/wizards/api/${name.underscore()}`, {
ajax(`/admin/wizards/api/${underscore(name)}`, {
type: "DELETE",
})
.catch(popupAjaxError)
@ -262,7 +242,7 @@ export default Controller.extend({
return;
}
ajax(`/admin/wizards/api/${name.underscore()}/logs`, {
ajax(`/admin/wizards/api/${underscore(name)}/logs`, {
type: "DELETE",
})
.catch(popupAjaxError)

Datei anzeigen

@ -10,6 +10,7 @@ import { later, scheduleOnce } from "@ember/runloop";
import Controller from "@ember/controller";
import copyText from "discourse/lib/copy-text";
import I18n from "I18n";
import { filterValues } from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema";
export default Controller.extend({
hasName: notEmpty("wizard.name"),
@ -59,6 +60,19 @@ export default Controller.extend({
}
return wizardFieldList(steps);
},
@discourseComputed("fieldTypes", "wizard.allowGuests")
filteredFieldTypes(fieldTypes) {
const fieldTypeIds = fieldTypes.map((f) => f.id);
const allowedTypeIds = filterValues(
this.wizard,
"field",
"type",
fieldTypeIds
);
return fieldTypes.filter((f) => allowedTypeIds.includes(f.id));
},
getErrorMessage(result) {
if (result.backend_validation_error) {
return result.backend_validation_error;

Datei anzeigen

@ -5,7 +5,10 @@ export default Controller.extend({
title: "admin.wizard.after_time_modal.title",
setup() {
this.set("bufferedDateTime", moment(this.model.dateTime));
this.set(
"bufferedDateTime",
this.model.dateTime ? moment(this.model.dateTime) : moment(Date.now())
);
},
@discourseComputed("bufferedDateTime")

Datei anzeigen

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

Datei anzeigen

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

Datei anzeigen

@ -69,7 +69,10 @@ export default {
},
_wizardInsertText(text, options) {
if (this.session.wizardEventFieldId === this.fieldId) {
if (
this.session.wizardEventFieldId === this.fieldId &&
this.element
) {
this.insertText(text, options);
}
},

Datei anzeigen

@ -1,14 +1,16 @@
import ApplicationRoute from "discourse/routes/application";
import DiscourseURL from "discourse/lib/url";
import { withPluginApi } from "discourse/lib/plugin-api";
import { dasherize } from "@ember/string";
export default {
name: "custom-wizard-redirect",
after: "message-bus",
initialize: function (container) {
initialize(container) {
const messageBus = container.lookup("service:message-bus");
const siteSettings = container.lookup("service:site-settings");
if (!siteSettings.custom_wizard_enabled || !messageBus) {
if (!siteSettings.custom_wizard_enabled) {
return;
}
@ -17,28 +19,26 @@ export default {
window.location.href = wizardUrl;
});
ApplicationRoute.reopen({
actions: {
willTransition(transition) {
const redirectToWizard = this.get("currentUser.redirect_to_wizard");
const excludedPaths = this.siteSettings.wizard_redirect_exclude_paths
withPluginApi("0.8.36", (api) => {
api.onAppEvent("page:changed", (data) => {
const currentUser = api.getCurrentUser();
if (currentUser) {
const redirectToWizard = currentUser.redirect_to_wizard;
const excludedPaths = siteSettings.wizard_redirect_exclude_paths
.split("|")
.concat(["loading"]);
if (
redirectToWizard &&
(!transition.intent.name ||
!excludedPaths.find((p) => {
return transition.intent.name.indexOf(p) > -1;
}))
data.currentRouteName !== "customWizardStep" &&
!excludedPaths.find((p) => {
return data.currentRouteName.indexOf(p) > -1;
})
) {
transition.abort();
window.location = "/w/" + redirectToWizard.dasherize();
DiscourseURL.routeTo(`/w/${dasherize(redirectToWizard)}`);
}
return this._super(transition);
},
},
}
});
});
},
};

Datei anzeigen

@ -35,6 +35,7 @@ function inputTypesContent(options = {}) {
const connectors = {
pair: [
"equal",
"not_equal",
"greater",
"less",
"greater_or_equal",

Datei anzeigen

@ -72,6 +72,7 @@ const field = {
required: null,
type: null,
condition: null,
tag_groups: null,
},
types: {},
mapped: ["prefill", "content", "condition", "index"],
@ -210,11 +211,42 @@ const action = {
objectArrays: {},
};
const filters = {
allow_guests: {
field: {
type: [
"text",
"textarea",
"text_only",
"date",
"time",
"date_time",
"number",
"checkbox",
"url",
"dropdown",
"tag",
"category",
"group",
"user_selector",
],
},
action: {
type: ["route_to", "send_message"],
},
},
};
const custom_field = {
klass: ["topic", "post", "group", "category"],
type: ["string", "boolean", "integer", "json"],
};
export function buildFieldTypes(types) {
wizardSchema.field.types = types;
wizardSchema.field.type = Object.keys(types);
}
field.type = Object.keys(field.types);
action.type = Object.keys(action.types);
@ -224,16 +256,29 @@ const wizardSchema = {
field,
custom_field,
action,
filters,
};
export function buildFieldTypes(types) {
wizardSchema.field.types = types;
}
export function buildFieldValidations(validations) {
wizardSchema.field.validations = validations;
}
export function filterValues(currentWizard, feature, attribute, values = null) {
values = values || wizardSchema[feature][attribute];
if (currentWizard && currentWizard.allowGuests) {
const filteredFeature = wizardSchema.filters.allow_guests[feature];
if (filteredFeature) {
const filtered = filteredFeature[attribute];
if (filtered) {
values = values.filter((v) => filtered.includes(v));
}
}
}
return values;
}
const siteSettings = getOwner(this).lookup("service:site-settings");
if (siteSettings.wizard_apis_enabled) {
wizardSchema.action.types.send_to_api = {

Datei anzeigen

@ -4,6 +4,8 @@ import { get, set } from "@ember/object";
import Mixin from "@ember/object/mixin";
import { deepEqual } from "discourse-common/lib/object";
const observedCache = [];
export default Mixin.create({
didInsertElement() {
this._super(...arguments);
@ -32,7 +34,13 @@ export default Mixin.create({
};
listProperties(componentType, opts).forEach((property) => {
obj.removeObserver(property, this, this.toggleUndo);
if (observedCache.includes(property)) {
obj.removeObserver(property, this, this.toggleUndo);
let index = observedCache.indexOf(property);
if (index !== -1) {
observedCache.splice(index, 1);
}
}
});
},
@ -45,6 +53,9 @@ export default Mixin.create({
};
listProperties(componentType, opts).forEach((property) => {
if (observedCache.indexOf(property) === -1) {
observedCache.push(property);
}
obj.addObserver(property, this, this.toggleUndo);
});
},

Datei anzeigen

@ -5,8 +5,20 @@ import wizardSchema from "../lib/wizard-schema";
import { Promise } from "rsvp";
import { ajax } from "discourse/lib/ajax";
import { popupAjaxError } from "discourse/lib/ajax-error";
import discourseComputed from "discourse-common/utils/decorators";
const GUEST_GROUP_ID = -1;
const CustomWizardAdmin = EmberObject.extend({
@discourseComputed("permitted.@each.output")
allowGuests(permitted) {
return (
permitted &&
permitted.filter((p) => p.output && p.output.includes(GUEST_GROUP_ID))
.length
);
},
save(opts) {
return new Promise((resolve, reject) => {
let wizard = this.buildJson(this, "wizard");

Datei anzeigen

@ -72,7 +72,7 @@ export default EmberObject.extend(ValidState, {
valid = true;
}
this.setValid(valid);
this.setValid(Boolean(valid));
return valid;
},

Datei anzeigen

@ -10,6 +10,12 @@ export default DiscourseRoute.extend({
}
},
afterModel(model) {
if (model === null) {
return this.transitionTo("adminWizardsApi");
}
},
setupController(controller, model) {
controller.set("api", model);
},

Datei anzeigen

@ -7,6 +7,12 @@ export default DiscourseRoute.extend({
return CustomWizardLogs.list(params.wizardId);
},
afterModel(model) {
if (model === null) {
return this.transitionTo("adminWizardsLogs");
}
},
setupController(controller, model) {
controller.setProperties({
wizard: model.wizard,

Datei anzeigen

@ -8,6 +8,12 @@ export default DiscourseRoute.extend({
return CustomWizardAdmin.submissions(params.wizardId);
},
afterModel(model) {
if (model === null) {
return this.transitionTo("adminWizardsSubmissions");
}
},
setupController(controller, model) {
const { fields, submissions } = formatModel(model);

Datei anzeigen

@ -4,13 +4,7 @@ import Route from "@ember/routing/route";
export default Route.extend({
beforeModel() {
const wizard = getCachedWizard();
if (
wizard &&
wizard.user &&
wizard.permitted &&
!wizard.completed &&
wizard.start
) {
if (wizard && wizard.permitted && !wizard.completed && wizard.start) {
this.replaceWith("customWizardStep", wizard.start);
}
},
@ -26,7 +20,7 @@ export default Route.extend({
const wizardId = model.get("id");
const user = model.get("user");
const name = model.get("name");
const requiresLogin = !user;
const requiresLogin = !user && !permitted;
const notPermitted = !permitted;
const props = {

Datei anzeigen

@ -1,13 +1,15 @@
import I18n from "I18n";
import { getCachedWizard } from "../models/custom-wizard";
import Route from "@ember/routing/route";
import { scrollTop } from "discourse/mixins/scroll-top";
import { action } from "@ember/object";
export default Route.extend({
beforeModel() {
const wizard = getCachedWizard();
this.set("wizard", wizard);
if (!wizard || !wizard.user || !wizard.permitted || wizard.completed) {
if (!wizard || !wizard.permitted || wizard.completed) {
this.replaceWith("customWizard");
}
},
@ -48,4 +50,10 @@ export default Route.extend({
controller.setProperties(props);
},
@action
didTransition() {
scrollTop();
return true;
},
});

Datei anzeigen

@ -1,6 +1,7 @@
import { findCustomWizard, updateCachedWizard } from "../models/custom-wizard";
import I18n from "I18n";
import DiscourseRoute from "discourse/routes/discourse";
import bootbox from "bootbox";
export default DiscourseRoute.extend({
titleToken() {

Datei anzeigen

@ -8,7 +8,12 @@
{{/if}}
{{/if}}
{{d-button label="admin.wizard.api.save" action=(action "save") class="btn-primary" disabled=saveDisabled}}
{{d-button
label="admin.wizard.api.save"
action=(action "save")
class="btn-primary"
disabled=saveDisabled
}}
{{#if showRemove}}
{{d-button action=(action "remove") label="admin.wizard.api.remove"}}
@ -32,13 +37,19 @@
<div class="metadata">
<div class="title">
<label>{{i18n "admin.wizard.api.title"}}</label>
{{input value=api.title placeholder=(i18n "admin.wizard.api.title_placeholder")}}
<Input
@value={{this.api.title}}
placeholder={{i18n "admin.wizard.api.title_placeholder"}}
/>
</div>
<div class="name {{nameClass}}">
<label>{{i18n "admin.wizard.api.name"}}</label>
{{#if api.isNew}}
{{input value=api.name placeholder=(i18n "admin.wizard.api.name_placeholder")}}
<Input
@value={{this.api.name}}
placeholder={{i18n "admin.wizard.api.name_placeholder"}}
/>
{{else}}
<span>{{api.name}}</span>
{{/if}}
@ -56,10 +67,12 @@
<span>{{authErrorMessage}}</span>
{{/if}}
{{/if}}
{{d-button label="admin.wizard.api.auth.btn"
action=(action "authorize")
disabled=authDisabled
class="btn-primary"}}
{{d-button
label="admin.wizard.api.auth.btn"
action=(action "authorize")
disabled=authDisabled
class="btn-primary"
}}
{{/if}}
</div>
@ -93,9 +106,8 @@
value=api.authType
content=authorizationTypes
onChange=(action (mut api.authType))
options=(hash
none="admin.wizard.api.auth.type_none"
)}}
options=(hash none="admin.wizard.api.auth.type_none")
}}
</div>
</div>
@ -104,7 +116,7 @@
<div class="control-group">
<label>{{i18n "admin.wizard.api.auth.url"}}</label>
<div class="controls">
{{input value=api.authUrl}}
<Input @value={{this.api.authUrl}} />
</div>
</div>
{{/if}}
@ -112,21 +124,21 @@
<div class="control-group">
<label>{{i18n "admin.wizard.api.auth.token_url"}}</label>
<div class="controls">
{{input value=api.tokenUrl}}
<Input @value={{this.api.tokenUrl}} />
</div>
</div>
<div class="control-group">
<label>{{i18n "admin.wizard.api.auth.client_id"}}</label>
<div class="controls">
{{input value=api.clientId}}
<Input @value={{this.api.clientId}} />
</div>
</div>
<div class="control-group">
<label>{{i18n "admin.wizard.api.auth.client_secret"}}</label>
<div class="controls">
{{input value=api.clientSecret}}
<Input @value={{this.api.clientSecret}} />
</div>
</div>
@ -135,12 +147,26 @@
<div class="controls">
{{#each api.authParams as |param|}}
<div class="param">
{{input value=param.key placeholder=(i18n "admin.wizard.key")}}
{{input value=param.value placeholder=(i18n "admin.wizard.value")}}
{{d-button action=(action "removeParam") actionParam=param icon="times"}}
<Input
@value={{this.param.key}}
placeholder={{i18n "admin.wizard.key"}}
/>
<Input
@value={{this.param.value}}
placeholder={{i18n "admin.wizard.value"}}
/>
{{d-button
action=(action "removeParam")
actionParam=param
icon="times"
}}
</div>
{{/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>
{{/if}}
@ -149,14 +175,14 @@
<div class="control-group">
<label>{{i18n "admin.wizard.api.auth.username"}}</label>
<div class="controls">
{{input value=api.username}}
<Input @value={{this.api.username}} />
</div>
</div>
<div class="control-group">
<label>{{i18n "admin.wizard.api.auth.password"}}</label>
<div class="controls">
{{input value=api.password}}
<Input @value={{this.api.password}} />
</div>
</div>
{{/if}}
@ -225,7 +251,11 @@
</div>
<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}}
<div class="endpoint-list">
@ -235,38 +265,43 @@
<div class="endpoint">
<div class="endpoint-">
<div class="top">
{{input value=endpoint.name
placeholder=(i18n "admin.wizard.api.endpoint.name")}}
{{input value=endpoint.url
placeholder=(i18n "admin.wizard.api.endpoint.url")
class="endpoint-url"}}
{{d-button action=(action "removeEndpoint")
actionParam=endpoint
icon="times"
class="remove-endpoint"}}
<Input
@value={{endpoint.name}}
placeholder={{i18n "admin.wizard.api.endpoint.name"}}
/>
<Input
@value={{endpoint.url}}
placeholder={{i18n "admin.wizard.api.endpoint.url"}}
class="endpoint-url"
/>
{{d-button
action=(action "removeEndpoint")
actionParam=endpoint
icon="times"
class="remove-endpoint"
}}
</div>
<div class="bottom">
{{combo-box
content=endpointMethods
value=endpoint.method
onChange=(action (mut endpoint.method))
options=(hash
none="admin.wizard.api.endpoint.method"
)}}
options=(hash none="admin.wizard.api.endpoint.method")
}}
{{combo-box
content=contentTypes
value=endpoint.content_type
onChange=(action (mut endpoint.content_type))
options=(hash
none="admin.wizard.api.endpoint.content_type"
)}}
options=(hash none="admin.wizard.api.endpoint.content_type")
}}
{{multi-select
value=endpoint.success_codes
content=successCodes
onChange=(action (mut endpoint.success_codes))
options=(hash
none="admin.wizard.api.endpoint.success_codes"
)}}
)
}}
</div>
</div>
</div>
@ -284,7 +319,8 @@
{{d-button
action=(action "clearLogs")
class="clear-logs"
label="admin.wizard.api.log.clear"}}
label="admin.wizard.api.log.clear"
}}
</div>
</div>
@ -304,7 +340,10 @@
<td>{{logentry.time}}</td>
<td class="user-image">
<div class="user-image-inner">
<a href={{logentry.userpath}} data-user-card={{logentry.username}}>{{avatar logentry imageSize="medium"}}</a>
<a
href={{logentry.userpath}}
data-user-card={{logentry.username}}
>{{avatar logentry imageSize="medium"}}</a>
</div>
</td>
<td>{{logentry.status}}</td>
@ -315,4 +354,4 @@
</tbody>
</table>
</div>
</div>
</div>

Datei anzeigen

@ -3,16 +3,16 @@
value=apiName
content=apiList
onChange=(route-action "changeApi")
options=(hash
none="admin.wizard.api.select"
)}}
options=(hash none="admin.wizard.api.select")
}}
{{d-button
action=(route-action "createApi")
label="admin.wizard.api.create"
icon="plus"}}
icon="plus"
}}
</div>
<div class="admin-wizard-container">
{{outlet}}
</div>
</div>

Datei anzeigen

@ -5,7 +5,8 @@
{{d-button
label="admin.wizard.custom_field.add"
icon="plus"
action=(action "addField")}}
action=(action "addField")
}}
</div>
</div>
@ -14,7 +15,8 @@
opts=messageOpts
type=messageType
url=documentationUrl
component="custom_fields"}}
component="custom_fields"
}}
<div class="admin-wizard-container">
{{#if customFields}}
@ -32,9 +34,10 @@
{{custom-field-input
field=field
removeField=(action "removeField")
saveField=(action "saveField")}}
saveField=(action "saveField")
}}
{{/each}}
</tbody>
</table>
{{/if}}
</div>
</div>

Datei anzeigen

@ -9,7 +9,8 @@
label="refresh"
icon="sync"
action=(action "refresh")
class="refresh"}}
class="refresh"
}}
</div>
</div>
@ -31,7 +32,10 @@
{{#each logs as |log|}}
<tr>
{{#each-in log as |field value|}}
<td class="small">{{wizard-table-field field=field value=value}}</td>
<td class="small">{{wizard-table-field
field=field
value=value
}}</td>
{{/each-in}}
</tr>
{{/each}}
@ -42,4 +46,4 @@
{{conditional-loading-spinner condition=refreshing}}
{{/load-more}}
</div>
{{/if}}
{{/if}}

Datei anzeigen

@ -3,17 +3,17 @@
value=wizardId
content=wizardList
onChange=(route-action "changeWizard")
options=(hash
none="admin.wizard.select"
)}}
options=(hash none="admin.wizard.select")
}}
</div>
{{wizard-message
key=messageKey
opts=messageOpts
url=documentationUrl
component="logs"}}
component="logs"
}}
<div class="admin-wizard-container">
{{outlet}}
</div>
</div>

Datei anzeigen

@ -11,30 +11,35 @@
</div>
{{/if}}
{{input
<Input
id="custom-wizard-file-upload"
type="file"
@type="file"
accept="application/json"
input=(action "setFile")}}
{{on "input" (action "setFile")}}
/>
{{d-button
id="upload-button"
label="admin.wizard.manager.upload"
action=(action "upload")}}
action=(action "upload")
}}
{{d-button
id="import-button"
label="admin.wizard.manager.import"
action=(action "import")
disabled=importDisabled}}
disabled=importDisabled
}}
{{d-button
id="export-button"
label="admin.wizard.manager.export"
action=(action "export")
disabled=exportDisabled}}
disabled=exportDisabled
}}
{{d-button
id="destroy-button"
label="admin.wizard.manager.destroy"
action=(action "destroy")
disabled=destoryDisabled}}
disabled=destoryDisabled
}}
</div>
</div>
@ -45,7 +50,8 @@
opts=messageOpts
items=messageItems
loading=loading
component="manager"}}
component="manager"
}}
<div class="admin-wizard-container">
<table class="table grid">
@ -65,19 +71,21 @@
{{/link-to}}
</td>
<td class="control-column">
{{input
type="checkbox"
<Input
@type="checkbox"
class="export"
change=(action "selectWizard")}}
{{on "change" (action "selectWizard")}}
/>
</td>
<td class="control-column">
{{input
type="checkbox"
<Input
@type="checkbox"
class="destroy"
change=(action "selectWizard")}}
{{on "change" (action "selectWizard")}}
/>
</td>
</tr>
{{/each}}
</tbody>
</table>
</div>
</div>

Datei anzeigen

@ -58,4 +58,4 @@
{{conditional-loading-spinner condition=loadingMore}}
{{/load-more}}
</div>
{{/if}}
{{/if}}

Datei anzeigen

@ -3,17 +3,17 @@
value=wizardId
content=wizardList
onChange=(route-action "changeWizard")
options=(hash
none="admin.wizard.select"
)}}
options=(hash none="admin.wizard.select")
}}
</div>
{{wizard-message
key=messageKey
opts=messageOpts
url=documentationUrl
component="submissions"}}
component="submissions"
}}
<div class="admin-wizard-container">
{{outlet}}
</div>
</div>

Datei anzeigen

@ -1,18 +1,31 @@
{{#if wizard}}
<div class="wizard-header large">
{{input
<Input
@value={{this.wizard.name}}
name="name"
value=wizard.name
placeholderKey="admin.wizard.name_placeholder"}}
placeholder={{i18n "admin.wizard.name_placeholder"}}
/>
<div class="wizard-url">
{{#if wizard.name}}
{{#if copiedUrl}}
{{d-button class="btn-hover pull-right" icon="copy" label="ip_lookup.copied"}}
{{d-button
class="btn-hover pull-right"
icon="copy"
label="ip_lookup.copied"
}}
{{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}}
<a href={{wizardUrl}} target="_blank" rel="noopener noreferrer">{{wizardUrl}}</a>
<a
href={{wizardUrl}}
target="_blank"
rel="noopener noreferrer"
>{{wizardUrl}}</a>
{{/if}}
</div>
</div>
@ -23,11 +36,12 @@
<label>{{i18n "admin.wizard.background"}}</label>
</div>
<div class="setting-value">
{{input
<Input
@value={{this.wizard.background}}
name="background"
value=wizard.background
placeholderKey="admin.wizard.background_placeholder"
class="small"}}
placeholder={{i18n "admin.wizard.background_placeholder"}}
class="small"
/>
</div>
</div>
@ -41,9 +55,8 @@
valueProperty="id"
value=wizard.theme_id
onChange=(action (mut wizard.theme_id))
options=(hash
none="admin.wizard.no_theme"
)}}
options=(hash none="admin.wizard.no_theme")
}}
</div>
</div>
</div>
@ -58,7 +71,7 @@
<label>{{i18n "admin.wizard.save_submissions"}}</label>
</div>
<div class="setting-value">
{{input type="checkbox" checked=wizard.save_submissions}}
<Input @type="checkbox" @checked={{this.wizard.save_submissions}} />
<span>{{i18n "admin.wizard.save_submissions_label"}}</span>
</div>
</div>
@ -68,7 +81,7 @@
<label>{{i18n "admin.wizard.multiple_submissions"}}</label>
</div>
<div class="setting-value">
{{input type="checkbox" checked=wizard.multiple_submissions}}
<Input @type="checkbox" @checked={{this.wizard.multiple_submissions}} />
<span>{{i18n "admin.wizard.multiple_submissions_label"}}</span>
</div>
</div>
@ -78,7 +91,7 @@
<label>{{i18n "admin.wizard.after_signup"}}</label>
</div>
<div class="setting-value">
{{input type="checkbox" checked=wizard.after_signup}}
<Input @type="checkbox" @checked={{this.wizard.after_signup}} />
<span>{{i18n "admin.wizard.after_signup_label"}}</span>
</div>
</div>
@ -88,7 +101,7 @@
<label>{{i18n "admin.wizard.prompt_completion"}}</label>
</div>
<div class="setting-value">
{{input type="checkbox" checked=wizard.prompt_completion}}
<Input @type="checkbox" @checked={{this.wizard.prompt_completion}} />
<span>{{i18n "admin.wizard.prompt_completion_label"}}</span>
</div>
</div>
@ -98,13 +111,14 @@
<label>{{i18n "admin.wizard.after_time"}}</label>
</div>
<div class="setting-value">
{{input type="checkbox" checked=wizard.after_time}}
<Input @type="checkbox" @checked={{this.wizard.after_time}} />
<span>{{i18n "admin.wizard.after_time_label"}}</span>
{{d-button
action=(action "setNextSessionScheduled")
translatedLabel=nextSessionScheduledLabel
class="btn-after-time"
icon="far-calendar"}}
icon="far-calendar"
}}
</div>
</div>
@ -114,7 +128,7 @@
<label>{{i18n "admin.wizard.required"}}</label>
</div>
<div class="setting-value">
{{input type="checkbox" checked=wizard.required}}
<Input @type="checkbox" @checked={{this.wizard.required}} />
<span>{{i18n "admin.wizard.required_label"}}</span>
</div>
</div>
@ -124,7 +138,7 @@
<label>{{i18n "admin.wizard.restart_on_revisit"}}</label>
</div>
<div class="setting-value">
{{input type="checkbox" checked=wizard.restart_on_revisit}}
<Input @type="checkbox" @checked={{this.wizard.restart_on_revisit}} />
<span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
</div>
</div>
@ -140,19 +154,18 @@
context="wizard"
inputTypes="assignment,validation"
groupSelection="output"
guestGroup=true
userFieldSelection="key"
textSelection="value"
inputConnector="and"
)}}
)
}}
</div>
</div>
{{/wizard-subscription-container}}
</div>
{{wizard-links
itemType="step"
current=currentStep
items=wizard.steps}}
{{wizard-links itemType="step" current=currentStep items=wizard.steps}}
{{#if currentStep}}
{{wizard-custom-step
@ -160,15 +173,17 @@
wizard=wizard
currentField=currentField
wizardFields=wizardFields
fieldTypes=fieldTypes
subscribed=subscribed}}
fieldTypes=filteredFieldTypes
subscribed=subscribed
}}
{{/if}}
{{wizard-links
itemType="action"
current=currentAction
items=wizard.actions
generateLabels=true}}
generateLabels=true
}}
{{#each wizard.actions as |wizardAction|}}
{{wizard-custom-action
@ -178,11 +193,17 @@
apis=apis
removeAction="removeAction"
wizardFields=wizardFields
fieldTypes=fieldTypes}}
fieldTypes=filteredFieldTypes
}}
{{/each}}
<div class="admin-wizard-buttons">
<button {{action "save"}} disabled={{disableSave}} class="btn btn-primary" type="button">
<button
{{action "save"}}
disabled={{disableSave}}
class="btn btn-primary"
type="button"
>
{{i18n "admin.wizard.save"}}
</button>
@ -198,4 +219,4 @@
<span class="error">{{d-icon "times"}}{{error}}</span>
{{/if}}
</div>
{{/if}}
{{/if}}

Datei anzeigen

@ -3,21 +3,18 @@
value=wizardListVal
content=wizardList
onChange=(route-action "changeWizard")
options=(hash
none="admin.wizard.select"
)}}
options=(hash none="admin.wizard.select")
}}
{{d-button
action=(route-action "createWizard")
label="admin.wizard.create"
icon="plus"}}
icon="plus"
}}
</div>
{{wizard-message
key=messageKey
url=messageUrl
component="wizard"}}
{{wizard-message key=messageKey url=messageUrl component="wizard"}}
<div class="admin-wizard-container settings">
{{outlet}}
</div>
</div>

Datei anzeigen

@ -1,12 +1,21 @@
{{#admin-nav}}
{{nav-item route="adminWizardsWizard" label="admin.wizard.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="adminWizardsCustomFields"
label="admin.wizard.custom_field.nav_label"
}}
{{nav-item
route="adminWizardsSubmissions"
label="admin.wizard.submissions.nav_label"
}}
{{#if showApi}}
{{nav-item route="adminWizardsApi" label="admin.wizard.api.nav_label"}}
{{/if}}
{{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"
}}
<div class="admin-actions">
{{wizard-subscription-badge}}
@ -16,4 +25,4 @@
<div class="admin-container">
{{outlet}}
</div>
</div>

Datei anzeigen

@ -5,9 +5,8 @@
feature="custom_field"
attribute="klass"
onChange=(action (mut field.klass))
options=(hash
none="admin.wizard.custom_field.klass.select"
)}}
options=(hash none="admin.wizard.custom_field.klass.select")
}}
</td>
<td>
{{wizard-subscription-selector
@ -15,23 +14,22 @@
feature="custom_field"
attribute="type"
onChange=(action (mut field.type))
options=(hash
none="admin.wizard.custom_field.type.select"
)}}
options=(hash none="admin.wizard.custom_field.type.select")
}}
</td>
<td class="input">
{{input
value=field.name
placeholder=(i18n "admin.wizard.custom_field.name.select")}}
<Input
@value={{this.field.name}}
placeholder={{i18n "admin.wizard.custom_field.name.select"}}
/>
</td>
<td class="multi-select">
{{multi-select
value=field.serializers
content=serializerContent
onChange=(action (mut field.serializers))
options=(hash
none="admin.wizard.custom_field.serializers.select"
)}}
options=(hash none="admin.wizard.custom_field.serializers.select")
}}
</td>
<td class="actions">
{{#if loading}}
@ -45,16 +43,15 @@
action=(action "destroy")
icon="trash-alt"
class="destroy"
disabled=destroyDisabled}}
disabled=destroyDisabled
}}
{{d-button
icon="save"
action=(action "save")
disabled=saveDisabled
class="save"}}
{{d-button
action=(action "close")
icon="times"
disabled=closeDisabled}}
class="save"
}}
{{d-button action=(action "close") icon="times" disabled=closeDisabled}}
</td>
{{else}}
<td><label>{{field.klass}}</label></td>
@ -80,4 +77,4 @@
{{d-button action=(action "edit") icon="pencil-alt"}}
</td>
{{/if}}
{{/if}}
{{/if}}

Datei anzeigen

@ -14,7 +14,8 @@
wizardComposer=true
fieldId=field.id
disabled=disableTextarea
outletArgs=(hash composer=composer editorType="composer")}}
outletArgs=(hash composer=composer editorType="composer")
}}
<input
type="file"
@ -22,4 +23,4 @@
class="wizard-composer-upload"
accept={{allowedFileTypes}}
multiple
>
/>

Datei anzeigen

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

Datei anzeigen

@ -1,11 +1,11 @@
{{input
type=inputType
<Input
@type={{this.inputType}}
@value={{readonly this.value}}
class="date-picker"
placeholder=placeholder
value=(readonly value)
input=(action "onChangeDate")
tabindex=tabindex
placeholder={{this.placeholder}}
tabindex={{this.tabindex}}
{{on "input" (action "onChangeDate")}}
autocomplete="off"
}}
/>
<div class="picker-container"></div>
<div class="picker-container"></div>

Datei anzeigen

@ -26,9 +26,5 @@
{{/if}}
{{#if clearable}}
{{d-button
class="clear-date-time"
icon="times"
action=(action "onClear")
}}
{{/if}}
{{d-button class="clear-date-time" icon="times" action=(action "onClear")}}
{{/if}}

Datei anzeigen

@ -2,7 +2,7 @@
<div class="d-editor-container">
{{#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">
{{html-safe preview}}
</div>
@ -18,13 +18,16 @@
onExpand=(action b.action b)
class=b.className
content=popupMenuOptions
options=(hash
popupTitle=b.title
icon=b.icon
)}}
options=(hash popupTitle=b.title icon=b.icon)
}}
{{else}}
<div>{{d.icon}}</div>
<button class="wizard-btn {{b.className}}" {{action b.action b}} title={{b.title}} type="button">
<button
class="wizard-btn {{b.className}}"
{{action b.action b}}
title={{b.title}}
type="button"
>
{{d-icon b.icon}}
{{#if b.label}}
<span class="d-button-label">{{i18n b.label}}</span>
@ -40,7 +43,12 @@
</div>
{{conditional-loading-spinner condition=loading}}
{{textarea tabindex=tabindex value=value class="d-editor-input" placeholder=placeholder}}
<Textarea
tabindex={{this.tabindex}}
@value={{this.value}}
class="d-editor-input"
placeholder={{this.placeholder}}
/>
</div>
{{/if}}
</div>
</div>

Datei anzeigen

@ -1,8 +1,8 @@
{{custom-wizard-category-selector
categories=categories
class=fieldClass
whitelist=field.content
onChange=(action (mut categories))
tabindex=field.tabindex
options=(hash
maximum=field.limit
)}}
options=(hash maximum=field.limit)
}}

Datei anzeigen

@ -1 +1,7 @@
{{input type="checkbox" id=field.id checked=field.value tabindex=field.tabindex}}
<Input
id={{this.field.id}}
@type="checkbox"
@checked={{this.field.value}}
tabindex={{this.field.tabindex}}
class={{this.fieldClass}}
/>

Datei anzeigen

@ -2,4 +2,4 @@
<div class="d-editor-preview">
{{html-safe field.preview_template}}
</div>
</div>
</div>

Datei anzeigen

@ -2,18 +2,24 @@
field=field
composer=composer
wizard=wizard
fieldClass=fieldClass
groupsMentioned=(action "groupsMentioned")
cannotSeeMention=(action "cannotSeeMention")
importQuote=(action "importQuote")
togglePreview=(action "togglePreview")
afterRefresh=(action "afterRefresh")}}
afterRefresh=(action "afterRefresh")
}}
<div class="bottom-bar">
<button class="wizard-btn toggle-preview" {{action "togglePreview"}} type="button">
<button
class="wizard-btn toggle-preview"
{{action "togglePreview"}}
type="button"
>
<span class="d-button-label">{{i18n togglePreviewLabel}}</span>
</button>
{{#if field.char_counter}}
{{char-counter field.value field.max_length}}
{{wizard-char-counter field.value field.max_length}}
{{/if}}
</div>
</div>

Datei anzeigen

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

Datei anzeigen

@ -3,4 +3,4 @@
onChange=(action "onChange")
tabindex=field.tabindex
format=field.format
}}
}}

Datei anzeigen

@ -4,6 +4,5 @@
content=field.content
tabindex=field.tabindex
onChange=(action "onChangeValue")
options=(hash
none="select_kit.default_header_text"
)}}
options=(hash none="select_kit.default_header_text")
}}

Datei anzeigen

@ -1,10 +1,10 @@
{{custom-wizard-group-selector
groups=site.groups
class=fieldClass
field=field
whitelist=field.content
value=field.value
tabindex=field.tabindex
onChange=(action (mut field.value))
options=(hash
none="select_kit.default_header_text"
)}}
options=(hash none="select_kit.default_header_text")
}}

Datei anzeigen

@ -1 +1,8 @@
{{input type="number" step="0.01" id=field.id value=field.value tabindex=field.tabindex}}
<Input
id={{this.field.id}}
step="0.01"
@type="number"
@value={{this.field.value}}
tabindex={{this.field.tabindex}}
class={{this.fieldClass}}
/>

Datei anzeigen

@ -1,9 +1,8 @@
{{custom-wizard-tag-chooser
tags=field.value
class=fieldClass
tabindex=field.tabindex
tagGroups=field.tag_groups
everyTag=true
options=(hash
maximum=field.limit
allowAny=field.can_create_tag
)}}
options=(hash maximum=field.limit allowAny=field.can_create_tag)
}}

Datei anzeigen

@ -1 +1,8 @@
{{input id=field.id value=field.value class=fieldClass placeholder=field.translatedPlaceholder tabindex=field.tabindex autocomplete=autocomplete}}
<Input
id={{this.field.id}}
@value={{this.field.value}}
tabindex={{this.field.tabindex}}
class={{this.fieldClass}}
placeholder={{this.field.translatedPlaceholder}}
autocomplete={{this.autocomplete}}
/>

Datei anzeigen

@ -1 +1,7 @@
{{textarea id=field.id value=field.value class=fieldClass placeholder=field.translatedPlaceholder tabindex=field.tabindex}}
<Textarea
id={{this.field.id}}
@value={{this.field.value}}
tabindex={{this.field.tabindex}}
class={{this.fieldClass}}
placeholder={{this.field.translatedPlaceholder}}
/>

Datei anzeigen

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

Datei anzeigen

@ -1,4 +1,7 @@
<label class="wizard-btn wizard-btn-upload-file {{if uploading "disabled"}}" tabindex={{field.tabindex}}>
<label
class="wizard-btn wizard-btn-upload-file {{if uploading 'disabled'}}"
tabindex={{field.tabindex}}
>
{{#if uploading}}
{{i18n "wizard.uploading"}}
{{else}}
@ -6,13 +9,19 @@
{{d-icon "upload"}}
{{/if}}
<input disabled={{uploading}} class="hidden-upload-field" type="file" accept={{field.file_types}} style="visibility: hidden; position: absolute;" >
<input
disabled={{uploading}}
class="hidden-upload-field"
type="file"
accept={{field.file_types}}
style="visibility: hidden; position: absolute;"
/>
</label>
{{#if field.value}}
{{#if isImage}}
<img src={{field.value.url}} class="wizard-image-preview">
<img src={{field.value.url}} class="wizard-image-preview" />
{{else}}
{{field.value.original_filename}}
{{/if}}
{{/if}}
{{/if}}

Datei anzeigen

@ -1 +1,6 @@
{{input type="text" id=field.id value=field.value tabindex=field.tabindex}}
<Input
id={{this.field.id}}
@value={{this.field.value}}
tabindex={{this.field.tabindex}}
class={{this.fieldClass}}
/>

Datei anzeigen

@ -1,4 +1,5 @@
{{custom-user-selector
usernames=field.value
placeholderKey=field.placeholder
tabindex=field.tabindex}}
tabindex=field.tabindex
}}

Datei anzeigen

@ -1,29 +1,38 @@
<label for={{field.id}} class="field-label">
{{html-safe field.translatedLabel}}
</label>
{{#if field.image}}
<div class="field-image"><img src={{field.image}}></div>
{{/if}}
{{#if field.description}}
<div class="field-description">{{cookedDescription}}</div>
{{/if}}
{{#field-validators field=field as |validators|}}
{{#if inputComponentName}}
<div class="input-area">
{{component inputComponentName field=field step=step fieldClass=fieldClass wizard=wizard autocomplete=validators.autocomplete}}
</div>
{{/if}}
{{/field-validators}}
{{#if field.char_counter}}
{{#if textType}}
{{char-counter field.value field.max_length}}
{{/if}}
{{/if}}
{{#if field.errorDescription}}
<div class="field-error-description">{{html-safe field.errorDescription}}</div>
{{/if}}
<label for={{field.id}} class="field-label">
{{html-safe field.translatedLabel}}
</label>
{{#if field.image}}
<div class="field-image"><img src={{field.image}} /></div>
{{/if}}
{{#if field.description}}
<div class="field-description">{{cookedDescription}}</div>
{{/if}}
{{#field-validators field=field as |validators|}}
{{#if inputComponentName}}
<div class="input-area">
{{component
inputComponentName
field=field
step=step
fieldClass=fieldClass
wizard=wizard
autocomplete=validators.autocomplete
}}
</div>
{{/if}}
{{/field-validators}}
{{#if field.char_counter}}
{{#if textType}}
{{wizard-char-counter field.value field.max_length}}
{{/if}}
{{/if}}
{{#if field.errorDescription}}
<div class="field-error-description">{{html-safe
field.errorDescription
}}</div>
{{/if}}

Datei anzeigen

@ -1,7 +1,11 @@
<div>{{text}}</div>
<div class="no-access-gutter">
<button class="wizard-btn primary return-to-site" {{action "skip"}} type="button">
<button
class="wizard-btn primary return-to-site"
{{action "skip"}}
type="button"
>
{{i18n "wizard.return_to_site" siteName=siteName}}
{{d-icon "sign-out-alt"}}
</button>
</div>
</div>

Datei anzeigen

@ -1,4 +1,6 @@
<a href={{topic.url}} target="_blank" rel="noopener noreferrer">
<span class="title">{{html-safe topic.fancy_title}}</span>
<div class="blurb">{{date-node topic.created_at}} - {{html-safe topic.blurb}}</div>
</a>
<div class="blurb">{{date-node topic.created_at}}
-
{{html-safe topic.blurb}}</div>
</a>

Datei anzeigen

@ -1,11 +1,11 @@
{{#if showTopics}}
<ul>
{{#each topics as |topic|}}
<li>{{custom-wizard-similar-topic topic=topic}}</li>
{{/each}}
</ul>
{{else}}
<a role="button" class="show-topics" {{action "toggleShowTopics"}}>
{{i18n "realtime_validations.similar_topics.show"}}
</a>
{{/if}}
{{#if showTopics}}
<ul>
{{#each topics as |topic|}}
<li>{{custom-wizard-similar-topic topic=topic}}</li>
{{/each}}
</ul>
{{else}}
<a role="button" class="show-topics" {{action "toggleShowTopics"}}>
{{i18n "realtime_validations.similar_topics.show"}}
</a>
{{/if}}

Datei anzeigen

@ -5,7 +5,7 @@
{{#if bannerImage}}
<div class="wizard-step-banner">
<img src={{bannerImage}}>
<img src={{bannerImage}} />
</div>
{{/if}}
@ -26,7 +26,11 @@
<div class="white"></div>
<div class="black" style={{barStyle}}></div>
<div class="screen"></div>
<span>{{i18n "wizard.step" current=step.displayIndex total=wizard.totalSteps}}</span>
<span>{{i18n
"wizard.step"
current=step.displayIndex
total=wizard.totalSteps
}}</span>
</div>
<div class="wizard-buttons">
@ -34,25 +38,47 @@
{{loading-spinner size="small"}}
{{else}}
{{#if showQuitButton}}
<a href {{action "quit"}} class="action-link quit" tabindex={{secondaryButtonIndex}}>{{i18n "wizard.quit"}}</a>
<a
href
{{action "quit"}}
class="action-link quit"
tabindex={{secondaryButtonIndex}}
>{{i18n "wizard.quit"}}</a>
{{/if}}
{{#if showBackButton}}
<a href {{action "backStep"}} class="action-link back" tabindex={{secondaryButtonIndex}}>{{i18n "wizard.back"}}</a>
<a
href
{{action "backStep"}}
class="action-link back"
tabindex={{secondaryButtonIndex}}
>{{i18n "wizard.back"}}</a>
{{/if}}
{{/if}}
{{#if showNextButton}}
<button type="button" class="wizard-btn next primary" {{action "nextStep"}} disabled={{saving}} tabindex={{primaryButtonIndex}}>
<button
type="button"
class="wizard-btn next primary"
{{action "nextStep"}}
disabled={{saving}}
tabindex={{primaryButtonIndex}}
>
{{i18n "wizard.next"}}
{{d-icon "chevron-right"}}
</button>
{{/if}}
{{#if showDoneButton}}
<button type="button" class="wizard-btn done" {{action "done"}} disabled={{saving}} tabindex={{primaryButtonIndex}}>
<button
type="button"
class="wizard-btn done"
{{action "done"}}
disabled={{saving}}
tabindex={{primaryButtonIndex}}
>
{{i18n "wizard.done_custom"}}
</button>
{{/if}}
</div>
</div>
</div>

Datei anzeigen

@ -10,4 +10,4 @@
autoInsertNoneItem=false
translatedFilterPlaceholder="--:--"
)
}}
}}

Datei anzeigen

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

Datei anzeigen

@ -10,4 +10,4 @@
{{#if showSimilarTopics}}
{{custom-wizard-similar-topics topics=similarTopics}}
{{/if}}
{{/if}}

Datei anzeigen

@ -2,4 +2,4 @@
{{i18n validMessageKey}}
{{else}}
{{i18n invalidMessageKey}}
{{/if}}
{{/if}}

Datei anzeigen

@ -3,7 +3,8 @@
action=(action "undoChanges")
icon=undoIcon
label=undoKey
class="undo-changes"}}
class="undo-changes"
}}
{{/if}}
<div class="setting">
@ -17,9 +18,8 @@
feature="action"
attribute="type"
onChange=(action "changeType")
options=(hash
none="admin.wizard.select_type"
)
wizard=wizard
options=(hash none="admin.wizard.select_type")
}}
</div>
</div>
@ -33,14 +33,12 @@
{{combo-box
value=action.run_after
content=runAfterContent
onChange=(action (mut action.run_after))}}
onChange=(action (mut action.run_after))
}}
</div>
</div>
{{wizard-message
key=messageKey
url=messageUrl
component="action"}}
{{wizard-message key=messageKey url=messageUrl component="action"}}
{{#if basicTopicFields}}
<div class="setting full field-mapper-setting">
@ -57,7 +55,8 @@
wizardFieldSelection=true
userFieldSelection="key,value"
context="action"
)}}
)
}}
</div>
</div>
@ -75,10 +74,11 @@
options=(hash
none="admin.wizard.selector.placeholder.wizard_field"
isDisabled=showPostBuilder
)}}
)
}}
<div class="setting-gutter">
{{input type="checkbox" checked=action.post_builder}}
<Input @type="checkbox" @checked={{this.action.post_builder}} />
<span>{{i18n "admin.wizard.action.post_builder.checkbox"}}</span>
</div>
</div>
@ -93,7 +93,8 @@
<div class="setting-value editor">
{{wizard-text-editor
value=action.post_template
wizardFields=wizardFields}}
wizardFields=wizardFields
}}
</div>
</div>
{{/if}}
@ -118,7 +119,8 @@
wizardActionSelection="output"
outputDefaultSelection="category"
context="action"
)}}
)
}}
</div>
</div>
@ -139,7 +141,8 @@
wizardFieldSelection=true
userFieldSelection="key,value"
context="action"
)}}
)
}}
</div>
</div>
@ -154,10 +157,9 @@
property="visible"
onUpdate=(action "mappedFieldUpdated")
options=(hash
wizardFieldSelection=true
userFieldSelection=true
context="action"
)}}
wizardFieldSelection=true userFieldSelection=true context="action"
)
}}
</div>
</div>
@ -172,10 +174,8 @@
inputs=action.add_event
property="add_event"
onUpdate=(action "mappedFieldUpdated")
options=(hash
wizardFieldSelection=true
context="action"
)}}
options=(hash wizardFieldSelection=true context="action")
}}
</div>
</div>
{{/if}}
@ -191,10 +191,8 @@
inputs=action.add_location
property="add_location"
onUpdate=(action "mappedFieldUpdated")
options=(hash
wizardFieldSelection=true
context="action"
)}}
options=(hash wizardFieldSelection=true context="action")
}}
</div>
</div>
{{/if}}
@ -219,7 +217,8 @@
userSelection="output"
outputDefaultSelection="user"
context="action"
)}}
)
}}
</div>
</div>
{{/if}}
@ -242,7 +241,8 @@
wizardActionSelection="value"
keyDefaultSelection="userField"
context="action"
)}}
)
}}
</div>
{{/if}}
@ -260,7 +260,8 @@
options=(hash
isDisabled=action.custom_title_enabled
none="admin.wizard.action.send_to_api.select_an_api"
)}}
)
}}
</div>
</div>
@ -277,7 +278,8 @@
options=(hash
isDisabled=apiEmpty
none="admin.wizard.action.send_to_api.select_an_endpoint"
)}}
)
}}
</div>
</div>
@ -292,7 +294,8 @@
previewEnabled=false
barEnabled=false
wizardFields=wizardFields
placeholder="admin.wizard.action.send_to_api.body_placeholder"}}
placeholder="admin.wizard.action.send_to_api.body_placeholder"
}}
</div>
</div>
{{/if}}
@ -316,7 +319,8 @@
groupSelection="value,output"
outputDefaultSelection="group"
context="action"
)}}
)
}}
</div>
</div>
{{/if}}
@ -339,7 +343,8 @@
groupSelection="key,value"
categorySelection="key,value"
userSelection="key,value"
)}}
)
}}
</div>
</div>
{{/if}}
@ -362,13 +367,16 @@
userFieldSelection="key,value"
categorySelection="output"
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.action.watch_categories.mute_remainder"}}</label>
<label>{{i18n
"admin.wizard.action.watch_categories.mute_remainder"
}}</label>
</div>
<div class="setting-value">
@ -380,13 +388,16 @@
context="action"
wizardFieldSelection=true
userFieldSelection="key,value"
)}}
)
}}
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.action.watch_x.notification_level.label"}}</label>
<label>{{i18n
"admin.wizard.action.watch_x.notification_level.label"
}}</label>
</div>
<div class="setting-value">
@ -397,7 +408,8 @@
options=(hash
isDisabled=action.custom_title_enabled
none="admin.wizard.action.watch_x.select_a_notification_level"
)}}
)
}}
</div>
</div>
@ -407,7 +419,7 @@
</div>
<div class="setting-value">
{{input type="checkbox" checked=action.wizard_user}}
<Input @type="checkbox" @checked={{this.action.wizard_user}} />
</div>
</div>
@ -426,7 +438,8 @@
wizardFieldSelection=true
userFieldSelection="key,value"
userSelection="output"
)}}
)
}}
</div>
</div>
{{/if}}
@ -449,13 +462,16 @@
wizardActionSelection=true
userFieldSelection="key,value"
context="action"
)}}
)
}}
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.action.watch_x.notification_level.label"}}</label>
<label>{{i18n
"admin.wizard.action.watch_x.notification_level.label"
}}</label>
</div>
<div class="setting-value">
@ -466,7 +482,8 @@
options=(hash
isDisabled=action.custom_title_enabled
none="admin.wizard.action.watch_x.select_a_notification_level"
)}}
)
}}
</div>
</div>
@ -476,7 +493,7 @@
</div>
<div class="setting-value">
{{input type="checkbox" checked=action.wizard_user}}
<Input @type="checkbox" @checked={{this.action.wizard_user}} />
</div>
</div>
@ -495,7 +512,8 @@
wizardFieldSelection=true
userFieldSelection="key,value"
userSelection="output"
)}}
)
}}
</div>
</div>
{{/if}}
@ -516,7 +534,8 @@
wizardFieldSelection=true
userFieldSelection=true
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
@ -534,7 +553,8 @@
wizardFieldSelection=true
userFieldSelection=true
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
@ -552,7 +572,8 @@
wizardFieldSelection=true
userFieldSelection=true
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
@ -570,7 +591,8 @@
wizardFieldSelection=true
userFieldSelection=true
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
@ -589,7 +611,8 @@
userFieldSelection=true
userSelection="output"
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
@ -608,12 +631,15 @@
userFieldSelection=true
userSelection="output"
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
<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 class="setting-value">
@ -626,12 +652,15 @@
wizardFieldSelection=true
userFieldSelection=true
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
<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 class="setting-value">
@ -644,12 +673,15 @@
wizardFieldSelection=true
userFieldSelection=true
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
<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 class="setting-value">
@ -662,12 +694,15 @@
wizardFieldSelection=true
userFieldSelection=true
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
<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 class="setting-value">
@ -680,12 +715,15 @@
wizardFieldSelection=true
userFieldSelection=true
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
<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 class="setting-value">
@ -698,7 +736,8 @@
wizardFieldSelection=true
userFieldSelection=true
context="action"
)}}
)
}}
</div>
</div>
{{/if}}
@ -715,11 +754,12 @@
property="name"
onUpdate=(action "mappedFieldUpdated")
options=(hash
textSelection="key,value"
textSelection="key,value,output"
wizardFieldSelection=true
userFieldSelection="key,value"
context="action"
)}}
)
}}
</div>
</div>
@ -738,7 +778,8 @@
wizardFieldSelection=true
userFieldSelection="key,value"
context="action"
)}}
)
}}
</div>
</div>
@ -757,7 +798,8 @@
wizardFieldSelection=true
userFieldSelection="key,value"
context="action"
)}}
)
}}
</div>
</div>
@ -776,13 +818,16 @@
wizardFieldSelection=true
userFieldSelection="key,value"
context="action"
)}}
)
}}
</div>
</div>
<div class="setting full field-mapper-setting">
<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 class="setting-value">
@ -796,7 +841,8 @@
userFieldSelection="key,value"
categorySelection="output"
context="action"
)}}
)
}}
</div>
</div>
@ -818,7 +864,8 @@
userFieldSelection=true
groupSelection="key"
context="action"
)}}
)
}}
</div>
</div>
{{/if}}
@ -842,7 +889,8 @@
userFieldSelection="value"
keyPlaceholder="admin.wizard.action.custom_fields.key"
context=customFieldsContext
)}}
)
}}
</div>
</div>
{{/if}}
@ -864,7 +912,8 @@
userFieldSelection=true
groupSelection=true
context="action"
)}}
)
}}
</div>
</div>
{{/if}}
@ -876,7 +925,7 @@
</div>
<div class="setting-value">
{{input type="checkbox" checked=action.skip_redirect}}
<Input @type="checkbox" @checked={{this.action.skip_redirect}} />
<span>
{{i18n "admin.wizard.action.skip_redirect.description" type="topic"}}
@ -890,10 +939,13 @@
</div>
<div class="setting-value">
{{input type="checkbox" checked=action.suppress_notifications}}
<Input @type="checkbox" @checked={{this.action.suppress_notifications}} />
<span>
{{i18n "admin.wizard.action.suppress_notifications.description" type="topic"}}
{{i18n
"admin.wizard.action.suppress_notifications.description"
type="topic"
}}
</span>
</div>
</div>
@ -906,7 +958,7 @@
</div>
<div class="setting-value">
{{input value=action.code}}
<Input @value={{this.action.code}} />
</div>
</div>
{{/if}}
{{/if}}

Datei anzeigen

@ -1,285 +1,289 @@
{{#if showUndo}}
{{d-button
action=(action "undoChanges")
icon=undoIcon
label=undoKey
class="undo-changes"}}
{{/if}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.label"}}</label>
</div>
<div class="setting-value">
{{input name="label" value=field.label}}
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.required"}}</label>
</div>
<div class="setting-value">
<span>{{i18n "admin.wizard.field.required_label"}}</span>
{{input type="checkbox" checked=field.required}}
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.description"}}</label>
</div>
<div class="setting-value">
{{textarea name="description" value=field.description}}
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.image"}}</label>
</div>
<div class="setting-value">
{{uppy-image-uploader
imageUrl=field.image
onUploadDone=(action "imageUploadDone")
onUploadDeleted=(action "imageUploadDeleted")
type="wizard-field-image"
class="no-repeat contain-image"
id=(concat "wizard-field-" field.id "-image-upload")}}
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.type"}}</label>
</div>
<div class="setting-value">
{{combo-box
value=field.type
content=fieldTypes
onChange=(action "changeType")
options=(hash
none="admin.wizard.select_type"
)}}
</div>
</div>
{{wizard-message
key=messageKey
url=messageUrl
component="field"}}
{{#if isTextType}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.min_length"}}</label>
</div>
<div class="setting-value">
{{input
type="number"
name="min_length"
value=field.min_length
class="small"}}
</div>
</div>
<div class="setting full">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.max_length"}}</label>
</div>
<div class="setting-value">
{{input
type="number"
name="max_length"
value=field.max_length
class="small"}}
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.char_counter"}}</label>
</div>
<div class="setting-value">
<span>{{i18n "admin.wizard.field.char_counter_placeholder"}}</span>
{{input
type="checkbox"
checked=field.char_counter}}
</div>
</div>
<div class="setting full">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.field_placeholder"}}</label>
</div>
<div class="setting-value">
{{textarea
name="field_placeholder"
class="medium"
value=field.placeholder}}
</div>
</div>
{{/if}}
{{#if isComposerPreview}}
<div class="setting full">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.preview_template"}}</label>
</div>
<div class="setting-value">
{{textarea name="preview-template" value=field.preview_template class="preview-template"}}
</div>
</div>
{{/if}}
{{#if isUpload}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.file_types"}}</label>
</div>
<div class="setting-value">
{{input value=field.file_types class="medium"}}
</div>
</div>
{{/if}}
{{#if showLimit}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.limit"}}</label>
</div>
<div class="setting-value">
{{input type="number" value=field.limit class="small"}}
</div>
</div>
{{/if}}
{{#if isDateTime}}
<div class="setting">
<div class="setting-label">
<label>{{html-safe (i18n "admin.wizard.field.date_time_format.label")}}</label>
</div>
<div class="setting-value">
{{input value=field.format class="medium"}}
<label>{{html-safe (i18n "admin.wizard.field.date_time_format.instructions")}}</label>
</div>
</div>
{{/if}}
{{#if showPrefill}}
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.prefill"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=field.prefill
property="prefill"
onUpdate=(action "mappedFieldUpdated")
options=prefillOptions}}
</div>
</div>
{{/if}}
{{#if showContent}}
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.content"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=field.content
property="content"
onUpdate=(action "mappedFieldUpdated")
options=contentOptions}}
</div>
</div>
{{/if}}
{{#if isTag}}
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.tag_groups"}}</label>
</div>
<div class="setting-value">
{{tag-group-chooser
id=(concat field.id "-tag-groups")
tagGroups=field.tag_groups
onChange=(action (mut field.tag_groups))
}}
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.can_create_tag"}}</label>
</div>
<div class="setting-value">
{{input
type="checkbox"
checked=field.can_create_tag}}
</div>
</div>
{{/if}}
{{#wizard-subscription-container}}
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.condition"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=field.condition
options=fieldConditionOptions}}
</div>
</div>
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.index"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=field.index
options=fieldIndexOptions}}
</div>
</div>
{{#if isCategory}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.property"}}</label>
</div>
<div class="setting-value">
{{combo-box
value=field.property
content=categoryPropertyTypes
onChange=(action (mut field.property))
options=(hash
none="admin.wizard.selector.placeholder.property"
)}}
</div>
</div>
{{/if}}
{{#if validations}}
{{wizard-realtime-validations field=field validations=validations}}
{{/if}}
{{/wizard-subscription-container}}
{{#if showUndo}}
{{d-button
action=(action "undoChanges")
icon=undoIcon
label=undoKey
class="undo-changes"
}}
{{/if}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.label"}}</label>
</div>
<div class="setting-value">
<Input name="label" @value={{this.field.label}} />
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.required"}}</label>
</div>
<div class="setting-value">
<span>{{i18n "admin.wizard.field.required_label"}}</span>
<Input @type="checkbox" @checked={{this.field.required}} />
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.description"}}</label>
</div>
<div class="setting-value">
<Textarea name="description" @value={{this.field.description}} />
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.image"}}</label>
</div>
<div class="setting-value">
{{uppy-image-uploader
imageUrl=field.image
onUploadDone=(action "imageUploadDone")
onUploadDeleted=(action "imageUploadDeleted")
type="wizard-field-image"
class="no-repeat contain-image"
id=(concat "wizard-field-" field.id "-image-upload")
}}
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.type"}}</label>
</div>
<div class="setting-value">
{{wizard-subscription-selector
value=field.type
feature="field"
attribute="type"
onChange=(action "changeType")
wizard=wizard
options=(hash none="admin.wizard.select_type")
}}
</div>
</div>
{{wizard-message key=messageKey url=messageUrl component="field"}}
{{#if isTextType}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.min_length"}}</label>
</div>
<div class="setting-value">
<Input
@type="number"
name="min_length"
@value={{this.field.min_length}}
class="small"
/>
</div>
</div>
<div class="setting full">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.max_length"}}</label>
</div>
<div class="setting-value">
<Input
@type="number"
name="max_length"
@value={{this.field.max_length}}
class="small"
/>
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.char_counter"}}</label>
</div>
<div class="setting-value">
<span>{{i18n "admin.wizard.field.char_counter_placeholder"}}</span>
<Input @type="checkbox" @checked={{this.field.char_counter}} />
</div>
</div>
<div class="setting full">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.field_placeholder"}}</label>
</div>
<div class="setting-value">
<Textarea
name="field_placeholder"
class="medium"
@value={{this.field.placeholder}}
/>
</div>
</div>
{{/if}}
{{#if isComposerPreview}}
<div class="setting full">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.preview_template"}}</label>
</div>
<div class="setting-value">
<Textarea
name="preview-template"
class="preview-template"
@value={{this.field.preview_template}}
/>
</div>
</div>
{{/if}}
{{#if isUpload}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.file_types"}}</label>
</div>
<div class="setting-value">
<Input @value={{this.field.file_types}} class="medium" />
</div>
</div>
{{/if}}
{{#if showLimit}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.limit"}}</label>
</div>
<div class="setting-value">
<Input @type="number" @value={{this.field.limit}} class="small" />
</div>
</div>
{{/if}}
{{#if isDateTime}}
<div class="setting">
<div class="setting-label">
<label>{{html-safe
(i18n "admin.wizard.field.date_time_format.label")
}}</label>
</div>
<div class="setting-value">
<Input @value={{this.field.format}} class="medium" />
<label>{{html-safe
(i18n "admin.wizard.field.date_time_format.instructions")
}}</label>
</div>
</div>
{{/if}}
{{#if showPrefill}}
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.prefill"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=field.prefill
property="prefill"
onUpdate=(action "mappedFieldUpdated")
options=prefillOptions
}}
</div>
</div>
{{/if}}
{{#if showContent}}
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.content"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=field.content
property="content"
onUpdate=(action "mappedFieldUpdated")
options=contentOptions
}}
</div>
</div>
{{/if}}
{{#if isTag}}
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.tag_groups"}}</label>
</div>
<div class="setting-value">
{{tag-group-chooser
id=(concat field.id "-tag-groups")
tagGroups=field.tag_groups
onChange=(action (mut field.tag_groups))
}}
</div>
</div>
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.can_create_tag"}}</label>
</div>
<div class="setting-value">
<Input @type="checkbox" @checked={{this.field.can_create_tag}} />
</div>
</div>
{{/if}}
{{#wizard-subscription-container}}
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.condition"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper inputs=field.condition options=fieldConditionOptions}}
</div>
</div>
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.index"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper inputs=field.index options=fieldIndexOptions}}
</div>
</div>
{{#if isCategory}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.field.property"}}</label>
</div>
<div class="setting-value">
{{combo-box
value=field.property
content=categoryPropertyTypes
onChange=(action (mut field.property))
options=(hash none="admin.wizard.selector.placeholder.property")
}}
</div>
</div>
{{/if}}
{{#if validations}}
{{wizard-realtime-validations field=field validations=validations}}
{{/if}}
{{/wizard-subscription-container}}

Datei anzeigen

@ -1,119 +1,120 @@
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.step.title"}}</label>
</div>
<div class="setting-value">
{{input
name="title"
value=step.title}}
</div>
</div>
<div class="setting full">
<div class="setting-label">
<label>{{i18n "admin.wizard.step.banner"}}</label>
</div>
<div class="setting-value">
{{uppy-image-uploader
imageUrl=step.banner
onUploadDone=(action "bannerUploadDone")
onUploadDeleted=(action "bannerUploadDeleted")
type="wizard-step-banner"
class="no-repeat contain-image"
id=(concat "wizard-step-" step.id "-banner-upload")}}
</div>
</div>
<div class="setting full">
<div class="setting-label">
<label>{{i18n "admin.wizard.step.description"}}</label>
</div>
<div class="setting-value">
{{wizard-text-editor
value=step.raw_description}}
</div>
</div>
{{#wizard-subscription-container}}
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.condition"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=step.condition
options=stepConditionOptions}}
</div>
</div>
<div class="setting full">
<div class="setting-label"></div>
<div class="setting-value force-final">
<h4>{{i18n "admin.wizard.step.force_final.label"}}</h4>
{{input type="checkbox" checked=step.force_final}}
<span>{{i18n "admin.wizard.step.force_final.description"}}</span>
</div>
</div>
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.step.required_data.label"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=step.required_data
options=(hash
inputTypes="validation"
inputConnector="and"
wizardFieldSelection="value"
userFieldSelection="value"
keyPlaceholder="admin.wizard.submission_key"
context="step"
)}}
{{#if step.required_data}}
<div class="required-data-message">
<div class="label">
{{i18n "admin.wizard.step.required_data.not_permitted_message"}}
</div>
{{input value=step.required_data_message}}
</div>
{{/if}}
</div>
</div>
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.step.permitted_params.label"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=step.permitted_params
options=(hash
pairConnector="set"
inputTypes="association"
keyPlaceholder="admin.wizard.param_key"
valuePlaceholder="admin.wizard.submission_key"
context="step"
)}}
</div>
</div>
{{/wizard-subscription-container}}
{{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
subscribed=subscribed}}
{{/each}}
<div class="setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.step.title"}}</label>
</div>
<div class="setting-value">
<Input name="title" @value={{this.step.title}} />
</div>
</div>
<div class="setting full">
<div class="setting-label">
<label>{{i18n "admin.wizard.step.banner"}}</label>
</div>
<div class="setting-value">
{{uppy-image-uploader
imageUrl=step.banner
onUploadDone=(action "bannerUploadDone")
onUploadDeleted=(action "bannerUploadDeleted")
type="wizard-step-banner"
class="no-repeat contain-image"
id=(concat "wizard-step-" step.id "-banner-upload")
}}
</div>
</div>
<div class="setting full">
<div class="setting-label">
<label>{{i18n "admin.wizard.step.description"}}</label>
</div>
<div class="setting-value">
{{wizard-text-editor value=step.raw_description}}
</div>
</div>
{{#wizard-subscription-container}}
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.condition"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper inputs=step.condition options=stepConditionOptions}}
</div>
</div>
<div class="setting full">
<div class="setting-label"></div>
<div class="setting-value force-final">
<h4>{{i18n "admin.wizard.step.force_final.label"}}</h4>
<Input @type="checkbox" @checked={{this.step.force_final}} />
<span>{{i18n "admin.wizard.step.force_final.description"}}</span>
</div>
</div>
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.step.required_data.label"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=step.required_data
options=(hash
inputTypes="validation"
inputConnector="and"
wizardFieldSelection="value"
userFieldSelection="value"
keyPlaceholder="admin.wizard.submission_key"
context="step"
)
}}
{{#if step.required_data}}
<div class="required-data-message">
<div class="label">
{{i18n "admin.wizard.step.required_data.not_permitted_message"}}
</div>
<Input @value={{this.step.required_data_message}} />
</div>
{{/if}}
</div>
</div>
<div class="setting full field-mapper-setting">
<div class="setting-label">
<label>{{i18n "admin.wizard.step.permitted_params.label"}}</label>
</div>
<div class="setting-value">
{{wizard-mapper
inputs=step.permitted_params
options=(hash
pairConnector="set"
inputTypes="association"
keyPlaceholder="admin.wizard.param_key"
valuePlaceholder="admin.wizard.submission_key"
context="step"
)
}}
</div>
</div>
{{/wizard-subscription-container}}
{{wizard-links
itemType="field"
current=currentField
items=step.fields
parentId=step.id
}}
{{#each step.fields as |field|}}
{{wizard-custom-field
field=field
step=step
wizard=wizard
currentFieldId=currentField.id
fieldTypes=fieldTypes
removeField="removeField"
wizardFields=wizardFields
subscribed=subscribed
}}
{{/each}}

Datei anzeigen

@ -4,16 +4,36 @@
{{#if anyLinks}}
{{#each links as |link|}}
<div data-id={{link.id}}>
{{d-button action=(action "change") actionParam=link.id translatedLabel=link.label class=link.classes}}
{{d-button
action=(action "change")
actionParam=link.id
translatedLabel=link.label
class=link.classes
}}
{{#unless link.first}}
{{d-button action=(action "back") actionParam=link icon="arrow-left" class="back"}}
{{d-button
action=(action "back")
actionParam=link
icon="arrow-left"
class="back"
}}
{{/unless}}
{{#unless link.last}}
{{d-button action=(action "forward") actionParam=link icon="arrow-right" class="forward"}}
{{d-button
action=(action "forward")
actionParam=link
icon="arrow-right"
class="forward"
}}
{{/unless}}
{{d-button action=(action "remove") actionParam=link.id icon="times" class="remove"}}
{{d-button
action=(action "remove")
actionParam=link.id
icon="times"
class="remove"
}}
</div>
{{/each}}
{{/if}}
{{d-button action=(action "add") label="admin.wizard.add" icon="plus"}}
</div>
</div>

Datei anzeigen

@ -2,11 +2,12 @@
{{combo-box
value=connector
content=connectors
onChange=(action "changeConnector")}}
onChange=(action "changeConnector")
}}
{{else}}
{{#if connector}}
<span class="connector-single">
{{connectorLabel}}
</span>
{{/if}}
{{/if}}
{{/if}}

Datei anzeigen

@ -5,7 +5,8 @@
inputType=inputType
connectorType="type"
options=options
onUpdate=onUpdate}}
onUpdate=onUpdate
}}
{{#if hasPairs}}
<div class="mapper-pairs mapper-block">
@ -16,7 +17,8 @@
inputType=inputType
options=options
removePair=(action "removePair")
onUpdate=onUpdate}}
onUpdate=onUpdate
}}
{{/each}}
{{#if canAddPair}}
@ -35,7 +37,8 @@
connectorType="output"
inputType=inputType
options=options
onUpdate=onUpdate}}
onUpdate=onUpdate
}}
{{/if}}
<div class="output mapper-block">
@ -45,10 +48,11 @@
value=input.output
activeType=input.output_type
options=options
onUpdate=onUpdate}}
onUpdate=onUpdate
}}
</div>
{{/if}}
<a role="button" class="remove-input" {{action remove input}}>
{{d-icon "times"}}
</a>
</a>

Datei anzeigen

@ -5,7 +5,8 @@
value=pair.key
activeType=pair.key_type
options=options
onUpdate=onUpdate}}
onUpdate=onUpdate
}}
</div>
{{wizard-mapper-connector
@ -14,7 +15,8 @@
connectorType="pair"
inputType=inputType
options=options
onUpdate=onUpdate}}
onUpdate=onUpdate
}}
<div class="value mapper-block">
{{wizard-mapper-selector
@ -24,7 +26,8 @@
activeType=pair.value_type
options=options
onUpdate=onUpdate
connector=pair.connector}}
connector=pair.connector
}}
</div>
{{#if showJoin}}
@ -32,5 +35,7 @@
{{/if}}
{{#if showRemove}}
<a role="button" {{action removePair pair}} class="remove-pair">{{d-icon "times"}}</a>
{{/if}}
<a role="button" {{action removePair pair}} class="remove-pair">{{d-icon
"times"
}}</a>
{{/if}}

Datei anzeigen

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

Datei anzeigen

@ -10,7 +10,8 @@
{{wizard-mapper-selector-type
activeType=activeType
item=item
toggle=(action "toggleType")}}
toggle=(action "toggleType")
}}
{{/each}}
</div>
{{/if}}
@ -21,11 +22,12 @@
<div class="input">
{{#if showText}}
{{input
type="text"
value=value
placeholder=(i18n placeholderKey)
change=(action "changeInputValue")}}
<Input
@type="text"
@value={{this.value}}
placeholder={{i18n placeholderKey}}
{{on "change" (action "changeInputValue")}}
/>
{{/if}}
{{#if showComboBox}}
@ -33,10 +35,8 @@
value=value
content=comboBoxContent
onChange=(action "changeValue")
options=(hash
none=placeholderKey
allowAny=comboBoxAllowAny
)}}
options=(hash none=placeholderKey allowAny=comboBoxAllowAny)
}}
{{/if}}
{{#if showMultiSelect}}
@ -44,14 +44,16 @@
content=multiSelectContent
value=value
onChange=(action "changeValue")
options=multiSelectOptions}}
options=multiSelectOptions
}}
{{/if}}
{{#if showList}}
{{wizard-value-list
values=value
addKey=placeholderKey
onChange=(action "changeValue")}}
onChange=(action "changeValue")
}}
{{/if}}
{{#if showTag}}
@ -59,10 +61,8 @@
tags=value
onChange=(action "changeValue")
everyTag=true
options=(hash
none=placeholderKey
filterable=true
)}}
options=(hash none=placeholderKey filterable=true)
}}
{{/if}}
{{#if showUser}}
@ -71,8 +71,7 @@
value=value
autocomplete="discourse"
onChange=(action "changeUserValue")
options=(hash
includeMessageableGroups="true"
)}}
options=(hash includeMessageableGroups="true")
}}
{{/if}}
</div>
</div>

Datei anzeigen

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

Datei anzeigen

@ -23,4 +23,4 @@
{{documentation}}
</a>
</div>
{{/if}}
{{/if}}

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