Skip to content

Commit

Permalink
Fix Versions page closes #410, credits to EliasVal <3 (#432)
Browse files Browse the repository at this point in the history
* Fix Versions page closes #410, credits to EliasVal <3

Original author: https://github.com/EliasVal

See #412

* Replace icons with text for better dark and light theme

* Remove extra lines and comments

* Update completed emoji for better dark and light theme

* Update fontSize for arrow icon in versions list
  • Loading branch information
GabLeRoux authored Oct 24, 2023
1 parent 3711393 commit 8a8a225
Show file tree
Hide file tree
Showing 14 changed files with 514 additions and 82 deletions.
93 changes: 93 additions & 0 deletions src/components/docs/versions/builds/build-failure-details.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import React, { useReducer } from 'react';
import CodeBlock from '@theme/CodeBlock';

interface Props {
ciJob;
ciBuild;
repoVersionInfo;
editorVersionInfo;
style;
}

const BuildFailureDetails = ({
ciJob,
repoVersionInfo,
editorVersionInfo,
ciBuild,
...rest
}: Props) => {
const { editorVersion, baseOs, targetPlatform } = ciBuild.buildInfo;
const { major, minor, patch } = repoVersionInfo;

const reducer = (state, action) => {
const { tag, value } = action;
return { ...state, [tag]: value };
};

const [tags /* , dispatch */] = useReducer(reducer, {
[`${baseOs}-${editorVersion}-${targetPlatform}-${major}`]: '❓',
[`${baseOs}-${editorVersion}-${targetPlatform}-${major}.${minor}`]: '❓',
[`${baseOs}-${editorVersion}-${targetPlatform}-${major}.${minor}.${patch}`]: '❓',
[`${editorVersion}-${targetPlatform}-${major}`]: '❓',
[`${editorVersion}-${targetPlatform}-${major}.${minor}`]: '❓',
[`${editorVersion}-${targetPlatform}-${major}.${minor}.${patch}`]: '❓',
});

// Todo - fetch docker info from dockerhub for all tags, or do it on the server
// useEffect(() => {
// (async () => {
// const repo = 'unityci/editor';
// for (const tag of Object.keys(tags)) {
// const requestUrl = `https://index.docker.io/v1/repositories/${repo}/tags/${tag}`;
// try {
// const response = await fetch(requestUrl);
// dispatch({ tag, value: response.status === 0 });
// } catch (error) {
// dispatch({ tag, value: false });
// }
// }
// })();
// }, []);

const { changeSet } = editorVersionInfo;
const buildCommand = `#!/usr/bin/env bash
git clone git@github.com:game-ci/docker.git
cd docker
editor_version=${editorVersion}
change_set=${changeSet}
base_os=${baseOs}
target_platform=${targetPlatform}
image_name=unityci-editor:$editor_version-$target_platform
docker build . \\
--file ./images/$base_os/editor/Dockerfile \\
-t $image_name \\
--build-arg=version=$editor_version \\
--build-arg=changeSet=$change_set \\
--build-arg=module=$target_platform
`;

const pullCommand = `docker pull unityci/editor:${baseOs}-${editorVersion}-${targetPlatform}-${major}.${minor}.${patch}`;

return (
<div {...rest}>
<h4>CI Job identification</h4>
<CodeBlock language="json">{JSON.stringify(ciJob, null, 2)}</CodeBlock>
<br />
<h4>Commands</h4>
<p>Build the docker image locally for debugging:</p>
<CodeBlock language="bash">{buildCommand}</CodeBlock>
<p>Pull this docker image:</p>
<CodeBlock language="bash">{pullCommand}</CodeBlock>
<br />
<h4>Associated tags on docker hub</h4>
<CodeBlock language="json">{JSON.stringify(tags, null, 2)}</CodeBlock>
<br />
<h4>CI Build details</h4>
<CodeBlock language="json">{JSON.stringify(ciBuild, null, 2)}</CodeBlock>
</div>
);
};

export default BuildFailureDetails;
83 changes: 83 additions & 0 deletions src/components/docs/versions/builds/build-row.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import React, { useState } from 'react';
import DockerImageLinkOrRetryButton, {
type Record,
} from '@site/src/components/docs/versions/docker-image-link-or-retry-button';
import Spinner from '@site/src/components/molecules/spinner';
import Tooltip from '@site/src/components/molecules/tooltip/tooltip';
import styles from './builds.module.scss';

const mapBuildStatusToIcon = {
started: <Spinner type="slow" />,
failed: '⚠',
published: '✅',
};

type Props = {
children: React.JSX.Element | React.JSX.Element[];
build: Record;
};

const CopyToClipboard = (copyString: string) => {
navigator.clipboard.writeText(copyString);
};

export default function BuildRow({ children, build }: Props) {
const [expanded, setExpanded] = useState(false);
const [toolbarContent, setToolbarContent] = useState('Click to copy');

const MapBuildStatusToElement = (status: string) => {
const icon = mapBuildStatusToIcon[status];

switch (status) {
case 'started':
return <Spinner type="slow" />;
case 'failed':
return <Tooltip content={build.failure?.reason}>{icon}</Tooltip>;
case 'published':
return icon;
default:
return status;
}
};

return (
<>
<tr className={styles.tableRow}>
<td
onClick={() => setExpanded(!expanded)}
className="text-center select-none cursor-pointer text-2xl"
>
{expanded ? '-' : '+'}
</td>
<td className="text-center">{MapBuildStatusToElement(build.status)}</td>
<td>
<span>
<Tooltip content={toolbarContent}>
<button
onClick={() => {
CopyToClipboard(build.buildId);
setToolbarContent('Copied to clipboard!');
}}
onMouseLeave={() => {
setToolbarContent('Click to copy');
}}
type="button"
>
{build.buildId}
</button>
</Tooltip>
<DockerImageLinkOrRetryButton record={build} />
</span>
</td>
<td>{build.imageType}</td>
<td>{build.buildInfo.baseOs}</td>
<td>{build.buildInfo.targetPlatform}</td>
</tr>
{expanded && (
<tr className={styles.expandedContentRow}>
<td colSpan={6}>{children}</td>
</tr>
)}
</>
);
}
22 changes: 22 additions & 0 deletions src/components/docs/versions/builds/builds.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.stickyRow:global(.ant-table-row.ant-table-row-level-0) > :global(td) {
position: sticky;
top: 99px; /* height of the collapse-item-header + the parent tr > td sticky */
background-color: rgb(255, 255, 255);
z-index: 2;
box-shadow: 0 0 25px rgba(255,255,255,1), 0 0 15px rgba(255,255,255,1), 0 0 20px rgba(255,255,255,1);
clip-path: inset(-25px 0 0 0);
}

.stickyRow:global(.ant-table-row.ant-table-row-level-0) > :global(td:not(:last-child)) {
clip-path: inset(-25px -1px 0 0); /* fix for space from responsive vs fixed width on cells */
}

.expandedContentRow {
height: 0;
overflow: hidden;
}


.tableRow {
width: 100%;
}
62 changes: 62 additions & 0 deletions src/components/docs/versions/builds/builds.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react';
import { useFirestore, useFirestoreCollectionData } from 'reactfire';
import BuildFailureDetails from '@site/src/components/docs/versions/builds/build-failure-details';
import styles from './builds.module.scss';
import BuildRow from './build-row';
import { Record } from '../docker-image-link-or-retry-button';

interface RepoVersionInfo {
version: string;
major: number;
minor: number;
patch: number;
}

interface Props {
ciJobId: string;
repoVersionInfo: RepoVersionInfo;
editorVersionInfo;
}

const Builds = ({ ciJobId, repoVersionInfo, editorVersionInfo }: Props) => {
const loading = <p>Fetching builds...</p>;

const ciBuilds = useFirestore().collection('ciBuilds').where('relatedJobId', '==', ciJobId);

const { status, data } = useFirestoreCollectionData<{ [key: string]: any }>(ciBuilds);
const isLoading = status === 'loading';

if (isLoading) {
return loading;
}

const expandable = {
expandedRowRender: (record) => (
<BuildFailureDetails
style={{ margin: 0 }}
ciJob={ciJobId}
editorVersionInfo={editorVersionInfo}
repoVersionInfo={repoVersionInfo}
ciBuild={record}
/>
),
};

return (
<table className="w-full max-w-screen-lg block border-collapse">
<tr className={styles.tableRow}>
<th> </th>
<th className="text-center">Status</th>
<th>Build ID</th>
<th>Image type</th>
<th>OS</th>
<th>Target Platform</th>
</tr>
{data.map((build: Record) => (
<BuildRow build={build}>{expandable.expandedRowRender(build)}</BuildRow>
))}
</table>
);
};

export default Builds;
11 changes: 9 additions & 2 deletions src/components/docs/versions/date-time.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';
import Tooltip from '../../molecules/tooltip/tooltip';

interface Props {
utcSeconds: number;
Expand All @@ -10,16 +11,22 @@ const options: Intl.DateTimeFormatOptions = {
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
timeZoneName: 'short',
hour12: true,
};

const DateTime = ({ utcSeconds }: Props) => {
const date = new Date(0); // Use epoch

date.setUTCSeconds(utcSeconds);

return <span>{`${date.toLocaleString('en-GB', options)}`}</span>;
return (
<Tooltip content={`${date.toLocaleString('en-GB', options)}`}>
<span style={{ color: 'rgba(255, 255, 255, 0.4)' }}>
<u>( ... )</u>
</span>
</Tooltip>
);
};

export default DateTime;
40 changes: 23 additions & 17 deletions src/components/docs/versions/docker-image-link-or-retry-button.tsx
Original file line number Diff line number Diff line change
@@ -1,30 +1,36 @@
import { Tooltip } from 'antd';
import React, { useState } from 'react';
import { HiOutlineRefresh } from 'react-icons/hi';
import { SimpleAuthCheck } from '@site/src/components/auth/safe-auth-check';
import DockerImageLink from '@site/src/components/docs/versions/docker-image-link';
import { useAuthenticatedEndpoint } from '@site/src/core/hooks/use-authenticated-endpoint';
import { useNotification } from '@site/src/core/hooks/use-notification';
import Spinner from '@site/src/components/molecules/spinner';
import Tooltip from '@site/src/components/molecules/tooltip/tooltip';

interface Props {
record: {
buildId: string;
relatedJobId: string;
buildInfo: {
baseOs: string;
editorVersion: string;
targetPlatform: string;
repoVersion: string;
};
dockerInfo: {
imageRepo: string;
imageName: string;
};
status: string;
type Record = {
buildId: string;
relatedJobId: string;
buildInfo: {
baseOs: string;
editorVersion: string;
targetPlatform: string;
repoVersion: string;
};
dockerInfo: {
digest: string;
imageRepo: string;
imageName: string;
};
status: string;
[key: string]: any;
};

interface Props {
record: Record;
}

export { Record };

const DockerImageLinkOrRetryButton = ({ record }: Props) => {
const { buildInfo, dockerInfo, buildId, relatedJobId, status } = record;
const { baseOs, editorVersion, targetPlatform, repoVersion } = buildInfo;
Expand Down Expand Up @@ -55,7 +61,7 @@ const DockerImageLinkOrRetryButton = ({ record }: Props) => {

return (
<SimpleAuthCheck fallback={<span />} requiredClaims={{ admin: true }}>
<Tooltip title={`Delete tag "${imageTag}" then click this retry button.`}>
<Tooltip content={`Delete tag "${imageTag}" then click this retry button.`}>
<button
type="button"
onClick={onClick}
Expand Down
26 changes: 15 additions & 11 deletions src/components/docs/versions/docker-image-link.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { SiDocker } from 'react-icons/si';
import Tooltip from '../../molecules/tooltip/tooltip';

interface Props {
imageRepo: string;
Expand All @@ -9,17 +10,20 @@ interface Props {

const DockerImageLink = ({ imageRepo, imageName, imageTag }: Props) => {
return (
<a
aria-label="Image url"
target="_blank"
rel="noreferrer"
href={
`https://hub.docker.com/repository/docker/${imageRepo}/${imageName}/tags` +
`?page=1&ordering=last_updated&name=${imageTag}`
}
>
<SiDocker />
</a>
<Tooltip content="Dockerhub Image">
<a
aria-label="Image url"
target="_blank"
rel="noreferrer"
href={
`https://hub.docker.com/repository/docker/${imageRepo}/${imageName}/tags` +
`?page=1&ordering=last_updated&name=${imageTag}`
}
className="align-middle ml-2 text-blue-600"
>
<SiDocker />
</a>
</Tooltip>
);
};

Expand Down
Loading

0 comments on commit 8a8a225

Please sign in to comment.