Skip to content

Commit

Permalink
Merge pull request #2421 from Johnetordoff/institutional-access-user-…
Browse files Browse the repository at this point in the history
…message-modal

[ENG-6665] Add user messaging modal to user's tab on institutional dashboard
  • Loading branch information
Johnetordoff authored Dec 18, 2024
2 parents f41bc9a + 434288e commit 5bbb5a3
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 0 deletions.
13 changes: 13 additions & 0 deletions app/adapters/user-message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// app/adapters/user-message.js
import { inject as service } from '@ember/service';
import config from 'ember-osf-web/config/environment';
const { OSF: { apiUrl } } = config;
import OsfAdapter from './osf-adapter';

export default class UserMessageAdapter extends OsfAdapter {
@service session;
urlForCreateRecord(modelName, snapshot) {
const userId = snapshot.record.user;
return `${apiUrl}/v2/users/${userId}/messages/`;
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { task } from 'ember-concurrency';
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
Expand All @@ -10,6 +11,7 @@ import InstitutionModel from 'ember-osf-web/models/institution';
import InstitutionDepartmentsModel from 'ember-osf-web/models/institution-department';
import Analytics from 'ember-osf-web/services/analytics';
import { RelationshipWithLinks } from 'osf-api';
import {MessageTypeChoices} from 'ember-osf-web/models/user-message';

interface Column {
key: string;
Expand All @@ -27,6 +29,8 @@ interface InstitutionalUsersListArgs {
export default class InstitutionalUsersList extends Component<InstitutionalUsersListArgs> {
@service analytics!: Analytics;
@service intl!: Intl;
@service store;
@service currentUser!: CurrentUser;

institution?: InstitutionModel;

Expand All @@ -37,6 +41,12 @@ export default class InstitutionalUsersList extends Component<InstitutionalUsers
@tracked sort = 'user_name';
@tracked selectedDepartments: string[] = [];
@tracked filteredUsers = [];
@tracked messageModalShown = false;
@tracked messageText = '';
@tracked bcc_sender = false;
@tracked replyTo = false;
@tracked selectedUserId = null;
@service toast!: Toast;

@tracked columns: Column[] = [
{
Expand Down Expand Up @@ -262,4 +272,54 @@ export default class InstitutionalUsersList extends Component<InstitutionalUsers
clickToggleOrcidFilter(hasOrcid: boolean) {
this.hasOrcid = !hasOrcid;
}

@action
openMessageModal(userId: string) {
this.selectedUserId = userId;
this.messageModalShown = true;
}

@action
toggleMessageModal(userId: string | null = null) {
this.messageModalShown = !this.messageModalShown;
this.selectedUserId = userId;
if (!this.messageModalShown) {
this.resetModalFields();
}
}

@action
resetModalFields() {
this.messageText = '';
this.bcc_sender = false;
this.replyTo = false;
this.selectedUserId = null;
}

@task
@waitFor
async sendMessage() {
if (!this.messageText.trim()) {
this.toast.error(this.intl.t('error.empty_message'));
return;
}

try {
const userMessage = this.store.createRecord('user-message', {
messageText: this.messageText.trim(),
messageType: MessageTypeChoices.InstitutionalRequest,
bcc_sender: this.bcc_sender,
replyTo: this.replyTo,
institution: this.args.institution,
user: this.selectedUserId,
});

await userMessage.save();
this.toast.success(this.intl.t('institutions.dashboard.send_message_modal.message_sent_success'));
} catch (error) {
this.toast.error(this.intl.t('institutions.dashboard.send_message_modal.message_sent_failed'));
} finally {
this.messageModalShown = false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -319,3 +319,41 @@ input:checked + .slider::before {
justify-content: flex-end;
margin-right: 15px;
}


.icon-message {
opacity: 0;
color: $color-text-blue-dark;
/* !important used to override ember Button border scripting */
background-color: inherit !important;
border: 0 !important;
box-shadow: 0 !important;
}

.icon-message:hover {
opacity: 1;
background-color: inherit !important;
}

.message-textarea {
min-width: 450px;
min-height: 280px;
}

.message-label {
display: block;
}

.checkbox-container {
display: flex;
flex-direction: column;
gap: 10px;
padding: 10px;
}

.checkbox-item {
display: flex;
align-items: center;
gap: 8px;
font-size: 14px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,14 @@
<OsfLink @href={{concat '/' institutionalUser.userGuid '/'}}>
{{institutionalUser.userName}}
</OsfLink>
<Button
local-class='icon-message'
aria-label={{t 'institutions.dashboard.send_message_modal.open_aira_label'}}

{{on 'click' (fn this.openMessageModal institutionalUser.userGuid)}}
>
<FaIcon @icon='comment' />
</Button>
{{else if (eq column.type 'osf_link')}}
<OsfLink @href={{concat '/' institutionalUser.userGuid '/'}}>
{{institutionalUser.userGuid}}
Expand Down Expand Up @@ -204,4 +212,50 @@
{{t 'institutions.dashboard.users_list.empty'}}
</list.empty>
</PaginatedList::HasMany>
<OsfDialog @isOpen={{this.messageModalShown}} @onClose={{this.toggleMessageModal}} as |dialog|>
<dialog.heading>
{{t 'institutions.dashboard.send_message_modal.title'}}
</dialog.heading>
<dialog.main>
<div>
<label for='message-text' local-class='message-label'>
{{t 'institutions.dashboard.send_message_modal.opening_message_label'}}
</label>
<Textarea
id='message-text'
local-class='message-textarea'
@value={{this.messageText}}
/>
<div>
{{t 'institutions.dashboard.send_message_modal.closing_message_label' adminName=this.currentUser.user.fullName htmlSafe=true}}
</div>
<div local-class='checkbox-container'>
<label local-class='checkbox-item'>
<Input @type='checkbox' @checked={{this.bcc_sender}} />
{{t 'institutions.dashboard.send_message_modal.cc_label'}}
</label>
<label local-class='checkbox-item'>
<Input @type='checkbox' @checked={{this.replyTo}} />
{{t 'institutions.dashboard.send_message_modal.reply_to_label'}}
</label>
</div>
</div>
</dialog.main>
<dialog.footer>
<Button
@type='secondary'
{{on 'click' this.toggleMessageModal}}
>
{{t 'general.cancel'}}
</Button>
<Button
@type='primary'
@disabled={{not this.messageText.trim}}
{{on 'click' (queue (perform this.sendMessage))}}

>
{{t 'institutions.dashboard.send_message_modal.send'}}
</Button>
</dialog.footer>
</OsfDialog>
{{/if}}
15 changes: 15 additions & 0 deletions app/models/user-message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// app/models/user-message.js
import Model, { attr, belongsTo } from '@ember-data/model';

export enum MessageTypeChoices {
InstitutionalRequest = 'institutional_request',
}


export default class UserMessageModel extends Model {
@attr('string') messageText;
@attr('string') messageType: MessageTypeChoices;
@attr('boolean') bcc_sender;
@attr('boolean') replyTo;
@belongsTo('institution') institution;
}
12 changes: 12 additions & 0 deletions translations/en-us.yml
Original file line number Diff line number Diff line change
Expand Up @@ -799,6 +799,18 @@ institutions:
search_placeholder: 'Search institutions'
load_more: 'Load more institutions'
dashboard:
send_message_modal:
open_aira_label: 'Open User Message Modal Button'
close_aira_label: 'Close User Message Modal Button'
send_aira_label: 'Send User Message Button'
title: 'Send Email'
opening_message_label: 'Comments:'
closing_message_label: 'Sincerely Yours,<br> {adminName}'
message_sent_success: 'Message has been sent'
message_sent_failed: 'Message has failed to send. If the issue persists contact your administrator'
send: 'Send'
cc_label: 'CC sender'
reply_to_label: 'Allow reply to sender address'
tabs:
summary: Summary
users: Users
Expand Down

0 comments on commit 5bbb5a3

Please sign in to comment.