Spiegel von
https://github.com/paviliondev/discourse-custom-wizard.git
synchronisiert 2024-11-25 18:50:27 +01:00
completed categories and date after filters
Dieser Commit ist enthalten in:
Ursprung
ffd2101a30
Commit
77ca946745
13 geänderte Dateien mit 402 neuen und 17 gelöschten Zeilen
|
@ -1,4 +1,7 @@
|
||||||
import Component from "@ember/component";
|
import Component from "@ember/component";
|
||||||
|
import EmberObject from "@ember/object";
|
||||||
|
import { cloneJSON } from "discourse-common/lib/object";
|
||||||
|
import Category from "discourse/models/category";
|
||||||
|
|
||||||
export default Component.extend({
|
export default Component.extend({
|
||||||
init(){
|
init(){
|
||||||
|
@ -13,5 +16,20 @@ export default Component.extend({
|
||||||
|
|
||||||
this.set('field.validations', EmberObject.create(validations));
|
this.set('field.validations', EmberObject.create(validations));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const validationBuffer = cloneJSON(this.get('field.validations'));
|
||||||
|
let bufferCategories;
|
||||||
|
if( validationBuffer.similar_topics && (bufferCategories = validationBuffer.similar_topics.categories)) {
|
||||||
|
const categories = Category.findByIds(bufferCategories);
|
||||||
|
validationBuffer.similar_topics.categories = categories;
|
||||||
|
}
|
||||||
|
this.set('validationBuffer', validationBuffer);
|
||||||
|
},
|
||||||
|
|
||||||
|
actions: {
|
||||||
|
updateValidationCategories(name, validation, categories) {
|
||||||
|
this.set(`validationBuffer.${name}.categories`, categories);
|
||||||
|
this.set(`field.validations.${name}.categories`, categories.map(category => category.id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -4,8 +4,25 @@
|
||||||
{{#each-in field.validations as |name props|}}
|
{{#each-in field.validations as |name props|}}
|
||||||
<span class="setting-title">
|
<span class="setting-title">
|
||||||
{{input type="checkbox" checked=props.status }}
|
{{input type="checkbox" checked=props.status }}
|
||||||
{{i18n (concat 'admin.wizard.field.validations.' name)}}
|
{{i18n (concat 'admin.wizard.field.validations.' name) }}
|
||||||
</span>
|
</span>
|
||||||
|
<div class="setting full">
|
||||||
|
<span class="setting-label">{{i18n 'admin.wizard.field.validations.categories'}}</span>
|
||||||
|
<div class="setting-value">
|
||||||
|
{{category-selector
|
||||||
|
categories=(get this (concat 'validationBuffer.' name '.categories'))
|
||||||
|
onChange=(action 'updateValidationCategories' name props) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="setting full">
|
||||||
|
<span class="setting-label">{{i18n 'admin.wizard.field.validations.date_after'}}</span>
|
||||||
|
<div class="setting-value">
|
||||||
|
{{date-picker-past
|
||||||
|
value=(readonly props.date_after)
|
||||||
|
containerId="date-container"
|
||||||
|
onSelect=(action (mut props.date_after))}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{{radio-button name=(concat name field.id) value="above" selection=props.position}} {{i18n 'admin.wizard.field.validations.above'}}
|
{{radio-button name=(concat name field.id) value="above" selection=props.position}} {{i18n 'admin.wizard.field.validations.above'}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -144,3 +144,29 @@
|
||||||
//= require_tree ./wizard/models
|
//= require_tree ./wizard/models
|
||||||
//= require_tree ./wizard/routes
|
//= require_tree ./wizard/routes
|
||||||
//= require_tree ./wizard/templates
|
//= require_tree ./wizard/templates
|
||||||
|
|
||||||
|
//= require discourse/app/components/mount-widget
|
||||||
|
//= require discourse/app/widgets/widget
|
||||||
|
//= require discourse/app/widgets/hooks
|
||||||
|
//= require discourse/app/widgets/decorator-helper
|
||||||
|
//= require discourse/app/widgets/connector
|
||||||
|
//= require discourse/app/widgets/post-cooked
|
||||||
|
//= require discourse/app/lib/highlight-html
|
||||||
|
//= require discourse/app/lib/highlight-search
|
||||||
|
//= require discourse/app/lib/constants
|
||||||
|
//= require discourse/app/lib/click-track
|
||||||
|
//= require discourse/app/helpers/loading-spinner
|
||||||
|
//= require discourse/app/widgets/raw-html
|
||||||
|
//= require discourse/app/lib/dirty-keys
|
||||||
|
|
||||||
|
//= require discourse/app/widgets/search-menu
|
||||||
|
//= require discourse/app/widgets/search-menu-results
|
||||||
|
//= require discourse/app/widgets/post
|
||||||
|
//= require discourse/app/helpers/node
|
||||||
|
//= require discourse/app/widgets/post-stream
|
||||||
|
|
||||||
|
//= require discourse/app/lib/posts-with-placeholders
|
||||||
|
//= require discourse/app/lib/transform-post
|
||||||
|
//= require discourse/app/helpers/category-link
|
||||||
|
//= require discourse/app/lib/render-tags
|
||||||
|
//= require discourse/app/helpers/topic-status-icons
|
|
@ -1,20 +1,53 @@
|
||||||
import WizardFieldValidator from "../../wizard/components/validator";
|
import WizardFieldValidator from "../../wizard/components/validator";
|
||||||
import { ajax } from "discourse/lib/ajax";
|
import { deepMerge } from "discourse-common/lib/object";
|
||||||
import { getToken } from "wizard/lib/ajax";
|
import { observes } from "discourse-common/utils/decorators";
|
||||||
import { getOwner } from "discourse-common/lib/get-owner";
|
import { cancel, later } from "@ember/runloop";
|
||||||
import discourseComputed from "discourse-common/utils/decorators";
|
import { A } from '@ember/array';
|
||||||
|
import EmberObject from "@ember/object";
|
||||||
|
|
||||||
export default WizardFieldValidator.extend({
|
export default WizardFieldValidator.extend({
|
||||||
validMessageKey: 'hello',
|
validMessageKey: 'hello',
|
||||||
invalidMessageKey: 'world',
|
invalidMessageKey: 'world',
|
||||||
|
similarTopics: [],
|
||||||
|
|
||||||
validate() {
|
validate() {
|
||||||
this.backendValidate({title: this.get("field.value")}).then(response => {
|
},
|
||||||
console.log(response)
|
@observes("field.value")
|
||||||
})
|
customValidate(){
|
||||||
|
const lastKeyUp = new Date();
|
||||||
|
this._lastKeyUp = lastKeyUp;
|
||||||
|
|
||||||
|
// One second from now, check to see if the last key was hit when
|
||||||
|
// we recorded it. If it was, the user paused typing.
|
||||||
|
cancel(this._lastKeyTimeout);
|
||||||
|
this._lastKeyTimeout = later(() => {
|
||||||
|
if (lastKeyUp !== this._lastKeyUp) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateSimilarTopics();
|
||||||
|
}, 1000);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
updateSimilarTopics(){
|
||||||
|
this.backendValidate({
|
||||||
|
title: this.get("field.value"),
|
||||||
|
categories: this.get('validation.categories'),
|
||||||
|
date_after: this.get('validation.date_after')
|
||||||
|
}).then((result) => {
|
||||||
|
const similarTopics = A(deepMerge(result['topics'], result['similar_topics']));
|
||||||
|
similarTopics.forEach(function(topic, index) {
|
||||||
|
similarTopics[index] = EmberObject.create(topic);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.set('similarTopics', similarTopics);
|
||||||
|
});
|
||||||
|
},
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
closeMessage(){}
|
||||||
}
|
}
|
||||||
});
|
});
|
|
@ -17,8 +17,7 @@ export default Component.extend({
|
||||||
// set a function that can be called as often as it need to
|
// set a function that can be called as often as it need to
|
||||||
// from the derived component
|
// from the derived component
|
||||||
this.backendValidate = (params) => {
|
this.backendValidate = (params) => {
|
||||||
return ajax('/w/realtime_validation', {
|
return ajax('/realtime_validations', {
|
||||||
type: 'put',
|
|
||||||
data: {
|
data: {
|
||||||
validation: this.get('name'),
|
validation: this.get('name'),
|
||||||
authenticity_token: getToken(),
|
authenticity_token: getToken(),
|
||||||
|
|
276
assets/javascripts/wizard/initializers/register-widgets.js.es6
Normale Datei
276
assets/javascripts/wizard/initializers/register-widgets.js.es6
Normale Datei
|
@ -0,0 +1,276 @@
|
||||||
|
import { escapeExpression, formatUsername } from "discourse/lib/utilities";
|
||||||
|
import I18n from "I18n";
|
||||||
|
import RawHtml from "discourse/widgets/raw-html";
|
||||||
|
import { avatarImg } from "discourse/widgets/post";
|
||||||
|
import { createWidget } from "discourse/widgets/widget";
|
||||||
|
import { dateNode } from "discourse/helpers/node";
|
||||||
|
import { emojiUnescape } from "discourse/lib/text";
|
||||||
|
import { h } from "virtual-dom";
|
||||||
|
import highlightSearch from "discourse/lib/highlight-search";
|
||||||
|
import { iconNode } from "discourse-common/lib/icon-library";
|
||||||
|
import renderTag from "discourse/lib/render-tag";
|
||||||
|
import DiscourseURL from "discourse/lib/url";
|
||||||
|
import getURL from "discourse-common/lib/get-url";
|
||||||
|
import { wantsNewWindow } from "discourse/lib/intercept-click";
|
||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
|
import renderTags from "discourse/lib/render-tags";
|
||||||
|
import TopicStatusIcons from "discourse/helpers/topic-status-icons";
|
||||||
|
|
||||||
|
class Highlighted extends RawHtml {
|
||||||
|
constructor(html, term) {
|
||||||
|
super({ html: `<span>${html}</span>` });
|
||||||
|
this.term = term;
|
||||||
|
}
|
||||||
|
|
||||||
|
decorate($html) {
|
||||||
|
highlightSearch($html[0], this.term);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "wizard-register-widgets",
|
||||||
|
after: "custom-routes",
|
||||||
|
initialize(app) {
|
||||||
|
if (window.location.pathname.indexOf("/w/") < 0) return;
|
||||||
|
|
||||||
|
createWidget("link", {
|
||||||
|
tagName: "a",
|
||||||
|
|
||||||
|
href(attrs) {
|
||||||
|
const route = attrs.route;
|
||||||
|
if (route) {
|
||||||
|
const router = this.register.lookup("router:main");
|
||||||
|
if (router && router._routerMicrolib) {
|
||||||
|
const params = [route];
|
||||||
|
if (attrs.model) {
|
||||||
|
params.push(attrs.model);
|
||||||
|
}
|
||||||
|
return getURL(
|
||||||
|
router._routerMicrolib.generate.apply(router._routerMicrolib, params)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return getURL(attrs.href);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
buildClasses(attrs) {
|
||||||
|
const result = [];
|
||||||
|
result.push("widget-link");
|
||||||
|
if (attrs.className) {
|
||||||
|
result.push(attrs.className);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
buildAttributes(attrs) {
|
||||||
|
const ret = {
|
||||||
|
href: this.href(attrs),
|
||||||
|
title: attrs.title
|
||||||
|
? I18n.t(attrs.title, attrs.titleOptions)
|
||||||
|
: this.label(attrs),
|
||||||
|
};
|
||||||
|
if (attrs.attributes) {
|
||||||
|
Object.keys(attrs.attributes).forEach(
|
||||||
|
(k) => (ret[k] = attrs.attributes[k])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
|
||||||
|
label(attrs) {
|
||||||
|
if (attrs.labelCount && attrs.count) {
|
||||||
|
return I18n.t(attrs.labelCount, { count: attrs.count });
|
||||||
|
}
|
||||||
|
return attrs.rawLabel || (attrs.label ? I18n.t(attrs.label) : "");
|
||||||
|
},
|
||||||
|
|
||||||
|
html(attrs) {
|
||||||
|
if (attrs.contents) {
|
||||||
|
return attrs.contents();
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = [];
|
||||||
|
if (attrs.icon) {
|
||||||
|
if (attrs.alt) {
|
||||||
|
let icon = iconNode(attrs.icon);
|
||||||
|
icon.properties.attributes["alt"] = I18n.t(attrs.alt);
|
||||||
|
icon.properties.attributes["aria-hidden"] = false;
|
||||||
|
result.push(icon);
|
||||||
|
} else {
|
||||||
|
result.push(iconNode(attrs.icon));
|
||||||
|
}
|
||||||
|
result.push(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!attrs.hideLabel) {
|
||||||
|
let label = this.label(attrs);
|
||||||
|
|
||||||
|
if (attrs.omitSpan) {
|
||||||
|
result.push(label);
|
||||||
|
} else {
|
||||||
|
result.push(h("span.d-label", label));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentUser = this.currentUser;
|
||||||
|
if (currentUser && attrs.badgeCount) {
|
||||||
|
const val = parseInt(currentUser.get(attrs.badgeCount), 10);
|
||||||
|
if (val > 0) {
|
||||||
|
const title = attrs.badgeTitle ? I18n.t(attrs.badgeTitle) : "";
|
||||||
|
result.push(" ");
|
||||||
|
result.push(
|
||||||
|
h(
|
||||||
|
"span.badge-notification",
|
||||||
|
{
|
||||||
|
className: attrs.badgeClass,
|
||||||
|
attributes: { title },
|
||||||
|
},
|
||||||
|
val
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
|
||||||
|
click(e) {
|
||||||
|
if (this.attrs.attributes && this.attrs.attributes.target === "_blank") {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wantsNewWindow(e)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
if (this.attrs.action) {
|
||||||
|
e.preventDefault();
|
||||||
|
return this.sendWidgetAction(this.attrs.action, this.attrs.actionParam);
|
||||||
|
} else {
|
||||||
|
this.sendWidgetEvent("linkClicked", this.attrs);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DiscourseURL.routeToTag($(e.target).closest("a")[0]);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
createWidget("topic-status", {
|
||||||
|
tagName: "div.topic-statuses",
|
||||||
|
|
||||||
|
html(attrs) {
|
||||||
|
const topic = attrs.topic;
|
||||||
|
const canAct = this.currentUser && !attrs.disableActions;
|
||||||
|
|
||||||
|
const result = [];
|
||||||
|
TopicStatusIcons.render(topic, function (name, key) {
|
||||||
|
const iconArgs = key === "unpinned" ? { class: "unpinned" } : null;
|
||||||
|
const icon = iconNode(name, iconArgs);
|
||||||
|
|
||||||
|
const attributes = {
|
||||||
|
title: escapeExpression(I18n.t(`topic_statuses.${key}.help`)),
|
||||||
|
};
|
||||||
|
result.push(h(`${canAct ? "a" : "span"}.topic-status`, attributes, icon));
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
createSearchResult({
|
||||||
|
type: "topic",
|
||||||
|
linkField: "url",
|
||||||
|
builder(result, term) {
|
||||||
|
const topic = result;
|
||||||
|
|
||||||
|
const firstLine = [
|
||||||
|
this.attach("topic-status", { topic, disableActions: true }),
|
||||||
|
h(
|
||||||
|
"span.topic-title",
|
||||||
|
{ attributes: { "data-topic-id": topic.id } },
|
||||||
|
this.siteSettings.use_pg_headlines_for_excerpt &&
|
||||||
|
result.topic_title_headline
|
||||||
|
? new RawHtml({
|
||||||
|
html: `<span>${emojiUnescape(
|
||||||
|
result.topic_title_headline
|
||||||
|
)}</span>`,
|
||||||
|
})
|
||||||
|
: new Highlighted(topic.fancy_title, term)
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
const secondLine = [
|
||||||
|
// this.attach("category-link", {
|
||||||
|
// category: topic.category,
|
||||||
|
// link: false,
|
||||||
|
// }),
|
||||||
|
];
|
||||||
|
// if (this.siteSettings.tagging_enabled) {
|
||||||
|
// secondLine.push(
|
||||||
|
// this.attach("discourse-tags", { topic, tagName: "span" })
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
|
||||||
|
const link = h("span.topic", [
|
||||||
|
h("div.first-line", firstLine),
|
||||||
|
h("div.second-line", secondLine),
|
||||||
|
]);
|
||||||
|
|
||||||
|
return postResult.call(this, result, link, term);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createSearchResult({ type, linkField, builder }) {
|
||||||
|
return createWidget(`search-result-${type}`, {
|
||||||
|
tagName: "ul.list",
|
||||||
|
|
||||||
|
html(attrs) {
|
||||||
|
return attrs.results.map((r) => {
|
||||||
|
let searchResultId;
|
||||||
|
|
||||||
|
if (type === "topic") {
|
||||||
|
searchResultId = r.topic_id;
|
||||||
|
} else {
|
||||||
|
searchResultId = r.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return h(
|
||||||
|
"li.item",
|
||||||
|
this.attach("link", {
|
||||||
|
href: r[linkField],
|
||||||
|
contents: () => builder.call(this, r, attrs.term),
|
||||||
|
className: "search-link",
|
||||||
|
searchResultId,
|
||||||
|
searchResultType: type,
|
||||||
|
searchContextEnabled: attrs.searchContextEnabled,
|
||||||
|
searchLogId: attrs.searchLogId,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function postResult(result, link, term) {
|
||||||
|
const html = [link];
|
||||||
|
|
||||||
|
if (!this.site.mobileView) {
|
||||||
|
html.push(
|
||||||
|
h("span.blurb", [
|
||||||
|
dateNode(result.created_at),
|
||||||
|
h("span", " - "),
|
||||||
|
this.siteSettings.use_pg_headlines_for_excerpt
|
||||||
|
? new RawHtml({ html: `<span>${result.blurb}</span>` })
|
||||||
|
: new Highlighted(result.blurb, term),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return html;
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
{{#if similarTopics}}
|
||||||
|
<a href {{action 'closeMessage' message}} class="close">{{d-icon "times"}}</a>
|
||||||
|
<h3>{{i18n "composer.similar_topics"}}</h3>
|
||||||
|
|
||||||
|
|
||||||
|
<ul class="topics">
|
||||||
|
{{mount-widget widget="search-result-topic" args=(hash results=similarTopics)}}
|
||||||
|
</ul>
|
||||||
|
{{/if}}
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
{{#field-validators field=field as |validators|}}
|
{{#field-validators field=field as |validators|}}
|
||||||
{{#if inputComponentName}}
|
{{#if inputComponentName}}
|
||||||
<div class='input-area'>
|
<div class='input-area'>
|
||||||
{{component inputComponentName field=field step=step fieldClass=fieldClass wizard=wizard focusOut=validators.perform}}
|
{{component inputComponentName field=field step=step fieldClass=fieldClass wizard=wizard }}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/field-validators}}
|
{{/field-validators}}
|
||||||
|
|
|
@ -178,9 +178,11 @@ en:
|
||||||
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 Validation Settings"
|
header: "Realtime Validation Settings"
|
||||||
suggested_topics: "Suggested Topics"
|
similar_topics: "Similar Topics"
|
||||||
above: "Above"
|
above: "Above"
|
||||||
below: "Below"
|
below: "Below"
|
||||||
|
categories: "Categories"
|
||||||
|
date_after: "Date After"
|
||||||
|
|
||||||
type:
|
type:
|
||||||
text: "Text"
|
text: "Text"
|
||||||
|
|
|
@ -4,12 +4,12 @@ CustomWizard::Engine.routes.draw do
|
||||||
get ':wizard_id/steps' => 'wizard#index'
|
get ':wizard_id/steps' => 'wizard#index'
|
||||||
get ':wizard_id/steps/:step_id' => 'wizard#index'
|
get ':wizard_id/steps/:step_id' => 'wizard#index'
|
||||||
put ':wizard_id/steps/:step_id' => 'steps#update'
|
put ':wizard_id/steps/:step_id' => 'steps#update'
|
||||||
put 'realtime_validation' => 'realtime_validation#validate'
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Discourse::Application.routes.append do
|
Discourse::Application.routes.append do
|
||||||
mount ::CustomWizard::Engine, at: 'w'
|
mount ::CustomWizard::Engine, at: 'w'
|
||||||
post 'wizard/authorization/callback' => "custom_wizard/authorization#callback"
|
post 'wizard/authorization/callback' => "custom_wizard/authorization#callback"
|
||||||
|
get 'realtime_validations' => 'custom_wizard/realtime_validations#validate'
|
||||||
|
|
||||||
scope module: 'custom_wizard', constraints: AdminConstraint.new do
|
scope module: 'custom_wizard', constraints: AdminConstraint.new do
|
||||||
get 'admin/wizards' => 'admin#index'
|
get 'admin/wizards' => 'admin#index'
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class CustomWizard::RealtimeValidationController < ::ApplicationController
|
class CustomWizard::RealtimeValidationsController < ::ApplicationController
|
||||||
def validate
|
def validate
|
||||||
params.require(:validation)
|
params.require(:validation)
|
||||||
params.require(::CustomWizard::RealtimeValidation.types[params[:validation].to_sym][:required_params])
|
params.require(::CustomWizard::RealtimeValidation.types[params[:validation].to_sym][:required_params])
|
|
@ -1,7 +1,7 @@
|
||||||
class CustomWizard::RealtimeValidation
|
class CustomWizard::RealtimeValidation
|
||||||
cattr_accessor :types
|
cattr_accessor :types
|
||||||
@@types ||= {
|
@@types ||= {
|
||||||
suggested_topics: { types: [:text], component: "suggested-validator", backend: true, required_params: [] }
|
similar_topics: { types: [:text], component: "suggested-validator", backend: true, required_params: [] }
|
||||||
}
|
}
|
||||||
|
|
||||||
class SimilarTopic
|
class SimilarTopic
|
||||||
|
@ -16,15 +16,19 @@ class CustomWizard::RealtimeValidation
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.suggested_topics(params, current_user)
|
def self.similar_topics(params, current_user)
|
||||||
title = params[:title]
|
title = params[:title]
|
||||||
raw = params[:raw]
|
raw = params[:raw]
|
||||||
|
categories = params[:categories]
|
||||||
|
date_after = params[:date_after]
|
||||||
|
|
||||||
if title.length < SiteSetting.min_title_similar_length || !Topic.count_exceeds_minimum?
|
if title.length < SiteSetting.min_title_similar_length || !Topic.count_exceeds_minimum?
|
||||||
return []
|
return []
|
||||||
end
|
end
|
||||||
|
|
||||||
topics = Topic.similar_to(title, raw, current_user).to_a
|
topics = Topic.similar_to(title, raw, current_user).to_a
|
||||||
|
topics.select! { |t| categories.include?(t.category.id.to_s) } if categories.present?
|
||||||
|
topics.select! { |t| t.created_at > DateTime.parse(date_after) } if date_after.present?
|
||||||
topics.map! { |t| SimilarTopic.new(t) }
|
topics.map! { |t| SimilarTopic.new(t) }
|
||||||
::ActiveModel::ArraySerializer.new(topics, each_serializer: SimilarTopicSerializer, root: :similar_topics, rest_serializer: true, scope: ::Guardian.new(current_user))
|
::ActiveModel::ArraySerializer.new(topics, each_serializer: SimilarTopicSerializer, root: :similar_topics, rest_serializer: true, scope: ::Guardian.new(current_user))
|
||||||
end
|
end
|
||||||
|
|
|
@ -47,7 +47,7 @@ after_initialize do
|
||||||
../controllers/custom_wizard/admin/custom_fields.rb
|
../controllers/custom_wizard/admin/custom_fields.rb
|
||||||
../controllers/custom_wizard/wizard.rb
|
../controllers/custom_wizard/wizard.rb
|
||||||
../controllers/custom_wizard/steps.rb
|
../controllers/custom_wizard/steps.rb
|
||||||
../controllers/custom_wizard/realtime_validation.rb
|
../controllers/custom_wizard/realtime_validations.rb
|
||||||
../jobs/clear_after_time_wizard.rb
|
../jobs/clear_after_time_wizard.rb
|
||||||
../jobs/refresh_api_access_token.rb
|
../jobs/refresh_api_access_token.rb
|
||||||
../jobs/set_after_time_wizard.rb
|
../jobs/set_after_time_wizard.rb
|
||||||
|
|
Laden …
In neuem Issue referenzieren