Skip to content
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
5 changes: 5 additions & 0 deletions apps/backend/src/datasources/FapDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,11 @@ export interface FapDataSource {
callId?: number | null;
instrumentId?: number | null;
}): Promise<FapProposal[]>;
getLegacyFapProposals(filter: {
fapId: number;
callId?: number | null;
instrumentId?: number | null;
}): Promise<FapProposal[]>;
getFapUsersByProposalPkAndCallId(
proposalPk: number,
callId: number
Expand Down
8 changes: 8 additions & 0 deletions apps/backend/src/datasources/mockups/FapDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,14 @@ export class FapDataSourceMock implements FapDataSource {
);
}

getLegacyFapProposals(filter: {
fapId: number;
callId?: number | null;
instrumentId?: number | null;
}): Promise<FapProposal[]> {
throw new Error('Method not implemented.');
}

updateTimeAllocation(
fapId: number,
proposalPk: number,
Expand Down
39 changes: 39 additions & 0 deletions apps/backend/src/datasources/postgres/FapDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,45 @@ export default class PostgresFapDataSource implements FapDataSource {
);
}

async getLegacyFapProposals(filter: {
fapId: number;
callId?: number | null;
instrumentId?: number | null;
}): Promise<FapProposal[]> {
const fapProposals: FapProposalRecord[] = await database
.select(['fp.*'])
.from('fap_proposals as fp')
.modify((query) => {
query
.join('proposals as p', {
'p.proposal_pk': 'fp.proposal_pk',
})
.join('statuses as s', {
'p.status_id': 's.status_id',
})
.join('call as c', {
'p.call_id': 'c.call_id',
})
.where(function () {
this.where('p.submitted', true);
this.andWhere('c.call_fap_review_ended', true);
});

if (filter.callId) {
query.andWhere('fp.call_id', filter.callId);
}
if (filter.instrumentId) {
query.andWhere('fp.instrument_id', filter.instrumentId);
}
})
.where('fp.fap_id', filter.fapId)
.distinctOn('fp.proposal_pk');

return fapProposals.map((fapProposal) =>
createFapProposalObject(fapProposal)
);
}

async getFapUsersByProposalPkAndCallId(
proposalPk: number,
callId: number
Expand Down
1 change: 1 addition & 0 deletions apps/backend/src/queries/FapQueries.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ describe('Test FapQueries', () => {
fapId: 1,
callId: 1,
instrumentId: 1,
legacy: false,
})
).resolves.toStrictEqual([dummyFapProposal]);
});
Expand Down
35 changes: 33 additions & 2 deletions apps/backend/src/queries/FapQueries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,45 @@ export default class FapQueries {
fapId,
callId,
instrumentId,
}: { fapId: number; callId: number | null; instrumentId: number | null }
legacy,
}: {
fapId: number;
callId: number | null;
instrumentId: number | null;
legacy: boolean;
}
) {
if (
this.userAuth.isApiToken(agent) ||
this.userAuth.isUserOfficer(agent) ||
(await this.userAuth.isMemberOfFap(agent, fapId))
) {
return this.dataSource.getFapProposals({ fapId, callId, instrumentId });
const fapProposals = legacy
? await this.dataSource.getLegacyFapProposals({
fapId,
callId,
instrumentId,
})
: await this.dataSource.getFapProposals({
fapId,
callId,
instrumentId,
});

// Remove users proposals from the list if the user is a FAP Reviewer
// This ensures that Reviewers cannot see reviews of there own proposals
// which might contain sensitive information
if (agent?.currentRole?.shortCode === Roles.FAP_REVIEWER) {
const usersProposals = (
await this.proposalDataSource.getUserProposals(agent.id)
).map((p) => p.primaryKey);

return fapProposals.filter(
(fp) => !usersProposals.includes(fp.proposalPk)
);
}

return fapProposals;
} else {
return null;
}
Expand Down
2 changes: 2 additions & 0 deletions apps/backend/src/resolvers/queries/FapQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ export class FapQuery {
@Arg('callId', () => Int, { nullable: true }) callId: number | null,
@Arg('instrumentId', () => Int, { nullable: true })
instrumentId: number | null,
@Arg('legacy', () => Boolean, { nullable: true }) legacy: boolean,
@Ctx() context: ResolverContext
): Promise<FapProposal[] | null> {
return context.queries.fap.getFapProposals(context.user, {
fapId,
callId,
instrumentId,
legacy,
});
}

Expand Down
72 changes: 71 additions & 1 deletion apps/e2e/cypress/e2e/FAPs.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1877,7 +1877,7 @@ context('Fap reviews tests', () => {
.find('[aria-label="Edit"]')
.click();

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

cy.finishedLoading();

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

cy.contains(comment1).should('not.exist');
});

it('Fap Reviewer should be see legacy FAP proposals page', () => {
cy.createCall({
...updatedCall,
shortCode: 'legacy call',
esiTemplateId: createdEsiTemplateId,
proposalWorkflowId: createdWorkflowId,
faps: [createdFapId],
}).then((result) => {
createdCallId = result.createCall.id;

cy.assignInstrumentToCall({
callId: createdCallId,
instrumentFapIds: { instrumentId: newlyCreatedInstrumentId },
});

cy.createProposal({ callId: createdCallId }).then((result) => {
const createdProposal = result.createProposal;

if (createdProposal) {
secondCreatedProposalPk = createdProposal.primaryKey;

cy.updateProposal({
proposalPk: createdProposal.primaryKey,
title: proposal2.title,
abstract: proposal2.abstract,
proposerId: initialDBData.users.user1.id,
});

cy.submitProposal({ proposalPk: createdProposal.primaryKey });

cy.changeProposalsStatus({
statusId: initialDBData.proposalStatuses.finished.id,
proposalPks: [secondCreatedProposalPk],
});

cy.assignProposalsToInstruments({
instrumentIds: [newlyCreatedInstrumentId],
proposalPks: [secondCreatedProposalPk],
});
cy.assignProposalsToFaps({
fapInstruments: [
{ instrumentId: newlyCreatedInstrumentId, fapId: createdFapId },
],
proposalPks: [createdProposal.primaryKey],
});
}

cy.updateCall({
id: createdCallId,
...closedCall,
shortCode: 'legacy call',
proposalWorkflowId: createdWorkflowId,
esiTemplateId: createdEsiTemplateId,
faps: [createdFapId],
callFapReviewEnded: true,
});

cy.visit('/FapPage/' + createdFapId);

cy.contains(firstCreatedProposalId).should('exist');
cy.contains(createdProposal.proposalId).should('not.exist');

cy.contains('Legacy Proposals').click();

cy.contains(createdProposal.proposalId).should('exist');
cy.contains(firstCreatedProposalId).should('not.exist');
});
});
});
});
});

Expand Down
2 changes: 1 addition & 1 deletion apps/e2e/cypress/e2e/eventLogs.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ context('Event log tests', () => {
cy.get('[data-cy="add-participant-button"]').click();
cy.get('input[type="checkbox"]').eq(0).check();
cy.get('[data-cy="assign-selected-users"]').click();
cy.get('.MuiTabs-flexContainer > #horizontal-tab-6').click();
cy.get('.MuiTabs-flexContainer > #horizontal-tab-7').click();
cy.contains('userId:2 impersonating userId:1');
});
});
Expand Down
12 changes: 6 additions & 6 deletions apps/e2e/cypress/e2e/generalFaps.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ context('General facility access panel tests', () => {
const fileName1 = 'pdf_5_pages.pdf';
const fileName2 = 'pdf_3_pages.pdf';
cy.login('officer');
cy.visit(`/FapPage/1?tab=5`);
cy.visit(`/FapPage/1?tab=6`);

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

// Files persist after reload
cy.visit(`/FapPage/1?tab=5`);
cy.visit(`/FapPage/1?tab=6`);

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

// Files removed after reload
cy.visit(`/FapPage/1?tab=5`);
cy.visit(`/FapPage/1?tab=6`);

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

cy.login('officer');
cy.visit(`/FapPage/1?tab=5`);
cy.visit(`/FapPage/1?tab=6`);

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

cy.login('officer');
cy.visit(`/FapPage/1?tab=5`);
cy.visit(`/FapPage/1?tab=6`);

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

cy.login('officer');
cy.visit(`/FapPage/1?tab=5`);
cy.visit(`/FapPage/1?tab=6`);

cy.intercept({
method: 'POST',
Expand Down
1 change: 0 additions & 1 deletion apps/frontend/src/components/call/CreateUpdateCall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ const CreateUpdateCall = ({ call, close }: CreateUpdateCallProps) => {
<Wizard
initialValues={initialValues}
onSubmit={async (values) => {
console.log({ values });
if (call) {
const { updateCall } = await api({
toastSuccessMessage: 'Call updated successfully!',
Expand Down
19 changes: 19 additions & 0 deletions apps/frontend/src/components/fap/FapPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import FapGeneralInfo from './General/FapGeneralInfo';
import FapMeetingComponentsView from './MeetingComponents/FapMeetingComponentsView';
import FapMembers from './Members/FapMembers';
import FapProposalsAndAssignmentsView from './Proposals/FapProposalsAndAssignmentsView';
import LegacyFapProposals from './Proposals/LegacyFapProposals';

const FapPage = () => {
const { id } = useParams();
Expand Down Expand Up @@ -76,6 +77,15 @@ const FapPage = () => {
name: 'Documents',
element: <FapFilesView data={fap} />,
},
{
name: 'Legacy Proposals',
element: (
<LegacyFapProposals
data={fap}
onFapUpdate={(newFap: Fap): void => setFap(newFap)}
/>
),
},
];

if (isFapChairOrSecretary || isUserOfficer) {
Expand Down Expand Up @@ -120,6 +130,15 @@ const FapPage = () => {
name: 'Meeting Components',
element: <FapMeetingComponentsView fapId={fap.id} code={fap.code} />,
},
{
name: 'Legacy Proposals',
element: (
<LegacyFapProposals
data={fap}
onFapUpdate={(newFap: Fap): void => setFap(newFap)}
/>
),
},
];
}

Expand Down
Loading