diff --git a/src/app/features/moderation/components/collection-submission-item/collection-submission-item.component.html b/src/app/features/moderation/components/collection-submission-item/collection-submission-item.component.html
index b5bfb2c65..e411a6cc2 100644
--- a/src/app/features/moderation/components/collection-submission-item/collection-submission-item.component.html
+++ b/src/app/features/moderation/components/collection-submission-item/collection-submission-item.component.html
@@ -2,53 +2,81 @@
@let attributes = currentSubmissionAttributes();
@if (action && attributes) {
-
-
-
+
+
+
+
+
+
-
- @switch (action.toState) {
- @case (SubmissionReviewStatus.Pending) {
- {{ 'moderation.submissionReview.submitted' | translate }}
- }
- @case (SubmissionReviewStatus.Accepted) {
- @if (!collectionProvider()?.reviewsWorkflow) {
- {{ 'moderation.submissionReview.submitted' | translate }}
- } @else {
- {{ 'moderation.submissionReview.accepted' | translate }}
- }
- }
- @case (SubmissionReviewStatus.Rejected) {
- {{ 'moderation.submissionReview.rejected' | translate }}
- }
- @case (SubmissionReviewStatus.Removed) {
- {{ 'moderation.submissionReview.withdrawn' | translate }}
- }
- }
- {{ action.dateCreated | dateAgo }}
- {{ 'moderation.submissionReview.by' | translate }}
- {{ action.createdBy }}
-
+
+ @switch (action.toState) {
+ @case (SubmissionReviewStatus.Pending) {
+ {{ 'moderation.submissionReview.submitted' | translate }}
+ }
+ @case (SubmissionReviewStatus.Accepted) {
+ @if (!collectionProvider()?.reviewsWorkflow) {
+ {{ 'moderation.submissionReview.submitted' | translate }}
+ } @else {
+ {{ 'moderation.submissionReview.accepted' | translate }}
+ }
+ }
+ @case (SubmissionReviewStatus.Rejected) {
+ {{ 'moderation.submissionReview.rejected' | translate }}
+ }
+ @case (SubmissionReviewStatus.Removed) {
+ {{ 'moderation.submissionReview.withdrawn' | translate }}
+ }
+ }
+ {{ action.dateCreated | dateAgo }}
+ {{ 'moderation.submissionReview.by' | translate }}
+ {{ action.createdBy }}
+
-
- @for (attribute of attributes; track attribute.key) {
- @if (!$first) {
-
|
- }
-
- {{ attribute.label }}: {{ attribute.value }}
-
- }
-
+
+ @for (attribute of attributes; track attribute.key) {
+ @if (!$first) {
+
|
+ }
+
+ {{ attribute.label }}: {{ attribute.value }}
+
+ }
+
- @if (action.comment) {
-
- }
+ @if (action.comment) {
+
+ }
+
+
+
+
+
+
+
{{ 'common.labels.contributors' | translate }}:
+
+
+
+
+
+
}
diff --git a/src/app/features/moderation/components/collection-submission-item/collection-submission-item.component.ts b/src/app/features/moderation/components/collection-submission-item/collection-submission-item.component.ts
index c24ba1577..0f5d0a3ae 100644
--- a/src/app/features/moderation/components/collection-submission-item/collection-submission-item.component.ts
+++ b/src/app/features/moderation/components/collection-submission-item/collection-submission-item.component.ts
@@ -2,12 +2,14 @@ import { select } from '@ngxs/store';
import { TranslatePipe } from '@ngx-translate/core';
+import { Accordion, AccordionContent, AccordionHeader, AccordionPanel } from 'primeng/accordion';
import { Button } from 'primeng/button';
-import { ChangeDetectionStrategy, Component, computed, inject, input } from '@angular/core';
+import { ChangeDetectionStrategy, Component, computed, inject, input, output } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { collectionFilterNames } from '@osf/features/collections/constants';
+import { ContributorsListComponent } from '@osf/shared/components/contributors-list/contributors-list.component';
import { IconComponent } from '@osf/shared/components/icon/icon.component';
import { TruncatedTextComponent } from '@osf/shared/components/truncated-text/truncated-text.component';
import { CollectionSubmissionWithGuid } from '@osf/shared/models/collections/collections.models';
@@ -19,7 +21,18 @@ import { SubmissionReviewStatus } from '../../enums';
@Component({
selector: 'osf-submission-item',
- imports: [TranslatePipe, IconComponent, DateAgoPipe, Button, TruncatedTextComponent],
+ imports: [
+ TranslatePipe,
+ IconComponent,
+ DateAgoPipe,
+ Button,
+ TruncatedTextComponent,
+ Accordion,
+ AccordionPanel,
+ AccordionHeader,
+ AccordionContent,
+ ContributorsListComponent,
+ ],
templateUrl: './collection-submission-item.component.html',
styleUrl: './collection-submission-item.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -29,7 +42,8 @@ export class CollectionSubmissionItemComponent {
private activatedRoute = inject(ActivatedRoute);
submission = input.required
();
-
+ loadContributors = output();
+ loadMoreContributors = output();
collectionProvider = select(CollectionsSelectors.getCollectionProvider);
readonly reviewStatusIcon = ReviewStatusIcon;
@@ -55,6 +69,15 @@ export class CollectionSubmissionItemComponent {
.filter((attribute) => attribute.value);
});
+ hasMoreContributors = computed(() => {
+ const submission = this.submission();
+ if (submission.contributors && submission.totalContributors) {
+ return submission.contributors.length < submission.totalContributors;
+ }
+
+ return false;
+ });
+
handleNavigation() {
const currentStatus = this.activatedRoute.snapshot.queryParams['status'];
const queryParams = currentStatus ? { status: currentStatus, mode: 'moderation' } : {};
@@ -68,4 +91,8 @@ export class CollectionSubmissionItemComponent {
window.open(url, '_blank');
}
+
+ handleOpen() {
+ this.loadContributors.emit();
+ }
}
diff --git a/src/app/features/moderation/components/collection-submissions-list/collection-submissions-list.component.html b/src/app/features/moderation/components/collection-submissions-list/collection-submissions-list.component.html
index 5e6d11a21..fc38d9de7 100644
--- a/src/app/features/moderation/components/collection-submissions-list/collection-submissions-list.component.html
+++ b/src/app/features/moderation/components/collection-submissions-list/collection-submissions-list.component.html
@@ -2,7 +2,12 @@
@for (item of submissions(); track $index) {
-
+
+
}
diff --git a/src/app/features/moderation/components/collection-submissions-list/collection-submissions-list.component.ts b/src/app/features/moderation/components/collection-submissions-list/collection-submissions-list.component.ts
index 1bf63272c..e87f597fd 100644
--- a/src/app/features/moderation/components/collection-submissions-list/collection-submissions-list.component.ts
+++ b/src/app/features/moderation/components/collection-submissions-list/collection-submissions-list.component.ts
@@ -1,9 +1,15 @@
-import { select } from '@ngxs/store';
+import { createDispatchMap, select } from '@ngxs/store';
import { TranslatePipe } from '@ngx-translate/core';
import { ChangeDetectionStrategy, Component } from '@angular/core';
+import {
+ GetCollectionSubmissionContributors,
+ LoadMoreCollectionSubmissionContributors,
+} from '@osf/features/moderation/store/collections-moderation';
+import { CollectionSubmissionWithGuid } from '@shared/models/collections/collections.models';
+
import { CollectionsModerationSelectors } from '../../store/collections-moderation';
import { CollectionSubmissionItemComponent } from '../collection-submission-item/collection-submission-item.component';
@@ -16,4 +22,17 @@ import { CollectionSubmissionItemComponent } from '../collection-submission-item
})
export class CollectionSubmissionsListComponent {
submissions = select(CollectionsModerationSelectors.getCollectionSubmissions);
+
+ readonly actions = createDispatchMap({
+ getCollectionSubmissionContributors: GetCollectionSubmissionContributors,
+ loadMoreCollectionSubmissionContributors: LoadMoreCollectionSubmissionContributors,
+ });
+
+ loadContributors(item: CollectionSubmissionWithGuid) {
+ this.actions.getCollectionSubmissionContributors(item.id, 1);
+ }
+
+ loadMoreContributors(item: CollectionSubmissionWithGuid) {
+ this.actions.loadMoreCollectionSubmissionContributors(item.id);
+ }
}
diff --git a/src/app/features/moderation/components/registry-pending-submissions/registry-pending-submissions.component.html b/src/app/features/moderation/components/registry-pending-submissions/registry-pending-submissions.component.html
index 8c9be9cf7..77f120b97 100644
--- a/src/app/features/moderation/components/registry-pending-submissions/registry-pending-submissions.component.html
+++ b/src/app/features/moderation/components/registry-pending-submissions/registry-pending-submissions.component.html
@@ -39,6 +39,8 @@
[submission]="item"
[status]="selectedReviewOption()"
(selected)="navigateToRegistration(item)"
+ (loadContributors)="loadContributors(item)"
+ (loadMoreContributors)="loadMoreContributors(item)"
>
}
diff --git a/src/app/features/moderation/components/registry-pending-submissions/registry-pending-submissions.component.ts b/src/app/features/moderation/components/registry-pending-submissions/registry-pending-submissions.component.ts
index 7f21e3fc5..ac0f00e76 100644
--- a/src/app/features/moderation/components/registry-pending-submissions/registry-pending-submissions.component.ts
+++ b/src/app/features/moderation/components/registry-pending-submissions/registry-pending-submissions.component.ts
@@ -24,7 +24,12 @@ import { Primitive } from '@osf/shared/helpers/types.helper';
import { PENDING_SUBMISSION_REVIEW_OPTIONS, REGISTRY_SORT_OPTIONS } from '../../constants';
import { RegistrySort, SubmissionReviewStatus } from '../../enums';
import { RegistryModeration } from '../../models';
-import { GetRegistrySubmissions, RegistryModerationSelectors } from '../../store/registry-moderation';
+import {
+ GetRegistrySubmissionContributors,
+ GetRegistrySubmissions,
+ LoadMoreRegistrySubmissionContributors,
+ RegistryModerationSelectors,
+} from '../../store/registry-moderation';
import { RegistrySubmissionItemComponent } from '../registry-submission-item/registry-submission-item.component';
@Component({
@@ -54,7 +59,11 @@ export class RegistryPendingSubmissionsComponent implements OnInit {
this.route.parent?.params.pipe(map((params) => params['providerId'])) ?? of(undefined)
);
- readonly actions = createDispatchMap({ getRegistrySubmissions: GetRegistrySubmissions });
+ readonly actions = createDispatchMap({
+ getRegistrySubmissions: GetRegistrySubmissions,
+ getRegistrySubmissionContributors: GetRegistrySubmissionContributors,
+ loadMoreRegistrySubmissionContributors: LoadMoreRegistrySubmissionContributors,
+ });
readonly submissions = select(RegistryModerationSelectors.getRegistrySubmissions);
readonly isLoading = select(RegistryModerationSelectors.areRegistrySubmissionLoading);
@@ -112,6 +121,14 @@ export class RegistryPendingSubmissionsComponent implements OnInit {
window.open(url, '_blank');
}
+ loadContributors(item: RegistryModeration) {
+ this.actions.getRegistrySubmissionContributors(item.id);
+ }
+
+ loadMoreContributors(item: RegistryModeration) {
+ this.actions.loadMoreRegistrySubmissionContributors(item.id);
+ }
+
private getStatusFromQueryParams() {
const queryParams = this.route.snapshot.queryParams;
const statusValues = Object.values(SubmissionReviewStatus);
diff --git a/src/app/features/moderation/components/registry-submission-item/registry-submission-item.component.html b/src/app/features/moderation/components/registry-submission-item/registry-submission-item.component.html
index 86c6bbef2..006ce75fc 100644
--- a/src/app/features/moderation/components/registry-submission-item/registry-submission-item.component.html
+++ b/src/app/features/moderation/components/registry-submission-item/registry-submission-item.component.html
@@ -1,54 +1,76 @@
-
-
-
-
- @if (isRejected) {
-
{{ submission().title }}
- } @else {
-
- }
-
- @if (submission().public && !submission().embargoEndDate) {
-
{{ 'registry.overview.statuses.accepted.text' | translate }}
- }
-
- @if (submission().embargoEndDate) {
-
- {{ 'moderation.registryEmbargoedWithEndDate' | translate }}
- {{ submission().embargoEndDate | date: 'MMM d, y' }}
-
- }
-
- @for (action of showAll ? submission().actions : submission().actions.slice(0, limitValue); track $index) {
-
- {{ registryActionLabel[action.toState] | translate }}
- {{ action.dateModified | dateAgo }}
- {{ 'moderation.submissionReview.by' | translate }}
- {{ action.creator?.name }}
-
- @if (action.toState === registryActionState.Accepted) {
- {{ 'moderation.withNoEmbargo' | translate }}
- }
-
- @if (action.comment.length) {
-
- }
-
- }
-
- @if (submission().actions.length > 1) {
-
- }
-
+
+
+
+
+
+
+
+
+ @if (isRejected) {
+
{{ submission().title }}
+ } @else {
+
+ }
+
+ @if (submission().public && !submission().embargoEndDate) {
+
{{ 'registry.overview.statuses.accepted.text' | translate }}
+ }
+
+ @if (submission().embargoEndDate) {
+
+ {{ 'moderation.registryEmbargoedWithEndDate' | translate }}
+ {{ submission().embargoEndDate | date: 'MMM d, y' }}
+
+ }
+
+ @for (action of showAll ? submission().actions : submission().actions.slice(0, limitValue); track $index) {
+
+ {{ registryActionLabel[action.toState] | translate }}
+ {{ action.dateModified | dateAgo }}
+ {{ 'moderation.submissionReview.by' | translate }}
+ {{ action.creator?.name }}
+
+ @if (action.toState === registryActionState.Accepted) {
+ {{ 'moderation.withNoEmbargo' | translate }}
+ }
+
+ @if (action.comment.length) {
+
+ }
+
+ }
+
+ @if (submission().actions.length > 1) {
+
+ }
+
+
+
+
+
+
+
{{ 'common.labels.contributors' | translate }}:
+
+
+
+
+
+
+
diff --git a/src/app/features/moderation/components/registry-submission-item/registry-submission-item.component.ts b/src/app/features/moderation/components/registry-submission-item/registry-submission-item.component.ts
index 38f265cf8..770db64d4 100644
--- a/src/app/features/moderation/components/registry-submission-item/registry-submission-item.component.ts
+++ b/src/app/features/moderation/components/registry-submission-item/registry-submission-item.component.ts
@@ -1,10 +1,12 @@
import { TranslatePipe } from '@ngx-translate/core';
+import { Accordion, AccordionContent, AccordionHeader, AccordionPanel } from 'primeng/accordion';
import { Button } from 'primeng/button';
import { DatePipe } from '@angular/common';
-import { ChangeDetectionStrategy, Component, input, output } from '@angular/core';
+import { ChangeDetectionStrategy, Component, computed, input, output } from '@angular/core';
+import { ContributorsListComponent } from '@osf/shared/components/contributors-list/contributors-list.component';
import { IconComponent } from '@osf/shared/components/icon/icon.component';
import { TruncatedTextComponent } from '@osf/shared/components/truncated-text/truncated-text.component';
import { DateAgoPipe } from '@osf/shared/pipes/date-ago.pipe';
@@ -15,7 +17,19 @@ import { RegistryModeration } from '../../models';
@Component({
selector: 'osf-registry-submission-item',
- imports: [IconComponent, DateAgoPipe, Button, TranslatePipe, DatePipe, TruncatedTextComponent],
+ imports: [
+ IconComponent,
+ DateAgoPipe,
+ Button,
+ TranslatePipe,
+ DatePipe,
+ TruncatedTextComponent,
+ Accordion,
+ AccordionPanel,
+ AccordionHeader,
+ AccordionContent,
+ ContributorsListComponent,
+ ],
templateUrl: './registry-submission-item.component.html',
styleUrl: './registry-submission-item.component.scss',
changeDetection: ChangeDetectionStrategy.OnPush,
@@ -23,6 +37,8 @@ import { RegistryModeration } from '../../models';
export class RegistrySubmissionItemComponent {
status = input.required
();
submission = input.required();
+ loadContributors = output();
+ loadMoreContributors = output();
selected = output();
@@ -40,4 +56,17 @@ export class RegistrySubmissionItemComponent {
toggleHistory() {
this.showAll = !this.showAll;
}
+
+ hasMoreContributors = computed(() => {
+ const submission = this.submission();
+ if (submission.contributors && submission.totalContributors) {
+ return submission.contributors.length < submission.totalContributors;
+ }
+
+ return false;
+ });
+
+ handleOpen() {
+ this.loadContributors.emit();
+ }
}
diff --git a/src/app/features/moderation/components/registry-submissions/registry-submissions.component.html b/src/app/features/moderation/components/registry-submissions/registry-submissions.component.html
index 53a842857..5066d15f7 100644
--- a/src/app/features/moderation/components/registry-submissions/registry-submissions.component.html
+++ b/src/app/features/moderation/components/registry-submissions/registry-submissions.component.html
@@ -39,6 +39,8 @@
[submission]="item"
[status]="selectedReviewOption()"
(selected)="navigateToRegistration(item)"
+ (loadContributors)="loadContributors(item)"
+ (loadMoreContributors)="loadMoreContributors(item)"
>
}
diff --git a/src/app/features/moderation/components/registry-submissions/registry-submissions.component.ts b/src/app/features/moderation/components/registry-submissions/registry-submissions.component.ts
index 86afd1975..e664daacc 100644
--- a/src/app/features/moderation/components/registry-submissions/registry-submissions.component.ts
+++ b/src/app/features/moderation/components/registry-submissions/registry-submissions.component.ts
@@ -24,7 +24,12 @@ import { Primitive } from '@osf/shared/helpers/types.helper';
import { REGISTRY_SORT_OPTIONS, SUBMITTED_SUBMISSION_REVIEW_OPTIONS } from '../../constants';
import { RegistrySort, SubmissionReviewStatus } from '../../enums';
import { RegistryModeration } from '../../models';
-import { GetRegistrySubmissions, RegistryModerationSelectors } from '../../store/registry-moderation';
+import {
+ GetRegistrySubmissionContributors,
+ GetRegistrySubmissions,
+ LoadMoreRegistrySubmissionContributors,
+ RegistryModerationSelectors,
+} from '../../store/registry-moderation';
import { RegistrySubmissionItemComponent } from '..';
@Component({
@@ -54,7 +59,11 @@ export class RegistrySubmissionsComponent implements OnInit {
this.route.parent?.params.pipe(map((params) => params['providerId'])) ?? of(undefined)
);
- readonly actions = createDispatchMap({ getRegistrySubmissions: GetRegistrySubmissions });
+ readonly actions = createDispatchMap({
+ getRegistrySubmissions: GetRegistrySubmissions,
+ getRegistrySubmissionContributors: GetRegistrySubmissionContributors,
+ loadMoreRegistrySubmissionContributors: LoadMoreRegistrySubmissionContributors,
+ });
readonly submissions = select(RegistryModerationSelectors.getRegistrySubmissions);
readonly isLoading = select(RegistryModerationSelectors.areRegistrySubmissionLoading);
@@ -112,6 +121,14 @@ export class RegistrySubmissionsComponent implements OnInit {
window.open(url, '_blank');
}
+ loadContributors(item: RegistryModeration) {
+ this.actions.getRegistrySubmissionContributors(item.id);
+ }
+
+ loadMoreContributors(item: RegistryModeration) {
+ this.actions.loadMoreRegistrySubmissionContributors(item.id);
+ }
+
private getStatusFromQueryParams() {
const queryParams = this.route.snapshot.queryParams;
const statusValues = Object.values(SubmissionReviewStatus);
diff --git a/src/app/features/moderation/models/registry-moderation.model.ts b/src/app/features/moderation/models/registry-moderation.model.ts
index cf2cc9662..2d59b2681 100644
--- a/src/app/features/moderation/models/registry-moderation.model.ts
+++ b/src/app/features/moderation/models/registry-moderation.model.ts
@@ -1,5 +1,6 @@
import { RegistrationReviewStates } from '@osf/shared/enums/registration-review-states.enum';
import { RevisionReviewStates } from '@osf/shared/enums/revision-review-states.enum';
+import { ContributorModel } from '@shared/models/contributors/contributor.model';
import { ReviewAction } from './review-action.model';
@@ -13,4 +14,8 @@ export interface RegistryModeration {
embargoEndDate: string | null;
actions: ReviewAction[];
revisionId?: string | null;
+ contributorsLoading?: boolean;
+ contributors?: ContributorModel[];
+ totalContributors?: number;
+ contributorsPage?: number;
}
diff --git a/src/app/features/moderation/store/collections-moderation/collections-moderation.actions.ts b/src/app/features/moderation/store/collections-moderation/collections-moderation.actions.ts
index dc44a8e29..a71fbfd7b 100644
--- a/src/app/features/moderation/store/collections-moderation/collections-moderation.actions.ts
+++ b/src/app/features/moderation/store/collections-moderation/collections-moderation.actions.ts
@@ -29,3 +29,18 @@ export class CreateCollectionSubmissionAction {
export class ClearCollectionModeration {
static readonly type = '[Collections Moderation] ClearCollectionModeration';
}
+
+export class GetCollectionSubmissionContributors {
+ static readonly type = `[Collections Moderation] Get Registry Submission Contributors`;
+
+ constructor(
+ public collectionId: string,
+ public page = 1
+ ) {}
+}
+
+export class LoadMoreCollectionSubmissionContributors {
+ static readonly type = `[Collections Moderation] Load More Collection Submission Contributors`;
+
+ constructor(public collectionId: string) {}
+}
diff --git a/src/app/features/moderation/store/collections-moderation/collections-moderation.state.ts b/src/app/features/moderation/store/collections-moderation/collections-moderation.state.ts
index 5e4d94010..fb5132c9b 100644
--- a/src/app/features/moderation/store/collections-moderation/collections-moderation.state.ts
+++ b/src/app/features/moderation/store/collections-moderation/collections-moderation.state.ts
@@ -6,13 +6,18 @@ import { catchError, forkJoin, map, of, switchMap, tap } from 'rxjs';
import { inject, Injectable } from '@angular/core';
import { CollectionsService } from '@osf/shared/services/collections.service';
+import { DEFAULT_TABLE_PARAMS } from '@shared/constants/default-table-params.constants';
+import { ResourceType } from '@shared/enums/resource-type.enum';
import { handleSectionError } from '@shared/helpers/state-error.handler';
+import { ContributorsService } from '@shared/services/contributors.service';
import {
ClearCollectionModeration,
CreateCollectionSubmissionAction,
+ GetCollectionSubmissionContributors,
GetCollectionSubmissions,
GetSubmissionsReviewActions,
+ LoadMoreCollectionSubmissionContributors,
} from './collections-moderation.actions';
import { COLLECTIONS_MODERATION_STATE_DEFAULTS, CollectionsModerationStateModel } from './collections-moderation.model';
@@ -23,6 +28,7 @@ import { COLLECTIONS_MODERATION_STATE_DEFAULTS, CollectionsModerationStateModel
@Injectable()
export class CollectionsModerationState {
collectionsService = inject(CollectionsService);
+ contributorsService = inject(ContributorsService);
@Action(GetCollectionSubmissions)
getCollectionSubmissions(ctx: StateContext