Skip to content

Commit dab0ddb

Browse files
authored
feat: legacy fap proposals page (#1226)
1 parent 6a8fe03 commit dab0ddb

17 files changed

Lines changed: 812 additions & 74 deletions

File tree

apps/backend/src/datasources/FapDataSource.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,11 @@ export interface FapDataSource {
7676
callId?: number | null;
7777
instrumentId?: number | null;
7878
}): Promise<FapProposal[]>;
79+
getLegacyFapProposals(filter: {
80+
fapId: number;
81+
callId?: number | null;
82+
instrumentId?: number | null;
83+
}): Promise<FapProposal[]>;
7984
getFapUsersByProposalPkAndCallId(
8085
proposalPk: number,
8186
callId: number

apps/backend/src/datasources/mockups/FapDataSource.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,14 @@ export class FapDataSourceMock implements FapDataSource {
239239
);
240240
}
241241

242+
getLegacyFapProposals(filter: {
243+
fapId: number;
244+
callId?: number | null;
245+
instrumentId?: number | null;
246+
}): Promise<FapProposal[]> {
247+
throw new Error('Method not implemented.');
248+
}
249+
242250
updateTimeAllocation(
243251
fapId: number,
244252
proposalPk: number,

apps/backend/src/datasources/postgres/FapDataSource.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,45 @@ export default class PostgresFapDataSource implements FapDataSource {
340340
);
341341
}
342342

343+
async getLegacyFapProposals(filter: {
344+
fapId: number;
345+
callId?: number | null;
346+
instrumentId?: number | null;
347+
}): Promise<FapProposal[]> {
348+
const fapProposals: FapProposalRecord[] = await database
349+
.select(['fp.*'])
350+
.from('fap_proposals as fp')
351+
.modify((query) => {
352+
query
353+
.join('proposals as p', {
354+
'p.proposal_pk': 'fp.proposal_pk',
355+
})
356+
.join('statuses as s', {
357+
'p.status_id': 's.status_id',
358+
})
359+
.join('call as c', {
360+
'p.call_id': 'c.call_id',
361+
})
362+
.where(function () {
363+
this.where('p.submitted', true);
364+
this.andWhere('c.call_fap_review_ended', true);
365+
});
366+
367+
if (filter.callId) {
368+
query.andWhere('fp.call_id', filter.callId);
369+
}
370+
if (filter.instrumentId) {
371+
query.andWhere('fp.instrument_id', filter.instrumentId);
372+
}
373+
})
374+
.where('fp.fap_id', filter.fapId)
375+
.distinctOn('fp.proposal_pk');
376+
377+
return fapProposals.map((fapProposal) =>
378+
createFapProposalObject(fapProposal)
379+
);
380+
}
381+
343382
async getFapUsersByProposalPkAndCallId(
344383
proposalPk: number,
345384
callId: number

apps/backend/src/queries/FapQueries.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ describe('Test FapQueries', () => {
7373
fapId: 1,
7474
callId: 1,
7575
instrumentId: 1,
76+
legacy: false,
7677
})
7778
).resolves.toStrictEqual([dummyFapProposal]);
7879
});

apps/backend/src/queries/FapQueries.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,45 @@ export default class FapQueries {
6969
fapId,
7070
callId,
7171
instrumentId,
72-
}: { fapId: number; callId: number | null; instrumentId: number | null }
72+
legacy,
73+
}: {
74+
fapId: number;
75+
callId: number | null;
76+
instrumentId: number | null;
77+
legacy: boolean;
78+
}
7379
) {
7480
if (
7581
this.userAuth.isApiToken(agent) ||
7682
this.userAuth.isUserOfficer(agent) ||
7783
(await this.userAuth.isMemberOfFap(agent, fapId))
7884
) {
79-
return this.dataSource.getFapProposals({ fapId, callId, instrumentId });
85+
const fapProposals = legacy
86+
? await this.dataSource.getLegacyFapProposals({
87+
fapId,
88+
callId,
89+
instrumentId,
90+
})
91+
: await this.dataSource.getFapProposals({
92+
fapId,
93+
callId,
94+
instrumentId,
95+
});
96+
97+
// Remove users proposals from the list if the user is a FAP Reviewer
98+
// This ensures that Reviewers cannot see reviews of there own proposals
99+
// which might contain sensitive information
100+
if (agent?.currentRole?.shortCode === Roles.FAP_REVIEWER) {
101+
const usersProposals = (
102+
await this.proposalDataSource.getUserProposals(agent.id)
103+
).map((p) => p.primaryKey);
104+
105+
return fapProposals.filter(
106+
(fp) => !usersProposals.includes(fp.proposalPk)
107+
);
108+
}
109+
110+
return fapProposals;
80111
} else {
81112
return null;
82113
}

apps/backend/src/resolvers/queries/FapQuery.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ export class FapQuery {
3737
@Arg('callId', () => Int, { nullable: true }) callId: number | null,
3838
@Arg('instrumentId', () => Int, { nullable: true })
3939
instrumentId: number | null,
40+
@Arg('legacy', () => Boolean, { nullable: true }) legacy: boolean,
4041
@Ctx() context: ResolverContext
4142
): Promise<FapProposal[] | null> {
4243
return context.queries.fap.getFapProposals(context.user, {
4344
fapId,
4445
callId,
4546
instrumentId,
47+
legacy,
4648
});
4749
}
4850

apps/e2e/cypress/e2e/FAPs.cy.ts

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1877,7 +1877,7 @@ context('Fap reviews tests', () => {
18771877
.find('[aria-label="Edit"]')
18781878
.click();
18791879

1880-
cy.get('[role="tablist"] [role="tab"]').should('have.length', 2);
1880+
cy.get('[role="tablist"] [role="tab"]').should('have.length', 3);
18811881

18821882
cy.finishedLoading();
18831883

@@ -1913,6 +1913,76 @@ context('Fap reviews tests', () => {
19131913

19141914
cy.contains(comment1).should('not.exist');
19151915
});
1916+
1917+
it('Fap Reviewer should be see legacy FAP proposals page', () => {
1918+
cy.createCall({
1919+
...updatedCall,
1920+
shortCode: 'legacy call',
1921+
esiTemplateId: createdEsiTemplateId,
1922+
proposalWorkflowId: createdWorkflowId,
1923+
faps: [createdFapId],
1924+
}).then((result) => {
1925+
createdCallId = result.createCall.id;
1926+
1927+
cy.assignInstrumentToCall({
1928+
callId: createdCallId,
1929+
instrumentFapIds: { instrumentId: newlyCreatedInstrumentId },
1930+
});
1931+
1932+
cy.createProposal({ callId: createdCallId }).then((result) => {
1933+
const createdProposal = result.createProposal;
1934+
1935+
if (createdProposal) {
1936+
secondCreatedProposalPk = createdProposal.primaryKey;
1937+
1938+
cy.updateProposal({
1939+
proposalPk: createdProposal.primaryKey,
1940+
title: proposal2.title,
1941+
abstract: proposal2.abstract,
1942+
proposerId: initialDBData.users.user1.id,
1943+
});
1944+
1945+
cy.submitProposal({ proposalPk: createdProposal.primaryKey });
1946+
1947+
cy.changeProposalsStatus({
1948+
statusId: initialDBData.proposalStatuses.finished.id,
1949+
proposalPks: [secondCreatedProposalPk],
1950+
});
1951+
1952+
cy.assignProposalsToInstruments({
1953+
instrumentIds: [newlyCreatedInstrumentId],
1954+
proposalPks: [secondCreatedProposalPk],
1955+
});
1956+
cy.assignProposalsToFaps({
1957+
fapInstruments: [
1958+
{ instrumentId: newlyCreatedInstrumentId, fapId: createdFapId },
1959+
],
1960+
proposalPks: [createdProposal.primaryKey],
1961+
});
1962+
}
1963+
1964+
cy.updateCall({
1965+
id: createdCallId,
1966+
...closedCall,
1967+
shortCode: 'legacy call',
1968+
proposalWorkflowId: createdWorkflowId,
1969+
esiTemplateId: createdEsiTemplateId,
1970+
faps: [createdFapId],
1971+
callFapReviewEnded: true,
1972+
});
1973+
1974+
cy.visit('/FapPage/' + createdFapId);
1975+
1976+
cy.contains(firstCreatedProposalId).should('exist');
1977+
cy.contains(createdProposal.proposalId).should('not.exist');
1978+
1979+
cy.contains('Legacy Proposals').click();
1980+
1981+
cy.contains(createdProposal.proposalId).should('exist');
1982+
cy.contains(firstCreatedProposalId).should('not.exist');
1983+
});
1984+
});
1985+
});
19161986
});
19171987
});
19181988

apps/e2e/cypress/e2e/eventLogs.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ context('Event log tests', () => {
134134
cy.get('[data-cy="add-participant-button"]').click();
135135
cy.get('input[type="checkbox"]').eq(0).check();
136136
cy.get('[data-cy="assign-selected-users"]').click();
137-
cy.get('.MuiTabs-flexContainer > #horizontal-tab-6').click();
137+
cy.get('.MuiTabs-flexContainer > #horizontal-tab-7').click();
138138
cy.contains('userId:2 impersonating userId:1');
139139
});
140140
});

apps/e2e/cypress/e2e/generalFaps.cy.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -729,7 +729,7 @@ context('General facility access panel tests', () => {
729729
const fileName1 = 'pdf_5_pages.pdf';
730730
const fileName2 = 'pdf_3_pages.pdf';
731731
cy.login('officer');
732-
cy.visit(`/FapPage/1?tab=5`);
732+
cy.visit(`/FapPage/1?tab=6`);
733733

734734
cy.intercept({
735735
method: 'POST',
@@ -762,7 +762,7 @@ context('General facility access panel tests', () => {
762762
cy.contains(fileName2).should('exist');
763763

764764
// Files persist after reload
765-
cy.visit(`/FapPage/1?tab=5`);
765+
cy.visit(`/FapPage/1?tab=6`);
766766

767767
cy.contains(fileName1).should('exist');
768768
cy.contains(fileName2).should('exist');
@@ -773,7 +773,7 @@ context('General facility access panel tests', () => {
773773
cy.contains(fileName2).should('not.exist');
774774

775775
// Files removed after reload
776-
cy.visit(`/FapPage/1?tab=5`);
776+
cy.visit(`/FapPage/1?tab=6`);
777777

778778
cy.contains(fileName1).should('not.exist');
779779
cy.contains(fileName2).should('not.exist');
@@ -798,7 +798,7 @@ context('General facility access panel tests', () => {
798798
const fileName1 = 'pdf_5_pages.pdf';
799799

800800
cy.login('officer');
801-
cy.visit(`/FapPage/1?tab=5`);
801+
cy.visit(`/FapPage/1?tab=6`);
802802

803803
cy.intercept({
804804
method: 'POST',
@@ -843,7 +843,7 @@ context('General facility access panel tests', () => {
843843
const fileName1 = 'pdf_5_pages.pdf';
844844

845845
cy.login('officer');
846-
cy.visit(`/FapPage/1?tab=5`);
846+
cy.visit(`/FapPage/1?tab=6`);
847847

848848
cy.intercept({
849849
method: 'POST',
@@ -885,7 +885,7 @@ context('General facility access panel tests', () => {
885885
const fileName1 = 'pdf_5_pages.pdf';
886886

887887
cy.login('officer');
888-
cy.visit(`/FapPage/1?tab=5`);
888+
cy.visit(`/FapPage/1?tab=6`);
889889

890890
cy.intercept({
891891
method: 'POST',

apps/frontend/src/components/call/CreateUpdateCall.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,6 @@ const CreateUpdateCall = ({ call, close }: CreateUpdateCallProps) => {
168168
<Wizard
169169
initialValues={initialValues}
170170
onSubmit={async (values) => {
171-
console.log({ values });
172171
if (call) {
173172
const { updateCall } = await api({
174173
toastSuccessMessage: 'Call updated successfully!',

0 commit comments

Comments
 (0)