Skip to content

Commit

Permalink
feat(web): implement support for new operations
Browse files Browse the repository at this point in the history
Implements new UI for deleting and transferring packages.
  • Loading branch information
LordTermor committed Jul 5, 2024
1 parent b046ace commit 1e017f3
Show file tree
Hide file tree
Showing 13 changed files with 930 additions and 185 deletions.
101 changes: 74 additions & 27 deletions web/src/components/CommitCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@
*
*/
import {
faCodeBranch,
faCubes,
faMicrochip,
faArrowsAlt,
faCirclePlus,
faCopy,
faDeleteLeft,
faTrashAlt,
faTrashCan
} from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useMemo } from "react";
import { Card, CardProps } from "react-daisyui";
import { Badge, Button, Card, CardProps } from "react-daisyui";
import SectionLabel from "./SectionLabel";
import _ from "lodash";

export type CommitCardProps = CardProps & {
section: Section;
Expand All @@ -27,35 +31,78 @@ export default function CommitCard(props: CommitCardProps) {
[props.section]
);

const { toAdd, toDelete, toCopy, toMove } = useMemo(
() => props.commit,
[props.commit]
);

return (
<Card
onClick={() => props.onActivate?.(props.section, props.commit)}
{...props}
className="h-30 bg-white"
className="bg-white"
compact="sm"
>
<div className="w-full flex justify-end">
<FontAwesomeIcon
onClick={(e) => {
e.stopPropagation();
if (props.onDeleteRequested)
return props.onDeleteRequested(props.section);
}}
className="px-1"
icon={faTrashCan}
/>
</div>
<Card.Body className="font-bold">
{props.commit.size} package
{props.commit.size == 1 ? "" : "s"}
<Card.Body className="w-full flex-col">
<div className="flex justify-center">
<Badge color="secondary" className="float-right text-white">
<SectionLabel
section={{ branch, repository, architecture }}
/>
</Badge>
</div>
<div className="grid grid-cols-2 grid-rows-2 gap-2">
{[
{
visible: toAdd.size > 0,
icon: faCirclePlus,
text: `To Add: ${toAdd.size}`
},
{
visible: toDelete.size > 0,
icon: faTrashAlt,
text: `To Delete: ${toDelete.size}`
},
{
visible: toCopy.size > 0,
icon: faCopy,
text: `To Copy: ${toCopy.size}`
},
{
visible: toMove.size > 0,
icon: faArrowsAlt,
text: `To Move: ${toMove.size}`
}
].map(
({ visible, icon, text }, index) =>
visible && (
<span
key={index}
className="justify-self-center self-center"
>
<FontAwesomeIcon
icon={icon}
className="mr-1"
/>
{text}
</span>
)
)}
</div>
</Card.Body>
<span className="space-x-4">
<FontAwesomeIcon className="px-1" icon={faCodeBranch} />
{branch}
<FontAwesomeIcon className="px-1" icon={faCubes} />
{repository}
<FontAwesomeIcon className="px-1" icon={faMicrochip} />
{architecture}
</span>
<Card.Actions>
<Button className="w-full flex justify-end" color="ghost">
<FontAwesomeIcon
onClick={(e) => {
e.stopPropagation();
if (props.onDeleteRequested)
return props.onDeleteRequested(props.section);
}}
className="px-1"
icon={faDeleteLeft}
/>
</Button>
</Card.Actions>
</Card>
);
}
139 changes: 129 additions & 10 deletions web/src/components/FileManager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,15 @@
*
*/

import { useEffect, useState } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { faCodeCommit } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
FileArray,
FileBrowserHandle,
FileBrowserProps,
FullFileBrowser as F,
setChonkyDefaults
} from "chonky";

import { Button, Loading } from "react-daisyui";
import Dropzone from "react-dropzone-esm";
import { usePushCommitsHandler, useSections } from "../hooks/BxtHooks";
Expand All @@ -36,14 +34,27 @@ import { ChonkyIconFA } from "chonky-icon-fontawesome";
import { useFilesFromSections } from "../hooks/BxtFsHooks";
import { CommitsState } from "../hooks/useCommits";
import { useOpenHandler } from "../fmActions/OpenAction";
import {
CopyAction,
CopyActionButton,
DeleteAction,
DeleteActionButton,
MoveAction,
MoveActionButton,
useHandler
} from "../fmActions/PackageActions";
import { createCommit, mergeCommits } from "../utils/CommitUtils";

export type FileManagerProps = {
path: string[];
setPath: (path: string[]) => void;
commitsState: CommitsState;
openModalWithCommitHandler: (
isNew: boolean
) => (section: Section, commit: Commit) => void;
section: Section,
commit: Commit,
defaultCheckedAction?: ActionType
) => void;
openSectionSelectModal: (cb: (section?: Section) => void) => void;
openSnapshotModalWithBranchHandler: () => void;
openPackageModal: () => void;
};
Expand Down Expand Up @@ -91,13 +102,106 @@ export default function FileManager(props: FileManagerProps) {
packages ?? []
);

const fileAction = useFileActionHandler([snapshotHandler, openHandler]);

const { commits, addCommit, deleteCommit, clearCommits } =
props.commitsState;

const handleFileAction = useCallback(
(
actionType: "copy" | "move" | "delete",
path: string[] | undefined
) => {
if (!path) {
return;
}

const [section, packageName] = [
SectionUtils.fromPath(path),
path[4]
];

if (!section || !packageName) {
return;
}

const withTargetSection = (targetSection?: Section) => {
let action;
switch (actionType) {
case "copy":
case "move":
if (!targetSection) {
return;
}
action = new Map<string, Section>().set(
packageName,
targetSection
);
break;
case "delete":
action = new Set<string>([packageName]);
break;
}

const existingCommit = commits.get(
SectionUtils.toString(section)
);
const commitAction = {
copy: "toCopy",
move: "toMove",
delete: "toDelete"
}[actionType];

const commit = existingCommit
? mergeCommits(existingCommit, { [commitAction]: action })
: createCommit({ [commitAction]: action });

openModalWithCommitHandler(section, commit, actionType);
};

if (actionType === "delete") {
withTargetSection();
} else {
props.openSectionSelectModal(withTargetSection);
}
},
[commits, openModalWithCommitHandler, props]
);

const copyHandler = useHandler(CopyAction.id, (path) =>
handleFileAction("copy", path)
);

const moveHandler = useHandler(MoveAction.id, (path) =>
handleFileAction("move", path)
);

const deleteHandler = useHandler(DeleteAction.id, (path) =>
handleFileAction("delete", path)
);

const fileAction = useFileActionHandler([
snapshotHandler,
openHandler,
copyHandler,
moveHandler,
deleteHandler
]);

const folderChain = useFolderChainForPath(path);

const fileActions = useMemo(
() => [
DeleteAction,
DeleteActionButton,
CopyAction,
CopyActionButton,
MoveAction,
MoveActionButton,
SnapToAction,
SnapshotAction
],
[]
);

return (
<CommitDrawer
isOpen={drawerOpened && !progress}
Expand All @@ -106,7 +210,7 @@ export default function FileManager(props: FileManagerProps) {
clearCommits();
updateSections();
})}
onCardActivate={openModalWithCommitHandler(true)}
onCardActivate={openModalWithCommitHandler}
onCardDelete={(section) => {
deleteCommit(section);
}}
Expand All @@ -117,14 +221,29 @@ export default function FileManager(props: FileManagerProps) {
noClick={true}
onDrop={usePackageDropHandler(
SectionUtils.fromPath(path) || sections[0],
openModalWithCommitHandler(false)
(section, addAction) => {
const existingCommit = commits.get(
SectionUtils.toString(section)
);
if (!existingCommit) {
openModalWithCommitHandler(
section,
createCommit({ toAdd: addAction })
);
return;
}
const addCommit = mergeCommits(existingCommit, {
toAdd: addAction
});
openModalWithCommitHandler(section, addCommit);
}
)}
>
{({ getRootProps, getInputProps }) => (
<div className="h-full" {...getRootProps()}>
<input {...getInputProps()} />
<FullFileBrowser
fileActions={[SnapToAction, SnapshotAction]}
fileActions={fileActions}
files={files}
onFileAction={fileAction}
folderChain={folderChain}
Expand Down
70 changes: 70 additions & 0 deletions web/src/components/commit/AddTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* === This file is part of bxt ===
*
* SPDX-FileCopyrightText: 2024 Artem Grinev <[email protected]>
* SPDX-License-Identifier: AGPL-3.0-or-later
*
*/
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { Button, Table } from "react-daisyui";
import {
faCube,
faSignature,
faTrashCan
} from "@fortawesome/free-solid-svg-icons";

type CommitTableProps = {
action?: AddAction;
deletePackage?: (name: string) => void;
};

export const AddTable = ({ action, deletePackage }: CommitTableProps) => {
return (
<Table zebra={true} size="xs" className="overflow-x-auto">
<Table.Head>
<span>Name</span>
<span />
<span />
</Table.Head>
<Table.Body>
{Array.from(action || []).map(([name, upload]) => (
<Table.Row key={name}>
<span className="flex items-center">
{upload.file !== undefined && (
<FontAwesomeIcon
icon={faCube}
className="px-2 max-h-6"
/>
)}
{upload.signatureFile !== undefined && (
<FontAwesomeIcon
icon={faSignature}
color="green"
className="px-2 max-h-6"
/>
)}
{name}
</span>
<span></span>
<span>
<Button
size="xs"
color="error"
onClick={(e) => {
e.preventDefault();
deletePackage?.(name);
}}
>
<FontAwesomeIcon
icon={faTrashCan}
color="white"
className="max-h-6"
/>
</Button>
</span>
</Table.Row>
))}
</Table.Body>
</Table>
);
};
export default AddTable;
Loading

0 comments on commit 1e017f3

Please sign in to comment.