Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FEATURE: Make it possible to reassign posts on the topic level assign modal #562

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions assets/javascripts/discourse/components/assign-user-form.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import Assignment from "./assignment";

export default class AssignUserForm extends Component {
@tracked showValidationErrors = false;

constructor() {
super(...arguments);

this.args.formApi.submit = this.assign;
}

get assigneeIsEmpty() {
return !this.args.model.username && !this.args.model.group_name;
}

@action
async assign() {
if (this.assigneeIsEmpty) {
this.showValidationErrors = true;
return;
}

await this.args.onSubmit();
}

<template>
<Assignment
@assignment={{@model}}
@onSubmit={{this.assign}}
@showValidationErrors={{this.showValidationErrors}}
/>
</template>
}
56 changes: 0 additions & 56 deletions assets/javascripts/discourse/components/assign-user-form.hbs

This file was deleted.

63 changes: 0 additions & 63 deletions assets/javascripts/discourse/components/assign-user-form.js

This file was deleted.

134 changes: 134 additions & 0 deletions assets/javascripts/discourse/components/assignment.gjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import Component from "@glimmer/component";
import { hash } from "@ember/helper";
import { TextArea } from "@ember/legacy-built-in-components";
import { on } from "@ember/modifier";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
import icon from "discourse-common/helpers/d-icon";
import i18n from "discourse-common/helpers/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 {
@service siteSettings;
@service taskActions;

get assignee() {
return this.args.assignment.username || this.args.assignment.group_name;
}

get status() {
return this.args.assignment.status || this.assignStatuses[0];
}

get assignStatuses() {
return this.siteSettings.assign_statuses.split("|").filter(Boolean);
}

get assignStatusOptions() {
return this.assignStatuses.map((status) => ({ id: status, name: status }));
}

get assigneeIsEmpty() {
return !this.args.assignment.username && !this.args.assignment.group_name;
}

get showAssigneeIeEmptyError() {
return this.assigneeIsEmpty && this.args.showValidationErrors;
}

@action
handleTextAreaKeydown(event) {
if ((event.ctrlKey || event.metaKey) && event.key === "Enter") {
this.args.onSubmit();
}
}

@action
markAsEdited() {
this.args.assignment.isEdited = true;
}

@action
setAssignee([newAssignee]) {
if (this.taskActions.allowedGroupsForAssignment.includes(newAssignee)) {
this.args.assignment.username = null;
this.args.assignment.group_name = newAssignee;
} else {
this.args.assignment.username = newAssignee;
this.args.assignment.group_name = null;
}
this.markAsEdited();
}

@action
setStatus(status) {
this.args.assignment.status = status;
this.markAsEdited();
}

<template>
<div
class="control-group
{{if this.showAssigneeIeEmptyError 'assignee-error'}}"
>
<label>{{i18n "discourse_assign.assign_modal.assignee_label"}}</label>
<AssigneeChooser
autocomplete="off"
@id="assignee-chooser"
@value={{this.assignee}}
@onChange={{this.setAssignee}}
@showUserStatus={{true}}
@options={{hash
mobilePlacementStrategy="absolute"
includeGroups=true
customSearchOptions=(hash
assignableGroups=true
defaultSearchResults=this.taskActions.suggestions
)
groupMembersOf=this.taskActions.allowedGroups
maximum=1
tabindex=1
expandedOnInsert=(not this.assignee)
caretUpIcon="search"
caretDownIcon="search"
}}
/>

{{#if this.showAssigneeIeEmptyError}}
<span class="error-label">
{{icon "exclamation-triangle"}}
{{i18n "discourse_assign.assign_modal.choose_assignee"}}
</span>
{{/if}}
</div>

{{#if this.siteSettings.enable_assign_status}}
<div class="control-group assign-status">
<label>{{i18n "discourse_assign.assign_modal.status_label"}}</label>
<ComboBox
@id="assign-status"
@content={{this.assignStatusOptions}}
@value={{this.status}}
@onChange={{this.setStatus}}
/>
</div>
{{/if}}

<div class="control-group assign-status">
<label>
{{i18n "discourse_assign.assign_modal.note_label"}}&nbsp;<span
class="label-optional"
>{{i18n "discourse_assign.assign_modal.optional_label"}}</span>
</label>

<TextArea
id="assign-modal-note"
@value={{@assignment.note}}
{{on "keydown" this.handleTextAreaKeydown}}
{{on "input" this.markAsEdited}}
/>
</div>
</template>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import Component from "@glimmer/component";
import { tracked } from "@glimmer/tracking";
import { action } from "@ember/object";
import { inject as service } from "@ember/service";
import DButton from "discourse/components/d-button";
import DModal from "discourse/components/d-modal";
import DModalCancel from "discourse/components/d-modal-cancel";
import { popupAjaxError } from "discourse/lib/ajax-error";
import I18n from "I18n";
import TopicAssignments from "../topic-assignments";

export default class EditTopicAssignments extends Component {
@service taskActions;

@tracked assignments = this.topic.assignments();

get title() {
if (this.topic.isAssigned() || this.topic.hasAssignedPosts()) {
return I18n.t("edit_assignments_modal.title");
} else {
return I18n.t("discourse_assign.assign_modal.title");
}
}

get topic() {
return this.args.model.topic;
}

@action
async submit() {
this.args.closeModal();
try {
await this.#assign();
} catch (error) {
popupAjaxError(error);
}
}

async #assign() {
for (const assignment of this.assignments) {
if (assignment.isEdited) {
await this.taskActions.putAssignment(assignment);
}
}
}

<template>
<DModal class="assign" @title={{this.title}} @closeModal={{@closeModal}}>
<:body>
<TopicAssignments @assignments={{this.assignments}} />
</:body>
<:footer>
<DButton
class="btn-primary"
@action={{this.submit}}
@label={{if
this.model.reassign
"discourse_assign.reassign.title"
"discourse_assign.assign_modal.assign"
}}
/>

<DModalCancel @close={{@closeModal}} />
</:footer>
</DModal>
</template>
}
Loading
Loading