Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-25 18:50:27 +01:00
Merge pull request #204 from paviliondev/pro-release
Custom Wizard 2.0
Dieser Commit ist enthalten in:
Commit
e38b54351f
166 geänderte Dateien mit 3791 neuen und 1938 gelöschten Zeilen
2
.github/workflows/plugin-tests.yml
gevendort
2
.github/workflows/plugin-tests.yml
gevendort
|
@ -8,7 +8,7 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: plugin-tests-${{ format('{0}-{1}', github.head_ref || github.run_number, github.job) }}
|
group: tests-${{ format('{0}-{1}', github.head_ref || github.run_number, github.job) }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
|
@ -1,2 +1,8 @@
|
||||||
inherit_gem:
|
inherit_gem:
|
||||||
rubocop-discourse: default.yml
|
rubocop-discourse: default.yml
|
||||||
|
|
||||||
|
RSpec/ContextWording:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
|
RSpec/DescribeClass:
|
||||||
|
Enabled: false
|
||||||
|
|
|
@ -3,6 +3,13 @@ class CustomWizard::AdminController < ::Admin::AdminController
|
||||||
before_action :ensure_admin
|
before_action :ensure_admin
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
subcription = CustomWizard::Subscription.new
|
||||||
|
render_json_dump(
|
||||||
|
subscribed: subcription.subscribed?,
|
||||||
|
subscription_type: subcription.type,
|
||||||
|
subscription_attributes: CustomWizard::Subscription.attributes,
|
||||||
|
subscription_client_installed: subcription.client_installed?
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
# 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
|
||||||
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update
|
def update
|
||||||
|
|
|
@ -1,9 +1,44 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class CustomWizard::AdminLogsController < CustomWizard::AdminController
|
class CustomWizard::AdminLogsController < CustomWizard::AdminController
|
||||||
|
before_action :find_wizard, except: [:index]
|
||||||
|
|
||||||
def index
|
def index
|
||||||
render_serialized(
|
render json: ActiveModel::ArraySerializer.new(
|
||||||
CustomWizard::Log.list(params[:page].to_i, params[:limit].to_i),
|
CustomWizard::Wizard.list(current_user),
|
||||||
CustomWizard::LogSerializer
|
each_serializer: CustomWizard::BasicWizardSerializer
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def show
|
||||||
|
render_json_dump(
|
||||||
|
wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false),
|
||||||
|
logs: ActiveModel::ArraySerializer.new(
|
||||||
|
log_list.logs,
|
||||||
|
each_serializer: CustomWizard::LogSerializer
|
||||||
|
),
|
||||||
|
total: log_list.total
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def log_list
|
||||||
|
@log_list ||= begin
|
||||||
|
list = CustomWizard::Log.list(params[:page].to_i, params[:limit].to_i, params[:wizard_id])
|
||||||
|
|
||||||
|
if list.logs.any? && (usernames = list.logs.map(&:username)).present?
|
||||||
|
user_map = User.where(username: usernames)
|
||||||
|
.reduce({}) do |result, user|
|
||||||
|
result[user.username] = user
|
||||||
|
result
|
||||||
|
end
|
||||||
|
|
||||||
|
list.logs.each do |log_item|
|
||||||
|
log_item.user = user_map[log_item.username]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
list
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,12 +13,16 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController
|
||||||
def show
|
def show
|
||||||
render_json_dump(
|
render_json_dump(
|
||||||
wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false),
|
wizard: CustomWizard::BasicWizardSerializer.new(@wizard, root: false),
|
||||||
submissions: ActiveModel::ArraySerializer.new(ordered_submissions, each_serializer: CustomWizard::SubmissionSerializer)
|
submissions: ActiveModel::ArraySerializer.new(
|
||||||
|
submission_list.submissions,
|
||||||
|
each_serializer: CustomWizard::SubmissionSerializer
|
||||||
|
),
|
||||||
|
total: submission_list.total
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
def download
|
def download
|
||||||
send_data ordered_submissions.to_json,
|
send_data submission_list.submissions.to_json,
|
||||||
filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json",
|
filename: "#{Discourse.current_hostname}-wizard-submissions-#{@wizard.name}.json",
|
||||||
content_type: "application/json",
|
content_type: "application/json",
|
||||||
disposition: "attachment"
|
disposition: "attachment"
|
||||||
|
@ -26,7 +30,7 @@ class CustomWizard::AdminSubmissionsController < CustomWizard::AdminController
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def ordered_submissions
|
def submission_list
|
||||||
CustomWizard::Submission.list(@wizard, order_by: 'id')
|
CustomWizard::Submission.list(@wizard, page: params[:page].to_i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class CustomWizard::LogSerializer < ApplicationSerializer
|
class CustomWizard::LogSerializer < ApplicationSerializer
|
||||||
attributes :message, :date
|
attributes :date,
|
||||||
|
:action,
|
||||||
|
:username,
|
||||||
|
:message
|
||||||
|
|
||||||
|
has_one :user, serializer: ::BasicUserSerializer, embed: :objects
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,16 +1,32 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
class CustomWizard::SubmissionSerializer < ApplicationSerializer
|
class CustomWizard::SubmissionSerializer < ApplicationSerializer
|
||||||
attributes :id,
|
attributes :id,
|
||||||
:username,
|
|
||||||
:fields,
|
:fields,
|
||||||
:submitted_at,
|
:submitted_at
|
||||||
:route_to,
|
|
||||||
:redirect_on_complete,
|
|
||||||
:redirect_to
|
|
||||||
|
|
||||||
def username
|
has_one :user, serializer: ::BasicUserSerializer, embed: :objects
|
||||||
object.user.present? ?
|
|
||||||
object.user.username :
|
def include_user?
|
||||||
I18n.t('admin.wizard.submission.no_user', user_id: object.user_id)
|
object.user.present?
|
||||||
|
end
|
||||||
|
|
||||||
|
def fields
|
||||||
|
@fields ||= begin
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
object.wizard.template['steps'].each do |step|
|
||||||
|
step['fields'].each do |field|
|
||||||
|
if value = object.fields[field['id']]
|
||||||
|
result[field['id']] = {
|
||||||
|
value: value,
|
||||||
|
type: field['type'],
|
||||||
|
label: field['label']
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
result
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -42,13 +42,8 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer
|
||||||
object.value
|
object.value
|
||||||
end
|
end
|
||||||
|
|
||||||
def i18n_key
|
|
||||||
@i18n_key ||= "wizard.step.#{object.step.id}.fields.#{object.id}".underscore
|
|
||||||
end
|
|
||||||
|
|
||||||
def label
|
def label
|
||||||
return object.label if object.label.present?
|
I18n.t("#{i18n_key}.label", default: object.label, base_url: Discourse.base_url)
|
||||||
I18n.t("#{object.key || i18n_key}.label", default: '')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def include_label?
|
def include_label?
|
||||||
|
@ -56,14 +51,21 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def description
|
def description
|
||||||
return object.description if object.description.present?
|
I18n.t("#{i18n_key}.description", default: object.description, base_url: Discourse.base_url)
|
||||||
I18n.t("#{object.key || i18n_key}.description", default: '', base_url: Discourse.base_url)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def include_description?
|
def include_description?
|
||||||
description.present?
|
description.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def placeholder
|
||||||
|
I18n.t("#{i18n_key}.placeholder", default: object.placeholder)
|
||||||
|
end
|
||||||
|
|
||||||
|
def include_placeholder?
|
||||||
|
placeholder.present?
|
||||||
|
end
|
||||||
|
|
||||||
def image
|
def image
|
||||||
object.image
|
object.image
|
||||||
end
|
end
|
||||||
|
@ -72,15 +74,6 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer
|
||||||
object.image.present?
|
object.image.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def placeholder
|
|
||||||
return object.placeholder if object.placeholder.present?
|
|
||||||
I18n.t("#{object.key || i18n_key}.placeholder", default: '')
|
|
||||||
end
|
|
||||||
|
|
||||||
def include_placeholder?
|
|
||||||
placeholder.present?
|
|
||||||
end
|
|
||||||
|
|
||||||
def file_types
|
def file_types
|
||||||
object.file_types
|
object.file_types
|
||||||
end
|
end
|
||||||
|
@ -127,4 +120,14 @@ class CustomWizard::FieldSerializer < ::ApplicationSerializer
|
||||||
def preview_template
|
def preview_template
|
||||||
object.preview_template
|
object.preview_template
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def i18n_key
|
||||||
|
@i18n_key ||= "#{object.step.wizard.id}.#{object.step.id}.#{object.id}".underscore
|
||||||
|
end
|
||||||
|
|
||||||
|
def subscribed?
|
||||||
|
@subscribed ||= CustomWizard::Subscription.subscribed?
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -39,13 +39,8 @@ class CustomWizard::StepSerializer < ::ApplicationSerializer
|
||||||
object.previous.present?
|
object.previous.present?
|
||||||
end
|
end
|
||||||
|
|
||||||
def i18n_key
|
|
||||||
@i18n_key ||= "wizard.step.#{object.id}".underscore
|
|
||||||
end
|
|
||||||
|
|
||||||
def title
|
def title
|
||||||
return PrettyText.cook(object.title) if object.title
|
I18n.t("#{i18n_key}.title", default: object.title, base_url: Discourse.base_url)
|
||||||
PrettyText.cook(I18n.t("#{object.key || i18n_key}.title", default: ''))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def include_title?
|
def include_title?
|
||||||
|
@ -53,8 +48,7 @@ class CustomWizard::StepSerializer < ::ApplicationSerializer
|
||||||
end
|
end
|
||||||
|
|
||||||
def description
|
def description
|
||||||
return object.description if object.description
|
I18n.t("#{i18n_key}.description", default: object.description, base_url: Discourse.base_url)
|
||||||
PrettyText.cook(I18n.t("#{object.key || i18n_key}.description", default: '', base_url: Discourse.base_url))
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def include_description?
|
def include_description?
|
||||||
|
@ -80,4 +74,10 @@ class CustomWizard::StepSerializer < ::ApplicationSerializer
|
||||||
def final
|
def final
|
||||||
object.final?
|
object.final?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def i18n_key
|
||||||
|
@i18n_key ||= "#{object.wizard.id}.#{object.id}".underscore
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
28
app/views/layouts/qunit.html.erb
Normale Datei
28
app/views/layouts/qunit.html.erb
Normale Datei
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Custom Wizard QUnit Test Runner</title>
|
||||||
|
<%= discourse_stylesheet_link_tag(:test_helper, theme_id: nil) %>
|
||||||
|
<%= discourse_stylesheet_link_tag :wizard, theme_id: nil %>
|
||||||
|
<%= discourse_stylesheet_link_tag :wizard_custom %>
|
||||||
|
<%= preload_script "locales/en" %>
|
||||||
|
<%= preload_script "ember_jquery" %>
|
||||||
|
<%= preload_script "wizard-vendor" %>
|
||||||
|
<%= preload_script "wizard-custom" %>
|
||||||
|
<%= preload_script "wizard-raw-templates" %>
|
||||||
|
<%= preload_script "wizard-plugin" %>
|
||||||
|
<%= preload_script "pretty-text-bundle" %>
|
||||||
|
<%= preload_script "wizard-qunit" %>
|
||||||
|
<%= csrf_meta_tags %>
|
||||||
|
|
||||||
|
<script src="<%= ExtraLocalesController.url("wizard") %>"></script>
|
||||||
|
|
||||||
|
<%= tag.meta id: 'data-discourse-setup', data: client_side_setup_data %>
|
||||||
|
<meta name="discourse_theme_id" content="">
|
||||||
|
<meta name="discourse-base-uri" content="<%= Discourse.base_path %>">
|
||||||
|
</head>
|
||||||
|
<body class="custom-wizard">
|
||||||
|
<div id="qunit"></div>
|
||||||
|
<div id="qunit-fixture"></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -3,27 +3,12 @@ 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 I18n from "I18n";
|
import I18n from "I18n";
|
||||||
|
|
||||||
const generateContent = function (array, type) {
|
|
||||||
return array.map((key) => ({
|
|
||||||
id: key,
|
|
||||||
name: I18n.t(`admin.wizard.custom_field.${type}.${key}`),
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
tagName: "tr",
|
tagName: "tr",
|
||||||
topicSerializers: ["topic_view", "topic_list_item"],
|
topicSerializers: ["topic_view", "topic_list_item"],
|
||||||
postSerializers: ["post"],
|
postSerializers: ["post"],
|
||||||
groupSerializers: ["basic_group"],
|
groupSerializers: ["basic_group"],
|
||||||
categorySerializers: ["basic_category"],
|
categorySerializers: ["basic_category"],
|
||||||
klassContent: generateContent(
|
|
||||||
["topic", "post", "group", "category"],
|
|
||||||
"klass"
|
|
||||||
),
|
|
||||||
typeContent: generateContent(
|
|
||||||
["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,9 +25,13 @@ 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 serializers.reduce((result, key) => {
|
||||||
} else {
|
result.push({
|
||||||
return [];
|
id: key,
|
||||||
|
name: I18n.t(`admin.wizard.custom_field.serializers.${key}`),
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}, []);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -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");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
||||||
import { and, empty, equal, or } from "@ember/object/computed";
|
import { subscriptionSelectKitContent } from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-subscription";
|
||||||
|
import { 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,
|
||||||
|
@ -102,6 +94,11 @@ export default Component.extend(UndoChanges, {
|
||||||
return apis.find((a) => a.name === api).endpoints;
|
return apis.find((a) => a.name === api).endpoints;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@discourseComputed
|
||||||
|
actionTypes() {
|
||||||
|
return subscriptionSelectKitContent("action", "types");
|
||||||
|
},
|
||||||
|
|
||||||
@discourseComputed("fieldTypes")
|
@discourseComputed("fieldTypes")
|
||||||
hasEventsField(fieldTypes) {
|
hasEventsField(fieldTypes) {
|
||||||
return fieldTypes.map((ft) => ft.id).includes("event");
|
return fieldTypes.map((ft) => ft.id).includes("event");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
||||||
import { alias, equal, or } from "@ember/object/computed";
|
import { equal, or } from "@ember/object/computed";
|
||||||
import { computed } from "@ember/object";
|
import { computed } from "@ember/object";
|
||||||
import { selectKitContent } from "../lib/wizard";
|
import { selectKitContent } from "../lib/wizard";
|
||||||
import UndoChanges from "../mixins/undo-changes";
|
import UndoChanges from "../mixins/undo-changes";
|
||||||
|
@ -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://discourse.pluginmanager.org/t/field-settings",
|
messageUrl: "https://discourse.pluginmanager.org/t/field-settings",
|
||||||
|
|
||||||
@discourseComputed("field.type")
|
@discourseComputed("field.type")
|
||||||
|
|
|
@ -6,6 +6,7 @@ import I18n from "I18n";
|
||||||
const icons = {
|
const icons = {
|
||||||
error: "times-circle",
|
error: "times-circle",
|
||||||
success: "check-circle",
|
success: "check-circle",
|
||||||
|
warn: "exclamation-circle",
|
||||||
info: "info-circle",
|
info: "info-circle",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,8 @@ import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
classNames: ["realtime-validations"],
|
classNames: ["realtime-validations", "setting", "full", "subscription"],
|
||||||
|
|
||||||
@discourseComputed
|
@discourseComputed
|
||||||
timeUnits() {
|
timeUnits() {
|
||||||
return ["days", "weeks", "months", "years"].map((unit) => {
|
return ["days", "weeks", "months", "years"].map((unit) => {
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
import Component from "@ember/component";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import Subscription from "../mixins/subscription";
|
||||||
|
import DiscourseURL from "discourse/lib/url";
|
||||||
|
import I18n from "I18n";
|
||||||
|
|
||||||
|
export default Component.extend(Subscription, {
|
||||||
|
tagName: "a",
|
||||||
|
classNameBindings: [":wizard-subscription-badge", "subscriptionType"],
|
||||||
|
attributeBindings: ["title"],
|
||||||
|
|
||||||
|
@discourseComputed("subscriptionType")
|
||||||
|
i18nKey(type) {
|
||||||
|
return `admin.wizard.subscription.type.${type ? type : "none"}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("i18nKey")
|
||||||
|
title(i18nKey) {
|
||||||
|
return I18n.t(`${i18nKey}.title`);
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("i18nKey")
|
||||||
|
label(i18nKey) {
|
||||||
|
return I18n.t(`${i18nKey}.label`);
|
||||||
|
},
|
||||||
|
|
||||||
|
click() {
|
||||||
|
DiscourseURL.routeTo(this.subscriptionLink);
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,26 @@
|
||||||
|
import Component from "@ember/component";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import Subscription from "../mixins/subscription";
|
||||||
|
|
||||||
|
export default Component.extend(Subscription, {
|
||||||
|
classNameBindings: [":wizard-subscription-container", "subscribed"],
|
||||||
|
|
||||||
|
@discourseComputed("subscribed")
|
||||||
|
subscribedIcon(subscribed) {
|
||||||
|
return subscribed ? "check" : "dash";
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("subscribed")
|
||||||
|
subscribedLabel(subscribed) {
|
||||||
|
return `admin.wizard.subscription.${
|
||||||
|
subscribed ? "subscribed" : "not_subscribed"
|
||||||
|
}.label`;
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("subscribed")
|
||||||
|
subscribedTitle(subscribed) {
|
||||||
|
return `admin.wizard.subscription.${
|
||||||
|
subscribed ? "subscribed" : "not_subscribed"
|
||||||
|
}.title`;
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,36 @@
|
||||||
|
import Component from "@ember/component";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import Subscription from "../mixins/subscription";
|
||||||
|
import I18n from "I18n";
|
||||||
|
|
||||||
|
export default Component.extend(Subscription, {
|
||||||
|
tagName: "a",
|
||||||
|
classNameBindings: [":btn", ":btn-pavilion-support", "subscriptionType"],
|
||||||
|
attributeBindings: ["title"],
|
||||||
|
|
||||||
|
@discourseComputed("subscribed")
|
||||||
|
i18nKey(subscribed) {
|
||||||
|
return `admin.wizard.subscription.cta.${
|
||||||
|
subscribed ? "subscribed" : "none"
|
||||||
|
}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("subscribed")
|
||||||
|
icon(subscribed) {
|
||||||
|
return subscribed ? "far-life-ring" : "external-link-alt";
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("i18nKey")
|
||||||
|
title(i18nKey) {
|
||||||
|
return I18n.t(`${i18nKey}.title`);
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("i18nKey")
|
||||||
|
label(i18nKey) {
|
||||||
|
return I18n.t(`${i18nKey}.label`);
|
||||||
|
},
|
||||||
|
|
||||||
|
click() {
|
||||||
|
window.open(this.subscriptionCtaLink, "_blank").focus();
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,96 @@
|
||||||
|
import SingleSelectComponent from "select-kit/components/single-select";
|
||||||
|
import Subscription from "../mixins/subscription";
|
||||||
|
import wizardSchema from "discourse/plugins/discourse-custom-wizard/discourse/lib/wizard-schema";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import I18n from "I18n";
|
||||||
|
|
||||||
|
const nameKey = function (feature, attribute, value) {
|
||||||
|
if (feature === "action") {
|
||||||
|
return `admin.wizard.action.${value}.label`;
|
||||||
|
} else {
|
||||||
|
return `admin.wizard.${feature}.${attribute}.${value}`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SingleSelectComponent.extend(Subscription, {
|
||||||
|
classNames: ["combo-box", "wizard-subscription-selector"],
|
||||||
|
|
||||||
|
selectKitOptions: {
|
||||||
|
autoFilterable: false,
|
||||||
|
filterable: false,
|
||||||
|
showFullTitle: true,
|
||||||
|
headerComponent:
|
||||||
|
"wizard-subscription-selector/wizard-subscription-selector-header",
|
||||||
|
caretUpIcon: "caret-up",
|
||||||
|
caretDownIcon: "caret-down",
|
||||||
|
},
|
||||||
|
|
||||||
|
allowedSubscriptionTypes(feature, attribute, value) {
|
||||||
|
let attributes = this.subscriptionAttributes[feature];
|
||||||
|
if (!attributes || !attributes[attribute]) {
|
||||||
|
return ["none"];
|
||||||
|
}
|
||||||
|
let allowedTypes = [];
|
||||||
|
Object.keys(attributes[attribute]).forEach((subscriptionType) => {
|
||||||
|
let values = attributes[attribute][subscriptionType];
|
||||||
|
if (values[0] === "*" || values.includes(value)) {
|
||||||
|
allowedTypes.push(subscriptionType);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return allowedTypes;
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("feature", "attribute")
|
||||||
|
content(feature, attribute) {
|
||||||
|
return wizardSchema[feature][attribute]
|
||||||
|
.map((value) => {
|
||||||
|
let allowedSubscriptionTypes = this.allowedSubscriptionTypes(
|
||||||
|
feature,
|
||||||
|
attribute,
|
||||||
|
value
|
||||||
|
);
|
||||||
|
|
||||||
|
let subscriptionRequired =
|
||||||
|
allowedSubscriptionTypes.length &&
|
||||||
|
!allowedSubscriptionTypes.includes("none");
|
||||||
|
|
||||||
|
let attrs = {
|
||||||
|
id: value,
|
||||||
|
name: I18n.t(nameKey(feature, attribute, value)),
|
||||||
|
subscriptionRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (subscriptionRequired) {
|
||||||
|
let subscribed = allowedSubscriptionTypes.includes(
|
||||||
|
this.subscriptionType
|
||||||
|
);
|
||||||
|
let selectorKey = subscribed ? "subscribed" : "not_subscribed";
|
||||||
|
let selectorLabel = `admin.wizard.subscription.${selectorKey}.selector`;
|
||||||
|
|
||||||
|
attrs.disabled = !subscribed;
|
||||||
|
attrs.selectorLabel = selectorLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrs;
|
||||||
|
})
|
||||||
|
.sort(function (a, b) {
|
||||||
|
if (a.subscriptionType && !b.subscriptionType) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!a.subscriptionType && b.subscriptionType) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (a.subscriptionType === b.subscriptionType) {
|
||||||
|
return a.subscriptionType
|
||||||
|
? a.subscriptionType.localeCompare(b.subscriptionType)
|
||||||
|
: 0;
|
||||||
|
} else {
|
||||||
|
return a.subscriptionType === "standard" ? -1 : 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
modifyComponentForRow() {
|
||||||
|
return "wizard-subscription-selector/wizard-subscription-selector-row";
|
||||||
|
},
|
||||||
|
});
|
|
@ -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-subscription-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;
|
||||||
|
}
|
||||||
|
),
|
||||||
|
});
|
|
@ -0,0 +1,20 @@
|
||||||
|
import SelectKitRowComponent from "select-kit/components/select-kit/select-kit-row";
|
||||||
|
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
|
export default SelectKitRowComponent.extend({
|
||||||
|
classNameBindings: ["isDisabled:disabled"],
|
||||||
|
|
||||||
|
@discourseComputed("item")
|
||||||
|
isDisabled() {
|
||||||
|
return this.item.disabled;
|
||||||
|
},
|
||||||
|
|
||||||
|
click(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
if (!this.item.disabled) {
|
||||||
|
this.selectKit.select(this.rowValue, this.item);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
});
|
139
assets/javascripts/discourse/components/wizard-table-field.js.es6
Normale Datei
139
assets/javascripts/discourse/components/wizard-table-field.js.es6
Normale Datei
|
@ -0,0 +1,139 @@
|
||||||
|
import Component from "@ember/component";
|
||||||
|
import { action } from "@ember/object";
|
||||||
|
import { equal, notEmpty } from "@ember/object/computed";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import I18n from "I18n";
|
||||||
|
|
||||||
|
export default Component.extend({
|
||||||
|
classNameBindings: ["value.type"],
|
||||||
|
isText: equal("value.type", "text"),
|
||||||
|
isComposer: equal("value.type", "composer"),
|
||||||
|
isDate: equal("value.type", "date"),
|
||||||
|
isTime: equal("value.type", "time"),
|
||||||
|
isDateTime: equal("value.type", "date_time"),
|
||||||
|
isNumber: equal("value.type", "number"),
|
||||||
|
isCheckbox: equal("value.type", "checkbox"),
|
||||||
|
isUrl: equal("value.type", "url"),
|
||||||
|
isUpload: equal("value.type", "upload"),
|
||||||
|
isDropdown: equal("value.type", "dropdown"),
|
||||||
|
isTag: equal("value.type", "tag"),
|
||||||
|
isCategory: equal("value.type", "category"),
|
||||||
|
isGroup: equal("value.type", "group"),
|
||||||
|
isUserSelector: equal("value.type", "user_selector"),
|
||||||
|
isSubmittedAt: equal("field", "submitted_at"),
|
||||||
|
isComposerPreview: equal("value.type", "composer_preview"),
|
||||||
|
textState: "text-collapsed",
|
||||||
|
toggleText: I18n.t("admin.wizard.expand_text"),
|
||||||
|
|
||||||
|
@discourseComputed("value", "isUser")
|
||||||
|
hasValue(value, isUser) {
|
||||||
|
if (isUser) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
return value && value.value;
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("field", "value.type")
|
||||||
|
isUser(field, type) {
|
||||||
|
return field === "username" || field === "user" || type === "user";
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("value.type")
|
||||||
|
isLongtext(type) {
|
||||||
|
return type === "textarea" || type === "long_text";
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("value")
|
||||||
|
checkboxValue(value) {
|
||||||
|
const isCheckbox = this.get("isCheckbox");
|
||||||
|
if (isCheckbox) {
|
||||||
|
if (value.value.includes("true")) {
|
||||||
|
return true;
|
||||||
|
} else if (value.value.includes("false")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@action
|
||||||
|
expandText() {
|
||||||
|
const state = this.get("textState");
|
||||||
|
|
||||||
|
if (state === "text-collapsed") {
|
||||||
|
this.set("textState", "text-expanded");
|
||||||
|
this.set("toggleText", I18n.t("admin.wizard.collapse_text"));
|
||||||
|
} else if (state === "text-expanded") {
|
||||||
|
this.set("textState", "text-collapsed");
|
||||||
|
this.set("toggleText", I18n.t("admin.wizard.expand_text"));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("value")
|
||||||
|
file(value) {
|
||||||
|
const isUpload = this.get("isUpload");
|
||||||
|
if (isUpload) {
|
||||||
|
return value.value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("value")
|
||||||
|
submittedUsers(value) {
|
||||||
|
const isUserSelector = this.get("isUserSelector");
|
||||||
|
const users = [];
|
||||||
|
|
||||||
|
if (isUserSelector) {
|
||||||
|
const userData = value.value;
|
||||||
|
const usernames = [];
|
||||||
|
|
||||||
|
if (userData.indexOf(",")) {
|
||||||
|
usernames.push(...userData.split(","));
|
||||||
|
|
||||||
|
usernames.forEach((u) => {
|
||||||
|
const user = {
|
||||||
|
username: u,
|
||||||
|
url: `/u/${u}`,
|
||||||
|
};
|
||||||
|
users.push(user);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return users;
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("isUser", "field", "value")
|
||||||
|
username(isUser, field, value) {
|
||||||
|
if (isUser) {
|
||||||
|
return value.username;
|
||||||
|
}
|
||||||
|
if (field === "username") {
|
||||||
|
return value.value;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
|
||||||
|
showUsername: notEmpty("username"),
|
||||||
|
|
||||||
|
@discourseComputed("username")
|
||||||
|
userProfileUrl(username) {
|
||||||
|
if (username) {
|
||||||
|
return `/u/${username}`;
|
||||||
|
}
|
||||||
|
return "/";
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("value")
|
||||||
|
categoryUrl(value) {
|
||||||
|
const isCategory = this.get("isCategory");
|
||||||
|
if (isCategory) {
|
||||||
|
return `/c/${value.value}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("value")
|
||||||
|
groupUrl(value) {
|
||||||
|
const isGroup = this.get("isGroup");
|
||||||
|
if (isGroup) {
|
||||||
|
return `/g/${value.value}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,3 +1,7 @@
|
||||||
{{#if currentUser.admin}}
|
{{#if currentUser.admin}}
|
||||||
{{nav-item route="adminWizards" label="admin.wizard.nav_label"}}
|
{{nav-item route="adminWizards" label="admin.wizard.nav_label"}}
|
||||||
|
|
||||||
|
{{#if wizardErrorNotice}}
|
||||||
|
{{d-icon "exclaimation-circle"}}
|
||||||
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -11,7 +11,7 @@ export default Controller.extend({
|
||||||
queryParams: ["refresh_list"],
|
queryParams: ["refresh_list"],
|
||||||
loadingSubscriptions: false,
|
loadingSubscriptions: false,
|
||||||
notAuthorized: not("api.authorized"),
|
notAuthorized: not("api.authorized"),
|
||||||
endpointMethods: selectKitContent(["GET", "PUT", "POST", "PATCH", "DELETE"]),
|
endpointMethods: selectKitContent(["PUT", "POST", "PATCH", "DELETE"]),
|
||||||
showRemove: not("isNew"),
|
showRemove: not("isNew"),
|
||||||
showRedirectUri: and("threeLeggedOauth", "api.name"),
|
showRedirectUri: and("threeLeggedOauth", "api.name"),
|
||||||
responseIcon: null,
|
responseIcon: null,
|
||||||
|
@ -88,6 +88,11 @@ export default Controller.extend({
|
||||||
twoLeggedOauth: equal("api.authType", "oauth_2"),
|
twoLeggedOauth: equal("api.authType", "oauth_2"),
|
||||||
threeLeggedOauth: equal("api.authType", "oauth_3"),
|
threeLeggedOauth: equal("api.authType", "oauth_3"),
|
||||||
|
|
||||||
|
@discourseComputed("api.isNew")
|
||||||
|
nameClass(isNew) {
|
||||||
|
return isNew ? "new" : "saved";
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
addParam() {
|
addParam() {
|
||||||
this.get("api.authParams").pushObject({});
|
this.get("api.authParams").pushObject({});
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
import Controller from "@ember/controller";
|
||||||
|
import ModalFunctionality from "discourse/mixins/modal-functionality";
|
||||||
|
|
||||||
|
export default Controller.extend(ModalFunctionality, {
|
||||||
|
actions: {
|
||||||
|
save() {
|
||||||
|
this.send("closeModal");
|
||||||
|
},
|
||||||
|
|
||||||
|
resetToDefault() {
|
||||||
|
this.get("model.reset")();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
|
@ -0,0 +1,52 @@
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
import { notEmpty } from "@ember/object/computed";
|
||||||
|
import CustomWizardLogs from "../models/custom-wizard-logs";
|
||||||
|
import Controller from "@ember/controller";
|
||||||
|
|
||||||
|
export default Controller.extend({
|
||||||
|
refreshing: false,
|
||||||
|
hasLogs: notEmpty("logs"),
|
||||||
|
page: 0,
|
||||||
|
canLoadMore: true,
|
||||||
|
logs: [],
|
||||||
|
messageKey: "viewing",
|
||||||
|
|
||||||
|
loadLogs() {
|
||||||
|
if (!this.canLoadMore) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const page = this.get("page");
|
||||||
|
const wizardId = this.get("wizard.id");
|
||||||
|
|
||||||
|
this.set("refreshing", true);
|
||||||
|
|
||||||
|
CustomWizardLogs.list(wizardId, page)
|
||||||
|
.then((result) => {
|
||||||
|
this.set("logs", this.logs.concat(result.logs));
|
||||||
|
})
|
||||||
|
.finally(() => this.set("refreshing", false));
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("hasLogs", "refreshing")
|
||||||
|
noResults(hasLogs, refreshing) {
|
||||||
|
return !hasLogs && !refreshing;
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
loadMore() {
|
||||||
|
if (!this.loadingMore && this.logs.length < this.total) {
|
||||||
|
this.set("page", (this.page += 1));
|
||||||
|
this.loadLogs();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
refresh() {
|
||||||
|
this.setProperties({
|
||||||
|
canLoadMore: true,
|
||||||
|
page: 0,
|
||||||
|
logs: [],
|
||||||
|
});
|
||||||
|
this.loadLogs();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,50 +1,34 @@
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
|
||||||
import { notEmpty } from "@ember/object/computed";
|
|
||||||
import CustomWizardLogs from "../models/custom-wizard-logs";
|
|
||||||
import Controller from "@ember/controller";
|
import Controller from "@ember/controller";
|
||||||
|
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
export default Controller.extend({
|
export default Controller.extend({
|
||||||
refreshing: false,
|
documentationUrl: "https://thepavilion.io/t/2818",
|
||||||
hasLogs: notEmpty("logs"),
|
|
||||||
page: 0,
|
|
||||||
canLoadMore: true,
|
|
||||||
logs: [],
|
|
||||||
|
|
||||||
loadLogs() {
|
@discourseComputed("wizardId")
|
||||||
if (!this.canLoadMore) {
|
wizardName(wizardId) {
|
||||||
return;
|
let currentWizard = this.wizardList.find(
|
||||||
|
(wizard) => wizard.id === wizardId
|
||||||
|
);
|
||||||
|
if (currentWizard) {
|
||||||
|
return currentWizard.name;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("wizardName")
|
||||||
|
messageOpts(wizardName) {
|
||||||
|
return {
|
||||||
|
wizardName,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("wizardId")
|
||||||
|
messageKey(wizardId) {
|
||||||
|
let key = "select";
|
||||||
|
|
||||||
|
if (wizardId) {
|
||||||
|
key = "viewing";
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set("refreshing", true);
|
return key;
|
||||||
|
|
||||||
CustomWizardLogs.list()
|
|
||||||
.then((result) => {
|
|
||||||
if (!result || result.length === 0) {
|
|
||||||
this.set("canLoadMore", false);
|
|
||||||
}
|
|
||||||
this.set("logs", this.logs.concat(result));
|
|
||||||
})
|
|
||||||
.finally(() => this.set("refreshing", false));
|
|
||||||
},
|
|
||||||
|
|
||||||
@discourseComputed("hasLogs", "refreshing")
|
|
||||||
noResults(hasLogs, refreshing) {
|
|
||||||
return !hasLogs && !refreshing;
|
|
||||||
},
|
|
||||||
|
|
||||||
actions: {
|
|
||||||
loadMore() {
|
|
||||||
this.set("page", (this.page += 1));
|
|
||||||
this.loadLogs();
|
|
||||||
},
|
|
||||||
|
|
||||||
refresh() {
|
|
||||||
this.setProperties({
|
|
||||||
canLoadMore: true,
|
|
||||||
page: 0,
|
|
||||||
logs: [],
|
|
||||||
});
|
|
||||||
this.loadLogs();
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,69 @@
|
||||||
import Controller from "@ember/controller";
|
import Controller from "@ember/controller";
|
||||||
|
import { empty } from "@ember/object/computed";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
import { fmt } from "discourse/lib/computed";
|
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"),
|
||||||
|
noResults: empty("submissions"),
|
||||||
|
page: 0,
|
||||||
|
total: 0,
|
||||||
|
|
||||||
|
loadMoreSubmissions() {
|
||||||
|
const page = this.get("page");
|
||||||
|
const wizardId = this.get("wizard.id");
|
||||||
|
|
||||||
|
this.set("loadingMore", true);
|
||||||
|
CustomWizard.submissions(wizardId, page)
|
||||||
|
.then((result) => {
|
||||||
|
if (result.submissions) {
|
||||||
|
this.get("submissions").pushObjects(result.submissions);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.set("loadingMore", false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("submissions", "fields.@each.enabled")
|
||||||
|
displaySubmissions(submissions, fields) {
|
||||||
|
let result = [];
|
||||||
|
|
||||||
|
submissions.forEach((submission) => {
|
||||||
|
let sub = {};
|
||||||
|
|
||||||
|
Object.keys(submission).forEach((fieldId) => {
|
||||||
|
if (fields.some((f) => f.id === fieldId && f.enabled)) {
|
||||||
|
sub[fieldId] = submission[fieldId];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
result.push(sub);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
loadMore() {
|
||||||
|
if (!this.loadingMore && this.submissions.length < this.total) {
|
||||||
|
this.set("page", this.get("page") + 1);
|
||||||
|
this.loadMoreSubmissions();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
showEditColumnsModal() {
|
||||||
|
return showModal("admin-wizards-columns", {
|
||||||
|
model: {
|
||||||
|
columns: this.get("fields"),
|
||||||
|
reset: () => {
|
||||||
|
this.get("fields").forEach((field) => {
|
||||||
|
field.set("enabled", true);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
import Controller from "@ember/controller";
|
||||||
|
import { default as discourseComputed } from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
|
export default Controller.extend({
|
||||||
|
documentationUrl: "https://thepavilion.io/t/2818",
|
||||||
|
|
||||||
|
@discourseComputed("wizardId")
|
||||||
|
wizardName(wizardId) {
|
||||||
|
let currentWizard = this.wizardList.find(
|
||||||
|
(wizard) => wizard.id === wizardId
|
||||||
|
);
|
||||||
|
if (currentWizard) {
|
||||||
|
return currentWizard.name;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("wizardName")
|
||||||
|
messageOpts(wizardName) {
|
||||||
|
return {
|
||||||
|
wizardName,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("wizardId")
|
||||||
|
messageKey(wizardId) {
|
||||||
|
let key = "select";
|
||||||
|
|
||||||
|
if (wizardId) {
|
||||||
|
key = "viewing";
|
||||||
|
}
|
||||||
|
|
||||||
|
return key;
|
||||||
|
},
|
||||||
|
});
|
|
@ -92,7 +92,11 @@ export default Controller.extend({
|
||||||
wizard
|
wizard
|
||||||
.save(opts)
|
.save(opts)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
|
if (result.wizard_id) {
|
||||||
this.send("afterSave", result.wizard_id);
|
this.send("afterSave", result.wizard_id);
|
||||||
|
} else if (result.errors) {
|
||||||
|
this.set("error", result.errors.join(", "));
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.catch((result) => {
|
.catch((result) => {
|
||||||
this.set("error", this.getErrorMessage(result));
|
this.set("error", this.getErrorMessage(result));
|
||||||
|
@ -118,10 +122,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);
|
||||||
|
|
9
assets/javascripts/discourse/controllers/admin-wizards.js.es6
Normale Datei
9
assets/javascripts/discourse/controllers/admin-wizards.js.es6
Normale Datei
|
@ -0,0 +1,9 @@
|
||||||
|
import Controller from "@ember/controller";
|
||||||
|
import { equal, or } from "@ember/object/computed";
|
||||||
|
|
||||||
|
export default Controller.extend({
|
||||||
|
businessSubscription: equal("subscriptionType", "business"),
|
||||||
|
communitySubscription: equal("subscriptionType", "community"),
|
||||||
|
standardSubscription: equal("subscriptionType", "standard"),
|
||||||
|
showApi: or("businessSubscription", "communitySubscription"),
|
||||||
|
});
|
|
@ -43,7 +43,16 @@ export default {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
this.route("adminWizardsLogs", { path: "/logs", resetNamespace: true });
|
this.route(
|
||||||
|
"adminWizardsLogs",
|
||||||
|
{ path: "/logs", resetNamespace: true },
|
||||||
|
function () {
|
||||||
|
this.route("adminWizardsLogsShow", {
|
||||||
|
path: "/:wizardId/",
|
||||||
|
resetNamespace: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
this.route("adminWizardsManager", {
|
this.route("adminWizardsManager", {
|
||||||
path: "/manager",
|
path: "/manager",
|
||||||
|
|
|
@ -20,7 +20,7 @@ export default {
|
||||||
return existing.apply(this, [path, opts]);
|
return existing.apply(this, [path, opts]);
|
||||||
};
|
};
|
||||||
|
|
||||||
withPluginApi("0.8.7", (api) => {
|
withPluginApi("0.8.36", (api) => {
|
||||||
api.modifyClass("component:d-navigation", {
|
api.modifyClass("component:d-navigation", {
|
||||||
pluginId: "custom-wizard",
|
pluginId: "custom-wizard",
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -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 || [];
|
||||||
|
|
|
@ -19,7 +19,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",
|
||||||
|
@ -41,7 +40,6 @@ const step = {
|
||||||
id: null,
|
id: null,
|
||||||
index: null,
|
index: null,
|
||||||
title: null,
|
title: null,
|
||||||
key: null,
|
|
||||||
banner: null,
|
banner: null,
|
||||||
banner_upload_id: null,
|
banner_upload_id: null,
|
||||||
raw_description: null,
|
raw_description: null,
|
||||||
|
@ -52,7 +50,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: {
|
||||||
|
@ -71,14 +68,13 @@ const field = {
|
||||||
image: null,
|
image: null,
|
||||||
image_upload_id: null,
|
image_upload_id: null,
|
||||||
description: null,
|
description: null,
|
||||||
|
property: null,
|
||||||
required: null,
|
required: null,
|
||||||
key: null,
|
|
||||||
type: null,
|
type: null,
|
||||||
condition: null,
|
condition: null,
|
||||||
},
|
},
|
||||||
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: {},
|
||||||
|
@ -201,22 +197,24 @@ const action = {
|
||||||
"members_visibility_level",
|
"members_visibility_level",
|
||||||
"add_event",
|
"add_event",
|
||||||
],
|
],
|
||||||
advanced: [
|
|
||||||
"code",
|
|
||||||
"custom_fields",
|
|
||||||
"skip_redirect",
|
|
||||||
"suppress_notifications",
|
|
||||||
"required",
|
|
||||||
],
|
|
||||||
required: ["id", "type"],
|
required: ["id", "type"],
|
||||||
dependent: {},
|
dependent: {},
|
||||||
objectArrays: {},
|
objectArrays: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const custom_field = {
|
||||||
|
klass: ["topic", "post", "group", "category"],
|
||||||
|
type: ["string", "boolean", "integer", "json"],
|
||||||
|
};
|
||||||
|
|
||||||
|
field.type = Object.keys(field.types);
|
||||||
|
action.type = Object.keys(action.types);
|
||||||
|
|
||||||
const wizardSchema = {
|
const wizardSchema = {
|
||||||
wizard,
|
wizard,
|
||||||
step,
|
step,
|
||||||
field,
|
field,
|
||||||
|
custom_field,
|
||||||
action,
|
action,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
53
assets/javascripts/discourse/mixins/subscription.js.es6
Normale Datei
53
assets/javascripts/discourse/mixins/subscription.js.es6
Normale Datei
|
@ -0,0 +1,53 @@
|
||||||
|
import Mixin from "@ember/object/mixin";
|
||||||
|
import { getOwner } from "discourse-common/lib/get-owner";
|
||||||
|
import { readOnly } from "@ember/object/computed";
|
||||||
|
import discourseComputed from "discourse-common/utils/decorators";
|
||||||
|
|
||||||
|
const PRODUCT_PAGE = "https://custom-wizard.pavilion.tech";
|
||||||
|
const SUPPORT_MESSAGE =
|
||||||
|
"https://coop.pavilion.tech/new-message?username=support&title=Custom%20Wizard%20Support";
|
||||||
|
const MANAGER_CATEGORY =
|
||||||
|
"https://discourse.pluginmanager.org/c/discourse-custom-wizard";
|
||||||
|
|
||||||
|
export default Mixin.create({
|
||||||
|
subscriptionLandingUrl: PRODUCT_PAGE,
|
||||||
|
subscriptionClientUrl: "/admin/plugins/subscription-client",
|
||||||
|
|
||||||
|
@discourseComputed
|
||||||
|
adminWizards() {
|
||||||
|
return getOwner(this).lookup("controller:admin-wizards");
|
||||||
|
},
|
||||||
|
|
||||||
|
subscribed: readOnly("adminWizards.subscribed"),
|
||||||
|
subscriptionType: readOnly("adminWizards.subscriptionType"),
|
||||||
|
businessSubscription: readOnly("adminWizards.businessSubscription"),
|
||||||
|
communitySubscription: readOnly("adminWizards.communitySubscription"),
|
||||||
|
standardSubscription: readOnly("adminWizards.standardSubscription"),
|
||||||
|
subscriptionAttributes: readOnly("adminWizards.subscriptionAttributes"),
|
||||||
|
subscriptionClientInstalled: readOnly(
|
||||||
|
"adminWizards.subscriptionClientInstalled"
|
||||||
|
),
|
||||||
|
|
||||||
|
@discourseComputed("subscriptionClientInstalled")
|
||||||
|
subscriptionLink(subscriptionClientInstalled) {
|
||||||
|
return subscriptionClientInstalled
|
||||||
|
? this.subscriptionClientUrl
|
||||||
|
: this.subscriptionLandingUrl;
|
||||||
|
},
|
||||||
|
|
||||||
|
@discourseComputed("subscriptionType")
|
||||||
|
subscriptionCtaLink(subscriptionType) {
|
||||||
|
switch (subscriptionType) {
|
||||||
|
case "none":
|
||||||
|
return PRODUCT_PAGE;
|
||||||
|
case "standard":
|
||||||
|
return SUPPORT_MESSAGE;
|
||||||
|
case "business":
|
||||||
|
return SUPPORT_MESSAGE;
|
||||||
|
case "community":
|
||||||
|
return MANAGER_CATEGORY;
|
||||||
|
default:
|
||||||
|
return PRODUCT_PAGE;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
|
@ -3,14 +3,54 @@ import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
import EmberObject from "@ember/object";
|
import EmberObject from "@ember/object";
|
||||||
|
|
||||||
const CustomWizardLogs = EmberObject.extend();
|
const CustomWizardLogs = EmberObject.extend();
|
||||||
|
const logItemTypes = {
|
||||||
|
date: "date_time",
|
||||||
|
action: "text",
|
||||||
|
message: "long_text",
|
||||||
|
user: "user",
|
||||||
|
username: "text",
|
||||||
|
};
|
||||||
|
|
||||||
|
function logItem(item, attr) {
|
||||||
|
return {
|
||||||
|
value: item[attr],
|
||||||
|
type: logItemTypes[attr],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
CustomWizardLogs.reopenClass({
|
CustomWizardLogs.reopenClass({
|
||||||
list(page = 0) {
|
list(wizardId, page = 0) {
|
||||||
return ajax("/admin/wizards/logs", {
|
let data = {
|
||||||
data: {
|
|
||||||
page,
|
page,
|
||||||
},
|
};
|
||||||
}).catch(popupAjaxError);
|
|
||||||
|
return ajax(`/admin/wizards/logs/${wizardId}`, { data })
|
||||||
|
.catch(popupAjaxError)
|
||||||
|
.then((result) => {
|
||||||
|
if (result.logs) {
|
||||||
|
result.logs = result.logs.map((item) => {
|
||||||
|
let map = {};
|
||||||
|
|
||||||
|
if (item.date) {
|
||||||
|
map.date = logItem(item, "date");
|
||||||
|
}
|
||||||
|
if (item.action) {
|
||||||
|
map.action = logItem(item, "action");
|
||||||
|
}
|
||||||
|
if (item.user) {
|
||||||
|
map.user = item.user;
|
||||||
|
} else {
|
||||||
|
map.user = logItem(item, "username");
|
||||||
|
}
|
||||||
|
if (item.message) {
|
||||||
|
map.message = logItem(item, "message");
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,10 @@ export default DiscourseRoute.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
const customFields = A(model || []);
|
const customFields = A(model.custom_fields || []);
|
||||||
controller.set("customFields", customFields);
|
|
||||||
|
controller.setProperties({
|
||||||
|
customFields,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
17
assets/javascripts/discourse/routes/admin-wizards-logs-show.js.es6
Normale Datei
17
assets/javascripts/discourse/routes/admin-wizards-logs-show.js.es6
Normale Datei
|
@ -0,0 +1,17 @@
|
||||||
|
import CustomWizardLogs from "../models/custom-wizard-logs";
|
||||||
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
|
import { A } from "@ember/array";
|
||||||
|
|
||||||
|
export default DiscourseRoute.extend({
|
||||||
|
model(params) {
|
||||||
|
return CustomWizardLogs.list(params.wizardId);
|
||||||
|
},
|
||||||
|
|
||||||
|
setupController(controller, model) {
|
||||||
|
controller.setProperties({
|
||||||
|
wizard: model.wizard,
|
||||||
|
logs: A(model.logs),
|
||||||
|
total: model.total,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,12 +1,24 @@
|
||||||
import CustomWizardLogs from "../models/custom-wizard-logs";
|
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
model() {
|
model() {
|
||||||
return CustomWizardLogs.list();
|
return ajax(`/admin/wizards/wizard`);
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
controller.set("logs", model);
|
const showParams = this.paramsFor("adminWizardsLogsShow");
|
||||||
|
|
||||||
|
controller.setProperties({
|
||||||
|
wizardId: showParams.wizardId,
|
||||||
|
wizardList: model.wizard_list,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
changeWizard(wizardId) {
|
||||||
|
this.controllerFor("adminWizardsLogs").set("wizardId", wizardId);
|
||||||
|
this.transitionTo("adminWizardsLogsShow", wizardId);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,42 +1,24 @@
|
||||||
|
import { A } from "@ember/array";
|
||||||
|
import EmberObject from "@ember/object";
|
||||||
import CustomWizardAdmin from "../models/custom-wizard-admin";
|
import CustomWizardAdmin from "../models/custom-wizard-admin";
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
|
|
||||||
const excludedMetaFields = ["route_to", "redirect_on_complete", "redirect_to"];
|
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
model(params) {
|
model(params) {
|
||||||
return CustomWizardAdmin.submissions(params.wizardId);
|
return CustomWizardAdmin.submissions(params.wizardId);
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
if (model && model.submissions) {
|
const fields = model.fields.map((f) => {
|
||||||
let fields = ["username"];
|
const fieldsObject = EmberObject.create(f);
|
||||||
model.submissions.forEach((s) => {
|
fieldsObject.enabled = true;
|
||||||
Object.keys(s.fields).forEach((k) => {
|
return fieldsObject;
|
||||||
if (!excludedMetaFields.includes(k) && fields.indexOf(k) < 0) {
|
|
||||||
fields.push(k);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
let submissions = [];
|
|
||||||
model.submissions.forEach((s) => {
|
|
||||||
let submission = {
|
|
||||||
username: s.username,
|
|
||||||
};
|
|
||||||
Object.keys(s.fields).forEach((f) => {
|
|
||||||
if (fields.includes(f)) {
|
|
||||||
submission[f] = s.fields[f];
|
|
||||||
}
|
|
||||||
});
|
|
||||||
submissions.push(submission);
|
|
||||||
});
|
|
||||||
|
|
||||||
controller.setProperties({
|
controller.setProperties({
|
||||||
wizard: model.wizard,
|
wizard: model.wizard,
|
||||||
submissions,
|
fields: A(fields),
|
||||||
fields,
|
submissions: A(model.submissions),
|
||||||
|
total: model.total,
|
||||||
});
|
});
|
||||||
}
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,21 @@
|
||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
beforeModel(transition) {
|
model() {
|
||||||
|
return ajax("/admin/wizards");
|
||||||
|
},
|
||||||
|
|
||||||
|
setupController(controller, model) {
|
||||||
|
controller.setProperties({
|
||||||
|
subscribed: model.subscribed,
|
||||||
|
subscriptionType: model.subscription_type,
|
||||||
|
subscriptionAttributes: model.subscription_attributes,
|
||||||
|
subscriptionClientInstalled: model.subscription_client_installed,
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
afterModel(model, transition) {
|
||||||
if (transition.targetName === "adminWizards.index") {
|
if (transition.targetName === "adminWizards.index") {
|
||||||
this.transitionTo("adminWizardsWizard");
|
this.transitionTo("adminWizardsWizard");
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,11 +21,11 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header">
|
<div class="wizard-header large">
|
||||||
{{#if api.isNew}}
|
{{#if api.isNew}}
|
||||||
{{i18n "admin.wizard.api.new"}}
|
{{i18n "admin.wizard.api.new"}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{api.title}}
|
<span>{{api.title}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -35,12 +35,12 @@
|
||||||
{{input value=api.title placeholder=(i18n "admin.wizard.api.title_placeholder")}}
|
{{input value=api.title placeholder=(i18n "admin.wizard.api.title_placeholder")}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="name">
|
<div class="name {{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=api.name placeholder=(i18n "admin.wizard.api.name_placeholder")}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{api.name}}
|
<span>{{api.name}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -63,7 +63,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header">
|
<div class="wizard-header medium">
|
||||||
{{i18n "admin.wizard.api.auth.label"}}
|
{{i18n "admin.wizard.api.auth.label"}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -71,7 +71,7 @@
|
||||||
<div class="wizard-api-authentication">
|
<div class="wizard-api-authentication">
|
||||||
<div class="settings">
|
<div class="settings">
|
||||||
|
|
||||||
<div class="wizard-header medium">
|
<div class="wizard-header small">
|
||||||
{{i18n "admin.wizard.api.auth.settings"}}
|
{{i18n "admin.wizard.api.auth.settings"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header medium">
|
<div class="wizard-header small">
|
||||||
{{i18n "admin.wizard.api.status.label"}}
|
{{i18n "admin.wizard.api.status.label"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -220,7 +220,7 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header">
|
<div class="wizard-header medium">
|
||||||
{{i18n "admin.wizard.api.endpoint.label"}}
|
{{i18n "admin.wizard.api.endpoint.label"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -277,11 +277,15 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-header">
|
<div class="wizard-header medium">
|
||||||
{{i18n "admin.wizard.api.log.label"}}
|
{{i18n "admin.wizard.api.log.label"}}
|
||||||
{{d-button action=(action "clearLogs")
|
|
||||||
icon="trash-alt"
|
<div class="controls">
|
||||||
class="clear-logs"}}
|
{{d-button
|
||||||
|
action=(action "clearLogs")
|
||||||
|
class="clear-logs"
|
||||||
|
label="admin.wizard.api.log.clear"}}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-api-log">
|
<div class="wizard-api-log">
|
||||||
|
@ -300,7 +304,7 @@
|
||||||
<td>{{logentry.time}}</td>
|
<td>{{logentry.time}}</td>
|
||||||
<td class="user-image">
|
<td class="user-image">
|
||||||
<div class="user-image-inner">
|
<div class="user-image-inner">
|
||||||
<a href={{logentry.userpath}} data-user-card={{logentry.username}}>{{avatar logentry imageSize="large"}}</a>
|
<a href={{logentry.userpath}} data-user-card={{logentry.username}}>{{avatar logentry imageSize="medium"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td>{{logentry.status}}</td>
|
<td>{{logentry.status}}</td>
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
)}}
|
)}}
|
||||||
|
|
||||||
{{d-button
|
{{d-button
|
||||||
action="createApi"
|
action=(route-action "createApi")
|
||||||
label="admin.wizard.api.create"
|
label="admin.wizard.api.create"
|
||||||
icon="plus"}}
|
icon="plus"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
{{d-button
|
{{d-button
|
||||||
label="admin.wizard.custom_field.add"
|
label="admin.wizard.custom_field.add"
|
||||||
icon="plus"
|
icon="plus"
|
||||||
action="addField"}}
|
action=(action "addField")}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
45
assets/javascripts/discourse/templates/admin-wizards-logs-show.hbs
Normale Datei
45
assets/javascripts/discourse/templates/admin-wizards-logs-show.hbs
Normale Datei
|
@ -0,0 +1,45 @@
|
||||||
|
{{#if logs}}
|
||||||
|
<div class="wizard-header large">
|
||||||
|
<label>
|
||||||
|
{{i18n "admin.wizard.log.title" name=wizard.name}}
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<div class="controls">
|
||||||
|
{{d-button
|
||||||
|
label="refresh"
|
||||||
|
icon="sync"
|
||||||
|
action=(action "refresh")
|
||||||
|
class="refresh"}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="wizard-table">
|
||||||
|
{{#load-more selector=".wizard-table tr" action=(action "loadMore")}}
|
||||||
|
{{#if noResults}}
|
||||||
|
<p>{{i18n "search.no_results"}}</p>
|
||||||
|
{{else}}
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="date">{{i18n "admin.wizard.log.date"}}</th>
|
||||||
|
<th>{{i18n "admin.wizard.log.action"}}</th>
|
||||||
|
<th>{{i18n "admin.wizard.log.user"}}</th>
|
||||||
|
<th>{{i18n "admin.wizard.log.message"}}</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{#each logs as |log|}}
|
||||||
|
<tr>
|
||||||
|
{{#each-in log as |field value|}}
|
||||||
|
<td class="small">{{wizard-table-field field=field value=value}}</td>
|
||||||
|
{{/each-in}}
|
||||||
|
</tr>
|
||||||
|
{{/each}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{conditional-loading-spinner condition=refreshing}}
|
||||||
|
{{/load-more}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
|
@ -1,34 +1,19 @@
|
||||||
<div class="admin-wizard-controls">
|
<div class="admin-wizard-select admin-wizard-controls">
|
||||||
<h3>{{i18n "admin.wizard.log.nav_label"}}</h3>
|
{{combo-box
|
||||||
|
value=wizardId
|
||||||
{{d-button
|
content=wizardList
|
||||||
label="refresh"
|
onChange=(route-action "changeWizard")
|
||||||
icon="sync"
|
options=(hash
|
||||||
action="refresh"
|
none="admin.wizard.select"
|
||||||
class="refresh"}}
|
)}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#load-more selector=".log-list tr" action=(action "loadMore") class="wizard-logs"}}
|
{{wizard-message
|
||||||
{{#if noResults}}
|
key=messageKey
|
||||||
<p>{{i18n "search.no_results"}}</p>
|
opts=messageOpts
|
||||||
{{else}}
|
url=documentationUrl
|
||||||
<table class="table grid">
|
component="logs"}}
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Message</th>
|
|
||||||
<th class="date">Date</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{{#each logs as |log|}}
|
|
||||||
<tr>
|
|
||||||
<td>{{log.message}}</td>
|
|
||||||
<td class="date">{{bound-date log.date}}</td>
|
|
||||||
</tr>
|
|
||||||
{{/each}}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{conditional-loading-spinner condition=refreshing}}
|
<div class="admin-wizard-container">
|
||||||
{{/load-more}}
|
{{outlet}}
|
||||||
|
</div>
|
||||||
|
|
|
@ -1,8 +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>
|
||||||
|
|
||||||
<a class="btn btn-default download-link" href={{downloadUrl}} target="_blank" rel="noopener noreferrer">
|
<div class="controls">
|
||||||
|
{{d-button
|
||||||
|
icon="sliders-h"
|
||||||
|
label="admin.wizard.edit_columns"
|
||||||
|
action=(action "showEditColumnsModal")
|
||||||
|
class="btn-default open-edit-columns-btn download-link"
|
||||||
|
}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<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"}}
|
||||||
|
@ -10,24 +26,36 @@
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="wizard-submissions">
|
<div class="wizard-table">
|
||||||
|
{{#load-more selector=".wizard-table tr" action=(action "loadMore")}}
|
||||||
|
{{#if noResults}}
|
||||||
|
<p>{{i18n "search.no_results"}}</p>
|
||||||
|
{{else}}
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
{{#each fields as |f|}}
|
{{#each fields as |field|}}
|
||||||
<th>{{f}}</th>
|
{{#if field.enabled}}
|
||||||
|
<th>
|
||||||
|
{{field.label}}
|
||||||
|
</th>
|
||||||
|
{{/if}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{#each submissions as |s|}}
|
{{#each displaySubmissions as |submission|}}
|
||||||
<tr>
|
<tr>
|
||||||
{{#each-in s as |k v|}}
|
{{#each-in submission as |field value|}}
|
||||||
<td>{{v}}</td>
|
<td>{{wizard-table-field field=field value=value}}</td>
|
||||||
{{/each-in}}
|
{{/each-in}}
|
||||||
</tr>
|
</tr>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{conditional-loading-spinner condition=loadingMore}}
|
||||||
|
{{/load-more}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<div class="admin-wizard-select">
|
<div class="admin-wizard-select admin-wizard-controls">
|
||||||
{{combo-box
|
{{combo-box
|
||||||
value=wizardId
|
value=wizardId
|
||||||
content=wizardList
|
content=wizardList
|
||||||
|
@ -8,6 +8,12 @@
|
||||||
)}}
|
)}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{wizard-message
|
||||||
|
key=messageKey
|
||||||
|
opts=messageOpts
|
||||||
|
url=documentationUrl
|
||||||
|
component="submissions"}}
|
||||||
|
|
||||||
<div class="admin-wizard-container">
|
<div class="admin-wizard-container">
|
||||||
{{outlet}}
|
{{outlet}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -101,7 +101,7 @@
|
||||||
{{input type="checkbox" checked=wizard.after_time}}
|
{{input type="checkbox" checked=wizard.after_time}}
|
||||||
<span>{{i18n "admin.wizard.after_time_label"}}</span>
|
<span>{{i18n "admin.wizard.after_time_label"}}</span>
|
||||||
{{d-button
|
{{d-button
|
||||||
action="setNextSessionScheduled"
|
action=(action "setNextSessionScheduled")
|
||||||
translatedLabel=nextSessionScheduledLabel
|
translatedLabel=nextSessionScheduledLabel
|
||||||
class="btn-after-time"
|
class="btn-after-time"
|
||||||
icon="far-calendar"}}
|
icon="far-calendar"}}
|
||||||
|
@ -126,11 +126,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{wizard-advanced-toggle showAdvanced=wizard.showAdvanced}}
|
{{#wizard-subscription-container}}
|
||||||
|
|
||||||
{{#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,19 +146,7 @@
|
||||||
<span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
|
<span>{{i18n "admin.wizard.restart_on_revisit_label"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{/wizard-subscription-container}}
|
||||||
<div class="setting">
|
|
||||||
<div class="setting-label">
|
|
||||||
<label>{{i18n "admin.wizard.resume_on_revisit"}}</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-value">
|
|
||||||
{{input type="checkbox" checked=wizard.resume_on_revisit}}
|
|
||||||
<span>{{i18n "admin.wizard.resume_on_revisit_label"}}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{wizard-links
|
{{wizard-links
|
||||||
|
@ -176,7 +160,8 @@
|
||||||
wizard=wizard
|
wizard=wizard
|
||||||
currentField=currentField
|
currentField=currentField
|
||||||
wizardFields=wizardFields
|
wizardFields=wizardFields
|
||||||
fieldTypes=fieldTypes}}
|
fieldTypes=fieldTypes
|
||||||
|
subscribed=subscribed}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{wizard-links
|
{{wizard-links
|
||||||
|
@ -185,9 +170,9 @@
|
||||||
items=wizard.actions
|
items=wizard.actions
|
||||||
generateLabels=true}}
|
generateLabels=true}}
|
||||||
|
|
||||||
{{#each wizard.actions as |action|}}
|
{{#each wizard.actions as |wizardAction|}}
|
||||||
{{wizard-custom-action
|
{{wizard-custom-action
|
||||||
action=action
|
action=wizardAction
|
||||||
currentActionId=currentAction.id
|
currentActionId=currentAction.id
|
||||||
wizard=wizard
|
wizard=wizard
|
||||||
apis=apis
|
apis=apis
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
)}}
|
)}}
|
||||||
|
|
||||||
{{d-button
|
{{d-button
|
||||||
action="createWizard"
|
action=(route-action "createWizard")
|
||||||
label="admin.wizard.create"
|
label="admin.wizard.create"
|
||||||
icon="plus"}}
|
icon="plus"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -2,17 +2,15 @@
|
||||||
{{nav-item route="adminWizardsWizard" label="admin.wizard.nav_label"}}
|
{{nav-item route="adminWizardsWizard" label="admin.wizard.nav_label"}}
|
||||||
{{nav-item route="adminWizardsCustomFields" label="admin.wizard.custom_field.nav_label"}}
|
{{nav-item route="adminWizardsCustomFields" label="admin.wizard.custom_field.nav_label"}}
|
||||||
{{nav-item route="adminWizardsSubmissions" label="admin.wizard.submissions.nav_label"}}
|
{{nav-item route="adminWizardsSubmissions" label="admin.wizard.submissions.nav_label"}}
|
||||||
{{#if siteSettings.wizard_apis_enabled}}
|
{{#if showApi}}
|
||||||
{{nav-item route="adminWizardsApi" label="admin.wizard.api.nav_label"}}
|
{{nav-item route="adminWizardsApi" label="admin.wizard.api.nav_label"}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}}
|
{{nav-item route="adminWizardsLogs" label="admin.wizard.log.nav_label"}}
|
||||||
{{nav-item route="adminWizardsManager" label="admin.wizard.manager.nav_label"}}
|
{{nav-item route="adminWizardsManager" label="admin.wizard.manager.nav_label"}}
|
||||||
|
|
||||||
<div class="announcement">
|
<div class="admin-actions">
|
||||||
<a href="https://custom-wizard.pavilion.tech/subscriptions" target="_blank" title="Click to learn more about Custom Wizard Subscriptions">
|
{{wizard-subscription-badge}}
|
||||||
<img src='/images/emoji/twitter/man_mage.png?v=12'>
|
{{wizard-subscription-cta}}
|
||||||
<span>Custom Wizard Subscriptions Are Coming!</span>
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
{{/admin-nav}}
|
{{/admin-nav}}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
{{#if showInputs}}
|
{{#if showInputs}}
|
||||||
<td>
|
<td>
|
||||||
{{combo-box
|
{{wizard-subscription-selector
|
||||||
value=field.klass
|
value=field.klass
|
||||||
content=klassContent
|
feature="custom_field"
|
||||||
|
attribute="klass"
|
||||||
|
onChange=(action (mut field.klass))
|
||||||
|
options=(hash
|
||||||
none="admin.wizard.custom_field.klass.select"
|
none="admin.wizard.custom_field.klass.select"
|
||||||
onChange=(action (mut field.klass))}}
|
)}}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{combo-box
|
{{wizard-subscription-selector
|
||||||
value=field.type
|
value=field.type
|
||||||
content=typeContent
|
feature="custom_field"
|
||||||
|
attribute="type"
|
||||||
|
onChange=(action (mut field.type))
|
||||||
|
options=(hash
|
||||||
none="admin.wizard.custom_field.type.select"
|
none="admin.wizard.custom_field.type.select"
|
||||||
onChange=(action (mut field.type))}}
|
)}}
|
||||||
</td>
|
</td>
|
||||||
<td class="input">
|
<td class="input">
|
||||||
{{input
|
{{input
|
||||||
|
@ -22,8 +28,10 @@
|
||||||
{{multi-select
|
{{multi-select
|
||||||
value=field.serializers
|
value=field.serializers
|
||||||
content=serializerContent
|
content=serializerContent
|
||||||
|
onChange=(action (mut field.serializers))
|
||||||
|
options=(hash
|
||||||
none="admin.wizard.custom_field.serializers.select"
|
none="admin.wizard.custom_field.serializers.select"
|
||||||
onChange=(action (mut field.serializers))}}
|
)}}
|
||||||
</td>
|
</td>
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
{{#if loading}}
|
{{#if loading}}
|
||||||
|
@ -34,17 +42,17 @@
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{d-button
|
{{d-button
|
||||||
action="destroy"
|
action=(action "destroy")
|
||||||
icon="trash-alt"
|
icon="trash-alt"
|
||||||
class="destroy"
|
class="destroy"
|
||||||
disabled=destroyDisabled}}
|
disabled=destroyDisabled}}
|
||||||
{{d-button
|
{{d-button
|
||||||
icon="save"
|
icon="save"
|
||||||
action="save"
|
action=(action "save")
|
||||||
disabled=saveDisabled
|
disabled=saveDisabled
|
||||||
class="save"}}
|
class="save"}}
|
||||||
{{d-button
|
{{d-button
|
||||||
action="close"
|
action=(action "close")
|
||||||
icon="times"
|
icon="times"
|
||||||
disabled=closeDisabled}}
|
disabled=closeDisabled}}
|
||||||
</td>
|
</td>
|
||||||
|
@ -69,7 +77,7 @@
|
||||||
</td>
|
</td>
|
||||||
{{else}}
|
{{else}}
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
{{d-button action="edit" icon="pencil-alt"}}
|
{{d-button action=(action "edit") icon="pencil-alt"}}
|
||||||
</td>
|
</td>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
{{d-button
|
|
||||||
action="toggleAdvanced"
|
|
||||||
label="admin.wizard.advanced"
|
|
||||||
class=toggleClass}}
|
|
|
@ -1,6 +1,6 @@
|
||||||
{{#if showUndo}}
|
{{#if showUndo}}
|
||||||
{{d-button
|
{{d-button
|
||||||
action="undoChanges"
|
action=(action "undoChanges")
|
||||||
icon=undoIcon
|
icon=undoIcon
|
||||||
label=undoKey
|
label=undoKey
|
||||||
class="undo-changes"}}
|
class="undo-changes"}}
|
||||||
|
@ -12,13 +12,15 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{combo-box
|
{{wizard-subscription-selector
|
||||||
value=action.type
|
value=action.type
|
||||||
content=actionTypes
|
feature="action"
|
||||||
|
attribute="type"
|
||||||
onChange=(action "changeType")
|
onChange=(action "changeType")
|
||||||
options=(hash
|
options=(hash
|
||||||
none="admin.wizard.select_type"
|
none="admin.wizard.select_type"
|
||||||
)}}
|
)
|
||||||
|
}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -733,12 +735,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">
|
||||||
|
@ -826,6 +822,3 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{{#if showUndo}}
|
{{#if showUndo}}
|
||||||
{{d-button
|
{{d-button
|
||||||
action="undoChanges"
|
action=(action "undoChanges")
|
||||||
icon=undoIcon
|
icon=undoIcon
|
||||||
label=undoKey
|
label=undoKey
|
||||||
class="undo-changes"}}
|
class="undo-changes"}}
|
||||||
|
@ -224,12 +224,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if showAdvanced}}
|
{{#wizard-subscription-container}}
|
||||||
{{wizard-advanced-toggle showAdvanced=field.showAdvanced}}
|
|
||||||
|
|
||||||
{{#if field.showAdvanced}}
|
|
||||||
<div class="advanced-settings">
|
|
||||||
|
|
||||||
<div class="setting full field-mapper-setting">
|
<div class="setting full field-mapper-setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.condition"}}</label>
|
<label>{{i18n "admin.wizard.condition"}}</label>
|
||||||
|
@ -272,22 +267,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="setting">
|
|
||||||
<div class="setting-label">
|
|
||||||
<label>{{i18n "admin.wizard.translation"}}</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-value medium">
|
|
||||||
{{input
|
|
||||||
name="key"
|
|
||||||
value=field.key
|
|
||||||
class="medium"
|
|
||||||
placeholderKey="admin.wizard.translation_placeholder"}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{{#if validations}}
|
{{#if validations}}
|
||||||
{{wizard-realtime-validations field=field validations=validations}}
|
{{wizard-realtime-validations field=field validations=validations}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
{{/wizard-subscription-container}}
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
|
@ -34,11 +34,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{wizard-advanced-toggle showAdvanced=step.showAdvanced}}
|
{{#wizard-subscription-container}}
|
||||||
|
|
||||||
{{#if step.showAdvanced}}
|
|
||||||
<div class="advanced-settings">
|
|
||||||
|
|
||||||
<div class="setting full field-mapper-setting">
|
<div class="setting full field-mapper-setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.condition"}}</label>
|
<label>{{i18n "admin.wizard.condition"}}</label>
|
||||||
|
@ -64,6 +60,7 @@
|
||||||
<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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{wizard-mapper
|
{{wizard-mapper
|
||||||
inputs=step.required_data
|
inputs=step.required_data
|
||||||
|
@ -102,20 +99,7 @@
|
||||||
)}}
|
)}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{/wizard-subscription-container}}
|
||||||
<div class="setting">
|
|
||||||
<div class="setting-label">
|
|
||||||
<label>{{i18n "admin.wizard.translation"}}</label>
|
|
||||||
</div>
|
|
||||||
<div class="setting-value">
|
|
||||||
{{input
|
|
||||||
name="key"
|
|
||||||
value=step.key
|
|
||||||
placeholderKey="admin.wizard.translation_placeholder"}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{wizard-links
|
{{wizard-links
|
||||||
itemType="field"
|
itemType="field"
|
||||||
|
@ -130,5 +114,6 @@
|
||||||
currentFieldId=currentField.id
|
currentFieldId=currentField.id
|
||||||
fieldTypes=fieldTypes
|
fieldTypes=fieldTypes
|
||||||
removeField="removeField"
|
removeField="removeField"
|
||||||
wizardFields=wizardFields}}
|
wizardFields=wizardFields
|
||||||
|
subscribed=subscribed}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|
|
@ -4,17 +4,16 @@
|
||||||
{{#if anyLinks}}
|
{{#if anyLinks}}
|
||||||
{{#each links as |link|}}
|
{{#each links as |link|}}
|
||||||
<div data-id={{link.id}}>
|
<div data-id={{link.id}}>
|
||||||
{{d-button action="change" actionParam=link.id translatedLabel=link.label class=link.classes}}
|
{{d-button action=(action "change") actionParam=link.id translatedLabel=link.label class=link.classes}}
|
||||||
{{#unless link.first}}
|
{{#unless link.first}}
|
||||||
{{d-button action="back" actionParam=link icon="arrow-left" class="back"}}
|
{{d-button action=(action "back") actionParam=link icon="arrow-left" class="back"}}
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
{{#unless link.last}}
|
{{#unless link.last}}
|
||||||
{{d-button action="forward" actionParam=link icon="arrow-right" class="forward"}}
|
{{d-button action=(action "forward") actionParam=link icon="arrow-right" class="forward"}}
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
{{d-button action="remove" actionParam=link.id icon="times" class="remove"}}
|
{{d-button action=(action "remove") actionParam=link.id icon="times" class="remove"}}
|
||||||
</div>
|
</div>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{d-button action="add" label="admin.wizard.add" icon="plus"}}
|
{{d-button action=(action "add") label="admin.wizard.add" icon="plus"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,6 @@
|
||||||
|
|
||||||
{{#if canAdd}}
|
{{#if canAdd}}
|
||||||
<span class="add-mapper-input">
|
<span class="add-mapper-input">
|
||||||
{{d-button action="add" label="admin.wizard.add" icon="plus"}}
|
{{d-button action=(action "add") label="admin.wizard.add" icon="plus"}}
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
<h3>{{i18n "admin.wizard.field.validations.header"}}</h3>
|
<div class="setting-label">
|
||||||
|
<label>{{i18n "admin.wizard.field.validations.header"}}</label>
|
||||||
|
</div>
|
||||||
|
<div class="setting-value full">
|
||||||
<ul>
|
<ul>
|
||||||
{{#each-in field.validations as |type props|}}
|
{{#each-in field.validations as |type props|}}
|
||||||
<li>
|
<li>
|
||||||
|
@ -39,12 +41,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-value">
|
<div class="setting-value">
|
||||||
{{radio-button name=(concat type field.id) value="above" selection=props.position}}
|
{{radio-button name=(concat type field.id) value="above" selection=props.position}}
|
||||||
{{i18n "admin.wizard.field.validations.above"}}
|
<span>{{i18n "admin.wizard.field.validations.above"}}</span>
|
||||||
{{radio-button name=(concat type field.id) value="below" selection=props.position}}
|
{{radio-button name=(concat type field.id) value="below" selection=props.position}}
|
||||||
{{i18n "admin.wizard.field.validations.below"}}
|
<span>{{i18n "admin.wizard.field.validations.below"}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{{/each-in}}
|
{{/each-in}}
|
||||||
</ul>
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
<svg width="300px" height="300px" viewBox="0 0 300 300" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<g id="pavilion-logo" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<path id="Combined-Shape" stroke="currentColor" stroke-width="35" d="M41.1381822,291.00006 L40.5778853,130.009744 M258.850727,291.638415 L259.290397,130.37133 M36.0002279,140.721678 L139.995368,36.2122772 M263.350577,141.009083 L138.927245,16.2478517"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
<span>{{label}}</span>
|
Nachher Breite: | Höhe: | Größe: 538 B |
|
@ -0,0 +1,12 @@
|
||||||
|
<div class="subscription-header">
|
||||||
|
<h4>{{i18n "admin.wizard.subscription.title"}}</h4>
|
||||||
|
|
||||||
|
<a href={{subscriptionLink}} title={{i18n subscribedTitle}}>
|
||||||
|
{{d-icon subscribedIcon}}
|
||||||
|
{{i18n subscribedLabel}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="subscription-settings">
|
||||||
|
{{yield}}
|
||||||
|
</div>
|
|
@ -0,0 +1 @@
|
||||||
|
{{d-icon icon}}{{label}}
|
|
@ -0,0 +1,15 @@
|
||||||
|
<div class="select-kit-header-wrapper">
|
||||||
|
|
||||||
|
{{component selectKit.options.selectedNameComponent
|
||||||
|
tabindex=tabindex
|
||||||
|
item=selectedContent
|
||||||
|
selectKit=selectKit
|
||||||
|
shouldDisplayClearableButton=shouldDisplayClearableButton
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{#if subscriptionRequired}}
|
||||||
|
<span class="subscription-label">{{i18n selectorLabel}}</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{d-icon caretIcon class="caret-icon"}}
|
||||||
|
</div>
|
|
@ -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.subscriptionRequired}}
|
||||||
|
<span class="subscription-label">{{i18n item.selectorLabel}}</span>
|
||||||
|
{{/if}}
|
||||||
|
</div>
|
161
assets/javascripts/discourse/templates/components/wizard-table-field.hbs
Normale Datei
161
assets/javascripts/discourse/templates/components/wizard-table-field.hbs
Normale Datei
|
@ -0,0 +1,161 @@
|
||||||
|
{{#if hasValue}}
|
||||||
|
{{#if isText}}
|
||||||
|
{{value.value}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isLongtext}}
|
||||||
|
<div class="wizard-table-long-text">
|
||||||
|
<p class="wizard-table-long-text-content {{textState}}">
|
||||||
|
{{value.value}}
|
||||||
|
</p>
|
||||||
|
<a href {{action "expandText"}}>
|
||||||
|
{{toggleText}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isComposer}}
|
||||||
|
<div class="wizard-table-long-text">
|
||||||
|
<p class="wizard-table-composer-text wizard-table-long-text-content {{textState}}">
|
||||||
|
{{value.value}}
|
||||||
|
</p>
|
||||||
|
<a href {{action "expandText"}}>
|
||||||
|
{{toggleText}}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isComposerPreview}}
|
||||||
|
{{d-icon "comment-alt"}}
|
||||||
|
<span class="wizard-table-composer-text">
|
||||||
|
{{i18n "admin.wizard.submissions.composer_preview"}}: {{value.value}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isTextOnly}}
|
||||||
|
{{value.value}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isDate}}
|
||||||
|
<span class="wizard-table-icon-item">
|
||||||
|
{{d-icon "calendar"}}{{value.value}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isTime}}
|
||||||
|
<span class="wizard-table-icon-item">
|
||||||
|
{{d-icon "clock"}}{{value.value}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isDateTime}}
|
||||||
|
<span class="wizard-table-icon-item" title={{value.value}}>
|
||||||
|
{{d-icon "calendar"}}{{format-date value.value format="medium"}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isNumber}}
|
||||||
|
{{value.value}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isCheckbox}}
|
||||||
|
{{#if checkboxValue}}
|
||||||
|
<span class="wizard-table-icon-item checkbox-true">
|
||||||
|
{{d-icon "check"}}{{value.value}}
|
||||||
|
</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="wizard-table-icon-item checkbox-false">
|
||||||
|
{{d-icon "times"}}{{value.value}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isUrl}}
|
||||||
|
<span class="wizard-table-icon-item url">
|
||||||
|
{{d-icon "link"}}
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href={{value.value}}>
|
||||||
|
{{value.value}}
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isUpload}}
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="attachment"
|
||||||
|
href={{file.url}}
|
||||||
|
download
|
||||||
|
>
|
||||||
|
{{file.original_filename}}
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isDropdown}}
|
||||||
|
<span class="wizard-table-icon-item">
|
||||||
|
{{d-icon "check-square"}}
|
||||||
|
{{value.value}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isTag}}
|
||||||
|
{{#each value.value as |tag|}}
|
||||||
|
{{discourse-tag tag}}
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isCategory}}
|
||||||
|
<strong>
|
||||||
|
{{i18n "admin.wizard.submissions.category_id"}}:
|
||||||
|
</strong>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={{categoryUrl}}
|
||||||
|
title={{value.value}}
|
||||||
|
>
|
||||||
|
{{value.value}}
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isGroup}}
|
||||||
|
<strong>
|
||||||
|
{{i18n "admin.wizard.submissions.group_id"}}:
|
||||||
|
</strong>
|
||||||
|
{{value.value}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isUserSelector}}
|
||||||
|
{{#each submittedUsers as |user|}}
|
||||||
|
{{d-icon "user"}}
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={{user.url}}
|
||||||
|
title={{user.username}}
|
||||||
|
>
|
||||||
|
{{user.username}}
|
||||||
|
</a>
|
||||||
|
{{/each}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isUser}}
|
||||||
|
{{#link-to "user" value}}
|
||||||
|
{{avatar value imageSize="tiny"}}
|
||||||
|
{{/link-to}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if showUsername}}
|
||||||
|
<a target="_blank" rel="noopener noreferrer" href={{userProfileUrl}} title={{username}}>
|
||||||
|
{{username}}
|
||||||
|
</a>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isSubmittedAt}}
|
||||||
|
<span class="date" title={{value.value}}>
|
||||||
|
{{d-icon "clock"}}{{format-date value format="tiny"}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
{{else}}
|
||||||
|
—
|
||||||
|
{{/if}}
|
|
@ -6,13 +6,13 @@
|
||||||
<div class="wizard-editor-gutter">
|
<div class="wizard-editor-gutter">
|
||||||
{{#if previewEnabled}}
|
{{#if previewEnabled}}
|
||||||
{{d-button
|
{{d-button
|
||||||
action="togglePreview"
|
action=(action "togglePreview")
|
||||||
translatedLabel=previewLabel}}
|
translatedLabel=previewLabel}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
{{#if fieldsEnabled}}
|
{{#if fieldsEnabled}}
|
||||||
{{d-button
|
{{d-button
|
||||||
action="togglePopover"
|
action=(action "togglePopover")
|
||||||
translatedLabel=popoverLabel}}
|
translatedLabel=popoverLabel}}
|
||||||
|
|
||||||
{{#if showPopover}}
|
{{#if showPopover}}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
{{#d-modal-body title="admin.wizard.edit_columns"}}
|
||||||
|
{{#if loading}}
|
||||||
|
{{loading-spinner size="large"}}
|
||||||
|
{{else}}
|
||||||
|
<div class="edit-directory-columns-container">
|
||||||
|
{{#each model.columns as |column|}}
|
||||||
|
<div class="edit-directory-column">
|
||||||
|
<div class="left-content">
|
||||||
|
<label class="column-name">
|
||||||
|
{{input type="checkbox" checked=column.enabled}}
|
||||||
|
{{directory-table-header-title field=column.label translated=true}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{/d-modal-body}}
|
||||||
|
|
||||||
|
<div class="modal-footer">
|
||||||
|
{{d-button
|
||||||
|
class="btn-primary"
|
||||||
|
label="directory.edit_columns.save"
|
||||||
|
action=(action "save")
|
||||||
|
}}
|
||||||
|
|
||||||
|
{{d-button
|
||||||
|
class="btn-secondary reset-to-default"
|
||||||
|
label="directory.edit_columns.reset_to_default"
|
||||||
|
action=(action "resetToDefault")
|
||||||
|
}}
|
||||||
|
</div>
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
{{d-button
|
{{d-button
|
||||||
action="submit"
|
action=(action "submit")
|
||||||
class="btn-primary"
|
class="btn-primary"
|
||||||
label="admin.wizard.after_time_modal.done"
|
label="admin.wizard.after_time_modal.done"
|
||||||
disabled=submitDisabled}}
|
disabled=submitDisabled}}
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
@import "wizard-mapper";
|
@import "admin/mapper";
|
||||||
@import "wizard-manager";
|
@import "admin/manager";
|
||||||
@import "wizard-api";
|
@import "admin/api";
|
||||||
@import "common/components/buttons";
|
@import "common/components/buttons";
|
||||||
|
@import "admin/variables";
|
||||||
|
|
||||||
|
$expired: #339b18;
|
||||||
|
$info: #038ae7;
|
||||||
|
$warning: #d47e00;
|
||||||
|
$error: #ef1700;
|
||||||
|
|
||||||
.announcement {
|
.announcement {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
|
@ -25,11 +31,24 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
margin-bottom: 20px;
|
margin-bottom: 10px;
|
||||||
|
min-height: 34px;
|
||||||
|
|
||||||
& + .wizard-message + div {
|
& + .wizard-message + div {
|
||||||
margin-top: 20px;
|
margin-top: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.admin-wizards .admin-actions {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.btn-pavilion-support {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-message {
|
.wizard-message {
|
||||||
|
@ -78,35 +97,68 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
& + div {
|
& + div,
|
||||||
|
& + div + div {
|
||||||
margin-top: 30px;
|
margin-top: 30px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-submissions {
|
.wizard-table {
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
|
|
||||||
table td {
|
table td:not(.small) {
|
||||||
min-width: 150px;
|
min-width: 150px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table thead th {
|
||||||
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-wizards-logs {
|
.wizard-table-icon-item {
|
||||||
.admin-wizard-controls {
|
display: flex;
|
||||||
h3 {
|
align-items: center;
|
||||||
margin: 0 7px;
|
|
||||||
|
svg {
|
||||||
|
margin-right: 5px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-logs {
|
.wizard-table-checkbox-true {
|
||||||
.date {
|
text-transform: capitalize;
|
||||||
width: 100px;
|
color: var(--success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.wizard-table-checkbox-false {
|
||||||
|
text-transform: capitalize;
|
||||||
|
color: var(--danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-table-long-text {
|
||||||
|
&-content {
|
||||||
|
white-space: nowrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
width: 250px;
|
||||||
|
margin-bottom: 0;
|
||||||
|
|
||||||
|
&.text-expanded {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-size: var(--font-down-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-table-composer-text {
|
||||||
|
font-family: monospace;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-settings-parent {
|
.wizard-settings-parent {
|
||||||
padding: 20px;
|
padding: 1em;
|
||||||
border: 1px solid var(--primary-low);
|
border: 1px solid var(--primary-low);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,10 +179,20 @@
|
||||||
|
|
||||||
.wizard-basic-details,
|
.wizard-basic-details,
|
||||||
.wizard-custom-field,
|
.wizard-custom-field,
|
||||||
.advanced-settings {
|
.subscription-settings {
|
||||||
@extend .wizard-settings-group;
|
@extend .wizard-settings-group;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.admin-wizard-container.settings {
|
||||||
|
.wizard-settings {
|
||||||
|
.wizard-subscription-container {
|
||||||
|
[class~="setting"] {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.wizard-custom-field {
|
.wizard-custom-field {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
background-color: var(--primary-very-low);
|
background-color: var(--primary-very-low);
|
||||||
|
@ -169,6 +231,7 @@
|
||||||
|
|
||||||
.wizard-header {
|
.wizard-header {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
&.large {
|
&.large {
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
|
@ -187,6 +250,10 @@
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
.download-link {
|
.download-link {
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
line-height: 20px;
|
line-height: 20px;
|
||||||
|
@ -202,25 +269,28 @@
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
background-color: var(--primary-low);
|
background-color: var(--primary-low);
|
||||||
}
|
}
|
||||||
|
|
||||||
button {
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.medium {
|
&.medium {
|
||||||
font-size: 1.3em;
|
font-size: 1.2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.small {
|
&.small {
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
|
font-weight: 700;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.underline {
|
&.underline {
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
font-size: 1rem;
|
||||||
|
display: flex;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.admin-wizard-buttons {
|
.admin-wizard-buttons {
|
||||||
|
@ -261,7 +331,7 @@
|
||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
}
|
}
|
||||||
|
|
||||||
span {
|
> span {
|
||||||
font-size: 0.929em;
|
font-size: 0.929em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -394,14 +464,16 @@
|
||||||
.setting-gutter {
|
.setting-gutter {
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.subscription {
|
||||||
|
.setting-label {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
label {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.advanced-settings {
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 30px;
|
|
||||||
|
|
||||||
[class~="setting"]:first-of-type {
|
|
||||||
border-top: none;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,27 +771,59 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.realtime-validations > ul {
|
.admin-wizard-container.settings .realtime-validations .setting-value > ul {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
background-color: var(--primary-low);
|
border: 1px solid var(--primary);
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
margin: 0 0 1em 0;
|
margin: 0 0 1em 0;
|
||||||
|
|
||||||
input {
|
.setting-title {
|
||||||
margin-bottom: 0;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin: 0 15px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
margin: 0 5px 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-label {
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.setting-value {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
.input .select-kit,
|
||||||
|
> .select-kit {
|
||||||
|
max-width: unset !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.validation-container {
|
.validation-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
padding: 1em 0;
|
padding: 1em 0;
|
||||||
|
|
||||||
.validation-section {
|
.validation-section {
|
||||||
width: 250px;
|
min-width: 250px;
|
||||||
|
margin: 0.5em 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,3 +840,113 @@
|
||||||
width: 80px;
|
width: 80px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn.btn-pavilion-support {
|
||||||
|
background: var(--pavilion-primary);
|
||||||
|
color: var(--pavilion-secondary);
|
||||||
|
|
||||||
|
.d-icon {
|
||||||
|
color: var(--pavilion-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover,
|
||||||
|
&:focus {
|
||||||
|
background: darken($pavilion_primary, 5%);
|
||||||
|
|
||||||
|
&[href],
|
||||||
|
svg.d-icon {
|
||||||
|
color: darken($pavilion_secondary, 10%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-subscription-container {
|
||||||
|
width: 100%;
|
||||||
|
padding: 1em;
|
||||||
|
background-color: rgba($pavilion_primary, 0.1);
|
||||||
|
|
||||||
|
.subscription-header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 0.25em;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.subscribed) .subscription-settings {
|
||||||
|
filter: blur(1px);
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-subscription-badge {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
max-height: 34px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0.5em 0.65em;
|
||||||
|
background-color: rgba($primary-medium, 0.05);
|
||||||
|
border: 1.5px solid rgba($primary-medium, 0.5);
|
||||||
|
color: $primary-medium;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $primary-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
svg {
|
||||||
|
width: 15px;
|
||||||
|
height: 15px;
|
||||||
|
margin-right: 0.45em;
|
||||||
|
margin-bottom: 0.15em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.standard {
|
||||||
|
background-color: rgba($subscription_standard, 0.05);
|
||||||
|
border: 1.5px solid rgba($subscription_standard, 0.5);
|
||||||
|
color: $subscription_standard;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.business {
|
||||||
|
background-color: $subscription_business;
|
||||||
|
border: 1.5px solid $subscription_business;
|
||||||
|
color: $secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.community {
|
||||||
|
background-color: $subscription_community;
|
||||||
|
border: 1.5px solid $pavilion_primary;
|
||||||
|
color: $pavilion_primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.d-icon {
|
||||||
|
margin-right: 0.75em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wizard-subscription-selector.select-kit.single-select {
|
||||||
|
.select-kit-row {
|
||||||
|
.texts {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
&.disabled {
|
||||||
|
background: var(--primary-low);
|
||||||
|
cursor: unset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.subscription-label {
|
||||||
|
margin-left: 0.75em;
|
||||||
|
padding-top: 0.25em;
|
||||||
|
color: var(--pavilion-primary);
|
||||||
|
font-size: 0.75em;
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,9 +40,18 @@
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wizard-header {
|
.metadata {
|
||||||
overflow: hidden;
|
display: flex;
|
||||||
font-size: 1.3em;
|
|
||||||
|
.title {
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name.saved span {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 6px 12px;
|
||||||
|
background-color: var(--primary-low);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,10 +83,6 @@
|
||||||
width: 50%;
|
width: 50%;
|
||||||
max-width: 50%;
|
max-width: 50%;
|
||||||
|
|
||||||
.wizard-header {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.authorization {
|
.authorization {
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
|
@ -2,10 +2,6 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.buttons {
|
.buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-left: auto;
|
margin-left: auto;
|
16
assets/stylesheets/common/admin/variables.scss
Normale Datei
16
assets/stylesheets/common/admin/variables.scss
Normale Datei
|
@ -0,0 +1,16 @@
|
||||||
|
$pavilion_primary: #3c1c8c;
|
||||||
|
$pavilion_secondary: #ffffff;
|
||||||
|
$pavilion_warning: rgb(243, 163, 61);
|
||||||
|
|
||||||
|
$subscription_standard: $pavilion_primary;
|
||||||
|
$subscription_business: #333;
|
||||||
|
$subscription_community: #fff;
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--pavilion-primary: #{$pavilion_primary};
|
||||||
|
--pavilion-secondary: #{$pavilion_secondary};
|
||||||
|
--pavilion-warning: #{$pavilion_warning};
|
||||||
|
--subscription-standard: #{$subscription_standard};
|
||||||
|
--subscription-business: #{$subscription_business};
|
||||||
|
--subscription-community: #{$subscription_community};
|
||||||
|
}
|
|
@ -1,14 +0,0 @@
|
||||||
@import "custom/base";
|
|
||||||
@import "custom/wizard";
|
|
||||||
@import "custom/header";
|
|
||||||
@import "custom/step";
|
|
||||||
@import "custom/badges";
|
|
||||||
@import "custom/buttons";
|
|
||||||
@import "custom/field";
|
|
||||||
@import "custom/validators";
|
|
||||||
@import "custom/mobile";
|
|
||||||
@import "custom/autocomplete";
|
|
||||||
@import "custom/composer";
|
|
||||||
@import "custom/events";
|
|
||||||
@import "custom/locations";
|
|
||||||
@import "custom/mentionables";
|
|
14
assets/stylesheets/common/wizard.scss
Normale Datei
14
assets/stylesheets/common/wizard.scss
Normale Datei
|
@ -0,0 +1,14 @@
|
||||||
|
@import "wizard/base";
|
||||||
|
@import "wizard/wizard";
|
||||||
|
@import "wizard/header";
|
||||||
|
@import "wizard/step";
|
||||||
|
@import "wizard/badges";
|
||||||
|
@import "wizard/buttons";
|
||||||
|
@import "wizard/field";
|
||||||
|
@import "wizard/validators";
|
||||||
|
@import "wizard/mobile";
|
||||||
|
@import "wizard/autocomplete";
|
||||||
|
@import "wizard/composer";
|
||||||
|
@import "wizard/events";
|
||||||
|
@import "wizard/locations";
|
||||||
|
@import "wizard/mentionables";
|
|
@ -67,6 +67,10 @@ body.custom-wizard {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
order: 2;
|
order: 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
& > .field-label + .field-description {
|
||||||
|
margin-left: 0.5em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.url-field input {
|
.url-field input {
|
|
@ -114,8 +114,6 @@ en:
|
||||||
key: "Key"
|
key: "Key"
|
||||||
value: "Value"
|
value: "Value"
|
||||||
profile: "profile"
|
profile: "profile"
|
||||||
translation: "Translation"
|
|
||||||
translation_placeholder: "key"
|
|
||||||
type: "Type"
|
type: "Type"
|
||||||
none: "Make a selection"
|
none: "Make a selection"
|
||||||
submission_key: 'submission key'
|
submission_key: 'submission key'
|
||||||
|
@ -128,6 +126,9 @@ en:
|
||||||
select_type: "Select a type"
|
select_type: "Select a type"
|
||||||
condition: "Condition"
|
condition: "Condition"
|
||||||
index: "Index"
|
index: "Index"
|
||||||
|
edit_columns: "Edit Columns"
|
||||||
|
expand_text: "Read More"
|
||||||
|
collapse_text: "Show Less"
|
||||||
category_settings:
|
category_settings:
|
||||||
custom_wizard:
|
custom_wizard:
|
||||||
title: "Custom Wizard"
|
title: "Custom Wizard"
|
||||||
|
@ -160,11 +161,30 @@ en:
|
||||||
no_file: Please choose a file to import
|
no_file: Please choose a file to import
|
||||||
file_size_error: The file size must be 512kb or less
|
file_size_error: The file size must be 512kb or less
|
||||||
file_format_error: The file must be a .json file
|
file_format_error: The file must be a .json file
|
||||||
server_error: "Error: {{message}}"
|
|
||||||
importing: Importing wizards...
|
importing: Importing wizards...
|
||||||
destroying: Destroying wizards...
|
destroying: Destroying wizards...
|
||||||
import_complete: Import complete
|
import_complete: Import complete
|
||||||
destroy_complete: Destruction complete
|
destroy_complete: Destruction complete
|
||||||
|
subscription:
|
||||||
|
documentation: Check out the subscription documentation
|
||||||
|
authorize: "Authorize this forum to use your Custom Wizard subscription plan on %{server}."
|
||||||
|
not_subscribed: "You've authorized, but are not currently subscribed to a Custom Wizard plan on %{server}."
|
||||||
|
subscription_expiring: "Your subscription is active, but will expire in the next 48 hours."
|
||||||
|
subscription_active: "Your subscription is active."
|
||||||
|
subscription_inactive: "Your subscription is inactive on this forum. Read more in <a href='https://thepavilion.io/t/3652'>the documentation</a>."
|
||||||
|
unauthorized: "You're unauthorized. If you have a subscription, it will become inactive in the next 48 hours."
|
||||||
|
unauthorize_failed: Failed to unauthorize.
|
||||||
|
submissions:
|
||||||
|
select: "Select a wizard to see its submissions"
|
||||||
|
viewing: "You're viewing the submissions of the %{wizardName}"
|
||||||
|
documentation: "Check out the submissions documentation"
|
||||||
|
logs:
|
||||||
|
select: "Select a wizard to see its logs"
|
||||||
|
viewing: "View recent logs for wizards on the forum"
|
||||||
|
documentation: "Check out the logs documentation"
|
||||||
|
notices:
|
||||||
|
info: "Plugin status and subscription notices"
|
||||||
|
documentation: Check out the notices documentation
|
||||||
|
|
||||||
editor:
|
editor:
|
||||||
show: "Show"
|
show: "Show"
|
||||||
|
@ -227,10 +247,10 @@ en:
|
||||||
banner: "Banner"
|
banner: "Banner"
|
||||||
description: "Description"
|
description: "Description"
|
||||||
required_data:
|
required_data:
|
||||||
label: "Required"
|
label: "Required Data"
|
||||||
not_permitted_message: "Message shown when required data not present"
|
not_permitted_message: "Message shown when required data not present"
|
||||||
permitted_params:
|
permitted_params:
|
||||||
label: "Params"
|
label: "Permitted Params"
|
||||||
force_final:
|
force_final:
|
||||||
label: "Conditional Final Step"
|
label: "Conditional Final Step"
|
||||||
description: "Display this step as the final step if conditions on later steps have not passed when the user reaches this step."
|
description: "Display this step as the final step if conditions on later steps have not passed when the user reaches this step."
|
||||||
|
@ -247,9 +267,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: "Template"
|
preview_template: "Template"
|
||||||
limit: "Limit"
|
limit: "Limit"
|
||||||
|
@ -261,7 +281,7 @@ en:
|
||||||
label: "Format"
|
label: "Format"
|
||||||
instructions: "<a href='https://momentjs.com/docs/#/displaying/format/' target='_blank'>Moment.js format</a>"
|
instructions: "<a href='https://momentjs.com/docs/#/displaying/format/' target='_blank'>Moment.js format</a>"
|
||||||
validations:
|
validations:
|
||||||
header: "Realtime Validations"
|
header: "Validations"
|
||||||
enabled: "Enabled"
|
enabled: "Enabled"
|
||||||
similar_topics: "Similar Topics"
|
similar_topics: "Similar Topics"
|
||||||
position: "Position"
|
position: "Position"
|
||||||
|
@ -438,6 +458,9 @@ en:
|
||||||
nav_label: "Submissions"
|
nav_label: "Submissions"
|
||||||
title: "{{name}} Submissions"
|
title: "{{name}} Submissions"
|
||||||
download: "Download"
|
download: "Download"
|
||||||
|
group_id: "Group ID"
|
||||||
|
category_id: "Category ID"
|
||||||
|
composer_preview: "Composer Preview"
|
||||||
|
|
||||||
api:
|
api:
|
||||||
label: "API"
|
label: "API"
|
||||||
|
@ -491,9 +514,15 @@ en:
|
||||||
|
|
||||||
log:
|
log:
|
||||||
label: "Logs"
|
label: "Logs"
|
||||||
|
clear: clear
|
||||||
|
|
||||||
log:
|
log:
|
||||||
nav_label: "Logs"
|
nav_label: "Logs"
|
||||||
|
title: "{{name}} Logs"
|
||||||
|
date: Date
|
||||||
|
action: Action
|
||||||
|
user: User
|
||||||
|
message: Message
|
||||||
|
|
||||||
manager:
|
manager:
|
||||||
nav_label: Manager
|
nav_label: Manager
|
||||||
|
@ -505,6 +534,38 @@ en:
|
||||||
destroy: Destroy
|
destroy: Destroy
|
||||||
destroyed: destroyed
|
destroyed: destroyed
|
||||||
|
|
||||||
|
subscription:
|
||||||
|
title: Subscriber Features
|
||||||
|
subscribed:
|
||||||
|
label: Subscribed
|
||||||
|
title: You're subscribed and can use these features
|
||||||
|
selector: subscribed
|
||||||
|
not_subscribed:
|
||||||
|
label: Not Subscribed
|
||||||
|
title: Subscribe to use these features
|
||||||
|
selector: not subscribed
|
||||||
|
type:
|
||||||
|
none:
|
||||||
|
label: Not Subscribed
|
||||||
|
title: There is no Custom Wizard subscription active on this forum.
|
||||||
|
business:
|
||||||
|
label: Business
|
||||||
|
title: There is a Custom Wizard Business subscription active on this forum.
|
||||||
|
standard:
|
||||||
|
label: Standard
|
||||||
|
title: There is a Custom Wizard Standard subscription active on this forum.
|
||||||
|
community:
|
||||||
|
label: Community
|
||||||
|
title: There is a Custom Wizard Community subscription active on this forum.
|
||||||
|
cta:
|
||||||
|
none:
|
||||||
|
label: Get a Subscription
|
||||||
|
title: Get a subscription for this forum.
|
||||||
|
subscribed:
|
||||||
|
label: Support
|
||||||
|
title: Get support for your subscription.
|
||||||
|
|
||||||
|
|
||||||
wizard_js:
|
wizard_js:
|
||||||
group:
|
group:
|
||||||
select: "Select a group"
|
select: "Select a group"
|
||||||
|
|
|
@ -17,6 +17,7 @@ en:
|
||||||
name_too_short: "'%{name}' is too short for a custom field name (min length is #{min_length})"
|
name_too_short: "'%{name}' is too short for a custom field name (min length is #{min_length})"
|
||||||
name_already_taken: "'%{name}' is already taken as a custom field name"
|
name_already_taken: "'%{name}' is already taken as a custom field name"
|
||||||
save_default: "Failed to save custom field '%{name}'"
|
save_default: "Failed to save custom field '%{name}'"
|
||||||
|
subscription_type: "%{type} custom fields require a subscription"
|
||||||
|
|
||||||
field:
|
field:
|
||||||
too_short: "%{label} must be at least %{min} characters"
|
too_short: "%{label} must be at least %{min} characters"
|
||||||
|
@ -52,9 +53,11 @@ en:
|
||||||
after_signup_after_time: "You can't use 'after time' and 'after signup' on the same wizard."
|
after_signup_after_time: "You can't use 'after time' and 'after signup' on the same wizard."
|
||||||
after_time: "After time setting is invalid."
|
after_time: "After time setting is invalid."
|
||||||
liquid_syntax_error: "Liquid syntax error in %{attribute}: %{message}"
|
liquid_syntax_error: "Liquid syntax error in %{attribute}: %{message}"
|
||||||
|
subscription: "%{type} %{property} is subscription only"
|
||||||
|
|
||||||
site_settings:
|
site_settings:
|
||||||
custom_wizard_enabled: "Enable custom wizards."
|
custom_wizard_enabled: "Enable custom wizards."
|
||||||
wizard_redirect_exclude_paths: "Routes excluded from wizard redirects."
|
wizard_redirect_exclude_paths: "Routes excluded from wizard redirects."
|
||||||
wizard_recognised_image_upload_formats: "File types which will result in upload displaying an image preview"
|
wizard_recognised_image_upload_formats: "File types which will result in upload displaying an image preview"
|
||||||
wizard_apis_enabled: "Enable API features (experimental)."
|
wizard_apis_enabled: "Enable API features (experimental)."
|
||||||
|
wizard_critical_notices_on_dashboard: "Show critical notices about the custom wizard plugin on the admin dashboard."
|
||||||
|
|
|
@ -38,6 +38,7 @@ Discourse::Application.routes.append do
|
||||||
get 'admin/wizards/api/:name/authorize' => 'admin_api#authorize'
|
get 'admin/wizards/api/:name/authorize' => 'admin_api#authorize'
|
||||||
|
|
||||||
get 'admin/wizards/logs' => 'admin_logs#index'
|
get 'admin/wizards/logs' => 'admin_logs#index'
|
||||||
|
get 'admin/wizards/logs/:wizard_id' => 'admin_logs#show'
|
||||||
|
|
||||||
get 'admin/wizards/manager' => 'admin_manager#index'
|
get 'admin/wizards/manager' => 'admin_manager#index'
|
||||||
get 'admin/wizards/manager/export' => 'admin_manager#export'
|
get 'admin/wizards/manager/export' => 'admin_manager#export'
|
||||||
|
|
|
@ -15,6 +15,6 @@ plugins:
|
||||||
refresh: true
|
refresh: true
|
||||||
type: list
|
type: list
|
||||||
list_type: compact
|
list_type: compact
|
||||||
wizard_apis_enabled:
|
wizard_important_notices_on_dashboard:
|
||||||
client: true
|
client: true
|
||||||
default: false
|
default: true
|
||||||
|
|
89
db/migrate/20210806135416_split_custom_wizard_log_fields.rb
Normale Datei
89
db/migrate/20210806135416_split_custom_wizard_log_fields.rb
Normale Datei
|
@ -0,0 +1,89 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
class SplitCustomWizardLogFields < ActiveRecord::Migration[6.1]
|
||||||
|
KEY_MAP = {
|
||||||
|
wizard: "wizard_id",
|
||||||
|
action: "action",
|
||||||
|
user: "username",
|
||||||
|
date: "date",
|
||||||
|
message: "message"
|
||||||
|
}
|
||||||
|
|
||||||
|
def change
|
||||||
|
reversible do |dir|
|
||||||
|
dir.up do
|
||||||
|
# separate wizard/action/user into their own keys
|
||||||
|
|
||||||
|
wizard_logs = PluginStoreRow.where("plugin_name = 'custom_wizard_log'")
|
||||||
|
|
||||||
|
if wizard_logs.exists?
|
||||||
|
wizard_logs.each do |row|
|
||||||
|
begin
|
||||||
|
log_json = JSON.parse(row.value)
|
||||||
|
rescue TypeError, JSON::ParserError
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
if log_json.key?('message') && log_json['message'].is_a?(String)
|
||||||
|
|
||||||
|
attr_strs = []
|
||||||
|
|
||||||
|
# assumes no whitespace in the values
|
||||||
|
attr_strs << log_json['message'].slice!(/(wizard: \S*; )/, 1)
|
||||||
|
attr_strs << log_json['message'].slice!(/(action: \S*; )/, 1)
|
||||||
|
attr_strs << log_json['message'].slice!(/(user: \S*; )/, 1)
|
||||||
|
|
||||||
|
attr_strs.each do |attr_str|
|
||||||
|
if attr_str.is_a? String
|
||||||
|
attr_str.gsub!(/[;]/ , "")
|
||||||
|
key, value = attr_str.split(': ')
|
||||||
|
value.strip! if value
|
||||||
|
key = KEY_MAP[key.to_sym] ? KEY_MAP[key.to_sym] : key
|
||||||
|
log_json[key] = value ? value : ''
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
row.value = log_json.to_json
|
||||||
|
row.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
dir.down do
|
||||||
|
wizard_logs = PluginStoreRow.where("plugin_name = 'custom_wizard_log'")
|
||||||
|
|
||||||
|
if wizard_logs.exists?
|
||||||
|
wizard_logs.each do |row|
|
||||||
|
begin
|
||||||
|
log_json = JSON.parse(row.value)
|
||||||
|
rescue TypeError, JSON::ParserError
|
||||||
|
next
|
||||||
|
end
|
||||||
|
|
||||||
|
# concatenate wizard/action/user to start of message
|
||||||
|
prefixes = log_json.extract!('wizard_id', 'action', 'username')
|
||||||
|
message_prefix = ""
|
||||||
|
|
||||||
|
if prefixes.present?
|
||||||
|
message_prefix = prefixes.map do |k, v|
|
||||||
|
key = KEY_MAP.key(k) ? KEY_MAP.key(k) : k
|
||||||
|
"#{key.to_s}: #{v};"
|
||||||
|
end.join(' ')
|
||||||
|
end
|
||||||
|
|
||||||
|
if log_json.key?('message')
|
||||||
|
message = log_json['message']
|
||||||
|
message = "#{message_prefix} #{message}" if message_prefix.present?
|
||||||
|
log_json['message'] = message
|
||||||
|
else
|
||||||
|
log_json['message'] = message_prefix
|
||||||
|
end
|
||||||
|
|
||||||
|
row.value = log_json.to_json
|
||||||
|
row.save
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -763,14 +763,11 @@ class CustomWizard::Action
|
||||||
end
|
end
|
||||||
|
|
||||||
def save_log
|
def save_log
|
||||||
log = "wizard: #{@wizard.id}; action: #{action['type']}; user: #{user.username}"
|
CustomWizard::Log.create(
|
||||||
|
@wizard.id,
|
||||||
if @log.any?
|
action['type'],
|
||||||
@log.each do |item|
|
user.username,
|
||||||
log += "; #{item.to_s}"
|
@log.join('; ')
|
||||||
end
|
)
|
||||||
end
|
|
||||||
|
|
||||||
CustomWizard::Log.create(log)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden Mehr anzeigen
Laden …
In neuem Issue referenzieren