Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-22 09:20:29 +01:00
Merge branch 'main' into subscription_client_update
Dieser Commit ist enthalten in:
Commit
6be5511d18
61 geänderte Dateien mit 739 neuen und 248 gelöschten Zeilen
2
.github/workflows/discourse-plugin.yml
gevendort
2
.github/workflows/discourse-plugin.yml
gevendort
|
@ -5,6 +5,8 @@ on:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
|
schedule:
|
||||||
|
- cron: "0 0 * * *"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ci:
|
ci:
|
||||||
|
|
|
@ -10,7 +10,7 @@ class CustomWizard::SubmissionSerializer < ApplicationSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def user
|
def user
|
||||||
::BasicUserSerializer.new(object.wizard.user).as_json
|
::BasicUserSerializer.new(object.wizard.user, root: false).as_json
|
||||||
end
|
end
|
||||||
|
|
||||||
def fields
|
def fields
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { alias } from "@ember/object/computed";
|
||||||
import Site from "discourse/models/site";
|
import Site from "discourse/models/site";
|
||||||
import { uploadIcon } from "discourse/lib/uploads";
|
import { uploadIcon } from "discourse/lib/uploads";
|
||||||
import { dasherize } from "@ember/string";
|
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;
|
||||||
|
|
||||||
|
@ -19,7 +20,6 @@ export default ComposerEditor.extend({
|
||||||
classNameBindings: ["fieldClass"],
|
classNameBindings: ["fieldClass"],
|
||||||
allowUpload: true,
|
allowUpload: true,
|
||||||
showLink: false,
|
showLink: false,
|
||||||
showHyperlinkBox: false,
|
|
||||||
topic: null,
|
topic: null,
|
||||||
showToolbar: true,
|
showToolbar: true,
|
||||||
focusTarget: "reply",
|
focusTarget: "reply",
|
||||||
|
@ -29,6 +29,7 @@ export default ComposerEditor.extend({
|
||||||
draftStatus: "null",
|
draftStatus: "null",
|
||||||
replyPlaceholder: alias("field.translatedPlaceholder"),
|
replyPlaceholder: alias("field.translatedPlaceholder"),
|
||||||
wizardEventFieldId: null,
|
wizardEventFieldId: null,
|
||||||
|
composerEventPrefix: "wizard-editor",
|
||||||
|
|
||||||
@on("didInsertElement")
|
@on("didInsertElement")
|
||||||
_composerEditorInit() {
|
_composerEditorInit() {
|
||||||
|
@ -77,24 +78,13 @@ export default ComposerEditor.extend({
|
||||||
$input.on("scroll", this._throttledSyncEditorAndPreviewScroll);
|
$input.on("scroll", this._throttledSyncEditorAndPreviewScroll);
|
||||||
this._bindUploadTarget();
|
this._bindUploadTarget();
|
||||||
|
|
||||||
const wizardEventNames = ["insert-text", "replace-text"];
|
const field = this.field;
|
||||||
const eventPrefix = this.eventPrefix;
|
this.editorInputClass = `.${dasherize(field.type)}-${dasherize(
|
||||||
this.appEvents.reopen({
|
field.id
|
||||||
trigger(name, ...args) {
|
)} .d-editor-input`;
|
||||||
let eventParts = name.split(":");
|
|
||||||
let currentEventPrefix = eventParts[0];
|
|
||||||
let currentEventName = eventParts[1];
|
|
||||||
|
|
||||||
if (
|
this._uppyInstance.on("file-added", () => {
|
||||||
currentEventPrefix !== "wizard-editor" &&
|
this.session.set("wizardEventFieldId", field.id);
|
||||||
wizardEventNames.some((wen) => wen === currentEventName)
|
|
||||||
) {
|
|
||||||
let wizardEventName = name.replace(eventPrefix, "wizard-editor");
|
|
||||||
return this._super(wizardEventName, ...args);
|
|
||||||
} else {
|
|
||||||
return this._super(name, ...args);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -116,12 +106,6 @@ export default ComposerEditor.extend({
|
||||||
return uploadIcon(false, this.siteSettings);
|
return uploadIcon(false, this.siteSettings);
|
||||||
},
|
},
|
||||||
|
|
||||||
click(e) {
|
|
||||||
if ($(e.target).hasClass("wizard-composer-hyperlink")) {
|
|
||||||
this.set("showHyperlinkBox", false);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
@bind
|
@bind
|
||||||
_handleImageDeleteButtonClick(event) {
|
_handleImageDeleteButtonClick(event) {
|
||||||
if (!event.target.classList.contains("delete-image-button")) {
|
if (!event.target.classList.contains("delete-image-button")) {
|
||||||
|
@ -165,7 +149,7 @@ export default ComposerEditor.extend({
|
||||||
shortcut: "K",
|
shortcut: "K",
|
||||||
trimLeading: true,
|
trimLeading: true,
|
||||||
unshift: true,
|
unshift: true,
|
||||||
sendAction: () => component.set("showHyperlinkBox", true),
|
sendAction: (event) => component.send("showLinkModal", event),
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.siteSettings.mentionables_enabled) {
|
if (this.siteSettings.mentionables_enabled) {
|
||||||
|
@ -206,17 +190,18 @@ export default ComposerEditor.extend({
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
},
|
},
|
||||||
|
|
||||||
addLink(linkName, linkUrl) {
|
showLinkModal(toolbarEvent) {
|
||||||
let link = `[${linkName}](${linkUrl})`;
|
let linkText = "";
|
||||||
this.appEvents.trigger("wizard-editor:insert-text", {
|
this._lastSel = toolbarEvent.selected;
|
||||||
fieldId: this.field.id,
|
|
||||||
text: link,
|
|
||||||
});
|
|
||||||
this.set("showHyperlinkBox", false);
|
|
||||||
},
|
|
||||||
|
|
||||||
hideBox() {
|
if (this._lastSel) {
|
||||||
this.set("showHyperlinkBox", false);
|
linkText = this._lastSel.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
showModal("insert-hyperlink").setProperties({
|
||||||
|
linkText,
|
||||||
|
toolbarEvent,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
showUploadModal() {
|
showUploadModal() {
|
||||||
|
|
|
@ -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();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -3,6 +3,7 @@ import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
export default DateInput.extend({
|
export default DateInput.extend({
|
||||||
useNativePicker: false,
|
useNativePicker: false,
|
||||||
|
classNameBindings: ["fieldClass"],
|
||||||
|
|
||||||
@discourseComputed()
|
@discourseComputed()
|
||||||
placeholder() {
|
placeholder() {
|
||||||
|
|
|
@ -2,6 +2,8 @@ import DateTimeInput from "discourse/components/date-time-input";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
export default DateTimeInput.extend({
|
export default DateTimeInput.extend({
|
||||||
|
classNameBindings: ["fieldClass"],
|
||||||
|
|
||||||
@discourseComputed("timeFirst", "tabindex")
|
@discourseComputed("timeFirst", "tabindex")
|
||||||
timeTabindex(timeFirst, tabindex) {
|
timeTabindex(timeFirst, tabindex) {
|
||||||
return timeFirst ? tabindex : tabindex + 1;
|
return timeFirst ? tabindex : tabindex + 1;
|
||||||
|
|
|
@ -2,6 +2,8 @@ import Component from "@ember/component";
|
||||||
import { observes } from "discourse-common/utils/decorators";
|
import { observes } from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
|
classNameBindings: ["fieldClass"],
|
||||||
|
|
||||||
@observes("time")
|
@observes("time")
|
||||||
setValue() {
|
setValue() {
|
||||||
this.set("field.value", this.time.format(this.field.format));
|
this.set("field.value", this.time.format(this.field.format));
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { computed } from "@ember/object";
|
||||||
|
|
||||||
export default Component.extend(UppyUploadMixin, {
|
export default Component.extend(UppyUploadMixin, {
|
||||||
classNames: ["wizard-field-upload"],
|
classNames: ["wizard-field-upload"],
|
||||||
classNameBindings: ["isImage"],
|
classNameBindings: ["isImage", "fieldClass"],
|
||||||
uploading: false,
|
uploading: false,
|
||||||
type: computed(function () {
|
type: computed(function () {
|
||||||
return `wizard_${this.field.id}`;
|
return `wizard_${this.field.id}`;
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
|
||||||
export default Component.extend({});
|
export default Component.extend({
|
||||||
|
classNameBindings: ["fieldClass"],
|
||||||
|
});
|
||||||
|
|
|
@ -9,6 +9,7 @@ import CustomWizard, {
|
||||||
updateCachedWizard,
|
updateCachedWizard,
|
||||||
} from "discourse/plugins/discourse-custom-wizard/discourse/models/custom-wizard";
|
} from "discourse/plugins/discourse-custom-wizard/discourse/models/custom-wizard";
|
||||||
import { alias, not } from "@ember/object/computed";
|
import { alias, not } from "@ember/object/computed";
|
||||||
|
import discourseLater from "discourse-common/lib/later";
|
||||||
|
|
||||||
const alreadyWarned = {};
|
const alreadyWarned = {};
|
||||||
|
|
||||||
|
@ -110,29 +111,22 @@ export default Component.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
autoFocus() {
|
autoFocus() {
|
||||||
|
discourseLater(() => {
|
||||||
schedule("afterRender", () => {
|
schedule("afterRender", () => {
|
||||||
const $invalid = $(
|
if ($(".invalid .wizard-focusable").length) {
|
||||||
".wizard-field.invalid:nth-of-type(1) .wizard-focusable"
|
this.animateInvalidFields();
|
||||||
);
|
|
||||||
|
|
||||||
if ($invalid.length) {
|
|
||||||
return $invalid.focus();
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
$(".wizard-focusable:first").focus();
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
animateInvalidFields() {
|
animateInvalidFields() {
|
||||||
schedule("afterRender", () => {
|
schedule("afterRender", () => {
|
||||||
let $element = $(
|
let $invalid = $(".invalid .wizard-focusable");
|
||||||
".invalid input[type=text],.invalid textarea,.invalid input[type=checkbox],.invalid .select-kit"
|
if ($invalid.length) {
|
||||||
);
|
|
||||||
|
|
||||||
if ($element.length) {
|
|
||||||
$([document.documentElement, document.body]).animate(
|
$([document.documentElement, document.body]).animate(
|
||||||
{
|
{
|
||||||
scrollTop: $element.offset().top - 200,
|
scrollTop: $invalid.offset().top - 200,
|
||||||
},
|
},
|
||||||
400
|
400
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,7 +7,7 @@ export default Component.extend(Subscription, {
|
||||||
|
|
||||||
@discourseComputed("subscribed")
|
@discourseComputed("subscribed")
|
||||||
subscribedIcon(subscribed) {
|
subscribedIcon(subscribed) {
|
||||||
return subscribed ? "check" : "dash";
|
return subscribed ? "check" : "times";
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("subscribed")
|
@discourseComputed("subscribed")
|
||||||
|
|
|
@ -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);
|
|
||||||
});
|
|
25
assets/javascripts/discourse/helpers/wizard-char-counter.js.es6
Normale Datei
25
assets/javascripts/discourse/helpers/wizard-char-counter.js.es6
Normale Datei
|
@ -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);
|
||||||
|
}
|
||||||
|
);
|
|
@ -35,6 +35,7 @@ function inputTypesContent(options = {}) {
|
||||||
const connectors = {
|
const connectors = {
|
||||||
pair: [
|
pair: [
|
||||||
"equal",
|
"equal",
|
||||||
|
"not_equal",
|
||||||
"greater",
|
"greater",
|
||||||
"less",
|
"less",
|
||||||
"greater_or_equal",
|
"greater_or_equal",
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { get, set } from "@ember/object";
|
||||||
import Mixin from "@ember/object/mixin";
|
import Mixin from "@ember/object/mixin";
|
||||||
import { deepEqual } from "discourse-common/lib/object";
|
import { deepEqual } from "discourse-common/lib/object";
|
||||||
|
|
||||||
|
const observedCache = [];
|
||||||
|
|
||||||
export default Mixin.create({
|
export default Mixin.create({
|
||||||
didInsertElement() {
|
didInsertElement() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
@ -32,7 +34,13 @@ export default Mixin.create({
|
||||||
};
|
};
|
||||||
|
|
||||||
listProperties(componentType, opts).forEach((property) => {
|
listProperties(componentType, opts).forEach((property) => {
|
||||||
|
if (observedCache.includes(property)) {
|
||||||
obj.removeObserver(property, this, this.toggleUndo);
|
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) => {
|
listProperties(componentType, opts).forEach((property) => {
|
||||||
|
if (observedCache.indexOf(property) === -1) {
|
||||||
|
observedCache.push(property);
|
||||||
|
}
|
||||||
obj.addObserver(property, this, this.toggleUndo);
|
obj.addObserver(property, this, this.toggleUndo);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -72,7 +72,7 @@ export default EmberObject.extend(ValidState, {
|
||||||
valid = true;
|
valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.setValid(valid);
|
this.setValid(Boolean(valid));
|
||||||
|
|
||||||
return valid;
|
return valid;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import { getCachedWizard } from "../models/custom-wizard";
|
import { getCachedWizard } from "../models/custom-wizard";
|
||||||
import Route from "@ember/routing/route";
|
import Route from "@ember/routing/route";
|
||||||
|
import { scrollTop } from "discourse/mixins/scroll-top";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
|
||||||
export default Route.extend({
|
export default Route.extend({
|
||||||
beforeModel() {
|
beforeModel() {
|
||||||
|
@ -48,4 +50,10 @@ export default Route.extend({
|
||||||
|
|
||||||
controller.setProperties(props);
|
controller.setProperties(props);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
didTransition() {
|
||||||
|
scrollTop();
|
||||||
|
return true;
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -32,13 +32,19 @@
|
||||||
<div class="metadata">
|
<div class="metadata">
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<label>{{i18n "admin.wizard.api.title"}}</label>
|
<label>{{i18n "admin.wizard.api.title"}}</label>
|
||||||
{{input value=api.title placeholder=(i18n "admin.wizard.api.title_placeholder")}}
|
<Input
|
||||||
|
@value={{this.api.title}}
|
||||||
|
placeholder={{i18n "admin.wizard.api.title_placeholder"}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="name {{nameClass}}">
|
<div class="name {{nameClass}}">
|
||||||
<label>{{i18n "admin.wizard.api.name"}}</label>
|
<label>{{i18n "admin.wizard.api.name"}}</label>
|
||||||
{{#if api.isNew}}
|
{{#if api.isNew}}
|
||||||
{{input value=api.name placeholder=(i18n "admin.wizard.api.name_placeholder")}}
|
<Input
|
||||||
|
@value={{this.api.name}}
|
||||||
|
placeholder={{i18n "admin.wizard.api.name_placeholder"}}
|
||||||
|
/>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span>{{api.name}}</span>
|
<span>{{api.name}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -104,7 +110,9 @@
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.url"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.url"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{input value=api.authUrl}}
|
<Input
|
||||||
|
@value={{this.api.authUrl}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -112,21 +120,27 @@
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.token_url"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.token_url"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{input value=api.tokenUrl}}
|
<Input
|
||||||
|
@value={{this.api.tokenUrl}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.client_id"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.client_id"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{input value=api.clientId}}
|
<Input
|
||||||
|
@value={{this.api.clientId}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.client_secret"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.client_secret"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{input value=api.clientSecret}}
|
<Input
|
||||||
|
@value={{this.api.clientSecret}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -135,8 +149,14 @@
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{#each api.authParams as |param|}}
|
{{#each api.authParams as |param|}}
|
||||||
<div class="param">
|
<div class="param">
|
||||||
{{input value=param.key placeholder=(i18n "admin.wizard.key")}}
|
<Input
|
||||||
{{input value=param.value placeholder=(i18n "admin.wizard.value")}}
|
@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"}}
|
{{d-button action=(action "removeParam") actionParam=param icon="times"}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -149,14 +169,18 @@
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.username"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.username"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{input value=api.username}}
|
<Input
|
||||||
|
@value={{this.api.username}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>{{i18n "admin.wizard.api.auth.password"}}</label>
|
<label>{{i18n "admin.wizard.api.auth.password"}}</label>
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{input value=api.password}}
|
<Input
|
||||||
|
@value={{this.api.password}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -235,11 +259,15 @@
|
||||||
<div class="endpoint">
|
<div class="endpoint">
|
||||||
<div class="endpoint-">
|
<div class="endpoint-">
|
||||||
<div class="top">
|
<div class="top">
|
||||||
{{input value=endpoint.name
|
<Input
|
||||||
placeholder=(i18n "admin.wizard.api.endpoint.name")}}
|
@value={{this.endpoint.name}}
|
||||||
{{input value=endpoint.url
|
placeholder={{i18n "admin.wizard.api.endpoint.name"}}
|
||||||
placeholder=(i18n "admin.wizard.api.endpoint.url")
|
/>
|
||||||
class="endpoint-url"}}
|
<Input
|
||||||
|
@value={{this.endpoint.url}}
|
||||||
|
placeholder={{i18n "admin.wizard.api.endpoint.url"}}
|
||||||
|
class="endpoint-url"
|
||||||
|
/>
|
||||||
{{d-button action=(action "removeEndpoint")
|
{{d-button action=(action "removeEndpoint")
|
||||||
actionParam=endpoint
|
actionParam=endpoint
|
||||||
icon="times"
|
icon="times"
|
||||||
|
|
|
@ -11,11 +11,12 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{input
|
<Input
|
||||||
id="custom-wizard-file-upload"
|
id="custom-wizard-file-upload"
|
||||||
type="file"
|
@type="file"
|
||||||
accept="application/json"
|
accept="application/json"
|
||||||
input=(action "setFile")}}
|
{{on "input" (action "setFile")}}
|
||||||
|
/>
|
||||||
{{d-button
|
{{d-button
|
||||||
id="upload-button"
|
id="upload-button"
|
||||||
label="admin.wizard.manager.upload"
|
label="admin.wizard.manager.upload"
|
||||||
|
@ -65,16 +66,18 @@
|
||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
</td>
|
</td>
|
||||||
<td class="control-column">
|
<td class="control-column">
|
||||||
{{input
|
<Input
|
||||||
type="checkbox"
|
@type="checkbox"
|
||||||
class="export"
|
class="export"
|
||||||
change=(action "selectWizard")}}
|
{{on "change" (action "selectWizard")}}
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td class="control-column">
|
<td class="control-column">
|
||||||
{{input
|
<Input
|
||||||
type="checkbox"
|
@type="checkbox"
|
||||||
class="destroy"
|
class="destroy"
|
||||||
change=(action "selectWizard")}}
|
{{on "change" (action "selectWizard")}}
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
{{#if wizard}}
|
{{#if wizard}}
|
||||||
<div class="wizard-header large">
|
<div class="wizard-header large">
|
||||||
{{input
|
<Input
|
||||||
|
@value={{this.wizard.name}}
|
||||||
name="name"
|
name="name"
|
||||||
value=wizard.name
|
placeholder={{i18n "admin.wizard.name_placeholder"}}
|
||||||
placeholderKey="admin.wizard.name_placeholder"}}
|
/>
|
||||||
|
|
||||||
<div class="wizard-url">
|
<div class="wizard-url">
|
||||||
{{#if wizard.name}}
|
{{#if wizard.name}}
|
||||||
|
@ -23,11 +24,12 @@
|
||||||
<label>{{i18n "admin.wizard.background"}}</label>
|
<label>{{i18n "admin.wizard.background"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input
|
<Input
|
||||||
|
@value={{this.wizard.background}}
|
||||||
name="background"
|
name="background"
|
||||||
value=wizard.background
|
placeholder={{i18n "admin.wizard.background_placeholder"}}
|
||||||
placeholderKey="admin.wizard.background_placeholder"
|
class="small"
|
||||||
class="small"}}
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -58,7 +60,10 @@
|
||||||
<label>{{i18n "admin.wizard.save_submissions"}}</label>
|
<label>{{i18n "admin.wizard.save_submissions"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=wizard.save_submissions}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.wizard.save_submissions}}
|
||||||
|
/>
|
||||||
<span>{{i18n "admin.wizard.save_submissions_label"}}</span>
|
<span>{{i18n "admin.wizard.save_submissions_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -68,7 +73,10 @@
|
||||||
<label>{{i18n "admin.wizard.multiple_submissions"}}</label>
|
<label>{{i18n "admin.wizard.multiple_submissions"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<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>
|
<span>{{i18n "admin.wizard.multiple_submissions_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -78,7 +86,10 @@
|
||||||
<label>{{i18n "admin.wizard.after_signup"}}</label>
|
<label>{{i18n "admin.wizard.after_signup"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=wizard.after_signup}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.wizard.after_signup}}
|
||||||
|
/>
|
||||||
<span>{{i18n "admin.wizard.after_signup_label"}}</span>
|
<span>{{i18n "admin.wizard.after_signup_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -88,7 +99,10 @@
|
||||||
<label>{{i18n "admin.wizard.prompt_completion"}}</label>
|
<label>{{i18n "admin.wizard.prompt_completion"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<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>
|
<span>{{i18n "admin.wizard.prompt_completion_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -98,7 +112,10 @@
|
||||||
<label>{{i18n "admin.wizard.after_time"}}</label>
|
<label>{{i18n "admin.wizard.after_time"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=wizard.after_time}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.wizard.after_time}}
|
||||||
|
/>
|
||||||
<span>{{i18n "admin.wizard.after_time_label"}}</span>
|
<span>{{i18n "admin.wizard.after_time_label"}}</span>
|
||||||
{{d-button
|
{{d-button
|
||||||
action=(action "setNextSessionScheduled")
|
action=(action "setNextSessionScheduled")
|
||||||
|
@ -114,7 +131,10 @@
|
||||||
<label>{{i18n "admin.wizard.required"}}</label>
|
<label>{{i18n "admin.wizard.required"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=wizard.required}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.wizard.required}}
|
||||||
|
/>
|
||||||
<span>{{i18n "admin.wizard.required_label"}}</span>
|
<span>{{i18n "admin.wizard.required_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -124,7 +144,10 @@
|
||||||
<label>{{i18n "admin.wizard.restart_on_revisit"}}</label>
|
<label>{{i18n "admin.wizard.restart_on_revisit"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=wizard.restart_on_revisit}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.wizard.restart_on_revisit}}
|
||||||
|
/>
|
||||||
<span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
|
<span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -20,9 +20,10 @@
|
||||||
)}}
|
)}}
|
||||||
</td>
|
</td>
|
||||||
<td class="input">
|
<td class="input">
|
||||||
{{input
|
<Input
|
||||||
value=field.name
|
@value={{this.field.name}}
|
||||||
placeholder=(i18n "admin.wizard.custom_field.name.select")}}
|
placeholder={{i18n "admin.wizard.custom_field.name.select"}}
|
||||||
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td class="multi-select">
|
<td class="multi-select">
|
||||||
{{multi-select
|
{{multi-select
|
||||||
|
|
|
@ -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>
|
|
|
@ -1,11 +1,11 @@
|
||||||
{{input
|
<Input
|
||||||
type=inputType
|
@type={{this.inputType}}
|
||||||
|
@value={{readonly this.value}}
|
||||||
class="date-picker"
|
class="date-picker"
|
||||||
placeholder=placeholder
|
placeholder={{this.placeholder}}
|
||||||
value=(readonly value)
|
tabindex={{this.tabindex}}
|
||||||
input=(action "onChangeDate")
|
{{on "input" (action "onChangeDate")}}
|
||||||
tabindex=tabindex
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
}}
|
/>
|
||||||
|
|
||||||
<div class="picker-container"></div>
|
<div class="picker-container"></div>
|
||||||
|
|
|
@ -40,7 +40,12 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{conditional-loading-spinner condition=loading}}
|
{{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>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{{custom-wizard-category-selector
|
{{custom-wizard-category-selector
|
||||||
categories=categories
|
categories=categories
|
||||||
|
class=fieldClass
|
||||||
whitelist=field.content
|
whitelist=field.content
|
||||||
onChange=(action (mut categories))
|
onChange=(action (mut categories))
|
||||||
tabindex=field.tabindex
|
tabindex=field.tabindex
|
||||||
|
|
|
@ -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}}
|
||||||
|
/>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
field=field
|
field=field
|
||||||
composer=composer
|
composer=composer
|
||||||
wizard=wizard
|
wizard=wizard
|
||||||
|
fieldClass=fieldClass
|
||||||
groupsMentioned=(action "groupsMentioned")
|
groupsMentioned=(action "groupsMentioned")
|
||||||
cannotSeeMention=(action "cannotSeeMention")
|
cannotSeeMention=(action "cannotSeeMention")
|
||||||
importQuote=(action "importQuote")
|
importQuote=(action "importQuote")
|
||||||
|
@ -14,6 +15,6 @@
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
{{#if field.char_counter}}
|
{{#if field.char_counter}}
|
||||||
{{char-counter field.value field.max_length}}
|
{{wizard-char-counter field.value field.max_length}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{{custom-wizard-group-selector
|
{{custom-wizard-group-selector
|
||||||
groups=site.groups
|
groups=site.groups
|
||||||
|
class=fieldClass
|
||||||
field=field
|
field=field
|
||||||
whitelist=field.content
|
whitelist=field.content
|
||||||
value=field.value
|
value=field.value
|
||||||
|
|
|
@ -1 +1,9 @@
|
||||||
{{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}}
|
||||||
|
/>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
{{custom-wizard-tag-chooser
|
{{custom-wizard-tag-chooser
|
||||||
tags=field.value
|
tags=field.value
|
||||||
|
class=fieldClass
|
||||||
tabindex=field.tabindex
|
tabindex=field.tabindex
|
||||||
tagGroups=field.tag_groups
|
tagGroups=field.tag_groups
|
||||||
everyTag=true
|
everyTag=true
|
||||||
|
|
|
@ -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}}
|
||||||
|
/>
|
||||||
|
|
|
@ -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}}
|
||||||
|
/>
|
||||||
|
|
|
@ -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}}
|
||||||
|
/>
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
{{#if field.char_counter}}
|
{{#if field.char_counter}}
|
||||||
{{#if textType}}
|
{{#if textType}}
|
||||||
{{char-counter field.value field.max_length}}
|
{{wizard-char-counter field.value field.max_length}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
|
@ -79,7 +79,10 @@
|
||||||
)}}
|
)}}
|
||||||
|
|
||||||
<div class="setting-gutter">
|
<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>
|
<span>{{i18n "admin.wizard.action.post_builder.checkbox"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -408,7 +411,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=action.wizard_user}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.action.wizard_user}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -477,7 +483,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=action.wizard_user}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.action.wizard_user}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -716,7 +725,7 @@
|
||||||
property="name"
|
property="name"
|
||||||
onUpdate=(action "mappedFieldUpdated")
|
onUpdate=(action "mappedFieldUpdated")
|
||||||
options=(hash
|
options=(hash
|
||||||
textSelection="key,value"
|
textSelection="key,value,output"
|
||||||
wizardFieldSelection=true
|
wizardFieldSelection=true
|
||||||
userFieldSelection="key,value"
|
userFieldSelection="key,value"
|
||||||
context="action"
|
context="action"
|
||||||
|
@ -877,7 +886,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=action.skip_redirect}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.action.skip_redirect}}
|
||||||
|
/>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
{{i18n "admin.wizard.action.skip_redirect.description" type="topic"}}
|
{{i18n "admin.wizard.action.skip_redirect.description" type="topic"}}
|
||||||
|
@ -891,7 +903,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="checkbox" checked=action.suppress_notifications}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.action.suppress_notifications}}
|
||||||
|
/>
|
||||||
|
|
||||||
<span>
|
<span>
|
||||||
{{i18n "admin.wizard.action.suppress_notifications.description" type="topic"}}
|
{{i18n "admin.wizard.action.suppress_notifications.description" type="topic"}}
|
||||||
|
@ -907,7 +922,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input value=action.code}}
|
<Input @value={{this.action.code}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -11,7 +11,10 @@
|
||||||
<label>{{i18n "admin.wizard.field.label"}}</label>
|
<label>{{i18n "admin.wizard.field.label"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input name="label" value=field.label}}
|
<Input
|
||||||
|
name="label"
|
||||||
|
@value={{this.field.label}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -22,7 +25,10 @@
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
<span>{{i18n "admin.wizard.field.required_label"}}</span>
|
<span>{{i18n "admin.wizard.field.required_label"}}</span>
|
||||||
{{input type="checkbox" checked=field.required}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.field.required}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -31,7 +37,10 @@
|
||||||
<label>{{i18n "admin.wizard.field.description"}}</label>
|
<label>{{i18n "admin.wizard.field.description"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{textarea name="description" value=field.description}}
|
<Textarea
|
||||||
|
name="description"
|
||||||
|
@value={{this.field.description}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -78,11 +87,12 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input
|
<Input
|
||||||
type="number"
|
@type="number"
|
||||||
name="min_length"
|
name="min_length"
|
||||||
value=field.min_length
|
@value={{this.field.min_length}}
|
||||||
class="small"}}
|
class="small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -92,11 +102,12 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input
|
<Input
|
||||||
type="number"
|
@type="number"
|
||||||
name="max_length"
|
name="max_length"
|
||||||
value=field.max_length
|
@value={{this.field.max_length}}
|
||||||
class="small"}}
|
class="small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -107,9 +118,10 @@
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
<span>{{i18n "admin.wizard.field.char_counter_placeholder"}}</span>
|
<span>{{i18n "admin.wizard.field.char_counter_placeholder"}}</span>
|
||||||
{{input
|
<Input
|
||||||
type="checkbox"
|
@type="checkbox"
|
||||||
checked=field.char_counter}}
|
@checked={{this.field.char_counter}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -119,10 +131,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{textarea
|
<Textarea
|
||||||
name="field_placeholder"
|
name="field_placeholder"
|
||||||
class="medium"
|
class="medium"
|
||||||
value=field.placeholder}}
|
@value={{this.field.placeholder}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -134,7 +147,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{textarea name="preview-template" value=field.preview_template class="preview-template"}}
|
<Textarea
|
||||||
|
name="preview-template"
|
||||||
|
class="preview-template"
|
||||||
|
@value={{this.field.preview_template}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -146,7 +163,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input value=field.file_types class="medium"}}
|
<Input
|
||||||
|
@value={{this.field.file_types}}
|
||||||
|
class="medium"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -158,7 +178,11 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="number" value=field.limit class="small"}}
|
<Input
|
||||||
|
@type="number"
|
||||||
|
@value={{this.field.limit}}
|
||||||
|
class="small"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@ -170,7 +194,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input value=field.format class="medium"}}
|
<Input
|
||||||
|
@value={{this.field.format}}
|
||||||
|
class="medium"
|
||||||
|
/>
|
||||||
<label>{{html-safe (i18n "admin.wizard.field.date_time_format.instructions")}}</label>
|
<label>{{html-safe (i18n "admin.wizard.field.date_time_format.instructions")}}</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -229,9 +256,10 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input
|
<Input
|
||||||
type="checkbox"
|
@type="checkbox"
|
||||||
checked=field.can_create_tag}}
|
@checked={{this.field.can_create_tag}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -3,9 +3,10 @@
|
||||||
<label>{{i18n "admin.wizard.step.title"}}</label>
|
<label>{{i18n "admin.wizard.step.title"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input
|
<Input
|
||||||
name="title"
|
name="title"
|
||||||
value=step.title}}
|
@value={{this.step.title}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -51,7 +52,10 @@
|
||||||
<div class="setting-label"></div>
|
<div class="setting-label"></div>
|
||||||
<div class="setting-value force-final">
|
<div class="setting-value force-final">
|
||||||
<h4>{{i18n "admin.wizard.step.force_final.label"}}</h4>
|
<h4>{{i18n "admin.wizard.step.force_final.label"}}</h4>
|
||||||
{{input type="checkbox" checked=step.force_final}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.step.force_final}}
|
||||||
|
/>
|
||||||
<span>{{i18n "admin.wizard.step.force_final.description"}}</span>
|
<span>{{i18n "admin.wizard.step.force_final.description"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -77,7 +81,9 @@
|
||||||
<div class="label">
|
<div class="label">
|
||||||
{{i18n "admin.wizard.step.required_data.not_permitted_message"}}
|
{{i18n "admin.wizard.step.required_data.not_permitted_message"}}
|
||||||
</div>
|
</div>
|
||||||
{{input value=step.required_data_message}}
|
<Input
|
||||||
|
@value={{this.step.required_data_message}}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,11 +21,12 @@
|
||||||
|
|
||||||
<div class="input">
|
<div class="input">
|
||||||
{{#if showText}}
|
{{#if showText}}
|
||||||
{{input
|
<Input
|
||||||
type="text"
|
@type="text"
|
||||||
value=value
|
@value={{this.value}}
|
||||||
placeholder=(i18n placeholderKey)
|
placeholder={{i18n placeholderKey}}
|
||||||
change=(action "changeInputValue")}}
|
{{on "change" (action "changeInputValue")}}
|
||||||
|
/>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if showComboBox}}
|
{{#if showComboBox}}
|
||||||
|
|
|
@ -7,7 +7,10 @@
|
||||||
<li>
|
<li>
|
||||||
<span class="setting-title">
|
<span class="setting-title">
|
||||||
<h4>{{i18n (concat "admin.wizard.field.validations." type)}}</h4>
|
<h4>{{i18n (concat "admin.wizard.field.validations." type)}}</h4>
|
||||||
{{input type="checkbox" checked=props.status}}
|
<Input
|
||||||
|
@type="checkbox"
|
||||||
|
@checked={{this.props.status}}
|
||||||
|
/>
|
||||||
{{i18n "admin.wizard.field.validations.enabled"}}
|
{{i18n "admin.wizard.field.validations.enabled"}}
|
||||||
</span>
|
</span>
|
||||||
<div class="validation-container">
|
<div class="validation-container">
|
||||||
|
@ -27,7 +30,11 @@
|
||||||
<label>{{i18n "admin.wizard.field.validations.max_topic_age"}}</label>
|
<label>{{i18n "admin.wizard.field.validations.max_topic_age"}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{input type="number" class="time-n-value" value=props.time_n_value}}
|
<Input
|
||||||
|
@type="number"
|
||||||
|
@value={{this.props.time_n_value}}
|
||||||
|
class="time-n-value"
|
||||||
|
/>
|
||||||
{{combo-box
|
{{combo-box
|
||||||
value=(readonly props.time_unit)
|
value=(readonly props.time_unit)
|
||||||
content=timeUnits
|
content=timeUnits
|
||||||
|
|
|
@ -32,15 +32,10 @@ body.custom-wizard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.invalid {
|
&.invalid .wizard-focusable {
|
||||||
textarea,
|
|
||||||
input[type="text"],
|
|
||||||
input[type="checkbox"],
|
|
||||||
.select-kit {
|
|
||||||
outline: 4px solid var(--danger);
|
outline: 4px solid var(--danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.checkbox-field {
|
.checkbox-field {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
|
@ -324,6 +324,7 @@ en:
|
||||||
then: "then"
|
then: "then"
|
||||||
set: "set"
|
set: "set"
|
||||||
equal: '='
|
equal: '='
|
||||||
|
not_equal: '!='
|
||||||
greater: '>'
|
greater: '>'
|
||||||
less: '<'
|
less: '<'
|
||||||
greater_or_equal: '>='
|
greater_or_equal: '>='
|
||||||
|
|
|
@ -456,11 +456,16 @@ class CustomWizard::Action
|
||||||
|
|
||||||
if new_group_params[:usernames].present?
|
if new_group_params[:usernames].present?
|
||||||
user_ids = get_user_ids(new_group_params[:usernames])
|
user_ids = get_user_ids(new_group_params[:usernames])
|
||||||
|
if user_ids.count < new_group_params[:usernames].count
|
||||||
|
log_error("Warning, group creation: some users were not found!")
|
||||||
|
end
|
||||||
user_ids -= owner_ids if owner_ids
|
user_ids -= owner_ids if owner_ids
|
||||||
user_ids.each { |user_id| group.group_users.build(user_id: user_id) }
|
user_ids.each { |user_id| group.group_users.build(user_id: user_id) }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if group.save
|
||||||
log_success("Group created", group.name)
|
log_success("Group created", group.name)
|
||||||
|
end
|
||||||
|
|
||||||
result.output = group.name
|
result.output = group.name
|
||||||
else
|
else
|
||||||
|
|
|
@ -15,13 +15,13 @@ class CustomWizard::Log
|
||||||
@username = attrs['username']
|
@username = attrs['username']
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.create(wizard_id, action, username, message)
|
def self.create(wizard_id, action, username, message, date = Time.now)
|
||||||
log_id = SecureRandom.hex(12)
|
log_id = SecureRandom.hex(12)
|
||||||
|
|
||||||
PluginStore.set('custom_wizard_log',
|
PluginStore.set('custom_wizard_log',
|
||||||
log_id.to_s,
|
log_id.to_s,
|
||||||
{
|
{
|
||||||
date: Time.now,
|
date: date,
|
||||||
wizard_id: wizard_id,
|
wizard_id: wizard_id,
|
||||||
action: action,
|
action: action,
|
||||||
username: username,
|
username: username,
|
||||||
|
|
|
@ -30,6 +30,7 @@ class CustomWizard::Mapper
|
||||||
|
|
||||||
OPERATORS = {
|
OPERATORS = {
|
||||||
equal: '==',
|
equal: '==',
|
||||||
|
not_equal: "!=",
|
||||||
greater: '>',
|
greater: '>',
|
||||||
less: '<',
|
less: '<',
|
||||||
greater_or_equal: '>=',
|
greater_or_equal: '>=',
|
||||||
|
@ -44,7 +45,7 @@ class CustomWizard::Mapper
|
||||||
|
|
||||||
def initialize(params)
|
def initialize(params)
|
||||||
@inputs = params[:inputs] || {}
|
@inputs = params[:inputs] || {}
|
||||||
@data = params[:data] || {}
|
@data = params[:data] ? params[:data].with_indifferent_access : {}
|
||||||
@user = params[:user]
|
@user = params[:user]
|
||||||
@opts = params[:opts] || {}
|
@opts = params[:opts] || {}
|
||||||
end
|
end
|
||||||
|
@ -255,7 +256,7 @@ class CustomWizard::Mapper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if opts[:template] && CustomWizard::Subscription.subscribed?
|
if opts[:template] #&& CustomWizard::Subscription.subscribed?
|
||||||
template = Liquid::Template.parse(string)
|
template = Liquid::Template.parse(string)
|
||||||
string = template.render(data)
|
string = template.render(data)
|
||||||
end
|
end
|
||||||
|
@ -267,7 +268,12 @@ class CustomWizard::Mapper
|
||||||
return nil if data.nil?
|
return nil if data.nil?
|
||||||
k = keys.shift
|
k = keys.shift
|
||||||
result = data[k]
|
result = data[k]
|
||||||
keys.empty? ? result : self.recurse(result, keys)
|
|
||||||
|
if keys.empty?
|
||||||
|
result.is_a?(Hash) ? "" : result
|
||||||
|
else
|
||||||
|
self.recurse(result, keys)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def bool(value)
|
def bool(value)
|
||||||
|
|
|
@ -84,6 +84,10 @@ class CustomWizard::Submission
|
||||||
data
|
data
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def submitted?
|
||||||
|
!!submitted_at
|
||||||
|
end
|
||||||
|
|
||||||
def self.get(wizard)
|
def self.get(wizard)
|
||||||
data = PluginStore.get("#{wizard.id}_#{KEY}", wizard.actor_id).last
|
data = PluginStore.get("#{wizard.id}_#{KEY}", wizard.actor_id).last
|
||||||
new(wizard, data)
|
new(wizard, data)
|
||||||
|
@ -120,16 +124,23 @@ class CustomWizard::Submission
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.list(wizard, order_by: nil, page: nil)
|
def self.list(wizard, order_by: nil, page: nil)
|
||||||
|
list_actor_id = wizard.actor_id
|
||||||
|
list_user = wizard.user if wizard.user.present?
|
||||||
|
|
||||||
params = { plugin_name: "#{wizard.id}_#{KEY}" }
|
params = { plugin_name: "#{wizard.id}_#{KEY}" }
|
||||||
params[:key] = wizard.actor_id if wizard.actor_id
|
params[:key] = list_actor_id if list_actor_id
|
||||||
|
|
||||||
query = PluginStoreRow.where(params)
|
query = PluginStoreRow.where(params)
|
||||||
result = OpenStruct.new(submissions: [], total: nil)
|
result = OpenStruct.new(submissions: [], total: nil)
|
||||||
|
|
||||||
query.each do |record|
|
query.each do |record|
|
||||||
if (submission_data = ::JSON.parse(record.value)).any?
|
if (submission_data = ::JSON.parse(record.value)).any?
|
||||||
|
submission_user = list_user || User.find_by(id: record.key.to_i)
|
||||||
|
|
||||||
submission_data.each do |data|
|
submission_data.each do |data|
|
||||||
result.submissions.push(new(wizard, data))
|
_wizard = wizard.clone
|
||||||
|
_wizard.user = submission_user if submission_user.present?
|
||||||
|
result.submissions.push(new(_wizard, data))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -84,7 +84,7 @@ class CustomWizard::TemplateValidator
|
||||||
|
|
||||||
def validate_guests(object, type)
|
def validate_guests(object, type)
|
||||||
guests_permitted = @data[:permitted] && @data[:permitted].any? do |m|
|
guests_permitted = @data[:permitted] && @data[:permitted].any? do |m|
|
||||||
m["output"].include?(CustomWizard::Wizard::GUEST_GROUP_ID)
|
m["output"]&.include?(CustomWizard::Wizard::GUEST_GROUP_ID)
|
||||||
end
|
end
|
||||||
return unless guests_permitted
|
return unless guests_permitted
|
||||||
|
|
||||||
|
|
|
@ -176,6 +176,7 @@ class CustomWizard::Wizard
|
||||||
|
|
||||||
def unfinished?
|
def unfinished?
|
||||||
return nil unless actor_id
|
return nil unless actor_id
|
||||||
|
return false if last_submission&.submitted?
|
||||||
|
|
||||||
most_recent = CustomWizard::UserHistory.where(
|
most_recent = CustomWizard::UserHistory.where(
|
||||||
actor_id: actor_id,
|
actor_id: actor_id,
|
||||||
|
@ -194,6 +195,7 @@ class CustomWizard::Wizard
|
||||||
|
|
||||||
def completed?
|
def completed?
|
||||||
return nil unless actor_id
|
return nil unless actor_id
|
||||||
|
return true if last_submission&.submitted?
|
||||||
|
|
||||||
history = CustomWizard::UserHistory.where(
|
history = CustomWizard::UserHistory.where(
|
||||||
actor_id: actor_id,
|
actor_id: actor_id,
|
||||||
|
@ -230,6 +232,7 @@ class CustomWizard::Wizard
|
||||||
m[:type] === 'assignment' && [*m[:result]].include?(GUEST_GROUP_ID)
|
m[:type] === 'assignment' && [*m[:result]].include?(GUEST_GROUP_ID)
|
||||||
else
|
else
|
||||||
if m[:type] === 'assignment'
|
if m[:type] === 'assignment'
|
||||||
|
[*m[:result]].include?(GUEST_GROUP_ID) ||
|
||||||
[*m[:result]].include?(Group::AUTO_GROUPS[:everyone]) ||
|
[*m[:result]].include?(Group::AUTO_GROUPS[:everyone]) ||
|
||||||
GroupUser.exists?(group_id: m[:result], user_id: user.id)
|
GroupUser.exists?(group_id: m[:result], user_id: user.id)
|
||||||
elsif m[:type] === 'validation'
|
elsif m[:type] === 'validation'
|
||||||
|
@ -281,6 +284,10 @@ class CustomWizard::Wizard
|
||||||
@submissions ||= CustomWizard::Submission.list(self).submissions
|
@submissions ||= CustomWizard::Submission.list(self).submissions
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def last_submission
|
||||||
|
@last_submission ||= submissions&.last
|
||||||
|
end
|
||||||
|
|
||||||
def current_submission
|
def current_submission
|
||||||
@current_submission ||= begin
|
@current_submission ||= begin
|
||||||
if submissions.present?
|
if submissions.present?
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
# name: discourse-custom-wizard
|
# name: discourse-custom-wizard
|
||||||
# about: Forms for Discourse. Better onboarding, structured posting, data enrichment, automated actions and much more.
|
# about: Forms for Discourse. Better onboarding, structured posting, data enrichment, automated actions and much more.
|
||||||
# version: 2.3.0
|
# version: 2.3.4
|
||||||
# authors: Angus McLeod, Faizaan Gagan, Robert Barrow, Keegan George, Kaitlin Maddever
|
# authors: Angus McLeod, Faizaan Gagan, Robert Barrow, Keegan George, Kaitlin Maddever
|
||||||
# url: https://github.com/paviliondev/discourse-custom-wizard
|
# url: https://github.com/paviliondev/discourse-custom-wizard
|
||||||
# contact_emails: development@pavilion.tech
|
# contact_emails: development@pavilion.tech
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
describe CustomWizard::Action do
|
describe CustomWizard::Action do
|
||||||
fab!(:user) { Fabricate(:user, name: "Angus", username: 'angus', email: "angus@email.com", trust_level: TrustLevel[2]) }
|
fab!(:user) { Fabricate(:user, name: "Angus", username: 'angus', email: "angus@email.com", trust_level: TrustLevel[2]) }
|
||||||
|
fab!(:user1) { Fabricate(:user, name: "Angus One", username: 'angus1', email: "angus_one@email.com", trust_level: TrustLevel[2]) }
|
||||||
fab!(:category) { Fabricate(:category, name: 'cat1', slug: 'cat-slug') }
|
fab!(:category) { Fabricate(:category, name: 'cat1', slug: 'cat-slug') }
|
||||||
fab!(:tag) { Fabricate(:tag, name: 'tag1') }
|
fab!(:tag) { Fabricate(:tag, name: 'tag1') }
|
||||||
fab!(:group) { Fabricate(:group) }
|
fab!(:group) { Fabricate(:group) }
|
||||||
|
@ -12,6 +13,7 @@ describe CustomWizard::Action do
|
||||||
let(:watch_categories) { get_wizard_fixture("actions/watch_categories") }
|
let(:watch_categories) { get_wizard_fixture("actions/watch_categories") }
|
||||||
let(:watch_tags) { get_wizard_fixture("actions/watch_tags") }
|
let(:watch_tags) { get_wizard_fixture("actions/watch_tags") }
|
||||||
let(:create_group) { get_wizard_fixture("actions/create_group") }
|
let(:create_group) { get_wizard_fixture("actions/create_group") }
|
||||||
|
let(:create_group_with_nonexistent_user) { get_wizard_fixture("actions/create_group_bad_user") }
|
||||||
let(:add_to_group) { get_wizard_fixture("actions/add_to_group") }
|
let(:add_to_group) { get_wizard_fixture("actions/add_to_group") }
|
||||||
let(:send_message) { get_wizard_fixture("actions/send_message") }
|
let(:send_message) { get_wizard_fixture("actions/send_message") }
|
||||||
let(:send_message_multi) { get_wizard_fixture("actions/send_message_multi") }
|
let(:send_message_multi) { get_wizard_fixture("actions/send_message_multi") }
|
||||||
|
@ -350,7 +352,25 @@ describe CustomWizard::Action do
|
||||||
wizard = CustomWizard::Builder.new(@template[:id], user).build
|
wizard = CustomWizard::Builder.new(@template[:id], user).build
|
||||||
wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update
|
wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update
|
||||||
|
|
||||||
|
group_id = Group.where(name: wizard.current_submission.fields['action_9']).first.id
|
||||||
|
user_id = User.find_by(username: wizard_template['actions'][4]['usernames'][0]["output"][0]).id
|
||||||
|
|
||||||
expect(Group.where(name: wizard.current_submission.fields['action_9']).exists?).to eq(true)
|
expect(Group.where(name: wizard.current_submission.fields['action_9']).exists?).to eq(true)
|
||||||
|
expect(GroupUser.where(group_id: group_id, user_id: user_id).exists?).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it '#create_group completes successfully when user included in usernames does not exist but excludes users who do not exist and includes warning in log' do
|
||||||
|
wizard_template['actions'] << create_group_with_nonexistent_user
|
||||||
|
update_template(wizard_template)
|
||||||
|
|
||||||
|
wizard = CustomWizard::Builder.new(@template[:id], user).build
|
||||||
|
wizard.create_updater(wizard.steps[0].id, step_1_field_1: "Text input").update
|
||||||
|
|
||||||
|
group_id = Group.where(name: wizard.current_submission.fields['action_9']).first.id
|
||||||
|
|
||||||
|
expect(CustomWizard::Log.list_query.all.last.value.include? "some users were not found").to eq(true)
|
||||||
|
expect(Group.where(name: wizard.current_submission.fields['action_9']).exists?).to eq(true)
|
||||||
|
expect(GroupUser.where(group_id: group_id).count).to eq(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
it '#add_to_group' do
|
it '#add_to_group' do
|
||||||
|
|
|
@ -58,6 +58,11 @@ describe CustomWizard::Mapper do
|
||||||
"step_1_field_3" => "Value"
|
"step_1_field_3" => "Value"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let(:template_params_object) {
|
||||||
|
{
|
||||||
|
"step_1_field_1": get_wizard_fixture("field/upload")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
def create_template_mapper(data, user)
|
def create_template_mapper(data, user)
|
||||||
CustomWizard::Mapper.new(
|
CustomWizard::Mapper.new(
|
||||||
|
@ -286,6 +291,19 @@ describe CustomWizard::Mapper do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "handles not equal pairs" do
|
||||||
|
expect(CustomWizard::Mapper.new(
|
||||||
|
inputs: inputs['not_equals_pair'],
|
||||||
|
data: data,
|
||||||
|
user: user1
|
||||||
|
).perform).to eq(true)
|
||||||
|
expect(CustomWizard::Mapper.new(
|
||||||
|
inputs: inputs['not_equals_pair'],
|
||||||
|
data: data,
|
||||||
|
user: user2
|
||||||
|
).perform).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
it "handles greater than pairs" do
|
it "handles greater than pairs" do
|
||||||
expect(CustomWizard::Mapper.new(
|
expect(CustomWizard::Mapper.new(
|
||||||
inputs: inputs['greater_than_pair'],
|
inputs: inputs['greater_than_pair'],
|
||||||
|
@ -373,7 +391,7 @@ describe CustomWizard::Mapper do
|
||||||
expect(result).to eq(template_params["step_1_field_1"])
|
expect(result).to eq(template_params["step_1_field_1"])
|
||||||
end
|
end
|
||||||
|
|
||||||
it "requires a subscription" do
|
it "does not require a subscription" do
|
||||||
template = '{{ "w{step_1_field_1}" | size }}'
|
template = '{{ "w{step_1_field_1}" | size }}'
|
||||||
mapper = create_template_mapper(template_params, user1)
|
mapper = create_template_mapper(template_params, user1)
|
||||||
result = mapper.interpolate(
|
result = mapper.interpolate(
|
||||||
|
@ -383,7 +401,7 @@ describe CustomWizard::Mapper do
|
||||||
wizard: true,
|
wizard: true,
|
||||||
value: true
|
value: true
|
||||||
)
|
)
|
||||||
expect(result).to eq("{{ \"#{template_params["step_1_field_1"]}\" | size }}")
|
expect(result).to eq("5")
|
||||||
end
|
end
|
||||||
|
|
||||||
context "with a subscription" do
|
context "with a subscription" do
|
||||||
|
@ -448,6 +466,40 @@ describe CustomWizard::Mapper do
|
||||||
expect(result).to eq(template)
|
expect(result).to eq(template)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "handles correct object variable references" do
|
||||||
|
template = <<-LIQUID.strip
|
||||||
|
{%- if "w{step_1_field_1.id}" == "step_2_field_7" -%}
|
||||||
|
Correct
|
||||||
|
{%- else -%}
|
||||||
|
Incorrect
|
||||||
|
{%-endif-%}
|
||||||
|
LIQUID
|
||||||
|
mapper = create_template_mapper(template_params_object, user1)
|
||||||
|
result = mapper.interpolate(
|
||||||
|
template.dup,
|
||||||
|
template: true,
|
||||||
|
wizard: true
|
||||||
|
)
|
||||||
|
expect(result).to eq("Correct")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "handles incorrect object variable references" do
|
||||||
|
template = <<-LIQUID.strip
|
||||||
|
{%- if "w{step_1_field_1}" == "step_2_field_7" -%}
|
||||||
|
Correct
|
||||||
|
{%- else -%}
|
||||||
|
Incorrect
|
||||||
|
{%-endif-%}
|
||||||
|
LIQUID
|
||||||
|
mapper = create_template_mapper(template_params_object, user1)
|
||||||
|
result = mapper.interpolate(
|
||||||
|
template.dup,
|
||||||
|
template: true,
|
||||||
|
wizard: true
|
||||||
|
)
|
||||||
|
expect(result).to eq("Incorrect")
|
||||||
|
end
|
||||||
|
|
||||||
context "custom filter: 'first_non_empty'" do
|
context "custom filter: 'first_non_empty'" do
|
||||||
it "gives first non empty element from list" do
|
it "gives first non empty element from list" do
|
||||||
template = <<-LIQUID.strip
|
template = <<-LIQUID.strip
|
||||||
|
|
|
@ -9,6 +9,7 @@ describe CustomWizard::TemplateValidator do
|
||||||
let(:composer_preview) { get_wizard_fixture("field/composer_preview") }
|
let(:composer_preview) { get_wizard_fixture("field/composer_preview") }
|
||||||
let(:guests_permitted) { get_wizard_fixture("wizard/guests_permitted") }
|
let(:guests_permitted) { get_wizard_fixture("wizard/guests_permitted") }
|
||||||
let(:upload_field) { get_wizard_fixture("field/upload") }
|
let(:upload_field) { get_wizard_fixture("field/upload") }
|
||||||
|
let(:validation_condition) { get_wizard_fixture("condition/validation_condition") }
|
||||||
|
|
||||||
let(:valid_liquid_template) {
|
let(:valid_liquid_template) {
|
||||||
<<-LIQUID.strip
|
<<-LIQUID.strip
|
||||||
|
@ -182,6 +183,13 @@ describe CustomWizard::TemplateValidator do
|
||||||
CustomWizard::TemplateValidator.new(template).perform
|
CustomWizard::TemplateValidator.new(template).perform
|
||||||
).to eq(true)
|
).to eq(true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "validates settings with validation conditions" do
|
||||||
|
template[:permitted] = validation_condition["condition"]
|
||||||
|
expect(
|
||||||
|
CustomWizard::TemplateValidator.new(template).perform
|
||||||
|
).to eq(true)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
context "steps" do
|
context "steps" do
|
||||||
|
|
|
@ -6,11 +6,15 @@ describe CustomWizard::Wizard do
|
||||||
fab!(:admin_user) { Fabricate(:user, admin: true) }
|
fab!(:admin_user) { Fabricate(:user, admin: true) }
|
||||||
let(:template_json) { get_wizard_fixture("wizard") }
|
let(:template_json) { get_wizard_fixture("wizard") }
|
||||||
let(:permitted_json) { get_wizard_fixture("wizard/permitted") }
|
let(:permitted_json) { get_wizard_fixture("wizard/permitted") }
|
||||||
|
let(:guests_permitted_json) { get_wizard_fixture("wizard/guests_permitted") }
|
||||||
|
let(:step_json) { get_wizard_fixture("step/step") }
|
||||||
|
|
||||||
before do
|
before do
|
||||||
Group.refresh_automatic_group!(:trust_level_3)
|
Group.refresh_automatic_group!(:trust_level_3)
|
||||||
@permitted_template = template_json.dup
|
@permitted_template = template_json.dup
|
||||||
@permitted_template["permitted"] = permitted_json["permitted"]
|
@permitted_template["permitted"] = permitted_json["permitted"]
|
||||||
|
@guests_permitted_template = template_json.dup
|
||||||
|
@guests_permitted_template["permitted"] = guests_permitted_json["permitted"]
|
||||||
@wizard = CustomWizard::Wizard.new(template_json, user)
|
@wizard = CustomWizard::Wizard.new(template_json, user)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -72,6 +76,28 @@ describe CustomWizard::Wizard do
|
||||||
expect(@wizard.start).to eq('step_2')
|
expect(@wizard.start).to eq('step_2')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "determines the user's current step if steps are added" do
|
||||||
|
append_steps
|
||||||
|
progress_step('step_1')
|
||||||
|
progress_step('step_2')
|
||||||
|
progress_step("step_3")
|
||||||
|
|
||||||
|
fourth_step = step_json.dup
|
||||||
|
fourth_step['id'] = "step_4"
|
||||||
|
template = template_json.dup
|
||||||
|
template['steps'] << fourth_step
|
||||||
|
|
||||||
|
CustomWizard::Template.save(template, skip_jobs: true)
|
||||||
|
|
||||||
|
wizard = CustomWizard::Wizard.new(template, user)
|
||||||
|
template['steps'].each do |step_template|
|
||||||
|
wizard.append_step(step_template['id'])
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(wizard.steps.size).to eq(4)
|
||||||
|
expect(wizard.start).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
it "creates a step updater" do
|
it "creates a step updater" do
|
||||||
expect(
|
expect(
|
||||||
@wizard.create_updater('step_1', step_1_field_1: "Text input")
|
@wizard.create_updater('step_1', step_1_field_1: "Text input")
|
||||||
|
@ -200,6 +226,30 @@ describe CustomWizard::Wizard do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context "with subscription and guest wizard" do
|
||||||
|
before do
|
||||||
|
enable_subscription("standard")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "permits admins" do
|
||||||
|
expect(
|
||||||
|
CustomWizard::Wizard.new(@guests_permitted_template, admin_user).permitted?
|
||||||
|
).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "permits regular users" do
|
||||||
|
expect(
|
||||||
|
CustomWizard::Wizard.new(@guests_permitted_template, user).permitted?
|
||||||
|
).to eq(true)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "permits guests" do
|
||||||
|
expect(
|
||||||
|
CustomWizard::Wizard.new(@guests_permitted_template, nil, "guest123").permitted?
|
||||||
|
).to eq(true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
context "submissions" do
|
context "submissions" do
|
||||||
before do
|
before do
|
||||||
CustomWizard::Submission.new(@wizard, step_1_field_1: "I am a user submission").save
|
CustomWizard::Submission.new(@wizard, step_1_field_1: "I am a user submission").save
|
||||||
|
|
104
spec/fixtures/actions/create_group_bad_user.json
gevendort
Normale Datei
104
spec/fixtures/actions/create_group_bad_user.json
gevendort
Normale Datei
|
@ -0,0 +1,104 @@
|
||||||
|
{
|
||||||
|
"id": "action_9",
|
||||||
|
"run_after": "step_1",
|
||||||
|
"type": "create_group",
|
||||||
|
"title": [
|
||||||
|
{
|
||||||
|
"type": "assignment",
|
||||||
|
"output": "New Group Member",
|
||||||
|
"output_type": "text",
|
||||||
|
"output_connector": "set"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"custom_fields": [
|
||||||
|
{
|
||||||
|
"type": "association",
|
||||||
|
"pairs": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"key": "group_custom_field",
|
||||||
|
"key_type": "text",
|
||||||
|
"value": "step_3_field_1",
|
||||||
|
"value_type": "wizard_field",
|
||||||
|
"connector": "association"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": [
|
||||||
|
{
|
||||||
|
"type": "assignment",
|
||||||
|
"output": "step_1_field_1",
|
||||||
|
"output_type": "wizard_field",
|
||||||
|
"output_connector": "set"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"full_name": [
|
||||||
|
{
|
||||||
|
"type": "assignment",
|
||||||
|
"output": "step_1_field_1",
|
||||||
|
"output_type": "wizard_field",
|
||||||
|
"output_connector": "set"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"usernames": [
|
||||||
|
{
|
||||||
|
"type": "assignment",
|
||||||
|
"output_type": "user",
|
||||||
|
"output_connector": "set",
|
||||||
|
"output": [
|
||||||
|
"angus3"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"owner_usernames": [
|
||||||
|
{
|
||||||
|
"type": "assignment",
|
||||||
|
"output_type": "user",
|
||||||
|
"output_connector": "set",
|
||||||
|
"output": [
|
||||||
|
"angus"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"grant_trust_level": [
|
||||||
|
{
|
||||||
|
"type": "assignment",
|
||||||
|
"output": "3",
|
||||||
|
"output_type": "text",
|
||||||
|
"output_connector": "set"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"mentionable_level": [
|
||||||
|
{
|
||||||
|
"type": "assignment",
|
||||||
|
"output": "1",
|
||||||
|
"output_type": "text",
|
||||||
|
"output_connector": "set"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"messageable_level": [
|
||||||
|
{
|
||||||
|
"type": "assignment",
|
||||||
|
"output": "2",
|
||||||
|
"output_type": "text",
|
||||||
|
"output_connector": "set"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"visibility_level": [
|
||||||
|
{
|
||||||
|
"type": "assignment",
|
||||||
|
"output": "3",
|
||||||
|
"output_type": "text",
|
||||||
|
"output_connector": "set"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"members_visibility_level": [
|
||||||
|
{
|
||||||
|
"type": "assignment",
|
||||||
|
"output": "99",
|
||||||
|
"output_type": "text",
|
||||||
|
"output_connector": "set"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
17
spec/fixtures/condition/validation_condition.json
gevendort
Normale Datei
17
spec/fixtures/condition/validation_condition.json
gevendort
Normale Datei
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
"condition": [
|
||||||
|
{
|
||||||
|
"type": "validation",
|
||||||
|
"pairs": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"key": "trust_level",
|
||||||
|
"key_type": "user_field",
|
||||||
|
"value": "2",
|
||||||
|
"value_type": "text",
|
||||||
|
"connector": "greater_or_equal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
15
spec/fixtures/mapper/inputs.json
gevendort
15
spec/fixtures/mapper/inputs.json
gevendort
|
@ -195,6 +195,21 @@
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"not_equals_pair": [
|
||||||
|
{
|
||||||
|
"type": "validation",
|
||||||
|
"pairs": [
|
||||||
|
{
|
||||||
|
"index": 0,
|
||||||
|
"key": "trust_level",
|
||||||
|
"key_type": "user_field",
|
||||||
|
"value": "1",
|
||||||
|
"value_type": "text",
|
||||||
|
"connector": "not_equal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"greater_than_pair": [
|
"greater_than_pair": [
|
||||||
{
|
{
|
||||||
"type": "validation",
|
"type": "validation",
|
||||||
|
|
|
@ -4,7 +4,7 @@ describe CustomWizard::LogSerializer do
|
||||||
fab!(:user) { Fabricate(:user) }
|
fab!(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
it 'should return log attributes' do
|
it 'should return log attributes' do
|
||||||
CustomWizard::Log.create('first-test-wizard', 'perform_first_action', 'first_test_user', 'First log message')
|
CustomWizard::Log.create('first-test-wizard', 'perform_first_action', 'first_test_user', 'First log message', 1.day.ago)
|
||||||
CustomWizard::Log.create('second-test-wizard', 'perform_second_action', 'second_test_user', 'Second log message')
|
CustomWizard::Log.create('second-test-wizard', 'perform_second_action', 'second_test_user', 'Second log message')
|
||||||
|
|
||||||
json_array = ActiveModel::ArraySerializer.new(
|
json_array = ActiveModel::ArraySerializer.new(
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
require_relative '../../plugin_helper'
|
require_relative '../../plugin_helper'
|
||||||
|
|
||||||
describe CustomWizard::SubmissionSerializer do
|
describe CustomWizard::SubmissionSerializer do
|
||||||
fab!(:user) { Fabricate(:user) }
|
fab!(:user1) { Fabricate(:user) }
|
||||||
|
fab!(:user2) { Fabricate(:user) }
|
||||||
|
|
||||||
let(:template_json) {
|
let(:template_json) {
|
||||||
JSON.parse(File.open(
|
JSON.parse(File.open(
|
||||||
|
@ -13,36 +14,43 @@ describe CustomWizard::SubmissionSerializer do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
CustomWizard::Template.save(template_json, skip_jobs: true)
|
CustomWizard::Template.save(template_json, skip_jobs: true)
|
||||||
wizard = CustomWizard::Wizard.create(template_json["id"], user)
|
|
||||||
CustomWizard::Submission.new(wizard,
|
wizard = CustomWizard::Wizard.create(template_json["id"], user1)
|
||||||
step_1_field_1: "I am user submission",
|
CustomWizard::Submission.new(wizard, step_1_field_1: "I am user1 submission", submitted_at: Time.now.iso8601).save
|
||||||
submitted_at: Time.now.iso8601
|
|
||||||
).save
|
wizard = CustomWizard::Wizard.create(template_json["id"], user2)
|
||||||
@list = CustomWizard::Submission.list(wizard, page: 0)
|
CustomWizard::Submission.new(wizard, step_1_field_1: "I am user2 submission", submitted_at: Time.now.iso8601).save
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'should return submission attributes' do
|
it 'should return submission attributes' do
|
||||||
|
wizard = CustomWizard::Wizard.create(template_json["id"])
|
||||||
|
list = CustomWizard::Submission.list(wizard, page: 0)
|
||||||
|
|
||||||
json_array = ActiveModel::ArraySerializer.new(
|
json_array = ActiveModel::ArraySerializer.new(
|
||||||
@list.submissions,
|
list.submissions,
|
||||||
each_serializer: described_class
|
each_serializer: described_class
|
||||||
).as_json
|
).as_json
|
||||||
|
|
||||||
expect(json_array.length).to eq(1)
|
expect(json_array.length).to eq(2)
|
||||||
expect(json_array[0][:id].present?).to eq(true)
|
expect(json_array[0][:id].present?).to eq(true)
|
||||||
expect(json_array[0][:user].present?).to eq(true)
|
|
||||||
expect(json_array[0][:submitted_at].present?).to eq(true)
|
expect(json_array[0][:submitted_at].present?).to eq(true)
|
||||||
|
expect(json_array[0][:user]).to eq(BasicUserSerializer.new(user2, root: false).as_json)
|
||||||
|
expect(json_array[1][:user]).to eq(BasicUserSerializer.new(user1, root: false).as_json)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "should return field values, types and labels" do
|
it "should return field values, types and labels" do
|
||||||
|
wizard = CustomWizard::Wizard.create(template_json["id"])
|
||||||
|
list = CustomWizard::Submission.list(wizard, page: 0)
|
||||||
|
|
||||||
json_array = ActiveModel::ArraySerializer.new(
|
json_array = ActiveModel::ArraySerializer.new(
|
||||||
@list.submissions,
|
list.submissions,
|
||||||
each_serializer: described_class
|
each_serializer: described_class
|
||||||
).as_json
|
).as_json
|
||||||
|
|
||||||
expect(json_array.length).to eq(1)
|
expect(json_array.length).to eq(2)
|
||||||
expect(json_array[0][:fields].as_json).to eq({
|
expect(json_array[0][:fields].as_json).to eq({
|
||||||
"step_1_field_1": {
|
"step_1_field_1": {
|
||||||
"value": "I am user submission",
|
"value": "I am user2 submission",
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"label": "Text"
|
"label": "Text"
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,6 +54,70 @@ acceptance("Field | Fields", function (needs) {
|
||||||
"Input in composer"
|
"Input in composer"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
test("Composer - Hyperlink", async function (assert) {
|
||||||
|
await visit("/w/wizard");
|
||||||
|
assert.ok(
|
||||||
|
visible(".wizard-field.composer-field .wizard-field-composer textarea")
|
||||||
|
);
|
||||||
|
assert.ok(
|
||||||
|
exists(".wizard-field.composer-field .d-editor-button-bar button")
|
||||||
|
);
|
||||||
|
assert.ok(visible(".wizard-btn.toggle-preview"));
|
||||||
|
await fillIn(
|
||||||
|
".wizard-field.composer-field .wizard-field-composer textarea",
|
||||||
|
"This is a link to "
|
||||||
|
);
|
||||||
|
assert.ok(
|
||||||
|
!exists(".insert-link.modal-body"),
|
||||||
|
"no hyperlink modal by default"
|
||||||
|
);
|
||||||
|
await click(
|
||||||
|
".wizard-field.composer-field .wizard-field-composer .d-editor button.link"
|
||||||
|
);
|
||||||
|
assert.ok(exists(".insert-link.modal-body"), "hyperlink modal visible");
|
||||||
|
|
||||||
|
await fillIn(".modal-body .link-url", "google.com");
|
||||||
|
await fillIn(".modal-body .link-text", "Google");
|
||||||
|
await click(".modal-footer button.btn-primary");
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
query(".wizard-field.composer-field .wizard-field-composer textarea")
|
||||||
|
.value,
|
||||||
|
"This is a link to [Google](https://google.com)",
|
||||||
|
"adds link with url and text, prepends 'https://'"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
!exists(
|
||||||
|
".wizard-field.composer-field .wizard-field-composer .insert-link.modal-body"
|
||||||
|
),
|
||||||
|
"modal dismissed after submitting link"
|
||||||
|
);
|
||||||
|
|
||||||
|
await fillIn(
|
||||||
|
".wizard-field.composer-field .wizard-field-composer textarea",
|
||||||
|
"Reset textarea contents."
|
||||||
|
);
|
||||||
|
|
||||||
|
await click(
|
||||||
|
".wizard-field.composer-field .wizard-field-composer .d-editor button.link"
|
||||||
|
);
|
||||||
|
await fillIn(".modal-body .link-url", "google.com");
|
||||||
|
await fillIn(".modal-body .link-text", "Google");
|
||||||
|
await click(".modal-footer button.btn-danger");
|
||||||
|
|
||||||
|
assert.strictEqual(
|
||||||
|
query(".wizard-field.composer-field .wizard-field-composer textarea")
|
||||||
|
.value,
|
||||||
|
"Reset textarea contents.",
|
||||||
|
"does not insert anything after cancelling"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
|
!exists(".insert-link.modal-body"),
|
||||||
|
"modal dismissed after cancelling"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test("Text Only", async function (assert) {
|
test("Text Only", async function (assert) {
|
||||||
await visit("/w/wizard");
|
await visit("/w/wizard");
|
||||||
|
|
Laden …
In neuem Issue referenzieren