diff --git a/apps/heattrace/CHANGELOG.md b/apps/heattrace/CHANGELOG.md new file mode 100644 index 000000000..c7b0ef975 --- /dev/null +++ b/apps/heattrace/CHANGELOG.md @@ -0,0 +1,3 @@ +## Version 0.0.1 + +Init app diff --git a/apps/heattrace/README.md b/apps/heattrace/README.md new file mode 100644 index 000000000..724955f32 --- /dev/null +++ b/apps/heattrace/README.md @@ -0,0 +1,3 @@ +# heattrace + +Add readme diff --git a/apps/heattrace/app.config.js b/apps/heattrace/app.config.js new file mode 100644 index 000000000..6905e5016 --- /dev/null +++ b/apps/heattrace/app.config.js @@ -0,0 +1,15 @@ +import { readFileSync } from 'fs'; + +const { name } = JSON.parse(readFileSync('./package.json').toString('utf-8')); + +export default () => ({ + manifest: { + key: name, + name: name, + }, + environment: { + uri: 'https://backend-fusion-data-gateway-test.radix.equinor.com', + defaultScopes: ['api://ed6de162-dd30-4757-95eb-0ffc8d34fbe0/access_as_user'], + }, + endpoints: {}, +}); diff --git a/apps/heattrace/package.json b/apps/heattrace/package.json new file mode 100644 index 000000000..88a171ac8 --- /dev/null +++ b/apps/heattrace/package.json @@ -0,0 +1,23 @@ +{ + "name": "heat-trace", + "displayName": "Heat Trace", + "shortName": "heat-trace", + "version": "0.0.1", + "main": "/src/main.tsx", + "private": true, + "type": "module", + "scripts": { + "dev": "fusion-framework-cli app dev", + "build": "tsc -b -f", + "pr:deploy": "npx ts-node --esm ../../github-action/src/releasePr.ts release", + "fprd:deploy": "npx ts-node --esm ../../github-action/src/releaseMain.ts release" + }, + "dependencies": { + "@cc-components/heattraceapp": "workspace:^", + "@cc-components/shared": "workspace:^" + }, + "files": [ + "dist/app-bundle.js", + "app-manifest.json" + ] +} diff --git a/apps/heattrace/prod.skip b/apps/heattrace/prod.skip new file mode 100644 index 000000000..e69de29bb diff --git a/apps/heattrace/src/main.tsx b/apps/heattrace/src/main.tsx new file mode 100644 index 000000000..ca4584cde --- /dev/null +++ b/apps/heattrace/src/main.tsx @@ -0,0 +1,15 @@ +import { configure, WorkspaceWrapper } from '@cc-components/heattraceapp'; +import { useHttpClient } from '@equinor/fusion-framework-react-app/http'; +import { createRender, RootAppWrapper } from '@cc-components/shared'; + +const MyApp = () => { + const client = useHttpClient('cc-api'); + return ( + + + + ); +}; + +export const render = createRender(MyApp, configure); +export default render; diff --git a/apps/heattrace/tsconfig.app.json b/apps/heattrace/tsconfig.app.json new file mode 100644 index 000000000..8effb71fe --- /dev/null +++ b/apps/heattrace/tsconfig.app.json @@ -0,0 +1,22 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "types": ["node"], + "rootDir": "." + }, + "exclude": [ + "jest.config.ts", + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "dist", + "vite.config.ts" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/apps/heattrace/tsconfig.json b/apps/heattrace/tsconfig.json new file mode 100644 index 000000000..a6adc9189 --- /dev/null +++ b/apps/heattrace/tsconfig.json @@ -0,0 +1,22 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": true, + "esModuleInterop": true, + "allowSyntheticDefaultImports": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/apps/heattrace/vite.config.ts b/apps/heattrace/vite.config.ts new file mode 100644 index 000000000..30db614d0 --- /dev/null +++ b/apps/heattrace/vite.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'vite'; +import EnvironmentPlugin from 'vite-plugin-environment'; + +export default defineConfig({ + plugins: [ + EnvironmentPlugin({ + NODE_ENV: 'production', + }), + ], + appType: 'custom', + build: { + emptyOutDir: true, + lib: { + entry: './src/main.tsx', + fileName: 'app-bundle', + formats: ['es'], + }, + }, +}); diff --git a/libs/electricalconsumersapp/src/lib/config/ElectricalSidesheet.tsx b/libs/electricalconsumersapp/src/lib/config/ElectricalSidesheet.tsx index 6b7c6e39c..c634af9f9 100644 --- a/libs/electricalconsumersapp/src/lib/config/ElectricalSidesheet.tsx +++ b/libs/electricalconsumersapp/src/lib/config/ElectricalSidesheet.tsx @@ -55,9 +55,9 @@ export function ElectricalInnerSidesheet({ const client = useHttpClient(); const context = useContextId(); - const [itemId, facility, project] = id.split('_'); + const [itemNo, facility, project] = id.split('_'); - if (!facility || !itemId) { + if (!facility || !itemNo) { closeSidesheet(); return <>; } @@ -65,11 +65,11 @@ export function ElectricalInnerSidesheet({ const { data: elenetwork, isLoading: isLoadingEle } = useQuery( /**Change facility to project */ - /** facility*/ [itemId, facility, project], + /** facility*/ [itemNo, facility, project], async ({ signal }) => { const res = await client.fetch( `api/contexts/${context}/electrical/consumers/electrical-network/${encodeURIComponent( - itemId + itemNo )}/${facility}`, { signal } ); @@ -97,7 +97,7 @@ export function ElectricalInnerSidesheet({ /** facility*/ [id], async ({ signal }) => { const res = await client.fetch( - `api/contexts/${context}/electrical/consumers/${facility}/${project}/${itemId}`, + `api/contexts/${context}/electrical/consumers/${facility}/${project}/${itemNo}`, { signal } ); if (!res.ok) { @@ -148,7 +148,7 @@ export function ElectricalInnerSidesheet({ { if (reszied.current.hasResized) return; const newWidth = element.scrollWidth; diff --git a/libs/electricalconsumersapp/src/lib/sidesheet/CircuitDiagramTab.tsx b/libs/electricalconsumersapp/src/lib/sidesheet/CircuitDiagramTab.tsx index 298cc619d..82d7cb681 100644 --- a/libs/electricalconsumersapp/src/lib/sidesheet/CircuitDiagramTab.tsx +++ b/libs/electricalconsumersapp/src/lib/sidesheet/CircuitDiagramTab.tsx @@ -2,12 +2,12 @@ import { CircuitDiagram, ElectricalNetwork } from '@cc-components/shared'; type CircuitDiagramTabProps = { elenetwork?: ElectricalNetwork | null; - itemId: string; + itemNo: string; onCircuitDiagramReady?: (element: HTMLDivElement) => void; }; export const CircuitDiagramTab = ({ elenetwork, - itemId, + itemNo, onCircuitDiagramReady, }: CircuitDiagramTabProps) => { if (elenetwork === null) { @@ -17,7 +17,7 @@ export const CircuitDiagramTab = ({ ); diff --git a/libs/heattraceapp/README.md b/libs/heattraceapp/README.md new file mode 100644 index 000000000..8d172942b --- /dev/null +++ b/libs/heattraceapp/README.md @@ -0,0 +1,3 @@ +# heattraceapp + +Add readme diff --git a/libs/heattraceapp/package.json b/libs/heattraceapp/package.json new file mode 100644 index 000000000..064e7562d --- /dev/null +++ b/libs/heattraceapp/package.json @@ -0,0 +1,17 @@ +{ + "name": "@cc-components/heattraceapp", + "version": "0.0.1", + "type": "module", + "scripts": { + "build": "tsc -b" + }, + "module": "./dist/src/index.js", + "main": "./dist/src/index.js", + "types": "./dist/src/index.d.ts", + "dependencies": { + "@cc-components/shared": "workspace:^", + "@cc-components/sharedcomponents": "workspace:^", + "@cc-components/heattraceshared": "workspace:^", + "@cc-components/heattracesidesheet": "workspace:^" + } +} diff --git a/libs/heattraceapp/src/index.ts b/libs/heattraceapp/src/index.ts new file mode 100644 index 000000000..f41a696fd --- /dev/null +++ b/libs/heattraceapp/src/index.ts @@ -0,0 +1 @@ +export * from './lib'; diff --git a/libs/heattraceapp/src/lib/config/frameworkConfig.ts b/libs/heattraceapp/src/lib/config/frameworkConfig.ts new file mode 100644 index 000000000..3c7b185d6 --- /dev/null +++ b/libs/heattraceapp/src/lib/config/frameworkConfig.ts @@ -0,0 +1,40 @@ +import { enableAgGrid } from '@equinor/fusion-framework-module-ag-grid'; +import { + ComponentRenderArgs, + IAppConfigurator, +} from '@equinor/fusion-framework-react-app'; +import { enableContext } from '@equinor/fusion-framework-react-module-context'; +import buildQuery from 'odata-query'; + +export const configure = async (config: IAppConfigurator, c: ComponentRenderArgs) => { + enableContext(config, async (builder) => { + builder.setContextType(['ProjectMaster']); + builder.setContextParameterFn(({ search, type }) => { + return buildQuery({ + search, + filter: { + type: { + in: type, + }, + }, + }); + }); + }); + + const envConfig: HeattraceEnvConfig = c.env.config?.environment as HeattraceEnvConfig; + + if (!envConfig) { + throw new Error('Failed to load environemnt config for heat trace'); + } + config.configureHttpClient('cc-api', { + baseUri: envConfig?.uri, + defaultScopes: envConfig?.defaultScopes, + }); + + enableAgGrid(config); +}; + +type HeattraceEnvConfig = { + uri: string; + defaultScopes: string[]; +}; diff --git a/libs/heattraceapp/src/lib/config/gardenConfig.tsx b/libs/heattraceapp/src/lib/config/gardenConfig.tsx new file mode 100644 index 000000000..4709190fe --- /dev/null +++ b/libs/heattraceapp/src/lib/config/gardenConfig.tsx @@ -0,0 +1,35 @@ +import { HeatTrace } from '@cc-components/heattraceshared'; +import { GardenConfig } from '@equinor/workspace-fusion/garden'; +import { useGardenDataSource } from '@cc-components/shared/workspace-config'; +import { GardenItem } from '../ui-garden/'; +import { FilterState } from '@equinor/workspace-fusion/filter'; +import { useHttpClient } from '@cc-components/shared'; + +export const useGardenConfig = ( + contextId: string +): GardenConfig => { + const client = useHttpClient(); + const { getBlockAsync, getGardenMeta, getHeader, getSubgroupItems } = + useGardenDataSource({ + getBlockAsync: (req) => + client.fetch(`/api/contexts/${contextId}/heat-trace/garden`, req), + getGardenMeta: (req) => + client.fetch(`/api/contexts/${contextId}/heat-trace/garden-meta`, req), + getHeader: (req) => + client.fetch(`/api/contexts/${contextId}/heat-trace/garden`, req), + getSubgroupItems: (req) => + client.fetch(`/api/contexts/${contextId}/heat-trace/subgroup-items`, req), + }); + + return { + getBlockAsync, + getGardenMeta, + getHeader, + getSubgroupItems, + getDisplayName: (item) => item.heatTraceCableNo, + initialGrouping: ['Priority1'], + customViews: { + customItemView: GardenItem, + }, + }; +}; diff --git a/libs/heattraceapp/src/lib/config/heattraceSidesheet.tsx b/libs/heattraceapp/src/lib/config/heattraceSidesheet.tsx new file mode 100644 index 000000000..1cbf3238c --- /dev/null +++ b/libs/heattraceapp/src/lib/config/heattraceSidesheet.tsx @@ -0,0 +1,10 @@ +import { SidesheetConfig } from '@equinor/workspace-fusion/sidesheet'; +import { HeatTrace } from '@cc-components/heattraceshared'; +import { HeattraceSidesheet } from '@cc-components/heattracesidesheet'; + +export const sidesheetConfig: SidesheetConfig = { + type: 'default', + DetailsSidesheet: (props) => ( + + ), +}; diff --git a/libs/heattraceapp/src/lib/config/index.ts b/libs/heattraceapp/src/lib/config/index.ts new file mode 100644 index 000000000..6df8bcd95 --- /dev/null +++ b/libs/heattraceapp/src/lib/config/index.ts @@ -0,0 +1,2 @@ +export { WorkspaceWrapper } from './workspaceConfig'; +export { configure } from './frameworkConfig'; diff --git a/libs/heattraceapp/src/lib/config/statusBarConfig.ts b/libs/heattraceapp/src/lib/config/statusBarConfig.ts new file mode 100644 index 000000000..e7e30e665 --- /dev/null +++ b/libs/heattraceapp/src/lib/config/statusBarConfig.ts @@ -0,0 +1,20 @@ +import { StatusBarConfig } from '@equinor/workspace-fusion/status-bar'; +import { useHttpClient } from '@cc-components/shared'; + +export const useStatusBarConfig = (contextId: string): StatusBarConfig => { + const client = useHttpClient(); + + return async (filters, signal) => { + const res = await client.fetch(`/api/contexts/${contextId}/heat-trace/kpis`, { + method: 'POST', + body: JSON.stringify({ + filter: filters, + }), + signal, + headers: { + ['content-type']: 'application/json', + }, + }); + return (await res.json()).map((s: any) => ({ ...s, title: s.name })); + }; +}; diff --git a/libs/heattraceapp/src/lib/config/tableConfig.tsx b/libs/heattraceapp/src/lib/config/tableConfig.tsx new file mode 100644 index 000000000..0b9fb5f6c --- /dev/null +++ b/libs/heattraceapp/src/lib/config/tableConfig.tsx @@ -0,0 +1,97 @@ +import { ColDef, GridConfig, ICellRendererProps } from '@equinor/workspace-fusion/grid'; +import { CheckList, HeatTrace } from '@cc-components/heattraceshared'; +import { FilterState } from '@equinor/workspace-fusion/filter'; +import { + defaultGridOptions, + useGridDataSource, +} from '@cc-components/shared/workspace-config'; +import { + DateCell, + DescriptionCell, + LinkCell, + StyledMonospace, + useHttpClient, +} from '@cc-components/shared'; + +export const useTableConfig = (contextId: string): GridConfig => { + const client = useHttpClient(); + + const { getRows, colDefs } = useGridDataSource(async (req) => { + const res = await client.fetch(`/api/contexts/${contextId}/heat-trace/grid`, req); + const meta = await res.json(); + + return { + rowCount: meta.rowCount, + items: meta.items, + columnDefinitions: meta.columnDefinitions, + }; + }, columnDefinitions); + return { + gridOptions: { + ...defaultGridOptions, + onFirstDataRendered: (e) => { + e.columnApi.autoSizeColumns( + e.columnApi + .getAllDisplayedColumns() + .filter((column) => column.getColId() !== 'description') + ); + }, + }, + getRows: getRows, + columnDefinitions: colDefs as [ColDef, ...ColDef[]], + }; +}; + +const columnDefinitions: [ColDef, ...ColDef[]] = [ + { + colId: 'HeatTraceCableNo', + field: 'Tag', + valueGetter: (pkg) => pkg.data?.heatTraceCableNo, + cellRenderer: (props: ICellRendererProps) => { + return ( + + ); + }, + }, + { + colId: 'HeatTraceCableDescription', + field: 'Description', + valueGetter: (pkg) => pkg.data?.heatTraceCableDescription, + cellRenderer: (props: ICellRendererProps) => { + return ; + }, + width: 300, + }, + { colId: 'Priority1', field: 'Priority1', valueGetter: (pkg) => pkg.data?.priority1 }, + { + colId: 'Location', + field: 'Location', + valueGetter: (pkg) => pkg.data?.location, + cellRenderer: (props: ICellRendererProps) => { + return {props.value}; + }, + }, + // Need to implement the visual checklistStatus + { field: 'Checklist status', valueGetter: (pkg) => pkg.data?.status }, + { field: 'Current step', valueGetter: (pkg) => 't.b.d :D' }, + { + field: 'RFC', + valueGetter: (pkg) => pkg.data?.rfCPlannedForecastDate, + cellRenderer: (props: ICellRendererProps) => { + return props.value ? : null; + }, + }, + { + field: 'Pipetests', + valueGetter: (pkg) => pkg.data?.pipetest, + cellRenderer: (props: ICellRendererProps) => { + if (!props.value) return null; + return {props.value}; + // ( + // + // {generateCommaSeperatedStringArrayColumn(getHTList(props.value))} + // + // ); + }, + }, +]; diff --git a/libs/heattraceapp/src/lib/config/workspaceConfig.tsx b/libs/heattraceapp/src/lib/config/workspaceConfig.tsx new file mode 100644 index 000000000..94d1e2d79 --- /dev/null +++ b/libs/heattraceapp/src/lib/config/workspaceConfig.tsx @@ -0,0 +1,43 @@ +import Workspace from '@equinor/workspace-fusion'; +import { gridModule } from '@equinor/workspace-fusion/grid-module'; +import { gardenModule } from '@equinor/workspace-fusion/garden-module'; +import { useFilterConfig } from '@cc-components/shared/workspace-config'; +import { useTableConfig } from './tableConfig'; +import { useStatusBarConfig } from './statusBarConfig'; +import { useCCApiAccessCheck, useContextId, useHttpClient } from '@cc-components/shared'; +import { CCApiAccessLoading } from '@cc-components/sharedcomponents'; +import { useGardenConfig } from './gardenConfig'; +import { sidesheetConfig } from './heattraceSidesheet'; + +export const WorkspaceWrapper = () => { + const contextId = useContextId(); + const client = useHttpClient(); + const { isLoading } = useCCApiAccessCheck(contextId, client, 'heat-trace'); + + const filterOptions = useFilterConfig((req) => + client.fetch(`/api/contexts/${contextId}/heat-trace/filter-model`, req) + ); + + const tableConfig = useTableConfig(contextId); + const statusBarConfig = useStatusBarConfig(contextId); + const gardenConfig = useGardenConfig(contextId); + + if (isLoading) { + return ; + } + + return ( + ht.heatTraceCableNo, + defaultTab: 'grid', + }} + filterOptions={filterOptions} + gardenOptions={gardenConfig} + gridOptions={tableConfig} + statusBarOptions={statusBarConfig} + sidesheetOptions={sidesheetConfig} + modules={[gridModule, gardenModule]} + /> + ); +}; diff --git a/libs/heattraceapp/src/lib/index.ts b/libs/heattraceapp/src/lib/index.ts new file mode 100644 index 000000000..bae042f71 --- /dev/null +++ b/libs/heattraceapp/src/lib/index.ts @@ -0,0 +1 @@ +export { WorkspaceWrapper, configure } from './config'; diff --git a/libs/heattraceapp/src/lib/ui-garden/Item.tsx b/libs/heattraceapp/src/lib/ui-garden/Item.tsx new file mode 100644 index 000000000..f58688dfc --- /dev/null +++ b/libs/heattraceapp/src/lib/ui-garden/Item.tsx @@ -0,0 +1,102 @@ +import { pipetestStatusColormap } from '@cc-components/shared/mapping'; +import { PopoverWrapper } from '@cc-components/shared'; +import { CustomItemView } from '@equinor/workspace-fusion/garden'; +import { memo, useMemo, useRef, useState } from 'react'; +import { + StyledDescription, + StyledItemText, + StyledItemWrapper, + StyledRoot, + StyledStatusCircles, +} from './garden.styles'; +import { HeatTrace } from '@cc-components/heattraceshared'; +import { getHeatTraceStatuses } from '../utils-garden/getHeatTraceStatuses'; + +const HeattraceGardenItem = (props: CustomItemView) => { + const [isOpen, setIsOpen] = useState(false); + const [hoverTimeout, setHoverTimeout] = useState | null>( + null + ); + + const anchorRef = useRef(null); + + const { + data, + onClick, + columnExpanded, + depth, + width: itemWidth = 300, + isSelected, + rowStart, + columnStart, + parentRef, + displayName, + } = props; + + const { + backgroundColor, + textColor, + //TODO: group by keys + } = useMemo(() => getHeatTraceStatuses(data), [data]); + const width = useMemo(() => (depth ? 100 - depth * 3 : 100), [depth]); + const maxWidth = useMemo(() => itemWidth * 0.98, [itemWidth]); + + return ( + <> + + { + hoverTimeout && !isOpen && clearTimeout(hoverTimeout); + setHoverTimeout(setTimeout(() => setIsOpen(true), 700)); + }} + onMouseLeave={() => { + hoverTimeout && clearTimeout(hoverTimeout); + setIsOpen(false); + }} + backgroundColor={backgroundColor} + color={textColor} + onClick={onClick} + style={{ width: `${columnExpanded ? 100 : width}%`, maxWidth }} + isSelected={isSelected} + > + {displayName} + + + + {columnExpanded && ( + + {data.heatTraceCableDescription} + + )} + + + {isOpen && ( + setIsOpen(false)} + /> + )} + + ); +}; + +export const GardenItem = memo(HeattraceGardenItem); diff --git a/libs/heattraceapp/src/lib/ui-garden/garden.styles.ts b/libs/heattraceapp/src/lib/ui-garden/garden.styles.ts new file mode 100644 index 000000000..8663d3f49 --- /dev/null +++ b/libs/heattraceapp/src/lib/ui-garden/garden.styles.ts @@ -0,0 +1,110 @@ +import { tokens } from '@equinor/eds-tokens'; +import styled from 'styled-components'; +export const StyledRoot = styled.div` + height: 80%; + width: 100%; + display: flex; + align-items: center; + gap: 10px; + margin-left: 5px; + position: relative; +`; +export type ItemProps = { backgroundColor: string; isSelected: boolean }; + +export const StyledItemWrapper = styled.div` + display: grid; + grid-template-columns: 3fr auto; + align-items: center; + box-sizing: border-box; + position: relative; + background: ${(props) => props.backgroundColor}; + color: ${tokens.colors.text.static_icons__default.rgba}; + cursor: pointer; + border: 1px solid #ededed; + height: 100%; + border-radius: 5px; + font-weight: 500; + font-size: 13px; + padding-left: 20px; + padding-right: 2px; + outline: ${(props) => (props.isSelected ? '2px dashed green' : '')}; + outline-offset: ${(props) => (props.isSelected ? '2px' : '')}; + width: 100%; +`; + +export const StyledItemText = styled.div` + grid-column: 1/2; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +`; + +type StatusCirclesProps = { + mcColor: string | null; + commColor: string | null; +}; +export const StyledStatusCircles = styled.div` + display: flex; + grid-column: 2/3; + 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'}; + 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'}; + border-radius: 50%; + margin: 0px 1px; + outline: ${(props) => (props.commColor ? 'none' : `1px dashed gray`)}; + outline-offset: -2px; + content: ' '; + } +`; + +export const StyledStatuses = styled.div` + margin-top: 24px; + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 10px; + + > div { + margin-right: 16px; + + &:last-child { + margin: 0; + } + } +`; +type NoStatusProps = { + size: 'small' | 'medium'; +}; +export const StyledNoStatus = styled.div` + outline: ${(props) => + `${props.size === 'small' ? '2px' : '4px'} dashed ${ + tokens.colors.ui.background__medium.hex + }`}; + border-radius: ${(props) => (props.size === 'small' ? '17px' : '21px')}; + height: ${(props) => (props.size === 'small' ? '16px' : '20px')}; + width: ${(props) => (props.size === 'small' ? '16px' : '20px')}; +`; + +export const StyledDescription = styled.p` + all: unset; + width: 50%; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +`; diff --git a/libs/heattraceapp/src/lib/ui-garden/index.ts b/libs/heattraceapp/src/lib/ui-garden/index.ts new file mode 100644 index 000000000..cd7d702d9 --- /dev/null +++ b/libs/heattraceapp/src/lib/ui-garden/index.ts @@ -0,0 +1 @@ +export { GardenItem } from './Item'; diff --git a/libs/heattraceapp/src/lib/utils-garden/getHeatTraceStatuses.ts b/libs/heattraceapp/src/lib/utils-garden/getHeatTraceStatuses.ts new file mode 100644 index 000000000..ef54a1fb4 --- /dev/null +++ b/libs/heattraceapp/src/lib/utils-garden/getHeatTraceStatuses.ts @@ -0,0 +1,15 @@ +import { HeatTrace } from 'libs/heattraceshared/dist/src'; +import { pipetestAndHeatTraceColorMap } from '@cc-components/shared/mapping'; +import { getTextColor } from './getTextColor'; + +type PackageStatusReturn = { + backgroundColor: string; + textColor: string; +}; + +export const getHeatTraceStatuses = (data: HeatTrace): PackageStatusReturn => { + // const backgroundColor = pipetestAndHeatTraceColorMap[data.currentStep]; + // const textColor = getTextColor(data.currentStep); + + return { backgroundColor: 'green', textColor: 'white' }; +}; diff --git a/libs/heattraceapp/src/lib/utils-garden/getTextColor.ts b/libs/heattraceapp/src/lib/utils-garden/getTextColor.ts new file mode 100644 index 000000000..2cabec385 --- /dev/null +++ b/libs/heattraceapp/src/lib/utils-garden/getTextColor.ts @@ -0,0 +1,6 @@ +export const getTextColor = (status: string) => { + if (status === 'Pressure test' || status === 'Insulation' || status === 'Complete') + return '#000000'; + + return '#ffffff'; +}; diff --git a/libs/heattraceapp/src/lib/utils-table/generateCommaSeperatedStringArrayColumn.ts b/libs/heattraceapp/src/lib/utils-table/generateCommaSeperatedStringArrayColumn.ts new file mode 100644 index 000000000..6e73ceb9a --- /dev/null +++ b/libs/heattraceapp/src/lib/utils-table/generateCommaSeperatedStringArrayColumn.ts @@ -0,0 +1,15 @@ +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/heattraceapp/src/lib/utils-table/tableHelpers.ts b/libs/heattraceapp/src/lib/utils-table/tableHelpers.ts new file mode 100644 index 000000000..f90d780b6 --- /dev/null +++ b/libs/heattraceapp/src/lib/utils-table/tableHelpers.ts @@ -0,0 +1,5 @@ +import { CheckList } from 'libs/heattraceshared/dist/src'; + +export function getHTList(checkLists: CheckList[]): string[] { + return checkLists.filter((x) => x.isHeatTrace).map((ht: CheckList) => ht.tagNo); +} diff --git a/libs/heattraceapp/tsconfig.json b/libs/heattraceapp/tsconfig.json new file mode 100644 index 000000000..91f9168f9 --- /dev/null +++ b/libs/heattraceapp/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["vite/client"], + "resolveJsonModule": true + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/heattraceapp/tsconfig.lib.json b/libs/heattraceapp/tsconfig.lib.json new file mode 100644 index 000000000..2fc88d732 --- /dev/null +++ b/libs/heattraceapp/tsconfig.lib.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "types": ["node"], + "rootDir": "." + }, + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "dist" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/heattraceshared/README.md b/libs/heattraceshared/README.md new file mode 100644 index 000000000..8d172942b --- /dev/null +++ b/libs/heattraceshared/README.md @@ -0,0 +1,3 @@ +# heattraceapp + +Add readme diff --git a/libs/heattraceshared/package.json b/libs/heattraceshared/package.json new file mode 100644 index 000000000..645ed3989 --- /dev/null +++ b/libs/heattraceshared/package.json @@ -0,0 +1,14 @@ +{ + "name": "@cc-components/heattraceshared", + "version": "0.0.1", + "type": "module", + "scripts": { + "build": "tsc -b" + }, + "module": "./dist/src/index.js", + "main": "./dist/src/index.js", + "types": "./dist/src/index.d.ts", + "dependencies": { + "@cc-components/shared": "workspace:^" + } +} diff --git a/libs/heattraceshared/src/index.ts b/libs/heattraceshared/src/index.ts new file mode 100644 index 000000000..f41a696fd --- /dev/null +++ b/libs/heattraceshared/src/index.ts @@ -0,0 +1 @@ +export * from './lib'; diff --git a/libs/heattraceshared/src/lib/index.ts b/libs/heattraceshared/src/lib/index.ts new file mode 100644 index 000000000..fcb073fef --- /dev/null +++ b/libs/heattraceshared/src/lib/index.ts @@ -0,0 +1 @@ +export * from './types'; diff --git a/libs/heattraceshared/src/lib/types/dcrEnum.ts b/libs/heattraceshared/src/lib/types/dcrEnum.ts new file mode 100644 index 000000000..110fa7326 --- /dev/null +++ b/libs/heattraceshared/src/lib/types/dcrEnum.ts @@ -0,0 +1,81 @@ +//Usikker på om vi trenger alle enumene, men tok med alle i tilfelle +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/heattraceshared/src/lib/types/heatTraceChecklist.ts b/libs/heattraceshared/src/lib/types/heatTraceChecklist.ts new file mode 100644 index 000000000..b95423d00 --- /dev/null +++ b/libs/heattraceshared/src/lib/types/heatTraceChecklist.ts @@ -0,0 +1,46 @@ +export type HeatTraceChecklist = { + heatTraceCableNo: string; + heatTraceCableId: string; + heatTraceCableIdUrlId: string; + heatTraceCableDescription: string; + facility: string; + project: string; + projectDescription: string; + projectSchema: string; + checklistId: string; + checklistUrlId: string; + formResponsible: string; + mcResponsible: string; + commResponsible: string; + formularType: string; + formularGroup: string; + status: string; + revision: string; + signedDate: string; + pipeTest: string; + tagArea: string; + mechanicalCompletionArea: string; + mcDescription: string; + mechanicalCompletionPackageNo: string; + mechanicalCompletionPackageId: string; + mechanicalCompletionPackageUrlId: string; + mechanicalCompletionStatus: string; + priority1: string; + priority1Description: string; + priority2: string; + priority3: string; + rfC_Planned_Forecast_Date: string; + rfO_Planned_Forecast_Date: string; + commissioningPackageNo: string; + commissioningPackageId: string; + commissioningPackageUrlId: string; + system: string; + checklistStep: string; + checklistStepSequence: string; + pipetestType: string; + circuit: string; + switchboard: string; + checklistUrl: string | null; + commissioningPackageUrl: string | null; + mechanicalCompletionUrl: string | null; +}; diff --git a/libs/heattraceshared/src/lib/types/heattrace.ts b/libs/heattraceshared/src/lib/types/heattrace.ts new file mode 100644 index 000000000..7afaab878 --- /dev/null +++ b/libs/heattraceshared/src/lib/types/heattrace.ts @@ -0,0 +1,101 @@ +export type HeatTrace = { + facility: string; + project: string; + heatTraceCableNo: string; + heatTraceCableId: string; + heatTraceCableUrlId: string; + heatTraceCableDescription: string; + register: string; + commissioningPackageNo: string | null; + commissioningPackageId: string | null; + commissioningPackageUrlId: string | null; + commissioningResponsible: string | null; + commissioningPhase: string | null; + commissioningArea: string | null; + commissioningStatus: string | null; + mechanicalCompletionPackageNo: string | null; + mechanicalCompletionPackageId: string | null; + mechanicalCompletionUrlId: string | null; + mechanicalCompletionResponsible: string | null; + mechanicalCompletionPhase: string | null; + mechanicalCompletionStatus: string | null; + mechanicalCompletionId: string | null; + mechanicalCompletionArea: string | null; + mechanicalCompletionDiscipline: string | null; + status: string; + discipline: string; + location: string; + isVoided: string | null; + engineeringCode: string; + priority1: string | null; + priority2: string | null; + priority3: string | null; + projectDescription: string | null; + projectSchema: string | null; + mountedOnTagId: string | null; + pipetest: string | null; + pipetestType: string; + system: string | null; + rfCPlannedForecastDate: string; + rfOPlannedForecastDate: string; + m03PlannedForecastDate: string | null; + signedDate: string; + identifier: string | null; + identifierId: string | null; + heatTraceCableUrl: string | null; + commissioningPackageUrl: string | null; + mechanicalCompletionUrl: string | null; +}; + +export interface Pipetest { + name: string; + description: string; + commPkPriority1: string; + rfccPlanned: string; + location: string; + mcPkgId: string; + mcPkgUrlId: string; + checkLists: CheckList[]; + insulationBoxes: InsulationBox[]; + circuits: Circuit[]; + lines: Line[]; + hasDisconnectedEquipment: boolean; + hasIsolatedEquipment: boolean; +} + +export type CheckList = { + revision?: string; + isHeatTrace: boolean; + signedDate?: string; + c01Planned: string; + c01Forecast: string; + m03Planned: string; + m03Forecast: string | null; + m04Actual: string | null; + tagNo: string; + responsible: string; + formularType: string; + formularGroup: string; + status: string; +}; + +export interface InsulationBox { + objectNo: string; + objectName: string; + objectStatusName?: string; + objectStatus?: string; + object3dReference?: string; + procosysStatus?: string; +} + +export interface Circuit { + switchBoardTagNo: string; + circuitAndStarterTagNo: string; + checkLists: CheckList[]; + cableTagNos: string[]; +} + +export interface Line { + tagNo: string; + isCritical: boolean; +} diff --git a/libs/heattraceshared/src/lib/types/index.ts b/libs/heattraceshared/src/lib/types/index.ts new file mode 100644 index 000000000..8e24241f4 --- /dev/null +++ b/libs/heattraceshared/src/lib/types/index.ts @@ -0,0 +1,3 @@ +export * from './heattrace'; +export * from './heatTraceChecklist'; +export * from './dcrEnum'; diff --git a/libs/heattraceshared/tsconfig.json b/libs/heattraceshared/tsconfig.json new file mode 100644 index 000000000..c77dc187c --- /dev/null +++ b/libs/heattraceshared/tsconfig.json @@ -0,0 +1,19 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "resolveJsonModule": true, + "types": ["vite/client"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/heattraceshared/tsconfig.lib.json b/libs/heattraceshared/tsconfig.lib.json new file mode 100644 index 000000000..2fc88d732 --- /dev/null +++ b/libs/heattraceshared/tsconfig.lib.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "types": ["node"], + "rootDir": "." + }, + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "dist" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/heattracesidesheet/README.md b/libs/heattracesidesheet/README.md new file mode 100644 index 000000000..8d172942b --- /dev/null +++ b/libs/heattracesidesheet/README.md @@ -0,0 +1,3 @@ +# heattraceapp + +Add readme diff --git a/libs/heattracesidesheet/package.json b/libs/heattracesidesheet/package.json new file mode 100644 index 000000000..6375281fe --- /dev/null +++ b/libs/heattracesidesheet/package.json @@ -0,0 +1,16 @@ +{ + "name": "@cc-components/heattracesidesheet", + "version": "0.0.1", + "type": "module", + "scripts": { + "build": "tsc -b" + }, + "module": "./dist/src/index.js", + "main": "./dist/src/index.js", + "types": "./dist/src/index.d.ts", + "dependencies": { + "@cc-components/shared": "workspace:^", + "@cc-components/sharedcomponents": "workspace:^", + "@cc-components/heattraceshared": "workspace:^" + } +} diff --git a/libs/heattracesidesheet/src/index.ts b/libs/heattracesidesheet/src/index.ts new file mode 100644 index 000000000..f41a696fd --- /dev/null +++ b/libs/heattracesidesheet/src/index.ts @@ -0,0 +1 @@ +export * from './lib'; diff --git a/libs/heattracesidesheet/src/lib/index.ts b/libs/heattracesidesheet/src/lib/index.ts new file mode 100644 index 000000000..285402573 --- /dev/null +++ b/libs/heattracesidesheet/src/lib/index.ts @@ -0,0 +1 @@ +export * from './ui-sidesheet'; diff --git a/libs/heattracesidesheet/src/lib/types/index.ts b/libs/heattracesidesheet/src/lib/types/index.ts new file mode 100644 index 000000000..587c5e4a8 --- /dev/null +++ b/libs/heattracesidesheet/src/lib/types/index.ts @@ -0,0 +1 @@ +export { Workorder } from './workorder'; diff --git a/libs/heattracesidesheet/src/lib/types/workorder.ts b/libs/heattracesidesheet/src/lib/types/workorder.ts new file mode 100644 index 000000000..dfec6a95e --- /dev/null +++ b/libs/heattracesidesheet/src/lib/types/workorder.ts @@ -0,0 +1,23 @@ +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; +}; diff --git a/libs/heattracesidesheet/src/lib/ui-sidesheet/ChecklistTab.tsx b/libs/heattracesidesheet/src/lib/ui-sidesheet/ChecklistTab.tsx new file mode 100644 index 000000000..7cfd63bed --- /dev/null +++ b/libs/heattracesidesheet/src/lib/ui-sidesheet/ChecklistTab.tsx @@ -0,0 +1,27 @@ +import { TabTable } from '@cc-components/shared'; +import { StyledContentWrapper } from '@cc-components/sharedcomponents'; +import { checklistColumns } from './checklistColumns'; +import { HeatTraceChecklist } from 'libs/heattraceshared/dist/src'; + +type ChecklistTabProps = { + checklists: HeatTraceChecklist[] | undefined; + isFetching: boolean; + error: Error | null; +}; +export const ChecklistTab = ({ + checklists, + error, + isFetching, +}: ChecklistTabProps): JSX.Element => { + return ( + + + + ); +}; diff --git a/libs/heattracesidesheet/src/lib/ui-sidesheet/CircuitDiagramTab.tsx b/libs/heattracesidesheet/src/lib/ui-sidesheet/CircuitDiagramTab.tsx new file mode 100644 index 000000000..82d7cb681 --- /dev/null +++ b/libs/heattracesidesheet/src/lib/ui-sidesheet/CircuitDiagramTab.tsx @@ -0,0 +1,24 @@ +import { CircuitDiagram, ElectricalNetwork } from '@cc-components/shared'; + +type CircuitDiagramTabProps = { + elenetwork?: ElectricalNetwork | null; + itemNo: string; + onCircuitDiagramReady?: (element: HTMLDivElement) => void; +}; +export const CircuitDiagramTab = ({ + elenetwork, + itemNo, + onCircuitDiagramReady, +}: CircuitDiagramTabProps) => { + if (elenetwork === null) { + return
No elenetwork found
; + } + return ( + + ); +}; diff --git a/libs/heattracesidesheet/src/lib/ui-sidesheet/HeattraceSidesheet.tsx b/libs/heattracesidesheet/src/lib/ui-sidesheet/HeattraceSidesheet.tsx new file mode 100644 index 000000000..0d104b637 --- /dev/null +++ b/libs/heattracesidesheet/src/lib/ui-sidesheet/HeattraceSidesheet.tsx @@ -0,0 +1,199 @@ +import { HeatTrace } from '@cc-components/heattraceshared'; +import { createWidget, useResizeContext } from '@equinor/workspace-sidesheet'; +import { useRef, useState } from 'react'; +import { Tabs } from '@equinor/eds-core-react'; +import styled from 'styled-components'; +import { tokens } from '@equinor/eds-tokens'; +import { useGetWorkorders } from '../utils-sidesheet'; +import { WorkorderTab } from '@cc-components/shared/sidesheet'; +import { + ElectricalNetwork, + LinkCell, + useContextId, + useHttpClient, +} from '@cc-components/shared'; +import { + BannerItem, + SidesheetHeader, + StyledBanner, + StyledPanels, + StyledSideSheetContainer, + StyledTabs, + TabTitle, +} from '@cc-components/sharedcomponents'; + +import { Workorder } from '../types'; +import { ChecklistTab } from './ChecklistTab'; +import { useGetHeatTraceChecklists } from '../utils-sidesheet/useGetChecklists'; +import { useQuery } from '@tanstack/react-query'; +import { CircuitDiagramTab } from './CircuitDiagramTab'; + +const workorders: Workorder[] = []; + +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; +`; + +type HeatTraceProps = { + id: string; + item?: HeatTrace; + close: () => void; +}; + +export const HeattraceSidesheet = createWidget(({ props }) => { + const [activeTab, setActiveTab] = useState(0); + const { width, setWidth } = useResizeContext(); + const heattrace = props.item; + + if (!heattrace) { + throw new Error('Heat Trace undefined'); + } + + const htNo = heattrace.heatTraceCableNo; + const facility = heattrace.facility; + const project = heattrace.project; + + const { dataChecklists, errorChecklists, isLoadingChecklists } = + useGetHeatTraceChecklists(props.item?.heatTraceCableId ?? ''); + + const client = useHttpClient(); + const contextId = useContextId(); + + const reszied = useRef({ hasResized: false, id: props.id }); + if (reszied.current.id !== props.id) { + reszied.current = { hasResized: false, id: props.id }; + setWidth(700); + } + + const { data: elenetwork, isLoading: isLoadingEle } = + useQuery( + /**Change facility to project */ + /** facility*/ [htNo, facility, project], + async ({ signal }) => { + const res = await client.fetch( + `api/contexts/${contextId}/electrical/consumers/electrical-network/${encodeURIComponent( + htNo + )}/${facility}`, + { signal } + ); + + if (res.status === 204) { + return null; + } + + if (!res.ok) { + if (res.status === 404) { + return null; + } + throw new Error('Failed to fetch elenetwork'); + } + return res.json(); + }, + { + suspense: false, + useErrorBoundary: false, + } + ); + + const handleChange = (index: number) => { + setActiveTab(index); + }; + + return ( + + + + + + ) : ( + 'N/A' + ) + } + > + + ) : ( + 'N/A' + ) + } + /> + + + + + + Circuit diagram + + Work orders + + + Checklists + + + 3D + + + + + { + if (reszied.current.hasResized) return; + const newWidth = element.scrollWidth; + if (width !== 700) return; + setWidth(newWidth + 50); + reszied.current = { hasResized: true, id: props.id }; + }} + /> + + + + + + + + 3D is coming + + + + ); +}); + +export default HeattraceSidesheet.render; diff --git a/libs/heattracesidesheet/src/lib/ui-sidesheet/checklistColumns.tsx b/libs/heattracesidesheet/src/lib/ui-sidesheet/checklistColumns.tsx new file mode 100644 index 000000000..b036c3e94 --- /dev/null +++ b/libs/heattracesidesheet/src/lib/ui-sidesheet/checklistColumns.tsx @@ -0,0 +1,49 @@ +import { + BaseStatus, + StatusCircle, + StyledMonospace, + statusColorMap, +} from '@cc-components/shared'; +import { ColDef, ICellRendererProps } from '@equinor/workspace-ag-grid'; +import { HeatTraceChecklist } from '@cc-components/heattraceshared'; + +export const checklistColumns: ColDef[] = [ + { + field: 'Tag', + valueGetter: (pkg) => pkg.data?.heatTraceCableNo, + cellRenderer: (props: ICellRendererProps) => { + return {props.value}; + }, + }, + { + field: 'Revision', + valueGetter: (pkg) => pkg.data?.revision, + cellRenderer: (props: ICellRendererProps) => { + return {props.value}; + }, + }, + { + field: 'Formular type', + valueGetter: (pkg) => pkg.data?.formularType, + cellRenderer: (props: ICellRendererProps) => { + return {props.value}; + }, + }, + { + field: 'Responsible', + valueGetter: (pkg) => pkg.data?.mcResponsible, + }, + { + field: 'Status', + valueGetter: (pkg) => pkg.data?.status, + cellRenderer: (props: ICellRendererProps) => { + if (!props.data?.status) return null; + return ( + + ); + }, + }, +]; diff --git a/libs/heattracesidesheet/src/lib/ui-sidesheet/index.ts b/libs/heattracesidesheet/src/lib/ui-sidesheet/index.ts new file mode 100644 index 000000000..93abef238 --- /dev/null +++ b/libs/heattracesidesheet/src/lib/ui-sidesheet/index.ts @@ -0,0 +1 @@ +export * from './HeattraceSidesheet'; diff --git a/libs/heattracesidesheet/src/lib/utils-sidesheet/index.ts b/libs/heattracesidesheet/src/lib/utils-sidesheet/index.ts new file mode 100644 index 000000000..c30601b10 --- /dev/null +++ b/libs/heattracesidesheet/src/lib/utils-sidesheet/index.ts @@ -0,0 +1 @@ +export * from './useGetWorkorders'; diff --git a/libs/heattracesidesheet/src/lib/utils-sidesheet/useGetChecklists.ts b/libs/heattracesidesheet/src/lib/utils-sidesheet/useGetChecklists.ts new file mode 100644 index 000000000..4d2a5c546 --- /dev/null +++ b/libs/heattracesidesheet/src/lib/utils-sidesheet/useGetChecklists.ts @@ -0,0 +1,28 @@ +import { useHttpClient } from '@equinor/fusion-framework-react-app/http'; +import { useContextId } from '@cc-components/shared'; +import { useQuery } from '@tanstack/react-query'; +import { HeatTraceChecklist } from '@cc-components/heattraceshared'; + +export const useGetHeatTraceChecklists = (heatTraceCabelId: string) => { + const client = useHttpClient('cc-api'); + const contextId = useContextId(); + const { data, isLoading, error } = useQuery( + ['heat-trace', heatTraceCabelId, 'checklists'], + async ({ signal }) => { + const respons = await client.fetch( + `/api/contexts/${contextId}/heat-trace/${heatTraceCabelId}/checklists`, + { signal } + ); + if (!respons.ok) { + throw new Error(); + } + return respons.json(); + } + ); + + return { + dataChecklists: data, + isLoadingChecklists: isLoading, + errorChecklists: error, + }; +}; diff --git a/libs/heattracesidesheet/src/lib/utils-sidesheet/useGetWorkorders.ts b/libs/heattracesidesheet/src/lib/utils-sidesheet/useGetWorkorders.ts new file mode 100644 index 000000000..7ca030791 --- /dev/null +++ b/libs/heattracesidesheet/src/lib/utils-sidesheet/useGetWorkorders.ts @@ -0,0 +1,28 @@ +import { useHttpClient } from '@equinor/fusion-framework-react-app/http'; +import { useContextId } from '@cc-components/shared'; +import { useQuery } from '@tanstack/react-query'; +import { Workorder } from '../types'; + +export const useGetWorkorders = (heatTraceCabelNo: string) => { + const client = useHttpClient('cc-api'); + const contextId = useContextId(); + const { data, isLoading, error } = useQuery( + ['heat-trace', heatTraceCabelNo, 'workorders'], + async ({ signal }) => { + const respons = await client.fetch( + `/api/contexts/${contextId}/heat-trace/${heatTraceCabelNo}/workorders`, + { signal } + ); + if (!respons.ok) { + throw new Error(); + } + return respons.json(); + } + ); + + return { + data: data, + isLoading: isLoading, + error: error, + }; +}; diff --git a/libs/heattracesidesheet/tsconfig.json b/libs/heattracesidesheet/tsconfig.json new file mode 100644 index 000000000..6734c59c0 --- /dev/null +++ b/libs/heattracesidesheet/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "jsx": "react-jsx", + "allowJs": false, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "types": ["vite/client"] + }, + "files": [], + "include": [], + "references": [ + { + "path": "./tsconfig.lib.json" + } + ], + "extends": "../../tsconfig.base.json" +} diff --git a/libs/heattracesidesheet/tsconfig.lib.json b/libs/heattracesidesheet/tsconfig.lib.json new file mode 100644 index 000000000..2fc88d732 --- /dev/null +++ b/libs/heattracesidesheet/tsconfig.lib.json @@ -0,0 +1,20 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./dist", + "types": ["node"], + "rootDir": "." + }, + "exclude": [ + "**/*.spec.ts", + "**/*.test.ts", + "**/*.spec.tsx", + "**/*.test.tsx", + "**/*.spec.js", + "**/*.test.js", + "**/*.spec.jsx", + "**/*.test.jsx", + "dist" + ], + "include": ["**/*.js", "**/*.jsx", "**/*.ts", "**/*.tsx"] +} diff --git a/libs/shared/src/packages/circuit-diagram/ui/CircuitDiagram.tsx b/libs/shared/src/packages/circuit-diagram/ui/CircuitDiagram.tsx index 043534038..15ddbef7c 100644 --- a/libs/shared/src/packages/circuit-diagram/ui/CircuitDiagram.tsx +++ b/libs/shared/src/packages/circuit-diagram/ui/CircuitDiagram.tsx @@ -28,12 +28,11 @@ import { Transformer, Unknown, } from './CircuitDiagramComponents'; -import { on } from 'events'; type CircuitDiagramProps = { network?: ElectricalNetwork; isLoading?: boolean; - itemId: string; + itemNo: string; onCircuitDiagramReady?: (element: HTMLDivElement) => void; }; @@ -46,7 +45,7 @@ type ElectricalComponentProps = { export function CircuitDiagram({ network, isLoading, - itemId, + itemNo, onCircuitDiagramReady, }: CircuitDiagramProps) { const [circuitRef, setCircuitRef] = useState({}); @@ -80,7 +79,7 @@ export function CircuitDiagram({ network={circuitChildren} key={circuitChildren.name} circuitName={circuit.name} - itemId={itemId} + itemId={itemNo} /> ))} diff --git a/libs/shared/src/packages/mapping/src/lib/index.ts b/libs/shared/src/packages/mapping/src/lib/index.ts index 3b0f184b4..99f76d539 100644 --- a/libs/shared/src/packages/mapping/src/lib/index.ts +++ b/libs/shared/src/packages/mapping/src/lib/index.ts @@ -1,6 +1,6 @@ export { colorMap } from './colorMap'; export { materialStatusMap } from './materialStatusMap'; -export { statusColorMap } from './statusColorMap'; +export { statusColorMap, pipetestStatusColormap } from './statusColorMap'; export { itemContentColors } from './itemContentColors'; export { proCoSysStatusPriorityMap, @@ -8,3 +8,4 @@ export { proCoSysWorkOrderProgressColorMap, orderedProCoSysStatuses, } from './procosys'; +export { pipetestAndHeatTraceColorMap } from './pipetestAndHeatTraceColor'; diff --git a/libs/shared/src/packages/mapping/src/lib/pipetestAndHeatTraceColor.ts b/libs/shared/src/packages/mapping/src/lib/pipetestAndHeatTraceColor.ts new file mode 100644 index 000000000..463e9804f --- /dev/null +++ b/libs/shared/src/packages/mapping/src/lib/pipetestAndHeatTraceColor.ts @@ -0,0 +1,15 @@ +import { tokens } from '@equinor/eds-tokens'; + +export const pipetestAndHeatTraceColorMap: Record = { + 'Pressure test': '#6D889A', + 'Chemical cleaning': '#A8C8DE', + 'Bolt tensioning': '#F7F7F7', + Painting: tokens.colors.ui.background__medium.hex, + 'A-test': '#FFE7D6', + Insulation: tokens.colors.infographic.primary__moss_green_55.hex, + 'Box insulation': tokens.colors.infographic.primary__moss_green_34.hex, + 'B-test': '#FFC67A', + 'C-test': '#DCAB6A', + Marking: tokens.colors.interactive.table__cell__fill_activated.hex, + Complete: tokens.colors.interactive.success__resting.hex, +}; diff --git a/libs/shared/src/packages/mapping/src/lib/statusColorMap.ts b/libs/shared/src/packages/mapping/src/lib/statusColorMap.ts index aef2204ba..74518c46a 100644 --- a/libs/shared/src/packages/mapping/src/lib/statusColorMap.ts +++ b/libs/shared/src/packages/mapping/src/lib/statusColorMap.ts @@ -9,3 +9,5 @@ export const statusColorMap: Record = { PA: '#ff4081', OK: '#00c853', } as const; + +export const pipetestStatusColormap = { ...statusColorMap, IN: 'red' } as const; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e630d95f5..838a15245 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -165,6 +165,15 @@ importers: specifier: workspace:^ version: link:../../libs/shared + apps/heattrace: + dependencies: + '@cc-components/heattraceapp': + specifier: workspace:^ + version: link:../../libs/heattraceapp + '@cc-components/shared': + specifier: workspace:^ + version: link:../../libs/shared + apps/loop: dependencies: '@cc-components/loopapp': @@ -276,6 +285,39 @@ importers: specifier: workspace:^ version: link:../sharedcomponents + libs/heattraceapp: + dependencies: + '@cc-components/heattraceshared': + specifier: workspace:^ + version: link:../heattraceshared + '@cc-components/heattracesidesheet': + specifier: workspace:^ + version: link:../heattracesidesheet + '@cc-components/shared': + specifier: workspace:^ + version: link:../shared + '@cc-components/sharedcomponents': + specifier: workspace:^ + version: link:../sharedcomponents + + libs/heattraceshared: + dependencies: + '@cc-components/shared': + specifier: workspace:^ + version: link:../shared + + libs/heattracesidesheet: + dependencies: + '@cc-components/heattraceshared': + specifier: workspace:^ + version: link:../heattraceshared + '@cc-components/shared': + specifier: workspace:^ + version: link:../shared + '@cc-components/sharedcomponents': + specifier: workspace:^ + version: link:../sharedcomponents + libs/loopapp: dependencies: '@cc-components/loopshared':