Skip to content

Commit 7c36962

Browse files
committed
Merge branch 'release/21.8.0'
2 parents 9c7021d + ab12b7c commit 7c36962

File tree

17 files changed

+701
-239
lines changed

17 files changed

+701
-239
lines changed

CHANGELOG.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,18 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
55
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
66

7-
## [21.6.3] - 2021-09-14
7+
## [21.8.0] - 2021-10-04
8+
### Added
9+
- bulk upload component `Branded::Moderation::-Components::UploadCsv`
10+
- `registries.branded.moderation.settings` route
11+
12+
### Changed
13+
- bump ember-template-lint
14+
15+
### Remove
16+
- `registries.branded.moderation.notifications` route (now under `registries.branded.moderation.settings`)
17+
18+
## [21.7.0] - 2021-09-14
819
### Fixed
920
- A11y: Draft Registration Metadata Page - Critical WCAG 2A Rule Violations - Third Party Libraries
1021
- A11y: Draft Registration Metadata Page - Serious WCAG 2AA Rule Violation

app/services/current-user.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ export default class CurrentUserService extends Service {
7979

8080
constructor(...args: any[]) {
8181
super(...args);
82-
this.session.on('invalidationSucceeded', this, this._authRedirect.bind(this, AuthRoute.Logout));
82+
this.session.on('invalidationSucceeded', this, this._authRedirect.bind(this, AuthRoute.Logout, '/'));
8383
}
8484

8585
/**

lib/osf-components/addon/components/node-card/template.hbs

Lines changed: 50 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -98,80 +98,63 @@
9898
{{#if @node}}
9999
<dl>
100100
{{#if @node.isRegistration}}
101-
<div data-test-registration-template-name>
102-
<dt data-test-registration-template-label>
103-
{{t 'node_card.registration_template'}}
104-
</dt>
105-
<dd>
106-
{{@node.registrationSchema.name}}
107-
</dd>
108-
</div>
109-
<div data-test-registration-registry>
110-
<dt data-test-registration-registry-label>
111-
{{t 'node_card.registry'}}
112-
</dt>
113-
<dd data-test-registration-registry-name>
114-
{{@node.provider.name}}
115-
</dd>
116-
</div>
117-
{{/if}}
118-
<div data-test-created-timestamp>
119-
<dt data-test-created-timestamp-label>
120-
{{t (concat 'node_card.' @node.nodeType '.timestamp_label')}}
101+
<dt data-test-registration-template-label>
102+
{{t 'node_card.registration_template'}}
121103
</dt>
122-
<dd data-test-created-timestamp-value>
123-
{{moment @node.dateCreated}}
124-
</dd>
125-
</div>
126-
<div data-test-updated-timestamp>
127-
<dt data-test-updated-timestamp-label>
128-
{{t 'node_card.last_updated'}}
104+
<dd data-test-registration-template-name>
105+
{{@node.registrationSchema.name}}
106+
</dd><br />
107+
<dt data-test-registration-registry-label>
108+
{{t 'node_card.registry'}}
129109
</dt>
130-
<dd data-test-updated-timestamp-value>
131-
{{moment @node.dateModified}}
132-
</dd>
133-
</div>
134-
<div data-test-contributors>
135-
<dt
136-
data-test-contributors-label
110+
<dd data-test-registration-registry-name>
111+
{{@node.provider.name}}
112+
</dd><br />
113+
{{/if}}
114+
<dt data-test-created-timestamp-label>
115+
{{t (concat 'node_card.' @node.nodeType '.timestamp_label')}}
116+
</dt>
117+
<dd data-test-created-timestamp-value>
118+
{{moment @node.dateCreated}}
119+
</dd><br />
120+
<dt data-test-updated-timestamp-label>
121+
{{t 'node_card.last_updated'}}
122+
</dt>
123+
<dd data-test-updated-timestamp-value>
124+
{{moment @node.dateModified}}
125+
</dd><br />
126+
<dt
127+
data-test-contributors-label
128+
>
129+
{{t 'node_card.contributors'}}
130+
</dt>
131+
<dd>
132+
<ContributorList
133+
@model={{@node}}
134+
@shouldLinkUsers={{true}}
135+
/>
136+
</dd><br />
137+
<dt
138+
data-test-description-label
139+
>
140+
{{t 'node_card.description'}}
141+
</dt>
142+
<dd data-test-description local-class='NodeCard__description'>
143+
{{@node.description}}
144+
</dd><br />
145+
{{#if (and this.showTags @node.tags)}}
146+
<dt local-class='NodeCard__tags'
147+
data-test-tags-label
148+
137149
>
138-
{{t 'node_card.contributors'}}
150+
{{t 'node_card.tags'}}
139151
</dt>
140152
<dd>
141-
<ContributorList
142-
@model={{@node}}
143-
@shouldLinkUsers={{true}}
153+
<TagsWidget
154+
@taggable={{@node}}
155+
@inline={{true}}
144156
/>
145157
</dd>
146-
</div>
147-
<div data-test-description>
148-
<dt
149-
data-test-description-label
150-
>
151-
{{t 'node_card.description'}}
152-
</dt>
153-
<dd local-class='NodeCard__description'>
154-
{{@node.description}}
155-
</dd>
156-
</div>
157-
{{#if (and this.showTags @node.tags)}}
158-
<div
159-
data-test-tags
160-
local-class='NodeCard__tags'
161-
>
162-
<dt
163-
data-test-tags-label
164-
165-
>
166-
{{t 'node_card.tags'}}
167-
</dt>
168-
<dd>
169-
<TagsWidget
170-
@taggable={{@node}}
171-
@inline={{true}}
172-
/>
173-
</dd>
174-
</div>
175158
{{/if}}
176159
</dl>
177160
<OsfLink
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import config from 'ember-get-config';
2+
import { action } from '@ember/object';
3+
import Component from '@glimmer/component';
4+
import { tracked } from '@glimmer/tracking';
5+
import { inject as service } from '@ember/service';
6+
import Intl from 'ember-intl/services/intl';
7+
import { SafeString } from '@ember/template/-private/handlebars';
8+
import Toast from 'ember-toastr/services/toast';
9+
10+
const { OSF: { apiUrl } } = config;
11+
12+
interface Args {
13+
providerId: string;
14+
}
15+
16+
interface ErrorMessage {
17+
cell: string;
18+
title: string;
19+
detail: string | SafeString;
20+
}
21+
interface ApiErrorDetail {
22+
header: string;
23+
column_index: string;
24+
row_index: string;
25+
type: string;
26+
invalidHeaders?: string[];
27+
missingHeaders?: string[];
28+
}
29+
export default class UploadCsvComponent extends Component<Args> {
30+
dropzoneOptions = {
31+
createImageThumbnails: false,
32+
method: 'PUT',
33+
withCredentials: true,
34+
preventMultipleFiles: true,
35+
acceptDirectories: false,
36+
};
37+
38+
@service intl!: Intl;
39+
@service toast!: Toast;
40+
41+
@tracked errorMessages: ErrorMessage[] = [];
42+
@tracked shouldShowErrorModal = false;
43+
@tracked uploading: any[] = [];
44+
45+
@action
46+
buildUrl(files: any) {
47+
return `${apiUrl}/_/registries/${this.args.providerId}/bulk_create/${files[0].name}/`;
48+
}
49+
50+
@action
51+
addedFile(_: any, __: any, file: any) {
52+
this.uploading.push(file);
53+
}
54+
55+
@action
56+
error(_: any, __: any, file: any, { errors }: { errors: ApiErrorDetail[]}) {
57+
this.uploading.removeObject(file);
58+
this.shouldShowErrorModal = true;
59+
for (const error of errors) {
60+
this.errorMessages.push(
61+
{
62+
cell: error.column_index + error.row_index,
63+
title: this.intl.t(`registries.moderation.settings.${error.type}.title`),
64+
detail: this.intl.t(`registries.moderation.settings.${error.type}.detail`, {
65+
htmlSafe: true,
66+
invalidIds: error.invalidHeaders ? error.invalidHeaders.join(', ') : null,
67+
missingIds: error.missingHeaders ? error.missingHeaders.join(', ') : null,
68+
}),
69+
},
70+
);
71+
}
72+
}
73+
74+
@action
75+
success(_: any, __: any, file: any, ___: any) {
76+
this.uploading.removeObject(file);
77+
this.toast.success(this.intl.t('registries.moderation.settings.uploadSuccess'));
78+
}
79+
80+
@action
81+
closeErrorModal() {
82+
this.shouldShowErrorModal = false;
83+
this.errorMessages = [];
84+
}
85+
86+
@action
87+
async copyToClipboard(elementId: string) {
88+
const mainElement = document.getElementById(elementId);
89+
await navigator.clipboard.writeText(mainElement!.textContent!);
90+
this.toast.success(this.intl.t('registries.moderation.settings.copyToClipboardSuccess'));
91+
}
92+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.upload-zone-content {
2+
text-align: center;
3+
}
4+
5+
.upload-zone {
6+
padding: 50px;
7+
background: #f5f5f5;
8+
border: 5px dashed #c7c7c7;
9+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{{#let (unique-id 'upload-csv-dropzone') as |id|}}
2+
<DropzoneWidget
3+
@buildUrl={{this.buildUrl}}
4+
@options={{this.dropzoneOptions}}
5+
@dropzone={{false}}
6+
@addedfile={{this.addedFile}}
7+
@success={{this.success}}
8+
@error={{this.error}}
9+
@dragenter={{fn (mut this.dropping) true}}
10+
@dragover={{fn (mut this.dropping) true}}
11+
@drop={{fn (mut this.dropping) false}}
12+
@dragleave={{fn (mut this.dropping) false}}
13+
@enable={{true}}
14+
@id={{id}}
15+
@clickable={{array
16+
(concat '.' (local-class 'upload-zone'))
17+
}}
18+
data-test-bulk-upload-widget
19+
>
20+
<div local-class='upload-zone'>
21+
<div local-class='upload-zone-content'>
22+
<FaIcon @icon='upload' @size='5x' />
23+
<div
24+
local-class='file-placeholder-text'
25+
>
26+
{{t 'registries.moderation.settings.dropCsvHere'}}
27+
</div>
28+
</div>
29+
</div>
30+
</DropzoneWidget>
31+
{{/let}}
32+
33+
{{#let (unique-id 'main-content') as |id|}}
34+
<OsfDialog
35+
@isOpen={{this.shouldShowErrorModal}}
36+
@onClose={{this.closeErrorModal}}
37+
as |dialog|
38+
>
39+
<dialog.heading data-test-error-modal-heading>
40+
{{t 'registries.moderation.settings.uploadError'}}
41+
</dialog.heading>
42+
<dialog.main id={{id}} data-test-error-modal-main>
43+
<div data-test-error-modal-general-message>
44+
<p>{{t 'registries.moderation.settings.generalErrorMessage' htmlSafe=true}}</p>
45+
</div>
46+
47+
<dl data-test-error-modal-message-list>
48+
{{#each this.errorMessages as |msg|}}
49+
<p>
50+
{{#if msg.cell}}
51+
<dt data-test-error-modal-cell-identifier>{{t 'registries.moderation.settings.cell'}} {{msg.cell}}</dt>
52+
{{/if}}
53+
<dt data-test-error-modal-message-title>{{msg.title}}</dt>
54+
<dd data-test-error-modal-message-detail>{{msg.detail}}</dd>
55+
</p>
56+
{{/each}}
57+
</dl>
58+
</dialog.main>
59+
<dialog.footer>
60+
<BsButton
61+
data-test-copy-to-clipboard
62+
data-analytics-name='Copy error messages to clipboard'
63+
@type='primary'
64+
{{on 'click' (fn this.copyToClipboard id)}}
65+
>
66+
{{t 'registries.moderation.settings.copyToClipboard'}}
67+
</BsButton>
68+
</dialog.footer>
69+
</OsfDialog>
70+
{{/let}}

lib/registries/addon/branded/moderation/notifications/template.hbs

Lines changed: 0 additions & 17 deletions
This file was deleted.

lib/registries/addon/branded/moderation/notifications/controller.ts renamed to lib/registries/addon/branded/moderation/settings/controller.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@ import { computed } from '@ember/object';
33
import { alias } from '@ember/object/computed';
44
import config from 'ember-get-config';
55
import pathJoin from 'ember-osf-web/utils/path-join';
6+
import { ReviewPermissions } from 'ember-osf-web/models/provider';
67

7-
export default class BrandedModerationNotificationsController extends Controller {
8+
export default class BrandedModerationSettingsController extends Controller {
89
userSettingsLink = pathJoin(config.OSF.url, 'settings', 'notifications');
910
@alias('model.id') providerId?: string;
1011

12+
get shouldShowBulkUploadWidget() {
13+
return this.model.permissions.includes(ReviewPermissions.AddModerator);
14+
}
15+
1116
@computed('providerId')
1217
get subscriptionIds() {
1318
return this.providerId

lib/registries/addon/branded/moderation/notifications/route.ts renamed to lib/registries/addon/branded/moderation/settings/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { inject as service } from '@ember/service';
44

55
import Analytics from 'ember-osf-web/services/analytics';
66

7-
export default class BrandedModerationNotificationsRoute extends Route {
7+
export default class BrandedModerationSettingsRoute extends Route {
88
@service analytics!: Analytics;
99

1010
@action

0 commit comments

Comments
 (0)