Skip to content

Commit

Permalink
Merge pull request #4700 from 3drepo/ISSUE_4689
Browse files Browse the repository at this point in the history
ISSUE #4689 - add revision param to fetchTicketGroup
  • Loading branch information
sanmont3drepo authored Jan 22, 2024
2 parents 3e0ccff + a0e9c2f commit c2537c2
Show file tree
Hide file tree
Showing 8 changed files with 67 additions and 42 deletions.
7 changes: 6 additions & 1 deletion frontend/src/v5/services/api/tickets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,13 @@ export const fetchTicketGroup = async (
ticketId: string,
groupId: string,
isFed: boolean,
revision?: string,
) => {
const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/${modelType(isFed)}/${modelId}/tickets/${ticketId}/groups/${groupId}`);
let url = `teamspaces/${teamspace}/projects/${projectId}/${modelType(isFed)}/${modelId}/tickets/${ticketId}/groups/${groupId}`;
if (revision) {
url += `?revId=${revision}`;
}
const { data } = await api.get(url);
return data;
};

Expand Down
20 changes: 10 additions & 10 deletions frontend/src/v5/services/realtime/ticket.events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ import { TicketsActionsDispatchers } from '../actionsDispatchers';
import { fetchTicketGroup } from '../api/tickets';

// Container ticket
export const enableRealtimeContainerUpdateTicket = (teamspace: string, project: string, containerId: string) => (
export const enableRealtimeContainerUpdateTicket = (teamspace: string, project: string, containerId: string, revision?: string) => (
subscribeToRoomEvent(
{ teamspace, project, model: containerId },
'containerUpdateTicket',
(ticket: Partial<EditableTicket>) => {
fillOverridesIfEmpty(ticket);
TicketsActionsDispatchers.upsertTicketAndFetchGroups(teamspace, project, containerId, ticket);
TicketsActionsDispatchers.upsertTicketAndFetchGroups(teamspace, project, containerId, ticket, revision);
},
)
);

export const enableRealtimeContainerNewTicket = (teamspace: string, project: string, containerId: string) => (
export const enableRealtimeContainerNewTicket = (teamspace: string, project: string, containerId: string, revision?: string) => (
subscribeToRoomEvent(
{ teamspace, project, model: containerId },
'containerNewTicket',
(ticket: ITicket) => TicketsActionsDispatchers.upsertTicketAndFetchGroups(teamspace, project, containerId, ticket),
(ticket: ITicket) => TicketsActionsDispatchers.upsertTicketAndFetchGroups(teamspace, project, containerId, ticket, revision),
)
);

Expand All @@ -64,32 +64,32 @@ export const enableRealtimeContainerUpdateTicketGroup = (teamspace: string, proj
);

// Federation ticket
export const enableRealtimeFederationUpdateTicket = (teamspace: string, project: string, federationId: string) => (
export const enableRealtimeFederationUpdateTicket = (teamspace: string, project: string, federationId: string, revision?: string) => (
subscribeToRoomEvent(
{ teamspace, project, model: federationId },
'federationUpdateTicket',
(ticket: Partial<EditableTicket>) => {
fillOverridesIfEmpty(ticket);
TicketsActionsDispatchers.upsertTicketAndFetchGroups(teamspace, project, federationId, ticket);
TicketsActionsDispatchers.upsertTicketAndFetchGroups(teamspace, project, federationId, ticket, revision);
},
)
);

export const enableRealtimeFederationNewTicket = (teamspace: string, project: string, federationId: string) => (
export const enableRealtimeFederationNewTicket = (teamspace: string, project: string, federationId: string, revision?: string) => (
subscribeToRoomEvent(
{ teamspace, project, model: federationId },
'federationNewTicket',
(ticket: ITicket) => TicketsActionsDispatchers.upsertTicketAndFetchGroups(teamspace, project, federationId, ticket),
(ticket: ITicket) => TicketsActionsDispatchers.upsertTicketAndFetchGroups(teamspace, project, federationId, ticket, revision),
)
);

export const enableRealtimeFederationUpdateTicketGroup = (teamspace: string, project: string, federationId: string, revision: string) => (
export const enableRealtimeFederationUpdateTicketGroup = (teamspace: string, project: string, federationId: string) => (
subscribeToRoomEvent(
{ teamspace, project, model: federationId },
'federationUpdateTicketGroup',
async (group: Group) => {
if (group.rules) {
const { data } = await getMeshIDsByQuery(teamspace, federationId, group.rules, revision);
const { data } = await getMeshIDsByQuery(teamspace, federationId, group.rules);
// eslint-disable-next-line no-param-reassign
group.objects = meshObjectsToV5GroupNode(data);
// eslint-disable-next-line no-underscore-dangle
Expand Down
30 changes: 23 additions & 7 deletions frontend/src/v5/store/tickets/tickets.redux.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const getTicketByModelId = (state, modelId, ticketId) => (

export const { Types: TicketsTypes, Creators: TicketsActions } = createActions({
fetchTickets: ['teamspace', 'projectId', 'modelId', 'isFederation'],
fetchTicket: ['teamspace', 'projectId', 'modelId', 'ticketId', 'isFederation'],
fetchTicket: ['teamspace', 'projectId', 'modelId', 'ticketId', 'isFederation', 'revision'],
fetchTicketsSuccess: ['modelId', 'tickets'],
fetchTemplates: ['teamspace', 'projectId', 'modelId', 'isFederation', 'getDetails'],
fetchTemplate: ['teamspace', 'projectId', 'modelId', 'templateId', 'isFederation'],
Expand All @@ -40,11 +40,12 @@ export const { Types: TicketsTypes, Creators: TicketsActions } = createActions({
upsertTicketSuccess: ['modelId', 'ticket'],
fetchRiskCategories: ['teamspace'],
fetchRiskCategoriesSuccess: ['riskCategories'],
fetchTicketGroups: ['teamspace', 'projectId', 'modelId', 'ticketId'],
fetchTicketGroups: ['teamspace', 'projectId', 'modelId', 'ticketId', 'revision'],
fetchTicketGroupsSuccess: ['groups'],
upsertTicketAndFetchGroups: ['teamspace', 'projectId', 'modelId', 'ticket'],
upsertTicketAndFetchGroups: ['teamspace', 'projectId', 'modelId', 'ticket', 'revision'],
updateTicketGroup: ['teamspace', 'projectId', 'modelId', 'ticketId', 'group', 'isFederation'],
updateTicketGroupSuccess: ['group'],
clearGroups: [],
}, { prefix: 'TICKETS/' }) as { Types: Constants<ITicketsActionCreators>; Creators: ITicketsActionCreators };

export const INITIAL_STATE: ITicketsState = {
Expand Down Expand Up @@ -103,6 +104,10 @@ export const fetchRiskCategoriesSuccess = (
state.riskCategories = riskCategories;
};

export const clearGroups = (state: ITicketsState) => {
state.groupsByGroupId = {};
};

export const ticketsReducer = createReducer(INITIAL_STATE, produceAll({
[TicketsTypes.FETCH_TICKETS_SUCCESS]: fetchTicketsSuccess,
[TicketsTypes.FETCH_TEMPLATES_SUCCESS]: fetchTemplatesSuccess,
Expand All @@ -111,6 +116,7 @@ export const ticketsReducer = createReducer(INITIAL_STATE, produceAll({
[TicketsTypes.FETCH_RISK_CATEGORIES_SUCCESS]: fetchRiskCategoriesSuccess,
[TicketsTypes.FETCH_TICKET_GROUPS_SUCCESS]: fetchTicketGroupsSuccess,
[TicketsTypes.UPDATE_TICKET_GROUP_SUCCESS]: updateTicketGroupSuccess,
[TicketsTypes.CLEAR_GROUPS]: clearGroups,
}));

export interface ITicketsState {
Expand All @@ -121,22 +127,23 @@ export interface ITicketsState {
}

export type FetchTicketsAction = Action<'FETCH_TICKETS'> & TeamspaceProjectAndModel & { isFederation: boolean };
export type FetchTicketAction = Action<'FETCH_TICKET'> & TeamspaceProjectAndModel & { ticketId: string, isFederation: boolean };
export type FetchTicketAction = Action<'FETCH_TICKET'> & TeamspaceProjectAndModel & { ticketId: string, isFederation: boolean, revision?: string };
export type UpdateTicketAction = Action<'UPDATE_TICKET'> & TeamspaceProjectAndModel & { ticketId: string, ticket: Partial<ITicket>, isFederation: boolean };
export type CreateTicketAction = Action<'CREATE_TICKET'> & TeamspaceProjectAndModel & { ticket: NewTicket, isFederation: boolean, onSuccess: (ticketId) => void };
export type FetchTicketsSuccessAction = Action<'FETCH_TICKETS_SUCCESS'> & ModelId & { tickets: ITicket[] };
export type UpsertTicketSuccessAction = Action<'UPSERT_TICKET_SUCCESS'> & ModelId & { ticket: Partial<ITicket> };
export type UpsertTicketAndFetchGroupsAction = Action<'UPSERT_TICKET_AND_FETCH_GROUPS'> & TeamspaceProjectAndModel & { ticket: Partial<ITicket> };
export type UpsertTicketAndFetchGroupsAction = Action<'UPSERT_TICKET_AND_FETCH_GROUPS'> & TeamspaceProjectAndModel & { ticket: Partial<ITicket>, revision?: string };
export type ReplaceTemplateSuccessAction = Action<'REPLACE_TEMPLATE_SUCCESS'> & ModelId & { template: ITemplate };
export type FetchTemplatesAction = Action<'FETCH_TEMPLATES'> & TeamspaceProjectAndModel & { isFederation: boolean, getDetails?: boolean };
export type FetchTemplateAction = Action<'FETCH_TEMPLATES'> & TeamspaceProjectAndModel & { templateId: string, isFederation: boolean };
export type FetchTemplatesSuccessAction = Action<'FETCH_TEMPLATES_SUCCESS'> & ModelId & { templates: ITemplate[] };
export type FetchRiskCategoriesAction = Action<'FETCH_RISK_CATEGORIES'> & TeamspaceId;
export type FetchRiskCategoriesSuccessAction = Action<'FETCH_RISK_CATEGORIES_SUCCESS'> & { riskCategories: string[] };
export type FetchTicketGroupsAction = Action<'FETCH_TICKET_GROUPS'> & TeamspaceProjectAndModel & { ticketId:string, groupId: string };
export type FetchTicketGroupsAction = Action<'FETCH_TICKET_GROUPS'> & TeamspaceProjectAndModel & { ticketId: string, groupId: string, revision?: string };
export type FetchTicketGroupsSuccessAction = Action<'FETCH_TICKET_GROUPS_SUCCESS'> & { groups: Group[] };
export type UpdateTicketGroupAction = Action<'UPDATE_TICKET_GROUP'> & TeamspaceProjectAndModel & { ticketId: string, group: Group, isFederation: boolean };
export type UpdateTicketGroupSuccessAction = Action<'UPDATE_TICKET_GROUP_SUCCESS'> & { group: Group };
export type ClearGroupsAction = Action<'CLEAR_GROUPS'>;

export interface ITicketsActionCreators {
fetchTickets: (
Expand All @@ -151,6 +158,7 @@ export interface ITicketsActionCreators {
modelId: string,
ticketId: string,
isFederation: boolean,
revision?: string,
) => FetchTicketAction;
updateTicket: (
teamspace: string,
Expand Down Expand Up @@ -188,7 +196,13 @@ export interface ITicketsActionCreators {
isFederation: boolean,
) => FetchTemplateAction;
upsertTicketSuccess: (modelId: string, ticket: Partial<ITicket>) => UpsertTicketSuccessAction;
upsertTicketAndFetchGroups: (teamspace: string, projectId: string, modelId: string, ticket: Partial<ITicket>) => UpsertTicketAndFetchGroupsAction;
upsertTicketAndFetchGroups: (
teamspace: string,
projectId: string,
modelId: string,
ticket: Partial<ITicket>,
revision?: string,
) => UpsertTicketAndFetchGroupsAction;
replaceTemplateSuccess: (modelId: string, ticket: ITemplate) => ReplaceTemplateSuccessAction;
fetchRiskCategories: (teamspace: string) => FetchRiskCategoriesAction;
fetchRiskCategoriesSuccess: (riskCategories: string[]) => FetchRiskCategoriesSuccessAction;
Expand All @@ -197,6 +211,7 @@ export interface ITicketsActionCreators {
projectId: string,
modelId: string,
ticketId: string,
revision?: string,
) => FetchTicketGroupsAction;
fetchTicketGroupsSuccess: (
groups: Group[],
Expand All @@ -212,4 +227,5 @@ export interface ITicketsActionCreators {
updateTicketGroupSuccess: (
group: Group,
) => UpdateTicketGroupSuccessAction;
clearGroups: () => ClearGroupsAction;
}
14 changes: 7 additions & 7 deletions frontend/src/v5/store/tickets/tickets.sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ export function* fetchTickets({ teamspace, projectId, modelId, isFederation }: F
}
}

export function* fetchTicket({ teamspace, projectId, modelId, ticketId, isFederation }: FetchTicketAction) {
export function* fetchTicket({ teamspace, projectId, modelId, ticketId, isFederation, revision }: FetchTicketAction) {
try {
const fetchModelTicket = isFederation
? API.Tickets.fetchFederationTicket
: API.Tickets.fetchContainerTicket;
const ticket = yield fetchModelTicket(teamspace, projectId, modelId, ticketId);
yield put(TicketsActions.upsertTicketSuccess(modelId, ticket));
yield put(TicketsActions.fetchTicketGroups(teamspace, projectId, modelId, ticketId));
yield put(TicketsActions.fetchTicketGroups(teamspace, projectId, modelId, ticketId, revision));
} catch (error) {
yield put(DialogsActions.open('alert', {
currentActions: formatMessage(
Expand Down Expand Up @@ -202,7 +202,7 @@ const appendPropertiesGroupsToArray = (groupsIds: any[], properties: object) =>
});
};

const getTicketsGroupsIds = (ticket:ITicket) => {
const getTicketsGroupsIds = (ticket: ITicket) => {
const groupsIds = [];

appendPropertiesGroupsToArray(groupsIds, ticket.properties);
Expand All @@ -215,7 +215,7 @@ const getTicketsGroupsIds = (ticket:ITicket) => {
return groupsIds;
};

export function* fetchTicketGroups({ teamspace, projectId, modelId, ticketId }: FetchTicketGroupsAction) {
export function* fetchTicketGroups({ teamspace, projectId, modelId, ticketId, revision }: FetchTicketGroupsAction) {
try {
const ticket: ITicket = yield select(selectTicketByIdRaw, modelId, ticketId);
const fetchedGroups = yield select(selectTicketsGroups);
Expand All @@ -225,7 +225,7 @@ export function* fetchTicketGroups({ teamspace, projectId, modelId, ticketId }:
const groupsIds = getTicketsGroupsIds(ticket).filter((id) => isString(id) && !fetchedGroups[id]);

const groups = yield all(
groupsIds.map((groupId) => API.Tickets.fetchTicketGroup(teamspace, projectId, modelId, ticketId, groupId, isFed)),
groupsIds.map((groupId) => API.Tickets.fetchTicketGroup(teamspace, projectId, modelId, ticketId, groupId, isFed, revision)),
);

yield put(TicketsActions.fetchTicketGroupsSuccess(groups));
Expand All @@ -239,9 +239,9 @@ export function* fetchTicketGroups({ teamspace, projectId, modelId, ticketId }:
}
}

export function* upsertTicketAndFetchGroups({ teamspace, projectId, modelId, ticket }: UpsertTicketAndFetchGroupsAction) {
export function* upsertTicketAndFetchGroups({ teamspace, projectId, modelId, ticket, revision }: UpsertTicketAndFetchGroupsAction) {
yield put(TicketsActions.upsertTicketSuccess(modelId, ticket));
yield put(TicketsActions.fetchTicketGroups(teamspace, projectId, modelId, ticket._id));
yield put(TicketsActions.fetchTicketGroups(teamspace, projectId, modelId, ticket._id, revision));
}

export default function* ticketsSaga() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ enum IndexChange {
}

export const TicketDetailsCard = () => {
const { teamspace, project, containerOrFederation } = useParams();
const { teamspace, project, containerOrFederation, revision } = useParams();
const [, setTicketId] = useSearchParam('ticketId');
const { view, setDetailViewAndProps, viewProps } = useContext(TicketContext);
const treeNodesList = TreeHooksSelectors.selectTreeNodesList();
Expand Down Expand Up @@ -128,8 +128,7 @@ export const TicketDetailsCard = () => {
isFederation,
);
}
TicketsActionsDispatchers.fetchTicket(teamspace, project, containerOrFederation, ticket._id, isFederation);
TicketsActionsDispatchers.fetchTicketGroups(teamspace, project, containerOrFederation, ticket._id);
TicketsActionsDispatchers.fetchTicket(teamspace, project, containerOrFederation, ticket._id, isFederation, revision);
setTicketId(ticket._id);
}, [ticket?._id]);

Expand Down
16 changes: 10 additions & 6 deletions frontend/src/v5/ui/routes/viewer/tickets/tickets.component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,17 +54,21 @@ export const Tickets = () => {
useEffect(() => {
if (isFederation) {
return combineSubscriptions(
enableRealtimeFederationNewTicket(teamspace, project, containerOrFederation),
enableRealtimeFederationUpdateTicket(teamspace, project, containerOrFederation),
enableRealtimeFederationUpdateTicketGroup(teamspace, project, containerOrFederation, revision),
enableRealtimeFederationNewTicket(teamspace, project, containerOrFederation, revision),
enableRealtimeFederationUpdateTicket(teamspace, project, containerOrFederation, revision),
enableRealtimeFederationUpdateTicketGroup(teamspace, project, containerOrFederation),
);
}
return combineSubscriptions(
enableRealtimeContainerNewTicket(teamspace, project, containerOrFederation),
enableRealtimeContainerUpdateTicket(teamspace, project, containerOrFederation),
enableRealtimeContainerNewTicket(teamspace, project, containerOrFederation, revision),
enableRealtimeContainerUpdateTicket(teamspace, project, containerOrFederation, revision),
enableRealtimeContainerUpdateTicketGroup(teamspace, project, containerOrFederation, revision),
);
}, [containerOrFederation]);
}, [containerOrFederation, revision]);

useEffect(() => {
TicketsActionsDispatchers.clearGroups();
}, [revision]);

useEffect(() => () => {
if (view === TicketsCardViews.New) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ type TicketsListProps = {
};

export const TicketsList = ({ tickets }: TicketsListProps) => {
const { teamspace, project, containerOrFederation } = useParams<ViewerParams>();
const { teamspace, project, containerOrFederation, revision } = useParams<ViewerParams>();
const templates = TicketsHooksSelectors.selectTemplates(containerOrFederation);
const selectedTicket = TicketsCardHooksSelectors.selectSelectedTicket();
const selectedTemplates = TicketsCardHooksSelectors.selectFilteringTemplates();
Expand All @@ -66,7 +66,7 @@ export const TicketsList = ({ tickets }: TicketsListProps) => {
TicketsCardActionsDispatchers.openTicket(ticket._id);
}

TicketsActionsDispatchers.fetchTicketGroups(teamspace, project, containerOrFederation, ticket._id);
TicketsActionsDispatchers.fetchTicketGroups(teamspace, project, containerOrFederation, ticket._id, revision);
};

useEffect(() => {
Expand Down
13 changes: 7 additions & 6 deletions frontend/test/tickets/tickets.sagas.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ describe('Tickets: sagas', () => {
const teamspace = 'teamspace';
const projectId = 'project';
const modelId = 'modelId';
const revision = 'revision';

const populateTicketsStore = () => dispatch(TicketsActions.fetchTicketsSuccess(modelId, tickets));
const populateGroupsStore = () => dispatch(TicketsActions.fetchTicketGroupsSuccess(groups));
Expand Down Expand Up @@ -91,10 +92,10 @@ describe('Tickets: sagas', () => {
.reply(200, ticket);

await waitForActions(() => {
dispatch(TicketsActions.fetchTicket(teamspace, projectId, modelId, ticket._id, false));
dispatch(TicketsActions.fetchTicket(teamspace, projectId, modelId, ticket._id, false, revision));
}, [
TicketsActions.upsertTicketSuccess(modelId, ticket),
TicketsActions.fetchTicketGroups(teamspace, projectId, modelId, ticket._id),
TicketsActions.fetchTicketGroups(teamspace, projectId, modelId, ticket._id, revision),
]);
});
it('should call fetchContainerTicket endpoint with a 404', async () => {
Expand Down Expand Up @@ -202,10 +203,10 @@ describe('Tickets: sagas', () => {
.reply(200, ticket);

await waitForActions(() => {
dispatch(TicketsActions.fetchTicket(teamspace, projectId, modelId, ticket._id, true));
dispatch(TicketsActions.fetchTicket(teamspace, projectId, modelId, ticket._id, true, revision));
}, [
TicketsActions.upsertTicketSuccess(modelId, ticket),
TicketsActions.fetchTicketGroups(teamspace, projectId, modelId, ticket._id),
TicketsActions.fetchTicketGroups(teamspace, projectId, modelId, ticket._id, revision),
]);
});
it('should call fetchFederationTicket endpoint with a 404', async () => {
Expand Down Expand Up @@ -288,10 +289,10 @@ describe('Tickets: sagas', () => {
const updateProp = { _id: ticket._id, title: 'updatedTicketName' };

await waitForActions(() => {
dispatch(TicketsActions.upsertTicketAndFetchGroups(teamspace, projectId, modelId, updateProp));
dispatch(TicketsActions.upsertTicketAndFetchGroups(teamspace, projectId, modelId, updateProp, revision));
}, [
TicketsActions.upsertTicketSuccess(modelId, updateProp),
TicketsActions.fetchTicketGroups(teamspace, projectId, modelId, ticket._id),
TicketsActions.fetchTicketGroups(teamspace, projectId, modelId, ticket._id, revision),
]);
});
describe('containers', () => {
Expand Down

0 comments on commit c2537c2

Please sign in to comment.