From d4fecd12ea3a249c6fe2c66bd3c1263a0ca27643 Mon Sep 17 00:00:00 2001 From: sanmont3drepo Date: Thu, 6 Feb 2025 12:05:25 +0000 Subject: [PATCH 01/19] ISSUE #5379 - Refactored a bit how coordinates are converted into pins, added pin icon to be rendered --- frontend/src/v4/services/viewer/viewer.tsx | 4 +- .../tickets/card/ticketsCard.selectors.ts | 10 +-- .../src/v5/store/tickets/tickets.selectors.ts | 2 +- .../src/v5/store/tickets/tickets.types.ts | 13 +++- .../coordsProperty.component.tsx | 12 ++- .../coordsProperty/coordsProperty.helpers.ts | 74 ++++++++++++------- 6 files changed, 71 insertions(+), 44 deletions(-) diff --git a/frontend/src/v4/services/viewer/viewer.tsx b/frontend/src/v4/services/viewer/viewer.tsx index a2281b2b7d7..2da6de0acfd 100644 --- a/frontend/src/v4/services/viewer/viewer.tsx +++ b/frontend/src/v4/services/viewer/viewer.tsx @@ -39,9 +39,11 @@ interface IViewerConstructor { name?: string; } +export type PinType = 'issue' | 'risk' | 'bookmark' | 'ticket' | null; + export interface IPin { id: string; - type?: 'issue' | 'risk' | 'bookmark' | 'ticket' | null; + type?: PinType position: number[]; norm?: number[]; colour: number[]; diff --git a/frontend/src/v5/store/tickets/card/ticketsCard.selectors.ts b/frontend/src/v5/store/tickets/card/ticketsCard.selectors.ts index 715baaa4df7..7b86505eddd 100644 --- a/frontend/src/v5/store/tickets/card/ticketsCard.selectors.ts +++ b/frontend/src/v5/store/tickets/card/ticketsCard.selectors.ts @@ -20,7 +20,7 @@ import { SequencingProperties, TicketsCardViews } from '@/v5/ui/routes/viewer/ti import { createSelector } from 'reselect'; import { selectTemplateById, selectTemplates, selectTicketById, selectTickets } from '../tickets.selectors'; import { ITicketsCardState } from './ticketsCard.redux'; -import { DEFAULT_PIN, getPinColorHex, formatPin, getTicketPins } from '@/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers'; +import { DEFAULT_PIN, getTicketPins, toPin } from '@/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers'; import { IPin } from '@/v4/services/viewer/viewer'; import { selectSelectedDate } from '@/v4/modules/sequences'; import { ticketIsCompleted } from '@controls/chip/statusChip/statusChip.helpers'; @@ -176,9 +176,7 @@ export const selectTicketPins = createSelector( (accum, ticket) => { const pin = ticket.properties?.Pin; if (!pin) return accum; - const template = templates.find(({ _id }) => _id === ticket.type); - const color = getPinColorHex(DEFAULT_PIN, template, ticket); - + const { sequencing } = ticket.modules; if (sequencing && selectedSequenceDate) { @@ -189,8 +187,10 @@ export const selectTicketPins = createSelector( endDate && new Date(endDate) < new Date(selectedSequenceDate) ) return accum; } + + const template = templates.find(({ _id }) => _id === ticket.type); const isSelected = selectedTicketPinId === ticket._id; - return [...accum, formatPin(ticket._id, pin, isSelected, color)]; + return [...accum, toPin(DEFAULT_PIN, template, ticket, isSelected)]; }, [], ); diff --git a/frontend/src/v5/store/tickets/tickets.selectors.ts b/frontend/src/v5/store/tickets/tickets.selectors.ts index f03f5f4b406..bf5a9b12fe8 100644 --- a/frontend/src/v5/store/tickets/tickets.selectors.ts +++ b/frontend/src/v5/store/tickets/tickets.selectors.ts @@ -28,7 +28,7 @@ export const sortTicketsByCreationDate = (tickets: any[]) => orderBy(tickets, `p const getTemplateDefaultStatus = (template: ITemplate) => template.properties?.find(({ name }) => name === BaseProperties.STATUS)?.default; -export const getTicketWithStatus = (ticket: ITicket, template: ITemplate) => { +const getTicketWithStatus = (ticket: ITicket, template: ITemplate) => { if (ticket.properties[BaseProperties.STATUS] || !template) return ticket; return { ...ticket, diff --git a/frontend/src/v5/store/tickets/tickets.types.ts b/frontend/src/v5/store/tickets/tickets.types.ts index 91a99deb092..3aabb126699 100644 --- a/frontend/src/v5/store/tickets/tickets.types.ts +++ b/frontend/src/v5/store/tickets/tickets.types.ts @@ -69,10 +69,17 @@ export type IPinColorMapping = { ] }; -export type IPinSchema = { +export enum PinIcon { + 'DEFAULT', + 'RISK', + 'ISSUE', + 'MARKER', +} + +export type PinConfig = { name: string; - type: 'coords'; color: RgbArray | IPinColorMapping; + icon: PinIcon; }; export type StatusValue = { @@ -96,7 +103,7 @@ export interface ITemplate { comments?: boolean; defaultView?: boolean; issueProperties?: boolean; - pin?: boolean | IPinSchema; + pin?: boolean | PinConfig; status?: IStatusConfig; }; } diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx index 4a263d5fa6f..61251aec066 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx @@ -25,7 +25,7 @@ import { Viewer as ViewerService } from '@/v4/services/viewer/viewer'; import { FormHelperText, Tooltip } from '@mui/material'; import { FormInputProps } from '@controls/inputs/inputController.component'; import { CoordsAction, CoordsActionLabel, CoordsActions, CoordsInputContainer, Label, FlexRow, SelectPinButton } from './coordsProperty.styles'; -import { DEFAULT_PIN, getLinkedValuePath, getPinColorHex, NEW_TICKET_ID } from './coordsProperty.helpers'; +import { getPinColorPropPath, getPinColorHex, NEW_TICKET_ID, toPin, getPinId } from './coordsProperty.helpers'; import { TicketContext } from '../../../ticket.context'; import { formatMessage } from '@/v5/services/intl'; import { TicketsCardHooksSelectors, TicketsHooksSelectors } from '@/v5/services/selectorsHooks'; @@ -35,7 +35,6 @@ import { ITicket } from '@/v5/store/tickets/tickets.types'; import { isEqual } from 'lodash'; import { useFormContext, useWatch } from 'react-hook-form'; import { DrawingViewerService } from '@components/viewer/drawingViewer/drawingViewer.service'; -import { hexToGLColor } from '@/v5/helpers/colors.helper'; export const CoordsProperty = ({ value, label, onChange, onBlur, required, error, helperText, disabled, name }: FormInputProps) => { const { isViewer, containerOrFederation } = useContext(TicketContext); @@ -47,12 +46,12 @@ export const CoordsProperty = ({ value, label, onChange, onBlur, required, error const template = TicketsHooksSelectors.selectTemplateById(containerOrFederation, selectedTemplateId); const selectedPin = TicketsCardHooksSelectors.selectSelectedTicketPinId(); - const linkedPath = getLinkedValuePath(name, template); - useWatch({ name:linkedPath }); + const colourPropPath = getPinColorPropPath(name, template); + useWatch({ name:colourPropPath }); const isNewTicket = !ticket?._id; const ticketId = !isNewTicket ? ticket._id : NEW_TICKET_ID; - const pinId = name === DEFAULT_PIN ? ticketId : `${ticketId}.${name}`; + const pinId = getPinId(name, ticket); const editMode = pinToDrop === pinId; const isSelected = selectedPin === pinId; const hasPin = !!value; @@ -104,8 +103,7 @@ export const CoordsProperty = ({ value, label, onChange, onBlur, required, error } if (hasPin) { - ViewerService.showPin({ - id: pinId, position: value, colour: hexToGLColor(colorHex), type: 'ticket' }); + ViewerService.showPin(toPin(name, template, ticket, false, value)); } if (isSelected) ViewerService.setSelectionPin({ id: pinId, isSelected }); diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts index 1251d8a795a..6e3da7b11b7 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts @@ -15,9 +15,9 @@ * along with this program. If not, see . */ import { compact, get, isArray, isEmpty, isObject } from 'lodash'; -import { IPinColorMapping, IPinSchema, ITemplate, ITicket } from '@/v5/store/tickets/tickets.types'; +import { IPinColorMapping, PinConfig, ITemplate, ITicket, PinIcon } from '@/v5/store/tickets/tickets.types'; import { AdditionalProperties, TicketBaseKeys } from '../../../tickets.constants'; -import { IPin } from '@/v4/services/viewer/viewer'; +import { IPin, PinType } from '@/v4/services/viewer/viewer'; import { COLOR } from '@/v5/ui/themes/theme'; import { hexToGLColor, rgbToHex } from '@/v5/helpers/colors.helper'; @@ -30,23 +30,23 @@ export const DEFAULT_PIN = `${TicketBaseKeys.PROPERTIES}.${AdditionalProperties. export const hasDefaultPin = (ticket: ITicket) => !!get(ticket, [TicketBaseKeys.PROPERTIES, AdditionalProperties.PIN]); -const getPinSchema = (name: string, template: ITemplate): IPinSchema | boolean => { +const getPinConfig = (pinPath: string, template: ITemplate): PinConfig | boolean => { if (!template) return; - if (name === DEFAULT_PIN) return template.config?.pin; - const path = name.split('.'); + if (pinPath === DEFAULT_PIN) return template.config?.pin; + const path = pinPath.split('.'); if (path[0] === TicketBaseKeys.PROPERTIES) return findByName(template.properties, path[1]); const module = findByName(template.modules, path[1]); if (!module) return; return findByName(module.properties, path[2]); }; -export const getLinkedValuePath = (name, template): string => { - const pinSchema = getPinSchema(name, template); - const property = get(pinSchema, 'color.property'); +export const getPinColorPropPath = (name, template): string => { + const pinConfig = getPinConfig(name, template); + const property = get(pinConfig, 'color.property'); if (!property) return ''; const module = property.module ? `${TicketBaseKeys.MODULES}.${property.module}` : TicketBaseKeys.PROPERTIES; - const linkedValueName = property.name; - return `${module}.${linkedValueName}`; + const propName = property.name; + return `${module}.${propName}`; }; const getColorFromMapping = (ticket: ITicket, pinMapping: IPinColorMapping) => { @@ -62,20 +62,43 @@ const getColorFromMapping = (ticket: ITicket, pinMapping: IPinColorMapping) => { }; export const getPinColorHex = (name: string, template: ITemplate, ticket: ITicket) => { - const pinSchema = getPinSchema(name, template); - if (typeof pinSchema === 'boolean') return DEFAULT_COLOR; // if default pin with no colouring set - if (isArray(pinSchema?.color)) return rgbToHex(pinSchema.color); // a custom colour is set, no mapping - if (isObject(pinSchema?.color)) return getColorFromMapping(ticket, pinSchema.color); // a custom colour is set with mapping + const pinConfig = getPinConfig(name, template); + if (typeof pinConfig === 'boolean') return DEFAULT_COLOR; // if default pin with no colouring set + if (isArray(pinConfig?.color)) return rgbToHex(pinConfig.color); // a custom colour is set, no mapping + if (isObject(pinConfig?.color)) return getColorFromMapping(ticket, pinConfig.color); // a custom colour is set with mapping return DEFAULT_COLOR; // if custom pin with no colouring set }; -export const formatPin = (pinId, position, isSelected: boolean, color: string): IPin => ({ - id: pinId, - position, - isSelected, - type: 'ticket', - colour: hexToGLColor(color), -}); +export const getPinIcon = (name: string, template: ITemplate): PinIcon => { + const pinConfig = getPinConfig(name, template); + if (isObject(pinConfig) && pinConfig.icon) return pinConfig.icon; + return PinIcon.DEFAULT; +}; + +export const getPinId = (propPath, ticketOrId?: ITicket | string) => { + const id = (isObject(ticketOrId) ? ticketOrId._id : ticketOrId ) || NEW_TICKET_ID ; + return propPath === DEFAULT_PIN ? id : `${id}.${propPath}`; +}; + +const pinIconToType = { + [PinIcon.DEFAULT] : 'ticket', + [PinIcon.ISSUE] : 'issue', + [PinIcon.RISK] : 'risk', + [PinIcon.MARKER] : 'bookmark', +}; + +export const toPin = (propPath: string, template: ITemplate, ticket: ITicket, isSelected:boolean = false, coordValue?: number[]): IPin => { + const colour = hexToGLColor(getPinColorHex(propPath, template, ticket)); + const icon = getPinIcon(propPath, template); + const id = getPinId(propPath, ticket); + return { + id, + position: (coordValue || get(ticket, propPath) as number[]), + isSelected, + type: pinIconToType[icon] as PinType, + colour, + }; +}; export const getTicketPins = (templates, ticket, ticketPinId) => { const pinArray = []; @@ -83,16 +106,13 @@ export const getTicketPins = (templates, ticket, ticketPinId) => { if (isEmpty(ticket) || !selectedTemplate) return []; - const selectedTicketId = ticket?._id || NEW_TICKET_ID; - const moduleToPins = (modulePath) => ({ name, type }) => { const pinPath = `${modulePath}.${name}`; if (type !== 'coords' || !get(ticket, pinPath)) return; - const pinId = pinPath === DEFAULT_PIN ? selectedTicketId : `${selectedTicketId}.${pinPath}`; - const color = getPinColorHex(pinPath, selectedTemplate, ticket); - const isSelected = pinId === ticketPinId; - return formatPin(pinId, get(ticket, pinPath), isSelected, color); + const isSelected = getPinId(pinPath, ticket) === ticketPinId; + return toPin(pinPath, selectedTemplate, ticket, isSelected); }; + pinArray.push(...selectedTemplate.properties.map(moduleToPins(TicketBaseKeys.PROPERTIES))); selectedTemplate.modules.forEach((module) => { const moduleName = module.name || module.type; From 9cc2ffe5c7a788c252ef3717702020ed0f3406f4 Mon Sep 17 00:00:00 2001 From: sanmont3drepo Date: Thu, 6 Feb 2025 15:34:37 +0000 Subject: [PATCH 02/19] ISSUE #5379 - Added temp code to mock pin icon config --- frontend/src/v5/services/api/tickets.ts | 52 +++++++++++++++++-- .../src/v5/store/tickets/tickets.types.ts | 6 +-- 2 files changed, 50 insertions(+), 8 deletions(-) diff --git a/frontend/src/v5/services/api/tickets.ts b/frontend/src/v5/services/api/tickets.ts index 32457fa555a..f8a8f769620 100644 --- a/frontend/src/v5/services/api/tickets.ts +++ b/frontend/src/v5/services/api/tickets.ts @@ -14,11 +14,53 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import { ITicket, ITemplate, NewTicket, Group } from '@/v5/store/tickets/tickets.types'; +import { ITicket, ITemplate, NewTicket, Group, PinIcon, PropertyDefinition } from '@/v5/store/tickets/tickets.types'; import api from './default'; +import { isObject } from 'lodash'; export const modelType = (isFed: boolean) => (isFed ? 'federations' : 'containers'); +/*************** TEMPORAL CODE FOR MOCKING PIN ICONS *****************/ +const templates = {}; +const pinIcons = [PinIcon.DEFAULT, PinIcon.ISSUE, PinIcon.RISK, PinIcon.MARKER]; +let pinIndex = 0; + +const getCoords = (properties: PropertyDefinition[]) => (properties||[]).filter((p) => p.type === 'coords'); + +//.filter(p => ) + + +const fillDummyIconInProp = (prop) => ( {...prop, icon: pinIcons[(pinIndex++) % 4], color: [212, 0, 208] }); + +const fillDummyPinIcon = (template:ITemplate): ITemplate => { + if (templates[template._id]) return templates[template._id]; + + + if (template.config.pin) { + if (isObject(template.config.pin)) { + template.config.pin.icon = pinIcons[(pinIndex++) % 4]; + } else { + template.config.pin = fillDummyIconInProp(template.config.pin); + } + + // template.modules?.forEach((module) => { + // if (module.type === 'safetibase') + + // }); + } + + getCoords(template.properties).forEach((p) => Object.assign(p, fillDummyIconInProp(p))); + + template.modules.forEach((module) => { + getCoords(module.properties).forEach((p) => Object.assign(p, fillDummyIconInProp(p))); + }); + + return template; +}; + +/*********************************************************************/ + + export const fetchContainerTemplates = async ( teamspace: string, projectId: string, @@ -26,7 +68,7 @@ export const fetchContainerTemplates = async ( getDetails?: boolean, ): Promise => { const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/containers/${containerId}/tickets/templates?getDetails=${getDetails}`); - return data.templates; + return data.templates.map(fillDummyPinIcon); }; export const fetchContainerTemplate = async ( @@ -36,7 +78,7 @@ export const fetchContainerTemplate = async ( templateId:string, ): Promise => { const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/containers/${containerId}/tickets/templates/${templateId}`); - return data; + return fillDummyPinIcon(data); }; export const fetchFederationTemplates = async ( @@ -46,7 +88,7 @@ export const fetchFederationTemplates = async ( getDetails?: boolean, ): Promise => { const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/federations/${federationId}/tickets/templates?getDetails=${getDetails}`); - return data.templates; + return data.templates.map(fillDummyPinIcon); }; export const fetchFederationTemplate = async ( @@ -56,7 +98,7 @@ export const fetchFederationTemplate = async ( templateId: string, ): Promise => { const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/federations/${federationId}/tickets/templates/${templateId}`); - return data; + return fillDummyPinIcon(data); }; export const fetchContainerTickets = async ( diff --git a/frontend/src/v5/store/tickets/tickets.types.ts b/frontend/src/v5/store/tickets/tickets.types.ts index 3aabb126699..962d4537ed2 100644 --- a/frontend/src/v5/store/tickets/tickets.types.ts +++ b/frontend/src/v5/store/tickets/tickets.types.ts @@ -77,9 +77,9 @@ export enum PinIcon { } export type PinConfig = { - name: string; - color: RgbArray | IPinColorMapping; - icon: PinIcon; + name?: string; + color?: RgbArray | IPinColorMapping; + icon?: PinIcon; }; export type StatusValue = { From 77c7ef95b75154a189c02d08e1e2d606305afa47 Mon Sep 17 00:00:00 2001 From: sanmont3drepo Date: Mon, 10 Feb 2025 18:00:49 +0000 Subject: [PATCH 03/19] ISSUE #5379 - Now the actual pin icon is showing in the coordinate field --- .../icons/filled/pin_issue-filled.svg.tsx | 30 +++++++++++++++++++ .../icons/filled/pin_marker-filled.svg.tsx | 26 ++++++++++++++++ .../icons/filled/pin_risk-filled.svg.tsx | 29 ++++++++++++++++++ ...lled.svg.tsx => pin_ticket-filled.svg.tsx} | 0 frontend/src/v5/services/api/tickets.ts | 9 ++---- .../src/v5/store/tickets/tickets.types.ts | 7 +---- .../pinsLayer/pin2D/pin2D.component.tsx | 2 +- .../coordsProperty.component.tsx | 22 ++++++++++++-- .../coordsProperty/coordsProperty.helpers.ts | 10 +++---- .../ticketsList/ticketsListCard.component.tsx | 2 +- 10 files changed, 115 insertions(+), 22 deletions(-) create mode 100644 frontend/assets/icons/filled/pin_issue-filled.svg.tsx create mode 100644 frontend/assets/icons/filled/pin_marker-filled.svg.tsx create mode 100644 frontend/assets/icons/filled/pin_risk-filled.svg.tsx rename frontend/assets/icons/filled/{ticket_pin-filled.svg.tsx => pin_ticket-filled.svg.tsx} (100%) diff --git a/frontend/assets/icons/filled/pin_issue-filled.svg.tsx b/frontend/assets/icons/filled/pin_issue-filled.svg.tsx new file mode 100644 index 00000000000..d3b2fcb87fb --- /dev/null +++ b/frontend/assets/icons/filled/pin_issue-filled.svg.tsx @@ -0,0 +1,30 @@ +/** + * Copyright (C) 2025 3D Repo Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + + +type IProps = { + className?: any; +}; + +export default ({ className }: IProps) => ( + + + +); diff --git a/frontend/assets/icons/filled/pin_marker-filled.svg.tsx b/frontend/assets/icons/filled/pin_marker-filled.svg.tsx new file mode 100644 index 00000000000..bb815483572 --- /dev/null +++ b/frontend/assets/icons/filled/pin_marker-filled.svg.tsx @@ -0,0 +1,26 @@ +/** + * Copyright (C) 2023 3D Repo Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +type IProps = { + className?: any; +}; + +export default ({ className }: IProps) => ( + + + +); diff --git a/frontend/assets/icons/filled/pin_risk-filled.svg.tsx b/frontend/assets/icons/filled/pin_risk-filled.svg.tsx new file mode 100644 index 00000000000..9d47c1f932c --- /dev/null +++ b/frontend/assets/icons/filled/pin_risk-filled.svg.tsx @@ -0,0 +1,29 @@ +/** + * Copyright (C) 2025 3D Repo Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +type IProps = { + className?: any; +}; + +export default ({ className }: IProps) => ( + + + +); diff --git a/frontend/assets/icons/filled/ticket_pin-filled.svg.tsx b/frontend/assets/icons/filled/pin_ticket-filled.svg.tsx similarity index 100% rename from frontend/assets/icons/filled/ticket_pin-filled.svg.tsx rename to frontend/assets/icons/filled/pin_ticket-filled.svg.tsx diff --git a/frontend/src/v5/services/api/tickets.ts b/frontend/src/v5/services/api/tickets.ts index f8a8f769620..300d71d7120 100644 --- a/frontend/src/v5/services/api/tickets.ts +++ b/frontend/src/v5/services/api/tickets.ts @@ -22,7 +22,7 @@ export const modelType = (isFed: boolean) => (isFed ? 'federations' : 'container /*************** TEMPORAL CODE FOR MOCKING PIN ICONS *****************/ const templates = {}; -const pinIcons = [PinIcon.DEFAULT, PinIcon.ISSUE, PinIcon.RISK, PinIcon.MARKER]; +const pinIcons = [ 'DEFAULT', 'ISSUE', 'RISK', 'MARKER']; let pinIndex = 0; const getCoords = (properties: PropertyDefinition[]) => (properties||[]).filter((p) => p.type === 'coords'); @@ -38,15 +38,10 @@ const fillDummyPinIcon = (template:ITemplate): ITemplate => { if (template.config.pin) { if (isObject(template.config.pin)) { - template.config.pin.icon = pinIcons[(pinIndex++) % 4]; + template.config.pin.icon = pinIcons[(pinIndex++) % 4] as PinIcon; } else { template.config.pin = fillDummyIconInProp(template.config.pin); } - - // template.modules?.forEach((module) => { - // if (module.type === 'safetibase') - - // }); } getCoords(template.properties).forEach((p) => Object.assign(p, fillDummyIconInProp(p))); diff --git a/frontend/src/v5/store/tickets/tickets.types.ts b/frontend/src/v5/store/tickets/tickets.types.ts index 962d4537ed2..d3423b73bfe 100644 --- a/frontend/src/v5/store/tickets/tickets.types.ts +++ b/frontend/src/v5/store/tickets/tickets.types.ts @@ -69,12 +69,7 @@ export type IPinColorMapping = { ] }; -export enum PinIcon { - 'DEFAULT', - 'RISK', - 'ISSUE', - 'MARKER', -} +export type PinIcon = 'DEFAULT' | 'RISK' | 'ISSUE' | 'MARKER'; export type PinConfig = { name?: string; diff --git a/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx b/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx index 75387d1eb08..2ba85dd4df1 100644 --- a/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx +++ b/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx @@ -16,7 +16,7 @@ */ import { IPin } from '@/v4/services/viewer/viewer'; -import PinIcon from '@assets/icons/filled/ticket_pin-filled.svg'; +import PinIcon from '@assets/icons/filled/pin_ticket-filled.svg'; import { PinContainer } from './pin2D.styles'; import { TicketsCardActionsDispatchers } from '@/v5/services/actionsDispatchers'; import { TicketsHooksSelectors } from '@/v5/services/selectorsHooks'; diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx index 61251aec066..48a4d06f972 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx @@ -17,7 +17,11 @@ import { useContext, useEffect, useRef } from 'react'; import CircledPlusIcon from '@assets/icons/outlined/add_circle-outlined.svg'; -import PinIcon from '@assets/icons/filled/ticket_pin-filled.svg'; +import TicketPin from '@assets/icons/filled/pin_ticket-filled.svg'; +import IssuePin from '@assets/icons/filled/pin_issue-filled.svg'; +import RiskPin from '@assets/icons/filled/pin_risk-filled.svg'; +import MarkerPin from '@assets/icons/filled/pin_marker-filled.svg'; + import DeleteIcon from '@assets/icons/outlined/delete-outlined.svg'; import MoveIcon from '@assets/icons/outlined/arrow_cross-outlined.svg'; import { FormattedMessage } from 'react-intl'; @@ -25,7 +29,7 @@ import { Viewer as ViewerService } from '@/v4/services/viewer/viewer'; import { FormHelperText, Tooltip } from '@mui/material'; import { FormInputProps } from '@controls/inputs/inputController.component'; import { CoordsAction, CoordsActionLabel, CoordsActions, CoordsInputContainer, Label, FlexRow, SelectPinButton } from './coordsProperty.styles'; -import { getPinColorPropPath, getPinColorHex, NEW_TICKET_ID, toPin, getPinId } from './coordsProperty.helpers'; +import { getPinColorPropPath, getPinColorHex, NEW_TICKET_ID, toPin, getPinId, getPinIcon } from './coordsProperty.helpers'; import { TicketContext } from '../../../ticket.context'; import { formatMessage } from '@/v5/services/intl'; import { TicketsCardHooksSelectors, TicketsHooksSelectors } from '@/v5/services/selectorsHooks'; @@ -36,6 +40,17 @@ import { isEqual } from 'lodash'; import { useFormContext, useWatch } from 'react-hook-form'; import { DrawingViewerService } from '@components/viewer/drawingViewer/drawingViewer.service'; + +const PinPerType = +{ + 'ISSUE': IssuePin, + 'RISK': RiskPin, + 'DEFAULT': TicketPin, + 'MARKER': MarkerPin, +}; + + + export const CoordsProperty = ({ value, label, onChange, onBlur, required, error, helperText, disabled, name }: FormInputProps) => { const { isViewer, containerOrFederation } = useContext(TicketContext); const pinToDrop = TicketsCardHooksSelectors.selectPinToDrop(); @@ -56,6 +71,7 @@ export const CoordsProperty = ({ value, label, onChange, onBlur, required, error const isSelected = selectedPin === pinId; const hasPin = !!value; const colorHex = getPinColorHex(name, template, ticket); + const pinIcon = getPinIcon(name, template); const cancelEdit = () => { if (!editMode) return; @@ -138,6 +154,8 @@ export const CoordsProperty = ({ value, label, onChange, onBlur, required, error if (isNewTicket) ViewerService.removePin(pinId); }, []); + const PinIcon = PinPerType[pinIcon]; + return ( diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts index 6e3da7b11b7..fe5f84343e1 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts @@ -72,7 +72,7 @@ export const getPinColorHex = (name: string, template: ITemplate, ticket: ITicke export const getPinIcon = (name: string, template: ITemplate): PinIcon => { const pinConfig = getPinConfig(name, template); if (isObject(pinConfig) && pinConfig.icon) return pinConfig.icon; - return PinIcon.DEFAULT; + return 'DEFAULT'; }; export const getPinId = (propPath, ticketOrId?: ITicket | string) => { @@ -81,10 +81,10 @@ export const getPinId = (propPath, ticketOrId?: ITicket | string) => { }; const pinIconToType = { - [PinIcon.DEFAULT] : 'ticket', - [PinIcon.ISSUE] : 'issue', - [PinIcon.RISK] : 'risk', - [PinIcon.MARKER] : 'bookmark', + 'DEFAULT' : 'ticket', + 'ISSUE' : 'issue', + 'RISK' : 'risk', + 'MARKER' : 'bookmark', }; export const toPin = (propPath: string, template: ITemplate, ticket: ITicket, isSelected:boolean = false, coordValue?: number[]): IPin => { diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsList/ticketsListCard.component.tsx b/frontend/src/v5/ui/routes/viewer/tickets/ticketsList/ticketsListCard.component.tsx index 72937842b70..fda68557858 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsList/ticketsListCard.component.tsx +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsList/ticketsListCard.component.tsx @@ -27,7 +27,7 @@ import { ViewerParams } from '../../../routes.constants'; import { TicketsCardActionsDispatchers } from '@/v5/services/actionsDispatchers'; import { EllipsisMenu } from '@controls/ellipsisMenu'; import { formatMessage } from '@/v5/services/intl'; -import PinIcon from '@assets/icons/filled/ticket_pin-filled.svg'; +import PinIcon from '@assets/icons/filled/pin_ticket-filled.svg'; import { EllipsisMenuItemSwitch } from '@controls/ellipsisMenu/ellipsisMenuItem/ellipsisMenuItemSwitch.component'; import { CardHeader } from '@components/viewer/cards/cardHeader.component'; From c2a4f92fdf8e613dcbbcdbb432655c39e40bc020 Mon Sep 17 00:00:00 2001 From: sanmont3drepo Date: Tue, 11 Feb 2025 18:04:23 +0000 Subject: [PATCH 04/19] ISSUE #5379 - Added Pin type to 2d pin --- .../icons/filled/pin_marker-filled.svg.tsx | 11 ++++-- .../pinsLayer/pin2D/pin2D.component.tsx | 7 ++-- .../coordsProperty.component.tsx | 20 ++--------- .../coordsProperty/coordsProperty.helpers.ts | 2 ++ .../properties/coordsProperty/pin.tsx | 36 +++++++++++++++++++ 5 files changed, 53 insertions(+), 23 deletions(-) create mode 100644 frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/pin.tsx diff --git a/frontend/assets/icons/filled/pin_marker-filled.svg.tsx b/frontend/assets/icons/filled/pin_marker-filled.svg.tsx index bb815483572..98c66b93c10 100644 --- a/frontend/assets/icons/filled/pin_marker-filled.svg.tsx +++ b/frontend/assets/icons/filled/pin_marker-filled.svg.tsx @@ -20,7 +20,14 @@ type IProps = { }; export default ({ className }: IProps) => ( - - + + + + ); diff --git a/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx b/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx index 2ba85dd4df1..42ad8fcd41c 100644 --- a/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx +++ b/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx @@ -16,15 +16,16 @@ */ import { IPin } from '@/v4/services/viewer/viewer'; -import PinIcon from '@assets/icons/filled/pin_ticket-filled.svg'; import { PinContainer } from './pin2D.styles'; import { TicketsCardActionsDispatchers } from '@/v5/services/actionsDispatchers'; import { TicketsHooksSelectors } from '@/v5/services/selectorsHooks'; import { useParams } from 'react-router'; import { ViewerParams } from '@/v5/ui/routes/routes.constants'; +import { Pin } from '@/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/pin'; +import { toPinIcon } from '@/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers'; type Pin2DProps = IPin & { scale: number }; -export const Pin2D = ({ id, isSelected, position, colour, scale }: Pin2DProps) => { +export const Pin2D = ({ id, isSelected, position, colour, scale, type }: Pin2DProps) => { const { containerOrFederation } = useParams(); const tickets = TicketsHooksSelectors.selectTickets(containerOrFederation); @@ -43,7 +44,7 @@ export const Pin2D = ({ id, isSelected, position, colour, scale }: Pin2DProps) = selected={isSelected} style={{ transform: `translate(${position[0]}px, ${position[1]}px) scale(${0.333 / scale})` }} > - + ); }; diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx index 48a4d06f972..68e49f7c92f 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx @@ -17,10 +17,6 @@ import { useContext, useEffect, useRef } from 'react'; import CircledPlusIcon from '@assets/icons/outlined/add_circle-outlined.svg'; -import TicketPin from '@assets/icons/filled/pin_ticket-filled.svg'; -import IssuePin from '@assets/icons/filled/pin_issue-filled.svg'; -import RiskPin from '@assets/icons/filled/pin_risk-filled.svg'; -import MarkerPin from '@assets/icons/filled/pin_marker-filled.svg'; import DeleteIcon from '@assets/icons/outlined/delete-outlined.svg'; import MoveIcon from '@assets/icons/outlined/arrow_cross-outlined.svg'; @@ -39,17 +35,7 @@ import { ITicket } from '@/v5/store/tickets/tickets.types'; import { isEqual } from 'lodash'; import { useFormContext, useWatch } from 'react-hook-form'; import { DrawingViewerService } from '@components/viewer/drawingViewer/drawingViewer.service'; - - -const PinPerType = -{ - 'ISSUE': IssuePin, - 'RISK': RiskPin, - 'DEFAULT': TicketPin, - 'MARKER': MarkerPin, -}; - - +import { Pin } from './pin'; export const CoordsProperty = ({ value, label, onChange, onBlur, required, error, helperText, disabled, name }: FormInputProps) => { const { isViewer, containerOrFederation } = useContext(TicketContext); @@ -154,8 +140,6 @@ export const CoordsProperty = ({ value, label, onChange, onBlur, required, error if (isNewTicket) ViewerService.removePin(pinId); }, []); - const PinIcon = PinPerType[pinIcon]; - return ( @@ -207,7 +191,7 @@ export const CoordsProperty = ({ value, label, onChange, onBlur, required, error onClick={onClickSelectPin} disabled={!hasPin} > - + )} diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts index fe5f84343e1..50cbb02a24c 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts @@ -100,6 +100,8 @@ export const toPin = (propPath: string, template: ITemplate, ticket: ITicket, i }; }; +export const toPinIcon = (type: PinType) => (Object.keys(pinIconToType).find((key) => pinIconToType[key] === type) || 'DEFAULT') as PinIcon; + export const getTicketPins = (templates, ticket, ticketPinId) => { const pinArray = []; const selectedTemplate = templates?.find(({ _id }) => _id === ticket?.type); diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/pin.tsx b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/pin.tsx new file mode 100644 index 00000000000..17b7af9ff42 --- /dev/null +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/pin.tsx @@ -0,0 +1,36 @@ +/** + * Copyright (C) 2025 3D Repo Ltd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ +import TicketPin from '@assets/icons/filled/pin_ticket-filled.svg'; +import IssuePin from '@assets/icons/filled/pin_issue-filled.svg'; +import RiskPin from '@assets/icons/filled/pin_risk-filled.svg'; +import MarkerPin from '@assets/icons/filled/pin_marker-filled.svg'; +import { PinIcon } from '@/v5/store/tickets/tickets.types'; + + +const PinPerType = +{ + 'ISSUE': IssuePin, + 'RISK': RiskPin, + 'DEFAULT': TicketPin, + 'MARKER': MarkerPin, +}; + + +export const Pin = ({ type }: { type:PinIcon }) => { + const Icon = PinPerType[type]; + return (); +}; \ No newline at end of file From 6f885d5172a9d80b3a4cbd0be6712aee6ed69482 Mon Sep 17 00:00:00 2001 From: sanmont3drepo Date: Wed, 12 Feb 2025 10:26:19 +0000 Subject: [PATCH 05/19] ISSUE #5379 - Fixed 2d pin selections and size in drawings --- .../icons/filled/pin_issue-filled.svg.tsx | 2 ++ .../icons/filled/pin_marker-filled.svg.tsx | 1 + .../icons/filled/pin_risk-filled.svg.tsx | 10 ++++--- .../icons/filled/pin_ticket-filled.svg.tsx | 4 +-- frontend/src/v5/services/api/tickets.ts | 7 ++--- .../pinsLayer/pin2D/pin2D.component.tsx | 4 +-- .../pinsLayer/pin2D/pin2D.styles.ts | 28 +++++++++++-------- .../properties/coordsProperty => }/pin.tsx | 5 ++-- .../coordsProperty.component.tsx | 4 +-- .../coordsProperty/coordsProperty.helpers.ts | 1 + .../coordsProperty/coordsProperty.styles.ts | 4 +-- 11 files changed, 39 insertions(+), 31 deletions(-) rename frontend/src/v5/ui/routes/viewer/tickets/{ticketsForm/properties/coordsProperty => }/pin.tsx (92%) diff --git a/frontend/assets/icons/filled/pin_issue-filled.svg.tsx b/frontend/assets/icons/filled/pin_issue-filled.svg.tsx index d3b2fcb87fb..e725eedbb3f 100644 --- a/frontend/assets/icons/filled/pin_issue-filled.svg.tsx +++ b/frontend/assets/icons/filled/pin_issue-filled.svg.tsx @@ -22,7 +22,9 @@ type IProps = { export default ({ className }: IProps) => ( + diff --git a/frontend/assets/icons/filled/pin_marker-filled.svg.tsx b/frontend/assets/icons/filled/pin_marker-filled.svg.tsx index 98c66b93c10..142df441683 100644 --- a/frontend/assets/icons/filled/pin_marker-filled.svg.tsx +++ b/frontend/assets/icons/filled/pin_marker-filled.svg.tsx @@ -22,6 +22,7 @@ type IProps = { export default ({ className }: IProps) => ( diff --git a/frontend/assets/icons/filled/pin_risk-filled.svg.tsx b/frontend/assets/icons/filled/pin_risk-filled.svg.tsx index 9d47c1f932c..1bf5c829d7f 100644 --- a/frontend/assets/icons/filled/pin_risk-filled.svg.tsx +++ b/frontend/assets/icons/filled/pin_risk-filled.svg.tsx @@ -20,10 +20,12 @@ type IProps = { }; export default ({ className }: IProps) => ( - - + + ); diff --git a/frontend/assets/icons/filled/pin_ticket-filled.svg.tsx b/frontend/assets/icons/filled/pin_ticket-filled.svg.tsx index 38e5371a9a2..4125eeecf6b 100644 --- a/frontend/assets/icons/filled/pin_ticket-filled.svg.tsx +++ b/frontend/assets/icons/filled/pin_ticket-filled.svg.tsx @@ -21,7 +21,7 @@ type IProps = { export default ({ className }: IProps) => ( - - + + ); diff --git a/frontend/src/v5/services/api/tickets.ts b/frontend/src/v5/services/api/tickets.ts index 300d71d7120..fd9b68d046a 100644 --- a/frontend/src/v5/services/api/tickets.ts +++ b/frontend/src/v5/services/api/tickets.ts @@ -25,12 +25,9 @@ const templates = {}; const pinIcons = [ 'DEFAULT', 'ISSUE', 'RISK', 'MARKER']; let pinIndex = 0; -const getCoords = (properties: PropertyDefinition[]) => (properties||[]).filter((p) => p.type === 'coords'); +const getCoords = (properties: PropertyDefinition[]) => (properties || []).filter((p) => p.type === 'coords'); -//.filter(p => ) - - -const fillDummyIconInProp = (prop) => ( {...prop, icon: pinIcons[(pinIndex++) % 4], color: [212, 0, 208] }); +const fillDummyIconInProp = (prop) => ( { ...prop, icon: pinIcons[(pinIndex++) % 4] }); const fillDummyPinIcon = (template:ITemplate): ITemplate => { if (templates[template._id]) return templates[template._id]; diff --git a/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx b/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx index 42ad8fcd41c..ace3f1feb82 100644 --- a/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx +++ b/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx @@ -21,7 +21,7 @@ import { TicketsCardActionsDispatchers } from '@/v5/services/actionsDispatchers' import { TicketsHooksSelectors } from '@/v5/services/selectorsHooks'; import { useParams } from 'react-router'; import { ViewerParams } from '@/v5/ui/routes/routes.constants'; -import { Pin } from '@/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/pin'; +import { Pin } from '@/v5/ui/routes/viewer/tickets/pin'; import { toPinIcon } from '@/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers'; type Pin2DProps = IPin & { scale: number }; @@ -44,7 +44,7 @@ export const Pin2D = ({ id, isSelected, position, colour, scale, type }: Pin2DPr selected={isSelected} style={{ transform: `translate(${position[0]}px, ${position[1]}px) scale(${0.333 / scale})` }} > - + ); }; diff --git a/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.styles.ts b/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.styles.ts index ce7074e819e..a478f85ef46 100644 --- a/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.styles.ts +++ b/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.styles.ts @@ -43,24 +43,30 @@ const popupAnimation = keyframes` export const PinContainer = styled.div<{ colour, selected?: boolean }>` position: absolute; - color: rgb(${({ colour }) => colour.map((val) => Math.round(val * 256)).join()}); - + svg { ${({ selected }) => selected && css` - transform-origin: bottom center; - animation: ${popupAnimation} 1s forwards; - - #selectionFill { - stroke-width: 7px; - } + transform-origin: bottom center; + animation: ${popupAnimation} 1s forwards; + + #selectionFill { + visibility: visible; + } `} position: absolute; - + left: -25px; top: -64px; + + #main { + color: rgb(${({ colour }) => colour.map((val) => Math.round(val * 256)).join()}); + stroke: #000; + stroke-width: 2%; + } - stroke: #000; - stroke-width: 2%; overflow: visible; + + height: 64px; + width: 64px; } `; diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/pin.tsx b/frontend/src/v5/ui/routes/viewer/tickets/pin.tsx similarity index 92% rename from frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/pin.tsx rename to frontend/src/v5/ui/routes/viewer/tickets/pin.tsx index 17b7af9ff42..a4386215743 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/pin.tsx +++ b/frontend/src/v5/ui/routes/viewer/tickets/pin.tsx @@ -29,8 +29,7 @@ const PinPerType = 'MARKER': MarkerPin, }; - -export const Pin = ({ type }: { type:PinIcon }) => { - const Icon = PinPerType[type]; +export const Pin = ({ pinIcon }: { pinIcon:PinIcon }) => { + const Icon = PinPerType[pinIcon]; return (); }; \ No newline at end of file diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx index 68e49f7c92f..41fef75e6d8 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx @@ -35,7 +35,7 @@ import { ITicket } from '@/v5/store/tickets/tickets.types'; import { isEqual } from 'lodash'; import { useFormContext, useWatch } from 'react-hook-form'; import { DrawingViewerService } from '@components/viewer/drawingViewer/drawingViewer.service'; -import { Pin } from './pin'; +import { Pin } from '../../../pin'; export const CoordsProperty = ({ value, label, onChange, onBlur, required, error, helperText, disabled, name }: FormInputProps) => { const { isViewer, containerOrFederation } = useContext(TicketContext); @@ -191,7 +191,7 @@ export const CoordsProperty = ({ value, label, onChange, onBlur, required, error onClick={onClickSelectPin} disabled={!hasPin} > - + )} diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts index 50cbb02a24c..a4ca66acea4 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts @@ -80,6 +80,7 @@ export const getPinId = (propPath, ticketOrId?: ITicket | string) => { return propPath === DEFAULT_PIN ? id : `${id}.${propPath}`; }; +// PinIcon is the pin type that comes from the backend const pinIconToType = { 'DEFAULT' : 'ticket', 'ISSUE' : 'issue', diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.styles.ts b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.styles.ts index db144cf966c..357ccbbe07e 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.styles.ts +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.styles.ts @@ -109,8 +109,8 @@ export const SelectPinButton = styled.div<{ color: string, isSelected: boolean; > svg { color: ${({ color, theme }) => color || theme.palette.primary.main}; - height: 20px; - width: auto; + max-height: 20px; + max-width: 20px; overflow: visible; } `; From c216dccf7481e138e96bea0589419d4e6cec575d Mon Sep 17 00:00:00 2001 From: sanmont3drepo Date: Wed, 12 Feb 2025 10:36:46 +0000 Subject: [PATCH 06/19] ISSUE #5379 - Fixed selection in 2d drawing of ticket pin --- frontend/assets/icons/filled/pin_ticket-filled.svg.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/assets/icons/filled/pin_ticket-filled.svg.tsx b/frontend/assets/icons/filled/pin_ticket-filled.svg.tsx index 4125eeecf6b..0b238345020 100644 --- a/frontend/assets/icons/filled/pin_ticket-filled.svg.tsx +++ b/frontend/assets/icons/filled/pin_ticket-filled.svg.tsx @@ -21,7 +21,7 @@ type IProps = { export default ({ className }: IProps) => ( - + ); From aef908867d8d5a89abfdbe13e5ba801f8e2be548 Mon Sep 17 00:00:00 2001 From: sanmont3drepo Date: Thu, 13 Feb 2025 18:20:08 +0000 Subject: [PATCH 07/19] ISSUE #5379 - Renamed some functions for readability --- .../pinsLayer/pin2D/pin2D.component.tsx | 4 +-- .../coordsProperty.component.tsx | 8 +++--- .../coordsProperty/coordsProperty.helpers.ts | 28 +++++++++---------- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx b/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx index ace3f1feb82..c86074efb3e 100644 --- a/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx +++ b/frontend/src/v5/ui/components/viewer/drawingViewer/pinsLayer/pin2D/pin2D.component.tsx @@ -22,7 +22,7 @@ import { TicketsHooksSelectors } from '@/v5/services/selectorsHooks'; import { useParams } from 'react-router'; import { ViewerParams } from '@/v5/ui/routes/routes.constants'; import { Pin } from '@/v5/ui/routes/viewer/tickets/pin'; -import { toPinIcon } from '@/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers'; +import { pinTypeToPinIcon } from '@/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers'; type Pin2DProps = IPin & { scale: number }; export const Pin2D = ({ id, isSelected, position, colour, scale, type }: Pin2DProps) => { @@ -44,7 +44,7 @@ export const Pin2D = ({ id, isSelected, position, colour, scale, type }: Pin2DPr selected={isSelected} style={{ transform: `translate(${position[0]}px, ${position[1]}px) scale(${0.333 / scale})` }} > - + ); }; diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx index 41fef75e6d8..7398e1300e0 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.component.tsx @@ -25,7 +25,7 @@ import { Viewer as ViewerService } from '@/v4/services/viewer/viewer'; import { FormHelperText, Tooltip } from '@mui/material'; import { FormInputProps } from '@controls/inputs/inputController.component'; import { CoordsAction, CoordsActionLabel, CoordsActions, CoordsInputContainer, Label, FlexRow, SelectPinButton } from './coordsProperty.styles'; -import { getPinColorPropPath, getPinColorHex, NEW_TICKET_ID, toPin, getPinId, getPinIcon } from './coordsProperty.helpers'; +import { getColorTriggerPropName, getPinColorHexForProperty, NEW_TICKET_ID, toPin, getPinId, getPinIconForProperty } from './coordsProperty.helpers'; import { TicketContext } from '../../../ticket.context'; import { formatMessage } from '@/v5/services/intl'; import { TicketsCardHooksSelectors, TicketsHooksSelectors } from '@/v5/services/selectorsHooks'; @@ -47,7 +47,7 @@ export const CoordsProperty = ({ value, label, onChange, onBlur, required, error const template = TicketsHooksSelectors.selectTemplateById(containerOrFederation, selectedTemplateId); const selectedPin = TicketsCardHooksSelectors.selectSelectedTicketPinId(); - const colourPropPath = getPinColorPropPath(name, template); + const colourPropPath = getColorTriggerPropName(name, template); useWatch({ name:colourPropPath }); const isNewTicket = !ticket?._id; @@ -56,8 +56,8 @@ export const CoordsProperty = ({ value, label, onChange, onBlur, required, error const editMode = pinToDrop === pinId; const isSelected = selectedPin === pinId; const hasPin = !!value; - const colorHex = getPinColorHex(name, template, ticket); - const pinIcon = getPinIcon(name, template); + const colorHex = getPinColorHexForProperty(name, template, ticket); + const pinIcon = getPinIconForProperty(name, template); const cancelEdit = () => { if (!editMode) return; diff --git a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts index a4ca66acea4..91cd87eb539 100644 --- a/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts +++ b/frontend/src/v5/ui/routes/viewer/tickets/ticketsForm/properties/coordsProperty/coordsProperty.helpers.ts @@ -40,13 +40,13 @@ const getPinConfig = (pinPath: string, template: ITemplate): PinConfig | boolean return findByName(module.properties, path[2]); }; -export const getPinColorPropPath = (name, template): string => { - const pinConfig = getPinConfig(name, template); +export const getColorTriggerPropName = (pinPropName, template): string => { + const pinConfig = getPinConfig(pinPropName, template); const property = get(pinConfig, 'color.property'); if (!property) return ''; const module = property.module ? `${TicketBaseKeys.MODULES}.${property.module}` : TicketBaseKeys.PROPERTIES; - const propName = property.name; - return `${module}.${propName}`; + const triggerPropertyName = property.name; + return `${module}.${triggerPropertyName}`; }; const getColorFromMapping = (ticket: ITicket, pinMapping: IPinColorMapping) => { @@ -61,16 +61,16 @@ const getColorFromMapping = (ticket: ITicket, pinMapping: IPinColorMapping) => { return rgb ? rgbToHex(rgb) : defaultColorHex; }; -export const getPinColorHex = (name: string, template: ITemplate, ticket: ITicket) => { - const pinConfig = getPinConfig(name, template); +export const getPinColorHexForProperty = (propertyName: string, template: ITemplate, ticket: ITicket) => { + const pinConfig = getPinConfig(propertyName, template); if (typeof pinConfig === 'boolean') return DEFAULT_COLOR; // if default pin with no colouring set if (isArray(pinConfig?.color)) return rgbToHex(pinConfig.color); // a custom colour is set, no mapping if (isObject(pinConfig?.color)) return getColorFromMapping(ticket, pinConfig.color); // a custom colour is set with mapping return DEFAULT_COLOR; // if custom pin with no colouring set }; -export const getPinIcon = (name: string, template: ITemplate): PinIcon => { - const pinConfig = getPinConfig(name, template); +export const getPinIconForProperty = (propertyName: string, template: ITemplate): PinIcon => { + const pinConfig = getPinConfig(propertyName, template); if (isObject(pinConfig) && pinConfig.icon) return pinConfig.icon; return 'DEFAULT'; }; @@ -88,20 +88,20 @@ const pinIconToType = { 'MARKER' : 'bookmark', }; -export const toPin = (propPath: string, template: ITemplate, ticket: ITicket, isSelected:boolean = false, coordValue?: number[]): IPin => { - const colour = hexToGLColor(getPinColorHex(propPath, template, ticket)); - const icon = getPinIcon(propPath, template); - const id = getPinId(propPath, ticket); +export const toPin = (propName: string, template: ITemplate, ticket: ITicket, isSelected:boolean = false, coordValue?: number[]): IPin => { + const colour = hexToGLColor(getPinColorHexForProperty(propName, template, ticket)); + const icon = getPinIconForProperty(propName, template); + const id = getPinId(propName, ticket); return { id, - position: (coordValue || get(ticket, propPath) as number[]), + position: (coordValue || get(ticket, propName) as number[]), isSelected, type: pinIconToType[icon] as PinType, colour, }; }; -export const toPinIcon = (type: PinType) => (Object.keys(pinIconToType).find((key) => pinIconToType[key] === type) || 'DEFAULT') as PinIcon; +export const pinTypeToPinIcon = (type: PinType) => (Object.keys(pinIconToType).find((key) => pinIconToType[key] === type) || 'DEFAULT') as PinIcon; export const getTicketPins = (templates, ticket, ticketPinId) => { const pinArray = []; From fd1146f0b407c2daa21fa66ede70b3f87072aca0 Mon Sep 17 00:00:00 2001 From: sanmont3drepo Date: Thu, 13 Feb 2025 18:32:36 +0000 Subject: [PATCH 08/19] ISSUE #5379 - Tabular view working --- frontend/src/v5/services/api/tickets.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/frontend/src/v5/services/api/tickets.ts b/frontend/src/v5/services/api/tickets.ts index fd9b68d046a..8d6e433241e 100644 --- a/frontend/src/v5/services/api/tickets.ts +++ b/frontend/src/v5/services/api/tickets.ts @@ -33,7 +33,7 @@ const fillDummyPinIcon = (template:ITemplate): ITemplate => { if (templates[template._id]) return templates[template._id]; - if (template.config.pin) { + if (template?.config?.pin) { if (isObject(template.config.pin)) { template.config.pin.icon = pinIcons[(pinIndex++) % 4] as PinIcon; } else { @@ -41,9 +41,9 @@ const fillDummyPinIcon = (template:ITemplate): ITemplate => { } } - getCoords(template.properties).forEach((p) => Object.assign(p, fillDummyIconInProp(p))); + getCoords(template?.properties).forEach((p) => Object.assign(p, fillDummyIconInProp(p))); - template.modules.forEach((module) => { + template?.modules?.forEach((module) => { getCoords(module.properties).forEach((p) => Object.assign(p, fillDummyIconInProp(p))); }); From 005e754208130786aa854fc1d18b50a17e525ed0 Mon Sep 17 00:00:00 2001 From: Charence <1438332+Charence@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:16:30 +0000 Subject: [PATCH 09/19] ISSUE #5414 - update runners to ubuntu-latest --- .github/workflows/automaticTesting.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/automaticTesting.yml b/.github/workflows/automaticTesting.yml index e739044116f..a4b6d7b345f 100644 --- a/.github/workflows/automaticTesting.yml +++ b/.github/workflows/automaticTesting.yml @@ -14,7 +14,7 @@ permissions: jobs: run-backend-tests: name: Run Backend tests - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest services: rabbitmq: image: rabbitmq:3.10.5-management @@ -51,7 +51,7 @@ jobs: run-backend-lint: name: Run Backend lint - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Check out Git repository uses: actions/checkout@v3 @@ -77,7 +77,7 @@ jobs: run-frontend-tests: name: Run Frontend tests - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Check out Git repository @@ -108,7 +108,7 @@ jobs: run-frontend-lint: name: Run Frontend lint - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Check out Git repository @@ -139,7 +139,7 @@ jobs: # make sure we're not merging DevOps changes devops-sanity-check: name: Ensure that custom settings are not being merged - runs-on: ubuntu-20.04 + runs-on: ubuntu-latest steps: - name: Checkout .azure/build-and-deploy.yaml uses: Bhacaz/checkout-files@v2 From 1bbf88d79fec7f028af4c7941d846f506a7e6151 Mon Sep 17 00:00:00 2001 From: Charence <1438332+Charence@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:22:30 +0000 Subject: [PATCH 10/19] ISSUE #5414 - specify ubuntu runner version for tests --- .github/workflows/automaticTesting.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/automaticTesting.yml b/.github/workflows/automaticTesting.yml index a4b6d7b345f..72d38f63cf9 100644 --- a/.github/workflows/automaticTesting.yml +++ b/.github/workflows/automaticTesting.yml @@ -14,7 +14,7 @@ permissions: jobs: run-backend-tests: name: Run Backend tests - runs-on: ubuntu-latest + runs-on: ubuntu-22.04 services: rabbitmq: image: rabbitmq:3.10.5-management @@ -51,7 +51,7 @@ jobs: run-backend-lint: name: Run Backend lint - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Check out Git repository uses: actions/checkout@v3 @@ -77,7 +77,7 @@ jobs: run-frontend-tests: name: Run Frontend tests - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Check out Git repository @@ -108,7 +108,7 @@ jobs: run-frontend-lint: name: Run Frontend lint - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Check out Git repository @@ -139,7 +139,7 @@ jobs: # make sure we're not merging DevOps changes devops-sanity-check: name: Ensure that custom settings are not being merged - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - name: Checkout .azure/build-and-deploy.yaml uses: Bhacaz/checkout-files@v2 From fc796b0db3c2d042bbdd8bdbc67024ddcbb1fa02 Mon Sep 17 00:00:00 2001 From: Charence <1438332+Charence@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:44:27 +0000 Subject: [PATCH 11/19] ISSUE #5414 - update backend test to Mongo v8 --- backend/jest-mongodb-config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/jest-mongodb-config.js b/backend/jest-mongodb-config.js index c66f1fc4e63..c66c356aa62 100644 --- a/backend/jest-mongodb-config.js +++ b/backend/jest-mongodb-config.js @@ -18,7 +18,7 @@ module.exports = { mongodbMemoryServerOptions: { binary: { - version: '5.0.8', + version: '8.0.4', skipMD5: true, downloadDir: './node_modules/.cache', }, From 8246c1a2a855769f5b9588295447914bdf67f884 Mon Sep 17 00:00:00 2001 From: Charence <1438332+Charence@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:50:48 +0000 Subject: [PATCH 12/19] ISSUE #5414 - upgrade backend test to noble numbat --- .github/workflows/automaticTesting.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/automaticTesting.yml b/.github/workflows/automaticTesting.yml index 72d38f63cf9..48e02fba7d8 100644 --- a/.github/workflows/automaticTesting.yml +++ b/.github/workflows/automaticTesting.yml @@ -14,7 +14,7 @@ permissions: jobs: run-backend-tests: name: Run Backend tests - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 services: rabbitmq: image: rabbitmq:3.10.5-management From 57f1baefd9b9fec780c8de605a030ec0ce7cf8ed Mon Sep 17 00:00:00 2001 From: Charence <1438332+Charence@users.noreply.github.com> Date: Fri, 14 Feb 2025 14:57:59 +0000 Subject: [PATCH 13/19] ISSUE #5414 - update ubuntu for azp --- .azure/build-and-deploy.yaml | 2 +- .azure/build.yaml | 2 +- .azure/destroy.yaml | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.azure/build-and-deploy.yaml b/.azure/build-and-deploy.yaml index 8ff7852c2fe..ed86ca13c93 100644 --- a/.azure/build-and-deploy.yaml +++ b/.azure/build-and-deploy.yaml @@ -17,7 +17,7 @@ resources: variables: # Agent VM image name - vmImageName: 'ubuntu-20.04' + vmImageName: 'ubuntu-24.04' # Container registry service connection established during pipeline creation dockerRegistryServiceConnection: '3drepo.azurecr.io' imageRepository: '3drepo.io' diff --git a/.azure/build.yaml b/.azure/build.yaml index a81997c76b3..a10f04ed49b 100644 --- a/.azure/build.yaml +++ b/.azure/build.yaml @@ -14,7 +14,7 @@ resources: variables: # Agent VM image name - vmImageName: 'ubuntu-20.04' + vmImageName: 'ubuntu-24.04' # Container registry service connection established during pipeline creation dockerRegistryServiceConnection: '3drepo.azurecr.io' imageRepository: '3drepo.io' diff --git a/.azure/destroy.yaml b/.azure/destroy.yaml index 02228697b7f..d0d173d99bb 100644 --- a/.azure/destroy.yaml +++ b/.azure/destroy.yaml @@ -2,7 +2,7 @@ trigger: none variables: # Agent VM image name - vmImageName: 'ubuntu-20.04' + vmImageName: 'ubuntu-24.04' # Container registry service connection established during pipeline creation dockerRegistryServiceConnection: '3drepo.azurecr.io' imageRepository: '3drepo.io' @@ -44,4 +44,4 @@ stages: kubernetesServiceConnection: 'stg3drepo' namespace: 'default' command: 'uninstall' - arguments: '$(branchName)' \ No newline at end of file + arguments: '$(branchName)' From e6b50014535dae1d996bfe1be238baa9affe9e0b Mon Sep 17 00:00:00 2001 From: Charence <1438332+Charence@users.noreply.github.com> Date: Tue, 18 Feb 2025 09:21:55 +0000 Subject: [PATCH 14/19] ISSUE #5414 - update travis to noble --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7a2572c78db..b661d7a4dd3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,13 +2,13 @@ matrix: include: # tests (v4) - language: node_js - dist: jammy + dist: noble name: Backend tests (V4) git: submodules: false depth: 1 node_js: - - "18.20.4" + - "18.20.6" sudo: true addons: apt: From 7216c00234e697955841a3b769076150ecb26ee4 Mon Sep 17 00:00:00 2001 From: Charence <1438332+Charence@users.noreply.github.com> Date: Tue, 18 Feb 2025 09:25:55 +0000 Subject: [PATCH 15/19] ISSUE #5414 - update to mongodb 8 --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b661d7a4dd3..3b70c05b948 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,8 +24,8 @@ matrix: before_install: - sudo apt remove mongodb && sudo apt purge mongodb && sudo apt autoremove && sudo rm -rf /var/lib/mongodb - sudo apt-get -y install gnupg curl - - curl -fsSL https://www.mongodb.org/static/pgp/server-6.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-6.0.gpg --dearmor - - echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-6.0.gpg ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list + - curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor + - echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list - sudo apt-get update - sudo apt-get install -y mongodb-org mongodb-org-database mongodb-org-server mongodb-org-mongos mongodb-org-tools - sudo mkdir -p /var/lib/mongodb From e250ec59e0a2d81f9b0bae8e9d3137a56e8bdc86 Mon Sep 17 00:00:00 2001 From: Alessandro Amantini Date: Tue, 18 Feb 2025 11:52:47 +0000 Subject: [PATCH 16/19] ISSUE #5379 - connect to backend --- frontend/src/v5/services/api/tickets.ts | 44 +++---------------------- 1 file changed, 5 insertions(+), 39 deletions(-) diff --git a/frontend/src/v5/services/api/tickets.ts b/frontend/src/v5/services/api/tickets.ts index 8d6e433241e..32457fa555a 100644 --- a/frontend/src/v5/services/api/tickets.ts +++ b/frontend/src/v5/services/api/tickets.ts @@ -14,45 +14,11 @@ * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ -import { ITicket, ITemplate, NewTicket, Group, PinIcon, PropertyDefinition } from '@/v5/store/tickets/tickets.types'; +import { ITicket, ITemplate, NewTicket, Group } from '@/v5/store/tickets/tickets.types'; import api from './default'; -import { isObject } from 'lodash'; export const modelType = (isFed: boolean) => (isFed ? 'federations' : 'containers'); -/*************** TEMPORAL CODE FOR MOCKING PIN ICONS *****************/ -const templates = {}; -const pinIcons = [ 'DEFAULT', 'ISSUE', 'RISK', 'MARKER']; -let pinIndex = 0; - -const getCoords = (properties: PropertyDefinition[]) => (properties || []).filter((p) => p.type === 'coords'); - -const fillDummyIconInProp = (prop) => ( { ...prop, icon: pinIcons[(pinIndex++) % 4] }); - -const fillDummyPinIcon = (template:ITemplate): ITemplate => { - if (templates[template._id]) return templates[template._id]; - - - if (template?.config?.pin) { - if (isObject(template.config.pin)) { - template.config.pin.icon = pinIcons[(pinIndex++) % 4] as PinIcon; - } else { - template.config.pin = fillDummyIconInProp(template.config.pin); - } - } - - getCoords(template?.properties).forEach((p) => Object.assign(p, fillDummyIconInProp(p))); - - template?.modules?.forEach((module) => { - getCoords(module.properties).forEach((p) => Object.assign(p, fillDummyIconInProp(p))); - }); - - return template; -}; - -/*********************************************************************/ - - export const fetchContainerTemplates = async ( teamspace: string, projectId: string, @@ -60,7 +26,7 @@ export const fetchContainerTemplates = async ( getDetails?: boolean, ): Promise => { const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/containers/${containerId}/tickets/templates?getDetails=${getDetails}`); - return data.templates.map(fillDummyPinIcon); + return data.templates; }; export const fetchContainerTemplate = async ( @@ -70,7 +36,7 @@ export const fetchContainerTemplate = async ( templateId:string, ): Promise => { const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/containers/${containerId}/tickets/templates/${templateId}`); - return fillDummyPinIcon(data); + return data; }; export const fetchFederationTemplates = async ( @@ -80,7 +46,7 @@ export const fetchFederationTemplates = async ( getDetails?: boolean, ): Promise => { const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/federations/${federationId}/tickets/templates?getDetails=${getDetails}`); - return data.templates.map(fillDummyPinIcon); + return data.templates; }; export const fetchFederationTemplate = async ( @@ -90,7 +56,7 @@ export const fetchFederationTemplate = async ( templateId: string, ): Promise => { const { data } = await api.get(`teamspaces/${teamspace}/projects/${projectId}/federations/${federationId}/tickets/templates/${templateId}`); - return fillDummyPinIcon(data); + return data; }; export const fetchContainerTickets = async ( From 337068625cd33e6fc0f3280c5e46729c80f085d7 Mon Sep 17 00:00:00 2001 From: Charence <1438332+Charence@users.noreply.github.com> Date: Tue, 18 Feb 2025 13:20:31 +0000 Subject: [PATCH 17/19] ISSUE #5414 - install expect --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3b70c05b948..4e7f3cf3ade 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ matrix: before_install: - sudo apt remove mongodb && sudo apt purge mongodb && sudo apt autoremove && sudo rm -rf /var/lib/mongodb - - sudo apt-get -y install gnupg curl + - sudo apt-get -y install gnupg curl expect - curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor - echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list - sudo apt-get update From 256cf7c84edd38ed70c0e9aa9bd8049279762b02 Mon Sep 17 00:00:00 2001 From: Carmen Fan Date: Thu, 20 Feb 2025 11:11:04 +0000 Subject: [PATCH 18/19] ISSUE #5418 kill the server if we run into Topology is closed --- backend/src/v4/response_codes.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/backend/src/v4/response_codes.js b/backend/src/v4/response_codes.js index f5c20d7b330..21e2543c65e 100644 --- a/backend/src/v4/response_codes.js +++ b/backend/src/v4/response_codes.js @@ -416,6 +416,10 @@ */ responseCodes.respond = function (place, req, res, next, resCode, extraInfo, format, cache, customHeaders) { + // Topology is closed mongo error is typically coming from the session management and the library + // doesn't let us recover from it (so far). So kill this pod and let it respawn. + const killServer = resCode?.name === "MongoError" && resCode?.message?.includes && resCode.message.includes("Topology is closed") ? resCode : false; + resCode = utils.mongoErrorToResCode(resCode); if (!resCode || valid_values.indexOf(resCode.value) === -1) { @@ -490,6 +494,10 @@ // log bandwidth and http status code systemLogger.logInfo(genResponseLogging(resCode, meta, req), undefined, logLabels.network); } + + if (killServer) { + return Promise.reject(killServer); + } }; responseCodes.writeStreamRespond = function (place, req, res, next, readStream, customHeaders) { From 65fa8db70779c6542bfb10729b6dc53cca3f4726 Mon Sep 17 00:00:00 2001 From: Carmen Fan Date: Thu, 20 Feb 2025 14:31:49 +0000 Subject: [PATCH 19/19] Version 5.14.2 --- backend/VERSION.json | 2 +- backend/package.json | 2 +- backend/src/v4/routes/apidoc.json | 2 +- frontend/package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/VERSION.json b/backend/VERSION.json index 9a78a2190c5..35ff3eaf152 100644 --- a/backend/VERSION.json +++ b/backend/VERSION.json @@ -1,4 +1,4 @@ -{ "VERSION" : "5.14.1", +{ "VERSION" : "5.14.2", "unity" : { "current" : "5.20.0", "supported": [] diff --git a/backend/package.json b/backend/package.json index 35c9f9b13b5..7bd6718977d 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "3drepo.io", - "version": "5.14.1", + "version": "5.14.2", "engines": { "node": "18.x.x" }, diff --git a/backend/src/v4/routes/apidoc.json b/backend/src/v4/routes/apidoc.json index 9bd8c0b0653..62ccda57b0c 100644 --- a/backend/src/v4/routes/apidoc.json +++ b/backend/src/v4/routes/apidoc.json @@ -1,3 +1,3 @@ { - "version": "5.14.1" + "version": "5.14.2" } diff --git a/frontend/package.json b/frontend/package.json index a6c2a266744..d3b42878364 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "3drepo.io-frontend", - "version": "5.14.1", + "version": "5.14.2", "description": "The frontend for 3drepo.io", "engines": { "node": "18.x.x"