diff --git a/apps/piping/app.config.js b/apps/piping/app.config.js index 6905e5016..ae3380f62 100644 --- a/apps/piping/app.config.js +++ b/apps/piping/app.config.js @@ -9,6 +9,8 @@ export default () => ({ }, environment: { uri: 'https://backend-fusion-data-gateway-test.radix.equinor.com', + electricalUri: + 'https://electrical-consumers-fusion-data-gateway-test.radix.equinor.com', defaultScopes: ['api://ed6de162-dd30-4757-95eb-0ffc8d34fbe0/access_as_user'], }, endpoints: {}, diff --git a/apps/piping/app.config.local.js b/apps/piping/app.config.local.js index c10cb7c95..c02db8223 100644 --- a/apps/piping/app.config.local.js +++ b/apps/piping/app.config.local.js @@ -9,6 +9,9 @@ export default () => ({ }, environment: { uri: 'https://localhost:7074', + electricalUri: + 'https://electrical-consumers-fusion-data-gateway-test.radix.equinor.com', + // electricalUri: 'https://localhost:7075', defaultScopes: ['api://ed6de162-dd30-4757-95eb-0ffc8d34fbe0/access_as_user'], }, endpoints: {}, diff --git a/libs/heattraceapp/src/lib/config/tableConfig.tsx b/libs/heattraceapp/src/lib/config/tableConfig.tsx index f5896add5..d3a0f12ee 100644 --- a/libs/heattraceapp/src/lib/config/tableConfig.tsx +++ b/libs/heattraceapp/src/lib/config/tableConfig.tsx @@ -9,7 +9,9 @@ import { DateCell, DescriptionCell, LinkCell, + StatusCircle, StyledMonospace, + pipetestStatusColormap, useHttpClient, } from '@cc-components/shared'; @@ -76,7 +78,19 @@ const columnDefinitions: [ColDef, ...ColDef[]] = [ }, }, // Need to implement the visual checklistStatus - { headerName: 'Checklist status', valueGetter: (pkg) => pkg.data?.formStatus }, + { + headerName: 'Checklist status', + valueGetter: (pkg) => pkg.data?.formStatus, + cellRenderer: (props: ICellRendererProps) => { + if (!props.data?.formStatus) return null; + return ( + + ); + }, + }, { headerName: 'Current step', valueGetter: (pkg) => pkg.data?.checklistStep }, { headerName: 'RFC', diff --git a/libs/heattraceshared/src/lib/types/heatTraceChecklist.ts b/libs/heattraceshared/src/lib/types/heatTraceChecklist.ts index f7a66ff1a..04f5d4e63 100644 --- a/libs/heattraceshared/src/lib/types/heatTraceChecklist.ts +++ b/libs/heattraceshared/src/lib/types/heatTraceChecklist.ts @@ -48,6 +48,7 @@ export type HeatTraceChecklist = { checklistUrl: string | null; commissioningPackageUrl: string | null; mechanicalCompletionUrl: string | null; + tagUrl: string | null; pipingRevisionMechanicalCompletionPackageNo: string; register: string; }; diff --git a/libs/heattracesidesheet/src/lib/ui-sidesheet/HeattraceSidesheet.tsx b/libs/heattracesidesheet/src/lib/ui-sidesheet/HeattraceSidesheet.tsx index f85c4257c..7498fca77 100644 --- a/libs/heattracesidesheet/src/lib/ui-sidesheet/HeattraceSidesheet.tsx +++ b/libs/heattracesidesheet/src/lib/ui-sidesheet/HeattraceSidesheet.tsx @@ -4,8 +4,11 @@ import { useMemo, useRef } from 'react'; import { useGetWorkorders } from '../utils-sidesheet'; import { WorkorderTab } from '@cc-components/shared/sidesheet'; import { + BaseStatus, ElectricalNetwork, LinkCell, + StatusCircle, + statusColorMap, useContextId, useHttpClient, } from '@cc-components/shared'; @@ -44,19 +47,18 @@ const HeattraceSidesheetComponent = (props: Required) => { /> - ) : ( - 'N/A' - ) + } - > - + /> [] = [ headerName: 'Tag No', valueGetter: (pkg) => pkg.data?.tagNo, cellRenderer: (props: ICellRendererProps) => { - return ( - - ); + return ; }, }, { @@ -26,6 +24,10 @@ export const checklistColumns: ColDef[] = [ ); }, }, + { + headerName: 'Formular group', + valueGetter: (pkg) => pkg.data?.formularGroup, + }, { headerName: 'Responsible', valueGetter: (pkg) => pkg.data?.formResponsible, diff --git a/libs/pipingapp/src/lib/config/frameworkConfig.ts b/libs/pipingapp/src/lib/config/frameworkConfig.ts index d44f536d6..83a427f95 100644 --- a/libs/pipingapp/src/lib/config/frameworkConfig.ts +++ b/libs/pipingapp/src/lib/config/frameworkConfig.ts @@ -20,7 +20,6 @@ export const configure = async (config: IAppConfigurator, c: ComponentRenderArgs }); }); }); - // Add more config if needed, e.g. enableAgGrid const envConfig: PipingEnvConfig = c.env.config?.environment as PipingEnvConfig; @@ -32,10 +31,16 @@ export const configure = async (config: IAppConfigurator, c: ComponentRenderArgs defaultScopes: envConfig?.defaultScopes, }); + config.configureHttpClient('electrical-api', { + baseUri: envConfig?.electricalUri, + defaultScopes: envConfig?.defaultScopes, + }); + enableAgGrid(config); }; type PipingEnvConfig = { uri: string; + electricalUri: string; defaultScopes: string[]; }; diff --git a/libs/pipingapp/src/lib/config/gardenConfig.tsx b/libs/pipingapp/src/lib/config/gardenConfig.tsx index 4a0215a9b..b22945a1b 100644 --- a/libs/pipingapp/src/lib/config/gardenConfig.tsx +++ b/libs/pipingapp/src/lib/config/gardenConfig.tsx @@ -25,10 +25,13 @@ export const useGardenConfig = ( getGardenMeta, getHeader, getSubgroupItems, - getDisplayName: (item) => item.id, - initialGrouping: ['Priority1'], + getDisplayName: (item) => item.pipetestNo, + initialGrouping: ['RFC'], customViews: { customItemView: GardenItem as any, }, + visuals: { + rowHeight: 31, + }, }; }; diff --git a/libs/pipingapp/src/lib/config/tableConfig.tsx b/libs/pipingapp/src/lib/config/tableConfig.tsx index 1b693f152..a536e3454 100644 --- a/libs/pipingapp/src/lib/config/tableConfig.tsx +++ b/libs/pipingapp/src/lib/config/tableConfig.tsx @@ -1,18 +1,21 @@ import { ColDef, GridConfig, ICellRendererProps } from '@equinor/workspace-fusion/grid'; -import { CheckList, Pipetest } from '@cc-components/pipingshared'; +import { Pipetest } from '@cc-components/pipingshared'; import { FilterState } from '@equinor/workspace-fusion/filter'; import { defaultGridOptions, useGridDataSource, } from '@cc-components/shared/workspace-config'; import { + BaseStatus, DateCell, DescriptionCell, - StyledMonospace, + LinkCell, + StatusCircle, + domainNames, + pipetestStatusColormap, useHttpClient, } from '@cc-components/shared'; -import { generateCommaSeperatedStringArrayColumn } from '../utils-table/generateCommaSeperatedStringArrayColumn'; -import { getHTList } from '../utils-table/tableHelpers'; +import { generateCommaSeperatedString } from '../utils-table/tableHelpers'; export const useTableConfig = (contextId: string): GridConfig => { const client = useHttpClient(); @@ -46,47 +49,109 @@ export const useTableConfig = (contextId: string): GridConfig, ...ColDef[]] = [ { headerName: 'Pipetest', - valueGetter: (pkg) => pkg.data?.id, - cellRenderer: (props: ICellRendererProps) => { - return {props.value}; - }, + colId: 'pipetestNo', + valueGetter: (element) => element.data?.pipetestNo, + cellRenderer: (props: ICellRendererProps) => ( + + ), }, { headerName: 'Description', colId: 'description', - valueGetter: (pkg) => pkg.data?.description, + valueGetter: (element) => element.data?.description, + cellRenderer: (props: ICellRendererProps) => ( + + ), + width: 300, + }, + { + headerName: domainNames.commPriority1, + colId: 'priority1', + valueGetter: (element) => element.data?.priority1, + }, + { + headerName: domainNames.commPriority2, + colId: 'priority2', + valueGetter: (element) => element.data?.priority2, + }, + { + headerName: domainNames.commPriority3, + colId: 'priority3', + valueGetter: (element) => element.data?.priority3, + }, + { + headerName: domainNames.mcLocation, + colId: 'location', + valueGetter: (element) => element.data?.location, + }, + { + headerName: domainNames.mcStatus, + colId: 'MechanicalCompletionStatus', + valueGetter: (element) => element.data?.mechanicalCompletionStatus, cellRenderer: (props: ICellRendererProps) => { - return ; + if (!props.value) return; + return ( + + ); }, - width: 300, }, - { headerName: 'Priority', valueGetter: (pkg) => pkg.data?.commPkPriority1 }, { - headerName: 'Location', - valueGetter: (pkg) => pkg.data?.location, - cellRenderer: (props: ICellRendererProps) => { - return {props.value}; + headerName: domainNames.checklistStatus, + colId: 'formStatus', + valueGetter: (element) => element.data?.formStatus, + cellRenderer: (props: ICellRendererProps) => { + if (!props.value) return; + return ( + + ); }, }, - { headerName: 'Checklist status', valueGetter: (pkg) => 't.b.d :D' }, - { headerName: 'Current step', valueGetter: (pkg) => 't.b.d :D' }, + { + headerName: domainNames.currentStep, + colId: 'currentStep', + valueGetter: (element) => element.data?.checklistStep, + }, { headerName: 'RFC', - valueGetter: (pkg) => pkg.data?.rfccPlanned, + colId: 'rfCPlannedForecastDate', + valueGetter: (element) => element.data?.rfCPlannedForecastDate, cellRenderer: (props: ICellRendererProps) => { return props.value ? : null; }, }, + { + headerName: domainNames.commIdentifier, + colId: 'commIdentifier', + valueGetter: (element) => '', // TODO: Add this once it is ready in the backend + }, + { + headerName: 'MC Handover Status', + colId: 'mechanicalCompletionHandoverStatus', + valueGetter: (element) => '', // TODO: Add this once it is ready in the backend + }, + { + headerName: domainNames.mcResponsible, + colId: 'mechanicalCompletionResponsible', + valueGetter: (element) => element.data?.mechanicalCompletionResponsible, + }, + { + headerName: domainNames.mcPhase, + colId: 'mechanicalCompletionPhase', + valueGetter: (element) => '', // TODO: Add this once it is ready in the backend + }, { headerName: 'HT cables', - valueGetter: (pkg) => pkg.data?.checkLists, - cellRenderer: (props: ICellRendererProps) => { - if (!props.value) return null; - return ( - - {generateCommaSeperatedStringArrayColumn(getHTList(props.value))} - - ); + colId: 'heatTraceCableNos', + valueGetter: (element) => element.data?.heatTraceCableNos, + cellRenderer: (props: ICellRendererProps) => { + const values = generateCommaSeperatedString(props.data?.heatTraceCableNos ?? []); + return ; }, }, -]; +]; \ No newline at end of file diff --git a/libs/pipingapp/src/lib/config/workspaceConfig.tsx b/libs/pipingapp/src/lib/config/workspaceConfig.tsx index 2a2de8a52..e5395cd38 100644 --- a/libs/pipingapp/src/lib/config/workspaceConfig.tsx +++ b/libs/pipingapp/src/lib/config/workspaceConfig.tsx @@ -31,6 +31,7 @@ export const WorkspaceWrapper = () => { if (isLoading) { return ; } + return ( ) => { const [isOpen, setIsOpen] = useState(false); @@ -33,6 +35,8 @@ const PipetestGardenItem = (props: CustomItemView) => { const width = useMemo(() => (depth ? 100 - depth * 3 : 100), [depth]); const maxWidth = useMemo(() => itemWidth * 0.98, [itemWidth]); + const colors = getPipetestStatusColors(data); + return ( <> @@ -46,45 +50,42 @@ const PipetestGardenItem = (props: CustomItemView) => { hoverTimeout && clearTimeout(hoverTimeout); setIsOpen(false); }} - backgroundColor={'green'} + backgroundColor={colors.backgroundColor} onClick={onClick} style={{ width: `${columnExpanded ? 100 : width}%`, maxWidth }} isSelected={isSelected} > - {displayName.replace('@PIPETEST-', '')} + {displayName} {columnExpanded && ( - - {data.description} - + {data.description} )} - {/* {isOpen && ( + {isOpen && ( - - - )} */} + popoverTitle={data.description} + close={() => setIsOpen(false)} + /> + )} ); }; diff --git a/libs/pipingapp/src/lib/ui-garden/garden.styles.ts b/libs/pipingapp/src/lib/ui-garden/garden.styles.ts index 8663d3f49..41eeb5451 100644 --- a/libs/pipingapp/src/lib/ui-garden/garden.styles.ts +++ b/libs/pipingapp/src/lib/ui-garden/garden.styles.ts @@ -45,30 +45,26 @@ type StatusCirclesProps = { }; export const StyledStatusCircles = styled.div` display: flex; - grid-column: 2/3; + grid-column: 3/4; justify-content: end; align-items: center; ::before { - width: ${(props) => (props.mcColor ? '12px' : '13px')}; - height: ${(props) => (props.mcColor ? '12px' : '13px')}; - border: ${(props) => (props.mcColor ? '1px solid white' : `none`)}; - background-color: ${(props) => props.mcColor ?? 'white'}; + width: 12px; + height: 12px; + border: 1px solid white; + background-color: ${(props) => props.mcColor}; border-radius: 50%; margin: 0px 1px; - outline: ${(props) => (props.mcColor ? 'none' : `1px dashed gray`)}; - outline-offset: -1px; content: ' '; } ::after { - width: ${(props) => (props.commColor ? '12px' : '13px')}; - height: ${(props) => (props.commColor ? '12px' : '13px')}; - border: ${(props) => (props.commColor ? '1px solid white' : `none`)}; - background-color: ${(props) => props.commColor ?? 'white'}; + width: 12px; + height: 12px; + border: 1px solid white; + background-color: ${(props) => props.commColor}; border-radius: 50%; margin: 0px 1px; - outline: ${(props) => (props.commColor ? 'none' : `1px dashed gray`)}; - outline-offset: -2px; content: ' '; } `; diff --git a/libs/pipingapp/src/lib/utils-garden/getPipetestStatusColors.ts b/libs/pipingapp/src/lib/utils-garden/getPipetestStatusColors.ts new file mode 100644 index 000000000..88935009e --- /dev/null +++ b/libs/pipingapp/src/lib/utils-garden/getPipetestStatusColors.ts @@ -0,0 +1,12 @@ +import { Pipetest } from '@cc-components/pipingshared'; +import { pipetestStatusColormap } from '@cc-components/shared/mapping'; +import { BaseStatus } from 'libs/shared/dist/src/packages'; + +type PackageStatusReturn = { + backgroundColor: string; +}; + +export const getPipetestStatusColors = (data: Pipetest): PackageStatusReturn => { + const backgroundColor = pipetestStatusColormap[data.formStatus as BaseStatus]; + return { backgroundColor }; +}; diff --git a/libs/pipingapp/src/lib/utils-table/generateCommaSeperatedStringArrayColumn.ts b/libs/pipingapp/src/lib/utils-table/generateCommaSeperatedStringArrayColumn.ts deleted file mode 100644 index 6e73ceb9a..000000000 --- a/libs/pipingapp/src/lib/utils-table/generateCommaSeperatedStringArrayColumn.ts +++ /dev/null @@ -1,15 +0,0 @@ -export function generateCommaSeperatedStringArrayColumn( - stringArray: string[], - maxLength?: number -): string { - if (stringArray.length === 0) { - return ''; - } - const length = maxLength ?? 3; - let commaString = stringArray.slice(0, length).join(', '); - - if (stringArray.length > length) { - commaString += ' (+' + (stringArray.length - length).toString() + ')'; - } - return commaString; -} diff --git a/libs/pipingapp/src/lib/utils-table/tableHelpers.ts b/libs/pipingapp/src/lib/utils-table/tableHelpers.ts index 6f6035fd5..9123c2d7e 100644 --- a/libs/pipingapp/src/lib/utils-table/tableHelpers.ts +++ b/libs/pipingapp/src/lib/utils-table/tableHelpers.ts @@ -1,5 +1,9 @@ -import { CheckList } from '@cc-components/pipingshared'; +export const generateCommaSeperatedString = (array: string[], length: number = 3): string => { + const value = array.slice(0, length).join(', '); -export function getHTList(checkLists: CheckList[]): string[] { - return checkLists.filter((x) => x.isHeatTrace).map((ht: CheckList) => ht.tagNo); -} + if (array.length > length) { + return `${value} (+${array.length - length})`; + } + + return value; +}; diff --git a/libs/pipingshared/src/lib/types/drcEnums.ts b/libs/pipingshared/src/lib/types/drcEnums.ts deleted file mode 100644 index 8d6a04360..000000000 --- a/libs/pipingshared/src/lib/types/drcEnums.ts +++ /dev/null @@ -1,80 +0,0 @@ -export enum PipetestStep { - Unknown = 'Unknown', - Bolttensioning = 'Bolt tensioning', - PressureTest = 'Pressure test', - ChemicalCleaning = 'Chemical cleaning', - HotOilFlushing = 'Hot oil flushing', - Painting = 'Painting', - HtTest = 'A-test', - Insulation = 'Insulation', - BoxInsulation = 'Box insulation', - HtRetest = 'B-test', - HtCTest = 'C-test', - Marking = 'Marking', - Complete = 'Complete', -} - -export enum CheckListStepTag { - Unknown = '#U', - Bolttensioning = '#B', - PressureTest = '#T', - ChemicalCleaning = '#C', - HotOilFlushing = '#H', - Painting = '#X', - HtTest = 'ELE19.1', - Insulation = '#Z', - BoxInsulation = '#I', - HtRetest = 'ELE19.2', - HtCTest = 'ELE19.3', - HtTemporary = 'ELE99', - Marking = '#M', - Complete = 'C', -} - -export enum CheckListStatus { - OK = 'OK', - Outstanding = 'OS', - PunchAError = 'PA', - PunchBError = 'PB', - Inactive = 'IN', -} - -export enum PipetestCompletionStatus { - Complete = 'Complete', - Outstanding = 'Outstanding', - PunchAError = 'PunchAError', - PunchBError = 'PunchBError', - Inactive = 'Inactive', -} - -export enum PipetestCheckListOrder { - Unknown = 0, - PressureTest = 1, - ChemicalCleaning = 2, - HotOilFlushing = 3, - Bolttensioning = 4, - Painting = 5, - HtTest = 6, - Insulation = 7, - BoxInsulation = 8, - HtRetest = 9, - HtCTest = 10, - Marking = 11, - Complete = 12, -} - -export enum PipetestStatusOrder { - Unknown = 0, - PressureTest = 1, - ChemicalCleaning = 2, - HotOilFlushing = 3, - Bolttensioning = 4, - Painting = 5, - HtTest = 6, - Insulation = 7, - BoxInsulation = 8, - HtRetest = 9, - HtCTest = 10, - Marking = 11, - Complete = 12, -} diff --git a/libs/pipingshared/src/lib/types/index.ts b/libs/pipingshared/src/lib/types/index.ts index 56ed88290..50351370d 100644 --- a/libs/pipingshared/src/lib/types/index.ts +++ b/libs/pipingshared/src/lib/types/index.ts @@ -1,2 +1 @@ export * from './pipetest'; -export * from './drcEnums'; diff --git a/libs/pipingshared/src/lib/types/pipetest.ts b/libs/pipingshared/src/lib/types/pipetest.ts index 6f8f819f4..a854d1d9f 100644 --- a/libs/pipingshared/src/lib/types/pipetest.ts +++ b/libs/pipingshared/src/lib/types/pipetest.ts @@ -1,113 +1,58 @@ -import { CheckListStatus, PipetestCompletionStatus, PipetestStep } from './drcEnums'; - export type Pipetest = { id: string; - step: PipetestStep; - htStep: PipetestStep; - circuitStep: PipetestStep; - steps: PipetestStep[]; - completionStatus: PipetestCompletionStatus; - pipetestProcessDoneInRightOrder: boolean; - shortformCompletionStatus: CheckListStatus; - checkLists: CheckList[]; - heatTraces: HeatTrace[]; - insulationBoxes: InsulationBox[]; - pipeInsulationBoxes: InsulationBox[]; - circuits: Circuit[]; + pipetestNo: string; + pipetestType: string; + facility: string; + project: string; + location: string; description: string; - commPkPriority1: string; - rfccPlanned: string; - htCableRfc: string; - overdue: string; + rfCPlannedForecastDate: string; + m03PlannedForecastDate: string; + signedDate: string; + mechanicalCompletionUrlId: string; + mechanicalCompletionResponsible: string; + mechanicalCompletionStatus: string; + mechanicalCompletionId: string; + commissioningPackageUrlId: string; + commissioningResponsible: string; + commissioningStatus: string; + commissioningPackageNo: string; dueDateTimePeriod: string; - location: string; - lines: Line[]; - hasCriticalLine: boolean; - mcPkgId: string; - mcPkgUrlId: string; - hasDisconnectedEquipment: boolean; - hasIsolatedEquipment: boolean; - htCableExposed: string | null; -}; - -export type CheckList = { + isOverdue: string; + checklistStep: string; + formStatus: string; + checklistStepSequence: number; + priority1: string; + priority2: string; + priority3: string; + projectDescription: string; + projectSchema?: string; + heatTraceCableIds: string[]; + heatTraceCableNos: string[]; + commissioningPackageUrl?: string; + mechanicalCompletionUrl?: string; +}; + +export type Checklist = { + checklistId: string; + checklistUrlId: string; tagNo: string; - responsible: string; + tagUrlId: string; + revision: string; formularType: string; - formularGroup: string; - status: string; - revision?: string; - test?: string; - isHeatTrace?: boolean; - workflowStepText?: string | undefined; - stepName?: string; - c01Planned?: string; - c01Forecast?: string; - m03Planned?: string; - m03Forecast?: string; - m04Actual?: string; - underline?: string; - signedDate?: string; - worstPipetestStep?: PipetestStep; -}; - -export type InsulationBox = { - objectNo: string; - objectName: string; - objectStatusName: string; - objectStatus: string; - object3dReference: string; - procosysStatus: string; -}; - -export type Circuit = { - switchBoardTagNo: string; - circuitAndStarterTagNo: string; - checkLists: CheckList[]; - worstPipetestStep?: PipetestStep; -}; - -export type HeatTrace = CheckList; - -export type CheckListType = { - tagNo: string; responsible: string; - formularType: string; - formularGroup: string; status: string; - revision?: string; - test?: string; - isHeatTrace?: boolean; - workflowStepText?: string | undefined; + checklistUrl: string; + tagUrl: string; }; -export type InsulationBoxType = { - objectNo: string; - objectName: string; - objectStatusName: string; - objectStatus: string; - object3dReference: string; - procosysStatus: string; +export type InsulationTagResponse = { + pipeInsulationTags: InsulationTag[]; + boxInsulationTags: InsulationTag[]; }; -export type Line = { +export type InsulationTag = { tagNo: string; - isCritical: boolean; -}; - -export type HTSidesheet = { - value: string; - items: Pipetest[]; -}; - -export type HeatTraceGrouped = { - htTagNo: string; - pipetests: Pipetest[]; - count: number; -}; - -export type CircuitGrouped = { - circuitTagNo: string; - pipetests: Pipetest[]; - count: number; + description: string; + status: string; }; diff --git a/libs/pipingsidesheet/src/lib/types/index.ts b/libs/pipingsidesheet/src/lib/types/index.ts deleted file mode 100644 index 643cc5c55..000000000 --- a/libs/pipingsidesheet/src/lib/types/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './workorder'; diff --git a/libs/pipingsidesheet/src/lib/types/workorder.ts b/libs/pipingsidesheet/src/lib/types/workorder.ts deleted file mode 100644 index 73bc56f03..000000000 --- a/libs/pipingsidesheet/src/lib/types/workorder.ts +++ /dev/null @@ -1,23 +0,0 @@ -export type Workorder = { - actualCompletionDate: string | null; - description: string | null; - discipline: string | null; - disciplineDescription: string | null; - estimatedManHours: number | null; - facility: string | null; - holdBy: string | null; - jobStatus: string | null; - loopId: string | null; - loopNo: string | null; - materialStatus: string | null; - plannedCompletionDate: string | null; - project: string | null; - projectProgress: number | null; - remainingManHours: number | null; - responsible: string | null; - responsibleDescription: string | null; - title: string | null; - workOrderId: string; - workOrderNo: string; - workOrderUrlId: string; -}; \ No newline at end of file diff --git a/libs/pipingsidesheet/src/lib/ui-sidesheet/ChecklistTab.tsx b/libs/pipingsidesheet/src/lib/ui-sidesheet/ChecklistTab.tsx index de1c6f3cb..2bda9ccae 100644 --- a/libs/pipingsidesheet/src/lib/ui-sidesheet/ChecklistTab.tsx +++ b/libs/pipingsidesheet/src/lib/ui-sidesheet/ChecklistTab.tsx @@ -1,13 +1,14 @@ import { TabTable } from '@cc-components/shared'; import { StyledContentWrapper } from '@cc-components/sharedcomponents'; -import { CheckList } from '@cc-components/pipingshared'; +import { Checklist } from '@cc-components/pipingshared'; import { checklistColumns } from './checklistColumns'; type ChecklistTabProps = { - checklists: CheckList[] | undefined; + checklists: Checklist[] | undefined; isFetching: boolean; error: Error | null; }; + export const ChecklistTab = ({ checklists, error, @@ -15,7 +16,6 @@ export const ChecklistTab = ({ }: ChecklistTabProps): JSX.Element => { return ( - {checklists ?

Pipetest checklist:

: ''} { + const { networks, isFetching, itemNo } = props; + + if (isFetching) { + return ; + } + + if (!networks || networks.length < 1) { + return ( + + + No Circuit Diagram found + + ); + } + + const diagrams = networks.map((network) => ( + + )); + + return {diagrams}; +}; diff --git a/libs/pipingsidesheet/src/lib/ui-sidesheet/InsultaionTab.tsx b/libs/pipingsidesheet/src/lib/ui-sidesheet/InsultaionTab.tsx index 958e7a805..0f21644d3 100644 --- a/libs/pipingsidesheet/src/lib/ui-sidesheet/InsultaionTab.tsx +++ b/libs/pipingsidesheet/src/lib/ui-sidesheet/InsultaionTab.tsx @@ -1,36 +1,35 @@ -import { InsulationBox } from '@cc-components/pipingshared'; +import { InsulationTagResponse } from '@cc-components/pipingshared'; import { TabTable } from '@cc-components/shared'; import { StyledContentWrapper } from '@cc-components/sharedcomponents'; import { insulationsColumns } from './insulationsColumns'; type InsulationTabProps = { - pipeInsulations: InsulationBox[] | undefined; - boxInsulations: InsulationBox[] | undefined; + insulationTags: InsulationTagResponse | undefined; isFetching: boolean; error: Error | null; }; + export const InsultaionTab = ({ - pipeInsulations, - boxInsulations, + insulationTags, error, isFetching, }: InsulationTabProps): JSX.Element => { return ( - {pipeInsulations ?

Pipe insulations:

: ''} + {insulationTags?.pipeInsulationTags ?

Pipe insulations:

: ''} - {boxInsulations ?

Box insulations:

: ''} + {insulationTags?.boxInsulationTags ?

Box insulations:

: ''}
diff --git a/libs/pipingsidesheet/src/lib/ui-sidesheet/PipingSidesheet.tsx b/libs/pipingsidesheet/src/lib/ui-sidesheet/PipingSidesheet.tsx index bfb3d5217..cc7790eb3 100644 --- a/libs/pipingsidesheet/src/lib/ui-sidesheet/PipingSidesheet.tsx +++ b/libs/pipingsidesheet/src/lib/ui-sidesheet/PipingSidesheet.tsx @@ -3,36 +3,47 @@ import { useState } from 'react'; import { Tabs } from '@equinor/eds-core-react'; import styled from 'styled-components'; import { tokens } from '@equinor/eds-tokens'; -import { WorkorderBase, WorkorderTab } from '@cc-components/shared/sidesheet'; -import { StatusCircle } from '@cc-components/shared/common'; -import { pipetestStatusColormap } from '@cc-components/shared/mapping'; -import { DateCell, useContextId, useHttpClient } from '@cc-components/shared'; +import { WorkorderTab } from '@cc-components/shared/sidesheet'; +import { + BaseStatus, + LinkCell, + StatusCircle, + pipetestStatusColormap, +} from '@cc-components/shared'; + import { BannerItem, SidesheetHeader, StyledBanner, - StyledPanels, StyledSideSheetContainer, - StyledTabs, + CustomStyledTabs, + CustomStyledPanels, TabTitle, + SidesheetSkeleton, } from '@cc-components/sharedcomponents'; + import { InsultaionTab } from './InsultaionTab'; import { ChecklistTab } from './ChecklistTab'; -const workorders: WorkorderBase[] = []; +import { useGetWorkorders } from '../utils-sidesheet'; +import { useGetChecklists } from '../utils-sidesheet/useGetChecklists'; +import { useGetPipetest } from '../utils-sidesheet/usePipetest'; +import { useGetInsulationTags } from '../utils-sidesheet/useGetInsulationTags'; +import { useElectricalNetworks } from '../utils-sidesheet/useElectricalNetwork'; +import { ElecticalNetworkTab } from './ElectricalNetworkTab'; export const StyledTabListWrapper = styled.div` overflow: hidden; width: 100%; background-color: ${tokens.colors.ui.background__light.hex}; `; + export const StyledTabsList = styled(Tabs.List)` overflow: auto; ::-webkit-scrollbar { width: 0; height: 0; } - scroll-behavior: smooth; `; @@ -42,32 +53,34 @@ type PipingProps = { close: VoidFunction; }; -export const PipingSidesheet = (props: PipingProps) => { +const PipingSidesheetContent = (props: Required) => { + const { item, close } = props; + const [activeTab, setActiveTab] = useState(0); - const client = useHttpClient(); - const contextId = useContextId(); - // const { data: pipetest } = useQuery( - // ['pipetest', props.id], - // async () => { - // const res = await client.fetch(`/api/contexts/${contextId}/pipetest/${props.id}`); - // if (!res.ok) { - // throw res; - // } - // return res.json(); - // }, - // { - // suspense: true, - // initialData: props.item, - // } - // ); - - const pipetest = props.item; - if (!pipetest) { - throw new Error('Pipetest undefined'); - } + const { + data: workorders, + isLoading: isLoadingWorkorders, + error: errorWorkorders, + } = useGetWorkorders(item.id); + + const { + data: checklists, + isLoading: isLoadingChecklists, + error: errorChecklists, + } = useGetChecklists(item.id); + + const { + data: insulationTags, + isLoading: isLoadingInsulationTags, + error: errorInsulationTags, + } = useGetInsulationTags(item.id); - // const { data, isLoading } = useGetWorkorders(pipetest.name); + const { + data: electricalNetworks, + isLoading: isLoadingElecticalNetworks, + error: errorElectricalNetworks, + } = useElectricalNetworks(item.facility, item.heatTraceCableNos); const handleChange = (index: number) => { setActiveTab(index); @@ -76,79 +89,114 @@ export const PipingSidesheet = (props: PipingProps) => { return ( - + ) : ( 'N/A' ) } - > + /> : 'N/A' + } /> - + Circuit diagram - Work orders + Work orders + Insulation - Checklists + Checklists + - 3D - - Circuit diagram is coming + + + + - + - 3D is coming - - + + ); }; + + +export const PipingSidesheet = (props: PipingProps) => { + const { id, item, close } = props; + + const { data, isLoading, error } = useGetPipetest(id, item) + + if (isLoading) { + return ; + } + + if (!data || error) { + return
Failed to get Pipetest with id: {id}
; + } + + return (); +}; diff --git a/libs/pipingsidesheet/src/lib/ui-sidesheet/checklistColumns.tsx b/libs/pipingsidesheet/src/lib/ui-sidesheet/checklistColumns.tsx index bb2ab2fbe..3a0db8f7f 100644 --- a/libs/pipingsidesheet/src/lib/ui-sidesheet/checklistColumns.tsx +++ b/libs/pipingsidesheet/src/lib/ui-sidesheet/checklistColumns.tsx @@ -3,40 +3,38 @@ import { StatusCircle, StyledMonospace, statusColorMap, + LinkCell } from '@cc-components/shared'; import { ColDef, ICellRendererProps } from '@equinor/workspace-ag-grid'; -import { CheckList } from '@cc-components/pipingshared'; +import { Checklist } from '@cc-components/pipingshared'; -export const checklistColumns: ColDef[] = [ +export const checklistColumns: ColDef[] = [ { - headerName: 'Tag', - valueGetter: (pkg) => pkg.data?.tagNo, - cellRenderer: (props: ICellRendererProps) => { - return {props.value}; + headerName: 'Tag No', + valueGetter: (item) => item.data?.tagNo, + cellRenderer: (props: ICellRendererProps) => { + return }, }, { headerName: 'Revision', - valueGetter: (pkg) => pkg.data?.revision, - cellRenderer: (props: ICellRendererProps) => { - return {props.value}; - }, + valueGetter: (item) => item.data?.revision, }, { headerName: 'Formular type', - valueGetter: (pkg) => pkg.data?.formularType, - cellRenderer: (props: ICellRendererProps) => { - return {props.value}; + valueGetter: (item) => item.data?.formularType, + cellRenderer: (props: ICellRendererProps) => { + return }, }, { headerName: 'Responsible', - valueGetter: (pkg) => pkg.data?.responsible, + valueGetter: (item) => item.data?.responsible, }, { headerName: 'Status', - valueGetter: (pkg) => pkg.data?.status, - cellRenderer: (props: ICellRendererProps) => { + valueGetter: (item) => item.data?.status, + cellRenderer: (props: ICellRendererProps) => { if (!props.data?.status) return null; return ( [] = [ +export const insulationsColumns: ColDef[] = [ { headerName: 'Pipe insulations', - valueGetter: (pkg) => pkg.data?.objectNo, - cellRenderer: (props: ICellRendererProps) => { + valueGetter: (element) => element.data?.tagNo, + cellRenderer: (props: ICellRendererProps) => { return {props.value}; }, }, { headerName: 'Description', - valueGetter: (pkg) => pkg.data?.objectName, - cellRenderer: (props: ICellRendererProps) => { + valueGetter: (element) => element.data?.description, + cellRenderer: (props: ICellRendererProps) => { return ; }, }, - { - headerName: 'Status', - valueGetter: (pkg) => pkg.data?.objectStatus, - cellRenderer: (props: ICellRendererProps) => { - return {props.value}; - }, - }, - { - headerName: 'Status name', - valueGetter: (pkg) => pkg.data?.objectStatusName, - }, { headerName: 'Checklist', - valueGetter: (pkg) => pkg.data?.procosysStatus, - cellRenderer: (props: ICellRendererProps) => { - if (!props.data?.procosysStatus) return null; + valueGetter: (element) => element.data?.status, + cellRenderer: (props: ICellRendererProps) => { + if (!props.data?.status) return null; return ( ); }, diff --git a/libs/pipingsidesheet/src/lib/utils-sidesheet/useElectricalNetwork.ts b/libs/pipingsidesheet/src/lib/utils-sidesheet/useElectricalNetwork.ts new file mode 100644 index 000000000..1e6f09cfa --- /dev/null +++ b/libs/pipingsidesheet/src/lib/utils-sidesheet/useElectricalNetwork.ts @@ -0,0 +1,41 @@ +import { useHttpClient } from '@equinor/fusion-framework-react-app/http'; +import { ElectricalNetwork, useContextId } from '@cc-components/shared'; + +import { useQuery } from '@tanstack/react-query'; + +export const useElectricalNetworks = (facility: string, tagNos: string[]) => { + const client = useHttpClient('electrical-api'); + const contextId = useContextId(); + + const { data, isLoading, error } = useQuery( + [facility, tagNos, 'electrical-networks'], + async ({ signal }) => { + const url = `api/contexts/${contextId}/electrical/consumers/electrical-network/${facility}`; + + const res = await client.fetch(url, { + method: 'POST', + signal, + body: JSON.stringify({ tagNos }), + headers: { + ['content-type']: 'application/json', + }, + }); + + if ([204, 404].includes(res.status)) { + return null; + } + + if (!res.ok) { + throw new Error('Failed to get elenetwork', { cause: res }); + } + + return res.json(); + } + ); + + return { + data, + isLoading, + error, + }; +}; diff --git a/libs/pipingsidesheet/src/lib/utils-sidesheet/useGetChecklists.ts b/libs/pipingsidesheet/src/lib/utils-sidesheet/useGetChecklists.ts new file mode 100644 index 000000000..7ed8974ea --- /dev/null +++ b/libs/pipingsidesheet/src/lib/utils-sidesheet/useGetChecklists.ts @@ -0,0 +1,24 @@ +import { useContextId, useHttpClient } from '@cc-components/shared'; +import { useQuery } from '@tanstack/react-query'; +import { Checklist } from '@cc-components/pipingshared'; + +export const useGetChecklists = (pipetestId: string) => { + const client = useHttpClient(); + const contextId = useContextId(); + + const { data, isLoading, error } = useQuery( + ['pipetest', pipetestId, 'checklists'], + async ({ signal }) => { + const response = await client.fetch( + `/api/contexts/${contextId}/pipetest/${pipetestId}/checklists`, + { signal } + ); + if (!response.ok) { + throw new Error('Failed to get checklists', { cause: response }); + } + return response.json(); + } + ); + + return { data, isLoading, error }; +}; diff --git a/libs/pipingsidesheet/src/lib/utils-sidesheet/useGetInsulationTags.ts b/libs/pipingsidesheet/src/lib/utils-sidesheet/useGetInsulationTags.ts new file mode 100644 index 000000000..524f93c0a --- /dev/null +++ b/libs/pipingsidesheet/src/lib/utils-sidesheet/useGetInsulationTags.ts @@ -0,0 +1,28 @@ +import { useContextId, useHttpClient } from '@cc-components/shared'; +import { useQuery } from '@tanstack/react-query'; +import { InsulationTagResponse } from '@cc-components/pipingshared'; + +export const useGetInsulationTags = (pipetestId: string) => { + const client = useHttpClient(); + const contextId = useContextId(); + + const { data, isLoading, error } = useQuery( + ['pipetest', pipetestId, 'insulation-tags'], + async ({ signal }) => { + const response = await client.fetch( + `/api/contexts/${contextId}/pipetest/${pipetestId}/insulation-tags`, + { signal } + ); + if (!response.ok) { + throw new Error('Failed to get insulation-tags', { cause: response }); + } + return response.json(); + } + ); + + return { + data: data, + isLoading: isLoading, + error: error, + }; +}; diff --git a/libs/pipingsidesheet/src/lib/utils-sidesheet/useGetWorkorders.ts b/libs/pipingsidesheet/src/lib/utils-sidesheet/useGetWorkorders.ts index d8bda2e25..7eb5288ec 100644 --- a/libs/pipingsidesheet/src/lib/utils-sidesheet/useGetWorkorders.ts +++ b/libs/pipingsidesheet/src/lib/utils-sidesheet/useGetWorkorders.ts @@ -1,22 +1,20 @@ -import { useHttpClient } from '@equinor/fusion-framework-react-app/http'; -import { useContextId } from '@cc-components/shared'; +import { WorkorderBase, useContextId, useHttpClient } from '@cc-components/shared'; import { useQuery } from '@tanstack/react-query'; -import { Workorder } from '../types'; -export const useGetWorkorders = (pipetestName: string) => { - const client = useHttpClient('cc-api'); +export const useGetWorkorders = (pipetestId: string) => { + const client = useHttpClient(); const contextId = useContextId(); - const { data, isLoading, error } = useQuery( - ['pipetest', pipetestName, 'workorders'], + const { data, isLoading, error } = useQuery( + ['pipetest', pipetestId, 'work-orders'], async ({ signal }) => { - const respons = await client.fetch( - `/api/contexts/${contextId}/pipetest/${pipetestName}/workorders`, + const response = await client.fetch( + `/api/contexts/${contextId}/pipetest/${pipetestId}/work-orders`, { signal } ); - if (!respons.ok) { - throw new Error(); + if (!response.ok) { + throw new Error('Failed to get work-orders', { cause: response }); } - return respons.json(); + return response.json(); } ); diff --git a/libs/pipingsidesheet/src/lib/utils-sidesheet/usePipetest.ts b/libs/pipingsidesheet/src/lib/utils-sidesheet/usePipetest.ts new file mode 100644 index 000000000..477ddbd2e --- /dev/null +++ b/libs/pipingsidesheet/src/lib/utils-sidesheet/usePipetest.ts @@ -0,0 +1,33 @@ +import { useHttpClient } from '@equinor/fusion-framework-react-app/http'; +import { useContextId } from '@cc-components/shared'; +import { useQuery } from '@tanstack/react-query'; +import { Pipetest } from '@cc-components/pipingshared'; + + +export const useGetPipetest = (pipetestId: string, initialData?: Pipetest) => { + const client = useHttpClient('cc-api'); + const contextId = useContextId(); + + const { data, isLoading, error } = useQuery( + ['pipetest', pipetestId], + async () => { + const res = await client.fetch(`/api/contexts/${contextId}/pipetest/${pipetestId}`); + if (!res.ok) { + throw res; + } + return res.json(); + }, + { + suspense: true, + initialData: initialData ?? undefined, + useErrorBoundary: false + } + ); + + return { + data: data, + isLoading: isLoading, + error: error, + }; + }; + \ No newline at end of file diff --git a/libs/shared/src/packages/fusion-framework/createRender.tsx b/libs/shared/src/packages/fusion-framework/createRender.tsx index be1167401..417485ea2 100644 --- a/libs/shared/src/packages/fusion-framework/createRender.tsx +++ b/libs/shared/src/packages/fusion-framework/createRender.tsx @@ -478,5 +478,13 @@ function ignorePowerBiGenericError(a: T) { ) { return false; } + if ( + a.name === 'Microsoft.ApplicationInsights.{0}.Exception' && + Object.keys(a.data ?? {}).includes('message') && + a.data?.message === + 'ErrorEvent: ResizeObserver loop completed with undelivered notifications.' + ) { + return false; + } return true; } diff --git a/libs/shared/src/packages/utils-domain/names.ts b/libs/shared/src/packages/utils-domain/names.ts index 47b68057f..fe5b41d0e 100644 --- a/libs/shared/src/packages/utils-domain/names.ts +++ b/libs/shared/src/packages/utils-domain/names.ts @@ -51,7 +51,7 @@ export const domainNames = { // Mechanical completion package mcDiscipline: `MC Discipline`, mcDisciplines: `MC Disciplines`, - mcLocation: `MC ${'Area'}`, + mcLocation: `MC ${'Location'}`, mcPhase: `MC ${'Phase'}`, mcPkg: 'Mc Pkg', mcResponsible: `MC ${'Responsible'}`, diff --git a/libs/sharedcomponents/src/packages/sidesheet/tabs/CustomTabs.tsx b/libs/sharedcomponents/src/packages/sidesheet/tabs/CustomTabs.tsx new file mode 100644 index 000000000..e4f522bbf --- /dev/null +++ b/libs/sharedcomponents/src/packages/sidesheet/tabs/CustomTabs.tsx @@ -0,0 +1,48 @@ +import { useState, useContext, createContext } from 'react'; +import { TabsProps, TabPanelsProps } from '@equinor/eds-core-react'; + +import { StyledTabs, StyledPanels } from './tabs.styles'; +import React from 'react'; + +// ########## Custom Tabs Context ########## + +const TabsContext = createContext(0); + +// ########## Custom Tabs ########## + +type CustomTabsProps = { + initialTabIndex?: number; +} + +type CustomProps = CustomTabsProps & TabsProps + +export const CustomStyledTabs = (props: CustomProps) => { + const [activeTab, setActiveTab] = useState(props.initialTabIndex ?? 0); + + const handleChange = (index: number) => { + setActiveTab(index); + if(props.onChange) props.onChange(index); + }; + + return ( + + + + ); +} + + +// ########## Custom Panels ########## + +export const CustomStyledPanels = (props: TabPanelsProps) => { + const activeTab = useContext(TabsContext); + + const panelChildren = React.Children.toArray(props.children); + + const children = panelChildren.map((child, index) => { + if(index == activeTab) return child; + return <> + }); + + return (); +} diff --git a/libs/sharedcomponents/src/packages/sidesheet/tabs/index.ts b/libs/sharedcomponents/src/packages/sidesheet/tabs/index.ts index e19612829..1a0e76a7c 100644 --- a/libs/sharedcomponents/src/packages/sidesheet/tabs/index.ts +++ b/libs/sharedcomponents/src/packages/sidesheet/tabs/index.ts @@ -1 +1,2 @@ export * from './Tabs'; +export * from './CustomTabs';