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

WITHDRAW / REINSTATE requests for an item #2759

Merged
merged 43 commits into from
Feb 27, 2024
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
752cb4d
[CST-11178] show allowed correction types
Micheleboychuk Oct 30, 2023
bf67fee
[CST-11178][CST-11179] page to select the target item for "relation" …
Micheleboychuk Oct 30, 2023
d49185e
[CST-11178][CST-11179] POST action of correction suggestion
Micheleboychuk Oct 30, 2023
eeefd86
[CST-11179][CST-11178] Fixes
Micheleboychuk Oct 30, 2023
d7857a6
[CST-11179][CST-11178] fix
alisaismailati Aug 9, 2023
c50dd72
[CST-11178][CST-11179] allow access for authorized user only
alisaismailati Aug 10, 2023
f76e224
[CST-11178]CST-11179] small fix
alisaismailati Aug 10, 2023
8157c47
[CST-11178] Fix correction-type-menu.component visualization
atarix83 Aug 28, 2023
5f63e30
[CST-11178] Fix issue with correction type routing
Micheleboychuk Oct 30, 2023
b907c81
[CST-11178] Fix issue with link
atarix83 Aug 29, 2023
ac7cf5b
[CST-11178] Fix issue while retrieving the id
atarix83 Aug 29, 2023
1a525df
[CST-11179] Fixed breadcrumb & refresh & labels & redirection from /f…
Micheleboychuk Oct 30, 2023
143916c
[CST-11178][CST-11179] fixed pagination for relationship management
alisaismailati Sep 6, 2023
9094d82
[CST-12109] implemented withdrawn-reinstate requests
Micheleboychuk Nov 1, 2023
0b39197
[CST-12109] added new labels
Micheleboychuk Nov 1, 2023
6dc3528
[CTS-12109] refactoring
Micheleboychuk Nov 2, 2023
ef1bd9f
[CST-12109] improve code
Micheleboychuk Nov 3, 2023
5589c76
[CST-12109] porting of box thatallows undo of QAEvent request
Micheleboychuk Nov 7, 2023
1c3776b
[CST-12109] porting missing code
Micheleboychuk Nov 24, 2023
101cd0a
[CST-12109] improvement code
Micheleboychuk Nov 27, 2023
3ecc1ca
Merge branch 'main' into CST-12109-WITHDRAWN-REINSTATE-requests
alisaismailati Jan 17, 2024
805e98b
[CST-12109] fixed failing unit tests after merge
alisaismailati Jan 17, 2024
a4b0c5a
cherry-picked "[CST-12791] changed the route for suggestions to be be…
alisaismailati Nov 30, 2023
80a0cd4
[CST-12109] "refresh" page on item withdrawn from details page
alisaismailati Jan 18, 2024
415bdea
cherry-picked "[CST-12145] get qa-sources by target for item-page & r…
alisaismailati Nov 2, 2023
e4858f2
[CST-12109] fixes
alisaismailati Jan 18, 2024
ad5e3af
[CST-12109] "refresh" page refactor
alisaismailati Jan 22, 2024
8cc45e8
[CST-12109] request reinstate for normal users
alisaismailati Jan 23, 2024
2f43bb7
[CST-12109] small fixes
alisaismailati Jan 23, 2024
ac6c890
[CST-12109] tests & translations
alisaismailati Jan 23, 2024
1b5007a
[CST-12109] display user's email info on topic list
alisaismailati Jan 24, 2024
f916bd7
[CST-12109] fixes
alisaismailati Feb 5, 2024
d72610f
Merge branch 'main' into CST-12109-WITHDRAWN-REINSTATE-requests
alisaismailati Feb 12, 2024
8d0971d
Merge branch 'main' into CST-12109-WITHDRAWN-REINSTATE-requests
alisaismailati Feb 21, 2024
7350fdd
[CST-12109] qa-event notification box fixes
alisaismailati Feb 21, 2024
c34a49e
[CST-12109] lint fix
alisaismailati Feb 21, 2024
6c73a2e
Merge branch 'main' into CST-12109-WITHDRAWN-REINSTATE-requests
alisaismailati Feb 22, 2024
e7579b7
[CST-12109] fix of text messages / source image
alisaismailati Feb 23, 2024
37dc8cc
[CST-12109] logo alignment
alisaismailati Feb 23, 2024
49a3310
[CST-12109] rewrite unit test case
alisaismailati Feb 23, 2024
d0ed405
[CST-12109] added discernable text to delete button for non-admin users
alisaismailati Feb 26, 2024
447b275
[CST-12109] Updated notification text messages
alisaismailati Feb 27, 2024
e4b2814
Merge branch 'main' of https://bitbucket.org/4Science/dspace-angular …
alisaismailati Feb 27, 2024
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
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { URLCombiner } from '../../core/url-combiner/url-combiner';
import { getNotificationsModuleRoute } from '../admin-routing-paths';

export const QUALITY_ASSURANCE_EDIT_PATH = 'quality-assurance';
export const PUBLICATION_CLAIMS_PATH = 'publication-claim';

export function getQualityAssuranceRoute(id: string) {
return new URLCombiner(getNotificationsModuleRoute(), QUALITY_ASSURANCE_EDIT_PATH, id).toString();
export function getQualityAssuranceEditRoute() {
return `/${QUALITY_ASSURANCE_EDIT_PATH}`;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ import { AdminQualityAssuranceTopicsPageResolver } from './admin-quality-assuran
import { AdminQualityAssuranceEventsPageResolver } from './admin-quality-assurance-events-page/admin-quality-assurance-events-page.resolver';
import { AdminQualityAssuranceSourcePageComponent } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page.component';
import { AdminQualityAssuranceSourcePageResolver } from './admin-quality-assurance-source-page-component/admin-quality-assurance-source-page-resolver.service';
import {
SiteAdministratorGuard
} from '../../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
import { QualityAssuranceBreadcrumbResolver } from '../../core/breadcrumbs/quality-assurance-breadcrumb.resolver';
import { QualityAssuranceBreadcrumbService } from '../../core/breadcrumbs/quality-assurance-breadcrumb.service';
import {
Expand Down Expand Up @@ -55,6 +58,21 @@ import {
},
{
canActivate: [ AuthenticatedGuard ],
path: `${QUALITY_ASSURANCE_EDIT_PATH}/:sourceId/target/:targetId`,
component: AdminQualityAssuranceTopicsPageComponent,
pathMatch: 'full',
resolve: {
breadcrumb: I18nBreadcrumbResolver,
openaireQualityAssuranceTopicsParams: AdminQualityAssuranceTopicsPageResolver
},
data: {
title: 'admin.quality-assurance.page.title',
breadcrumbKey: 'admin.quality-assurance',
showBreadcrumbsFluid: false
}
},
{
canActivate: [ SiteAdministratorGuard ],
path: `${QUALITY_ASSURANCE_EDIT_PATH}`,
component: AdminQualityAssuranceSourcePageComponent,
pathMatch: 'full',
Expand Down
5 changes: 5 additions & 0 deletions src/app/admin/admin-routing-paths.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { URLCombiner } from '../core/url-combiner/url-combiner';
import { getAdminModuleRoute } from '../app-routing-paths';
import { getQualityAssuranceEditRoute } from './admin-notifications/admin-notifications-routing-paths';

export const REGISTRIES_MODULE_PATH = 'registries';
export const NOTIFICATIONS_MODULE_PATH = 'notifications';
Expand All @@ -11,3 +12,7 @@ export function getRegistriesModuleRoute() {
export function getNotificationsModuleRoute() {
return new URLCombiner(getAdminModuleRoute(), NOTIFICATIONS_MODULE_PATH).toString();
}

export function getNotificatioQualityAssuranceRoute() {
return new URLCombiner(`/${NOTIFICATIONS_MODULE_PATH}`, getQualityAssuranceEditRoute()).toString();
}
29 changes: 17 additions & 12 deletions src/app/admin/admin-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,57 +6,62 @@ import { I18nBreadcrumbResolver } from '../core/breadcrumbs/i18n-breadcrumb.reso
import { AdminWorkflowPageComponent } from './admin-workflow-page/admin-workflow-page.component';
import { I18nBreadcrumbsService } from '../core/breadcrumbs/i18n-breadcrumbs.service';
import { AdminCurationTasksComponent } from './admin-curation-tasks/admin-curation-tasks.component';
import { REGISTRIES_MODULE_PATH, NOTIFICATIONS_MODULE_PATH } from './admin-routing-paths';
import { REGISTRIES_MODULE_PATH } from './admin-routing-paths';
import { BatchImportPageComponent } from './admin-import-batch-page/batch-import-page.component';
import {
SiteAdministratorGuard
} from '../core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';

@NgModule({
imports: [
RouterModule.forChild([
{
path: NOTIFICATIONS_MODULE_PATH,
loadChildren: () => import('./admin-notifications/admin-notifications.module')
.then((m) => m.AdminNotificationsModule),
},
{
path: REGISTRIES_MODULE_PATH,
loadChildren: () => import('./admin-registries/admin-registries.module')
.then((m) => m.AdminRegistriesModule),
canActivate: [SiteAdministratorGuard]
},
{
path: 'search',
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: AdminSearchPageComponent,
data: { title: 'admin.search.title', breadcrumbKey: 'admin.search' }
data: { title: 'admin.search.title', breadcrumbKey: 'admin.search' },
canActivate: [SiteAdministratorGuard]
},
{
path: 'workflow',
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: AdminWorkflowPageComponent,
data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' }
data: { title: 'admin.workflow.title', breadcrumbKey: 'admin.workflow' },
canActivate: [SiteAdministratorGuard]
},
{
path: 'curation-tasks',
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: AdminCurationTasksComponent,
data: { title: 'admin.curation-tasks.title', breadcrumbKey: 'admin.curation-tasks' }
data: { title: 'admin.curation-tasks.title', breadcrumbKey: 'admin.curation-tasks' },
canActivate: [SiteAdministratorGuard]
},
{
path: 'metadata-import',
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: MetadataImportPageComponent,
data: { title: 'admin.metadata-import.title', breadcrumbKey: 'admin.metadata-import' }
data: { title: 'admin.metadata-import.title', breadcrumbKey: 'admin.metadata-import' },
canActivate: [SiteAdministratorGuard]
},
{
path: 'batch-import',
resolve: { breadcrumb: I18nBreadcrumbResolver },
component: BatchImportPageComponent,
data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' }
data: { title: 'admin.batch-import.title', breadcrumbKey: 'admin.batch-import' },
canActivate: [SiteAdministratorGuard]
},
{
path: 'system-wide-alert',
resolve: { breadcrumb: I18nBreadcrumbResolver },
loadChildren: () => import('../system-wide-alert/system-wide-alert.module').then((m) => m.SystemWideAlertModule),
data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'}
data: {title: 'admin.system-wide-alert.title', breadcrumbKey: 'admin.system-wide-alert'},
canActivate: [SiteAdministratorGuard]
},
])
],
Expand Down
7 changes: 7 additions & 0 deletions src/app/app-routing-paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,10 @@ export const SUBSCRIPTIONS_MODULE_PATH = 'subscriptions';
export function getSubscriptionsModuleRoute() {
return `/${SUBSCRIPTIONS_MODULE_PATH}`;
}

export const EDIT_ITEM_PATH = 'edit-items';
export function getEditItemPageRoute() {
return `/${EDIT_ITEM_PATH}`;
}
export const CORRECTION_TYPE_PATH = 'corrections';

14 changes: 9 additions & 5 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ import { NoPreloading, RouterModule } from '@angular/router';
import { AuthBlockingGuard } from './core/auth/auth-blocking.guard';

import { AuthenticatedGuard } from './core/auth/authenticated.guard';
import {
SiteAdministratorGuard
} from './core/data/feature-authorization/feature-authorization-guard/site-administrator.guard';
import {
ACCESS_CONTROL_MODULE_PATH,
ADMIN_MODULE_PATH,
Expand Down Expand Up @@ -41,6 +38,7 @@ import { ServerCheckGuard } from './core/server-check/server-check.guard';
import { SUGGESTION_MODULE_PATH } from './suggestions-page/suggestions-page-routing-paths';
import { MenuResolver } from './menu.resolver';
import { ThemedPageErrorComponent } from './page-error/themed-page-error.component';
import { NOTIFICATIONS_MODULE_PATH } from './admin/admin-routing-paths';
import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-check-guard.guard';

@NgModule({
Expand Down Expand Up @@ -159,7 +157,13 @@ import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-c
path: ADMIN_MODULE_PATH,
loadChildren: () => import('./admin/admin.module')
.then((m) => m.AdminModule),
canActivate: [SiteAdministratorGuard, EndUserAgreementCurrentUserGuard]
canActivate: [EndUserAgreementCurrentUserGuard]
},
{
path: NOTIFICATIONS_MODULE_PATH,
loadChildren: () => import('./admin/admin-notifications/admin-notifications.module')
.then((m) => m.AdminNotificationsModule),
canActivate: [AuthenticatedGuard, EndUserAgreementCurrentUserGuard]
},
{
path: 'login',
Expand Down Expand Up @@ -247,7 +251,7 @@ import { ForgotPasswordCheckGuard } from './core/rest-property/forgot-password-c
.then((m) => m.SubscriptionsPageRoutingModule),
canActivate: [AuthenticatedGuard]
},
{ path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent },
{ path: '**', pathMatch: 'full', component: ThemedPageNotFoundComponent }
]
}
], {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ export class QualityAssuranceBreadcrumbService implements BreadcrumbsProviderSer
*/
getBreadcrumbs(key: string, url: string): Observable<Breadcrumb[]> {
const sourceId = key.split(':')[0];
const topicId = key.split(':')[1];
const topicId = key.split(':')[2];

if (topicId) {
return this.qualityAssuranceService.getTopic(topicId).pipe(
getFirstCompletedRemoteData(),
map((topic) => {
return [new Breadcrumb(this.translationService.instant(this.QUALITY_ASSURANCE_BREADCRUMB_KEY), url),
new Breadcrumb(sourceId, `${url}${sourceId}`),
new Breadcrumb(topicId, undefined)];
new Breadcrumb(topicId.replace(/[!:]/g, '/'), undefined)];
})
);
} else {
Expand Down
4 changes: 3 additions & 1 deletion src/app/core/core.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ import { FlatBrowseDefinition } from './shared/flat-browse-definition.model';
import { ValueListBrowseDefinition } from './shared/value-list-browse-definition.model';
import { NonHierarchicalBrowseDefinition } from './shared/non-hierarchical-browse-definition';
import { BulkAccessConditionOptions } from './config/models/bulk-access-condition-options.model';
import { CorrectionTypeDataService } from './submission/correctiontype-data.service';
import { SuggestionTarget } from './suggestion-notifications/models/suggestion-target.model';
import { SuggestionSource } from './suggestion-notifications/models/suggestion-source.model';

Expand Down Expand Up @@ -309,7 +310,8 @@ const PROVIDERS = [
OrcidAuthService,
OrcidQueueDataService,
OrcidHistoryDataService,
SupervisionOrderDataService
SupervisionOrderDataService,
CorrectionTypeDataService
];

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable } from '@angular/core';

import { Observable } from 'rxjs';
import { find, take } from 'rxjs/operators';
import { find, switchMap, take } from 'rxjs/operators';
import { ReplaceOperation } from 'fast-json-patch';

import { HALEndpointService } from '../../../shared/hal-endpoint.service';
Expand All @@ -25,6 +25,11 @@ import { SearchData, SearchDataImpl } from '../../../data/base/search-data';
import { DefaultChangeAnalyzer } from '../../../data/default-change-analyzer.service';
import { hasValue } from '../../../../shared/empty.util';
import { DeleteByIDRequest, PostRequest } from '../../../data/request.models';
import { HttpHeaders, HttpParams } from '@angular/common/http';
import { HttpOptions } from '../../../dspace-rest/dspace-rest.service';
import {
QualityAssuranceEventData
} from '../../../../notifications/qa/project-entry-import-modal/project-entry-import-modal.component';

/**
* The service handling all Quality Assurance topic REST requests.
Expand Down Expand Up @@ -84,6 +89,16 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService<Qu
return this.searchData.searchBy('findByTopic', options, true, true, ...linksToFollow);
}

/**
* Service for retrieving Quality Assurance events by topic and target.
* @param options (Optional) The search options to use when retrieving the events.
* @param linksToFollow (Optional) The links to follow when retrieving the events.
* @returns An observable of the remote data containing the paginated list of Quality Assurance events.
*/
public searchEventsByTopic(options: FindListOptions = {}, ...linksToFollow: FollowLinkConfig<QualityAssuranceEventObject>[]): Observable<RemoteData<PaginatedList<QualityAssuranceEventObject>>> {
return this.searchData.searchBy('findByTopic', options, true, true, ...linksToFollow);
}

/**
* Clear findByTopic requests from cache
*/
Expand Down Expand Up @@ -200,4 +215,38 @@ export class QualityAssuranceEventDataService extends IdentifiableDataService<Qu

return this.rdbService.buildFromRequestUUID<QualityAssuranceEventObject>(requestId);
}

/**
* Perform a post on an endpoint related to correction type
* @param data the data to post
* @returns the RestResponse as an Observable
*/
postData(target: string, correctionType: string, related: string, reason: string): Observable<RemoteData<QualityAssuranceEventObject>> {
const requestId = this.requestService.generateRequestId();
const href$ = this.getBrowseEndpoint();

return href$.pipe(
switchMap((href: string) => {
const options: HttpOptions = Object.create({});
let headers = new HttpHeaders();
headers = headers.append('Content-Type', 'application/json');
options.headers = headers;
let params = new HttpParams();
params = params.append('target', target)
.append('correctionType', correctionType);
options.params = params;
const request = new PostRequest(requestId, href, {'reason': reason} , options);
if (hasValue(this.responseMsToLive)) {
request.responseMsToLive = this.responseMsToLive;
}
this.requestService.send(request);
return this.rdbService.buildFromRequestUUID<QualityAssuranceEventObject>(requestId);
})
);
}

public deleteQAEvent(qaEvent: QualityAssuranceEventData): Observable<RemoteData<NoContent>> {
return this.deleteData.delete(qaEvent.id);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export interface SourceQualityAssuranceEventMessageObject {
*/
type: string;

reason: string;

/**
* The value suggested by Notifications
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { PaginatedList } from '../../../data/paginated-list.model';
import { FindListOptions } from '../../../data/find-list-options.model';
import { IdentifiableDataService } from '../../../data/base/identifiable-data.service';
import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data';
import { SearchData, SearchDataImpl } from '../../../data/base/search-data';

/**
* The service handling all Quality Assurance source REST requests.
Expand All @@ -25,6 +26,9 @@ import { FindAllData, FindAllDataImpl } from '../../../data/base/find-all-data';
export class QualityAssuranceSourceDataService extends IdentifiableDataService<QualityAssuranceSourceObject> {

private findAllData: FindAllData<QualityAssuranceSourceObject>;
private searchAllData: SearchData<QualityAssuranceSourceObject>;

private searchByTargetMethod = 'byTarget';

/**
* Initialize service variables
Expand All @@ -43,6 +47,7 @@ export class QualityAssuranceSourceDataService extends IdentifiableDataService<Q
) {
super('qualityassurancesources', requestService, rdbService, objectCache, halService);
this.findAllData = new FindAllDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive);
this.searchAllData = new SearchDataImpl(this.linkPath, requestService, rdbService, objectCache, halService, this.responseMsToLive);
}

/**
Expand Down Expand Up @@ -84,4 +89,16 @@ export class QualityAssuranceSourceDataService extends IdentifiableDataService<Q
public getSource(id: string, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<QualityAssuranceSourceObject>[]): Observable<RemoteData<QualityAssuranceSourceObject>> {
return this.findById(id, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
}

/**
* Retrieves a paginated list of QualityAssuranceSourceObject objects that are associated with a given target object.
* @param options The options for the search query.
* @param useCachedVersionIfAvailable Whether to use a cached version of the data if available.
* @param reRequestOnStale Whether to re-request the data if the cached version is stale.
* @param linksToFollow The links to follow to retrieve the data.
* @returns An observable that emits a RemoteData object containing the paginated list of QualityAssuranceSourceObject objects.
*/
public getSourcesByTarget(options: FindListOptions = {}, useCachedVersionIfAvailable = true, reRequestOnStale = true, ...linksToFollow: FollowLinkConfig<QualityAssuranceSourceObject>[]): Observable<RemoteData<PaginatedList<QualityAssuranceSourceObject>>> {
return this.searchAllData.searchBy(this.searchByTargetMethod, options, useCachedVersionIfAvailable, reRequestOnStale, ...linksToFollow);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,27 @@ describe('QualityAssuranceTopicDataService', () => {

spyOn((service as any).findAllData, 'findAll').and.callThrough();
spyOn((service as any), 'findById').and.callThrough();
spyOn((service as any).searchData, 'searchBy').and.callThrough();
});

describe('getTopics', () => {
it('should call findListByHref', (done) => {
service.getTopics().subscribe(
(res) => {
expect((service as any).findAllData.findAll).toHaveBeenCalledWith({}, true, true);
}
describe('searchTopicsByTarget', () => {
it('should call searchData.searchBy with the correct parameters', () => {
const options = { elementsPerPage: 10 };
const useCachedVersionIfAvailable = true;
const reRequestOnStale = true;

service.searchTopicsByTarget(options, useCachedVersionIfAvailable, reRequestOnStale);

expect((service as any).searchData.searchBy).toHaveBeenCalledWith(
'byTarget',
options,
useCachedVersionIfAvailable,
reRequestOnStale
);
done();
});

it('should return a RemoteData<PaginatedList<QualityAssuranceTopicObject>> for the object with the given URL', () => {
const result = service.getTopics();
const result = service.searchTopicsByTarget();
const expected = cold('(a)', {
a: paginatedListRD
});
Expand Down
Loading
Loading