DEV: Plugin API to allow creation of directory columns with item query (#13402)

DEV: Plugin API to allow creation of directory columns with item query (#13402)

The first thing we needed here was an enum rather than a boolean to determine how a directory_column was created. Now we have automatic, user_field and plugin directory columns.

This plugin API is assuming that the plugin has added a migration to a column to the directory_items table.

This was created to be initially used by discourse-solved. PR with API usage - Use `add_directory_column` API to add solutions count to user directory by markvanlan · Pull Request #137 · discourse/discourse-solved · GitHub

diff --git a/app/assets/javascripts/discourse/app/components/table-header-toggle.js b/app/assets/javascripts/discourse/app/components/table-header-toggle.js
index afe7ef3..424879f 100644
--- a/app/assets/javascripts/discourse/app/components/table-header-toggle.js
+++ b/app/assets/javascripts/discourse/app/components/table-header-toggle.js
@@ -9,6 +9,7 @@ export default Component.extend({
   chevronIcon: null,
   columnIcon: null,
   translated: false,
+  automatic: false,
   onActiveRender: null,
 
   toggleProperties() {
@@ -31,6 +32,9 @@ export default Component.extend({
   },
   didReceiveAttrs() {
     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.toggleChevron();
   },
diff --git a/app/assets/javascripts/discourse/app/controllers/edit-user-directory-columns.js b/app/assets/javascripts/discourse/app/controllers/edit-user-directory-columns.js
index a7fd826..21f2dd8 100644
--- a/app/assets/javascripts/discourse/app/controllers/edit-user-directory-columns.js
+++ b/app/assets/javascripts/discourse/app/controllers/edit-user-directory-columns.js
@@ -58,7 +58,7 @@ export default Controller.extend(ModalFunctionality, {
       .forEach((column, index) => {
         column.setProperties({
           position: column.automatic_position || index + 1,
-          enabled: column.automatic,
+          enabled: column.type === "automatic",
         });
       });
     this.set("columns", resetColumns);
diff --git a/app/assets/javascripts/discourse/app/controllers/users.js b/app/assets/javascripts/discourse/app/controllers/users.js
index e287882..1846b4e 100644
--- a/app/assets/javascripts/discourse/app/controllers/users.js
+++ b/app/assets/javascripts/discourse/app/controllers/users.js
@@ -28,13 +28,22 @@ export default Controller.extend({
     this.set("nameInput", params.name);
     this.set("order", params.order);
 
-    const custom_field_columns = this.columns.filter((c) => !c.automatic);
-    const user_field_ids = custom_field_columns
-      .map((c) => c.user_field_id)
-      .join("|");
+    const userFieldColumns = this.columns.filter(
+      (c) => c.type === "user_field"
+    );
+    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
-      .find("directoryItem", Object.assign(params, { user_field_ids }))
+      .find(
+        "directoryItem",
+        Object.assign(params, {
+          user_field_ids: userFieldIds,
+          plugin_column_ids: pluginColumnIds,
+        })
+      )
       .then((model) => {
         const lastUpdatedAt = model.get("resultSetMeta.last_updated_at");
         this.setProperties({
diff --git a/app/assets/javascripts/discourse/app/helpers/directory-item-helpers.js b/app/assets/javascripts/discourse/app/helpers/directory-item-helpers.js
new file mode 100644
index 0000000..1007a50
--- /dev/null
+++ b/app/assets/javascripts/discourse/app/helpers/directory-item-helpers.js
@@ -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";
+});
diff --git a/app/assets/javascripts/discourse/app/helpers/directory-item-label.js b/app/assets/javascripts/discourse/app/helpers/directory-item-label.js
deleted file mode 100644
index 56723ee..0000000
--- a/app/assets/javascripts/discourse/app/helpers/directory-item-label.js
+++ /dev/null
@@ -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 }));
-});
diff --git a/app/assets/javascripts/discourse/app/helpers/directory-item-user-field-value.js b/app/assets/javascripts/discourse/app/helpers/directory-item-user-field-value.js
deleted file mode 100644
index aeab4bc..0000000
--- a/app/assets/javascripts/discourse/app/helpers/directory-item-user-field-value.js
+++ /dev/null
@@ -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>`);
-  }
-);
diff --git a/app/assets/javascripts/discourse/app/helpers/directory-item-value.js b/app/assets/javascripts/discourse/app/helpers/directory-item-value.js
deleted file mode 100644
index a3c6e3d..0000000
--- a/app/assets/javascripts/discourse/app/helpers/directory-item-value.js
+++ /dev/null
@@ -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>`
-  );
-});
diff --git a/app/assets/javascripts/discourse/app/templates/components/directory-item.hbs b/app/assets/javascripts/discourse/app/templates/components/directory-item.hbs
index 0d4fece..b1b083b 100644
--- a/app/assets/javascripts/discourse/app/templates/components/directory-item.hbs
+++ b/app/assets/javascripts/discourse/app/templates/components/directory-item.hbs
@@ -1,10 +1,10 @@
 <td>{{user-info user=item.user}}</td>
 {{#each columns as |column|}}
   <td>
-    {{#if column.automatic}}
-      {{directory-item-value item=item column=column}}
-    {{else}}
+    {{#if (directory-column-is-user-field column=column)}}
       {{directory-item-user-field-value item=item column=column}}
+    {{else}}
+      {{directory-item-value item=item column=column}}
     {{/if}}
   </td>
 {{/each}}
diff --git a/app/assets/javascripts/discourse/app/templates/components/directory-table.hbs b/app/assets/javascripts/discourse/app/templates/components/directory-table.hbs
index 1aafa64..a646d79 100644
--- a/app/assets/javascripts/discourse/app/templates/components/directory-table.hbs

[... diff too long, it was truncated ...]

GitHub sha: 0c42a29dc4ad8e541d7b220623de09ec6354a12e

This commit appears in #13402 which was approved by eviltrout. It was merged by markvanlan.