DEV: [gjs-codemod] Convert all templates to gjs

This commit is contained in:
Jarek Radosz 2025-05-10 16:02:13 +02:00
parent bbb5147062
commit a2f0ce6381
No known key found for this signature in database
GPG Key ID: 98C198E7019429B3
31 changed files with 1300 additions and 723 deletions

View File

@ -14,30 +14,31 @@ GEM
securerandom (>= 0.3) securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5) tzinfo (~> 2.0, >= 2.0.5)
uri (>= 0.13.1) uri (>= 0.13.1)
ast (2.4.2) ast (2.4.3)
base64 (0.2.0) base64 (0.2.0)
benchmark (0.4.0) benchmark (0.4.0)
bigdecimal (3.1.9) bigdecimal (3.1.9)
concurrent-ruby (1.3.5) concurrent-ruby (1.3.5)
connection_pool (2.5.0) connection_pool (2.5.3)
drb (2.2.1) drb (2.2.1)
i18n (1.14.7) i18n (1.14.7)
concurrent-ruby (~> 1.0) concurrent-ruby (~> 1.0)
json (2.10.2) json (2.11.3)
language_server-protocol (3.17.0.4) language_server-protocol (3.17.0.4)
lint_roller (1.1.0) lint_roller (1.1.0)
logger (1.6.6) logger (1.7.0)
minitest (5.25.5) minitest (5.25.5)
parallel (1.26.3) parallel (1.27.0)
parser (3.3.7.1) parser (3.3.8.0)
ast (~> 2.4.1) ast (~> 2.4.1)
racc racc
prettier_print (1.2.1) prettier_print (1.2.1)
prism (1.4.0)
racc (1.8.1) racc (1.8.1)
rack (3.1.12) rack (3.1.14)
rainbow (3.1.1) rainbow (3.1.1)
regexp_parser (2.10.0) regexp_parser (2.10.0)
rubocop (1.74.0) rubocop (1.75.5)
json (~> 2.3) json (~> 2.3)
language_server-protocol (~> 3.17.0.2) language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0) lint_roller (~> 1.1.0)
@ -45,11 +46,12 @@ GEM
parser (>= 3.3.0.2) parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0) rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0) regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.38.0, < 2.0) rubocop-ast (>= 1.44.0, < 2.0)
ruby-progressbar (~> 1.7) ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0) unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.38.1) rubocop-ast (1.44.1)
parser (>= 3.3.1.0) parser (>= 3.3.7.2)
prism (~> 1.4)
rubocop-capybara (2.22.1) rubocop-capybara (2.22.1)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1) rubocop (~> 1.72, >= 1.72.1)
@ -65,13 +67,13 @@ GEM
rubocop-factory_bot (2.27.1) rubocop-factory_bot (2.27.1)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1) rubocop (~> 1.72, >= 1.72.1)
rubocop-rails (2.30.3) rubocop-rails (2.31.0)
activesupport (>= 4.2.0) activesupport (>= 4.2.0)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rack (>= 1.1) rack (>= 1.1)
rubocop (>= 1.72.1, < 2.0) rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.38.0, < 2.0) rubocop-ast (>= 1.38.0, < 2.0)
rubocop-rspec (3.5.0) rubocop-rspec (3.6.0)
lint_roller (~> 1.1) lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1) rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec_rails (2.31.0) rubocop-rspec_rails (2.31.0)
@ -97,4 +99,4 @@ DEPENDENCIES
syntax_tree syntax_tree
BUNDLED WITH BUNDLED WITH
2.6.6 2.6.8

View File

@ -0,0 +1,15 @@
import avatar from "discourse/helpers/avatar";
const AssignedTo = <template>
<div class="assigned-to-user">
{{avatar @user imageSize="small"}}
<span class="assigned-username">
{{@user.username}}
</span>
{{yield}}
</div>
</template>;
export default AssignedTo;

View File

@ -1,9 +0,0 @@
<div class="assigned-to-user">
{{avatar @user imageSize="small"}}
<span class="assigned-username">
{{@user.username}}
</span>
{{yield}}
</div>

View File

@ -0,0 +1,35 @@
import { and } from "truth-helpers";
import UserStatusMessage from "discourse/components/user-status-message";
import avatar from "discourse/helpers/avatar";
import icon from "discourse/helpers/d-icon";
import decorateUsernameSelector from "discourse/helpers/decorate-username-selector";
import formatUsername from "discourse/helpers/format-username";
import EmailGroupUserChooserRow from "select-kit/components/email-group-user-chooser-row";
export default class AssigneeChooserRow extends EmailGroupUserChooserRow {
<template>
{{#if this.item.isUser}}
{{avatar this.item imageSize="tiny"}}
<div class="user-wrapper">
<span class="identifier">{{formatUsername this.item.id}}</span>
<span class="name">{{this.item.name}}</span>
{{#if (and this.item.showUserStatus this.item.status)}}
<UserStatusMessage
@status={{this.item.status}}
@showDescription={{true}}
/>
{{/if}}
</div>
{{decorateUsernameSelector this.item.id}}
{{else if this.item.isGroup}}
{{icon "users"}}
<div class="user-wrapper">
<span class="identifier">{{this.item.id}}</span>
<span class="name">{{this.item.full_name}}</span>
</div>
{{else}}
{{icon "envelope"}}
<span class="identifier">{{this.item.id}}</span>
{{/if}}
</template>
}

View File

@ -1,23 +0,0 @@
{{#if this.item.isUser}}
{{avatar this.item imageSize="tiny"}}
<div class="user-wrapper">
<span class="identifier">{{format-username this.item.id}}</span>
<span class="name">{{this.item.name}}</span>
{{#if (and this.item.showUserStatus this.item.status)}}
<UserStatusMessage
@status={{this.item.status}}
@showDescription={{true}}
/>
{{/if}}
</div>
{{decorate-username-selector this.item.id}}
{{else if this.item.isGroup}}
{{d-icon "users"}}
<div class="user-wrapper">
<span class="identifier">{{this.item.id}}</span>
<span class="name">{{this.item.full_name}}</span>
</div>
{{else}}
{{d-icon "envelope"}}
<span class="identifier">{{this.item.id}}</span>
{{/if}}

View File

@ -1,3 +0,0 @@
import EmailGroupUserChooserRow from "select-kit/components/email-group-user-chooser-row";
export default class AssigneeChooserRow extends EmailGroupUserChooserRow {}

View File

@ -4,10 +4,10 @@ import { TextArea } from "@ember/legacy-built-in-components";
import { on } from "@ember/modifier"; import { on } from "@ember/modifier";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { service } from "@ember/service"; import { service } from "@ember/service";
import { not } from "truth-helpers";
import icon from "discourse/helpers/d-icon"; import icon from "discourse/helpers/d-icon";
import { i18n } from "discourse-i18n"; import { i18n } from "discourse-i18n";
import ComboBox from "select-kit/components/combo-box"; import ComboBox from "select-kit/components/combo-box";
import not from "truth-helpers/helpers/not";
import AssigneeChooser from "./assignee-chooser"; import AssigneeChooser from "./assignee-chooser";
export default class Assignment extends Component { export default class Assignment extends Component {

View File

@ -1,6 +1,8 @@
import Component from "@glimmer/component"; import Component from "@glimmer/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { TrackedObject } from "@ember-compat/tracked-built-ins"; import { TrackedObject } from "@ember-compat/tracked-built-ins";
import DButton from "discourse/components/d-button";
import AssignUserForm from "../assign-user-form";
export default class AssignUser extends Component { export default class AssignUser extends Component {
model = new TrackedObject({}); model = new TrackedObject({});
@ -19,4 +21,26 @@ export default class AssignUser extends Component {
note: this.model.note, note: this.model.note,
}); });
} }
<template>
<div>
<AssignUserForm
@model={{this.model}}
@onSubmit={{this.assign}}
@formApi={{this.formApi}}
/>
</div>
<div>
<DButton
class="btn-primary"
@action={{this.formApi.submit}}
@label={{if
this.model.reassign
"discourse_assign.reassign.title"
"discourse_assign.assign_modal.assign"
}}
/>
</div>
</template>
} }

View File

@ -1,19 +0,0 @@
<div>
<AssignUserForm
@model={{this.model}}
@onSubmit={{this.assign}}
@formApi={{this.formApi}}
/>
</div>
<div>
<DButton
class="btn-primary"
@action={{this.formApi.submit}}
@label={{if
this.model.reassign
"discourse_assign.reassign.title"
"discourse_assign.assign_modal.assign"
}}
/>
</div>

View File

@ -0,0 +1,66 @@
import { hash } from "@ember/helper";
import { LinkTo } from "@ember/routing";
import avatar from "discourse/helpers/avatar";
import icon from "discourse/helpers/d-icon";
import formatUsername from "discourse/helpers/format-username";
import { i18n } from "discourse-i18n";
const GroupAssignedFilter = <template>
<li>
{{#if @showAvatar}}
<LinkTo
@route="group.assigned.show"
@model={{@filter.username_lower}}
@query={{hash order=@order ascending=@ascending search=@search}}
>
<div class="assign-image">
<a
href={{@filter.userPath}}
data-user-card={{@filter.username}}
>{{avatar this.filter imageSize="large"}}</a>
</div>
<div class="assign-names">
<div class="assign-username">{{formatUsername @filter.username}}</div>
<div class="assign-name">{{@filter.name}}</div>
</div>
<div class="assign-count">
{{@filter.assignments_count}}
</div>
</LinkTo>
{{else if @groupName}}
<LinkTo
@route="group.assigned.show"
@model={{@filter}}
@query={{hash order=@order ascending=@ascending search=@search}}
>
<div class="assign-image">
{{icon "group-plus"}}
</div>
<div class="assign-names">
<div class="assign-username">{{@groupName}}</div>
</div>
<div class="assign-count">
{{@assignmentCount}}
</div>
</LinkTo>
{{else}}
<LinkTo
@route="group.assigned.show"
@model={{@filter}}
@query={{hash order=@order ascending=@ascending search=@search}}
>
<div class="assign-everyone">
{{i18n "discourse_assign.group_everyone"}}
</div>
<div class="assign-count">
{{@assignmentCount}}
</div>
</LinkTo>
{{/if}}
</li>
</template>;
export default GroupAssignedFilter;

View File

@ -1,55 +0,0 @@
<li>
{{#if @showAvatar}}
<LinkTo
@route="group.assigned.show"
@model={{@filter.username_lower}}
@query={{hash order=@order ascending=@ascending search=@search}}
>
<div class="assign-image">
<a
href={{@filter.userPath}}
data-user-card={{@filter.username}}
>{{avatar this.filter imageSize="large"}}</a>
</div>
<div class="assign-names">
<div class="assign-username">{{format-username @filter.username}}</div>
<div class="assign-name">{{@filter.name}}</div>
</div>
<div class="assign-count">
{{@filter.assignments_count}}
</div>
</LinkTo>
{{else if @groupName}}
<LinkTo
@route="group.assigned.show"
@model={{@filter}}
@query={{hash order=@order ascending=@ascending search=@search}}
>
<div class="assign-image">
{{d-icon "group-plus"}}
</div>
<div class="assign-names">
<div class="assign-username">{{@groupName}}</div>
</div>
<div class="assign-count">
{{@assignmentCount}}
</div>
</LinkTo>
{{else}}
<LinkTo
@route="group.assigned.show"
@model={{@filter}}
@query={{hash order=@order ascending=@ascending search=@search}}
>
<div class="assign-everyone">
{{i18n "discourse_assign.group_everyone"}}
</div>
<div class="assign-count">
{{@assignmentCount}}
</div>
</LinkTo>
{{/if}}
</li>

View File

@ -0,0 +1,12 @@
import { LinkTo } from "@ember/routing";
import icon from "discourse/helpers/d-icon";
import { i18n } from "discourse-i18n";
const GroupAssignedMenuItem = <template>
<LinkTo @route="group.assigned">
{{icon "group-plus" class="glyph"}}{{i18n "discourse_assign.assigned"}}
({{@group.assignment_count}})
</LinkTo>
</template>;
export default GroupAssignedMenuItem;

View File

@ -1,4 +0,0 @@
<LinkTo @route="group.assigned">
{{d-icon "group-plus" class="glyph"}}{{i18n "discourse_assign.assigned"}}
({{@group.assignment_count}})
</LinkTo>

View File

@ -2,7 +2,11 @@ import Component from "@glimmer/component";
import { action } from "@ember/object"; import { action } from "@ember/object";
import { service } from "@ember/service"; import { service } from "@ember/service";
import { TrackedObject } from "@ember-compat/tracked-built-ins"; import { TrackedObject } from "@ember-compat/tracked-built-ins";
import DButton from "discourse/components/d-button";
import DModal from "discourse/components/d-modal";
import DModalCancel from "discourse/components/d-modal-cancel";
import { i18n } from "discourse-i18n"; import { i18n } from "discourse-i18n";
import AssignUserForm from "../assign-user-form";
export default class AssignUser extends Component { export default class AssignUser extends Component {
@service taskActions; @service taskActions;
@ -38,4 +42,30 @@ export default class AssignUser extends Component {
this.args.closeModal(); this.args.closeModal();
await this.taskActions.assign(this.model); await this.taskActions.assign(this.model);
} }
<template>
<DModal class="assign" @title={{this.title}} @closeModal={{@closeModal}}>
<:body>
<AssignUserForm
@model={{this.model}}
@onSubmit={{this.onSubmit}}
@formApi={{this.formApi}}
/>
</:body>
<:footer>
<DButton
class="btn-primary"
@action={{this.formApi.submit}}
@label={{if
this.model.reassign
"discourse_assign.reassign.title"
"discourse_assign.assign_modal.assign"
}}
/>
<DModalCancel @close={{@closeModal}} />
</:footer>
</DModal>
</template>
} }

View File

@ -1,23 +0,0 @@
<DModal class="assign" @title={{this.title}} @closeModal={{@closeModal}}>
<:body>
<AssignUserForm
@model={{this.model}}
@onSubmit={{this.onSubmit}}
@formApi={{this.formApi}}
/>
</:body>
<:footer>
<DButton
class="btn-primary"
@action={{this.formApi.submit}}
@label={{if
this.model.reassign
"discourse_assign.reassign.title"
"discourse_assign.assign_modal.assign"
}}
/>
<DModalCancel @close={{@closeModal}} />
</:footer>
</DModal>

View File

@ -1,6 +1,7 @@
import Component from "@ember/component"; import Component from "@ember/component";
import discourseComputed from "discourse/lib/decorators"; import discourseComputed from "discourse/lib/decorators";
import { i18n } from "discourse-i18n"; import { i18n } from "discourse-i18n";
import ComboBox from "select-kit/components/combo-box";
export default class RemindAssignsFrequency extends Component { export default class RemindAssignsFrequency extends Component {
@discourseComputed( @discourseComputed(
@ -27,4 +28,23 @@ export default class RemindAssignsFrequency extends Component {
selected: false, selected: false,
})); }));
} }
<template>
{{#if this.siteSettings.assign_enabled}}
<div class="controls controls-dropdown">
<label>{{i18n
"discourse_assign.reminders_frequency.description"
}}</label>
<ComboBox
@id="remind-assigns-frequency"
@valueProperty="value"
@content={{this.availableFrequencies}}
@value={{this.selectedFrequency}}
@onChange={{action
(mut this.user.custom_fields.remind_assigns_frequency)
}}
/>
</div>
{{/if}}
</template>
} }

View File

@ -1,14 +0,0 @@
{{#if this.siteSettings.assign_enabled}}
<div class="controls controls-dropdown">
<label>{{i18n "discourse_assign.reminders_frequency.description"}}</label>
<ComboBox
@id="remind-assigns-frequency"
@valueProperty="value"
@content={{this.availableFrequencies}}
@value={{this.selectedFrequency}}
@onChange={{action
(mut this.user.custom_fields.remind_assigns_frequency)
}}
/>
</div>
{{/if}}

View File

@ -0,0 +1,25 @@
import icon from "discourse/helpers/d-icon";
import getUrl from "discourse/helpers/get-url";
import htmlSafe from "discourse/helpers/html-safe";
import { i18n } from "discourse-i18n";
const AssignsListEmptyState = <template>
<div class="empty-state">
<span class="empty-state-title">
{{i18n "user.no_assignments_title"}}
</span>
<div class="empty-state-body">
<p>
{{htmlSafe
(i18n
"user.no_assignments_body"
icon=(icon "user-plus")
preferencesUrl=(getUrl "/my/preferences/notifications")
)
}}
</p>
</div>
</div>
</template>;
export default AssignsListEmptyState;

View File

@ -1,16 +0,0 @@
<div class="empty-state">
<span class="empty-state-title">
{{i18n "user.no_assignments_title"}}
</span>
<div class="empty-state-body">
<p>
{{html-safe
(i18n
"user.no_assignments_body"
icon=(d-icon "user-plus")
preferencesUrl=(get-url "/my/preferences/notifications")
)
}}
</p>
</div>
</div>

View File

@ -0,0 +1,54 @@
import { Input } from "@ember/component";
import { on } from "@ember/modifier";
import RouteTemplate from "ember-route-template";
import BasicTopicList from "discourse/components/basic-topic-list";
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
import LoadMore from "discourse/components/load-more";
import withEventValue from "discourse/helpers/with-event-value";
import { i18n } from "discourse-i18n";
export default RouteTemplate(
<template>
<div class="topic-search-div">
<div class="inline-form full-width">
<Input
{{on "input" (withEventValue @controller.onChangeFilter)}}
@value={{readonly @controller.search}}
@type="search"
placeholder={{i18n "discourse_assign.topic_search_placeholder"}}
autocomplete="off"
class="no-blur"
/>
</div>
</div>
<LoadMore
@selector=".paginated-topics-list .topic-list tr"
@action={{@controller.loadMore}}
class="paginated-topics-list"
>
<BasicTopicList
@topicList={{@controller.model}}
@hideCategory={{@controller.hideCategory}}
@showPosters={{@controller.showPosters}}
@bulkSelectEnabled={{@controller.bulkSelectEnabled}}
@canBulkSelect={{@controller.canBulkSelect}}
@selected={{@controller.selected}}
@hasIncoming={{@controller.hasIncoming}}
@incomingCount={{@controller.incomingCount}}
@showInserted={{@controller.showInserted}}
@tagsForUser={{@controller.tagsForUser}}
@changeSort={{@controller.changeSort}}
@toggleBulkSelect={{@controller.toggleBulkSelect}}
@bulkSelectAction={{@controller.refresh}}
@bulkSelectHelper={{@controller.bulkSelectHelper}}
@unassign={{@controller.unassign}}
@reassign={{@controller.reassign}}
@onScroll={{@controller.saveScrollPosition}}
@scrollOnLoad={{true}}
/>
<ConditionalLoadingSpinner @condition={{@controller.model.loadingMore}} />
</LoadMore>
</template>
);

View File

@ -1,41 +0,0 @@
<div class="topic-search-div">
<div class="inline-form full-width">
<Input
{{on "input" (action "onChangeFilter" value="target.value")}}
@value={{readonly this.search}}
@type="search"
placeholder={{i18n "discourse_assign.topic_search_placeholder"}}
autocomplete="off"
class="no-blur"
/>
</div>
</div>
<LoadMore
@selector=".paginated-topics-list .topic-list tr"
@action={{action "loadMore"}}
class="paginated-topics-list"
>
<BasicTopicList
@topicList={{this.model}}
@hideCategory={{this.hideCategory}}
@showPosters={{this.showPosters}}
@bulkSelectEnabled={{this.bulkSelectEnabled}}
@canBulkSelect={{this.canBulkSelect}}
@selected={{this.selected}}
@hasIncoming={{this.hasIncoming}}
@incomingCount={{this.incomingCount}}
@showInserted={{action "showInserted"}}
@tagsForUser={{this.tagsForUser}}
@changeSort={{action "changeSort"}}
@toggleBulkSelect={{action "toggleBulkSelect"}}
@bulkSelectAction={{action "refresh"}}
@bulkSelectHelper={{this.bulkSelectHelper}}
@unassign={{action "unassign"}}
@reassign={{action "reassign"}}
@onScroll={{this.saveScrollPosition}}
@scrollOnLoad={{true}}
/>
<ConditionalLoadingSpinner @condition={{this.model.loadingMore}} />
</LoadMore>

View File

@ -0,0 +1,77 @@
import { Input } from "@ember/component";
import { on } from "@ember/modifier";
import RouteTemplate from "ember-route-template";
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
import LoadMore from "discourse/components/load-more";
import MobileNav from "discourse/components/mobile-nav";
import bodyClass from "discourse/helpers/body-class";
import withEventValue from "discourse/helpers/with-event-value";
import { i18n } from "discourse-i18n";
import GroupAssignedFilter from "../../components/group-assigned-filter";
export default RouteTemplate(
<template>
<section class="user-secondary-navigation group-assignments">
{{bodyClass "group-assign"}}
<MobileNav
@desktopClass="action-list activity-list nav-stacked"
class="activity-nav"
>
{{#if @controller.isDesktop}}
<div class="search-div">
<Input
{{on "input" (withEventValue @controller.onChangeFilterName)}}
@type="text"
@value={{readonly @controller.filterName}}
placeholder={{i18n
"discourse_assign.sidebar_name_filter_placeholder"
}}
class="search"
/>
</div>
{{/if}}
<LoadMore @selector=".activity-nav li" @action={{@controller.loadMore}}>
<GroupAssignedFilter
@showAvatar={{false}}
@filter="everyone"
@routeType={{@controller.route_type}}
@assignmentCount={{@controller.group.assignment_count}}
@search={{@controller.search}}
@ascending={{@controller.ascending}}
@order={{@controller.order}}
/>
<GroupAssignedFilter
@showAvatar={{false}}
@groupName={{@controller.group.name}}
@filter={{@controller.group.name}}
@routeType={{@controller.route_type}}
@assignmentCount={{@controller.group.group_assignment_count}}
@search={{@controller.search}}
@ascending={{@controller.ascending}}
@order={{@controller.order}}
/>
{{#each @controller.members as |member|}}
<GroupAssignedFilter
@showAvatar={{true}}
@filter={{member}}
@routeType={{@controller.route_type}}
@search={{@controller.search}}
@ascending={{@controller.ascending}}
@order={{@controller.order}}
/>
{{/each}}
<ConditionalLoadingSpinner @condition={{@controller.loading}} />
</LoadMore>
</MobileNav>
</section>
<section class="user-content">
{{outlet}}
</section>
</template>
);

View File

@ -1,61 +0,0 @@
<section class="user-secondary-navigation group-assignments">
{{body-class "group-assign"}}
<MobileNav
@desktopClass="action-list activity-list nav-stacked"
class="activity-nav"
>
{{#if this.isDesktop}}
<div class="search-div">
<Input
{{on "input" (action this.onChangeFilterName value="target.value")}}
@type="text"
@value={{readonly this.filterName}}
placeholder={{i18n
"discourse_assign.sidebar_name_filter_placeholder"
}}
class="search"
/>
</div>
{{/if}}
<LoadMore @selector=".activity-nav li" @action={{action "loadMore"}}>
<GroupAssignedFilter
@showAvatar={{false}}
@filter="everyone"
@routeType={{this.route_type}}
@assignmentCount={{this.group.assignment_count}}
@search={{this.search}}
@ascending={{this.ascending}}
@order={{this.order}}
/>
<GroupAssignedFilter
@showAvatar={{false}}
@groupName={{this.group.name}}
@filter={{this.group.name}}
@routeType={{this.route_type}}
@assignmentCount={{this.group.group_assignment_count}}
@search={{this.search}}
@ascending={{this.ascending}}
@order={{this.order}}
/>
{{#each this.members as |member|}}
<GroupAssignedFilter
@showAvatar={{true}}
@filter={{member}}
@routeType={{this.route_type}}
@search={{this.search}}
@ascending={{this.ascending}}
@order={{this.order}}
/>
{{/each}}
<ConditionalLoadingSpinner @condition={{this.loading}} />
</LoadMore>
</MobileNav>
</section>
<section class="user-content">
{{outlet}}
</section>

View File

@ -0,0 +1,27 @@
import RouteTemplate from "ember-route-template";
import DButton from "discourse/components/d-button";
import AssignUserForm from "../../components/assign-user-form";
export default RouteTemplate(
<template>
<div>
<AssignUserForm
@model={{@controller.model}}
@onSubmit={{@controller.assign}}
@formApi={{@controller.formApi}}
/>
</div>
<div>
<DButton
class="btn-primary"
@action={{@controller.formApi.submit}}
@label={{if
@controller.model.reassign
"discourse_assign.reassign.title"
"discourse_assign.assign_modal.assign"
}}
/>
</div>
</template>
);

View File

@ -1,19 +0,0 @@
<div>
<AssignUserForm
@model={{this.model}}
@onSubmit={{this.assign}}
@formApi={{this.formApi}}
/>
</div>
<div>
<DButton
class="btn-primary"
@action={{this.formApi.submit}}
@label={{if
this.model.reassign
"discourse_assign.reassign.title"
"discourse_assign.assign_modal.assign"
}}
/>
</div>

View File

@ -0,0 +1,60 @@
import { Input } from "@ember/component";
import { on } from "@ember/modifier";
import RouteTemplate from "ember-route-template";
import BasicTopicList from "discourse/components/basic-topic-list";
import ConditionalLoadingSpinner from "discourse/components/conditional-loading-spinner";
import EmptyState from "discourse/components/empty-state";
import LoadMore from "discourse/components/load-more";
import withEventValue from "discourse/helpers/with-event-value";
import { i18n } from "discourse-i18n";
export default RouteTemplate(
<template>
{{#if @controller.doesntHaveAssignments}}
<EmptyState
@title={{i18n "user.no_assignments_title"}}
@body={{@controller.emptyStateBody}}
/>
{{else}}
<div class="topic-search-div">
<div class="inline-form full-width">
<Input
{{on "input" (withEventValue "onChangeFilter")}}
@value={{readonly @controller.search}}
@type="search"
placeholder={{i18n "discourse_assign.topic_search_placeholder"}}
autocomplete="off"
class="no-blur"
/>
</div>
</div>
<LoadMore
@selector=".paginated-topics-list .topic-list tr"
@action={{@controller.loadMore}}
class="paginated-topics-list"
>
<BasicTopicList
@topicList={{@controller.model}}
@hideCategory={{@controller.hideCategory}}
@showPosters={{true}}
@bulkSelectEnabled={{@controller.bulkSelectEnabled}}
@selected={{@controller.selected}}
@hasIncoming={{@controller.hasIncoming}}
@incomingCount={{@controller.incomingCount}}
@showInserted={{@controller.showInserted}}
@tagsForUser={{@controller.tagsForUser}}
@changeSort={{@controller.changeSort}}
@unassign={{@controller.unassign}}
@reassign={{@controller.reassign}}
@onScroll={{@controller.saveScrollPosition}}
@scrollOnLoad={{true}}
/>
<ConditionalLoadingSpinner
@condition={{@controller.model.loadingMore}}
/>
</LoadMore>
{{/if}}
</template>
);

View File

@ -1,44 +0,0 @@
{{#if this.doesntHaveAssignments}}
<EmptyState
@title={{i18n "user.no_assignments_title"}}
@body={{this.emptyStateBody}}
/>
{{else}}
<div class="topic-search-div">
<div class="inline-form full-width">
<Input
{{on "input" (action "onChangeFilter" value="target.value")}}
@value={{readonly this.search}}
@type="search"
placeholder={{i18n "discourse_assign.topic_search_placeholder"}}
autocomplete="off"
class="no-blur"
/>
</div>
</div>
<LoadMore
@selector=".paginated-topics-list .topic-list tr"
@action={{action "loadMore"}}
class="paginated-topics-list"
>
<BasicTopicList
@topicList={{this.model}}
@hideCategory={{this.hideCategory}}
@showPosters={{true}}
@bulkSelectEnabled={{this.bulkSelectEnabled}}
@selected={{this.selected}}
@hasIncoming={{this.hasIncoming}}
@incomingCount={{this.incomingCount}}
@showInserted={{this.showInserted}}
@tagsForUser={{this.tagsForUser}}
@changeSort={{this.changeSort}}
@unassign={{this.unassign}}
@reassign={{this.reassign}}
@onScroll={{this.saveScrollPosition}}
@scrollOnLoad={{true}}
/>
<ConditionalLoadingSpinner @condition={{this.model.loadingMore}} />
</LoadMore>
{{/if}}

View File

@ -0,0 +1,20 @@
import { LinkTo } from "@ember/routing";
import RouteTemplate from "ember-route-template";
import MessagesSecondaryNav from "discourse/components/user-nav/messages-secondary-nav";
import icon from "discourse/helpers/d-icon";
import { i18n } from "discourse-i18n";
export default RouteTemplate(
<template>
<MessagesSecondaryNav>
<li class="messages-assigned-latest">
<LinkTo @route="userPrivateMessages.assigned.index">
{{icon "envelope"}}
<span>{{i18n "categories.latest"}}</span>
</LinkTo>
</li>
</MessagesSecondaryNav>
{{outlet}}
</template>
);

View File

@ -1,10 +0,0 @@
<UserNav::MessagesSecondaryNav>
<li class="messages-assigned-latest">
<LinkTo @route="userPrivateMessages.assigned.index">
{{d-icon "envelope"}}
<span>{{i18n "categories.latest"}}</span>
</LinkTo>
</li>
</UserNav::MessagesSecondaryNav>
{{outlet}}

View File

@ -1,11 +1,11 @@
{ {
"private": true, "private": true,
"devDependencies": { "devDependencies": {
"@discourse/lint-configs": "2.11.1", "@discourse/lint-configs": "2.16.1",
"ember-template-lint": "7.0.1", "ember-template-lint": "7.6.0",
"eslint": "9.22.0", "eslint": "9.26.0",
"prettier": "3.5.3", "prettier": "3.5.3",
"stylelint": "16.16.0" "stylelint": "16.19.1"
}, },
"engines": { "engines": {
"node": ">= 22", "node": ">= 22",

File diff suppressed because it is too large Load Diff