Show deploy step logs in collapsible component (#16)

* Use collapse to display process logs

* Implement functionality to copy log button

* Implement functionality to copy project id

* Add toast for successful copy

---------

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
This commit is contained in:
Nabarun Gogoi 2023-12-21 09:45:14 +05:30 committed by GitHub
parent 318ebdfd26
commit 6590b8f6f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 100 additions and 28 deletions

View File

@ -17,6 +17,7 @@
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
"react-dropdown": "^1.11.0", "react-dropdown": "^1.11.0",
"react-hook-form": "^7.49.0", "react-hook-form": "^7.49.0",
"react-hot-toast": "^2.4.1",
"react-router-dom": "^6.20.1", "react-router-dom": "^6.20.1",
"react-scripts": "5.0.1", "react-scripts": "5.0.1",
"react-tabs": "^6.0.2", "react-tabs": "^6.0.2",

View File

@ -0,0 +1,30 @@
[
"[20:50:03.502] Running build in Washington, D.C., USA (East) iad1",
"[20:50:03.641] Cloning github.com/saugatyadav11/nextjs2 (Branch: main, Commit: 4a5f47f)",
"[20:50:04.004] Previous build cache not available",
"[20:50:04.118] Cloning completed: 480.574ms",
"[20:50:04.382] Running 'vercel build'",
"[20:50:04.879] Vercel CLI 32.7.1",
"[20:50:05.289] Installing dependencies...",
"[20:50:16.267] added 333 packages in 10s",
"[20:50:16.268] 117 packages are looking for funding",
"[20:50:16.268] run 'npm fund' for details",
"[20:50:16.293] Detected Next.js version: 14.0.4",
"[20:50:16.296] Detected 'package-lock.json' generated by npm 7+",
"[20:50:16.297] Running 'npm run build'",
"[20:50:16.937] > nextjs@0.1.0 build",
"[20:50:16.938] > next build",
"[20:50:17.529] Attention: Next.js now collects completely anonymous telemetry regarding usage.",
"[20:50:17.530] This information is used to shape Next.js' roadmap and prioritize features.",
"[20:50:17.530] You can learn more, including how to opt-out if you'd not like to participate in this anonymous program, by visiting the following URL:",
"[20:50:17.530] https://nextjs.org/telemetry",
"[20:50:17.627] ▲ Next.js 14.0.4",
"[20:50:17.628] Creating an optimized production build ...",
"[20:50:25.681] ✓ Compiled successfully",
"[20:50:25.682] Linting and checking validity of types ...",
"[20:50:29.584] Collecting page data ...",
"[20:50:30.505] Generating static pages (0/5) ...",
"[20:50:30.703] Generating static pages (1/5)",
"[20:50:30.704] Generating static pages (2/5)",
"[20:50:30.734] Generating static pages (3/5)"
]

View File

@ -1,7 +1,7 @@
import React from 'react'; import React from 'react';
const HorizontalLine = () => { const HorizontalLine = () => {
return <hr className="h-px bg-slate-200 border-0" />; return <hr className="h-px bg-gray-300 border-0" />;
}; };
export default HorizontalLine; export default HorizontalLine;

View File

@ -1,13 +1,11 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import toast, { Toaster } from 'react-hot-toast';
import { Collapse, Button } from '@material-tailwind/react';
import { Stopwatch, setStopWatchOffset } from '../../../../StopWatch'; import { Stopwatch, setStopWatchOffset } from '../../../../StopWatch';
import FormatMillisecond from '../../../../FormatMilliSecond'; import FormatMillisecond from '../../../../FormatMilliSecond';
import processLogs from '../../../../../assets/process-logs.json';
const PROCESS_LOGS = [
'Lorem Ipsum is simply dummy text of the printing and typesetting industry.',
'Lorem Ipsum has been the industrys standard dummy text ever since the 1500s.',
'When an unknown printer took a galley of type and scrambled it to make a type specimen book.',
];
enum DeployStatus { enum DeployStatus {
PROCESSING = 'progress', PROCESSING = 'progress',
@ -33,8 +31,8 @@ const DeployStep = ({
const [collapse, setCollapse] = useState(false); const [collapse, setCollapse] = useState(false);
return ( return (
<> <div className="border-b-2 border-slate-200">
<div className="border-b-2 border-slate-200 flex justify-between p-2 gap-2"> <div className="flex justify-between p-2 gap-2">
{status === DeployStatus.NOT_STARTED && <div>{step}</div>} {status === DeployStatus.NOT_STARTED && <div>{step}</div>}
{status === DeployStatus.PROCESSING && <div>O</div>} {status === DeployStatus.PROCESSING && <div>O</div>}
{status === DeployStatus.COMPLETE && ( {status === DeployStatus.COMPLETE && (
@ -60,12 +58,27 @@ const DeployStep = ({
</> </>
)} )}
</div> </div>
<div className={`text-sm ${!collapse ? 'hidden' : ''}`}> <Collapse open={collapse}>
{PROCESS_LOGS.map((log, key) => { <div className="p-2 text-sm text-gray-500 h-36 overflow-y-scroll">
return <p key={key}>{log}</p>; {processLogs.map((log, key) => {
return <div key={key}>{log}</div>;
})} })}
<div className="sticky bottom-0 left-1/2 flex justify-center">
<Button
size="sm"
onClick={() => {
navigator.clipboard.writeText(processLogs.join('\n'));
toast.success('Logs copied');
}}
color="blue"
>
^ Copy log
</Button>
</div>
</div>
</Collapse>
<Toaster />
</div> </div>
</>
); );
}; };

View File

@ -1,9 +1,26 @@
import React from 'react'; import React from 'react';
import { useForm } from 'react-hook-form'; import { useForm } from 'react-hook-form';
import toast, { Toaster } from 'react-hot-toast';
import { Button } from '@material-tailwind/react'; import { Button } from '@material-tailwind/react';
import { Input } from '@material-tailwind/react'; import { Input } from '@material-tailwind/react';
const PROJECT_ID = '62f87575-7a2b-4951-8156-9f9821j380d';
const CopyIcon = ({ value }: { value: string }) => {
return (
<span
onClick={() => {
navigator.clipboard.writeText(value);
toast.success('Project ID copied');
}}
className="cursor-pointer"
>
^
</span>
);
};
const GeneralTabPanel = () => { const GeneralTabPanel = () => {
const { handleSubmit, register } = useForm({ const { handleSubmit, register } = useForm({
defaultValues: { defaultValues: {
@ -59,9 +76,10 @@ const GeneralTabPanel = () => {
id="input" id="input"
crossOrigin={undefined} crossOrigin={undefined}
variant="outlined" variant="outlined"
value="62f87575-7a2b-4951-8156-9f9821j380d" value={PROJECT_ID}
size="md" size="md"
disabled disabled
icon={<CopyIcon value={PROJECT_ID} />}
/> />
</div> </div>
<div> <div>
@ -69,6 +87,7 @@ const GeneralTabPanel = () => {
Save Save
</Button> </Button>
</div> </div>
<Toaster />
</form> </form>
); );
}; };

View File

@ -1,9 +1,9 @@
import React from 'react'; import React from 'react';
import { Outlet, useNavigate } from 'react-router-dom'; import { Outlet, Link } from 'react-router-dom';
import HorizontalLine from '../../components/HorizontalLine';
const CreateProject = () => { const CreateProject = () => {
const navigate = useNavigate();
return ( return (
<div className="bg-white rounded-3xl h-full p-4"> <div className="bg-white rounded-3xl h-full p-4">
<div className="flex p-2"> <div className="flex p-2">
@ -11,17 +11,14 @@ const CreateProject = () => {
<h3 className="text-gray-750 text-2xl">Create new project</h3> <h3 className="text-gray-750 text-2xl">Create new project</h3>
</div> </div>
<div className="p-4"> <div className="p-4">
<button <Link to="/">
className="bg-slate-300 text-gray-700 text-sm px-4 py-2 border rounded-full" <button className="bg-slate-300 text-gray-700 text-sm px-4 py-2 border rounded-full">
onClick={() => {
navigate(-1);
}}
>
X X
</button> </button>
</Link>
</div> </div>
</div> </div>
<hr className="h-px bg-slate-200 border-0" /> <HorizontalLine />
<Outlet /> <Outlet />
</div> </div>
); );

View File

@ -6394,6 +6394,11 @@ globby@11.1.0, globby@^11.0.4, globby@^11.1.0:
merge2 "^1.4.1" merge2 "^1.4.1"
slash "^3.0.0" slash "^3.0.0"
goober@^2.1.10:
version "2.1.13"
resolved "https://registry.yarnpkg.com/goober/-/goober-2.1.13.tgz#e3c06d5578486212a76c9eba860cbc3232ff6d7c"
integrity sha512-jFj3BQeleOoy7t93E9rZ2de+ScC4lQICLwiAQmKMg9F6roKGaLSHoCDYKkWlSafg138jejvq/mTdvmnwDQgqoQ==
gopd@^1.0.1: gopd@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz" resolved "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz"
@ -10374,6 +10379,13 @@ react-hook-form@^7.49.0:
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.49.0.tgz#9a91edfba6b6983d4b443653a9b225a780a42b3e" resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-7.49.0.tgz#9a91edfba6b6983d4b443653a9b225a780a42b3e"
integrity sha512-gf4qyY4WiqK2hP/E45UUT6wt3Khl49pleEVcIzxhLBrD6m+GMWtLRk0vMrRv45D1ZH8PnpXFwRPv0Pewske2jw== integrity sha512-gf4qyY4WiqK2hP/E45UUT6wt3Khl49pleEVcIzxhLBrD6m+GMWtLRk0vMrRv45D1ZH8PnpXFwRPv0Pewske2jw==
react-hot-toast@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/react-hot-toast/-/react-hot-toast-2.4.1.tgz#df04295eda8a7b12c4f968e54a61c8d36f4c0994"
integrity sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==
dependencies:
goober "^2.1.10"
react-is@^16.13.1: react-is@^16.13.1:
version "16.13.1" version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"