mirror of
https://github.com/discourse/discourse.git
synced 2025-04-16 20:59:06 +08:00
DEV: Plugin API to add directory columns (#13440)
This commit is contained in:
parent
fe5923da06
commit
7fc3d7bdde
@ -9,6 +9,7 @@ export default Component.extend({
|
|||||||
chevronIcon: null,
|
chevronIcon: null,
|
||||||
columnIcon: null,
|
columnIcon: null,
|
||||||
translated: false,
|
translated: false,
|
||||||
|
automatic: false,
|
||||||
onActiveRender: null,
|
onActiveRender: null,
|
||||||
|
|
||||||
toggleProperties() {
|
toggleProperties() {
|
||||||
@ -31,6 +32,9 @@ export default Component.extend({
|
|||||||
},
|
},
|
||||||
didReceiveAttrs() {
|
didReceiveAttrs() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
if (!this.automatic && !this.translated) {
|
||||||
|
this.set("labelKey", this.field);
|
||||||
|
}
|
||||||
this.set("id", `table-header-toggle-${this.field.replace(/\s/g, "")}`);
|
this.set("id", `table-header-toggle-${this.field.replace(/\s/g, "")}`);
|
||||||
this.toggleChevron();
|
this.toggleChevron();
|
||||||
},
|
},
|
||||||
|
@ -14,7 +14,7 @@ export default Controller.extend(ModalFunctionality, {
|
|||||||
labelKey: null,
|
labelKey: null,
|
||||||
|
|
||||||
onShow() {
|
onShow() {
|
||||||
ajax("directory-columns.json")
|
ajax("edit-directory-columns.json")
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
loading: false,
|
loading: false,
|
||||||
@ -35,7 +35,7 @@ export default Controller.extend(ModalFunctionality, {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
ajax("directory-columns.json", { type: "PUT", data })
|
ajax("edit-directory-columns.json", { type: "PUT", data })
|
||||||
.then(() => {
|
.then(() => {
|
||||||
reload();
|
reload();
|
||||||
})
|
})
|
||||||
@ -58,7 +58,7 @@ export default Controller.extend(ModalFunctionality, {
|
|||||||
.forEach((column, index) => {
|
.forEach((column, index) => {
|
||||||
column.setProperties({
|
column.setProperties({
|
||||||
position: column.automatic_position || index + 1,
|
position: column.automatic_position || index + 1,
|
||||||
enabled: column.automatic,
|
enabled: column.type === "automatic",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
this.set("columns", resetColumns);
|
this.set("columns", resetColumns);
|
||||||
|
@ -28,13 +28,22 @@ export default Controller.extend({
|
|||||||
this.set("nameInput", params.name);
|
this.set("nameInput", params.name);
|
||||||
this.set("order", params.order);
|
this.set("order", params.order);
|
||||||
|
|
||||||
const custom_field_columns = this.columns.filter((c) => !c.automatic);
|
const userFieldColumns = this.columns.filter(
|
||||||
const user_field_ids = custom_field_columns
|
(c) => c.type === "user_field"
|
||||||
.map((c) => c.user_field_id)
|
);
|
||||||
.join("|");
|
const userFieldIds = userFieldColumns.map((c) => c.user_field_id).join("|");
|
||||||
|
|
||||||
|
const pluginColumns = this.columns.filter((c) => c.type === "plugin");
|
||||||
|
const pluginColumnIds = pluginColumns.map((c) => c.id).join("|");
|
||||||
|
|
||||||
return this.store
|
return this.store
|
||||||
.find("directoryItem", Object.assign(params, { user_field_ids }))
|
.find(
|
||||||
|
"directoryItem",
|
||||||
|
Object.assign(params, {
|
||||||
|
user_field_ids: userFieldIds,
|
||||||
|
plugin_column_ids: pluginColumnIds,
|
||||||
|
})
|
||||||
|
)
|
||||||
.then((model) => {
|
.then((model) => {
|
||||||
const lastUpdatedAt = model.get("resultSetMeta.last_updated_at");
|
const lastUpdatedAt = model.get("resultSetMeta.last_updated_at");
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
import { htmlSafe } from "@ember/template";
|
||||||
|
import { number } from "discourse/lib/formatter";
|
||||||
|
import { registerUnbound } from "discourse-common/lib/helpers";
|
||||||
|
import I18n from "I18n";
|
||||||
|
|
||||||
|
registerUnbound("mobile-directory-item-label", function (args) {
|
||||||
|
// Args should include key/values { item, column }
|
||||||
|
const count = args.item.get(args.column.name);
|
||||||
|
return htmlSafe(I18n.t(`directory.${args.column.name}`, { count }));
|
||||||
|
});
|
||||||
|
|
||||||
|
registerUnbound("directory-item-value", function (args) {
|
||||||
|
// Args should include key/values { item, column }
|
||||||
|
return htmlSafe(
|
||||||
|
`<span class='number'>${number(args.item.get(args.column.name))}</span>`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
registerUnbound("directory-item-user-field-value", function (args) {
|
||||||
|
// Args should include key/values { item, column }
|
||||||
|
const value =
|
||||||
|
args.item.user && args.item.user.user_fields
|
||||||
|
? args.item.user.user_fields[args.column.user_field_id]
|
||||||
|
: null;
|
||||||
|
const content = value || "-";
|
||||||
|
return htmlSafe(`<span class='user-field-value'>${content}</span>`);
|
||||||
|
});
|
||||||
|
|
||||||
|
registerUnbound("directory-column-is-automatic", function (args) {
|
||||||
|
// Args should include key/values { column }
|
||||||
|
return args.column.type === "automatic";
|
||||||
|
});
|
||||||
|
|
||||||
|
registerUnbound("directory-column-is-user-field", function (args) {
|
||||||
|
// Args should include key/values { column }
|
||||||
|
return args.column.type === "user_field";
|
||||||
|
});
|
@ -1,10 +0,0 @@
|
|||||||
import { htmlSafe } from "@ember/template";
|
|
||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
|
||||||
import I18n from "I18n";
|
|
||||||
|
|
||||||
export default registerUnbound("mobile-directory-item-label", function (args) {
|
|
||||||
// Args should include key/values { item, column }
|
|
||||||
|
|
||||||
const count = args.item.get(args.column.name);
|
|
||||||
return htmlSafe(I18n.t(`directory.${args.column.name}`, { count }));
|
|
||||||
});
|
|
@ -1,16 +0,0 @@
|
|||||||
import { htmlSafe } from "@ember/template";
|
|
||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
|
||||||
|
|
||||||
export default registerUnbound(
|
|
||||||
"directory-item-user-field-value",
|
|
||||||
function (args) {
|
|
||||||
// Args should include key/values { item, column }
|
|
||||||
|
|
||||||
const value =
|
|
||||||
args.item.user && args.item.user.user_fields
|
|
||||||
? args.item.user.user_fields[args.column.user_field_id]
|
|
||||||
: null;
|
|
||||||
const content = value || "-";
|
|
||||||
return htmlSafe(`<span class='user-field-value'>${content}</span>`);
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,11 +0,0 @@
|
|||||||
import { htmlSafe } from "@ember/template";
|
|
||||||
import { registerUnbound } from "discourse-common/lib/helpers";
|
|
||||||
import { number } from "discourse/lib/formatter";
|
|
||||||
|
|
||||||
export default registerUnbound("directory-item-value", function (args) {
|
|
||||||
// Args should include key/values { item, column }
|
|
||||||
|
|
||||||
return htmlSafe(
|
|
||||||
`<span class='number'>${number(args.item.get(args.column.name))}</span>`
|
|
||||||
);
|
|
||||||
});
|
|
@ -1,6 +1,7 @@
|
|||||||
import DiscourseRoute from "discourse/routes/discourse";
|
import DiscourseRoute from "discourse/routes/discourse";
|
||||||
import I18n from "I18n";
|
import I18n from "I18n";
|
||||||
import PreloadStore from "discourse/lib/preload-store";
|
import { ajax } from "discourse/lib/ajax";
|
||||||
|
import { popupAjaxError } from "discourse/lib/ajax-error";
|
||||||
import { Promise } from "rsvp";
|
import { Promise } from "rsvp";
|
||||||
|
|
||||||
export default DiscourseRoute.extend({
|
export default DiscourseRoute.extend({
|
||||||
@ -38,9 +39,12 @@ export default DiscourseRoute.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
model(params) {
|
model(params) {
|
||||||
const columns = PreloadStore.get("directoryColumns");
|
return ajax("directory-columns.json")
|
||||||
params.order = params.order || columns[0].name;
|
.then((response) => {
|
||||||
return { params, columns };
|
params.order = params.order || response.directory_columns[0].name;
|
||||||
|
return { params, columns: response.directory_columns };
|
||||||
|
})
|
||||||
|
.catch(popupAjaxError);
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
setupController(controller, model) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<td>{{user-info user=item.user}}</td>
|
<td>{{user-info user=item.user}}</td>
|
||||||
{{#each columns as |column|}}
|
{{#each columns as |column|}}
|
||||||
<td>
|
<td>
|
||||||
{{#if column.automatic}}
|
{{#if (directory-column-is-user-field column=column)}}
|
||||||
{{directory-item-value item=item column=column}}
|
|
||||||
{{else}}
|
|
||||||
{{directory-item-user-field-value item=item column=column}}
|
{{directory-item-user-field-value item=item column=column}}
|
||||||
|
{{else}}
|
||||||
|
{{directory-item-value item=item column=column}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</td>
|
</td>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
icon=column.icon
|
icon=column.icon
|
||||||
order=order
|
order=order
|
||||||
asc=asc
|
asc=asc
|
||||||
|
automatic=(directory-column-is-automatic column=column)
|
||||||
translated=column.user_field_id
|
translated=column.user_field_id
|
||||||
onActiveRender=setActiveHeader
|
onActiveRender=setActiveHeader
|
||||||
}}
|
}}
|
||||||
|
@ -35,11 +35,11 @@
|
|||||||
{{d-button action=(action "bulkClearAll") label="topics.bulk.clear_all"}}
|
{{d-button action=(action "bulkClearAll") label="topics.bulk.clear_all"}}
|
||||||
</th>
|
</th>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{table-header-toggle order=order asc=asc field="username_lower" labelKey="username" class="username"}}
|
{{table-header-toggle order=order asc=asc field="username_lower" labelKey="username" class="username" automatic=true}}
|
||||||
<th class="group-owner"></th>
|
<th class="group-owner"></th>
|
||||||
{{table-header-toggle order=order asc=asc field="added_at" labelKey="groups.member_added"}}
|
{{table-header-toggle order=order asc=asc field="added_at" labelKey="groups.member_added" automatic=true}}
|
||||||
{{table-header-toggle order=order asc=asc field="last_posted_at" labelKey="last_post"}}
|
{{table-header-toggle order=order asc=asc field="last_posted_at" labelKey="last_post" automatic=true}}
|
||||||
{{table-header-toggle order=order asc=asc field="last_seen_at" labelKey="last_seen"}}
|
{{table-header-toggle order=order asc=asc field="last_seen_at" labelKey="last_seen" automatic=true}}
|
||||||
<th>
|
<th>
|
||||||
{{#if isBulk}}
|
{{#if isBulk}}
|
||||||
{{group-member-dropdown
|
{{group-member-dropdown
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
{{#load-more selector=".group-members tr" action=(action "loadMore")}}
|
{{#load-more selector=".group-members tr" action=(action "loadMore")}}
|
||||||
<table class="group-members">
|
<table class="group-members">
|
||||||
<thead>
|
<thead>
|
||||||
{{table-header-toggle order=order asc=asc field="username_lower" labelKey="username"}}
|
{{table-header-toggle order=order asc=asc field="username_lower" labelKey="username" automatic=true}}
|
||||||
{{table-header-toggle order=order asc=asc field="requested_at" labelKey="groups.member_requested"}}
|
{{table-header-toggle order=order asc=asc field="requested_at" labelKey="groups.member_requested" automatic=true}}
|
||||||
<th>{{i18n "groups.requests.reason"}}</th>
|
<th>{{i18n "groups.requests.reason"}}</th>
|
||||||
<th></th>
|
<th></th>
|
||||||
<th></th>
|
<th></th>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
{{user-info user=item.user}}
|
{{user-info user=item.user}}
|
||||||
|
|
||||||
{{#each columns as |column|}}
|
{{#each columns as |column|}}
|
||||||
{{#if column.automatic}}
|
{{#if (directory-column-is-automatic column=column)}}
|
||||||
<div class="user-stat">
|
<div class="user-stat">
|
||||||
<span class="value">
|
<span class="value">
|
||||||
{{directory-item-value item=item column=column}}
|
{{directory-item-value item=item column=column}}
|
||||||
|
@ -8,10 +8,12 @@
|
|||||||
<div class="left-content">
|
<div class="left-content">
|
||||||
<label class="column-name">
|
<label class="column-name">
|
||||||
{{input type="checkbox" checked=column.enabled}}
|
{{input type="checkbox" checked=column.enabled}}
|
||||||
{{#if column.automatic}}
|
{{#if (directory-column-is-automatic column=column)}}
|
||||||
{{directory-table-header-title field=column.name labelKey=labelKey icon=column.icon}}
|
{{directory-table-header-title field=column.name labelKey=labelKey icon=column.icon}}
|
||||||
{{else}}
|
{{else if (directory-column-is-user-field column=column)}}
|
||||||
{{directory-table-header-title field=column.user_field.name translated=true}}
|
{{directory-table-header-title field=column.user_field.name translated=true}}
|
||||||
|
{{else}}
|
||||||
|
{{directory-table-header-title field=(i18n column.name) translated=true}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
@ -938,13 +938,13 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
return [404, { "Content-Type": "application/html" }, ""];
|
return [404, { "Content-Type": "application/html" }, ""];
|
||||||
});
|
});
|
||||||
|
|
||||||
pretender.get("directory-columns.json", () => {
|
pretender.get("edit-directory-columns.json", () => {
|
||||||
return response(200, {
|
return response(200, {
|
||||||
directory_columns: [
|
directory_columns: [
|
||||||
{
|
{
|
||||||
id: 1,
|
id: 1,
|
||||||
name: "likes_received",
|
name: "likes_received",
|
||||||
automatic: true,
|
type: "automatic",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
automatic_position: 1,
|
automatic_position: 1,
|
||||||
position: 1,
|
position: 1,
|
||||||
@ -954,7 +954,7 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
{
|
{
|
||||||
id: 2,
|
id: 2,
|
||||||
name: "likes_given",
|
name: "likes_given",
|
||||||
automatic: true,
|
type: "automatic",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
automatic_position: 2,
|
automatic_position: 2,
|
||||||
position: 2,
|
position: 2,
|
||||||
@ -964,7 +964,7 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
{
|
{
|
||||||
id: 3,
|
id: 3,
|
||||||
name: "topic_count",
|
name: "topic_count",
|
||||||
automatic: true,
|
type: "automatic",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
automatic_position: 3,
|
automatic_position: 3,
|
||||||
position: 3,
|
position: 3,
|
||||||
@ -974,7 +974,7 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
{
|
{
|
||||||
id: 4,
|
id: 4,
|
||||||
name: "post_count",
|
name: "post_count",
|
||||||
automatic: true,
|
type: "automatic",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
automatic_position: 4,
|
automatic_position: 4,
|
||||||
position: 4,
|
position: 4,
|
||||||
@ -984,7 +984,7 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
{
|
{
|
||||||
id: 5,
|
id: 5,
|
||||||
name: "topics_entered",
|
name: "topics_entered",
|
||||||
automatic: true,
|
type: "automatic",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
automatic_position: 5,
|
automatic_position: 5,
|
||||||
position: 5,
|
position: 5,
|
||||||
@ -994,7 +994,7 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
{
|
{
|
||||||
id: 6,
|
id: 6,
|
||||||
name: "posts_read",
|
name: "posts_read",
|
||||||
automatic: true,
|
type: "automatic",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
automatic_position: 6,
|
automatic_position: 6,
|
||||||
position: 6,
|
position: 6,
|
||||||
@ -1004,7 +1004,7 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
{
|
{
|
||||||
id: 7,
|
id: 7,
|
||||||
name: "days_visited",
|
name: "days_visited",
|
||||||
automatic: true,
|
type: "automatic",
|
||||||
enabled: true,
|
enabled: true,
|
||||||
automatic_position: 7,
|
automatic_position: 7,
|
||||||
position: 7,
|
position: 7,
|
||||||
@ -1014,7 +1014,7 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
{
|
{
|
||||||
id: 9,
|
id: 9,
|
||||||
name: null,
|
name: null,
|
||||||
automatic: false,
|
type: "user_field",
|
||||||
enabled: false,
|
enabled: false,
|
||||||
automatic_position: null,
|
automatic_position: null,
|
||||||
position: 8,
|
position: 8,
|
||||||
@ -1035,4 +1035,75 @@ export function applyDefaultHandlers(pretender) {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
pretender.get("directory-columns.json", () => {
|
||||||
|
return response(200, {
|
||||||
|
directory_columns: [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: "likes_received",
|
||||||
|
type: "automatic",
|
||||||
|
position: 1,
|
||||||
|
icon: "heart",
|
||||||
|
user_field: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
name: "likes_given",
|
||||||
|
type: "automatic",
|
||||||
|
position: 2,
|
||||||
|
icon: "heart",
|
||||||
|
user_field: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: "topic_count",
|
||||||
|
type: "automatic",
|
||||||
|
position: 3,
|
||||||
|
icon: null,
|
||||||
|
user_field: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: "post_count",
|
||||||
|
type: "automatic",
|
||||||
|
position: 4,
|
||||||
|
icon: null,
|
||||||
|
user_field: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
name: "topics_entered",
|
||||||
|
type: "automatic",
|
||||||
|
position: 5,
|
||||||
|
icon: null,
|
||||||
|
user_field: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
name: "posts_read",
|
||||||
|
type: "automatic",
|
||||||
|
position: 6,
|
||||||
|
icon: null,
|
||||||
|
user_field: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
name: "days_visited",
|
||||||
|
type: "automatic",
|
||||||
|
position: 7,
|
||||||
|
icon: null,
|
||||||
|
user_field: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 9,
|
||||||
|
name: "Favorite Color",
|
||||||
|
type: "user_field",
|
||||||
|
position: 8,
|
||||||
|
icon: null,
|
||||||
|
user_field_id: 3,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
@ -229,12 +229,6 @@ function setupTestsCommon(application, container, config) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
PreloadStore.reset();
|
PreloadStore.reset();
|
||||||
PreloadStore.store(
|
|
||||||
"directoryColumns",
|
|
||||||
JSON.parse(
|
|
||||||
'[{"name":"likes_given","automatic":true,"icon":"heart","user_field_id":null},{"name":"posts_read","automatic":true,"icon":null,"user_field_id":null},{"name":"likes_received","automatic":true,"icon":"heart","user_field_id":null},{"name":"topic_count","automatic":true,"icon":null,"user_field_id":null},{"name":"post_count","automatic":true,"icon":null,"user_field_id":null},{"name":"topics_entered","automatic":true,"icon":null,"user_field_id":null},{"name":"days_visited","automatic":true,"icon":null,"user_field_id":null},{"name":"Favorite Color","automatic":false,"icon":null,"user_field_id":3}]'
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
sinon.stub(ScrollingDOMMethods, "screenNotFull");
|
sinon.stub(ScrollingDOMMethods, "screenNotFull");
|
||||||
sinon.stub(ScrollingDOMMethods, "bindOnScroll");
|
sinon.stub(ScrollingDOMMethods, "bindOnScroll");
|
||||||
|
@ -604,7 +604,6 @@ class ApplicationController < ActionController::Base
|
|||||||
store_preloaded("customEmoji", custom_emoji)
|
store_preloaded("customEmoji", custom_emoji)
|
||||||
store_preloaded("isReadOnly", @readonly_mode.to_s)
|
store_preloaded("isReadOnly", @readonly_mode.to_s)
|
||||||
store_preloaded("activatedThemes", activated_themes_json)
|
store_preloaded("activatedThemes", activated_themes_json)
|
||||||
store_preloaded("directoryColumns", directory_columns_json)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def preload_current_user_data
|
def preload_current_user_data
|
||||||
@ -616,20 +615,6 @@ class ApplicationController < ActionController::Base
|
|||||||
store_preloaded("topicTrackingStates", MultiJson.dump(serializer))
|
store_preloaded("topicTrackingStates", MultiJson.dump(serializer))
|
||||||
end
|
end
|
||||||
|
|
||||||
def directory_columns_json
|
|
||||||
DirectoryColumn
|
|
||||||
.left_joins(:user_field)
|
|
||||||
.where(enabled: true)
|
|
||||||
.order(:position)
|
|
||||||
.pluck('directory_columns.name',
|
|
||||||
'directory_columns.automatic',
|
|
||||||
'directory_columns.icon',
|
|
||||||
'user_fields.id',
|
|
||||||
'user_fields.name')
|
|
||||||
.map { |column| { name: column[0] || column[4], automatic: column[1], icon: column[2], user_field_id: column[3] } }
|
|
||||||
.to_json
|
|
||||||
end
|
|
||||||
|
|
||||||
def custom_html_json
|
def custom_html_json
|
||||||
target = view_context.mobile_view? ? :mobile : :desktop
|
target = view_context.mobile_view? ? :mobile : :desktop
|
||||||
|
|
||||||
|
@ -1,62 +1,8 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class DirectoryColumnsController < ApplicationController
|
class DirectoryColumnsController < ApplicationController
|
||||||
requires_login
|
|
||||||
|
|
||||||
def index
|
def index
|
||||||
raise Discourse::NotFound unless guardian.is_staff?
|
directory_columns = DirectoryColumn.includes(:user_field).where(enabled: true).order(:position)
|
||||||
|
render_json_dump(directory_columns: serialize_data(directory_columns, DirectoryColumnSerializer))
|
||||||
ensure_user_fields_have_columns
|
|
||||||
|
|
||||||
columns = DirectoryColumn.includes(:user_field).all
|
|
||||||
render_json_dump(directory_columns: serialize_data(columns, DirectoryColumnSerializer))
|
|
||||||
end
|
|
||||||
|
|
||||||
def update
|
|
||||||
raise Discourse::NotFound unless guardian.is_staff?
|
|
||||||
params.require(:directory_columns)
|
|
||||||
directory_column_params = params.permit(directory_columns: {})
|
|
||||||
directory_columns = DirectoryColumn.all
|
|
||||||
|
|
||||||
has_enabled_column = directory_column_params[:directory_columns].values.any? do |column_data|
|
|
||||||
column_data[:enabled].to_s == "true"
|
|
||||||
end
|
|
||||||
raise Discourse::InvalidParameters, "Must have at least one column enabled" unless has_enabled_column
|
|
||||||
|
|
||||||
directory_column_params[:directory_columns].values.each do |column_data|
|
|
||||||
existing_column = directory_columns.detect { |c| c.id == column_data[:id].to_i }
|
|
||||||
if (existing_column.enabled != column_data[:enabled] || existing_column.position != column_data[:position].to_i)
|
|
||||||
existing_column.update(enabled: column_data[:enabled], position: column_data[:position])
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
render json: success_json
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def ensure_user_fields_have_columns
|
|
||||||
user_fields_without_column =
|
|
||||||
UserField.left_outer_joins(:directory_column)
|
|
||||||
.where(directory_column: { user_field_id: nil })
|
|
||||||
.where("show_on_profile=? OR show_on_user_card=?", true, true)
|
|
||||||
|
|
||||||
return unless user_fields_without_column.count > 0
|
|
||||||
|
|
||||||
next_position = DirectoryColumn.maximum("position") + 1
|
|
||||||
|
|
||||||
new_directory_column_attrs = []
|
|
||||||
user_fields_without_column.each do |user_field|
|
|
||||||
new_directory_column_attrs.push({
|
|
||||||
user_field_id: user_field.id,
|
|
||||||
enabled: false,
|
|
||||||
automatic: false,
|
|
||||||
position: next_position
|
|
||||||
})
|
|
||||||
|
|
||||||
next_position += 1
|
|
||||||
end
|
|
||||||
|
|
||||||
DirectoryColumn.insert_all(new_directory_column_attrs)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -26,13 +26,14 @@ class DirectoryItemsController < ApplicationController
|
|||||||
result = result.references(:user).where.not(users: { username: params[:exclude_usernames].split(",") })
|
result = result.references(:user).where.not(users: { username: params[:exclude_usernames].split(",") })
|
||||||
end
|
end
|
||||||
|
|
||||||
order = params[:order] || DirectoryItem.headings.first
|
order = params[:order] || DirectoryColumn.automatic_column_names.first
|
||||||
dir = params[:asc] ? 'ASC' : 'DESC'
|
dir = params[:asc] ? 'ASC' : 'DESC'
|
||||||
if DirectoryItem.headings.include?(order.to_sym)
|
if DirectoryColumn.active_column_names.include?(order.to_sym)
|
||||||
result = result.order("directory_items.#{order} #{dir}, directory_items.id")
|
result = result.order("directory_items.#{order} #{dir}, directory_items.id")
|
||||||
elsif params[:order] === 'username'
|
elsif params[:order] === 'username'
|
||||||
result = result.order("users.#{order} #{dir}, directory_items.id")
|
result = result.order("users.#{order} #{dir}, directory_items.id")
|
||||||
else
|
else
|
||||||
|
# Ordering by user field value
|
||||||
user_field = UserField.find_by(name: params[:order])
|
user_field = UserField.find_by(name: params[:order])
|
||||||
if user_field
|
if user_field
|
||||||
result = result
|
result = result
|
||||||
@ -98,6 +99,10 @@ class DirectoryItemsController < ApplicationController
|
|||||||
serializer_opts[:user_field_ids] = params[:user_field_ids]&.split("|")&.map(&:to_i)
|
serializer_opts[:user_field_ids] = params[:user_field_ids]&.split("|")&.map(&:to_i)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if params[:plugin_column_ids]
|
||||||
|
serializer_opts[:plugin_column_ids] = params[:plugin_column_ids]&.split("|")&.map(&:to_i)
|
||||||
|
end
|
||||||
|
|
||||||
serialized = serialize_data(result, DirectoryItemSerializer, serializer_opts)
|
serialized = serialize_data(result, DirectoryItemSerializer, serializer_opts)
|
||||||
render_json_dump(directory_items: serialized,
|
render_json_dump(directory_items: serialized,
|
||||||
meta: {
|
meta: {
|
||||||
|
62
app/controllers/edit_directory_columns_controller.rb
Normal file
62
app/controllers/edit_directory_columns_controller.rb
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class EditDirectoryColumnsController < ApplicationController
|
||||||
|
requires_login
|
||||||
|
|
||||||
|
def index
|
||||||
|
raise Discourse::NotFound unless guardian.is_staff?
|
||||||
|
|
||||||
|
ensure_user_fields_have_columns
|
||||||
|
|
||||||
|
columns = DirectoryColumn.includes(:user_field).all
|
||||||
|
render_json_dump(directory_columns: serialize_data(columns, EditDirectoryColumnSerializer))
|
||||||
|
end
|
||||||
|
|
||||||
|
def update
|
||||||
|
raise Discourse::NotFound unless guardian.is_staff?
|
||||||
|
params.require(:directory_columns)
|
||||||
|
directory_column_params = params.permit(directory_columns: {})
|
||||||
|
directory_columns = DirectoryColumn.all
|
||||||
|
|
||||||
|
has_enabled_column = directory_column_params[:directory_columns].values.any? do |column_data|
|
||||||
|
column_data[:enabled].to_s == "true"
|
||||||
|
end
|
||||||
|
raise Discourse::InvalidParameters, "Must have at least one column enabled" unless has_enabled_column
|
||||||
|
|
||||||
|
directory_column_params[:directory_columns].values.each do |column_data|
|
||||||
|
existing_column = directory_columns.detect { |c| c.id == column_data[:id].to_i }
|
||||||
|
if (existing_column.enabled != column_data[:enabled] || existing_column.position != column_data[:position].to_i)
|
||||||
|
existing_column.update(enabled: column_data[:enabled], position: column_data[:position])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
render json: success_json
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def ensure_user_fields_have_columns
|
||||||
|
user_fields_without_column =
|
||||||
|
UserField.left_outer_joins(:directory_column)
|
||||||
|
.where(directory_column: { user_field_id: nil })
|
||||||
|
.where("show_on_profile=? OR show_on_user_card=?", true, true)
|
||||||
|
|
||||||
|
return unless user_fields_without_column.count > 0
|
||||||
|
|
||||||
|
next_position = DirectoryColumn.maximum("position") + 1
|
||||||
|
|
||||||
|
new_directory_column_attrs = []
|
||||||
|
user_fields_without_column.each do |user_field|
|
||||||
|
new_directory_column_attrs.push({
|
||||||
|
user_field_id: user_field.id,
|
||||||
|
enabled: false,
|
||||||
|
type: DirectoryColumn.types[:user_field],
|
||||||
|
position: next_position
|
||||||
|
})
|
||||||
|
|
||||||
|
next_position += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
DirectoryColumn.insert_all(new_directory_column_attrs)
|
||||||
|
end
|
||||||
|
end
|
@ -1,5 +1,52 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class DirectoryColumn < ActiveRecord::Base
|
class DirectoryColumn < ActiveRecord::Base
|
||||||
|
|
||||||
|
# TODO(2021-06-18): Remove automatic column
|
||||||
|
self.ignored_columns = ["automatic"]
|
||||||
|
self.inheritance_column = nil
|
||||||
|
|
||||||
|
enum type: { automatic: 0, user_field: 1, plugin: 2 }
|
||||||
|
|
||||||
|
def self.automatic_column_names
|
||||||
|
@automatic_column_names ||= [:likes_received,
|
||||||
|
:likes_given,
|
||||||
|
:topics_entered,
|
||||||
|
:topic_count,
|
||||||
|
:post_count,
|
||||||
|
:posts_read,
|
||||||
|
:days_visited]
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.active_column_names
|
||||||
|
DirectoryColumn.where(type: [:automatic, :plugin]).where(enabled: true).pluck(:name).map(&:to_sym)
|
||||||
|
end
|
||||||
|
|
||||||
|
@@plugin_directory_columns = []
|
||||||
|
|
||||||
|
def self.plugin_directory_columns
|
||||||
|
@@plugin_directory_columns
|
||||||
|
end
|
||||||
|
|
||||||
belongs_to :user_field
|
belongs_to :user_field
|
||||||
|
|
||||||
|
def self.clear_plugin_directory_columns
|
||||||
|
@@plugin_directory_columns = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.find_or_create_plugin_directory_column(attrs)
|
||||||
|
directory_column = find_or_create_by(
|
||||||
|
name: attrs[:column_name],
|
||||||
|
icon: attrs[:icon],
|
||||||
|
type: DirectoryColumn.types[:plugin]
|
||||||
|
) do |column|
|
||||||
|
column.position = DirectoryColumn.maximum("position") + 1
|
||||||
|
column.enabled = false
|
||||||
|
end
|
||||||
|
|
||||||
|
unless @@plugin_directory_columns.include?(directory_column.name)
|
||||||
|
@@plugin_directory_columns << directory_column.name
|
||||||
|
DirectoryItem.add_plugin_query(attrs[:query])
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -4,15 +4,7 @@ class DirectoryItem < ActiveRecord::Base
|
|||||||
belongs_to :user
|
belongs_to :user
|
||||||
has_one :user_stat, foreign_key: :user_id, primary_key: :user_id
|
has_one :user_stat, foreign_key: :user_id, primary_key: :user_id
|
||||||
|
|
||||||
def self.headings
|
@@plugin_queries = []
|
||||||
@headings ||= [:likes_received,
|
|
||||||
:likes_given,
|
|
||||||
:topics_entered,
|
|
||||||
:topic_count,
|
|
||||||
:post_count,
|
|
||||||
:posts_read,
|
|
||||||
:days_visited]
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.period_types
|
def self.period_types
|
||||||
@types ||= Enum.new(all: 1,
|
@types ||= Enum.new(all: 1,
|
||||||
@ -34,8 +26,16 @@ class DirectoryItem < ActiveRecord::Base
|
|||||||
Time.zone.at(val.to_i)
|
Time.zone.at(val.to_i)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.refresh_period!(period_type, force: false)
|
def self.add_plugin_query(details)
|
||||||
|
@@plugin_queries << details
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.clear_plugin_queries
|
||||||
|
@@plugin_queries = []
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.refresh_period!(period_type, force: false)
|
||||||
|
DiscourseEvent.trigger("before_directory_refresh")
|
||||||
Discourse.redis.set("directory_#{period_types[period_type]}", Time.zone.now.to_i)
|
Discourse.redis.set("directory_#{period_types[period_type]}", Time.zone.now.to_i)
|
||||||
|
|
||||||
# Don't calculate it if the user directory is disabled
|
# Don't calculate it if the user directory is disabled
|
||||||
@ -53,30 +53,26 @@ class DirectoryItem < ActiveRecord::Base
|
|||||||
|
|
||||||
ActiveRecord::Base.transaction do
|
ActiveRecord::Base.transaction do
|
||||||
# Delete records that belonged to users who have been deleted
|
# Delete records that belonged to users who have been deleted
|
||||||
DB.exec "DELETE FROM directory_items
|
DB.exec("DELETE FROM directory_items
|
||||||
USING directory_items di
|
USING directory_items di
|
||||||
LEFT JOIN users u ON (u.id = user_id AND u.active AND u.silenced_till IS NULL AND u.id > 0)
|
LEFT JOIN users u ON (u.id = user_id AND u.active AND u.silenced_till IS NULL AND u.id > 0)
|
||||||
WHERE di.id = directory_items.id AND
|
WHERE di.id = directory_items.id AND
|
||||||
u.id IS NULL AND
|
u.id IS NULL AND
|
||||||
di.period_type = :period_type", period_type: period_types[period_type]
|
di.period_type = :period_type", period_type: period_types[period_type])
|
||||||
|
|
||||||
# Create new records for users who don't have one yet
|
# Create new records for users who don't have one yet
|
||||||
DB.exec "INSERT INTO directory_items(period_type, user_id, likes_received, likes_given, topics_entered, days_visited, posts_read, topic_count, post_count)
|
|
||||||
|
column_names = DirectoryColumn.automatic_column_names + DirectoryColumn.plugin_directory_columns
|
||||||
|
DB.exec("INSERT INTO directory_items(period_type, user_id, #{column_names.map(&:to_s).join(", ")})
|
||||||
SELECT
|
SELECT
|
||||||
:period_type,
|
:period_type,
|
||||||
u.id,
|
u.id,
|
||||||
0,
|
#{Array.new(column_names.count) { |_| 0 }.join(", ") }
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
0
|
|
||||||
FROM users u
|
FROM users u
|
||||||
LEFT JOIN directory_items di ON di.user_id = u.id AND di.period_type = :period_type
|
LEFT JOIN directory_items di ON di.user_id = u.id AND di.period_type = :period_type
|
||||||
WHERE di.id IS NULL AND u.id > 0 AND u.silenced_till IS NULL AND u.active
|
WHERE di.id IS NULL AND u.id > 0 AND u.silenced_till IS NULL AND u.active
|
||||||
#{SiteSetting.must_approve_users ? 'AND u.approved' : ''}
|
#{SiteSetting.must_approve_users ? 'AND u.approved' : ''}
|
||||||
", period_type: period_types[period_type]
|
", period_type: period_types[period_type])
|
||||||
|
|
||||||
# Calculate new values and update records
|
# Calculate new values and update records
|
||||||
#
|
#
|
||||||
@ -84,7 +80,18 @@ class DirectoryItem < ActiveRecord::Base
|
|||||||
# TODO
|
# TODO
|
||||||
# WARNING: post_count is a wrong name, it should be reply_count (excluding topic post)
|
# WARNING: post_count is a wrong name, it should be reply_count (excluding topic post)
|
||||||
#
|
#
|
||||||
DB.exec "WITH x AS (SELECT
|
#
|
||||||
|
query_args = {
|
||||||
|
period_type: period_types[period_type],
|
||||||
|
since: since,
|
||||||
|
like_type: UserAction::LIKE,
|
||||||
|
was_liked_type: UserAction::WAS_LIKED,
|
||||||
|
new_topic_type: UserAction::NEW_TOPIC,
|
||||||
|
reply_type: UserAction::REPLY,
|
||||||
|
regular_post_type: Post.types[:regular]
|
||||||
|
}
|
||||||
|
|
||||||
|
DB.exec("WITH x AS (SELECT
|
||||||
u.id user_id,
|
u.id user_id,
|
||||||
SUM(CASE WHEN p.id IS NOT NULL AND t.id IS NOT NULL AND ua.action_type = :was_liked_type THEN 1 ELSE 0 END) likes_received,
|
SUM(CASE WHEN p.id IS NOT NULL AND t.id IS NOT NULL AND ua.action_type = :was_liked_type THEN 1 ELSE 0 END) likes_received,
|
||||||
SUM(CASE WHEN p.id IS NOT NULL AND t.id IS NOT NULL AND ua.action_type = :like_type THEN 1 ELSE 0 END) likes_given,
|
SUM(CASE WHEN p.id IS NOT NULL AND t.id IS NOT NULL AND ua.action_type = :like_type THEN 1 ELSE 0 END) likes_given,
|
||||||
@ -123,14 +130,13 @@ class DirectoryItem < ActiveRecord::Base
|
|||||||
di.topic_count <> x.topic_count OR
|
di.topic_count <> x.topic_count OR
|
||||||
di.post_count <> x.post_count )
|
di.post_count <> x.post_count )
|
||||||
|
|
||||||
",
|
",
|
||||||
period_type: period_types[period_type],
|
query_args
|
||||||
since: since,
|
)
|
||||||
like_type: UserAction::LIKE,
|
|
||||||
was_liked_type: UserAction::WAS_LIKED,
|
@@plugin_queries.each do |plugin_query|
|
||||||
new_topic_type: UserAction::NEW_TOPIC,
|
DB.exec(plugin_query, query_args)
|
||||||
reply_type: UserAction::REPLY,
|
end
|
||||||
regular_post_type: Post.types[:regular]
|
|
||||||
|
|
||||||
if period_type == :all
|
if period_type == :all
|
||||||
DB.exec <<~SQL
|
DB.exec <<~SQL
|
||||||
|
@ -3,11 +3,12 @@
|
|||||||
class DirectoryColumnSerializer < ApplicationSerializer
|
class DirectoryColumnSerializer < ApplicationSerializer
|
||||||
attributes :id,
|
attributes :id,
|
||||||
:name,
|
:name,
|
||||||
:automatic,
|
:type,
|
||||||
:enabled,
|
|
||||||
:automatic_position,
|
|
||||||
:position,
|
:position,
|
||||||
:icon
|
:icon,
|
||||||
|
:user_field_id
|
||||||
|
|
||||||
has_one :user_field, serializer: UserFieldSerializer, embed: :objects
|
def name
|
||||||
|
object.name || object.user_field.name
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -20,7 +20,7 @@ class DirectoryItemSerializer < ApplicationSerializer
|
|||||||
:time_read
|
:time_read
|
||||||
|
|
||||||
has_one :user, embed: :objects, serializer: UserSerializer
|
has_one :user, embed: :objects, serializer: UserSerializer
|
||||||
attributes *DirectoryItem.headings
|
attributes *DirectoryColumn.active_column_names
|
||||||
|
|
||||||
def id
|
def id
|
||||||
object.user_id
|
object.user_id
|
||||||
|
8
app/serializers/edit_directory_column_serializer.rb
Normal file
8
app/serializers/edit_directory_column_serializer.rb
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class EditDirectoryColumnSerializer < DirectoryColumnSerializer
|
||||||
|
attributes :enabled,
|
||||||
|
:automatic_position
|
||||||
|
|
||||||
|
has_one :user_field, serializer: UserFieldSerializer, embed: :objects
|
||||||
|
end
|
@ -388,7 +388,8 @@ Discourse::Application.routes.draw do
|
|||||||
|
|
||||||
get "user-cards" => "users#cards", format: :json
|
get "user-cards" => "users#cards", format: :json
|
||||||
get "directory-columns" => "directory_columns#index", format: :json
|
get "directory-columns" => "directory_columns#index", format: :json
|
||||||
put "directory-columns" => "directory_columns#update", format: :json
|
get "edit-directory-columns" => "edit_directory_columns#index", format: :json
|
||||||
|
put "edit-directory-columns" => "edit_directory_columns#update", format: :json
|
||||||
|
|
||||||
%w{users u}.each_with_index do |root_path, index|
|
%w{users u}.each_with_index do |root_path, index|
|
||||||
get "#{root_path}" => "users#index", constraints: { format: 'html' }
|
get "#{root_path}" => "users#index", constraints: { format: 'html' }
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ReintroduceTypeToDirectoryColumns < ActiveRecord::Migration[6.1]
|
||||||
|
def up
|
||||||
|
if !ActiveRecord::Base.connection.column_exists?(:directory_columns, :type)
|
||||||
|
# A migration that added this column was previously merged and reverted.
|
||||||
|
# Some sites have this column and some do not, so only add if missing.
|
||||||
|
add_column :directory_columns, :type, :integer, default: 0, null: false
|
||||||
|
end
|
||||||
|
|
||||||
|
DB.exec(
|
||||||
|
<<~SQL
|
||||||
|
UPDATE directory_columns
|
||||||
|
SET type = CASE WHEN automatic THEN 0 ELSE 1 END;
|
||||||
|
SQL
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :directory_columns, :type
|
||||||
|
end
|
||||||
|
end
|
@ -27,4 +27,7 @@ class DiscourseEvent
|
|||||||
events[event_name].delete(block)
|
events[event_name].delete(block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.all_off(event_name)
|
||||||
|
events.delete(event_name)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -373,6 +373,14 @@ class Plugin::Instance
|
|||||||
assets
|
assets
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_directory_column(column_name, query:, icon: nil)
|
||||||
|
validate_directory_column_name(column_name)
|
||||||
|
|
||||||
|
DiscourseEvent.on("before_directory_refresh") do
|
||||||
|
DirectoryColumn.find_or_create_plugin_directory_column(column_name: column_name, icon: icon, query: query)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def delete_extra_automatic_assets(good_paths)
|
def delete_extra_automatic_assets(good_paths)
|
||||||
return unless Dir.exists? auto_generated_path
|
return unless Dir.exists? auto_generated_path
|
||||||
|
|
||||||
@ -593,7 +601,6 @@ class Plugin::Instance
|
|||||||
# this allows us to present information about a plugin in the UI
|
# this allows us to present information about a plugin in the UI
|
||||||
# prior to activations
|
# prior to activations
|
||||||
def activate!
|
def activate!
|
||||||
|
|
||||||
if @path
|
if @path
|
||||||
root_dir_name = File.dirname(@path)
|
root_dir_name = File.dirname(@path)
|
||||||
|
|
||||||
@ -964,6 +971,11 @@ class Plugin::Instance
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
|
def validate_directory_column_name(column_name)
|
||||||
|
match = /^[_a-z]+$/.match(column_name)
|
||||||
|
raise "Invalid directory column name '#{column_name}'. Can only contain a-z and underscores" unless match
|
||||||
|
end
|
||||||
|
|
||||||
def write_asset(path, contents)
|
def write_asset(path, contents)
|
||||||
unless File.exists?(path)
|
unless File.exists?(path)
|
||||||
ensure_directory(path)
|
ensure_directory(path)
|
||||||
|
@ -83,9 +83,25 @@ describe DiscourseEvent do
|
|||||||
expect(harvey.job).to eq('Supervillain')
|
expect(harvey.job).to eq('Supervillain')
|
||||||
expect(harvey.name).to eq('Two Face')
|
expect(harvey.name).to eq('Two Face')
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
context '#all_off' do
|
||||||
|
|
||||||
|
let(:event_handler_2) do
|
||||||
|
Proc.new { |user| user.job = 'Supervillain' }
|
||||||
|
end
|
||||||
|
|
||||||
|
before do
|
||||||
|
DiscourseEvent.on(:acid_face, &event_handler_2)
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'removes all handlers with a key' do
|
||||||
|
harvey.job = 'gardening'
|
||||||
|
DiscourseEvent.all_off(:acid_face)
|
||||||
|
DiscourseEvent.trigger(:acid_face, harvey) # Doesn't change anything
|
||||||
|
expect(harvey.job).to eq('gardening')
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -600,4 +600,51 @@ describe Plugin::Instance do
|
|||||||
expect(ApiKeyScope.scope_mappings.dig(:groups, :create, :actions)).to contain_exactly(*actions)
|
expect(ApiKeyScope.scope_mappings.dig(:groups, :create, :actions)).to contain_exactly(*actions)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#add_directory_column' do
|
||||||
|
let!(:plugin) { Plugin::Instance.new }
|
||||||
|
|
||||||
|
before do
|
||||||
|
DirectoryItem.clear_plugin_queries
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
DirectoryColumn.clear_plugin_directory_columns
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "with valid column name" do
|
||||||
|
let(:column_name) { "random_c" }
|
||||||
|
|
||||||
|
before do
|
||||||
|
DB.exec("ALTER TABLE directory_items ADD COLUMN IF NOT EXISTS #{column_name} integer")
|
||||||
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
DB.exec("ALTER TABLE directory_items DROP COLUMN IF EXISTS #{column_name}")
|
||||||
|
DiscourseEvent.all_off("before_directory_refresh")
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'creates a directory column record when directory items are refreshed' do
|
||||||
|
plugin.add_directory_column(column_name, query: "SELECT COUNT(*) FROM users", icon: 'recycle')
|
||||||
|
expect(DirectoryColumn.find_by(name: column_name, icon: 'recycle', enabled: false)).not_to be_present
|
||||||
|
|
||||||
|
DirectoryItem.refresh!
|
||||||
|
expect(DirectoryColumn.find_by(name: column_name, icon: 'recycle', enabled: false)).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'errors when the column_name contains invalid characters' do
|
||||||
|
expect {
|
||||||
|
plugin.add_directory_column('Capital', query: "SELECT COUNT(*) FROM users", icon: 'recycle')
|
||||||
|
}.to raise_error(RuntimeError)
|
||||||
|
|
||||||
|
expect {
|
||||||
|
plugin.add_directory_column('has space', query: "SELECT COUNT(*) FROM users", icon: 'recycle')
|
||||||
|
}.to raise_error(RuntimeError)
|
||||||
|
|
||||||
|
expect {
|
||||||
|
plugin.add_directory_column('has_number_1', query: "SELECT COUNT(*) FROM users", icon: 'recycle')
|
||||||
|
}.to raise_error(RuntimeError)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -130,7 +130,7 @@ describe Admin::UserFieldsController do
|
|||||||
DirectoryColumn.create(
|
DirectoryColumn.create(
|
||||||
user_field_id: user_field.id,
|
user_field_id: user_field.id,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
automatic: false,
|
type: DirectoryColumn.types[:user_field],
|
||||||
position: next_position
|
position: next_position
|
||||||
)
|
)
|
||||||
expect {
|
expect {
|
||||||
|
@ -7,6 +7,17 @@ describe DirectoryColumnsController do
|
|||||||
fab!(:admin) { Fabricate(:admin) }
|
fab!(:admin) { Fabricate(:admin) }
|
||||||
|
|
||||||
describe "#index" do
|
describe "#index" do
|
||||||
|
it "returns all active directory columns" do
|
||||||
|
likes_given = DirectoryColumn.find_by(name: "likes_given")
|
||||||
|
likes_given.update(enabled: false)
|
||||||
|
|
||||||
|
get "/directory-columns.json"
|
||||||
|
|
||||||
|
expect(response.parsed_body["directory_columns"].map { |dc| dc["name"] }).not_to include("likes_given")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#edit-index" do
|
||||||
fab!(:public_user_field) { Fabricate(:user_field, show_on_profile: true) }
|
fab!(:public_user_field) { Fabricate(:user_field, show_on_profile: true) }
|
||||||
fab!(:private_user_field) { Fabricate(:user_field, show_on_profile: false, show_on_user_card: false) }
|
fab!(:private_user_field) { Fabricate(:user_field, show_on_profile: false, show_on_user_card: false) }
|
||||||
|
|
||||||
@ -14,13 +25,13 @@ describe DirectoryColumnsController do
|
|||||||
sign_in(admin)
|
sign_in(admin)
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
get "/directory-columns.json"
|
get "/edit-directory-columns.json"
|
||||||
}.to change { DirectoryColumn.count }.by(1)
|
}.to change { DirectoryColumn.count }.by(1)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns a 403 when not logged in as staff member" do
|
it "returns a 403 when not logged in as staff member" do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
get "/directory-columns.json"
|
get "/edit-directory-columns.json"
|
||||||
|
|
||||||
expect(response.status).to eq(404)
|
expect(response.status).to eq(404)
|
||||||
end
|
end
|
||||||
@ -50,7 +61,7 @@ describe DirectoryColumnsController do
|
|||||||
sign_in(admin)
|
sign_in(admin)
|
||||||
|
|
||||||
expect {
|
expect {
|
||||||
put "/directory-columns.json", params: params
|
put "/edit-directory-columns.json", params: params
|
||||||
}.to change { DirectoryColumn.find(first_directory_column_id).enabled }.from(true).to(false)
|
}.to change { DirectoryColumn.find(first_directory_column_id).enabled }.from(true).to(false)
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -59,14 +70,14 @@ describe DirectoryColumnsController do
|
|||||||
bad_params = params
|
bad_params = params
|
||||||
bad_params[:directory_columns][:"1"][:enabled] = false
|
bad_params[:directory_columns][:"1"][:enabled] = false
|
||||||
|
|
||||||
put "/directory-columns.json", params: bad_params
|
put "/edit-directory-columns.json", params: bad_params
|
||||||
|
|
||||||
expect(response.status).to eq(400)
|
expect(response.status).to eq(400)
|
||||||
end
|
end
|
||||||
|
|
||||||
it "returns a 404 when not logged in as a staff member" do
|
it "returns a 404 when not logged in as a staff member" do
|
||||||
sign_in(user)
|
sign_in(user)
|
||||||
put "/directory-columns.json", params: params
|
put "/edit-directory-columns.json", params: params
|
||||||
|
|
||||||
expect(response.status).to eq(404)
|
expect(response.status).to eq(404)
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user