Skip to content
This repository has been archived by the owner on Oct 28, 2023. It is now read-only.

Commit

Permalink
demo server
Browse files Browse the repository at this point in the history
  • Loading branch information
yylyyl committed Sep 20, 2023
1 parent e274193 commit c0eaed9
Show file tree
Hide file tree
Showing 26 changed files with 351 additions and 131 deletions.
Binary file added public/favicon.ico
Binary file not shown.
Binary file removed public/favicon.png
Binary file not shown.
2 changes: 1 addition & 1 deletion public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.png" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<!-- <link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />-->
Expand Down
21 changes: 21 additions & 0 deletions src/components/ContainerUpLearnMore.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import {Alert} from "@mui/material";

export default function ContainerUpLearnMore({variant}) {
if (!process.env.REACT_APP_CONTAINERUP_DEMO) {
return '';
}

if (variant === "long") {
return (
<Alert severity="info" sx={{mt: '5px'}}>
Love this project? Learn more about ContainerUp <a href="https://containerup.org/" target="_blank" rel="noreferrer">here</a>.
</Alert>
);
}

return (
<Alert severity="info" sx={{mt: '5px'}}>
Learn more about ContainerUp <a href="https://containerup.org/" target="_blank" rel="noreferrer">here</a>.
</Alert>
);
}
10 changes: 7 additions & 3 deletions src/components/MyDrawerItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ import ListItemText from "@mui/material/ListItemText";
import ListItem from "@mui/material/ListItem";
import {useLocation, useNavigate} from "react-router-dom";

export default function MyDrawerItem({drawerOpen, text, icon, path, or}) {
export default function MyDrawerItem({drawerOpen, text, icon, path, or, href}) {
const navigate = useNavigate();
const {pathname} = useLocation();

const handleClick = () => {
navigate(path)
}
if (href) {
window.open(href, '_blank').focus();
return;
}
navigate(path);
};

let selected = false;
if (pathname.indexOf(path) === 0
Expand Down
39 changes: 0 additions & 39 deletions src/components/MyTerminal.js

This file was deleted.

1 change: 0 additions & 1 deletion src/components/MyTerminalTwoWay.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ export default function MyTerminalTwoWay({dataSide}) {
default:
console.log('unknown dataSide command', data);
}
xterm.write(data)
});
xterm.onData(str => dsWriter({type: 'data', data: str}));
xterm.onResize(({cols, rows}) => reportSize({cols, rows}));
Expand Down
9 changes: 9 additions & 0 deletions src/components/WebsocketConnectError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import {Alert} from "@mui/material";

export default function WebsocketConnectError() {
return (
<Alert severity="error">
Failed to connect websocket.
</Alert>
);
}
22 changes: 22 additions & 0 deletions src/components/WebsocketDisconnectError.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import {enqueueSnackbar} from "notistack";
import {Button} from "@mui/material";
import RefreshIcon from '@mui/icons-material/Refresh';

export function showWebsocketDisconnectError() {
const action = snackbarId => (
<Button
color="inherit"
size="small"
startIcon={<RefreshIcon />}
onClick={() => window.location.reload()}
>
Reload
</Button>
);

enqueueSnackbar('Websocket disconnected. The information on this page is NOT up-to-date.', {
variant: 'warning',
persist: true,
action
});
}
31 changes: 28 additions & 3 deletions src/lib/dataProvidor.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ const makeAioConnection = (onData, onOpen, onError, onClose) => {
ws.close();
state = 99;

onError(new Error('Websocket error'));
onError(new WebsocketError('Cannot connect to websocket', websocketErrorTypeConnect));
});
ws.addEventListener('close', event => {
if (state === 99) {
Expand All @@ -57,7 +57,7 @@ const makeAioConnection = (onData, onOpen, onError, onClose) => {
if (code === 4001) {
err = dataModel.errors.errNoLogin;
} else {
err = new Error(`Websocket closed ${code} ${reason}`);
err = new WebsocketError(`Websocket closed ${code} ${reason}`, websocketErrorTypeDisconnect);
}
onClose(err);
});
Expand Down Expand Up @@ -147,7 +147,7 @@ const aioMain = onAioClose => {
return () => commonUnsubscribe(index, fnUnsub);
}
if (closed) {
onError(new Error('connection closed'));
onError(new WebsocketError('connection closed', websocketErrorTypeDisconnect));
return () => {};
}

Expand Down Expand Up @@ -230,3 +230,28 @@ export function aioProvider() {
});
return aio;
}

class WebsocketError extends Error {
constructor(message, type) {
super(message);
this.name = this.constructor.name;
this.errType = type;
}
}

const websocketErrorTypeDisconnect = 'disconnect';
const websocketErrorTypeConnect = 'connect';

export function isDisconnectError(err) {
if (!(err instanceof WebsocketError)) {
return false;
}
return err.errType === websocketErrorTypeDisconnect;
}

export function isConnectError(err) {
if (!(err instanceof WebsocketError)) {
return false;
}
return err.errType === websocketErrorTypeConnect;
}
42 changes: 42 additions & 0 deletions src/lib/ga4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useEffect } from "react";
import { useLocation } from "react-router-dom";

export const useGA4 = () => {
const ga4 = process.env.REACT_APP_CONTAINERUP_GA4;

useEffect(() => {
if (!ga4) {
return;
}

window.dataLayer = window.dataLayer || [];
function gtag(){window.dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', ga4, {
send_page_view: false
});

const script = document.createElement('script');
script.src = "https://www.googletagmanager.com/gtag/js?id=" + ga4;
script.async = true;

document.body.appendChild(script);
return () => {
document.body.removeChild(script);
};
}, [ga4]);

const location = useLocation();
useEffect(() => {
if (!ga4) {
return;
}

function gtag(){window.dataLayer.push(arguments);}
gtag("event", "page_view", {
page_path: location.pathname + location.search + location.hash,
page_search: location.search,
page_hash: location.hash,
});
}, [ga4, location]);
};
17 changes: 13 additions & 4 deletions src/routes/Containers/ContainerDetail.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import {Box, Tab, Tabs} from "@mui/material";
import {Link, Outlet, useLocation, useNavigate, useParams} from "react-router-dom";
import {useEffect, useMemo, useState} from "react";
import {getController} from "../../lib/HostGuestController";
import {aioProvider} from "../../lib/dataProvidor";
import {aioProvider, isDisconnectError} from "../../lib/dataProvidor";
import dataModel from "../../lib/dataModel";
import {showWebsocketDisconnectError} from "../../components/WebsocketDisconnectError";

const tabs = [{
to: "overview",
Expand Down Expand Up @@ -112,13 +113,21 @@ export default function ContainerDetail() {
if (error.response) {
e = error.response.data;
}
setErrMsg(e);
setLoading(false);
if (loading) {
setErrMsg(e);
setLoading(false);
} else {
if (isDisconnectError(error)) {
showWebsocketDisconnectError();
} else {
setErrMsg(e);
}
}
};

const cancel = aioProvider().container(containerId, onData, onError)
return () => cancel();
}, [containerId, navigate, pathname]);
}, [containerId, loading, navigate, pathname]);

return (
<>
Expand Down
14 changes: 10 additions & 4 deletions src/routes/Containers/ContainerDetailButtons.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import SaveIcon from "@mui/icons-material/Save";
import ListItemText from "@mui/material/ListItemText";
import {green, orange, red, yellow} from "@mui/material/colors";
import DeleteIcon from "@mui/icons-material/Delete";
import {useEffect, useState} from "react";
import {useCallback, useEffect, useState} from "react";
import StopIcon from "@mui/icons-material/Stop";
import PlayArrowIcon from "@mui/icons-material/PlayArrow";
import {getController} from "../../lib/HostGuestController";
Expand Down Expand Up @@ -192,6 +192,10 @@ export default function ContainerDetailButtons() {
return () => ac.abort();
}, [actioning, container, navigate, pathname, action]);

const handleDialogCommitClose = useCallback(() => {
setDialogCommitOpen(false)
}, []);

const st = getStatusText(container);

if (!container) {
Expand All @@ -205,7 +209,8 @@ export default function ContainerDetailButtons() {
{container && (
<>
<ContainerDialogRemove
container={container}
containerName={container.Name}
containerIdShort={container.Id.substring(0, 12)}
actioning={dialogRemoveOpen && actioning}
open={dialogRemoveOpen}
onClose={() => setDialogRemoveOpen(false)}
Expand All @@ -214,8 +219,9 @@ export default function ContainerDetailButtons() {

<ContainerDialogCommit
open={dialogCommitOpen}
container={container}
onClose={() => setDialogCommitOpen(false)}
containerName={container.Name}
containerIdShort={container.Id.substring(0, 12)}
onClose={handleDialogCommitClose}
/>
</>
)}
Expand Down
3 changes: 1 addition & 2 deletions src/routes/Containers/Create/ContainerCreate.js
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ export default function ContainerCreate() {
return {
container: v.container,
host: v.host,
rw: v.rw
readWrite: v.rw
};
}),
ports: ports.map(p => {
Expand All @@ -195,7 +195,6 @@ export default function ContainerCreate() {
return;
}

console.log(error)
let errStr = error.toString();
if (dataModel.errIsNoLogin(error)) {
errStr = 'Session expired. Reload the page, and try again.';
Expand Down
25 changes: 21 additions & 4 deletions src/routes/Containers/Create/CreateNameImage.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import ImagePullTerminal from "../../Images/List/ImagePullTerminal";
import CreateImagePullActions from "./CreateImagePullActions";
import Pipe from "../../../lib/Pipe";
import CheckIcon from "@mui/icons-material/Check";
import {demoImage} from "../../Images/List/ImagePullDialog";

const checkNameAndGetImage = (containerName, imageId, abortController) => {
const p1 = dataModel.containerInspect(containerName, false, abortController)
Expand Down Expand Up @@ -103,10 +104,22 @@ export default function CreateNameImage({name, image, onConfirm, onEdited}) {
const pullTerminationOnReceive = pullTerminationPipe.useOnReceive();
const pullTerminationWriter = pullTerminationPipe.useWriter();

const imgPulled = imageName && imageOpt && (
(imageOpt.Names && imageOpt.Names[0] && imageName === imageOpt.Names[0]) ||
(imageOpt.Id && imageName === imageOpt.Id.substring(0, 12))
);
let imgPulled = false;
if (imageName && imageOpt) {
if (imageOpt.Names) {
for (const name of imageOpt.Names) {
if (name === imageName) {
imgPulled = true;
break;
}
}
}
if (!imgPulled) {
if (imageOpt.Id && (imageName === imageOpt.Id.substring(0, 12) || imageOpt.Id === imageName)) {
imgPulled = true;
}
}
}

const [loadingImageDetail, setLoadingImageDetail] = useState(false);

Expand Down Expand Up @@ -384,6 +397,10 @@ export default function CreateNameImage({name, image, onConfirm, onEdited}) {
<>
The image <b>{imageName}</b> is not found locally. <br />
To continue, pull this image first. Pull the image now?

<Alert severity="info">
As a limit of the demo server, please try this one: <b>{demoImage}</b>
</Alert>
</>
)}
</DialogContentText>
Expand Down
Loading

0 comments on commit c0eaed9

Please sign in to comment.