Skip to content
Snippets Groups Projects
Commit e74eb8bc authored by Imre Toth's avatar Imre Toth
Browse files

ICSHWI-9403: Refining IOC details component

parent 865a3c49
No related branches found
No related tags found
4 merge requests!270Merging develop branch to master in order to create RC,!222Fixing missing time interval parameter for logs,!202Merging develop to master,!172ICSHWI-9403: Refining IOC details component
Pipeline #112529 passed
......@@ -178,4 +178,16 @@ export class IocActiveDeployment {
failedDeployment() {
return this.activeDeployment && ('successful'.localeCompare(this.activeDeployment?.jobStatus, undefined, { sensitivity: 'base' }) !== 0);
}
calculateNotDeployedText(deployedText) {
if (this.activeDeployment) {
return deployedText;
}
return '---';
}
hasDeployment() {
return (this.activeDeployment !== null) && (this.activeDeployment != 'undefined')
}
}
import React from 'react';
import { Button, Grid } from "@material-ui/core";
import { Button, Grid, makeStyles } from "@material-ui/core";
import { Alert } from "@material-ui/lab";
import { theme } from '../../style/Theme';
const useStyles = makeStyles((theme) => ({
infoBadge: {
backgroundColor: theme.infoBadge.bgColor,
}
}));
export default function AlertMessages({ alerts }) {
const classes = useStyles(theme);
function determineSeverity(alarmType) {
if (alarmType === "ERROR") {
return "error";
}
if(alarmType === "WARNING") {
return "warning";
}
return "info";
}
function determineClassName(alarmType) {
if(alarmType === "INFO") {
return classes.infoBadge;
}
}
return (
<Grid id="ioc-alerts" container spacing={1}>
{(alerts.map((alert) => (
<Grid item xs={12} key={alert}>
<Alert
severity={alert.type === "ERROR" ? "error" : "warning"}
<Alert className={determineClassName(alert.type)}
severity={determineSeverity(alert.type)}
action={ alert.link &&
<Button target="_blank" href={alert.link} color="inherit" size="small">
More Info
......
import React from 'react';
import { Typography, Link as MuiLink } from "@material-ui/core";
export default function GitRefLink({ioc}) {
export default function GitRefLink({ ioc }) {
let url = ioc.sourceUrl;
let url = ioc.sourceUrl;
//if no git reference has been entered
if ( (!url) || (url.trim === "")) {
return <></>
}
//if no git reference has been entered
if ((!url) || (url.trim === "")) {
return <></>
}
//if user enters GIT url with '.git' postfix -> remove it
if (url.toLowerCase().endsWith('.git')) {
url = url.toLowerCase().split(".git")[0];
}
//add trailing '/' if needed for GIT server address
if (!url.endsWith("/")) {
url = url + "/";
}
//calculate the endpoint for tag/commitId
url = url + '-/tree/' + ioc.sourceVersion;
//if user enters GIT url with '.git' postfix -> remove it
if (url.toLowerCase().endsWith('.git')) {
url = url.toLowerCase().split(".git")[0];
}
return <Typography display="inline"><MuiLink href={url} target="_blank" rel="noreferrer">{ioc.sourceVersionShort}</MuiLink></Typography>
//add trailing '/' if needed for GIT server address
if (!url.endsWith("/")) {
url = url + "/";
}
//calculate the endpoint for tag/commitId
url = url + '-/tree/' + ioc.sourceVersion;
return <Typography display="inline"><MuiLink href={url} target="_blank" rel="noreferrer">{ioc.sourceVersionShort}</MuiLink></Typography>;
}
\ No newline at end of file
import React, { useCallback, useContext, useEffect } from "react";
import { Typography, Link as MuiLink } from "@material-ui/core";
import { Typography, Link as MuiLink, makeStyles } from "@material-ui/core";
import { SimpleAccordion } from "../common/Accordion/SimpleAccordion";
import { IOCDetails } from "./IOCDetails";
import { Link } from 'react-router-dom';
......@@ -10,13 +10,22 @@ import { IOCService } from "./IOCService";
import { IOCCommandTable } from "./IOCCommandTable";
import AccessControl from '../../components/auth/AccessControl';
import { useDeploymentJobById, userContext } from "../../api/SwaggerApi";
import { DeploymentStatus } from "../../api/DataTypes";
import { DeploymentStatus, IocActiveDeployment } from "../../api/DataTypes";
import { theme } from "../../style/Theme";
const useStyles = makeStyles((theme) => ({
iocNotDeployed: {
color: theme.iocNotDeployed.color
}
}));
export function IOCLiveStatus({ ioc, currentCommand, commands, getCommands, buttonDisabled, setButtonDisabled,
commandLazyParams, setCommandLazyParams, commandColumnSort, setCommandColumnSort, rowsPerPage }) {
const { user } = useContext(userContext);
const [deploymentJob, getDeploymentJobById] = useDeploymentJobById();
const classes = useStyles(theme);
useEffect(() => {
if (ioc.activeDeployment?.awxJobId) {
getDeploymentJobById(ioc.activeDeployment?.awxJobId);
......@@ -27,54 +36,64 @@ export function IOCLiveStatus({ ioc, currentCommand, commands, getCommands, butt
liveIOC.name = ioc.namingName;
const getSubset = useCallback((ioc) => {
const iocHascDeployment = new IocActiveDeployment(ioc.activeDeployment).hasDeployment();
//if IOC is not deployed some fields has to show '---' value
if (!iocHascDeployment) {
var notDeployedText = {shownValue: '---', shownClass: classes.iocNotDeployed};
}
//Show START/STOP components only when IOC was deployed SUCCESSFULLY
const deploymentStatus = new DeploymentStatus(ioc.activeDeployment, deploymentJob);
const showControls = deploymentStatus.wasSuccessful();
let subset = {
"CCDB name":
<Typography><MuiLink href={`${window.CCDB_ADDRESS}?name=${ioc.namingName}`}
"CCDB name":
<Typography><MuiLink href={`${window.CCDB_ADDRESS}?name=${ioc.namingName}`}
target="_blank" rel="noreferrer">{ioc.namingName}</MuiLink></Typography>,
"Git reference": <GitRefLink ioc={ioc} />,
"Description": ioc.description,
"Owner": ioc.owner,
"Deployed on":
"Git reference": iocHascDeployment ? <GitRefLink ioc={ioc} /> : notDeployedText,
"Deployed on": iocHascDeployment ?
<Typography>
{ioc.activeDeployment?.host.csEntryId ?
<Link to={`/hosts/${ioc.activeDeployment?.host.csEntryId}`}>{ioc.activeDeployment?.host.fqdn}</Link>
:
<>{ioc.activeDeployment?.host.fqdn}</>
}
</Typography>,
</Typography>
: notDeployedText,
}
if (user) {
subset["IOC Service Controls"] = showControls ?
<IOCService {...{ ioc, currentCommand, getCommands, buttonDisabled, setButtonDisabled, commandColumnSort, commandLazyParams }} />
: "Can't be controlled, because IOC is not (yet) deployed succesfully";
}
subset["IOC Service Controls"] = showControls ?
<IOCService {...{ ioc, currentCommand, getCommands, buttonDisabled, setButtonDisabled, commandColumnSort, commandLazyParams }} />
: "Can't be controlled, because IOC is not (yet) deployed succesfully";
}
return subset
}, [buttonDisabled, commandColumnSort, commandLazyParams, currentCommand, deploymentJob, getCommands, setButtonDisabled, user]);
return subset
}, [buttonDisabled, commandColumnSort, commandLazyParams, currentCommand, deploymentJob, getCommands, setButtonDisabled, user, classes.iocNotDeployed]);
function isIocDeployed(ioc) {
return Boolean(ioc.activeDeployment);
}
function isIocDeployed(ioc) {
return Boolean(ioc.activeDeployment);
}
return (
<>
<IOCDetails ioc={liveIOC} getSubset={getSubset} alert={<AlertMessages alerts={liveIOC.alerts} />} />
<SimpleAccordion summary="IOC Service Control log">
<IOCCommandTable commands={commands}
commandLazyParams={commandLazyParams} setCommandLazyParams={setCommandLazyParams} commandColumnSort={commandColumnSort} setCommandColumnSort={setCommandColumnSort}
rowsPerPage={rowsPerPage} />
</SimpleAccordion>
{(liveIOC.activeDeployment?.host?.csEntryIdValid) &&
<AccessControl allowedRoles={["DeploymentToolAdmin", "DeploymentToolIntegrator"]}
renderNoAccess={() => <></>}>
<SimpleAccordion summary="ProcServLog info" defaultExpanded>
<LokiContainer csEntryId={liveIOC.activeDeployment?.host.csEntryId} iocName={ioc.namingName} isDeployed={isIocDeployed(ioc)} />
</SimpleAccordion>
</AccessControl>
}
</>
);
return (
<>
<IOCDetails ioc={liveIOC} getSubset={getSubset} alert={<AlertMessages alerts={liveIOC.alerts} />} />
<SimpleAccordion summary="IOC Service Control log">
<IOCCommandTable commands={commands}
commandLazyParams={commandLazyParams} setCommandLazyParams={setCommandLazyParams} commandColumnSort={commandColumnSort} setCommandColumnSort={setCommandColumnSort}
rowsPerPage={rowsPerPage} />
</SimpleAccordion>
{(liveIOC.activeDeployment?.host?.csEntryIdValid) &&
<AccessControl allowedRoles={["DeploymentToolAdmin", "DeploymentToolIntegrator"]}
renderNoAccess={() => <></>}>
<SimpleAccordion summary="ProcServLog info" defaultExpanded>
<LokiContainer csEntryId={liveIOC.activeDeployment?.host.csEntryId} iocName={ioc.namingName} isDeployed={isIocDeployed(ioc)} />
</SimpleAccordion>
</AccessControl>
}
</>
);
}
......@@ -16,7 +16,105 @@ import {
// },
// }))(TableRow);
export function KeyValueTable({ obj, variant="overline" }) {
/*
KEY-VALUE table visualiser
VALUE can be an object, or component
If you want to style the while entry, use a records for the VALUE
VALUE should consis of {shownValue:xxx, shownClass:yyy}
*/
export function KeyValueTable({ obj, variant = "overline" }) {
/**
* Trying to extract style class from the entry.
* If there is no style class NULL value will be returned.
*
* @param {*} value: The VALUE part of the entry
* @returns The style class name if it exists in the VALUE part.
* If there is not style class NULL value will be returned
*/
function extractStyle(value) {
if (!value) {
return null;
}
if (typeof (value) !== "object") {
return null;
}
if (value.shownClass) {
return value.shownClass;
}
return null;
}
/**
* Returning the "formatted" KEY part of the entry for overline variant.
* If VALUE has style class the KEY part will use the same style.
*
* @param {*} key: The KEY part of the entry
* @param {*} value: Then VALUE part of the entry that may contain Style class
* @returns: The "formatted" KEY part for the table
*/
function extractKey(key, value) {
const externalStyle = extractStyle(value);
if (externalStyle) {
return <Typography variant="overline" className={externalStyle}>
{key}
</Typography>
}
return (<Typography variant="overline">
{key}
</Typography>)
}
/**
* Returning the "formatted" VALUE part of the entry.
* If the VALUE part contains style class it will use it.
*
* @param {*} value: The VALUE part of the entry that may contain Style class
* @returns: The "formatted" VALUE part for the table
*/
function extractValue(value) {
const externalStyle = extractStyle(value);
if (externalStyle) {
return <div className={externalStyle}>{value.shownValue}</div>
}
return typeof (value) !== "object" ?
<Typography>
{`${value}`}
</Typography>
: <div>{value}</div>
}
/**
* Returning the "formatted" KEY part of the entry for table variant.
* If VALUE has style class the KEY part will use the same style.
*
* @param {*} key: The KEY part of the entry
* @param {*} value: Then VALUE part of the entry that may contain Style class
* @returns: The "formatted" KEY part for the table
*/
function extractKeyForTable(key, value) {
const externalStyle = extractStyle(value);
if (externalStyle) {
return <div className={externalStyle}>
<strong>{key}</strong>
</div>
}
return <strong>{key}</strong>;
}
return (
<Container style={{ overflow: "auto" }}>
<Table>
......@@ -26,22 +124,16 @@ export function KeyValueTable({ obj, variant="overline" }) {
{
(variant === "table") &&
<TableCell >
<strong>{key}</strong>
{extractKeyForTable(key, obj[key])}
</TableCell>
}
<TableCell>
{
(variant === "overline") &&
<Typography variant="overline">
{key}
</Typography>
extractKey(key, obj[key])
}
{
typeof(obj[key]) !== "object" ?
<Typography>
{`${obj[key]}`}
</Typography>
: <div>{obj[key]}</div>
extractValue(obj[key])
}
</TableCell>
</TableRow>
......
......@@ -157,6 +157,12 @@ export const theme = createMuiTheme({
},
'cccecustomtable': {
fontSize: 14,
},
infoBadge: {
bgColor: '#ececec'
},
iocNotDeployed: {
color: '#b2b2b2'
}
});
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment