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
15 changes: 10 additions & 5 deletions Environment/mock/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,18 @@
"start": "node index.js"
},
"devDependencies": {
"express": "4.18.1",
"@botchris/grpc-web-mock": "0.0.7",
"@dolittle/contracts.web": "7.5.0-boromir.0",
"@dolittle/rudiments": "6.0.0",
"@grafana/lezer-logql": "0.1.0",
"@prometheus-io/lezer-promql": "0.37.1",
"@lezer/lr": "1.2.3",
"@lezer/highlight": "1.1.0",
"@lezer/lr": "1.2.3",
"@prometheus-io/lezer-promql": "0.37.1",
"express": "4.18.1",
"express-ws": "5.0.2",
"node-pty": "0.10.1",
"jabber": "1.4.0"
"jabber": "1.4.0",
"node-pty": "0.10.1"
},
"dependencies": {
}
}
2 changes: 2 additions & 0 deletions Environment/mock/proxy/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
const { Router } = require('express');

const shell = require('./shell');
const runtimeManagement = require('./runtimeManagement');

const ports = Router({ mergeParams: true });
ports.use('/shell', shell);
ports.use('/runtime-management', runtimeManagement);

ports.get('/:port/*', (req, res) => {
const { applicationId, environment, microserviceId, port } = req.params;
Expand Down
13 changes: 13 additions & 0 deletions Environment/mock/proxy/runtimeManagement/artifacts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

const { Artifact } = require('@dolittle/contracts.web/Artifacts/Artifact_pb');
const { toUuid } = require('./guids')
module.exports = {
pbArtifact: (guidString, generation = 1) => {
const artifact = new Artifact();
artifact.setId(toUuid(guidString));
artifact.setGeneration(generation);
return artifact;
}
}
35 changes: 35 additions & 0 deletions Environment/mock/proxy/runtimeManagement/client/buildResults.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

const { ArtifactBuildResult, BuildResult, BuildResults } = require('@dolittle/contracts.web/Runtime/Client/BuildResult_pb');
const {GetBuildResultsResponse } = require('@dolittle/contracts.web/Runtime/Management/Client/Client_pb');
const { pbArtifact } = require('../artifacts')
const { respondWith } = require('../responses')
module.exports = {
emptyBuildResults: () => {
return new BuildResults();
},
artifactBuildResult: (idString, alias = '', generation = 1, buildResult = undefined) => {
const result = new ArtifactBuildResult();
result.setAritfact(pbArtifact(idString, generation));
result.setAlias(alias);
result.setBuildresult(buildResult);
return result;
},
buildResult: (message, type) => {
const result = new BuildResult();
result.setMessage(message);
result.setType(type);
return result;
},
respondWith: (res, buildResults) => {
const response = new GetBuildResultsResponse();
response.setBuildresults(buildResults);
respondWith(res, response);
},
type: {
Information: BuildResult.Type.INFORMATION,
Failure: BuildResult.Type.FAILURE,
Error: BuildResult.Type.ERROR,
}
}
57 changes: 57 additions & 0 deletions Environment/mock/proxy/runtimeManagement/client/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

const { Router } = require('express');
const { artifactBuildResult, buildResult, emptyBuildResults, respondWith, type } = require('./buildResults');
const routes = module.exports = Router({ mergeParams: true });

const characters ='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
function generateString(length) {
let result = ' ';
const charactersLength = characters.length;
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
}

return result;
}

const messages = {
short: () => generateString(20),
long: () => generateString(200)
}

const createArtifactBuildResults = () => [
artifactBuildResult('72426059-f47c-4311-86c8-2a4e47fa2a4a', 'Some Alias', 1, buildResult(messages.short(), type.Information)),
artifactBuildResult('72426059-f47c-4311-86c8-2a4e47fa2a4a', 'Some Alias', 1, buildResult(messages.long(), type.Information)),
artifactBuildResult('b46d86d7-7c10-40dd-a4ee-d9d05259c676', 'With Error', 1, buildResult(messages.short(), type.Information)),
artifactBuildResult('b46d86d7-7c10-40dd-a4ee-d9d05259c676', 'With Error', 1, buildResult(messages.long(), type.Error)),
artifactBuildResult('6eec65ea-71ac-4fe4-b74c-a42de5f9c4b9', 'With Failure', 1, buildResult(messages.short(), type.Information)),
artifactBuildResult('6eec65ea-71ac-4fe4-b74c-a42de5f9c4b9', 'With Failure', 1, buildResult(messages.long(), type.Failure)),
artifactBuildResult('bc226a57-5699-4923-9600-67da7e153784', 'Same Alias As Another', 1, buildResult(messages.short(), type.Information)),
artifactBuildResult('e62f7431-19b3-41f0-a6e3-bced556e510d', 'Same Alias As Another', 1, buildResult(messages.short(), type.Information)),
artifactBuildResult('5b79b500-b43a-4805-84cb-14740317b45d', 'Different Generations', 1, buildResult(messages.short(), type.Information)),
artifactBuildResult('5b79b500-b43a-4805-84cb-14740317b45d', 'Different Generations', 2, buildResult(messages.short(), type.Information)),
artifactBuildResult('31e18f24-aa1a-448a-b0a2-a82f1b825edf', 'Different Aliases1', 1, buildResult(messages.short(), type.Information)),
artifactBuildResult('31e18f24-aa1a-448a-b0a2-a82f1b825edf', 'Different Aliases2', 1, buildResult(messages.short(), type.Information)),
];

const other = [
buildResult(messages.short(), type.Information),
buildResult(messages.short(), type.Error),
buildResult(messages.short(), type.Failure),
buildResult(messages.long(), type.Information),
buildResult(messages.long(), type.Error),
buildResult(messages.long(), type.Failure),
];
routes.post('/GetBuildResults', (req, res) => {
const buildResults = emptyBuildResults();
buildResults.setEventtypesList(createArtifactBuildResults());
buildResults.setAggregaterootsList(createArtifactBuildResults());
buildResults.setEmbeddingsList(createArtifactBuildResults());
buildResults.setEventhandlersList(createArtifactBuildResults());
buildResults.setFiltersList(createArtifactBuildResults());
buildResults.setProjectionsList(createArtifactBuildResults());
buildResults.setOtherList(other);
respondWith(res, buildResults);
});
13 changes: 13 additions & 0 deletions Environment/mock/proxy/runtimeManagement/guids.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

const { Uuid } = require('@dolittle/contracts.web/Protobuf/Uuid_pb');
const { Guid } = require('@dolittle/rudiments');

module.exports = {
toUuid: (guidString) => {
const uuid = new Uuid();
uuid.setValue(new Uint8Array(Guid.parse(guidString).bytes));
return uuid;
}
}
15 changes: 15 additions & 0 deletions Environment/mock/proxy/runtimeManagement/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

const { Router } = require('express');
const routes = module.exports = Router({ mergeParams: true });
const { ToTextResponse } = require('@botchris/grpc-web-mock');
const client = require('./client');

routes.get('/*', (req, res) => {
console.log('Getting RUntime Management Proxy');
res.status(200).end();
})

routes.use('/dolittle.runtime.client.management.Client', client);

13 changes: 13 additions & 0 deletions Environment/mock/proxy/runtimeManagement/responses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

const { ToTextResponse } = require('@botchris/grpc-web-mock');

module.exports = {
respondWith: (res, protobuf) => {
const result = ToTextResponse(protobuf);
res.set(result.headers)
.status(result.statusCode)
.send(result.body);
}
}
1 change: 1 addition & 0 deletions Source/DesignSystem/atoms/Tabs/Tabs.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const { metadata, createStory } = componentStories(Tabs);
export default metadata;

export const Normal = createStory({
id: 'Tabs',
tabs: [
{
label: 'First tab',
Expand Down
16 changes: 11 additions & 5 deletions Source/DesignSystem/atoms/Tabs/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,26 @@ export type Tab = {

export type TabsProps = {
tabs: Tab[];
id?: string,
sx?: any;
};

export const Tabs = (props: TabsProps) => {
const getCacheKey = () => `selectedTab#${props.id}`;
const [currentTab, setCurrentTab] = useState(0);

useEffect(() => {
const storedSelectedOption = parseInt(sessionStorage.getItem('selectedTab') || '0');
setCurrentTab(storedSelectedOption);
}, []);
if (!!props.id) {
useEffect(() => {
const storedSelectedOption = parseInt(sessionStorage.getItem(getCacheKey()) || '0');
setCurrentTab(storedSelectedOption);
}, []);
}

const handleChange = (event: React.ChangeEvent<{}>, newValue: number) => {
setCurrentTab(newValue);
sessionStorage.setItem('selectedTab', newValue.toString());
if (!!props.id) {
sessionStorage.setItem(getCacheKey(), newValue.toString());
}
};

return (
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import { Uuid } from '@dolittle/contracts.web/Protobuf/Uuid_pb';
import { Artifact as PbArtifact } from '@dolittle/contracts.web/Artifacts/Artifact_pb';
import { Guid } from '@dolittle/rudiments';
import { Artifact } from './Types';

export function toGuid(uuid: Uuid) {
return new Guid(uuid.getValue_asU8());
}

export function toUuid(guid: Guid | string) {
const uuid = new Uuid();
uuid.setValue(new Uint8Array(Guid.as(guid).bytes));
return uuid;
}

export function toArtifact(artifact: PbArtifact): Artifact {
return {generation: artifact.getGeneration(), id: toGuid(artifact.getId()!).toString()};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

export type Artifact = {
id: string,
generation: number
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import React, {} from 'react';

import { View as BuildResults} from './buildResults/View';
import { useRuntimeManagementAvailable } from './useRuntimeManagement';

export type ViewProps = {
applicationId: string;
environment: string;
microserviceId: string;
};

export const View = (props: ViewProps) => {
const buildResultsAvailable = useRuntimeManagementAvailable(props.applicationId, props.environment, props.microserviceId);
return (
<>
{buildResultsAvailable
? <BuildResults applicationId={props.applicationId} environment={props.environment} microserviceId={props.microserviceId}/>
: <h2>There are not any management endpoints on your microservice.</h2>
}
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
// Copyright (c) Dolittle. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

import React, {} from 'react';
import { Typography, IconButton } from '@mui/material';
import { KeyboardArrowUp, KeyboardArrowDown } from '@mui/icons-material';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';

import { ArtifactResults, BuildResult } from './BuildResults';

export type ArtifactsResultsProps = {
results: ArtifactResults,
type: string
};

function toCombinedKey(id: string, alias: string, generation: number) {
return `${id}/${alias}/${generation}`;
}

function toGroupedResults(results: ArtifactResults) {
const result = new Map<string, {id: string, alias: string, generation: number, buildResults: BuildResult[]}>();
results.forEach(_ => {
const combinedKey = toCombinedKey(_.artifact.id, _.alias, _.artifact.generation);
let item = result.get(combinedKey);
if (item === undefined) {
item = {id: _.artifact.id, alias: _.alias, generation: _.artifact.generation, buildResults: []};
}
item.buildResults.push(_.buildResult);
result.set(combinedKey, item);
});
return result;
}

const ExpandableRow = ({children, buildMessages: buildResults}: {children: JSX.Element[], buildMessages: BuildResult[]}) => {
const [isExpanded, setIsExpanded] = React.useState(false);
return (
<>
<TableRow>
<TableCell padding="checkbox">
<IconButton onClick={() => setIsExpanded(!isExpanded)}>
{isExpanded ? <KeyboardArrowUp /> : <KeyboardArrowDown />}
</IconButton>
</TableCell>
{children}
</TableRow>
{isExpanded && buildResults.map((result, i) => (
<TableRow key={i}>
<TableCell padding="checkbox" />
<TableCell colSpan={4}>{`${result.type}: ${result.message}`}</TableCell>
</TableRow>
))}
</>
);
};

export const ArtifactsResultsView = (props: ArtifactsResultsProps) => {
if (!props.results?.length) {
return <></>;
}

const results = toGroupedResults(props.results);
return (
<>
<Typography variant='h3' sx={{ my: 2 }}>{props.type}</Typography>
<TableContainer>
<Table size="small" aria-label="simple table">
<TableHead>
<TableRow>
<TableCell align="left"></TableCell>
<TableCell align="left">Alias</TableCell>
<TableCell align="left">Id</TableCell>
<TableCell align="left">Generation</TableCell>
</TableRow>
</TableHead>
<TableBody>
{Array.from(results, ([combinedKey, {id, alias, generation, buildResults}]) => (
<ExpandableRow
key={combinedKey}
buildMessages={buildResults}
>
<TableCell sx={{color: buildResults.findIndex(_ => _.isFailed) === -1 ? undefined : 'red'}} align="left">{alias ?? 'No Alias'}</TableCell>
<TableCell align="left">{id}</TableCell>
<TableCell align="left">{generation}</TableCell>
</ExpandableRow>
))}
</TableBody>
</Table>
</TableContainer>
</>
);
};

Loading