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':