Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • 16-trains-with-no-changing-on-file-system
  • 18-predefined-selectable-option-as-an-environment-variable-value
  • 19-error-failed-to-parse-json-when-result-to-big
  • 19-error-failed-to-parse-json-when-result-to-big-2
  • 20-handling-the-telegraf-metrics-on-the-station-software-not-in-the-metadata-generator
  • 25-retrieving-the-station-pid-from-the-initial-env-file-and-setting-it-automatically-at-the
  • 39-add-anonymisation-feature-to-station-software
  • 40-allow-different-base-url-for-web-view
  • 41-update-packages
  • 43-streamlining-deployment
  • 48-adding-gpu-support-installation-to-the-install-script
  • 52-autofill-bind-mount
  • 8-vault-health-status
  • 88-poll-logs-only-if-running
  • 9-error-stdout-maxbuffer-length-exceeded
  • 93-vault-initialization-unsealing-error-in-station-software
  • api-for-keycloak-migration
  • cleaned-publishable-branch
  • cosign-integration
  • decouple-station-builds
  • edc-integration
  • enable-gzip-for-fl-results
  • error-tar-bad-archive
  • federated
  • federatedmerge
  • federatedmerge-backup
  • git-ci-test
  • interopt
  • job-automation-agent
  • keycloak-auth
  • main
  • main-fairds
  • prerelease
  • prerelease-semver
  • protect-routes-with-keycloak
  • redacted
  • renovate-axios-1.x-lockfile
  • renovate-diff2html-3.x-lockfile
  • renovate-eslint-8.x-lockfile
  • renovate-express-fileupload-1.x-lockfile
  • renovate-material-ui-popup-state-5.x-lockfile
  • renovate-mongo-4.x
  • renovate-mongoose-6.x-lockfile
  • renovate-nodemon-3.x-lockfile
  • renovate-reduxjs-toolkit-1.x-lockfile
  • renovate-semantic-release-monorepo
  • renovate/configure
  • replace-hardcoded-cs-path
  • set-sast-config-1
  • station-software-ui-update
  • v
  • v0.0.0
  • v1.0.0
  • v1.0.1
  • v1.0.5
  • v2.0.0
  • v2.0.1
  • v2.0.2
  • v2.0.3
  • v2.0.4
60 results

Target

Select target project
  • padme-development/padme-station-software
1 result
Select Git revision
  • 16-trains-with-no-changing-on-file-system
  • 18-predefined-selectable-option-as-an-environment-variable-value
  • 19-error-failed-to-parse-json-when-result-to-big
  • 19-error-failed-to-parse-json-when-result-to-big-2
  • 20-handling-the-telegraf-metrics-on-the-station-software-not-in-the-metadata-generator
  • 25-retrieving-the-station-pid-from-the-initial-env-file-and-setting-it-automatically-at-the
  • 39-add-anonymisation-feature-to-station-software
  • 40-allow-different-base-url-for-web-view
  • 41-update-packages
  • 43-streamlining-deployment
  • 48-adding-gpu-support-installation-to-the-install-script
  • 52-autofill-bind-mount
  • 8-vault-health-status
  • 88-poll-logs-only-if-running
  • 9-error-stdout-maxbuffer-length-exceeded
  • 93-vault-initialization-unsealing-error-in-station-software
  • api-for-keycloak-migration
  • cleaned-publishable-branch
  • cosign-integration
  • decouple-station-builds
  • edc-integration
  • enable-gzip-for-fl-results
  • error-tar-bad-archive
  • federated
  • federatedmerge
  • federatedmerge-backup
  • git-ci-test
  • interopt
  • job-automation-agent
  • keycloak-auth
  • main
  • main-fairds
  • prerelease
  • prerelease-semver
  • protect-routes-with-keycloak
  • redacted
  • renovate-axios-1.x-lockfile
  • renovate-diff2html-3.x-lockfile
  • renovate-eslint-8.x-lockfile
  • renovate-express-fileupload-1.x-lockfile
  • renovate-material-ui-popup-state-5.x-lockfile
  • renovate-mongo-4.x
  • renovate-mongoose-6.x-lockfile
  • renovate-nodemon-3.x-lockfile
  • renovate-reduxjs-toolkit-1.x-lockfile
  • renovate-semantic-release-monorepo
  • renovate/configure
  • replace-hardcoded-cs-path
  • set-sast-config-1
  • station-software-ui-update
  • v
  • v0.0.0
  • v1.0.0
  • v1.0.1
  • v1.0.5
  • v2.0.0
  • v2.0.1
  • v2.0.2
  • v2.0.3
  • v2.0.4
60 results
Show changes
Commits on Source (20)
# Configuration files
.eslint*
*.yml
renovate.json
Dockerfile.dev
.husky/*
# Environment files
.env*
# Node.js
node_modules
npm-debug.log
.env
Deployment_Guidance_of_Station_Software.docx
\ No newline at end of file
# Project files
wizard-frontend/*
!wizard-frontend/build
station-frontend/*
!station-frontend/build
StationDeploymentFiles/*
# Misc
Deployment_Guidance_of_Station_Software.docx
......@@ -17,14 +17,43 @@ variables:
REGISTRY_DIND_IMAGE: $CI_REGISTRY_IMAGE/dind
REGISTRY_VAULT_IMAGE: $CI_REGISTRY_IMAGE/vault
build_wizard_frontend:
stage: build 📦
image: node:18.18.2-bullseye-slim
script:
- echo "Building Wizard Frontend 🚧"
- cd wizard-frontend
- npm ci --omit=dev
- npm run build
- echo "Wizard Frontend Build Complete! ✅"
artifacts:
paths:
- wizard-frontend/build/
expire_in: 1 week
build_station_frontend:
stage: build 📦
image: node:18.18.2-bullseye-slim
script:
- echo "Building Station Frontend 🚧"
- cd station-frontend
- npm install
- npm run build
- echo "Station Frontend Build Complete! ✅"
artifacts:
paths:
- station-frontend/build/
expire_in: 1 week
build_station_software:
image: docker:23-dind
services:
- docker:23-dind
stage: build 📦
needs: ["build_station_frontend", "build_wizard_frontend"]
before_script:
- apk update && apk add git
- echo "$CI_BUILD_TOKEN" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
- echo "$CI_JOB_TOKEN" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
script:
- echo "Building Station Software 🚧"
- docker build --pull -t $REGISTRY_STATION_SOFTWARE_IMAGE:$CI_COMMIT_SHA -t $REGISTRY_STATION_SOFTWARE_IMAGE:$CI_COMMIT_REF_NAME .
......@@ -39,7 +68,7 @@ build_dind:
stage: build 📦
before_script:
- apk update && apk add git
- echo "$CI_BUILD_TOKEN" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
- echo "$CI_JOB_TOKEN" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
script:
- echo "Build dind image!"
- docker build --pull -t $REGISTRY_DIND_IMAGE:$CI_COMMIT_SHA StationDeploymentFiles/dind
......@@ -53,7 +82,7 @@ build_vault:
stage: build 📦
before_script:
- apk update && apk add git
- echo "$CI_BUILD_TOKEN" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
- echo "$CI_JOB_TOKEN" | docker login -u "$CI_REGISTRY_USER" --password-stdin $CI_REGISTRY
script:
- echo "Build vault image!"
- docker build --pull -t $REGISTRY_VAULT_IMAGE:$CI_COMMIT_SHA StationDeploymentFiles/pht-vault
......@@ -81,6 +110,7 @@ build_vault:
fetch_semantic_version:
extends: .common_release_config
stage: fetch-version 🔎
dependencies: []
script:
- echo "Fetching Station Software release version 🚧"
- npx semantic-release --dry-run
......@@ -90,13 +120,14 @@ fetch_semantic_version:
dotenv: variables.env
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "prerelease"
deploy_image_branch:
image: docker:23-dind
services:
- docker:23-dind
stage: deploy 🚅
dependencies:
- fetch_semantic_version
variables:
CI_HARBOR_REGISTRY: repository.padme-analytics.de/stationsoftware
HARBOR_STATION_SOFTWARE_IMAGE: $CI_HARBOR_REGISTRY/station-software
......@@ -117,17 +148,15 @@ deploy_image_branch:
- docker push $HARBOR_VAULT_IMAGE:$CI_COMMIT_BRANCH
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "prerelease"
release:
extends: .common_release_config
stage: release 🚀
dependencies: []
script:
- npx semantic-release
rules:
- if: $CI_COMMIT_BRANCH == "main"
- if: $CI_COMMIT_BRANCH == "prerelease"
# pages:
# image: ubuntu:latest
......
FROM node:latest as node_cache
####### Build image ########
FROM node:latest as build
RUN apt-get update && apt-get install -y --no-install-recommends dumb-init
# Create app directory
WORKDIR /usr/src/app
ENV NODE_ENV=production
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
......@@ -14,29 +15,30 @@ COPY package*.json ./
# Install only production dependencies in the Docker image to reduce size
RUN npm pkg delete scripts.prepare && npm ci --omit=dev
#Install dependencies for wizard UI
COPY wizard-frontend/package*.json ./wizard-frontend/
RUN npm --prefix wizard-frontend install
#Install dependencies for main UI
COPY station-frontend/package*.json ./station-frontend/
RUN npm --prefix station-frontend install
####### Production image ########
FROM gcr.io/projectsigstore/cosign:v2.2.1 as cosign-bin
FROM node:18.18.2-bullseye-slim
FROM node:latest
ENV NODE_ENV production
COPY --from=build /usr/bin/dumb-init /usr/bin/dumb-init
WORKDIR /usr/src/app
# Create a directory for the lockfile and change the ownership of the directory to the "node" user and group
RUN mkdir /lockfiledir \
&& chown -R node:node /lockfiledir
COPY --from=node_cache /usr/src/app/ .
WORKDIR /usr/src/app
# Bundle app source
COPY . .
# Change the ownership of the working directory to the non-root user "node"
RUN chown -R node:node /usr/src/app
RUN mkdir /lockfiledir
# Switch to the non-root user "node"
USER node
# Copy cosign binary
COPY --from=cosign-bin /ko-app/cosign /usr/local/bin/cosign
COPY --chown=node:node --from=build /usr/src/app/node_modules /usr/src/app/node_modules
COPY --chown=node:node . /usr/src/app
EXPOSE 3030
ENTRYPOINT npm run start
# Install dumb-init. Use this instead of node's built-in process manager
# to ensure that signals are properly forwarded to the node process.
CMD ["dumb-init", "node", "./bin/www"]
FROM node:latest as node_cache
FROM node:latest as build
# Create app directory
WORKDIR /usr/src/app
......@@ -9,29 +9,23 @@ WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
#Install dependencies for wizard UI
# Install dependencies for wizard UI
COPY wizard-frontend/package*.json ./wizard-frontend/
RUN npm --prefix wizard-frontend install
#Install dependencies for main UI
# Install dependencies for main UI
COPY station-frontend/package*.json ./station-frontend/
RUN npm --prefix station-frontend install
FROM gcr.io/projectsigstore/cosign:v2.2.1 as cosign-bin
FROM node:latest
FROM node:18.18.2-bullseye-slim
WORKDIR /usr/src/app
COPY --from=node_cache /usr/src/app/ .
# Bundle app source
COPY --from=cosign-bin /ko-app/cosign /usr/local/bin/cosign
COPY --from=build /usr/src/app/node_modules /usr/src/app/node_modules
COPY . .
RUN mkdir /lockfiledir
# Copy cosign binary
COPY --from=cosign-bin /ko-app/cosign /usr/local/bin/cosign
EXPOSE 3030
CMD [ "npm", "run", "dev" ]
CMD ["npm", "run", "dev"]
# PADME Station Software
<h1 align="center">PADME Station Software</h1>
<p align="center">
<img alt="semantic-release: angular" src="https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release">
<img alt="Commitizen friendly" src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg">
</p>
This repository contains the edge client of the PADME ecosystem, called the PADME Station Software. See [the documentation](https://docs.padme-analytics.de/) for more information on the different PADME services and the service architecture. An overview of all open source services is available [here](https://git.rwth-aachen.de/padme-development).
......
......@@ -5,7 +5,6 @@ const express = require("express");
const path = require("path");
const cookieParser = require("cookie-parser");
const logger = require("morgan");
const cors = require("cors");
const session = require("express-session");
const mongoose = require("mongoose");
const promiseRetry = require("promise-retry");
......@@ -20,6 +19,7 @@ function randomString(size = 21) {
var app = express();
if (process.env.NODE_ENV === "development") {
const cors = require("cors");
app.use(
cors({
origin: ["http://localhost:3001", "http://127.0.0.1:3001"],
......
......@@ -27,78 +27,100 @@ const setUpGuard = setUpGuardFactory("/lockfiledir");
var port = normalizePort(process.env.PORT || "3030");
setUpGuard(port).then(() => {
const { setPublicKey } = require('../config/keycloak-config');
setPublicKey().then(() => {
/**
* Module dependencies.
*/
console.log("Start with main programm...");
var app = require("../app");
var debug = require("debug")("pht-web:server");
//skip self-signed-cert
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
/**
* Get port from environment and store in Express.
*/
app.set("port", port);
let server;
/**
* Create an HTTP or HTTPS server depending on whether SSL certs are provided
*/
if (process.env.HTTPS_SERVER_KEY && process.env.HTTPS_SERVER_CERT) {
console.log("SSL certs provided, starting HTTPS server");
const options = {
key: fs.readFileSync(process.env.HTTPS_SERVER_KEY),
cert: fs.readFileSync(process.env.HTTPS_SERVER_CERT)
const { setPublicKey } = require("../config/keycloak-config");
setPublicKey()
.then(() => {
/**
* Module dependencies.
*/
console.log("Start with main programm...");
var app = require("../app");
var debug = require("debug")("pht-web:server");
//skip self-signed-cert
// process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"
/**
* Get port from environment and store in Express.
*/
app.set("port", port);
let server;
/**
* Create an HTTP or HTTPS server depending on whether SSL certs are provided
*/
if (process.env.HTTPS_SERVER_KEY && process.env.HTTPS_SERVER_CERT) {
console.log("SSL certs provided, starting HTTPS server");
const options = {
key: fs.readFileSync(process.env.HTTPS_SERVER_KEY),
cert: fs.readFileSync(process.env.HTTPS_SERVER_CERT),
};
server = https.createServer(options, app);
} else {
console.log("No SSL certs provided, starting HTTP server");
server = http.createServer(app);
}
server = https.createServer(options, app);
} else {
console.log("No SSL certs provided, starting HTTP server");
server = http.createServer(app);
}
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on("error", onError);
server.on("listening", onListening);
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== "listen") {
throw error;
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
server.on("error", onError);
server.on("listening", onListening);
/**
* Event listener for HTTP server "error" event.
*/
function onError(error) {
if (error.syscall !== "listen") {
throw error;
}
var bind = typeof port === "string" ? "Pipe " + port : "Port " + port;
// handle specific listen errors with friendly messages
switch (error.code) {
case "EACCES":
console.error(bind + " requires elevated privileges");
process.exit(1);
case "EADDRINUSE":
console.error(bind + " is already in use");
process.exit(1);
default:
throw error;
}
}
var bind = typeof port === "string" ? "Pipe " + port : "Port " + port;
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind =
typeof addr === "string" ? "pipe " + addr : "port " + addr.port;
debug("Listening on " + bind);
}
// handle specific listen errors with friendly messages
switch (error.code) {
case "EACCES":
console.error(bind + " requires elevated privileges");
process.exit(1);
case "EADDRINUSE":
console.error(bind + " is already in use");
/**
* Gracefully shutdown Express server
*/
function shutdown() {
console.log("Received kill signal, shutting down gracefully...");
server.close(() => {
console.log("Closed out remaining connections");
process.exit(0);
});
setTimeout(() => {
console.error(
"Could not close connections in time, forcefully shutting down"
);
process.exit(1);
default:
throw error;
}, 10000);
}
}
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port;
debug("Listening on " + bind);
}
})
.catch(e => console.error('Error starting the express server', e));
process.on("SIGTERM", shutdown);
process.on("SIGINT", shutdown);
})
.catch((e) => console.error("Error starting the express server", e));
});
const cors = require("cors");
const express = require("express");
const routerFactory = require("./installationWizard");
const configurationManager = require("./configurationManager");
......@@ -13,6 +12,7 @@ const app = express();
* app is running on.
*/
if (process.env.NODE_ENV === "development") {
const cors = require("cors");
app.use(
cors({
origin: ["http://localhost:3001", "http://127.0.0.1:3001"],
......
{
"name": "@padme-development/padme-station-software",
"version": "2.0.1",
"version": "2.0.2",
"description": "A Dockerized Javascript Web Application providing interfaces for Monitoring of the algorithms and components, which manage the business logic e.g. pulling a train, execute a train, inspect the results, and many more.",
"license": "MIT",
"homepage": "https://git.rwth-aachen.de/padme-development/padme-station-software",
......@@ -9,7 +9,7 @@
"cm": "cz",
"build:wizard": "npm run build --prefix wizard-frontend",
"build:station": "npm run build --prefix station-frontend",
"start": "npm run build:wizard && npm run build:station && node ./bin/www",
"start": "node ./bin/www",
"dev": "NODE_ENV=development nodemon ./bin/www",
"test": "jest",
"semantic-release": "semantic-release",
......@@ -63,8 +63,7 @@
},
"release": {
"branches": [
"main",
"prerelease"
"main"
],
"plugins": [
"@semantic-release/commit-analyzer",
......
......@@ -11,6 +11,7 @@ const { vault } = require("../utils");
const { utility } = require("../utils");
const { environment } = require("../utils");
const { verifyImage } = require("../utils/cosign");
const { version } = require("../package.json");
// Dashboard
// Get Docker Information
......@@ -256,6 +257,12 @@ function resolveVaultPathList(callback) {
}
module.exports = (keycloak) => {
router.get("/v2/stationInfo", (req, res) => {
res.send({
appVersion: version,
});
});
router.get(
"/v2",
keycloak.protect(),
......
......@@ -46,7 +46,6 @@ const { DockerClient } = require("../../client");
const dockerContainerChangesKind = { 0: "Modified", 1: "Added", 2: "Deleted" };
const DOCKER_URL = `https://${process.env.DOCKER_HOST}:${process.env.DOCKER_PORT}`;
const CENTRALSERVICE_URL = `https://${process.env.CENTRALSERVICE_ADDRESS}:${process.env.CENTRALSERVICE_PORT}/${process.env.CENTRALSERVICE_ENDPOINT}`;
module.exports = (keycloak) => {
router.get(
......
......@@ -16971,16 +16971,16 @@
}
},
"node_modules/typescript": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
"version": "4.9.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
"node": ">=4.2.0"
}
},
"node_modules/unbox-primitive": {
......
import { useState } from "react";
import { useState, useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { styled, useTheme, alpha } from "@mui/material/styles";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import Badge from "@mui/material/Badge";
import MuiDrawer from "@mui/material/Drawer";
import MuiAppBar from "@mui/material/AppBar";
import Toolbar from "@mui/material/Toolbar";
......@@ -15,6 +16,7 @@ import Menu from "@mui/material/Menu";
import MenuItem from "@mui/material/MenuItem";
import FormControl from "@mui/material/FormControl";
import Select from "@mui/material/Select";
import MuiLink from "@mui/material/Link";
import ListItem from "@mui/material/ListItem";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemIcon from "@mui/material/ListItemIcon";
......@@ -38,8 +40,17 @@ import {
setLearningType,
} from "../../redux/reducers/stationSlice";
import { fetchFederatedJobs } from "../../redux/reducers/federatedSlice";
import { fetchStationInfo } from "../../redux/reducers/stationSlice";
const drawerWidth = 210;
const muiBadgeStyles = {
".MuiBadge-badge": {
right: "-25px",
fontWeight: "bold",
borderRadius: "4px",
px: "4px",
},
};
const openedMixin = (theme) => ({
width: drawerWidth,
......@@ -98,7 +109,7 @@ const Drawer = styled(MuiDrawer, {
}));
const StyledFormControl = styled(FormControl)(({ theme }) => ({
marginLeft: theme.spacing(3),
marginLeft: theme.spacing(8),
"& .MuiInputBase-input, .MuiSelect-icon": {
color: theme.palette.common.white,
},
......@@ -119,10 +130,16 @@ export default function Navbar() {
const { pathname } = useLocation();
const [open, setOpen] = useState(false);
const [anchorEl, setAnchorEl] = useState(null);
const { learning, stationID, stationName } = useSelector(
const { learning, stationID, stationName, stationVersion } = useSelector(
(state) => state.station
);
const releaseHref = `https://git.rwth-aachen.de/padme-development/padme-station-software/-/releases/v${stationVersion}`;
useEffect(() => {
dispatch(fetchStationInfo());
}, [dispatch]);
const isMenuOpen = Boolean(anchorEl);
const handleChangeLearning = (event) => {
......@@ -204,9 +221,25 @@ export default function Navbar() {
style={{ maxWidth: "60px" }}
alt="PHT STATION SOFTWARE"
/>
<Typography variant="h6" ml={2} fontWeight="bold">
{stationName || stationID || "Station Software"}
</Typography>
<Badge
badgeContent={
<MuiLink
href={releaseHref}
color="inherit"
underline="none"
target="_blank"
rel="noreferer"
>
v{stationVersion}
</MuiLink>
}
color="error"
sx={muiBadgeStyles}
>
<Typography variant="h6" ml={2} fontWeight="bold">
{stationName || stationID || "Station Software"}
</Typography>
</Badge>
<StyledFormControl size="small">
<Select
id="select-learning-type"
......
import axios from "../../services/AxiosService";
export const fetchStationInfoAPI = () => axios.get("/dashboard/v2/stationInfo");
export const fetchTrainsAPI = () => axios.get("/dashboard/v2");
export const fetchImagesAPI = () => axios.get("/dashboard/images/v2");
......
import { createSlice, createAsyncThunk, isAnyOf } from "@reduxjs/toolkit";
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import { showAlert } from "./alertSlice";
import {
learningType,
......@@ -1069,6 +1069,28 @@ export const showContainerFileChanges = createAsyncThunk(
}
);
export const fetchStationInfo = createAsyncThunk(
"station/fetchStationInfo",
async (_, { dispatch, rejectWithValue }) => {
try {
const response = await API.fetchStationInfoAPI();
return response.data;
} catch (err) {
const message = `Error fetching station info (${err.message})`;
dispatch(
showAlert({
message,
options: {
key: "station/fetchStationInfoError",
variant: "error",
},
})
);
return rejectWithValue(message);
}
}
);
const initialState = {
jobs: [],
trains: [],
......@@ -1080,6 +1102,7 @@ const initialState = {
},
stationID: "",
stationName: "",
stationVersion: "",
containerLogs: "",
containerCompareDiff: "",
containerResultsFetchedId: "",
......@@ -1203,6 +1226,9 @@ const stationSlice = createSlice({
},
extraReducers: (builder) => {
builder
.addCase(fetchStationInfo.fulfilled, (state, { payload }) => {
state.stationVersion = payload.appVersion;
})
.addCase(fetchVaultStatus.pending, (state) => {
state.loadingVault = true;
})
......