Skip to content

Commit

Permalink
Merge pull request #117 from cptKNJO/ui
Browse files Browse the repository at this point in the history
UI
  • Loading branch information
uroni authored Dec 8, 2024
2 parents 7178d99 + 6817ded commit 6e8f098
Show file tree
Hide file tree
Showing 7 changed files with 633 additions and 299 deletions.
137 changes: 137 additions & 0 deletions urbackupserver/www2/src/components/Pagination.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import {
Pagination as FUIPagination,
IPaginationStyles,
} from "@fluentui/react-experiments";
import { Select, tokens } from "@fluentui/react-components";
import { registerIcons } from "@fluentui/react-experiments/lib/Styling";
import {
ArrowNext20Filled,
ArrowPrevious20Filled,
ChevronLeft20Filled,
ChevronRight20Filled,
} from "@fluentui/react-icons";
import { useState } from "react";

import { chunk } from "../utils/chunk";

// Register icons used in Pagination @fluentui/react-experiments. See https://github.com/microsoft/fluentui/wiki/Using-icons#registering-custom-icons.
registerIcons({
icons: {
CaretSolidLeft: <ChevronLeft20Filled />,
CaretSolidRight: <ChevronRight20Filled />,
Next: <ArrowNext20Filled />,
Previous: <ArrowPrevious20Filled />,
},
});

const PAGE_SIZES = [10, 25, 50, 100];

const paginationStyles: Partial<IPaginationStyles> = {
root: {
alignItems: "end",
marginBlockStart: tokens.spacingHorizontalM,
// Fix centering of page selection buttons
"[role=radiogroup]": {
display: "flex",
alignItems: "center",
},
i: {
display: "flex",
alignItems: "center",
},
// First, previous, next, last
"button:not([aria-disabled]) i": {
color: tokens.colorBrandForeground1,
},
// Selected page
"button[aria-checked='true']": {
fontWeight: "bold",
color: tokens.colorBrandForeground1,
position: "relative",
borderBottom: `1px solid ${tokens.colorBrandForeground1}`,
},
},
pageNumber: {
color: "currentColor",
},
visibleItemLabel: {
marginBlockStart: tokens.spacingVerticalS,
},
};

const pageSizeStyles = {
display: "flex",
alignItems: "center",
gap: tokens.spacingHorizontalS,
};

export function usePagination<T>(
data: T[],
config: { itemsPerPage?: number } = {},
) {
const [itemsPerPage, setItemsPerPage] = useState<number>(
config.itemsPerPage ?? PAGE_SIZES[0],
);

const [page, setPage] = useState(0);

const pageData = chunk(data, itemsPerPage);

return { itemsPerPage, setItemsPerPage, pageData, page, setPage };
}

export function Pagination({
page,
setPage,
pageCount,
itemsPerPage,
totalItemCount,
}: {
page: number;
setPage: React.Dispatch<React.SetStateAction<number>>;
pageCount: number;
itemsPerPage: number;
totalItemCount: number;
}) {
return (
<FUIPagination
selectedPageIndex={page}
pageCount={pageCount}
itemsPerPage={itemsPerPage}
totalItemCount={totalItemCount}
format={"buttons"}
previousPageAriaLabel={"previous page"}
nextPageAriaLabel={"next page"}
firstPageAriaLabel={"first page"}
lastPageAriaLabel={"last page"}
pageAriaLabel={"page"}
selectedAriaLabel={"selected"}
onPageChange={(index) => setPage(index)}
styles={paginationStyles}
/>
);
}

export function PaginationItemsPerPageSelector({
itemsPerPage,
setItemsPerPage,
}: {
itemsPerPage: number;
setItemsPerPage: React.Dispatch<React.SetStateAction<number>>;
}) {
return (
<label style={pageSizeStyles}>
Show
<Select
id="page-size"
defaultValue={itemsPerPage}
onChange={(_, data) => setItemsPerPage(+data.value)}
>
{PAGE_SIZES.map((size, id) => (
<option key={id}>{size}</option>
))}
</Select>
entries
</label>
);
}
68 changes: 68 additions & 0 deletions urbackupserver/www2/src/components/SearchBox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import {
Field,
SearchBox as FUISearchBox,
tokens,
} from "@fluentui/react-components";
import { useState } from "react";

const styles: Record<string, React.CSSProperties> = {
search: {
display: "flex",
alignItems: "center",
gap: tokens.spacingHorizontalS,
},
searchBox: {
width: "28ch",
},
};

export function useFilteredBySearch<T>(
data: T[],
filterFn: (d: T, search: string) => boolean,
) {
const [search, setSearch] = useState("");

const filteredItems = data.filter((d) => filterFn(d, search));

return {
search,
setSearch,
filteredItems,
};
}

export function SearchBox({
onSearch,
}: {
onSearch: (search: string) => void;
}) {
return (
<Field label="Search" style={styles.search}>
<FUISearchBox
autoComplete="off"
onChange={(_, data) => {
const search = data.value.toLowerCase();

onSearch(search);
}}
style={styles.searchBox}
/>
</Field>
);
}

export function filterBySearch(
search: string,
searchableFields: Record<string, string>,
): boolean {
if (search.length) {
// Find matching search term in data values
const match = Object.values(searchableFields).some((v) =>
String(v).toLowerCase().includes(search),
);

return match;
}

return true;
}
41 changes: 41 additions & 0 deletions urbackupserver/www2/src/css/global.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
@import url("reset.css") layer(reset);

:root {
/* FluentUI Spacing - https://react.fluentui.dev/?path=/docs/theme-spacing--docs */
--spacingXXS: 2px;
--spacingXS: 4px;
--spacingSNudge: 6px;
--spacingS: 8px;
--spacingMNudge: 10px;
--spacingM: 12px;
--spacingL: 16px;
--spacingXL: 20px;
--spacingXXL: 24px;
--spacingXXXL: 32px;

/* App variables */
--gutter: var(--spacingM);
}

@layer composition {
/*
FLOW COMPOSITION
Expand All @@ -9,6 +26,30 @@
.flow > * + * {
margin-top: var(--flow-space, 1em);
}

/*
CLUSTER
More info: https://every-layout.dev/layouts/cluster/
A layout that lets you distribute items with consitent
spacing, regardless of their size
CUSTOM PROPERTIES AND CONFIGURATION
--gutter: This defines the space
between each item.
--cluster-horizontal-alignment (flex-start) How items should align
horizontally. Can be any acceptable flexbox aligmnent value.
--cluster-vertical-alignment How items should align vertically.
Can be any acceptable flexbox alignment value.
*/
.cluster {
display: flex;
flex-wrap: wrap;
gap: var(--gutter);
justify-content: var(--cluster-horizontal-alignment, flex-start);
align-items: var(--cluster-vertical-alignment, center);
}
}

.table-wrapper {
Expand Down
Loading

0 comments on commit 6e8f098

Please sign in to comment.