Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 1764660

Browse files
committed
WIP
1 parent 6dc7632 commit 1764660

File tree

12 files changed

+400
-45
lines changed

12 files changed

+400
-45
lines changed
Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import DiscourseRoute from "discourse/routes/discourse";
22

33
export default class AdminPluginsShowDiscourseAiFeaturesEdit extends DiscourseRoute {
4-
model() {
5-
// todo
4+
async model(params) {
5+
const allFeatures = this.modelFor(
6+
"adminPlugins.show.discourse-ai-features"
7+
);
8+
const id = parseInt(params.id, 10);
9+
10+
return allFeatures.find((feature) => feature.id === id);
611
}
712
}
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import { ajax } from "discourse/lib/ajax";
1+
import { service } from "@ember/service";
22
import DiscourseRoute from "discourse/routes/discourse";
33

44
export default class AdminPluginsShowDiscourseAiFeatures extends DiscourseRoute {
5+
@service store;
6+
57
async model() {
6-
const { ai_features } = await ajax(
7-
`/admin/plugins/discourse-ai/ai-features.json`
8-
);
9-
return ai_features;
8+
return this.store.findAll("ai-feature");
109
}
1110
}
Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import RouteTemplate from "ember-route-template";
2+
import AiFeatureEditor from "discourse/plugins/discourse-ai/discourse/components/ai-feature-editor";
23

34
export default RouteTemplate(
4-
<template>
5-
<h1>AI Features EDIT</h1>
6-
</template>
5+
<template>
6+
<AiFeatureEditor @model={{@model}} />
7+
</template>
78
);

admin/assets/javascripts/discourse/templates/admin-plugins/show/discourse-ai-features/index.gjs

Lines changed: 94 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import Component from "@glimmer/component";
2+
import { get } from "@ember/helper";
23
import { service } from "@ember/service";
34
import RouteTemplate from "ember-route-template";
5+
import { gt } from "truth-helpers";
46
import DBreadcrumbsItem from "discourse/components/d-breadcrumbs-item";
57
import DButton from "discourse/components/d-button";
68
import DPageSubheader from "discourse/components/d-page-subheader";
@@ -9,55 +11,123 @@ import { i18n } from "discourse-i18n";
911
export default RouteTemplate(
1012
class extends Component {
1113
@service adminPluginNavManager;
14+
@service currentUser;
15+
16+
get tableHeaders() {
17+
const prefix = "discourse_ai.features.list.header";
18+
return [
19+
i18n(`${prefix}.name`),
20+
i18n(`${prefix}.persona`),
21+
i18n(`${prefix}.groups`),
22+
"",
23+
];
24+
}
1225

1326
<template>
1427
<DBreadcrumbsItem
1528
@path="/admin/plugins/{{this.adminPluginNavManager.currentPlugin.name}}/ai-features"
1629
@label={{i18n "discourse_ai.features.short_title"}}
1730
/>
18-
<section class="ai-feature-list-editor admin-detail">
31+
<section class="ai-feature-list admin-detail">
1932
<DPageSubheader
2033
@titleLabel={{i18n "discourse_ai.features.short_title"}}
2134
@descriptionLabel={{i18n "discourse_ai.features.description"}}
2235
@learnMoreUrl="todo"
2336
/>
2437

25-
<div class="ai-feature-list-editor__configured-features">
26-
<h3>Configured Features</h3>
38+
<div class="ai-feature-list__configured-features">
39+
<h3>{{i18n "discourse_ai.features.list.configured_features"}}</h3>
40+
2741
<table class="d-admin-table">
2842
<thead>
2943
<tr>
30-
<th>Name</th>
31-
<th>Persona</th>
32-
<th>Groups</th>
33-
<th></th>
44+
{{#each this.tableHeaders as |header|}}
45+
<th>{{header}}</th>
46+
{{/each}}
3447
</tr>
3548
</thead>
3649

3750
<tbody>
3851
{{#each @model as |feature|}}
39-
{{!-- {{log feature}} --}}
40-
<tr class="ai-features-list__row d-admin-row__content">
41-
<td class="d-admin-row__overview">
42-
<strong>{{feature.name}}</strong><br />
43-
{{feature.description}}
44-
</td>
45-
<td class="d-admin-row__detail">
46-
{{feature.persona}}
47-
</td>
48-
<td></td>
49-
<td class="d-admin-row_controls">
50-
<DButton @translatedLabel="Edit" />
51-
</td>
52-
</tr>
52+
{{#if feature.enabled}}
53+
<tr class="ai-feature-list__row d-admin-row__content">
54+
<td class="d-admin-row__overview ai-feature-list__row-item">
55+
<span class="ai-feature-list__row-item-name">
56+
<strong>
57+
{{feature.name}}
58+
</strong>
59+
</span>
60+
<span class="ai-feature-list__row-item-description">
61+
{{feature.description}}
62+
</span>
63+
</td>
64+
<td class="d-admin-row__detail ai-feature-list__row-item">
65+
{{feature.persona.name}}
66+
</td>
67+
<td class="d-admin-row__detail ai-feature-list__row-item">
68+
{{#if (gt feature.persona.allowed_groups.length 0)}}
69+
<ul class="ai-feature-list__row-item-groups">
70+
{{#each feature.persona.allowed_groups as |group|}}
71+
<li>{{group.name}}</li>
72+
{{/each}}
73+
</ul>
74+
{{/if}}
75+
</td>
76+
<td class="d-admin-row_controls">
77+
<DButton
78+
class="btn-small"
79+
@translatedLabel="Edit"
80+
@route="adminPlugins.show.discourse-ai-features.edit"
81+
@routeModels={{feature.id}}
82+
/>
83+
</td>
84+
</tr>
85+
{{/if}}
5386
{{/each}}
5487
</tbody>
5588
</table>
5689
</div>
5790

58-
{{! <div class="ai-feature-list-editor__unconfigured-features">
59-
<h3>Unconfigured Features</h3>
60-
</div> }}
91+
<div class="ai-feature-list-editor__unconfigured-features">
92+
<h3>{{i18n "discourse_ai.features.list.unconfigured_features"}}</h3>
93+
94+
<table class="d-admin-table">
95+
<thead>
96+
<tr>
97+
<th>{{i18n "discourse_ai.features.list.header.name"}}</th>
98+
<th></th>
99+
</tr>
100+
</thead>
101+
102+
<tbody>
103+
{{#each @model as |feature|}}
104+
{{#unless feature.enabled}}
105+
<tr class="ai-feature-list__row d-admin-row__content">
106+
<td class="d-admin-row__overview ai-feature-list__row-item">
107+
<span class="ai-feature-list__row-item-name">
108+
<strong>
109+
{{feature.name}}
110+
</strong>
111+
</span>
112+
<span class="ai-feature-list__row-item-description">
113+
{{feature.description}}
114+
</span>
115+
</td>
116+
117+
<td class="d-admin-row_controls">
118+
<DButton
119+
class="btn-small"
120+
@translatedLabel="Set up"
121+
@route="adminPlugins.show.discourse-ai-features.edit"
122+
@routeModels={{feature.id}}
123+
/>
124+
</td>
125+
</tr>
126+
{{/unless}}
127+
{{/each}}
128+
</tbody>
129+
</table>
130+
</div>
61131
</section>
62132
</template>
63133
}

app/controllers/discourse_ai/admin/ai_features_controller.rb

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ def index
1010
end
1111

1212
def edit
13+
raise Discourse::InvalidParameters.new(:id) if params[:id].blank?
14+
render json: find_feature_by_id(params[:id].to_i)
1315
end
1416

1517
def update
@@ -22,39 +24,79 @@ def destroy
2224

2325
# Eventually we may move this to an active record model
2426
def persona_backed_features
25-
# TODO: WIP just getting data rn, will cleanup AiPersona call later...
2627
[
2728
{
29+
id: 1,
2830
name: "Summaries",
2931
description:
3032
"Makes a summarization button available that allows visitors to summarize topics.",
31-
# persona: AiPersona.find_by(id: SiteSetting.ai_summarization_persona),
32-
persona: "Foo",
33+
persona:
34+
serialize_data(
35+
AiPersona.find_by(id: SiteSetting.ai_summarization_persona),
36+
AiFeaturesPersonaSerializer,
37+
root: false,
38+
),
3339
enabled: SiteSetting.ai_summarization_enabled,
40+
enable_setting: {
41+
type: SiteSetting.ai_summarization_enabled.class,
42+
value: "ai_summarization_enabled",
43+
},
3444
},
3545
{
46+
id: 2,
3647
name: "Short Summaries",
3748
description: "Adds the ability to view short summaries of topics on the topic list.",
38-
# persona: AiPersona.find_by(id: SiteSetting.ai_summary_gists_persona),
39-
persona: "Bar",
49+
persona:
50+
serialize_data(
51+
AiPersona.find_by(id: SiteSetting.ai_summary_gists_persona),
52+
AiFeaturesPersonaSerializer,
53+
root: false,
54+
),
4055
enabled: SiteSetting.ai_summary_gists_enabled,
56+
enable_setting: {
57+
type: SiteSetting.ai_summary_gists_enabled.class,
58+
value: "ai_summary_gists_enabled",
59+
},
4160
},
4261
{
62+
id: 3,
4363
name: "Discobot Discoveries",
44-
description: "",
45-
# persona: AiPersona.find_by(id: SiteSetting.ai_bot_discover_persona),
46-
persona: "Baz",
64+
description: "Enhances search experience by providing AI-generated answers to queries.",
65+
persona:
66+
serialize_data(
67+
AiPersona.find_by(id: SiteSetting.ai_bot_discover_persona),
68+
AiFeaturesPersonaSerializer,
69+
root: false,
70+
),
4771
enabled: SiteSetting.ai_bot_enabled,
72+
enable_setting: {
73+
type: SiteSetting.ai_bot_enabled.class,
74+
value: "ai_bot_enabled",
75+
},
4876
},
4977
{
78+
id: 4,
5079
name: "Discord Search",
5180
description: "Adds the ability to search Discord channels.",
52-
# persona: AiPersona.find_by(id: SiteSetting.ai_discord_search_persona),
53-
persona: "Qux",
54-
enabled: "",
81+
persona:
82+
serialize_data(
83+
AiPersona.find_by(id: SiteSetting.ai_discord_search_persona),
84+
AiFeaturesPersonaSerializer,
85+
root: false,
86+
),
87+
enabled: SiteSetting.ai_discord_app_id.present?,
88+
enable_setting: {
89+
type: SiteSetting.ai_discord_app_id.class,
90+
value: "ai_discord_app_id",
91+
},
5592
},
5693
]
5794
end
95+
96+
def find_feature_by_id(id)
97+
lookup = persona_backed_features.index_by { |feature| feature[:id] }
98+
lookup[id]
99+
end
58100
end
59101
end
60102
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# frozen_string_literal: true
2+
3+
class AiFeaturesPersonaSerializer < ApplicationSerializer
4+
attributes :id, :name, :system_prompt, :allowed_groups, :enabled
5+
6+
def allowed_groups
7+
Group
8+
.where(id: object.allowed_group_ids)
9+
.pluck(:id, :name)
10+
.map { |id, name| { id: id, name: name } }
11+
end
12+
end
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import RestAdapter from "discourse/adapters/rest";
2+
3+
export default class AiFeatureAdapter extends RestAdapter {
4+
jsonMode = true;
5+
6+
basePath() {
7+
return "/admin/plugins/discourse-ai/";
8+
}
9+
10+
pathFor(store, type, findArgs) {
11+
// removes underscores which are implemented in base
12+
let path =
13+
this.basePath(store, type, findArgs) +
14+
store.pluralize(this.apiNameFor(type));
15+
return this.appendQueryParams(path, findArgs);
16+
}
17+
18+
apiNameFor() {
19+
return "ai-feature";
20+
}
21+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { TrackedArray, TrackedObject } from "@ember-compat/tracked-built-ins";
2+
import RestModel from "discourse/models/rest";
3+
4+
export default class AiFeature extends RestModel {
5+
createProperties() {
6+
return this.getProperties(
7+
"id",
8+
"name",
9+
"description",
10+
"enabled",
11+
"enable_setting",
12+
"persona"
13+
);
14+
}
15+
16+
updateProperties() {
17+
const attrs = this.createProperties();
18+
19+
// TODO: add the ones to update
20+
// i.e. attrs.id = this.id;
21+
22+
return attrs;
23+
}
24+
}

0 commit comments

Comments
 (0)