Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-09 20:02:54 +01:00
Merge pull request #65 from paviliondev/text-counter
FEATURE: text length counter for text type fields
Dieser Commit ist enthalten in:
Commit
505043922e
14 geänderte Dateien mit 84 neuen und 10 gelöschten Zeilen
|
@ -21,7 +21,7 @@ export default Component.extend(UndoChanges, {
|
|||
showPrefill: or('isText', 'isCategory', 'isTag', 'isGroup', 'isDropdown'),
|
||||
showContent: or('isCategory', 'isTag', 'isGroup', 'isDropdown'),
|
||||
showLimit: or('isCategory', 'isTag'),
|
||||
showLengthControls: or('isText', 'isTextarea', 'isComposer'),
|
||||
isTextType: or('isText', 'isTextarea', 'isComposer'),
|
||||
categoryPropertyTypes: selectKitContent(['id', 'slug']),
|
||||
showAdvanced: alias('field.type'),
|
||||
messageUrl: 'https://thepavilion.io/t/2809',
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
url=messageUrl
|
||||
component='field'}}
|
||||
|
||||
{{#if showLengthControls}}
|
||||
{{#if isTextType}}
|
||||
<div class="setting">
|
||||
<div class="setting-label">
|
||||
<label>{{i18n 'admin.wizard.field.min_length'}}</label>
|
||||
|
@ -98,6 +98,19 @@
|
|||
class="small"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="setting">
|
||||
<div class="setting-label">
|
||||
<label>{{i18n 'admin.wizard.field.char_counter'}}</label>
|
||||
</div>
|
||||
|
||||
<div class="setting-value">
|
||||
<span>{{i18n 'admin.wizard.field.char_counter_placeholder'}}</span>
|
||||
{{input
|
||||
type="checkbox"
|
||||
checked=field.char_counter}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if isUpload}}
|
||||
|
|
15
assets/javascripts/wizard/helpers/char-counter.js.es6
Normale Datei
15
assets/javascripts/wizard/helpers/char-counter.js.es6
Normale Datei
|
@ -0,0 +1,15 @@
|
|||
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||
import I18n from "I18n";
|
||||
|
||||
export default registerUnbound("char-counter", function(body, maxLength) {
|
||||
let bodyLength = body ? body.length : 0;
|
||||
let finalString;
|
||||
|
||||
if (maxLength) {
|
||||
finalString = `<div class="body-length">${bodyLength} / ${I18n.t('wizard.x_characters', { count: parseInt(maxLength) })}</div>`;
|
||||
} else {
|
||||
finalString = `<div class="body-length">${I18n.t('wizard.x_characters', { count: parseInt(bodyLength) })}</div>`;
|
||||
}
|
||||
|
||||
return new Handlebars.SafeString(finalString);
|
||||
});
|
|
@ -1,4 +1,5 @@
|
|||
import { dasherize } from "@ember/string";
|
||||
import discourseComputed from "discourse-common/utils/decorators";
|
||||
|
||||
export default {
|
||||
name: "custom-wizard-field",
|
||||
|
@ -15,6 +16,11 @@ export default {
|
|||
FieldComponent.reopen({
|
||||
classNameBindings: ["field.id"],
|
||||
|
||||
@discourseComputed("field.type")
|
||||
textType(fieldType) {
|
||||
return ['text', 'textarea'].includes(fieldType);
|
||||
},
|
||||
|
||||
cookedDescription: function () {
|
||||
return cook(this.get("field.description"));
|
||||
}.property("field.description"),
|
||||
|
|
|
@ -7,6 +7,12 @@
|
|||
togglePreview=(action "togglePreview")
|
||||
afterRefresh=(action "afterRefresh")}}
|
||||
|
||||
<div class="bottom-bar">
|
||||
<button class='wizard-btn toggle-preview' {{action 'togglePreview'}}>
|
||||
<span class="d-button-label">{{wizard-i18n togglePreviewLabel}}</span>
|
||||
</button>
|
||||
</button>
|
||||
|
||||
{{#if field.char_counter}}
|
||||
{{char-counter field.value field.max_length}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
@ -16,6 +16,12 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if field.char_counter}}
|
||||
{{#if textType}}
|
||||
{{char-counter field.value field.max_length}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{#if field.errorDescription}}
|
||||
<div class='field-error-description'>{{{field.errorDescription}}}</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -80,3 +80,6 @@ textarea {
|
|||
}
|
||||
}
|
||||
|
||||
.body-length {
|
||||
text-align: right;
|
||||
}
|
||||
|
|
|
@ -50,10 +50,6 @@
|
|||
display: none;
|
||||
}
|
||||
|
||||
.custom-wizard .wizard-field-composer .toggle-preview {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.d-editor-textarea-wrapper,
|
||||
.d-editor-preview-wrapper {
|
||||
background-color: var(--secondary);
|
||||
|
@ -230,3 +226,10 @@
|
|||
bottom: -40px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.bottom-bar {
|
||||
display: flex;
|
||||
justify-content:space-between;
|
||||
margin-top: 20px;
|
||||
align-items: center;
|
||||
}
|
||||
|
|
|
@ -166,6 +166,8 @@ en:
|
|||
min_length_placeholder: "Minimum length in characters"
|
||||
max_length: "Max Length"
|
||||
max_length_placeholder: "Maximum length in characters"
|
||||
char_counter: "Character Counter"
|
||||
char_counter_placeholder: "Display Character Counter"
|
||||
file_types: "File Types"
|
||||
limit: "Limit"
|
||||
property: "Property"
|
||||
|
@ -469,6 +471,9 @@ en:
|
|||
requires_login: "You need to be logged in to access this wizard."
|
||||
reset: "Reset this wizard."
|
||||
step_not_permitted: "You're not permitted to view this step."
|
||||
x_characters:
|
||||
one: "%{count} Character"
|
||||
other: "%{count} Characters"
|
||||
|
||||
wizard_composer:
|
||||
show_preview: "Preview Post"
|
||||
|
|
|
@ -98,6 +98,7 @@ class CustomWizard::AdminWizardController < CustomWizard::AdminController
|
|||
:type,
|
||||
:min_length,
|
||||
:max_length,
|
||||
:char_counter,
|
||||
:file_types,
|
||||
:format,
|
||||
:limit,
|
||||
|
|
|
@ -6,6 +6,7 @@ module CustomWizardFieldExtension
|
|||
:key,
|
||||
:min_length,
|
||||
:max_length,
|
||||
:char_counter,
|
||||
:file_types,
|
||||
:format,
|
||||
:limit,
|
||||
|
@ -21,6 +22,7 @@ module CustomWizardFieldExtension
|
|||
@key = attrs[:key]
|
||||
@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]
|
||||
|
|
|
@ -160,6 +160,7 @@ class CustomWizard::Builder
|
|||
params[:key] = field_template['key'] if field_template['key']
|
||||
params[:min_length] = field_template['min_length'] if field_template['min_length']
|
||||
params[:max_length] = field_template['max_length'] if field_template['max_length']
|
||||
params[:char_counter] = field_template['char_counter'] if field_template['char_counter']
|
||||
params[:value] = prefill_field(field_template, step_template)
|
||||
|
||||
if !build_opts[:reset] && (submission = @wizard.current_submission)
|
||||
|
|
|
@ -4,16 +4,19 @@ class CustomWizard::Field
|
|||
text: {
|
||||
min_length: nil,
|
||||
max_length: nil,
|
||||
prefill: nil
|
||||
prefill: nil,
|
||||
char_counter: nil
|
||||
},
|
||||
textarea: {
|
||||
min_length: nil,
|
||||
max_length: nil,
|
||||
prefill: nil
|
||||
prefill: nil,
|
||||
char_counter: nil
|
||||
},
|
||||
composer: {
|
||||
min_length: nil,
|
||||
max_length: nil,
|
||||
char_counter: nil
|
||||
},
|
||||
text_only: {},
|
||||
date: {
|
||||
|
|
|
@ -8,6 +8,8 @@ class CustomWizard::FieldSerializer < ::WizardFieldSerializer
|
|||
:limit,
|
||||
:property,
|
||||
:content,
|
||||
:max_length,
|
||||
:char_counter,
|
||||
:number
|
||||
|
||||
def label
|
||||
|
@ -55,7 +57,15 @@ class CustomWizard::FieldSerializer < ::WizardFieldSerializer
|
|||
def include_choices?
|
||||
object.choices.present?
|
||||
end
|
||||
|
||||
|
||||
def max_length
|
||||
object.max_length
|
||||
end
|
||||
|
||||
def char_counter
|
||||
object.char_counter
|
||||
end
|
||||
|
||||
def number
|
||||
object.number
|
||||
end
|
||||
|
|
Laden …
In neuem Issue referenzieren