1
0
Fork 0

Complete pro-feature functionality

Dieser Commit ist enthalten in:
angusmcleod 2021-09-03 16:46:32 +08:00
Ursprung 6b1e7568c1
Commit 6ef333a657
26 geänderte Dateien mit 329 neuen und 280 gelöschten Zeilen

Datei anzeigen

@ -1,13 +1,29 @@
import Component from "@ember/component"; import Component from "@ember/component";
import discourseComputed, { observes } from "discourse-common/utils/decorators"; import discourseComputed, { observes } from "discourse-common/utils/decorators";
import { alias, equal, or } from "@ember/object/computed"; import { alias, equal, or } from "@ember/object/computed";
import { computed } from "@ember/object";
import I18n from "I18n"; import I18n from "I18n";
const generateContent = function (array, type) { const klasses = ["topic", "post", "group", "category"];
return array.map((key) => ({ const types = ["string", "boolean", "integer", "json"];
const proTypes = {
klass: ["group", "category"],
type: ["json"]
}
const generateContent = function (array, type, proSubscribed = false) {
return array.reduce((result, key) => {
let proArr = proTypes[type];
let pro = proArr && proArr.includes(key);
if (!pro || proSubscribed) {
result.push({
id: key, id: key,
name: I18n.t(`admin.wizard.custom_field.${type}.${key}`), name: I18n.t(`admin.wizard.custom_field.${type}.${key}`),
})); pro
});
}
return result;
}, []);
}; };
export default Component.extend({ export default Component.extend({
@ -16,14 +32,12 @@ export default Component.extend({
postSerializers: ["post"], postSerializers: ["post"],
groupSerializers: ["basic_group"], groupSerializers: ["basic_group"],
categorySerializers: ["basic_category"], categorySerializers: ["basic_category"],
klassContent: generateContent( klassContent: computed("proSubscribed", function() {
["topic", "post", "group", "category"], return generateContent(klasses, "klass", this.proSubscribed);
"klass" }),
), typeContent: computed("proSubscribed", function() {
typeContent: generateContent( return generateContent(types, "type", this.proSubscribed);
["string", "boolean", "integer", "json"], }),
"type"
),
showInputs: or("field.new", "field.edit"), showInputs: or("field.new", "field.edit"),
classNames: ["custom-field-input"], classNames: ["custom-field-input"],
loading: or("saving", "destroying"), loading: or("saving", "destroying"),
@ -40,7 +54,7 @@ export default Component.extend({
const serializers = this.get(`${klass}Serializers`); const serializers = this.get(`${klass}Serializers`);
if (serializers) { if (serializers) {
return generateContent(serializers, "serializers"); return generateContent(serializers, "serializers", this.proSubscribed);
} else { } else {
return []; return [];
} }

Datei anzeigen

@ -1,21 +0,0 @@
import { default as discourseComputed } from "discourse-common/utils/decorators";
import Component from "@ember/component";
export default Component.extend({
classNames: "wizard-advanced-toggle",
@discourseComputed("showAdvanced")
toggleClass(showAdvanced) {
let classes = "btn";
if (showAdvanced) {
classes += " btn-primary";
}
return classes;
},
actions: {
toggleAdvanced() {
this.toggleProperty("showAdvanced");
},
},
});

Datei anzeigen

@ -1,8 +1,8 @@
import { default as discourseComputed } from "discourse-common/utils/decorators"; import { default as discourseComputed } from "discourse-common/utils/decorators";
import wizardSchema from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema";
import { and, empty, equal, or } from "@ember/object/computed"; import { and, empty, equal, or } from "@ember/object/computed";
import { notificationLevels, selectKitContent } from "../lib/wizard"; import { notificationLevels, selectKitContent } from "../lib/wizard";
import { computed } from "@ember/object"; import { computed } from "@ember/object";
import wizardSchema from "../lib/wizard-schema";
import UndoChanges from "../mixins/undo-changes"; import UndoChanges from "../mixins/undo-changes";
import Component from "@ember/component"; import Component from "@ember/component";
import I18n from "I18n"; import I18n from "I18n";
@ -25,8 +25,6 @@ export default Component.extend(UndoChanges, {
createGroup: equal("action.type", "create_group"), createGroup: equal("action.type", "create_group"),
apiEmpty: empty("action.api"), apiEmpty: empty("action.api"),
groupPropertyTypes: selectKitContent(["id", "name"]), groupPropertyTypes: selectKitContent(["id", "name"]),
hasAdvanced: or("hasCustomFields", "routeTo"),
showAdvanced: and("hasAdvanced", "action.type"),
hasCustomFields: or( hasCustomFields: or(
"basicTopicFields", "basicTopicFields",
"updateProfile", "updateProfile",
@ -36,12 +34,6 @@ export default Component.extend(UndoChanges, {
basicTopicFields: or("createTopic", "sendMessage", "openComposer"), basicTopicFields: or("createTopic", "sendMessage", "openComposer"),
publicTopicFields: or("createTopic", "openComposer"), publicTopicFields: or("createTopic", "openComposer"),
showPostAdvanced: or("createTopic", "sendMessage"), showPostAdvanced: or("createTopic", "sendMessage"),
actionTypes: Object.keys(wizardSchema.action.types).map((type) => {
return {
id: type,
name: I18n.t(`admin.wizard.action.${type}.label`),
};
}),
availableNotificationLevels: notificationLevels.map((type) => { availableNotificationLevels: notificationLevels.map((type) => {
return { return {
id: type, id: type,
@ -101,4 +93,19 @@ export default Component.extend(UndoChanges, {
} }
return apis.find((a) => a.name === api).endpoints; return apis.find((a) => a.name === api).endpoints;
}, },
@discourseComputed("proSubscribed")
actionTypes(proSubscribed) {
return Object.keys(wizardSchema.action.types).reduce((result, type) => {
let pro = wizardSchema.action.proTypes.includes(type);
if (proSubscribed || !pro) {
result.push({
id: type,
name: I18n.t(`admin.wizard.action.${type}.label`),
pro
});
}
return result;
}, []);
}
}); });

Datei anzeigen

@ -27,7 +27,6 @@ export default Component.extend(UndoChanges, {
isTextType: or("isText", "isTextarea", "isComposer"), isTextType: or("isText", "isTextarea", "isComposer"),
isComposerPreview: equal("field.type", "composer_preview"), isComposerPreview: equal("field.type", "composer_preview"),
categoryPropertyTypes: selectKitContent(["id", "slug"]), categoryPropertyTypes: selectKitContent(["id", "slug"]),
showAdvanced: alias("field.type"),
messageUrl: "https://thepavilion.io/t/2809", messageUrl: "https://thepavilion.io/t/2809",
@discourseComputed("field.type") @discourseComputed("field.type")

Datei anzeigen

@ -0,0 +1,19 @@
import SingleSelectComponent from "select-kit/components/single-select";
import { computed } from "@ember/object";
export default SingleSelectComponent.extend({
classNames: ["combo-box", 'wizard-pro-selector'],
selectKitOptions: {
autoFilterable: false,
filterable: false,
showFullTitle: true,
headerComponent: "wizard-pro-selector/wizard-pro-selector-header",
caretUpIcon: "caret-up",
caretDownIcon: "caret-down"
},
modifyComponentForRow() {
return "wizard-pro-selector/wizard-pro-selector-row";
}
});

Datei anzeigen

@ -0,0 +1,17 @@
import SingleSelectHeaderComponent from "select-kit/components/select-kit/single-select-header";
import { computed } from "@ember/object";
import { reads } from "@ember/object/computed";
export default SingleSelectHeaderComponent.extend({
classNames: ["combo-box-header", "wizard-pro-selector-header"],
caretUpIcon: reads("selectKit.options.caretUpIcon"),
caretDownIcon: reads("selectKit.options.caretDownIcon"),
caretIcon: computed(
"selectKit.isExpanded",
"caretUpIcon",
"caretDownIcon",
function () {
return this.selectKit.isExpanded ? this.caretUpIcon : this.caretDownIcon;
}
),
});

Datei anzeigen

@ -0,0 +1,3 @@
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
export default SelectKitRowComponent.extend();

Datei anzeigen

@ -77,7 +77,6 @@ export default Controller.extend({
wizard wizard
.save(opts) .save(opts)
.then((result) => { .then((result) => {
console.log(result)
if (result.wizard_id) { if (result.wizard_id) {
this.send("afterSave", result.wizard_id); this.send("afterSave", result.wizard_id);
} else if (result.errors) { } else if (result.errors) {
@ -119,10 +118,6 @@ export default Controller.extend({
controller.setup(); controller.setup();
}, },
toggleAdvanced() {
this.toggleProperty("wizard.showAdvanced");
},
copyUrl() { copyUrl() {
const $copyRange = $('<p id="copy-range"></p>'); const $copyRange = $('<p id="copy-range"></p>');
$copyRange.html(this.wizardUrl); $copyRange.html(this.wizardUrl);

Datei anzeigen

@ -97,11 +97,6 @@ function buildObjectArray(json, type) {
if (present(json)) { if (present(json)) {
json.forEach((objJson, objectIndex) => { json.forEach((objJson, objectIndex) => {
let object = buildObject(objJson, type, objectIndex); let object = buildObject(objJson, type, objectIndex);
if (hasAdvancedProperties(object, type)) {
object.set("showAdvanced", true);
}
array.pushObject(object); array.pushObject(object);
}); });
} }
@ -112,21 +107,11 @@ function buildObjectArray(json, type) {
function buildBasicProperties(json, type, props, objectIndex = null) { function buildBasicProperties(json, type, props, objectIndex = null) {
listProperties(type).forEach((p) => { listProperties(type).forEach((p) => {
props[p] = buildProperty(json, p, type, objectIndex); props[p] = buildProperty(json, p, type, objectIndex);
if (hasAdvancedProperties(json, type)) {
props.showAdvanced = true;
}
}); });
return props; return props;
} }
function hasAdvancedProperties(object, type) {
return Object.keys(object).some((p) => {
return wizardSchema[type].advanced.indexOf(p) > -1 && present(object[p]);
});
}
/// to be removed: necessary due to action array being moved from step to wizard /// to be removed: necessary due to action array being moved from step to wizard
function actionPatch(json) { function actionPatch(json) {
let actions = json.actions || []; let actions = json.actions || [];

Datei anzeigen

@ -18,7 +18,6 @@ const wizard = {
permitted: null, permitted: null,
}, },
mapped: ["permitted"], mapped: ["permitted"],
advanced: ["restart_on_revisit"],
required: ["id"], required: ["id"],
dependent: { dependent: {
after_time: "after_time_scheduled", after_time: "after_time_scheduled",
@ -50,7 +49,6 @@ const step = {
force_final: false, force_final: false,
}, },
mapped: ["required_data", "permitted_params", "condition", "index"], mapped: ["required_data", "permitted_params", "condition", "index"],
advanced: ["required_data", "permitted_params", "condition", "index"],
required: ["id"], required: ["id"],
dependent: {}, dependent: {},
objectArrays: { objectArrays: {
@ -68,6 +66,7 @@ const field = {
label: null, label: null,
image: null, image: null,
description: null, description: null,
property: null,
required: null, required: null,
key: null, key: null,
type: null, type: null,
@ -75,7 +74,6 @@ const field = {
}, },
types: {}, types: {},
mapped: ["prefill", "content", "condition", "index"], mapped: ["prefill", "content", "condition", "index"],
advanced: ["property", "key", "condition", "index"],
required: ["id", "type"], required: ["id", "type"],
dependent: {}, dependent: {},
objectArrays: {}, objectArrays: {},
@ -196,14 +194,14 @@ const action = {
"visibility_level", "visibility_level",
"members_visibility_level", "members_visibility_level",
], ],
advanced: [
"code",
"custom_fields",
"skip_redirect",
"suppress_notifications",
"required",
],
required: ["id", "type"], required: ["id", "type"],
proTypes: [
'send_message',
'create_category',
'create_group',
'watch_categories',
'send_to_api'
],
dependent: {}, dependent: {},
objectArrays: {}, objectArrays: {},
}; };

Datei anzeigen

@ -8,7 +8,12 @@ export default DiscourseRoute.extend({
}, },
setupController(controller, model) { setupController(controller, model) {
const customFields = A(model || []); const customFields = A(model.custom_fields || []);
controller.set("customFields", customFields); const proSubscribed = model.pro_subscribed;
controller.setProperties({
customFields,
proSubscribed
});
}, },
}); });

Datei anzeigen

@ -32,7 +32,8 @@
{{custom-field-input {{custom-field-input
field=field field=field
removeField=(action "removeField") removeField=(action "removeField")
saveField=(action "saveField")}} saveField=(action "saveField")
proSubscribed=proSubscribed}}
{{/each}} {{/each}}
</tbody> </tbody>
</table> </table>

Datei anzeigen

@ -126,11 +126,6 @@
</div> </div>
</div> </div>
{{wizard-advanced-toggle showAdvanced=wizard.showAdvanced}}
{{#if wizard.showAdvanced}}
<div class="advanced-settings">
<div class="setting"> <div class="setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.save_submissions"}}</label> <label>{{i18n "admin.wizard.save_submissions"}}</label>
@ -150,9 +145,6 @@
<span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span> <span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
</div> </div>
</div> </div>
</div>
{{/if}}
</div> </div>
{{wizard-links {{wizard-links
@ -183,7 +175,8 @@
wizard=wizard wizard=wizard
apis=apis apis=apis
removeAction="removeAction" removeAction="removeAction"
wizardFields=wizardFields}} wizardFields=wizardFields
proSubscribed=proSubscribed}}
{{/each}} {{/each}}
<div class="admin-wizard-buttons"> <div class="admin-wizard-buttons">

Datei anzeigen

@ -1,13 +1,13 @@
{{#if showInputs}} {{#if showInputs}}
<td> <td>
{{combo-box {{wizard-pro-selector
value=field.klass value=field.klass
content=klassContent content=klassContent
none="admin.wizard.custom_field.klass.select" none="admin.wizard.custom_field.klass.select"
onChange=(action (mut field.klass))}} onChange=(action (mut field.klass))}}
</td> </td>
<td> <td>
{{combo-box {{wizard-pro-selector
value=field.type value=field.type
content=typeContent content=typeContent
none="admin.wizard.custom_field.type.select" none="admin.wizard.custom_field.type.select"

Datei anzeigen

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

Datei anzeigen

@ -12,13 +12,14 @@
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{combo-box {{wizard-pro-selector
value=action.type value=action.type
content=actionTypes content=actionTypes
onChange=(action "changeType") onChange=(action "changeType")
options=(hash options=(hash
none="admin.wizard.select_type" none="admin.wizard.select_type"
)}} )
}}
</div> </div>
</div> </div>
@ -714,12 +715,6 @@
</div> </div>
{{/if}} {{/if}}
{{#if showAdvanced}}
{{wizard-advanced-toggle showAdvanced=action.showAdvanced}}
{{#if action.showAdvanced}}
<div class="advanced-settings">
{{#if hasCustomFields}} {{#if hasCustomFields}}
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
@ -807,6 +802,3 @@
</div> </div>
</div> </div>
{{/if}} {{/if}}
</div>
{{/if}}
{{/if}}

Datei anzeigen

@ -258,11 +258,10 @@
<label>{{i18n "admin.wizard.translation"}}</label> <label>{{i18n "admin.wizard.translation"}}</label>
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span> <span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
</div> </div>
<div class="setting-value medium"> <div class="setting-value">
{{input {{input
name="key" name="key"
value=field.key value=field.key
class="medium"
placeholderKey="admin.wizard.translation_placeholder"}} placeholderKey="admin.wizard.translation_placeholder"}}
</div> </div>
</div> </div>

Datei anzeigen

@ -55,16 +55,11 @@
<span>{{i18n "admin.wizard.step.force_final.description"}}</span> <span>{{i18n "admin.wizard.step.force_final.description"}}</span>
</div> </div>
</div> </div>
{{/if}}
{{wizard-advanced-toggle showAdvanced=step.showAdvanced}} <div class="setting full field-mapper-setting pro">
{{#if step.showAdvanced}}
<div class="advanced-settings">
<div class="setting full field-mapper-setting">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.step.required_data.label"}}</label> <label>{{i18n "admin.wizard.step.required_data.label"}}</label>
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
@ -88,9 +83,10 @@
</div> </div>
</div> </div>
<div class="setting full field-mapper-setting"> <div class="setting full field-mapper-setting pro">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.step.permitted_params.label"}}</label> <label>{{i18n "admin.wizard.step.permitted_params.label"}}</label>
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{wizard-mapper {{wizard-mapper
@ -105,9 +101,10 @@
</div> </div>
</div> </div>
<div class="setting"> <div class="setting pro">
<div class="setting-label"> <div class="setting-label">
<label>{{i18n "admin.wizard.translation"}}</label> <label>{{i18n "admin.wizard.translation"}}</label>
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
</div> </div>
<div class="setting-value"> <div class="setting-value">
{{input {{input
@ -116,7 +113,6 @@
placeholderKey="admin.wizard.translation_placeholder"}} placeholderKey="admin.wizard.translation_placeholder"}}
</div> </div>
</div> </div>
</div>
{{/if}} {{/if}}
{{wizard-links {{wizard-links

Datei anzeigen

@ -0,0 +1,15 @@
<div class="select-kit-header-wrapper">
{{component selectKit.options.selectedNameComponent
tabindex=tabindex
item=selectedContent
selectKit=selectKit
shouldDisplayClearableButton=shouldDisplayClearableButton
}}
{{#if selectedContent.pro}}
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
{{/if}}
{{d-icon caretIcon class="caret-icon"}}
</div>

Datei anzeigen

@ -0,0 +1,15 @@
{{#if icons}}
<div class="icons">
<span class="selection-indicator"></span>
{{#each icons as |icon|}}
{{d-icon icon translatedtitle=(dasherize title)}}
{{/each}}
</div>
{{/if}}
<div class="texts">
<span class="name">{{html-safe label}}</span>
{{#if item.pro}}
<span class="pro-label">{{i18n "admin.wizard.pro.label"}}</span>
{{/if}}
</div>

Datei anzeigen

@ -243,7 +243,7 @@
font-size: 0.85em; font-size: 0.85em;
} }
span { > span {
font-size: 0.929em; font-size: 0.929em;
} }
@ -382,11 +382,6 @@
margin: 0; margin: 0;
} }
} }
.pro-label {
color: $tertiary;
font-size: .75em;
}
} }
} }
@ -764,6 +759,11 @@
vertical-align: middle; vertical-align: middle;
} }
.pro-label {
color: var(--tertiary);
font-size: .75em;
}
.admin-wizards-pro { .admin-wizards-pro {
.admin-wizard-controls { .admin-wizard-controls {
h3, label { h3, label {
@ -773,8 +773,8 @@
label { label {
padding: .4em .5em; padding: .4em .5em;
margin-left: .75em; margin-left: .75em;
background-color: $success; background-color: var(--success);
color: $secondary; color: var(--secondary);
} }
.buttons { .buttons {
@ -807,17 +807,29 @@
display: flex; display: flex;
align-items: center; align-items: center;
padding: 1em; padding: 1em;
background-color: $primary-very-low; background-color: var(--primary-very-low);
.subscription-state { .subscription-state {
padding: .25em .5em; padding: .25em .5em;
margin-right: .75em; margin-right: .75em;
&.active { &.active {
background-color: $success; background-color: var(--success);
color: $secondary; color: var(--secondary);
} }
} }
} }
} }
} }
.wizard-pro-selector.select-kit.single-select {
.select-kit-row .texts {
display: flex;
align-items: center;
}
.pro-label {
margin-left: .75em;
padding-top: .25em;
}
}

Datei anzeigen

@ -179,9 +179,9 @@ en:
min_length_placeholder: "Minimum length in characters" min_length_placeholder: "Minimum length in characters"
max_length: "Max Length" max_length: "Max Length"
max_length_placeholder: "Maximum length in characters" max_length_placeholder: "Maximum length in characters"
char_counter: "Character Counter" char_counter: "Counter"
char_counter_placeholder: "Display Character Counter" char_counter_placeholder: "Display Character Counter"
field_placeholder: "Field Placeholder" field_placeholder: "Placeholder"
file_types: "File Types" file_types: "File Types"
preview_template: "Preview Template" preview_template: "Preview Template"
limit: "Limit" limit: "Limit"

Datei anzeigen

@ -1,7 +1,10 @@
# frozen_string_literal: true # frozen_string_literal: true
class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController class CustomWizard::AdminCustomFieldsController < CustomWizard::AdminController
def index def index
render_json_dump(custom_field_list) render_json_dump(
custom_fields: custom_field_list,
pro_subscribed: CustomWizard::Pro.subscribed?
)
end end
def update def update

Datei anzeigen

@ -17,7 +17,9 @@ class ::CustomWizard::CustomField
category: ["basic_category"], category: ["basic_category"],
post: ["post"] post: ["post"]
} }
PRO_CLASSES ||= ['category', 'group']
TYPES ||= ["string", "boolean", "integer", "json"] TYPES ||= ["string", "boolean", "integer", "json"]
PRO_TYPES ||= ["json"]
LIST_CACHE_KEY ||= 'custom_field_list' LIST_CACHE_KEY ||= 'custom_field_list'
def self.serializers def self.serializers
@ -83,6 +85,10 @@ class ::CustomWizard::CustomField
next next
end end
if attr == 'klass' && PRO_CLASSES.include?(value) && !@pro.subscribed?
add_error(I18n.t("wizard.custom_field.error.pro_type", type: value))
end
if attr == 'serializers' && (unsupported = value - CLASSES[klass.to_sym]).length > 0 if attr == 'serializers' && (unsupported = value - CLASSES[klass.to_sym]).length > 0
add_error(I18n.t("#{i18n_key}.unsupported_serializers", add_error(I18n.t("#{i18n_key}.unsupported_serializers",
class: klass, class: klass,
@ -94,7 +100,7 @@ class ::CustomWizard::CustomField
add_error(I18n.t("#{i18n_key}.unsupported_type", type: value)) add_error(I18n.t("#{i18n_key}.unsupported_type", type: value))
end end
if attr == 'type' && value == 'json' && !@pro.subscribed? if attr == 'type' && PRO_TYPES.include?(value) && !@pro.subscribed?
add_error(I18n.t("wizard.custom_field.error.pro_type", type: value)) add_error(I18n.t("wizard.custom_field.error.pro_type", type: value))
end end

Datei anzeigen

@ -16,7 +16,7 @@ class CustomWizard::Pro
end end
def subscribed? def subscribed?
@subscription.active? false #@subscription.active?
end end
def server def server

Datei anzeigen

@ -31,7 +31,7 @@ class CustomWizard::TemplateValidator
if data[:actions].present? if data[:actions].present?
data[:actions].each do |action| data[:actions].each do |action|
validate_pro_action(action) validate_pro(action, :action)
check_required(action, :action) check_required(action, :action)
end end
end end