Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
734 changes: 367 additions & 367 deletions CHANGELOG.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions charts/puris/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ dependencies:
| frontend.podSecurityContext.seccompProfile.type | string | `"RuntimeDefault"` | Restrict a Container's Syscalls with seccomp |
| frontend.puris.appName | string | `"PURIS"` | The name of the app displayed in the frontend |
| frontend.puris.baseUrl | string | `"your-backend-host-address.com"` | The base URL for the backend base URL without further endpoints. Must contain protocol (http/https). If protocol is missing, it's defaulted based on ingress configuration. |
| frontend.puris.defaultProductionTime | string | `"23:59"` | The default time to complete production |
| frontend.puris.endpointAllMaterials | string | `"materials"` | The endpoint for interfacing with all materials |
| frontend.puris.endpointAllPartners | string | `"partners"` | The endpoint for interfacing with all partners |
| frontend.puris.endpointCustomer | string | `"stockView/customer?ownMaterialNumber="` | The endpoint for the customers who buy a material identified via the own material number for the stock view |
Expand Down
2 changes: 2 additions & 0 deletions charts/puris/templates/frontend-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "puris.frontend.fullname" . }}

Check warning on line 25 in charts/puris/templates/frontend-deployment.yaml

View workflow job for this annotation

GitHub Actions / Analyze KICS

[MEDIUM] Using Unrecommended Namespace

Namespaces like 'default', 'kube-system' or 'kube-public' should not be used
labels:
{{- include "puris.frontend.labels" . | nindent 4 }}
spec:
Expand All @@ -40,7 +40,7 @@
{{- end }}
labels:
{{- include "puris.frontend.selectorLabels" . | nindent 8 }}
spec:

Check warning on line 43 in charts/puris/templates/frontend-deployment.yaml

View workflow job for this annotation

GitHub Actions / Analyze KICS

[MEDIUM] Service Account Token Automount Not Disabled

Service Account Tokens are automatically mounted even if not necessary
{{- with .Values.frontend.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
Expand All @@ -50,7 +50,7 @@
{{- toYaml .Values.frontend.podSecurityContext | nindent 8 }}
containers:
- name: {{ include "puris.frontend.fullname" . }}
securityContext:

Check warning on line 53 in charts/puris/templates/frontend-deployment.yaml

View workflow job for this annotation

GitHub Actions / Analyze KICS

[MEDIUM] Container Running With Low UID

Check if containers are running with low UID, which might cause conflicts with the host's user table.
{{- toYaml .Values.frontend.securityContext | nindent 12 }}
image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.frontend.image.pullPolicy }}
Expand Down Expand Up @@ -121,6 +121,8 @@
value: "{{ .Values.frontend.puris.rateLimiting.rate }}"
- name: FRONTEND_GENERATE_MATERIAL_CATENAX_ID
value: "{{ .Values.backend.puris.generatematerialcatenaxid | default true }}"
- name: FRONTEND_DEFAULT_PRODUCTION_TIME
value: "{{ .Values.frontend.puris.defaultProductionTime | default "23:59" }}"
######################################
## Additional environment variables ##
######################################
Expand Down
2 changes: 2 additions & 0 deletions charts/puris/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,8 @@ frontend:
appName: PURIS
# -- The base URL for the backend base URL without further endpoints. Must contain protocol (http/https). If protocol is missing, it's defaulted based on ingress configuration.
baseUrl: *domain
# -- The default production time for production creation
defaultProductionTime: 23:59
# -- The endpoint for materials for the stock view
endpointMaterials: stockView/materials
# -- The endpoint for products for the stock view
Expand Down
2 changes: 2 additions & 0 deletions frontend/.env
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,5 @@ VITE_IDP_URL=http://localhost:10081/
VITE_IDP_REALM=Catena-X
VITE_IDP_CLIENT_ID=puris-customer
VITE_IDP_REDIRECT_URL_FRONTEND=http://localhost:5173/

VITE_DEFAULT_PRODUCTION_TIME=23:59
2 changes: 2 additions & 0 deletions frontend/.env.dockerbuild
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ VITE_IDP_URL=\$IDP_URL
VITE_IDP_REALM=\$IDP_REALM
VITE_IDP_CLIENT_ID=\$IDP_CLIENT_ID
VITE_IDP_REDIRECT_URL_FRONTEND=\$IDP_REDIRECT_URL_FRONTEND

VITE_DEFAULT_PRODUCTION_TIME=\$DEFAULT_PRODUCTION_TIME
3 changes: 2 additions & 1 deletion frontend/src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,6 @@
"ENDPOINT_ALL_MATERIALS": "$ENDPOINT_ALL_MATERIALS",
"GENERATE_MATERIAL_CATENAX_ID": "$GENERATE_MATERIAL_CATENAX_ID",
"ENDPOINT_ALL_PARTNERS": "$ENDPOINT_ALL_PARTNERS",
"ENDPOINT_MATERIAL_PARTNER_RELATIONS": "$ENDPOINT_MATERIAL_PARTNER_RELATIONS"
"ENDPOINT_MATERIAL_PARTNER_RELATIONS": "$ENDPOINT_MATERIAL_PARTNER_RELATIONS",
"DEFAULT_PRODUCTION_TIME": "$DEFAULT_PRODUCTION_TIME"
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,7 @@ SPDX-License-Identifier: Apache-2.0
*/

import { useEffect, useRef, useState } from 'react';
import {
Dialog,
DialogTitle,
Grid,
Button,
Stack,
FormLabel,
Box,
capitalize,
} from '@mui/material';
import { Dialog, DialogTitle, Grid, Button, Stack, FormLabel, Box, capitalize } from '@mui/material';
import { Input } from '@catena-x/portal-shared-components';
import { LabelledAutoComplete } from '@components/ui/LabelledAutoComplete';
import { DateTime } from '@components/ui/DateTime';
Expand All @@ -43,6 +34,7 @@ import { useSites } from '@features/stock-view/hooks/useSites';
import { postProduction, putProduction, updateProduction } from '@services/productions-service';
import { useNotifications } from '@contexts/notificationContext';
import { GridItem } from '@components/ui/GridItem';
import { withDefaultProductionTime } from '@util/production-helpers';
import { ConfirmUpdateDialog, ConfirmUpdateHandle } from './UpdateModal';
import { UUID } from 'crypto';

Expand All @@ -57,17 +49,13 @@ const isValidProduction = (production: Partial<Production>) =>
production &&
production.productionSiteBpns &&
production.estimatedTimeOfCompletion &&
typeof production.quantity === 'number' && production.quantity >= 0 &&
typeof production.quantity === 'number' &&
production.quantity >= 0 &&
production.measurementUnit &&
production.partner &&
isValidOrderReference(production);

export const PlannedProductionCreationModal = ({
open,
production,
onClose,
onSave,
}: ProductionCategoryCreationModalProps) => {
export const PlannedProductionCreationModal = ({ open, production, onClose, onSave }: ProductionCategoryCreationModalProps) => {
const [temporaryProduction, setTemporaryProduction] = useState<Partial<Production>>(production ?? {});
const { partners } = usePartners('product', temporaryProduction?.material?.materialNumberSupplier ?? null);
const { sites } = useSites();
Expand Down Expand Up @@ -123,9 +111,9 @@ export const PlannedProductionCreationModal = ({
}
const message =
`There is already a production matching your criteria with a quantity ` +
`${error?.quantity} ${UNITS_OF_MEASUREMENT.find(u => u.key === error?.measurementUnit)?.value ?? error?.measurementUnit}. ` +
`Do you want to update to ${temporaryProduction.quantity} ${UNITS_OF_MEASUREMENT.find(u => u.key === temporaryProduction.measurementUnit)?.value ?? temporaryProduction.measurementUnit}?`;
const confirmed = await confirmRef.current?.open({message});
`${error?.quantity} ${UNITS_OF_MEASUREMENT.find((u) => u.key === error?.measurementUnit)?.value ?? error?.measurementUnit}. ` +
`Do you want to update to ${temporaryProduction.quantity} ${UNITS_OF_MEASUREMENT.find((u) => u.key === temporaryProduction.measurementUnit)?.value ?? temporaryProduction.measurementUnit}?`;
const confirmed = await confirmRef.current?.open({ message });
if (confirmed) {
try {
const updated = await putProduction({
Expand All @@ -134,17 +122,17 @@ export const PlannedProductionCreationModal = ({
lastUpdatedOnDateTime: new Date().toISOString(),
});
onSave(updated);
notify({
title: 'Production Updated',
description: 'The production has been updated successfully',
severity: 'success'
notify({
title: 'Production Updated',
description: 'The production has been updated successfully',
severity: 'success',
});
handleClose();
}
catch (e: any) {
notify({
} catch (e: any) {
notify({
title: 'Error updating',
description: e?.error ?? 'Unexpected error', severity: 'error'
description: e?.error ?? 'Unexpected error',
severity: 'error',
});
}
}
Expand All @@ -155,13 +143,12 @@ export const PlannedProductionCreationModal = ({
severity: 'error',
});
}

});
};

const handleClose = () => {
setFormError(false);
setTemporaryProduction({})
setTemporaryProduction({});
onClose();
};

Expand Down Expand Up @@ -197,7 +184,13 @@ export const PlannedProductionCreationModal = ({
error={formError}
value={temporaryProduction.estimatedTimeOfCompletion ?? null}
onValueChange={(date) =>
setTemporaryProduction({ ...temporaryProduction, estimatedTimeOfCompletion: date ?? undefined })
setTemporaryProduction({
...temporaryProduction,
estimatedTimeOfCompletion:
temporaryProduction.estimatedTimeOfCompletion == null
? withDefaultProductionTime(date)
: (date ?? undefined),
})
}
/>
</Grid>
Expand Down Expand Up @@ -245,7 +238,10 @@ export const PlannedProductionCreationModal = ({
onChange={(_, value) => setTemporaryProduction((curr) => ({ ...curr, measurementUnit: value?.key }))}
value={
temporaryProduction.measurementUnit
? { key: temporaryProduction.measurementUnit, value: getUnitOfMeasurement(temporaryProduction.measurementUnit) }
? {
key: temporaryProduction.measurementUnit,
value: getUnitOfMeasurement(temporaryProduction.measurementUnit),
}
: null
}
isOptionEqualToValue={(option, value) => option?.key === value?.key}
Expand All @@ -271,7 +267,9 @@ export const PlannedProductionCreationModal = ({
type="text"
error={formError && !isValidOrderReference(temporaryProduction)}
value={temporaryProduction.customerOrderPositionNumber ?? ''}
onChange={(e) => setTemporaryProduction({ ...temporaryProduction, customerOrderPositionNumber: e.target.value })}
onChange={(e) =>
setTemporaryProduction({ ...temporaryProduction, customerOrderPositionNumber: e.target.value })
}
data-testid="production-customer-order-position-field"
/>
</Grid>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/models/constants/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ SPDX-License-Identifier: Apache-2.0
const app = {
APP_NAME: import.meta.env.VITE_APP_NAME.trim() as string,
BACKEND_BASE_URL: import.meta.env.VITE_BACKEND_BASE_URL.trim() as string,
DEFAULT_PRODUCTION_TIME: (import.meta.env.VITE_DEFAULT_PRODUCTION_TIME).trim() as string,
ENDPOINT_MATERIALS: import.meta.env.VITE_ENDPOINT_MATERIALS.trim() as string,
ENDPOINT_PRODUCTS: import.meta.env.VITE_ENDPOINT_PRODUCTS.trim() as string,
ENDPOINT_MATERIAL_STOCKS: import.meta.env.VITE_ENDPOINT_MATERIAL_STOCKS.trim() as string,
Expand Down
38 changes: 38 additions & 0 deletions frontend/src/util/production-helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
Copyright (c) 2026 Volkswagen AG
Copyright (c) 2026 Contributors to the Eclipse Foundation

See the NOTICE file(s) distributed with this work for additional
information regarding copyright ownership.

This program and the accompanying materials are made available under the
terms of the Apache License, Version 2.0 which is available at
https://www.apache.org/licenses/LICENSE-2.0.

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
License for the specific language governing permissions and limitations
under the License.

SPDX-License-Identifier: Apache-2.0
*/

import { config } from '@models/constants/config';

export function withDefaultProductionTime(date: Date | null): Date | undefined {
if (!date || isNaN(date.getTime())) {
return undefined;
}
const dateCopy = new Date(date);
const hasTime = dateCopy.getHours() !== 0 || dateCopy.getMinutes() !== 0;
if (!hasTime) {
const [hours, minutes] = getDefaultProductionTimeNumbers();
dateCopy.setHours(hours, minutes, 0, 0);
}
return dateCopy;
}

export function getDefaultProductionTimeNumbers(): [number, number] {
return config.app.DEFAULT_PRODUCTION_TIME.split(":").map(Number) as [number, number];
}
2 changes: 2 additions & 0 deletions local/docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ services:
- IDP_REALM=Catena-X
- IDP_CLIENT_ID=puris-customer
- IDP_REDIRECT_URL_FRONTEND=http://localhost:3000
- DEFAULT_PRODUCTION_TIME=23:59
- NGINX_RATE_LIMIT=10m
- NGINX_BURST=30
- NGINX_RATE=10r/s
Expand Down Expand Up @@ -257,6 +258,7 @@ services:
- IDP_REALM=Catena-X
- IDP_CLIENT_ID=puris-supplier
- IDP_REDIRECT_URL_FRONTEND=http://localhost:3001
- DEFAULT_PRODUCTION_TIME=23:59
- NGINX_RATE_LIMIT=10m
- NGINX_BURST=30
- NGINX_RATE=10r/s
Expand Down
Loading