Skip to content

PUB-2806 Add functionality to re-submit subscription in blob explorer #1454

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

Merged
merged 19 commits into from
Apr 11, 2025
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
30 changes: 22 additions & 8 deletions src/main/controllers/system-admin/BlobViewJsonController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,14 @@ const locationService = new LocationService();
const userManagementService = new UserManagementService();
export default class BlobViewJsonController {
public async get(req: PipRequest, res: Response): Promise<void> {
const artefactId = req.query.artefactId as string;
const artefactId = req.query.artefactId;
const data = await publicationService.getIndividualPublicationJson(artefactId, req.user['userId']);
const metadata = await publicationService.getIndividualPublicationMetadata(artefactId, req.user['userId']);

if (isValidList(data, metadata)) {
const listTypes = publicationService.getListTypes();
const noMatchArtefact = metadata.locationId.toString().includes('NoMatch');
let courtName = '';
if (!noMatchArtefact) {
courtName = (await locationService.getLocationById(parseInt(metadata.locationId.toString()))).name;
} else {
courtName = 'No match artefacts';
}
const locationName = await BlobViewJsonController.getLocationName(metadata.locationId, noMatchArtefact);

await userManagementService.auditAction(
req.user,
Expand All @@ -38,7 +33,7 @@ export default class BlobViewJsonController {
res.render('system-admin/blob-view-json', {
...cloneDeep(req.i18n.getDataByLanguage(req.lng)['blob-view-json']),
data: JSON.stringify(data),
courtName,
locationName,
artefactId,
metadata,
listUrl,
Expand All @@ -50,4 +45,23 @@ export default class BlobViewJsonController {
res.render('error', req.i18n.getDataByLanguage(req.lng).error);
}
}

public async post(req: PipRequest, res: Response): Promise<void> {
const artefactId = req.query.artefactId;
if (artefactId) {
res.redirect(`blob-view-subscription-resubmit-confirmation?artefactId=${artefactId}`);
} else {
res.render('error', req.i18n.getDataByLanguage(req.lng).error);
}
}

private static async getLocationName(locationId, noMatchArtefact): Promise<string> {
let locationName = '';
if (!noMatchArtefact) {
locationName = (await locationService.getLocationById(parseInt(locationId.toString()))).name;
} else {
locationName = 'No match artefacts';
}
return locationName;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { PipRequest } from '../../models/request/PipRequest';
import { Response } from 'express';
import { cloneDeep } from 'lodash';
import { PublicationService } from '../../service/PublicationService';
import { LocationService } from '../../service/LocationService';
import { SubscriptionService } from '../../service/SubscriptionService';
import { UserManagementService } from '../../service/UserManagementService';

const publicationService = new PublicationService();
const locationService = new LocationService();
const subscriptionService = new SubscriptionService();
const userManagementService = new UserManagementService();

export default class BlobViewSubscriptionResubmitConfirmationController {
public async get(req: PipRequest, res: Response): Promise<void> {
const artefactId = req.query.artefactId;
if (artefactId) {
const metadata = await publicationService.getIndividualPublicationMetadata(artefactId, req.user['userId']);
const locationName = (await locationService.getLocationById(parseInt(metadata.locationId.toString()))).name;
res.render('system-admin/blob-view-subscription-resubmit-confirmation', {
...cloneDeep(req.i18n.getDataByLanguage(req.lng)['blob-view-subscription-resubmit-confirmation']),
locationName,
metadata,
});
} else {
res.render('error', req.i18n.getDataByLanguage(req.lng).error);
}
}

public async post(req: PipRequest, res: Response): Promise<void> {
const artefactId = req.query.artefactId;
if (artefactId) {
const response = await subscriptionService.fulfillSubscriptions(artefactId, req.user['userId']);
if (response) {
await userManagementService.auditAction(
req.user,
'RESUBMIT_SUBSCRIPTION',
`Subscriptions for publication with artefact id ${artefactId} re-submitted successfully`
);

res.redirect('blob-view-subscription-resubmit-confirmed');
} else {
res.render('error', req.i18n.getDataByLanguage(req.lng).error);
}
} else {
res.render('error', req.i18n.getDataByLanguage(req.lng).error);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { PipRequest } from '../../models/request/PipRequest';
import { Response } from 'express';

export default class BlobViewSubscriptionResubmitConfirmedController {
public async get(req: PipRequest, res: Response): Promise<void> {
res.render(
'system-admin/blob-view-subscription-resubmit-confirmed',
req.i18n.getDataByLanguage(req.lng)['blob-view-subscription-resubmit-confirmed']
);
}
}
4 changes: 4 additions & 0 deletions src/main/resources/auditActions.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,9 @@
{
"key": "REJECT_MEDIA_APPLICATION",
"name": "Reject Media Application"
},
{
"key": "RESUBMIT_SUBSCRIPTION",
"name": "Re-submit subscription"
}
]
3 changes: 2 additions & 1 deletion src/main/resources/locales/cy/blob-view-json.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"viewJson": "View Raw JSON Content",
"viewLink": "Link to rendered template",
"flatFile": "Flat file",
"jsonFile": "JSON file"
"jsonFile": "JSON file",
"resubmit": "Re-submit subscription"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "Confirm subscription re-submission",
"confirmButton": "Confirm",
"cancelButton": "Cancel"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "Subscription re-submitted",
"nextMessage": "What do you want to do next?",
"blobLocation": "Blob explorer - Locations"
}
3 changes: 2 additions & 1 deletion src/main/resources/locales/en/blob-view-json.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
"viewJson": "View Raw JSON Content",
"viewLink": "Link to rendered template",
"flatFile": "Flat file",
"jsonFile": "JSON file"
"jsonFile": "JSON file",
"resubmit": "Re-submit subscription"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "Confirm subscription re-submission",
"confirmButton": "Confirm",
"cancelButton": "Cancel"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"title": "Subscription re-submitted",
"nextMessage": "What do you want to do next?",
"blobLocation": "Blob explorer - Locations"
}
10 changes: 10 additions & 0 deletions src/main/resources/requests/SubscriptionRequests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,14 @@ export class SubscriptionRequests {
}
return null;
}

public async fulfillSubscriptions(artefact): Promise<string> {
try {
const response = await subscriptionManagementApi.post('/subscription/artefact-recipients', artefact);
return response.data;
} catch (error) {
logHelper.logErrorResponse(error, `fulfill subscriptions for artefact with ID ${artefact.arterfactId}`);
}
return null;
}
}
18 changes: 18 additions & 0 deletions src/main/routes/routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -642,13 +642,31 @@ export default function (app: Application): void {
isPermittedSystemAdmin,
app.locals.container.cradle.systemAdminDashboardController.get
);

app.get('/blob-view-locations', isPermittedSystemAdmin, app.locals.container.cradle.blobViewLocationController.get);
app.get(
'/blob-view-publications',
isPermittedSystemAdmin,
app.locals.container.cradle.blobViewPublicationsController.get
);
app.get('/blob-view-json', isPermittedSystemAdmin, app.locals.container.cradle.blobViewJsonController.get);
app.post('/blob-view-json', isPermittedSystemAdmin, app.locals.container.cradle.blobViewJsonController.post);
app.get(
'/blob-view-subscription-resubmit-confirmation',
isPermittedSystemAdmin,
app.locals.container.cradle.blobViewSubscriptionResubmitConfirmationController.get
);
app.post(
'/blob-view-subscription-resubmit-confirmation',
isPermittedSystemAdmin,
app.locals.container.cradle.blobViewSubscriptionResubmitConfirmationController.post
);
app.get(
'/blob-view-subscription-resubmit-confirmed',
isPermittedSystemAdmin,
app.locals.container.cradle.blobViewSubscriptionResubmitConfirmedController.get
);

app.get(
'/bulk-create-media-accounts',
isPermittedSystemAdmin,
Expand Down
5 changes: 5 additions & 0 deletions src/main/service/SubscriptionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -639,4 +639,9 @@ export class SubscriptionService {
});
pendingSubscriptionsFromCache.setListTypeSubscription(userId, [...new Set(selectedListTypes)]);
}

public async fulfillSubscriptions(artefactId, userId): Promise<string> {
const artefact = await publicationService.getIndividualPublicationMetadata(artefactId, userId);
return await subscriptionRequests.fulfillSubscriptions(artefact);
}
}
45 changes: 23 additions & 22 deletions src/main/views/system-admin/blob-view-json.njk
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
{% extends "../template.njk" %}
{% from "../macros/common-components.njk" import goBack %}
{% from "../macros/common-components.njk" import goBack, submitButton %}
{% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}
{% from "govuk/components/details/macro.njk" import govukDetails %}

{% block head %}
{{ super() }}
{% endblock %}
{% block pageTitle %}
{{ title }}
{% endblock %}

{% block beforeContent %}

{{ super() }}
{{ goBack(text = backButton, cspNonce = cspNonce) }}
{{ goBack(cspNonce = cspNonce) }}
{% endblock %}

{% block content %}
Expand All @@ -27,23 +23,28 @@
{% endif %}</h1>

<div id="section1">
<h2 class="govuk-heading-m">Metadata</h2>
<form method="post">
{% if not noMatchArtefact %}
{{ submitButton(label = resubmit, id = 'resubmit-subscription') }}
{% endif %}

{{ govukSummaryList({
rows: [
{key: {text: "Artefact Id"}, value: { text: metadata.artefactId} },
{key: {text: "Language"}, value: { text: metadata.language | titleCase} },
{key: {text: "Location Id"}, value: { text: metadata.locationId} },
{key: {text: "Location Name"}, value: { text: courtName } },
{key: {text: "List Type"}, value: { text: metadata.listType | listType} },
{key: {text: "Provenance"}, value: { text: metadata.provenance} },
{key: {text: "Publication Type"}, value: { text: metadata.type | titleCase} },
{key: {text: "Sensitivity"}, value: { text: metadata.sensitivity | titleCase} },
{key: {text: "Content Date"}, value: { text: metadata.contentDate | date('Do MMMM YYYY [at] hh:mm a')} },
{key: {text: "Display From"}, value: { text: metadata.displayFrom | date('Do MMMM YYYY [at] hh:mm a')} },
{key: {text: "Display To"}, value: { text: metadata.displayTo | date('Do MMMM YYYY [at] hh:mm a')} }
]
}) }}
<h2 class="govuk-heading-m">Metadata</h2>
{{ govukSummaryList({
rows: [
{key: {text: "Artefact ID"}, value: { text: metadata.artefactId} },
{key: {text: "Location ID"}, value: { text: metadata.locationId} },
{key: {text: "Location Name"}, value: { text: locationName } },
{key: {text: "Publication Type"}, value: { text: metadata.type | titleCase} },
{key: {text: "List Type"}, value: { text: metadata.listType | listType} },
{key: {text: "Provenance"}, value: { text: metadata.provenance} },
{key: {text: "Language"}, value: { text: metadata.language | titleCase} },
{key: {text: "Sensitivity"}, value: { text: metadata.sensitivity | titleCase} },
{key: {text: "Content Date"}, value: { text: metadata.contentDate | date('Do MMMM YYYY [at] hh:mm a')} },
{key: {text: "Display From"}, value: { text: metadata.displayFrom | date('Do MMMM YYYY [at] hh:mm a')} },
{key: {text: "Display To"}, value: { text: metadata.displayTo | date('Do MMMM YYYY [at] hh:mm a')} }
]
}) }}
</form>
</div>
</div>
{% if not noMatchArtefact %}
Expand Down
2 changes: 1 addition & 1 deletion src/main/views/system-admin/blob-view-locations.njk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

{% block beforeContent %}
{{ super() }}
{{ goBack(text = backButton, cspNonce = cspNonce) }}
{{ goBack(cspNonce = cspNonce) }}
{% endblock %}

{% block content %}
Expand Down
2 changes: 1 addition & 1 deletion src/main/views/system-admin/blob-view-publications.njk
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

{% block beforeContent %}
{{ super() }}
{{ goBack(text = backButton, cspNonce = cspNonce) }}
{{ goBack(cspNonce = cspNonce) }}
{% endblock %}

{% block content %}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{% extends "../template.njk" %}
{% from "../macros/common-components.njk" import goBack, submitButton %}
{% from "govuk/components/summary-list/macro.njk" import govukSummaryList %}

{% block pageTitle %}
{{ title }}
{% endblock %}

{% block beforeContent %}
{{ super() }}
{{ goBack(cspNonce = cspNonce) }}
{% endblock %}

{% block content %}
<div class="parent-box">
<h1 class="govuk-heading-l">{{ title }}</h1>
<form method="post">
{{ govukSummaryList({
rows: [
{key: {text: "Location Name"}, value: { text: locationName } },
{key: {text: "Publication Type"}, value: { text: metadata.type | titleCase} },
{key: {text: "List Type"}, value: { text: metadata.listType | listType} },
{key: {text: "Provenance"}, value: { text: metadata.provenance} },
{key: {text: "Language"}, value: { text: metadata.language | titleCase} },
{key: {text: "Sensitivity"}, value: { text: metadata.sensitivity | titleCase} },
{key: {text: "Content Date"}, value: { text: metadata.contentDate | date('Do MMMM YYYY [at] hh:mm a')} },
{key: {text: "Display From"}, value: { text: metadata.displayFrom | date('Do MMMM YYYY [at] hh:mm a')} },
{key: {text: "Display To"}, value: { text: metadata.displayTo | date('Do MMMM YYYY [at] hh:mm a')} }
]
}) }}
<div class="govuk-button-group">
{{ submitButton(label = confirmButton, id = 'confirm-resubmit-subscription') }}
<a class="govuk-link" id='cancel-resubmit-subscription' href='blob-view-locations'>{{ cancelButton }}</a>
</div>
</form>
{{ super() }}
</div>
{% endblock %}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{% extends "../template.njk" %}
{% from "../macros/common-components.njk" import goBack, successPanel %}

{% block pageTitle %}
{{ title }}
{% endblock %}

{% block beforeContent %}
{{ super() }}
{{ goBack(cspNonce = cspNonce) }}
{% endblock %}

{% block content %}
{{ successPanel(title) }}
<p class="govuk-body govuk-!-font-weight-bold govuk-!-margin-top-6">{{ nextMessage }}</p>
<p class="govuk-body govuk-!-margin-0 govuk-!-font-weight-bold"><a class="govuk-link " href="blob-view-locations">{{ blobLocation }}</a></p>
{% endblock %}
4 changes: 4 additions & 0 deletions src/test/a11y/tests/system-admin-routes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { AuditLogService } from '../../../main/service/AuditLogService';
import fs from 'fs';
import path from 'path';
import { v4 as uuidv4 } from 'uuid';
import { SubscriptionService } from '../../../main/service/SubscriptionService';

const userId = '1';
const name = 'Test';
Expand All @@ -32,6 +33,8 @@ const systemAdminRoutes = [
{ path: '/blob-view-locations' },
{ path: '/blob-view-publications', parameter: '?locationId=123' },
{ path: '/blob-view-json', parameter: '?artefactId=abc' },
{ path: '/blob-view-subscription-resubmit-confirmation', parameter: '?artefactId=abc' },
{ path: '/blob-view-subscription-resubmit-confirmed' },
{ path: '/bulk-create-media-accounts', parameter: '?locationId=123' },
{ path: '/bulk-create-media-accounts-confirmation', parameter: '?artefactId=abc' },
{ path: '/bulk-create-media-accounts-confirmed' },
Expand Down Expand Up @@ -103,6 +106,7 @@ sinon.stub(FileHandlingService.prototype, 'readCsvToArray').returns([
]);
sinon.stub(UserManagementService.prototype, 'getFormattedData').resolves(userPageData);
sinon.stub(AuditLogService.prototype, 'getFormattedAuditData').returns(auditLogPageData);
sinon.stub(SubscriptionService.prototype, 'fulfillSubscriptions').resolves('success');

describe('Accessibility - System Admin Routes', () => {
app.request['cookies'] = {
Expand Down
2 changes: 1 addition & 1 deletion src/test/end-to-end/tests/system-admin/audit-log-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ Scenario('I as a system admin should be able to view audit log for admin delete
I.fillField('#filterDate-day', padFormatted(date.getDate()) as string);
I.fillField('#filterDate-month', padFormatted(date.getMonth() + 1));
I.fillField('#filterDate-year', date.getFullYear());
I.checkOption('#actions-20');
I.checkOption('#actions-21');
I.click('Apply filters');

const publicationLocator = locate('//tr').withText('Upload Publication').find('a').withText('View');
Expand Down
Loading
Loading