Skip to content

feat: only show instruments and calls on tags for proposal reader role#1465

Open
ellen-wright wants to merge 11 commits intodevelopfrom
1562-fix-filters-for-read-only-role
Open

feat: only show instruments and calls on tags for proposal reader role#1465
ellen-wright wants to merge 11 commits intodevelopfrom
1562-fix-filters-for-read-only-role

Conversation

@ellen-wright
Copy link
Copy Markdown
Contributor

Description

refs: UserOfficeProject/issue-tracker#1562

This PR makes it so that only calls and instruments on tags attached to the specific proposal reader role are shown in the proposal filters.

Motivation and Context

Currently all calls and instruments are shown even if a user does not have access to them through the tags attached tot eh proposal reader role.

Changes

Adds two new graphQL queries

  • getInstrumentsByRole
  • getCallsByRole

These are called from the instrument and call hooks when logged in on the proposal reader role and returns only the calls and instruments that are assigned to any tag attached to the role.
If there are no tags on a role or you are using the root proposal reader role then all calls and instruments are returned, similarly to user officer.

Depends on

Tests included/Docs Updated?

  • I have added tests to cover my changes.
  • All relevant doc has been updated

@ellen-wright ellen-wright requested a review from a team as a code owner April 8, 2026 10:07
@ellen-wright ellen-wright requested review from Scott-James-Hurley and removed request for a team April 8, 2026 10:07
@ellen-wright ellen-wright requested review from mutambaraf and removed request for Scott-James-Hurley April 8, 2026 10:07
Copy link
Copy Markdown
Contributor

@mutambaraf mutambaraf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some comments looks good.

callsByRole(@Ctx() context: ResolverContext) {
const t = context.queries.call.getTagCallsByRoleId(context.user);

return t;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can remove the variable declaration here.

isRootRole: false,
} as Role;
}
async getCallsbyRoleId(agent: number): Promise<Call[]> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can use camelCase here : getCallsByRoleId

}
}

async getCallsbyRoleId(agent: number): Promise<Call[]> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can improve naming here to getCallsByRoleId

}
}

async getInstrumentsbyRoleId(agent: number): Promise<Instrument[]> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can improve naming to : getInstrumentsbyRoleId

const tagIds = tags.map((tag) => tag.id);
if (tagIds.length != 0) {
const instruments = await database<InstrumentRecord>(
'tag_instrument as fi'
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can name it to ti here.

Comment on lines +62 to +83
if (currentRole === UserRole.PROPOSAL_READER) {
getCallsByRole({}).then((data) => {
if (unmounted) {
return;
}
if (data.callsByRole) {
setCalls(data.callsByRole as Call[]);
setLoadingCalls(false);
}
});
} else {
getCalls({ filter: callsFilter, ...callsQueryParams }).then((data) => {
if (unmounted) {
return;
}

getCalls({ filter: callsFilter, ...callsQueryParams }).then((data) => {
if (unmounted) {
return;
}

if (data.calls) {
setCalls(data.calls as Call[]);
}
setLoadingCalls(false);
});
if (data.calls) {
setCalls(data.calls as Call[]);
}
setLoadingCalls(false);
});
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in the backend we technically do not care if a user has UserRole.PROPOSAL_READER so do not know if we need the if switch here. Lets just add the filters callsFilter, ...callsQueryParams to getCallsByRole endpoint and use it for all calls.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because the get calls and instruments by tag isn't needed for User Officers and other roles so it's not necessary to alter how the filters are populated for them

Comment on lines +62 to +73
if (currentRole === UserRole.PROPOSAL_READER) {
getCallsByRole({}).then((data) => {
if (unmounted) {
return;
}
if (data.callsByRole) {
setCalls(data.callsByRole as Call[]);
setLoadingCalls(false);
}
});
} else {
getCalls({ filter: callsFilter, ...callsQueryParams }).then((data) => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are getting the calls by roles do we still need the if statement here we may just need to pass in the filters.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This separation is because currently the proposal reader is the role that changes depending on what tags are assigned

Comment on lines 46 to 61
} else if (currentRole === UserRole.PROPOSAL_READER) {
api()
.getInstrumentsByRole()
.then((data) => {
if (unmounted) {
return;
}

if (data.instrumentByRole) {
setInstruments(data.instrumentByRole);
}
setLoadingInstruments(false);
});
} else {
api()
.getMyInstrumentsMinimal()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have added a comment above.

Comment on lines +190 to +191
const tags = await this.getTagsByRoleId(agent);
const tagIds = tags.map((tag) => tag.id);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tags variable can be handled this way, If getTagsByRoleId(agent) returns null or undefined, the subsequent .map() call will throw a runtime error. Consider defaulting to an empty array to ensure safety: const tags = (await this.getTagsByRoleId(agent)) ?? [];."

Copy link
Copy Markdown
Contributor

@mutambaraf mutambaraf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

Copy link
Copy Markdown
Contributor

@jekabs-karklins jekabs-karklins left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question: will the proposal reader role will be able to get all calls by calling the previous call getCalls, say buy crafting the GraphQL request? If yes, I'm therefore thinking if it isn't better to simply modify the existing getCalls and getCallsMinimal and filter out calls that proposal reader is not part of in the backend query. Or was it what @mutambaraf already asked?

@ellen-wright
Copy link
Copy Markdown
Contributor Author

question: will the proposal reader role will be able to get all calls by calling the previous call getCalls, say buy crafting the GraphQL request? If yes, I'm therefore thinking if it isn't better to simply modify the existing getCalls and getCallsMinimal and filter out calls that proposal reader is not part of in the backend query. Or was it what @mutambaraf already asked?

Yeah I agree, I have removed the new queries and added them to the original call and instrument queries

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants