Commits vergleichen
18 Commits
main
...
templates_
Autor | SHA1 | Datum | |
---|---|---|---|
|
72faab283d | ||
|
098c16cd47 | ||
|
a904d14e70 | ||
|
5e0ffd49db | ||
|
07f7e285ec | ||
|
310a3b0328 | ||
|
28094ab17b | ||
|
f9f67c09e8 | ||
|
ce705d32da | ||
|
b37bd54bcc | ||
|
5213c3e6cd | ||
|
c70b815226 | ||
|
4b559fb74e | ||
|
442f096940 | ||
|
343f594f18 | ||
|
b0f7fbf298 | ||
|
856bd11e2a | ||
|
1db9793d3e |
11 geänderte Dateien mit 220 neuen und 108 gelöschten Zeilen
|
@ -61,6 +61,22 @@ const step = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unit: custom_wizard:templates_and_builder
|
||||||
|
* type: step
|
||||||
|
* number: 2
|
||||||
|
* title: Add the attribute to the wizard schema
|
||||||
|
* description: Custom Wizard templates are modeled and serialized in the
|
||||||
|
* client via the Wizard Schema. In some cases, when adding a new
|
||||||
|
* attribute, you just need to add it to the schema for the
|
||||||
|
* attribute to be loaded from, and sent back to, the server.
|
||||||
|
* However, if you are adding a new type-specific field attribute,
|
||||||
|
* currently you only need to add it to the field type schema on
|
||||||
|
* the server. The field schema on the server is loaded into the
|
||||||
|
* empty ``types`` object below.
|
||||||
|
* refernces: plugins/discourse-custom-wizard/discourse/lib/wizard-json
|
||||||
|
* plugins/discourse-custom-wizard/discourse/models/custom-wizard
|
||||||
|
*/
|
||||||
const field = {
|
const field = {
|
||||||
basic: {
|
basic: {
|
||||||
id: null,
|
id: null,
|
||||||
|
|
|
@ -99,6 +99,22 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
{{!--
|
||||||
|
/* learning_step
|
||||||
|
* unit: custom_wizard:templates_and_builder
|
||||||
|
* type: step
|
||||||
|
* number: 1
|
||||||
|
* title: Add the attribute to the template
|
||||||
|
* description: First, add a new setting block to allow the site admin to
|
||||||
|
* administer how the attribute will work. Here we can see the
|
||||||
|
* controls for the Character Counter field attribute. Note
|
||||||
|
* the attribute is only available for text type fields (see
|
||||||
|
* isTextType conditional above this block). Note the
|
||||||
|
* consistent use of the ``setting``, ``setting-label`` and
|
||||||
|
* ``setting-value`` HTML structure throughout this component,
|
||||||
|
* and other Custom Wizard admin components.
|
||||||
|
*/
|
||||||
|
--}}
|
||||||
<div class="setting">
|
<div class="setting">
|
||||||
<div class="setting-label">
|
<div class="setting-label">
|
||||||
<label>{{i18n "admin.wizard.field.char_counter"}}</label>
|
<label>{{i18n "admin.wizard.field.char_counter"}}</label>
|
||||||
|
|
|
@ -17,6 +17,17 @@ export default {
|
||||||
const { clipboardHelpers } = requirejs("discourse/lib/utilities");
|
const { clipboardHelpers } = requirejs("discourse/lib/utilities");
|
||||||
const toMarkdown = requirejs("discourse/lib/to-markdown").default;
|
const toMarkdown = requirejs("discourse/lib/to-markdown").default;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* unit: custom_wizard:templates_and_builder
|
||||||
|
* type: step
|
||||||
|
* number: 8
|
||||||
|
* title: Handle the attribute in the wizard client
|
||||||
|
* description: We can now handle our new attribute in the wizard client.
|
||||||
|
* For our "highlighted" attribute, we would add a
|
||||||
|
* classNameBinding in the wizard-field component which
|
||||||
|
* we've imported from the discourse/discourse wizard and are
|
||||||
|
* extending here.
|
||||||
|
*/
|
||||||
FieldComponent.reopen({
|
FieldComponent.reopen({
|
||||||
classNameBindings: ["field.id"],
|
classNameBindings: ["field.id"],
|
||||||
|
|
||||||
|
|
|
@ -82,40 +82,15 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
|
||||||
:theme_id,
|
:theme_id,
|
||||||
permitted: mapped_params,
|
permitted: mapped_params,
|
||||||
steps: [
|
steps: [
|
||||||
:id,
|
*CustomWizard::Step.type_attributes(:permitted),
|
||||||
:index,
|
CustomWizard::Step.type_attributes(:mapped).map do |attribute|
|
||||||
:title,
|
[attribute, mapped_params]
|
||||||
:key,
|
end.to_h,
|
||||||
:banner,
|
|
||||||
:raw_description,
|
|
||||||
:required_data_message,
|
|
||||||
:force_final,
|
|
||||||
required_data: mapped_params,
|
|
||||||
permitted_params: mapped_params,
|
|
||||||
condition: mapped_params,
|
|
||||||
fields: [
|
fields: [
|
||||||
:id,
|
*CustomWizard::Field.type_attributes(:permitted),
|
||||||
:index,
|
CustomWizard::Field.type_attributes(:mapped).map do |attribute|
|
||||||
:label,
|
[attribute, mapped_params]
|
||||||
:image,
|
end.to_h
|
||||||
:description,
|
|
||||||
:required,
|
|
||||||
:key,
|
|
||||||
:type,
|
|
||||||
:min_length,
|
|
||||||
:max_length,
|
|
||||||
:char_counter,
|
|
||||||
:file_types,
|
|
||||||
:format,
|
|
||||||
:limit,
|
|
||||||
:property,
|
|
||||||
:preview_template,
|
|
||||||
:placeholder,
|
|
||||||
prefill: mapped_params,
|
|
||||||
content: mapped_params,
|
|
||||||
condition: mapped_params,
|
|
||||||
index: mapped_params,
|
|
||||||
validations: {},
|
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
actions: [
|
actions: [
|
||||||
|
|
|
@ -78,6 +78,14 @@ class CustomWizard::Builder
|
||||||
@wizard
|
@wizard
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# type: step
|
||||||
|
# number: 7
|
||||||
|
# title: Add it to the builder
|
||||||
|
# description: When our template is built into a wizard, we need our new
|
||||||
|
# attribute to be built here in the builder so it's ready to
|
||||||
|
# be sent to the wizard client.
|
||||||
|
##
|
||||||
def append_field(step, step_template, field_template, build_opts)
|
def append_field(step, step_template, field_template, build_opts)
|
||||||
params = {
|
params = {
|
||||||
id: field_template['id'],
|
id: field_template['id'],
|
||||||
|
|
|
@ -3,51 +3,94 @@
|
||||||
class CustomWizard::Field
|
class CustomWizard::Field
|
||||||
include ActiveModel::SerializerSupport
|
include ActiveModel::SerializerSupport
|
||||||
|
|
||||||
attr_reader :raw,
|
##
|
||||||
:id,
|
# type: step
|
||||||
:type,
|
# number: 3
|
||||||
:required,
|
# title: Add the field name to attribute map
|
||||||
:value,
|
# description: The attribute map serves as a global registry for field attributes. Set the
|
||||||
:label,
|
# key as the attribute name and value as an array of properties. Use the properties according to
|
||||||
:description,
|
# your usecase. Here's a list and description of each of the properties.
|
||||||
:image,
|
# ```
|
||||||
:key,
|
# accessible: The attribute is set as a CustomWizard::Field attr_accessor
|
||||||
:validations,
|
# serializable: The attribute is serialized to the client
|
||||||
:min_length,
|
# permitted: The attribute is permitted in the admin controller
|
||||||
:max_length,
|
# mapped: The attribute is mapped and permitted (see above)
|
||||||
:char_counter,
|
# excluded: The attribute is not initialized in the constructor
|
||||||
:file_types,
|
# ```
|
||||||
:format,
|
##
|
||||||
:limit,
|
|
||||||
:property,
|
|
||||||
:content,
|
|
||||||
:preview_template,
|
|
||||||
:placeholder
|
|
||||||
|
|
||||||
attr_accessor :index,
|
def self.attribute_map
|
||||||
:step
|
{
|
||||||
|
raw: [],
|
||||||
|
id: [:serializable, :permitted],
|
||||||
|
index: [:accessible, :serializable, :permitted, :mapped],
|
||||||
|
type: [:serializable, :permitted],
|
||||||
|
step: [:accessible],
|
||||||
|
required: [:serializable, :permitted],
|
||||||
|
value: [:serializable],
|
||||||
|
description: [:serializable, :permitted],
|
||||||
|
image: [:serializable, :permitted],
|
||||||
|
key: [:permitted],
|
||||||
|
validations: [:serializable],
|
||||||
|
min_length: [:permitted],
|
||||||
|
max_length: [:serializable, :permitted],
|
||||||
|
char_counter: [:serializable, :permitted],
|
||||||
|
file_types: [:serializable, :permitted],
|
||||||
|
format: [:serializable, :permitted],
|
||||||
|
limit: [:serializable, :permitted],
|
||||||
|
property: [:serializable, :permitted],
|
||||||
|
# label is excluded so that it isn't initialized and the value
|
||||||
|
# returned by `label` method is used for serialization
|
||||||
|
label: [:excluded, :serializable, :permitted],
|
||||||
|
content: [:serializable, :permitted, :mapped],
|
||||||
|
prefill: [:permitted, :mapped],
|
||||||
|
condition: [:permitted, :mapped],
|
||||||
|
preview_template: [:serializable, :permitted, :mapped],
|
||||||
|
placeholder: [:serializable, :permitted, :mapped],
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.all_attributes
|
||||||
|
attribute_map.keys
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.included_attributes
|
||||||
|
all_attributes - excluded_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.type_attributes(type)
|
||||||
|
attribute_map.map { |attribute, props| props.include?(type.to_sym) ? attribute : nil }.compact
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.accessible_attributes
|
||||||
|
type_attributes(:accessible)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.excluded_attributes
|
||||||
|
type_attributes(:excluded)
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.readonly_attributes
|
||||||
|
included_attributes - accessible_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.serializable_attributes
|
||||||
|
type_attributes(:serializable)
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader *readonly_attributes
|
||||||
|
attr_accessor *accessible_attributes
|
||||||
|
|
||||||
def initialize(attrs)
|
def initialize(attrs)
|
||||||
|
attrs.each do |k, v|
|
||||||
|
if self.singleton_class.included_attributes.include?(k.to_sym)
|
||||||
|
instance_variable_set("@#{k}", v)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
@raw = attrs || {}
|
@raw = attrs || {}
|
||||||
@id = attrs[:id]
|
|
||||||
@index = attrs[:index]
|
|
||||||
@type = attrs[:type]
|
|
||||||
@required = !!attrs[:required]
|
@required = !!attrs[:required]
|
||||||
@value = attrs[:value] || default_value
|
@value = attrs[:value] || default_value
|
||||||
@description = attrs[:description]
|
|
||||||
@image = attrs[:image]
|
|
||||||
@key = attrs[:key]
|
|
||||||
@validations = attrs[:validations]
|
|
||||||
@min_length = attrs[:min_length]
|
|
||||||
@max_length = attrs[:max_length]
|
|
||||||
@char_counter = attrs[:char_counter]
|
|
||||||
@file_types = attrs[:file_types]
|
|
||||||
@format = attrs[:format]
|
|
||||||
@limit = attrs[:limit]
|
|
||||||
@property = attrs[:property]
|
|
||||||
@content = attrs[:content]
|
|
||||||
@preview_template = attrs[:preview_template]
|
|
||||||
@placeholder = attrs[:placeholder]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def label
|
def label
|
||||||
|
|
|
@ -3,25 +3,61 @@
|
||||||
class CustomWizard::Step
|
class CustomWizard::Step
|
||||||
include ActiveModel::SerializerSupport
|
include ActiveModel::SerializerSupport
|
||||||
|
|
||||||
attr_reader :id,
|
def self.attribute_map
|
||||||
:updater
|
{
|
||||||
|
id: [:serializable, :permitted],
|
||||||
|
updater: [],
|
||||||
|
index: [:accessible, :serializable, :permitted],
|
||||||
|
title: [:accessible, :serializable, :permitted],
|
||||||
|
description: [:accessible, :serializable],
|
||||||
|
key: [:accessible, :permitted],
|
||||||
|
permitted: [:accessible, :serializable],
|
||||||
|
permitted_message: [:accessible, :serializable],
|
||||||
|
fields: [:accessible],
|
||||||
|
next: [:accessible, :serializable],
|
||||||
|
previous: [:accessible, :serializable],
|
||||||
|
banner: [:accessible, :serializable, :permitted],
|
||||||
|
disabled: [:accessible],
|
||||||
|
description_vars: [:accessible],
|
||||||
|
last_step: [:accessible],
|
||||||
|
force_final: [:accessible],
|
||||||
|
conditional_final_step: [:accessible],
|
||||||
|
wizard: [:accessible],
|
||||||
|
raw_description: [:permitted],
|
||||||
|
required_data_message: [:permitted],
|
||||||
|
required_data: [:permitted, :mapped],
|
||||||
|
permitted_params: [:permitted, :mapped],
|
||||||
|
condition: [:permitted, :mapped],
|
||||||
|
final: [:serializable]
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
attr_accessor :index,
|
def self.type_attributes(type)
|
||||||
:title,
|
attribute_map.map { |attribute, props| props.include?(type.to_sym) ? attribute : nil }.compact
|
||||||
:description,
|
end
|
||||||
:key,
|
|
||||||
:permitted,
|
def self.all_attributes
|
||||||
:permitted_message,
|
attribute_map.keys
|
||||||
:fields,
|
end
|
||||||
:next,
|
|
||||||
:previous,
|
def self.accessible_attributes
|
||||||
:banner,
|
type_attributes(:accessible)
|
||||||
:disabled,
|
end
|
||||||
:description_vars,
|
|
||||||
:last_step,
|
def self.included_attributes
|
||||||
:force_final,
|
all_attributes - excluded_attributes
|
||||||
:conditional_final_step,
|
end
|
||||||
:wizard
|
|
||||||
|
def self.readonly_attributes
|
||||||
|
included_attributes - accessible_attributes
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.excluded_attributes
|
||||||
|
type_attributes(:excluded)
|
||||||
|
end
|
||||||
|
|
||||||
|
attr_reader *readonly_attributes
|
||||||
|
attr_accessor *accessible_attributes
|
||||||
|
|
||||||
def initialize(id)
|
def initialize(id)
|
||||||
@id = id
|
@id = id
|
||||||
|
|
|
@ -8,6 +8,15 @@ class CustomWizard::TemplateValidator
|
||||||
@opts = opts
|
@opts = opts
|
||||||
end
|
end
|
||||||
|
|
||||||
|
##
|
||||||
|
# type: step
|
||||||
|
# number: 5
|
||||||
|
# title: Add a template validation (optional)
|
||||||
|
# description: If our new attribute requires validation of a value entered
|
||||||
|
# during administration of a wizard that should be handled here.
|
||||||
|
# Template validators are run before the template is saved to
|
||||||
|
# the database.
|
||||||
|
##
|
||||||
def perform
|
def perform
|
||||||
data = @data
|
data = @data
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,14 @@ require_dependency 'wizard/builder'
|
||||||
|
|
||||||
UserHistory.actions[:custom_wizard_step] = 1000
|
UserHistory.actions[:custom_wizard_step] = 1000
|
||||||
|
|
||||||
|
##
|
||||||
|
# type: step
|
||||||
|
# number: 6
|
||||||
|
# title: Add the parameter to the wizard model
|
||||||
|
# description: The template is loaded into the wizard model when it is built,
|
||||||
|
# our attribute has to be present, for it to build properly...
|
||||||
|
##
|
||||||
|
|
||||||
class CustomWizard::Wizard
|
class CustomWizard::Wizard
|
||||||
include ActiveModel::SerializerSupport
|
include ActiveModel::SerializerSupport
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,13 @@
|
||||||
# url: https://github.com/paviliondev/discourse-custom-wizard
|
# url: https://github.com/paviliondev/discourse-custom-wizard
|
||||||
# contact emails: angus@thepavilion.io
|
# contact emails: angus@thepavilion.io
|
||||||
|
|
||||||
|
## learning_unit
|
||||||
|
# unit: custom_wizard:templates_and_builder
|
||||||
|
# type: introduction
|
||||||
|
# title: Adding a new wizard field attribute.
|
||||||
|
# description: In this unit, we'll learn about creating, editing, validating
|
||||||
|
# and building wizard templates by adding a new field attribute.
|
||||||
|
##
|
||||||
gem 'liquid', '5.0.1', require: true
|
gem 'liquid', '5.0.1', require: true
|
||||||
register_asset 'stylesheets/common/wizard-admin.scss'
|
register_asset 'stylesheets/common/wizard-admin.scss'
|
||||||
register_asset 'stylesheets/common/wizard-mapper.scss'
|
register_asset 'stylesheets/common/wizard-mapper.scss'
|
||||||
|
|
|
@ -2,24 +2,7 @@
|
||||||
|
|
||||||
class CustomWizard::FieldSerializer < ::ApplicationSerializer
|
class CustomWizard::FieldSerializer < ::ApplicationSerializer
|
||||||
|
|
||||||
attributes :id,
|
attributes *CustomWizard::Field.serializable_attributes
|
||||||
:index,
|
|
||||||
:type,
|
|
||||||
:required,
|
|
||||||
:value,
|
|
||||||
:label,
|
|
||||||
:placeholder,
|
|
||||||
:description,
|
|
||||||
:image,
|
|
||||||
:file_types,
|
|
||||||
:format,
|
|
||||||
:limit,
|
|
||||||
:property,
|
|
||||||
:content,
|
|
||||||
:validations,
|
|
||||||
:max_length,
|
|
||||||
:char_counter,
|
|
||||||
:preview_template
|
|
||||||
|
|
||||||
def id
|
def id
|
||||||
object.id
|
object.id
|
||||||
|
|
Laden …
In neuem Issue referenzieren