DEV: Update linting config and run gjs-codemod

This commit is contained in:
Jarek Radosz 2025-06-05 12:34:28 +02:00 committed by GitHub
parent bbb5147062
commit 5a5d3da950
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
53 changed files with 1105 additions and 946 deletions

View File

@ -1,3 +1,4 @@
< 3.5.0.beta5-dev: 6dcdcfdd24fde2587a15ed08caf299ec33751d06
< 3.5.0.beta3-dev: 261a47d119d200a8d922d008ad3d1667df869435
< 3.5.0.beta2-dev: bf2a4bdb3ea4e26ec493d8dbc1f4cc8680f6c543
< 3.5.0.beta1-dev: 698b5be85cc1a31707d528fe0d3c3c07c939c1df

View File

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

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 { action } from "@ember/object";
import { service } from "@ember/service";
import { not } from "truth-helpers";
import icon from "discourse/helpers/d-icon";
import { i18n } from "discourse-i18n";
import ComboBox from "select-kit/components/combo-box";
import not from "truth-helpers/helpers/not";
import AssigneeChooser from "./assignee-chooser";
export default class Assignment extends Component {

View File

@ -1,6 +1,8 @@
import Component from "@glimmer/component";
import { action } from "@ember/object";
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 {
model = new TrackedObject({});
@ -19,4 +21,26 @@ export default class AssignUser extends Component {
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 { service } from "@ember/service";
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 AssignUserForm from "../assign-user-form";
export default class AssignUser extends Component {
@service taskActions;
@ -38,4 +42,30 @@ export default class AssignUser extends Component {
this.args.closeModal();
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 discourseComputed from "discourse/lib/decorators";
import { i18n } from "discourse-i18n";
import ComboBox from "select-kit/components/combo-box";
export default class RemindAssignsFrequency extends Component {
@discourseComputed(
@ -27,4 +28,23 @@ export default class RemindAssignsFrequency extends Component {
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

@ -1,7 +1,10 @@
import Component from "@ember/component";
import { hash } from "@ember/helper";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { classNames } from "@ember-decorators/component";
import { i18n } from "discourse-i18n";
import EmailGroupUserChooser from "select-kit/components/email-group-user-chooser";
@classNames("assigned-to-filter")
export default class AssignedToFilter extends Component {
@ -23,4 +26,24 @@ export default class AssignedToFilter extends Component {
updateAssignedTo(selected) {
this.set("outletArgs.additionalFilters.assigned_to", selected.firstObject);
}
<template>
<div class="reviewable-filter discourse-assign-assign-to-filter">
<label class="filter-label">{{i18n
"discourse_assign.assigned_to"
}}</label>
<EmailGroupUserChooser
@value={{this.outletArgs.additionalFilters.assigned_to}}
@onChange={{this.updateAssignedTo}}
@options={{hash
maximum=1
fullWidthWrap=true
includeGroups=false
groupMembersOf=this.allowedGroups
}}
autocomplete="off"
/>
</div>
</template>
}

View File

@ -1,15 +0,0 @@
<div class="reviewable-filter discourse-assign-assign-to-filter">
<label class="filter-label">{{i18n "discourse_assign.assigned_to"}}</label>
<EmailGroupUserChooser
@value={{this.outletArgs.additionalFilters.assigned_to}}
@onChange={{this.updateAssignedTo}}
@options={{hash
maximum=1
fullWidthWrap=true
includeGroups=false
groupMembersOf=this.allowedGroups
}}
autocomplete="off"
/>
</div>

View File

@ -0,0 +1,46 @@
import Component from "@ember/component";
import { hash } from "@ember/helper";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { classNames } from "@ember-decorators/component";
import { i18n } from "discourse-i18n";
import EmailGroupUserChooser from "select-kit/components/email-group-user-chooser";
@classNames("assigned-advanced-search")
export default class AssignedAdvancedSearch extends Component {
static shouldRender(args, component) {
return component.currentUser?.can_assign;
}
@service currentUser;
@action
onChangeAssigned(value) {
this.outletArgs.onChangeSearchedTermField(
"assigned",
"updateSearchTermForAssignedUsername",
value
);
}
<template>
<div class="control-group">
<label class="control-label" for="search-assigned-to">
{{i18n "search.advanced.assigned.label"}}
</label>
<div class="controls">
<EmailGroupUserChooser
@value={{this.outletArgs.searchedTerms.assigned}}
@onChange={{this.onChangeAssigned}}
@options={{hash
maximum=1
excludeCurrentUser=false
includeGroups=true
customSearchOptions=(hash assignableGroups=true)
}}
/>
</div>
</div>
</template>
}

View File

@ -1,18 +0,0 @@
<div class="control-group">
<label class="control-label" for="search-assigned-to">
{{i18n "search.advanced.assigned.label"}}
</label>
<div class="controls">
<EmailGroupUserChooser
@value={{this.outletArgs.searchedTerms.assigned}}
@onChange={{this.onChangeAssigned}}
@options={{hash
maximum=1
excludeCurrentUser=false
includeGroups=true
customSearchOptions=(hash assignableGroups=true)
}}
/>
</div>
</div>

View File

@ -1,22 +0,0 @@
import Component from "@ember/component";
import { action } from "@ember/object";
import { service } from "@ember/service";
import { classNames } from "@ember-decorators/component";
@classNames("assigned-advanced-search")
export default class AssignedAdvancedSearch extends Component {
static shouldRender(args, component) {
return component.currentUser?.can_assign;
}
@service currentUser;
@action
onChangeAssigned(value) {
this.outletArgs.onChangeSearchedTermField(
"assigned",
"updateSearchTermForAssignedUsername",
value
);
}
}

View File

@ -0,0 +1,35 @@
import Component, { Input } from "@ember/component";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import { classNames } from "@ember-decorators/component";
import { i18n } from "discourse-i18n";
@classNames("assign-settings")
export default class AssignSettings extends Component {
@action
onChangeSetting(event) {
this.set(
"outletArgs.category.custom_fields.enable_unassigned_filter",
event.target.checked ? "true" : "false"
);
}
<template>
<h3>{{i18n "discourse_assign.assign.title"}}</h3>
<section class="field">
<div class="enable-accepted-answer">
<label class="checkbox-label">
<Input
@type="checkbox"
@checked={{readonly
this.outletArgs.category.enable_unassigned_filter
}}
{{on "change" this.onChangeSetting}}
/>
{{i18n "discourse_assign.add_unassigned_filter"}}
</label>
</div>
</section>
</template>
}

View File

@ -1,14 +0,0 @@
<h3>{{i18n "discourse_assign.assign.title"}}</h3>
<section class="field">
<div class="enable-accepted-answer">
<label class="checkbox-label">
<Input
@type="checkbox"
@checked={{readonly this.outletArgs.category.enable_unassigned_filter}}
{{on "change" this.onChangeSetting}}
/>
{{i18n "discourse_assign.add_unassigned_filter"}}
</label>
</div>
</section>

View File

@ -1,14 +0,0 @@
import Component from "@ember/component";
import { action } from "@ember/object";
import { classNames } from "@ember-decorators/component";
@classNames("assign-settings")
export default class AssignSettings extends Component {
@action
onChangeSetting(event) {
this.set(
"outletArgs.category.custom_fields.enable_unassigned_filter",
event.target.checked ? "true" : "false"
);
}
}

View File

@ -0,0 +1,17 @@
import Component from "@ember/component";
import { classNames, tagName } from "@ember-decorators/component";
import GroupAssignedMenuItem from "../../components/group-assigned-menu-item";
@tagName("li")
@classNames("group-reports-nav-item-outlet", "assigned-topic-list")
export default class AssignedTopicList extends Component {
static shouldRender(args, context) {
return (
context.currentUser?.can_assign &&
args.group.can_show_assigned_tab &&
args.group.assignment_count > 0
);
}
<template><GroupAssignedMenuItem @group={{this.group}} /></template>
}

View File

@ -1 +0,0 @@
<GroupAssignedMenuItem @group={{this.group}} />

View File

@ -1,9 +0,0 @@
export default {
shouldRender(args, component) {
return (
component.currentUser?.can_assign &&
args.group.can_show_assigned_tab &&
args.group.assignment_count > 0
);
},
};

View File

@ -1,6 +1,7 @@
import Component from "@glimmer/component";
import { action } from "@ember/object";
import { i18n } from "discourse-i18n";
import ComboBox from "select-kit/components/combo-box";
export default class AssignableInteractionFields extends Component {
assignableLevelOptions = [
@ -20,4 +21,27 @@ export default class AssignableInteractionFields extends Component {
onChangeAssignableLevel(level) {
this.args.outletArgs.model.set("assignable_level", level);
}
<template>
<div class="control-group">
<label class="control-label">
{{i18n "discourse_assign.admin.groups.manage.interaction.assign"}}
</label>
<label for="visibility">
{{i18n
"discourse_assign.admin.groups.manage.interaction.assignable_levels.title"
}}
</label>
<ComboBox
@name="alias"
@valueProperty="value"
@value={{this.assignableLevel}}
@content={{this.assignableLevelOptions}}
@onChange={{this.onChangeAssignableLevel}}
class="groups-form-assignable-level"
/>
</div>
</template>
}

View File

@ -1,20 +0,0 @@
<div class="control-group">
<label class="control-label">
{{i18n "discourse_assign.admin.groups.manage.interaction.assign"}}
</label>
<label for="visibility">
{{i18n
"discourse_assign.admin.groups.manage.interaction.assignable_levels.title"
}}
</label>
<ComboBox
@name="alias"
@valueProperty="value"
@value={{this.assignableLevel}}
@content={{this.assignableLevelOptions}}
@onChange={{this.onChangeAssignableLevel}}
class="groups-form-assignable-level"
/>
</div>

View File

@ -0,0 +1,18 @@
import Component from "@ember/component";
import { LinkTo } from "@ember/routing";
import { classNames, tagName } from "@ember-decorators/component";
import icon from "discourse/helpers/d-icon";
import { i18n } from "discourse-i18n";
@tagName("")
@classNames("user-activity-bottom-outlet", "assigned-list")
export default class AssignedList extends Component {
<template>
{{#if this.currentUser.can_assign}}
<LinkTo @route="userActivity.assigned">
{{icon "user-plus"}}
{{i18n "discourse_assign.assigned"}}
</LinkTo>
{{/if}}
</template>
}

View File

@ -1,6 +0,0 @@
{{#if this.currentUser.can_assign}}
<LinkTo @route="userActivity.assigned">
{{d-icon "user-plus"}}
{{i18n "discourse_assign.assigned"}}
</LinkTo>
{{/if}}

View File

@ -1,4 +0,0 @@
<LinkTo @route="userPrivateMessages.assigned" @model={{this.model}}>
{{d-icon "user-plus" class="glyph"}}
{{i18n "discourse_assign.assigned"}}
</LinkTo>

View File

@ -1,12 +0,0 @@
export function shouldShowAssigned(args, component) {
const needsButton = component.currentUser?.can_assign;
return (
needsButton && (!component.site.mobileView || args.model.isPrivateMessage)
);
}
export default {
shouldRender(args, component) {
return shouldShowAssigned(args, component);
},
};

View File

@ -0,0 +1,13 @@
import Component from "@ember/component";
import { classNames, tagName } from "@ember-decorators/component";
import RemindAssignsFrequency0 from "../../components/remind-assigns-frequency";
@tagName("div")
@classNames("user-preferences-notifications-outlet", "remind-assigns-frequency")
export default class RemindAssignsFrequency extends Component {
static shouldRender(args, context) {
return context.currentUser?.can_assign;
}
<template><RemindAssignsFrequency0 @user={{this.model}} /></template>
}

View File

@ -1 +0,0 @@
<RemindAssignsFrequency @user={{this.model}} />

View File

@ -1,5 +0,0 @@
export default {
shouldRender(args, component) {
return component.currentUser?.can_assign;
},
};

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,76 @@
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 @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={{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

@ -44,7 +44,7 @@
}
.select-kit-row[data-value="unassign-mobile-header"] {
background: rgba(var(--primary-low-rgb), 0.5);
background: rgb(var(--primary-low-rgb), 0.5);
pointer-events: none;
}

View File

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

File diff suppressed because it is too large Load Diff