2020-10-02 06:40:10 +02:00
|
|
|
import { dasherize } from "@ember/string";
|
2021-01-16 12:57:38 +01:00
|
|
|
import discourseComputed from "discourse-common/utils/decorators";
|
2020-10-02 06:40:10 +02:00
|
|
|
|
|
|
|
export default {
|
|
|
|
name: "custom-wizard-field",
|
|
|
|
initialize(app) {
|
|
|
|
if (window.location.pathname.indexOf("/w/") < 0) return;
|
2021-03-28 11:06:49 +02:00
|
|
|
|
2020-10-02 06:40:10 +02:00
|
|
|
const FieldComponent = requirejs("wizard/components/wizard-field").default;
|
|
|
|
const FieldModel = requirejs("wizard/models/wizard-field").default;
|
2021-03-28 11:06:49 +02:00
|
|
|
const { cook } = requirejs(
|
|
|
|
"discourse/plugins/discourse-custom-wizard/wizard/lib/text-lite"
|
|
|
|
);
|
2020-10-02 06:40:10 +02:00
|
|
|
const DEditor = requirejs("discourse/components/d-editor").default;
|
|
|
|
const { clipboardHelpers } = requirejs("discourse/lib/utilities");
|
|
|
|
const { toMarkdown } = requirejs("discourse/lib/to-markdown");
|
2021-03-29 08:17:57 +02:00
|
|
|
|
|
|
|
/*
|
|
|
|
* unit: custom_wizard:templates_and_builder
|
|
|
|
* type: step
|
|
|
|
* number: 9
|
|
|
|
* 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.
|
|
|
|
*/
|
2020-10-02 06:40:10 +02:00
|
|
|
FieldComponent.reopen({
|
|
|
|
classNameBindings: ["field.id"],
|
|
|
|
|
2021-01-16 12:57:38 +01:00
|
|
|
@discourseComputed("field.type")
|
|
|
|
textType(fieldType) {
|
2021-03-28 11:06:49 +02:00
|
|
|
return ["text", "textarea"].includes(fieldType);
|
2021-01-16 12:57:38 +01:00
|
|
|
},
|
2021-01-08 08:12:58 +01:00
|
|
|
|
2020-10-02 06:40:10 +02:00
|
|
|
cookedDescription: function () {
|
|
|
|
return cook(this.get("field.description"));
|
|
|
|
}.property("field.description"),
|
|
|
|
|
|
|
|
inputComponentName: function () {
|
|
|
|
const type = this.get("field.type");
|
|
|
|
const id = this.get("field.id");
|
|
|
|
if (["text_only"].includes(type)) return false;
|
|
|
|
return dasherize(type === "component" ? id : `wizard-field-${type}`);
|
|
|
|
}.property("field.type", "field.id"),
|
|
|
|
});
|
|
|
|
|
|
|
|
const StandardFieldValidation = [
|
|
|
|
"text",
|
|
|
|
"number",
|
|
|
|
"textarea",
|
|
|
|
"dropdown",
|
|
|
|
"tag",
|
|
|
|
"image",
|
|
|
|
"user_selector",
|
|
|
|
"text_only",
|
|
|
|
"composer",
|
|
|
|
"category",
|
|
|
|
"group",
|
|
|
|
"date",
|
|
|
|
"time",
|
|
|
|
"date_time",
|
|
|
|
];
|
|
|
|
|
|
|
|
FieldModel.reopen({
|
|
|
|
check() {
|
|
|
|
if (this.customCheck) {
|
|
|
|
return this.customCheck();
|
|
|
|
}
|
|
|
|
|
|
|
|
let valid = this.valid;
|
|
|
|
|
|
|
|
if (!this.required) {
|
|
|
|
this.setValid(true);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
const val = this.get("value");
|
|
|
|
const type = this.get("type");
|
|
|
|
|
|
|
|
if (type === "checkbox") {
|
|
|
|
valid = val;
|
|
|
|
} else if (type === "upload") {
|
|
|
|
valid = val && val.id > 0;
|
|
|
|
} else if (StandardFieldValidation.indexOf(type) > -1) {
|
|
|
|
valid = val && val.toString().length > 0;
|
|
|
|
} else if (type === "url") {
|
|
|
|
valid = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.setValid(valid);
|
|
|
|
|
|
|
|
return valid;
|
|
|
|
},
|
|
|
|
});
|
2021-03-28 11:06:49 +02:00
|
|
|
|
2020-10-02 06:40:10 +02:00
|
|
|
const isInside = (text, regex) => {
|
|
|
|
const matches = text.match(regex);
|
|
|
|
return matches && matches.length % 2;
|
|
|
|
};
|
2021-03-28 11:06:49 +02:00
|
|
|
|
2020-10-02 06:40:10 +02:00
|
|
|
DEditor.reopen({
|
|
|
|
isComposer: true,
|
2021-03-28 11:06:49 +02:00
|
|
|
|
2020-10-02 06:40:10 +02:00
|
|
|
didInsertElement() {
|
|
|
|
this._super();
|
|
|
|
if (this.wizardComposerEvents) {
|
2021-03-28 11:06:49 +02:00
|
|
|
this.appEvents.on(
|
|
|
|
"wizard-editor:insert-text",
|
|
|
|
this,
|
|
|
|
"_wizardInsertText"
|
|
|
|
);
|
|
|
|
this.appEvents.on(
|
|
|
|
"wizard-editor:replace-text",
|
|
|
|
this,
|
|
|
|
"_wizardReplaceText"
|
|
|
|
);
|
2020-10-02 06:40:10 +02:00
|
|
|
}
|
|
|
|
},
|
2021-03-28 11:06:49 +02:00
|
|
|
|
2020-10-02 06:40:10 +02:00
|
|
|
_wizardInsertText(args = {}) {
|
|
|
|
if (args.fieldId === this.fieldId) {
|
|
|
|
this._insertText(args.text, args.options);
|
|
|
|
}
|
|
|
|
},
|
2021-03-28 11:06:49 +02:00
|
|
|
|
2020-10-02 06:40:10 +02:00
|
|
|
_wizardReplaceText(args = {}) {
|
|
|
|
if (args.fieldId === this.fieldId) {
|
2021-03-28 11:06:49 +02:00
|
|
|
this._replaceText(args.oldVal, args.newVal, (args.opts = {}));
|
2020-10-02 06:40:10 +02:00
|
|
|
}
|
|
|
|
},
|
2021-03-28 11:06:49 +02:00
|
|
|
|
2020-10-02 06:40:10 +02:00
|
|
|
paste(e) {
|
|
|
|
if (!$(".d-editor-input").is(":focus")) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const isComposer = this.isComposer;
|
|
|
|
let { clipboard, canPasteHtml, canUpload } = clipboardHelpers(e, {
|
|
|
|
siteSettings: this.siteSettings,
|
|
|
|
canUpload: isComposer,
|
|
|
|
});
|
|
|
|
|
|
|
|
let plainText = clipboard.getData("text/plain");
|
|
|
|
let html = clipboard.getData("text/html");
|
|
|
|
let handled = false;
|
|
|
|
|
|
|
|
const { pre, lineVal } = this._getSelected(null, { lineVal: true });
|
|
|
|
const isInlinePasting = pre.match(/[^\n]$/);
|
|
|
|
const isCodeBlock = isInside(pre, /(^|\n)```/g);
|
|
|
|
|
|
|
|
if (
|
|
|
|
plainText &&
|
|
|
|
this.siteSettings.enable_rich_text_paste &&
|
|
|
|
!isInlinePasting &&
|
|
|
|
!isCodeBlock
|
|
|
|
) {
|
|
|
|
plainText = plainText.trim().replace(/\r/g, "");
|
|
|
|
const table = this._extractTable(plainText);
|
|
|
|
if (table) {
|
|
|
|
this.appEvents.trigger("wizard-editor:insert-text", {
|
|
|
|
fieldId: this.fieldId,
|
2021-03-28 11:06:49 +02:00
|
|
|
text: table,
|
2020-10-02 06:40:10 +02:00
|
|
|
});
|
|
|
|
handled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (canPasteHtml && plainText) {
|
|
|
|
if (isInlinePasting) {
|
|
|
|
canPasteHtml = !(
|
|
|
|
lineVal.match(/^```/) ||
|
|
|
|
isInside(pre, /`/g) ||
|
|
|
|
lineVal.match(/^ /)
|
|
|
|
);
|
|
|
|
} else {
|
|
|
|
canPasteHtml = !isCodeBlock;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (canPasteHtml && !handled) {
|
|
|
|
let markdown = toMarkdown(html);
|
|
|
|
|
|
|
|
if (!plainText || plainText.length < markdown.length) {
|
|
|
|
if (isInlinePasting) {
|
|
|
|
markdown = markdown.replace(/^#+/, "").trim();
|
|
|
|
markdown = pre.match(/\S$/) ? ` ${markdown}` : markdown;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.appEvents.trigger("composer:insert-text", {
|
|
|
|
fieldId: this.fieldId,
|
2021-03-28 11:06:49 +02:00
|
|
|
text: markdown,
|
2020-10-02 06:40:10 +02:00
|
|
|
});
|
|
|
|
handled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (handled || (canUpload && !plainText)) {
|
|
|
|
e.preventDefault();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
2021-03-28 11:06:49 +02:00
|
|
|
},
|
|
|
|
};
|