Skip to content

UI: Overhaul lakeFS look & feel #9022

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
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
19 changes: 13 additions & 6 deletions webui/src/lib/components/badges.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,19 @@ import Badge from 'react-bootstrap/Badge';
import Stack from 'react-bootstrap/Stack';
import { FaLock } from 'react-icons/fa';

export const ReadOnlyBadge: FC<{ readOnly: boolean, style: CSS.Properties }> = ({ readOnly, style }) => {
export const ReadOnlyBadge: FC<{ readOnly: boolean, style?: CSS.Properties }> = ({ readOnly, style = {} }) => {
return readOnly ? (
<Badge pill bg="secondary" style={style}>
<Stack direction="horizontal" gap={1}>
<FaLock />{`Read-only`}
</Stack>
<Badge
pill
bg="light"
text="dark"
className="border border-secondary shadow-sm"
style={style}
>
<Stack direction="horizontal" gap={1} className="align-items-center">
<FaLock size={10} />
<span>Read-only</span>
</Stack>
</Badge>
) : null;
};
};
56 changes: 43 additions & 13 deletions webui/src/lib/components/controls.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Tooltip from "react-bootstrap/Tooltip";
import Overlay from "react-bootstrap/Overlay";
import Table from "react-bootstrap/Table";
import {OverlayTrigger} from "react-bootstrap";
import {CheckIcon, PasteIcon, SearchIcon, SyncIcon} from "@primer/octicons-react";
import {CheckIcon, PasteIcon, SearchIcon, SyncIcon, AlertIcon, AlertFillIcon} from "@primer/octicons-react";
import {Link} from "./nav";
import {
Box,
Expand Down Expand Up @@ -63,9 +63,25 @@ export const DebouncedFormControl = React.forwardRef((props, ref) => {
});
DebouncedFormControl.displayName = "DebouncedFormControl";


export const Spinner = () => {
return (
<div className="loading-spinner mb-3">
<div className="spinner-border text-primary" role="status" style={{ width: '3rem', height: '3rem' }}>
<span className="visually-hidden">Loading...</span>
</div>
</div>
);
};

export const Loading = ({message = "Loading..."}) => {
return (
<Alert variant={"info"}>{message}</Alert>
<div className="loading-container d-flex flex-column align-items-center justify-content-center py-5">
<Spinner />
<div className="loading-text text-center text-muted">
{message}
</div>
</div>
);
};

Expand All @@ -82,15 +98,23 @@ export const AlertError = ({error, onDismiss = null, className = null}) => {
while (err.error) err = err.error;
if (err.message) content = err.message;

const alertClassName = `${className} text-wrap text-break`.trim();
const alertClassName = `${className} text-wrap text-break shadow-sm`.trim();

if (onDismiss !== null) {
return <Alert className={alertClassName} variant="danger" dismissible onClose={onDismiss}>{content}</Alert>;
}

return (
<Alert className={alertClassName} variant="danger">{content}</Alert>
);
<Alert
className={alertClassName}
variant="danger"
dismissible={onDismiss !== null}
onClose={onDismiss}
>
<div className="alert-error-body">
<div className="me-3">
<AlertFillIcon size={24} />
</div>
<div>{content}</div>
</div>
</Alert>
);
};

export const FormattedDate = ({ dateValue, format = "MM/DD/YYYY HH:mm:ss" }) => {
Expand Down Expand Up @@ -296,14 +320,15 @@ export const PrefixSearchWidget = ({ onFilter, text = "Search by Prefix", defaul

if (expanded) {
return (
<Form onSubmit={handleSubmit}>
<InputGroup>
<Form onSubmit={handleSubmit} className="prefix-search-form">
<InputGroup className="prefix-search-input-group">
<Form.Control
ref={ref}
autoFocus
defaultValue={defaultValue}
placeholder={text}
aria-label={text}
className="prefix-search-expanded"
/>
<Button variant="light" onClick={toggle}>
<SearchIcon/>
Expand Down Expand Up @@ -421,8 +446,13 @@ export const ToggleSwitch = ({ label, id, defaultChecked, onChange }) => {

export const Warning = (props) =>
<>
<Alert variant="warning">
&#x26A0; { props.children }
<Alert variant="warning" className="shadow-sm">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be a component.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is!

<div className="d-flex align-items-center">
<div className="me-3">
<AlertIcon size={24} />
</div>
<div>{ props.children }</div>
</div>
</Alert>
</>;

Expand Down
107 changes: 57 additions & 50 deletions webui/src/lib/components/repository/changes.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ import {

import {useAPIWithPagination} from "../../hooks/api";
import {useExpandCollapseDirs} from "../../hooks/useExpandCollapseDirs";
import {AlertError} from "../controls";
import {AlertError, TooltipButton} from "../controls";
import {ObjectsDiff} from "./ObjectsDiff";
import {ObjectTreeEntryRow, PrefixTreeEntryRow} from "./treeRows";
import Alert from "react-bootstrap/Alert";
import Button from "react-bootstrap/Button";
import Card from "react-bootstrap/Card";
import Table from "react-bootstrap/Table";
import Alert from "react-bootstrap/Alert";
import {refs} from "../../api";
import Form from "react-bootstrap/Form";
import Row from "react-bootstrap/Row";
Expand Down Expand Up @@ -154,7 +154,7 @@ export const TreeEntryPaginator = ({ path, setAfterUpdated, nextPage, depth=0, l
onClick={() => setAfterUpdated(nextPage)}
>
<td className="diff-indicator"/>
<td className="tree-path">
<td className="tree-path tree-path-action">
<span style={{marginLeft: depth * 20 + "px",color:"#007bff"}}>
{loading && <ClockIcon/>}
{pathSectionText}
Expand Down Expand Up @@ -189,58 +189,65 @@ export const TreeEntryPaginator = ({ path, setAfterUpdated, nextPage, depth=0, l
export const ChangesTreeContainer = ({results, delimiter, uriNavigator,
leftDiffRefID, rightDiffRefID, repo, reference, internalRefresh, prefix,
getMore, loading, nextPage, setAfterUpdated, onNavigate, onRevert,
changesTreeMessage}) => {
changesTreeMessage, noChangesText = 'No changes', emptyStateComponent}) => {
// Manages expand/collapse state for all directories in the tree.
const { isAllExpanded, expandAll, collapseAll, markDirAsManuallyToggled, wasDirManuallyToggled } = useExpandCollapseDirs();

if (results.length === 0) {
return <div className="tree-container">
<Alert variant="info">No changes</Alert>
</div>
} else {
return <div className="tree-container">
if (emptyStateComponent) {
return emptyStateComponent;
}
return (
<div className="tree-container">
<Alert variant="info">{noChangesText}</Alert>
</div>
);
}
return (
<div className="tree-container">
{changesTreeMessage && <div>{changesTreeMessage}</div>}
<Card>
<Card.Header className="d-flex justify-content-between align-items-center">
{(delimiter !== "") && uriNavigator}
<div className="d-flex gap-2">
<Button size="sm" variant="outline-secondary" onClick={expandAll}>
<FileDirectoryFillIcon className="me-1" />
<FoldDownIcon />
</Button>
<Button size="sm" variant="outline-secondary" onClick={collapseAll}>
<FileDirectoryFillIcon className="me-1" />
<FoldUpIcon />
</Button>
</div>
</Card.Header>
<Card>
<Card.Header className="d-flex justify-content-between align-items-center">
{(delimiter !== "") && uriNavigator}
<div className="d-flex gap-2">
<TooltipButton tooltip="Expand All" size="sm" variant="outline-secondary" onClick={expandAll}>
<FileDirectoryFillIcon className="me-1" />
<FoldDownIcon />
</TooltipButton>
<TooltipButton tooltip="Collapse All" size="sm" variant="outline-secondary" onClick={collapseAll}>
<FileDirectoryFillIcon className="me-1" />
<FoldUpIcon />
</TooltipButton>
</div>
</Card.Header>

<Card.Body>
<Table borderless size="sm">
<tbody>
{results.map(entry => {
return (
<TreeItemRow key={entry.path + "-item"} entry={entry} repo={repo}
reference={reference}
internalReferesh={internalRefresh} leftDiffRefID={leftDiffRefID}
rightDiffRefID={rightDiffRefID} delimiter={delimiter}
relativeTo={prefix}
onNavigate={onNavigate}
getMore={getMore}
onRevert={onRevert}
isAllExpanded={isAllExpanded}
markDirAsManuallyToggled={markDirAsManuallyToggled}
wasDirManuallyToggled={wasDirManuallyToggled}
/>);
})}
{!!nextPage &&
<TreeEntryPaginator path={""} loading={loading} nextPage={nextPage}
setAfterUpdated={setAfterUpdated}/>}
</tbody>
</Table>
</Card.Body>
</Card>
</div>
}
<Card.Body>
<Table borderless size="sm">
<tbody>
{results.map(entry => {
return (
<TreeItemRow key={entry.path + "-item"} entry={entry} repo={repo}
reference={reference}
internalReferesh={internalRefresh} leftDiffRefID={leftDiffRefID}
rightDiffRefID={rightDiffRefID} delimiter={delimiter}
relativeTo={prefix}
onNavigate={onNavigate}
getMore={getMore}
onRevert={onRevert}
isAllExpanded={isAllExpanded}
markDirAsManuallyToggled={markDirAsManuallyToggled}
wasDirManuallyToggled={wasDirManuallyToggled}
/>);
})}
{!!nextPage &&
<TreeEntryPaginator path={""} loading={loading} nextPage={nextPage}
setAfterUpdated={setAfterUpdated}/>}
</tbody>
</Table>
</Card.Body>
</Card>
</div>
);
}

export const defaultGetMoreChanges = (repo, leftRefId, rightRefId, delimiter) => (afterUpdated, path, useDelimiter= true, amount = -1) => {
Expand Down
7 changes: 2 additions & 5 deletions webui/src/lib/components/repository/commits.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@ import {MetadataRow, MetadataUIButton} from "../../../pages/repositories/reposit
import {Link} from "../nav";
import dayjs from "dayjs";
import Card from "react-bootstrap/Card";
import React, {useContext} from "react";
import {AppContext} from "../../hooks/appContext";

import React from "react";

const CommitActions = ({ repo, commit }) => {
const {state} = useContext(AppContext);
const buttonVariant = state.settings.darkMode ? "outline-light" : "outline-dark";
const buttonVariant = "light";

return (
<div>
Expand Down
Loading
Loading