Merge branch 'ui_conventions' of https://github.com/paviliondev/discourse-custom-wizard into pr/142
Dieser Commit ist enthalten in:
Commit
5063e3eaeb
24 geänderte Dateien mit 402 neuen und 164 gelöschten Zeilen
|
@ -1,10 +1,9 @@
|
||||||
import { action } from "@ember/object";
|
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
import { action } from "@ember/object";
|
||||||
import { equal } from "@ember/object/computed";
|
import { equal } from "@ember/object/computed";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
|
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
isText: equal("value.type", "text"),
|
isText: equal("value.type", "text"),
|
||||||
isComposer: equal("value.type", "composer"),
|
isComposer: equal("value.type", "composer"),
|
||||||
|
@ -25,7 +24,7 @@ export default Component.extend({
|
||||||
isTextArea: equal("value.type", "textarea"),
|
isTextArea: equal("value.type", "textarea"),
|
||||||
isComposerPreview: equal("value.type", "composer_preview"),
|
isComposerPreview: equal("value.type", "composer_preview"),
|
||||||
textState: "text-collapsed",
|
textState: "text-collapsed",
|
||||||
toggleText: I18n.t('admin.wizard.submissions.expand_text'),
|
toggleText: I18n.t("admin.wizard.submissions.expand_text"),
|
||||||
|
|
||||||
@discourseComputed("value")
|
@discourseComputed("value")
|
||||||
checkboxValue(value) {
|
checkboxValue(value) {
|
||||||
|
@ -45,14 +44,14 @@ export default Component.extend({
|
||||||
|
|
||||||
if (state === "text-collapsed") {
|
if (state === "text-collapsed") {
|
||||||
this.set("textState", "text-expanded");
|
this.set("textState", "text-expanded");
|
||||||
this.set("toggleText", I18n.t('admin.wizard.submissions.collapse_text'));
|
this.set("toggleText", I18n.t("admin.wizard.submissions.collapse_text"));
|
||||||
} else if (state === "text-expanded") {
|
} else if (state === "text-expanded") {
|
||||||
this.set("textState", "text-collapsed");
|
this.set("textState", "text-collapsed");
|
||||||
this.set("toggleText", I18n.t('admin.wizard.submissions.expand_text'));
|
this.set("toggleText", I18n.t("admin.wizard.submissions.expand_text"));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed('value')
|
@discourseComputed("value")
|
||||||
file(value) {
|
file(value) {
|
||||||
const isUpload = this.get("isUpload");
|
const isUpload = this.get("isUpload");
|
||||||
if (isUpload) {
|
if (isUpload) {
|
||||||
|
@ -60,52 +59,51 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed('value')
|
@discourseComputed("value")
|
||||||
submittedUsers(value) {
|
submittedUsers(value) {
|
||||||
const isUserSelector = this.get("isUserSelector");
|
const isUserSelector = this.get("isUserSelector");
|
||||||
const users = [];
|
const users = [];
|
||||||
|
|
||||||
if (isUserSelector) {
|
if (isUserSelector) {
|
||||||
const userData = value.value;
|
const userData = value.value;
|
||||||
const usernames = [];
|
const usernames = [];
|
||||||
|
|
||||||
if (userData.indexOf(',')) {
|
if (userData.indexOf(",")) {
|
||||||
usernames.push(...userData.split(','));
|
usernames.push(...userData.split(","));
|
||||||
|
|
||||||
usernames.forEach(u => {
|
usernames.forEach((u) => {
|
||||||
const user = {
|
const user = {
|
||||||
username: u,
|
username: u,
|
||||||
url: `/u/${u}`
|
url: `/u/${u}`,
|
||||||
}
|
};
|
||||||
users.push(user);
|
users.push(user);
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return users;
|
return users;
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed('value')
|
@discourseComputed("value")
|
||||||
userProfileUrl(value) {
|
userProfileUrl(value) {
|
||||||
const isUser = this.get("isUser");
|
const isUser = this.get("isUser");
|
||||||
const isUserSelector = this.get("isUserSelector");
|
|
||||||
|
|
||||||
if (isUser) {
|
if (isUser) {
|
||||||
return `/u/${value.username}`;
|
return `/u/${value.username}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed('value')
|
@discourseComputed("value")
|
||||||
categoryUrl(value) {
|
categoryUrl(value) {
|
||||||
const isCategory = this.get('isCategory');
|
const isCategory = this.get("isCategory");
|
||||||
|
|
||||||
if (isCategory) {
|
if (isCategory) {
|
||||||
return `/c/${value.value}`;
|
return `/c/${value.value}`;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed('value')
|
@discourseComputed("value")
|
||||||
groupUrl(value) {
|
groupUrl(value) {
|
||||||
const isGroup = this.get('isGroup');
|
const isGroup = this.get("isGroup");
|
||||||
|
|
||||||
if (isGroup) {
|
if (isGroup) {
|
||||||
return `/g/${value.value}`;
|
return `/g/${value.value}`;
|
||||||
|
|
|
@ -1,15 +1,10 @@
|
||||||
import {
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
default as discourseComputed,
|
|
||||||
observes,
|
|
||||||
on,
|
|
||||||
} from "discourse-common/utils/decorators";
|
|
||||||
import { generateName } from "../lib/wizard";
|
import { generateName } from "../lib/wizard";
|
||||||
import {
|
import {
|
||||||
setWizardDefaults,
|
setWizardDefaults,
|
||||||
default as wizardSchema,
|
default as wizardSchema,
|
||||||
} from "../lib/wizard-schema";
|
} from "../lib/wizard-schema";
|
||||||
import { notEmpty } from "@ember/object/computed";
|
import { notEmpty } from "@ember/object/computed";
|
||||||
import { scheduleOnce } from "@ember/runloop";
|
|
||||||
import EmberObject from "@ember/object";
|
import EmberObject from "@ember/object";
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
import { A } from "@ember/array";
|
import { A } from "@ember/array";
|
||||||
|
@ -19,28 +14,12 @@ export default Component.extend({
|
||||||
items: A(),
|
items: A(),
|
||||||
anyLinks: notEmpty("links"),
|
anyLinks: notEmpty("links"),
|
||||||
|
|
||||||
@on("didInsertElement")
|
|
||||||
@observes("links.[]")
|
|
||||||
setupSortable() {
|
|
||||||
scheduleOnce("afterRender", () => this.applySortable());
|
|
||||||
},
|
|
||||||
|
|
||||||
applySortable() {
|
|
||||||
$(this.element)
|
|
||||||
.find(".link-list")
|
|
||||||
.sortable({ tolerance: "pointer" })
|
|
||||||
.on("sortupdate", (e, ui) => {
|
|
||||||
this.updateItemOrder(ui.item.data("id"), ui.item.index());
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
updateItemOrder(itemId, newIndex) {
|
updateItemOrder(itemId, newIndex) {
|
||||||
const items = this.items;
|
const items = this.items;
|
||||||
const item = items.findBy("id", itemId);
|
const item = items.findBy("id", itemId);
|
||||||
items.removeObject(item);
|
items.removeObject(item);
|
||||||
item.set("index", newIndex);
|
item.set("index", newIndex);
|
||||||
items.insertAt(newIndex, item);
|
items.insertAt(newIndex, item);
|
||||||
scheduleOnce("afterRender", this, () => this.applySortable());
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@discourseComputed("itemType")
|
@discourseComputed("itemType")
|
||||||
|
@ -58,7 +37,7 @@ export default Component.extend({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return items.map((item) => {
|
return items.map((item, index) => {
|
||||||
if (item) {
|
if (item) {
|
||||||
let link = {
|
let link = {
|
||||||
id: item.id,
|
id: item.id,
|
||||||
|
@ -77,6 +56,15 @@ export default Component.extend({
|
||||||
}
|
}
|
||||||
|
|
||||||
link.classes = classes;
|
link.classes = classes;
|
||||||
|
link.index = index;
|
||||||
|
|
||||||
|
if (index === 0) {
|
||||||
|
link.first = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index === items.length - 1) {
|
||||||
|
link.last = true;
|
||||||
|
}
|
||||||
|
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
@ -118,6 +106,14 @@ export default Component.extend({
|
||||||
this.set("current", newItem);
|
this.set("current", newItem);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
back(item) {
|
||||||
|
this.updateItemOrder(item.id, item.index - 1);
|
||||||
|
},
|
||||||
|
|
||||||
|
forward(item) {
|
||||||
|
this.updateItemOrder(item.id, item.index + 1);
|
||||||
|
},
|
||||||
|
|
||||||
change(itemId) {
|
change(itemId) {
|
||||||
this.set("current", this.items.findBy("id", itemId));
|
this.set("current", this.items.findBy("id", itemId));
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,15 +2,14 @@ import Controller from "@ember/controller";
|
||||||
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||||
|
|
||||||
export default Controller.extend(ModalFunctionality, {
|
export default Controller.extend(ModalFunctionality, {
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
save() {
|
save() {
|
||||||
this.send("closeModal");
|
this.send("closeModal");
|
||||||
},
|
},
|
||||||
resetToDefault() {
|
resetToDefault() {
|
||||||
this.get('model.fields').forEach(field => {
|
this.get("model.fields").forEach((field) => {
|
||||||
field.set("enabled", true);
|
field.set("enabled", true);
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import Controller from "@ember/controller";
|
import Controller from "@ember/controller";
|
||||||
import { fmt } from "discourse/lib/computed";
|
|
||||||
import { empty } from "@ember/object/computed";
|
import { empty } from "@ember/object/computed";
|
||||||
import CustomWizard from "../models/custom-wizard";
|
|
||||||
import showModal from "discourse/lib/show-modal";
|
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import { fmt } from "discourse/lib/computed";
|
||||||
|
import showModal from "discourse/lib/show-modal";
|
||||||
|
import CustomWizard from "../models/custom-wizard";
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
downloadUrl: fmt("wizard.id", "/admin/wizards/submissions/%@/download"),
|
downloadUrl: fmt("wizard.id", "/admin/wizards/submissions/%@/download"),
|
||||||
|
@ -27,17 +26,16 @@ export default Controller.extend({
|
||||||
this.set("loadingMore", false);
|
this.set("loadingMore", false);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@discourseComputed("submissions", "fields.@each.enabled")
|
||||||
@discourseComputed('submissions', 'fields.@each.enabled')
|
|
||||||
displaySubmissions(submissions, fields) {
|
displaySubmissions(submissions, fields) {
|
||||||
let result = [];
|
let result = [];
|
||||||
|
|
||||||
submissions.forEach(submission => {
|
submissions.forEach((submission) => {
|
||||||
let sub = {};
|
let sub = {};
|
||||||
|
|
||||||
Object.keys(submission).forEach(fieldId => {
|
Object.keys(submission).forEach((fieldId) => {
|
||||||
if (fields.some(f => f.id === fieldId && f.enabled)) {
|
if (fields.some((f) => f.id === fieldId && f.enabled)) {
|
||||||
sub[fieldId] = submission[fieldId];
|
sub[fieldId] = submission[fieldId];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -56,11 +54,11 @@ export default Controller.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
showEditColumnsModal() {
|
showEditColumnsModal() {
|
||||||
const controller = showModal("admin-wizards-submissions-columns", {
|
return showModal("admin-wizards-submissions-columns", {
|
||||||
model: {
|
model: {
|
||||||
fields: this.get('fields'),
|
fields: this.get("fields"),
|
||||||
submissions: this.get('submissions')
|
submissions: this.get("submissions"),
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { ajax } from "discourse/lib/ajax";
|
|
||||||
import EmberObject from "@ember/object";
|
import EmberObject from "@ember/object";
|
||||||
import { buildProperties, mapped, present } from "../lib/wizard-json";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
import { listProperties, snakeCase } from "../lib/wizard";
|
|
||||||
import wizardSchema from "../lib/wizard-schema";
|
|
||||||
import { Promise } from "rsvp";
|
|
||||||
import { popupAjaxError } from "discourse/lib/ajax-error";
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
|
import { Promise } from "rsvp";
|
||||||
|
import { listProperties, snakeCase } from "../lib/wizard";
|
||||||
|
import { buildProperties, mapped, present } from "../lib/wizard-json";
|
||||||
|
import wizardSchema from "../lib/wizard-schema";
|
||||||
|
|
||||||
const CustomWizard = EmberObject.extend({
|
const CustomWizard = EmberObject.extend({
|
||||||
save(opts) {
|
save(opts) {
|
||||||
|
@ -224,8 +224,7 @@ CustomWizard.reopenClass({
|
||||||
})
|
})
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
if (result.wizard) {
|
if (result.wizard) {
|
||||||
console.log(result);
|
let fields = [{ id: "username", label: "User" }];
|
||||||
let fields = [{ id: "username", label: "User"}];
|
|
||||||
let submissions = [];
|
let submissions = [];
|
||||||
let wizard = result.wizard;
|
let wizard = result.wizard;
|
||||||
let total = result.total;
|
let total = result.total;
|
||||||
|
@ -236,7 +235,7 @@ CustomWizard.reopenClass({
|
||||||
};
|
};
|
||||||
|
|
||||||
Object.keys(s.fields).forEach((fieldId) => {
|
Object.keys(s.fields).forEach((fieldId) => {
|
||||||
if (!fields.some(field => field.id === fieldId)) {
|
if (!fields.some((field) => field.id === fieldId)) {
|
||||||
fields.push({ id: fieldId, label: s.fields[fieldId].label });
|
fields.push({ id: fieldId, label: s.fields[fieldId].label });
|
||||||
}
|
}
|
||||||
submission[fieldId] = s.fields[fieldId];
|
submission[fieldId] = s.fields[fieldId];
|
||||||
|
@ -247,9 +246,9 @@ CustomWizard.reopenClass({
|
||||||
|
|
||||||
let submittedAt = {
|
let submittedAt = {
|
||||||
id: "submitted_at",
|
id: "submitted_at",
|
||||||
label: "Submitted At"
|
label: "Submitted At",
|
||||||
}
|
};
|
||||||
|
|
||||||
fields.push(submittedAt);
|
fields.push(submittedAt);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,16 +1,24 @@
|
||||||
{{#if submissions}}
|
{{#if submissions}}
|
||||||
<div class="wizard-header large">
|
<div class="wizard-header large">
|
||||||
<label>{{i18n "admin.wizard.submissions.title" name=wizard.name}}</label>
|
<label>
|
||||||
|
{{i18n "admin.wizard.submissions.title" name=wizard.name}}
|
||||||
|
</label>
|
||||||
|
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
{{d-button
|
{{d-button
|
||||||
icon="sliders-h"
|
icon="sliders-h"
|
||||||
label="admin.wizard.submissions.edit_columns"
|
label="admin.wizard.submissions.edit_columns"
|
||||||
action=(action "showEditColumnsModal")
|
action=(action "showEditColumnsModal")
|
||||||
class="btn-default open-edit-columns-btn download-link"}}
|
class="btn-default open-edit-columns-btn download-link"
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<a class="btn btn-default download-link" href={{downloadUrl}} target="_blank" rel="noopener noreferrer">
|
<a
|
||||||
|
class="btn btn-default download-link"
|
||||||
|
href={{downloadUrl}}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
>
|
||||||
{{d-icon "download"}}
|
{{d-icon "download"}}
|
||||||
<span class="d-button-label">
|
<span class="d-button-label">
|
||||||
{{i18n "admin.wizard.submissions.download"}}
|
{{i18n "admin.wizard.submissions.download"}}
|
||||||
|
@ -21,14 +29,18 @@
|
||||||
<div class="wizard-submissions">
|
<div class="wizard-submissions">
|
||||||
{{#load-more selector=".wizard-submissions tr" action=(action "loadMore")}}
|
{{#load-more selector=".wizard-submissions tr" action=(action "loadMore")}}
|
||||||
{{#if noResults}}
|
{{#if noResults}}
|
||||||
<p>{{i18n "search.no_results"}}</p>
|
<p>
|
||||||
|
{{i18n "search.no_results"}}
|
||||||
|
</p>
|
||||||
{{else}}
|
{{else}}
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{{#each fields as |field|}}
|
{{#each fields as |field|}}
|
||||||
{{#if field.enabled}}
|
{{#if field.enabled}}
|
||||||
<th>{{field.label}}</th>
|
<th>
|
||||||
|
{{field.label}}
|
||||||
|
</th>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -37,7 +49,9 @@
|
||||||
{{#each displaySubmissions as |submission|}}
|
{{#each displaySubmissions as |submission|}}
|
||||||
<tr>
|
<tr>
|
||||||
{{#each-in submission as |field value|}}
|
{{#each-in submission as |field value|}}
|
||||||
<td>{{submission-field fieldName=field value=value}}</td>
|
<td>
|
||||||
|
{{submission-field fieldName=field value=value}}
|
||||||
|
</td>
|
||||||
{{/each-in}}
|
{{/each-in}}
|
||||||
</tr>
|
</tr>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -48,4 +62,4 @@
|
||||||
{{conditional-loading-spinner condition=loadingMore}}
|
{{conditional-loading-spinner condition=loadingMore}}
|
||||||
{{/load-more}}
|
{{/load-more}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
|
@ -7,6 +7,10 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}}
|
{{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}}
|
||||||
{{nav-item route="adminWizardsManager" label="admin.wizard.manager.nav_label"}}
|
{{nav-item route="adminWizardsManager" label="admin.wizard.manager.nav_label"}}
|
||||||
|
|
||||||
|
<div class="admin-actions">
|
||||||
|
<a target="_blank" class="btn btn-pavilion-pro" rel="noreferrer noopener" href="https://thepavilion.io/w/support" title={{i18n "admin.wizard.pro_support_button.title"}}>{{d-icon "far-life-ring"}}{{i18n "admin.wizard.pro_support_button.label"}}</a>
|
||||||
|
</div>
|
||||||
{{/admin-nav}}
|
{{/admin-nav}}
|
||||||
|
|
||||||
<div class="admin-container">
|
<div class="admin-container">
|
||||||
|
|
|
@ -4,20 +4,35 @@
|
||||||
|
|
||||||
{{#if isTextArea}}
|
{{#if isTextArea}}
|
||||||
<div class="submission-long-text">
|
<div class="submission-long-text">
|
||||||
<p class="submission-long-text-content {{textState}}">{{value.value}}</p>
|
<p class="submission-long-text-content {{textState}}">
|
||||||
<a href {{action "expandText"}}>{{toggleText}}</a>
|
{{value.value}}
|
||||||
|
</p>
|
||||||
|
<a href {{action "expandText"}}>
|
||||||
|
{{toggleText}}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isComposer}}
|
{{#if isComposer}}
|
||||||
<div class="submission-long-text">
|
<div class="submission-long-text">
|
||||||
<p class="submission-composer-text submission-long-text-content {{textState}}">{{value.value}}</p>
|
<p
|
||||||
<a href {{action "expandText"}}>{{toggleText}}</a>
|
class="submission-composer-text submission-long-text-content {{
|
||||||
|
textState
|
||||||
|
}}"
|
||||||
|
>
|
||||||
|
{{value.value}}
|
||||||
|
</p>
|
||||||
|
<a href {{action "expandText"}}>
|
||||||
|
{{toggleText}}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isComposerPreview}}
|
{{#if isComposerPreview}}
|
||||||
{{d-icon "comment-alt" }} <span class="submission-composer-text">{{i18n "admin.wizard.submissions.composer_preview"}}: {{value.value}}</span>
|
{{d-icon "comment-alt"}}
|
||||||
|
<span class="submission-composer-text">
|
||||||
|
{{i18n "admin.wizard.submissions.composer_preview"}}: {{value.value}}
|
||||||
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isTextOnly}}
|
{{#if isTextOnly}}
|
||||||
|
@ -48,35 +63,41 @@
|
||||||
|
|
||||||
{{#if isCheckbox}}
|
{{#if isCheckbox}}
|
||||||
{{#if checkboxValue}}
|
{{#if checkboxValue}}
|
||||||
<span class="submission-icon-item submission-checkbox-true">
|
<span class="submission-icon-item submission-checkbox-true">
|
||||||
{{d-icon "check"}}{{value.value}}
|
{{d-icon "check"}}{{value.value}}
|
||||||
</span>
|
</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
<span class="submission-icon-item submission-checkbox-false">
|
<span class="submission-icon-item submission-checkbox-false">
|
||||||
{{d-icon "times"}}{{value.value}}
|
{{d-icon "times"}}{{value.value}}
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isUrl}}
|
{{#if isUrl}}
|
||||||
<span class="submission-icon-item submission-url">
|
<span class="submission-icon-item submission-url">
|
||||||
{{ d-icon "link" }}
|
{{d-icon "link"}}
|
||||||
<a target="_blank" href={{value.value}}>
|
<a target="_blank" rel="noopener noreferrer" href={{value.value}}>
|
||||||
{{value.value}}
|
{{value.value}}
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isUpload}}
|
{{#if isUpload}}
|
||||||
<a target="_blank" class="attachment" href={{file.url}} download>
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="attachment"
|
||||||
|
href={{file.url}}
|
||||||
|
download
|
||||||
|
>
|
||||||
{{file.original_filename}}
|
{{file.original_filename}}
|
||||||
</a>
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isDropdown}}
|
{{#if isDropdown}}
|
||||||
<span class="submission-icon-item">
|
<span class="submission-icon-item">
|
||||||
{{ d-icon "check-square" }}
|
{{d-icon "check-square"}}
|
||||||
{{ value.value }}
|
{{value.value}}
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
@ -87,28 +108,56 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isCategory}}
|
{{#if isCategory}}
|
||||||
<strong>{{i18n "admin.wizard.submissions.category_id"}}: </strong><a target="_blank" href={{categoryUrl}} title={{value.value}}>{{value.value}}</a>
|
<strong>
|
||||||
|
{{i18n "admin.wizard.submissions.category_id"}}:
|
||||||
|
</strong>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={{categoryUrl}}
|
||||||
|
title={{value.value}}
|
||||||
|
>
|
||||||
|
{{value.value}}
|
||||||
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isGroup}}
|
{{#if isGroup}}
|
||||||
<strong>{{i18n "admin.wizard.submissions.group_id"}}: </strong> {{ value.value }}
|
<strong>
|
||||||
|
{{i18n "admin.wizard.submissions.group_id"}}:
|
||||||
|
</strong>
|
||||||
|
{{value.value}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
||||||
{{#if isUserSelector}}
|
{{#if isUserSelector}}
|
||||||
{{#each submittedUsers as |user|}}
|
{{#each submittedUsers as |user|}}
|
||||||
{{ d-icon "user" }}
|
{{d-icon "user"}}
|
||||||
<a target="_blank" href={{user.url}} title={{user.username}}>{{user.username}}</a>
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={{user.url}}
|
||||||
|
title={{user.username}}
|
||||||
|
>
|
||||||
|
{{user.username}}
|
||||||
|
</a>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isUser}}
|
{{#if isUser}}
|
||||||
{{#link-to "user" value}}{{avatar value imageSize="tiny"}}{{/link-to}}
|
{{#link-to "user" value}}
|
||||||
<a target="_blank" href={{userProfileUrl}} title={{value.name}}>{{value.username}}</a>
|
{{avatar value imageSize="tiny"}}
|
||||||
|
{{/link-to}}
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={{userProfileUrl}}
|
||||||
|
title={{value.name}}
|
||||||
|
>
|
||||||
|
{{value.username}}
|
||||||
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if isSubmittedAt}}
|
{{#if isSubmittedAt}}
|
||||||
<span class="submission-date" title={{value.value}}>
|
<span class="submission-date" title={{value.value}}>
|
||||||
{{d-icon "clock"}}{{format-date value format="tiny"}}
|
{{d-icon "clock"}}{{format-date value format="tiny"}}
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
|
@ -2,10 +2,16 @@
|
||||||
|
|
||||||
<div class="link-list">
|
<div class="link-list">
|
||||||
{{#if anyLinks}}
|
{{#if anyLinks}}
|
||||||
{{#each links as |l|}}
|
{{#each links as |link|}}
|
||||||
<div data-id={{l.id}}>
|
<div data-id={{link.id}}>
|
||||||
{{d-button action="change" actionParam=l.id translatedLabel=l.label class=l.classes}}
|
{{d-button action="change" actionParam=link.id translatedLabel=link.label class=link.classes}}
|
||||||
{{d-button action="remove" actionParam=l.id icon="times" class="remove"}}
|
{{#unless link.first}}
|
||||||
|
{{d-button action="back" actionParam=link icon="arrow-left" class="back"}}
|
||||||
|
{{/unless}}
|
||||||
|
{{#unless link.last}}
|
||||||
|
{{d-button action="forward" actionParam=link icon="arrow-right" class="forward"}}
|
||||||
|
{{/unless}}
|
||||||
|
{{d-button action="remove" actionParam=link.id icon="times" class="remove"}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -29,4 +29,4 @@
|
||||||
label="directory.edit_columns.reset_to_default"
|
label="directory.edit_columns.reset_to_default"
|
||||||
action=(action "resetToDefault")
|
action=(action "resetToDefault")
|
||||||
}}
|
}}
|
||||||
</div>
|
</div>
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
//= require discourse/app/mixins/singleton
|
//= require discourse/app/mixins/singleton
|
||||||
//= require discourse/app/mixins/upload
|
//= require discourse/app/mixins/upload
|
||||||
|
//= require discourse/app/mixins/composer-upload
|
||||||
|
|
||||||
//= require discourse/app/adapters/rest
|
//= require discourse/app/adapters/rest
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
@import "wizard-manager";
|
@import "wizard-manager";
|
||||||
@import "wizard-api";
|
@import "wizard-api";
|
||||||
@import "common/components/buttons";
|
@import "common/components/buttons";
|
||||||
|
@import "wizard-variables";
|
||||||
|
|
||||||
.admin-wizard-controls {
|
.admin-wizard-controls {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -766,3 +767,21 @@
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn.btn-pavilion-pro {
|
||||||
|
background: var(--pavilion-primary);
|
||||||
|
color: var(--pavilion-secondary);
|
||||||
|
|
||||||
|
.d-icon {
|
||||||
|
color: var(--pavilion-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background: darken($pavilionPrimary, 5%);
|
||||||
|
|
||||||
|
&[href],
|
||||||
|
svg.d-icon {
|
||||||
|
color: darken($pavilionSecondary, 10%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
7
assets/stylesheets/common/wizard-variables.scss
Normale Datei
7
assets/stylesheets/common/wizard-variables.scss
Normale Datei
|
@ -0,0 +1,7 @@
|
||||||
|
$pavilionPrimary: #3c1c8c;
|
||||||
|
$pavilionSecondary: #ffffff;
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--pavilion-primary: #3c1c8c;
|
||||||
|
--pavilion-secondary: #ffffff;
|
||||||
|
}
|
|
@ -58,6 +58,9 @@ en:
|
||||||
select_type: "Select a type"
|
select_type: "Select a type"
|
||||||
condition: "Condition"
|
condition: "Condition"
|
||||||
index: "Index"
|
index: "Index"
|
||||||
|
pro_support_button:
|
||||||
|
title: "Request Pro Support"
|
||||||
|
label: "Pro Support"
|
||||||
|
|
||||||
message:
|
message:
|
||||||
wizard:
|
wizard:
|
||||||
|
|
|
@ -68,7 +68,8 @@ class CustomWizard::WizardController < ::ApplicationController
|
||||||
result.merge!(redirect_to: submission.redirect_to)
|
result.merge!(redirect_to: submission.redirect_to)
|
||||||
end
|
end
|
||||||
|
|
||||||
wizard.final_cleanup!
|
submission.remove if submission.present?
|
||||||
|
wizard.reset
|
||||||
end
|
end
|
||||||
|
|
||||||
render json: result
|
render json: result
|
||||||
|
|
|
@ -392,7 +392,7 @@ class CustomWizard::Action
|
||||||
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
|
||||||
|
|
||||||
GroupActionLogger.new(user, group, skip_guardian: true).log_change_group_settings
|
GroupActionLogger.new(user, group).log_change_group_settings
|
||||||
log_success("Group created", group.name)
|
log_success("Group created", group.name)
|
||||||
|
|
||||||
result.output = group.name
|
result.output = group.name
|
||||||
|
|
|
@ -75,6 +75,7 @@ class CustomWizard::Builder
|
||||||
end
|
end
|
||||||
|
|
||||||
@wizard.update!
|
@wizard.update!
|
||||||
|
CustomWizard::Submission.cleanup_incomplete_submissions(@wizard)
|
||||||
@wizard
|
@wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ class CustomWizard::Submission
|
||||||
|
|
||||||
PAGE_LIMIT = 50
|
PAGE_LIMIT = 50
|
||||||
KEY ||= "submissions"
|
KEY ||= "submissions"
|
||||||
META ||= %w(submitted_at route_to redirect_on_complete redirect_to)
|
META ||= %w(updated_at submitted_at route_to redirect_on_complete redirect_to)
|
||||||
|
|
||||||
attr_reader :id,
|
attr_reader :id,
|
||||||
:user,
|
:user,
|
||||||
|
@ -46,6 +46,7 @@ class CustomWizard::Submission
|
||||||
|
|
||||||
submission_list = self.class.list(wizard, user_id: user.id)
|
submission_list = self.class.list(wizard, user_id: user.id)
|
||||||
submissions = submission_list.submissions.select { |submission| submission.id != self.id }
|
submissions = submission_list.submissions.select { |submission| submission.id != self.id }
|
||||||
|
self.updated_at = Time.now.iso8601
|
||||||
submissions.push(self)
|
submissions.push(self)
|
||||||
|
|
||||||
submission_data = submissions.map { |submission| data_to_save(submission) }
|
submission_data = submissions.map { |submission| data_to_save(submission) }
|
||||||
|
@ -97,7 +98,41 @@ class CustomWizard::Submission
|
||||||
new(wizard, data, user_id)
|
new(wizard, data, user_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.list(wizard, user_id: nil, page: nil)
|
def remove
|
||||||
|
if present?
|
||||||
|
user_id = @user.id
|
||||||
|
wizard_id = @wizard.id
|
||||||
|
submission_id = @id
|
||||||
|
data = PluginStore.get("#{wizard_id}_#{KEY}", user_id)
|
||||||
|
data.delete_if { |sub| sub["id"] == submission_id }
|
||||||
|
PluginStore.set("#{wizard_id}_#{KEY}", user_id, data)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.cleanup_incomplete_submissions(wizard)
|
||||||
|
user_id = wizard.user.id
|
||||||
|
all_submissions = list(wizard, user_id: user_id)
|
||||||
|
sorted_submissions = all_submissions.submissions.sort_by do |submission|
|
||||||
|
zero_epoch_time = DateTime.strptime("0", '%s')
|
||||||
|
[
|
||||||
|
submission.submitted_at ? Time.iso8601(submission.submitted_at) : zero_epoch_time,
|
||||||
|
submission.updated_at ? Time.iso8601(submission.updated_at) : zero_epoch_time
|
||||||
|
]
|
||||||
|
end.reverse
|
||||||
|
|
||||||
|
has_incomplete = false
|
||||||
|
valid_submissions = sorted_submissions.select do |submission|
|
||||||
|
to_be_included = submission.submitted_at || !has_incomplete
|
||||||
|
has_incomplete = true if !submission.submitted_at
|
||||||
|
|
||||||
|
to_be_included
|
||||||
|
end
|
||||||
|
|
||||||
|
valid_data = valid_submissions.map { |submission| submission.data_to_save(submission) }
|
||||||
|
PluginStore.set("#{wizard.id}_#{KEY}", user_id, valid_data)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.list(wizard, user_id: nil, order_by: nil, page: nil)
|
||||||
params = { plugin_name: "#{wizard.id}_#{KEY}" }
|
params = { plugin_name: "#{wizard.id}_#{KEY}" }
|
||||||
params[:key] = user_id if user_id.present?
|
params[:key] = user_id if user_id.present?
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,14 @@ class ::CustomWizard::UpdateValidator
|
||||||
@updater.errors.add(field_id, I18n.t('wizard.field.required', label: label))
|
@updater.errors.add(field_id, I18n.t('wizard.field.required', label: label))
|
||||||
end
|
end
|
||||||
|
|
||||||
if min_length.present? && value.is_a?(String) && value.strip.length < min_length.to_i
|
if value.is_a?(String) && (stripped_length = value.strip.length) > 0
|
||||||
@updater.errors.add(field_id, I18n.t('wizard.field.too_short', label: label, min: min_length.to_i))
|
if min_length.present? && stripped_length < min_length.to_i
|
||||||
end
|
@updater.errors.add(field_id, I18n.t('wizard.field.too_short', label: label, min: min_length.to_i))
|
||||||
|
end
|
||||||
|
|
||||||
if max_length.present? && value.is_a?(String) && value.strip.length > max_length.to_i
|
if max_length.present? && stripped_length > max_length.to_i
|
||||||
@updater.errors.add(field_id, I18n.t('wizard.field.too_long', label: label, max: max_length.to_i))
|
@updater.errors.add(field_id, I18n.t('wizard.field.too_long', label: label, max: max_length.to_i))
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if is_url_type(field) && value.present? && !check_if_url(value)
|
if is_url_type(field) && value.present? && !check_if_url(value)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
# name: discourse-custom-wizard
|
# name: discourse-custom-wizard
|
||||||
# about: Create custom wizards
|
# about: Create custom wizards
|
||||||
# version: 0.8.0
|
# version: 0.8.1
|
||||||
# authors: Angus McLeod
|
# authors: Angus McLeod
|
||||||
# url: https://github.com/paviliondev/discourse-custom-wizard
|
# url: https://github.com/paviliondev/discourse-custom-wizard
|
||||||
# contact emails: angus@thepavilion.io
|
# contact emails: angus@thepavilion.io
|
||||||
|
@ -40,6 +40,8 @@ if respond_to?(:register_svg_icon)
|
||||||
register_svg_icon "clock"
|
register_svg_icon "clock"
|
||||||
register_svg_icon "link"
|
register_svg_icon "link"
|
||||||
register_svg_icon "comment-alt"
|
register_svg_icon "comment-alt"
|
||||||
|
register_svg_icon "far-life-ring"
|
||||||
|
register_svg_icon "arrow-right"
|
||||||
end
|
end
|
||||||
|
|
||||||
class ::Sprockets::DirectiveProcessor
|
class ::Sprockets::DirectiveProcessor
|
||||||
|
|
|
@ -13,38 +13,89 @@ describe CustomWizard::Submission do
|
||||||
|
|
||||||
before do
|
before do
|
||||||
CustomWizard::Template.save(template_json, skip_jobs: true)
|
CustomWizard::Template.save(template_json, skip_jobs: true)
|
||||||
|
|
||||||
template_json_2 = template_json.dup
|
|
||||||
template_json_2["id"] = "super_mega_fun_wizard_2"
|
|
||||||
CustomWizard::Template.save(template_json_2, skip_jobs: true)
|
|
||||||
|
|
||||||
@wizard = CustomWizard::Wizard.create(template_json["id"], user)
|
@wizard = CustomWizard::Wizard.create(template_json["id"], user)
|
||||||
@wizard2 = CustomWizard::Wizard.create(template_json["id"], user2)
|
described_class.new(@wizard, step_1_field_1: "I am user submission").save
|
||||||
@wizard3 = CustomWizard::Wizard.create(template_json_2["id"], user)
|
|
||||||
@count = CustomWizard::Submission::PAGE_LIMIT + 20
|
|
||||||
|
|
||||||
@count.times do |index|
|
|
||||||
described_class.new(@wizard, step_1_field_1: "I am user submission #{index + 1}").save
|
|
||||||
end
|
|
||||||
described_class.new(@wizard2, step_1_field_1: "I am another user's submission").save
|
|
||||||
described_class.new(@wizard3, step_1_field_1: "I am a user submission on another wizard").save
|
|
||||||
end
|
end
|
||||||
|
|
||||||
it "saves a user's submission" do
|
it "saves a user's submission" do
|
||||||
expect(
|
expect(
|
||||||
described_class.get(@wizard, user.id).fields["step_1_field_1"]
|
described_class.get(@wizard, user.id).fields["step_1_field_1"]
|
||||||
).to eq("I am user submission #{@count}")
|
).to eq("I am user submission")
|
||||||
end
|
end
|
||||||
|
|
||||||
it "list submissions by wizard" do
|
context "#list" do
|
||||||
expect(described_class.list(@wizard).total).to eq(@count + 1)
|
before do
|
||||||
|
template_json_2 = template_json.dup
|
||||||
|
template_json_2["id"] = "super_mega_fun_wizard_2"
|
||||||
|
CustomWizard::Template.save(template_json_2, skip_jobs: true)
|
||||||
|
|
||||||
|
@wizard2 = CustomWizard::Wizard.create(template_json["id"], user2)
|
||||||
|
@wizard3 = CustomWizard::Wizard.create(template_json_2["id"], user)
|
||||||
|
@count = CustomWizard::Submission::PAGE_LIMIT + 20
|
||||||
|
|
||||||
|
@count.times do |index|
|
||||||
|
described_class.new(@wizard, step_1_field_1: "I am user submission #{index + 1}").save
|
||||||
|
end
|
||||||
|
described_class.new(@wizard2, step_1_field_1: "I am another user's submission").save
|
||||||
|
described_class.new(@wizard3, step_1_field_1: "I am a user submission on another wizard").save
|
||||||
|
end
|
||||||
|
|
||||||
|
it "list submissions by wizard" do
|
||||||
|
expect(described_class.list(@wizard).total).to eq(@count + 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "list submissions by wizard and user" do
|
||||||
|
expect(described_class.list(@wizard, user_id: user.id).total).to eq(@count + 1)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "paginates submission lists" do
|
||||||
|
expect(described_class.list(@wizard, page: 1).submissions.size).to eq((@count + 2) - CustomWizard::Submission::PAGE_LIMIT)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it "list submissions by wizard and user" do
|
context "#cleanup_incomplete_submissions" do
|
||||||
expect(described_class.list(@wizard, user_id: user.id).total).to eq(@count)
|
it "cleans up redundant incomplete submissions on each build" do
|
||||||
end
|
freeze_time Time.now + 1
|
||||||
|
described_class.new(@wizard, step_1_field_1: "I am the second submission").save
|
||||||
|
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)
|
||||||
|
builder.build
|
||||||
|
submissions = described_class.list(@wizard, user_id: @wizard.user.id).submissions
|
||||||
|
|
||||||
it "paginates submission lists" do
|
expect(submissions.length).to eq(1)
|
||||||
expect(described_class.list(@wizard, page: 1).submissions.size).to eq((@count + 1) - CustomWizard::Submission::PAGE_LIMIT)
|
expect(submissions.first.fields["step_1_field_1"]).to eq("I am the second submission")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "handles submissions without 'updated_at' field correctly" do
|
||||||
|
described_class.new(@wizard, step_1_field_1: "I am the second submission").save
|
||||||
|
described_class.new(@wizard, step_1_field_1: "I am the third submission").save
|
||||||
|
sub_data = PluginStore.get("#{@wizard.id}_submissions", @wizard.user.id)
|
||||||
|
sub_data.each do |sub|
|
||||||
|
sub['updated_at'] = nil
|
||||||
|
end
|
||||||
|
PluginStore.set("#{@wizard.id}_submissions", @wizard.user.id, sub_data)
|
||||||
|
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)
|
||||||
|
builder.build
|
||||||
|
submissions = described_class.list(@wizard, user_id: @wizard.user.id).submissions
|
||||||
|
|
||||||
|
expect(submissions.length).to eq(1)
|
||||||
|
expect(submissions.first.fields["step_1_field_1"]).to eq("I am the third submission")
|
||||||
|
end
|
||||||
|
|
||||||
|
it "handles submissions with and without 'updated_at' field correctly" do
|
||||||
|
freeze_time Time.now + 1
|
||||||
|
described_class.new(@wizard, step_1_field_1: "I am the second submission").save
|
||||||
|
freeze_time Time.now + 2
|
||||||
|
described_class.new(@wizard, step_1_field_1: "I am the third submission").save
|
||||||
|
sub_data = PluginStore.get("#{@wizard.id}_submissions", @wizard.user.id)
|
||||||
|
sub_data[0]['updated_at'] = nil
|
||||||
|
PluginStore.set("#{@wizard.id}_submissions", @wizard.user.id, sub_data)
|
||||||
|
|
||||||
|
builder = CustomWizard::Builder.new(@wizard.id, @wizard.user)
|
||||||
|
builder.build
|
||||||
|
submissions = described_class.list(@wizard, user_id: @wizard.user.id).submissions
|
||||||
|
|
||||||
|
expect(submissions.length).to eq(1)
|
||||||
|
expect(submissions.first.fields["step_1_field_1"]).to eq("I am the third submission")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -97,6 +97,31 @@ describe CustomWizard::UpdateValidator do
|
||||||
).to eq(nil)
|
).to eq(nil)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "applies min length only if the input is non-empty" do
|
||||||
|
min_length = 3
|
||||||
|
|
||||||
|
@template[:steps][0][:fields][0][:min_length] = min_length
|
||||||
|
|
||||||
|
CustomWizard::Template.save(@template)
|
||||||
|
|
||||||
|
updater = perform_validation('step_1', step_1_field_1: '')
|
||||||
|
expect(
|
||||||
|
updater.errors.messages[:step_1_field_1].first
|
||||||
|
).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "applies max length only if the input is non-empty" do
|
||||||
|
max_length = 100
|
||||||
|
|
||||||
|
@template[:steps][0][:fields][0][:max_length] = max_length
|
||||||
|
|
||||||
|
CustomWizard::Template.save(@template)
|
||||||
|
updater = perform_validation('step_1', step_1_field_1: "")
|
||||||
|
expect(
|
||||||
|
updater.errors.messages[:step_1_field_1].first
|
||||||
|
).to eq(nil)
|
||||||
|
end
|
||||||
|
|
||||||
it 'standardises boolean entries' do
|
it 'standardises boolean entries' do
|
||||||
updater = perform_validation('step_2', step_2_field_5: 'false')
|
updater = perform_validation('step_2', step_2_field_5: 'false')
|
||||||
expect(updater.submission['step_2_field_5']).to eq(false)
|
expect(updater.submission['step_2_field_5']).to eq(false)
|
||||||
|
|
|
@ -11,4 +11,7 @@ if ENV['SIMPLECOV']
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
require 'oj'
|
||||||
|
Oj.default_options = Oj.default_options.merge(cache_str: -1)
|
||||||
|
|
||||||
require 'rails_helper'
|
require 'rails_helper'
|
||||||
|
|
|
@ -50,30 +50,55 @@ describe CustomWizard::WizardController do
|
||||||
expect(response.parsed_body["error"]).to eq("We couldn't find a wizard at that address.")
|
expect(response.parsed_body["error"]).to eq("We couldn't find a wizard at that address.")
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'skips a wizard if user is allowed to skip' do
|
context 'when user skips the wizard' do
|
||||||
put '/w/super-mega-fun-wizard/skip.json'
|
|
||||||
expect(response.status).to eq(200)
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'lets user skip if user cant access wizard' do
|
it 'skips a wizard if user is allowed to skip' do
|
||||||
@template["permitted"] = permitted_json["permitted"]
|
put '/w/super-mega-fun-wizard/skip.json'
|
||||||
CustomWizard::Template.save(@template, skip_jobs: true)
|
expect(response.status).to eq(200)
|
||||||
|
end
|
||||||
|
|
||||||
put '/w/super-mega-fun-wizard/skip.json'
|
it 'lets user skip if user cant access wizard' do
|
||||||
expect(response.status).to eq(200)
|
@template["permitted"] = permitted_json["permitted"]
|
||||||
end
|
CustomWizard::Template.save(@template, skip_jobs: true)
|
||||||
|
|
||||||
it 'returns a no skip message if user is not allowed to skip' do
|
put '/w/super-mega-fun-wizard/skip.json'
|
||||||
@template['required'] = 'true'
|
expect(response.status).to eq(200)
|
||||||
CustomWizard::Template.save(@template)
|
end
|
||||||
put '/w/super-mega-fun-wizard/skip.json'
|
|
||||||
expect(response.parsed_body['error']).to eq("Wizard can't be skipped")
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'skip response contains a redirect_to if in users submissions' do
|
it 'returns a no skip message if user is not allowed to skip' do
|
||||||
@wizard = CustomWizard::Wizard.create(@template["id"], user)
|
@template['required'] = 'true'
|
||||||
CustomWizard::Submission.new(@wizard, redirect_to: "/t/2").save
|
CustomWizard::Template.save(@template)
|
||||||
put '/w/super-mega-fun-wizard/skip.json'
|
put '/w/super-mega-fun-wizard/skip.json'
|
||||||
expect(response.parsed_body['redirect_to']).to eq('/t/2')
|
expect(response.parsed_body['error']).to eq("Wizard can't be skipped")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'skip response contains a redirect_to if in users submissions' do
|
||||||
|
@wizard = CustomWizard::Wizard.create(@template["id"], user)
|
||||||
|
CustomWizard::Submission.new(@wizard, redirect_to: "/t/2").save
|
||||||
|
put '/w/super-mega-fun-wizard/skip.json'
|
||||||
|
expect(response.parsed_body['redirect_to']).to eq('/t/2')
|
||||||
|
end
|
||||||
|
|
||||||
|
it "deletes the submission if user has filled up some data" do
|
||||||
|
@wizard = CustomWizard::Wizard.create(@template["id"], user)
|
||||||
|
CustomWizard::Submission.new(@wizard, step_1_field_1: "Hello World").save
|
||||||
|
current_submission = @wizard.current_submission
|
||||||
|
put '/w/super-mega-fun-wizard/skip.json'
|
||||||
|
submissions = CustomWizard::Submission.list(@wizard).submissions
|
||||||
|
|
||||||
|
expect(submissions.any? { |submission| submission.id == current_submission.id }).to eq(false)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "starts from the first step if user visits after skipping the wizard" do
|
||||||
|
put '/w/super-mega-fun-wizard/steps/step_1.json', params: {
|
||||||
|
fields: {
|
||||||
|
step_1_field_1: "Text input"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
put '/w/super-mega-fun-wizard/skip.json'
|
||||||
|
get '/w/super-mega-fun-wizard.json'
|
||||||
|
|
||||||
|
expect(response.parsed_body["start"]).to eq('step_1')
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Laden …
In neuem Issue referenzieren