mirror of
https://github.com/umami-software/umami.git
synced 2026-02-06 13:47:15 +01:00
Converted user and website settings.
This commit is contained in:
parent
4c24e54fdd
commit
b5c6194f36
59 changed files with 363 additions and 554 deletions
|
|
@ -1,11 +1,11 @@
|
|||
import { ReactNode } from 'react';
|
||||
import { Button, LoadingButton, Form, FormButtons } from 'react-basics';
|
||||
import { Row, Button, FormSubmitButton, Form, FormButtons } from '@umami/react-zen';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
|
||||
export interface ConfirmationFormProps {
|
||||
message: ReactNode;
|
||||
buttonLabel?: ReactNode;
|
||||
buttonVariant?: 'none' | 'primary' | 'secondary' | 'quiet' | 'danger';
|
||||
buttonVariant?: 'primary' | 'quiet' | 'danger';
|
||||
isLoading?: boolean;
|
||||
error?: string | Error;
|
||||
onConfirm?: () => void;
|
||||
|
|
@ -24,13 +24,13 @@ export function ConfirmationForm({
|
|||
const { formatMessage, labels } = useMessages();
|
||||
|
||||
return (
|
||||
<Form error={error}>
|
||||
<p>{message}</p>
|
||||
<FormButtons flex>
|
||||
<LoadingButton isLoading={isLoading} onClick={onConfirm} variant={buttonVariant}>
|
||||
<Form onSubmit={onConfirm} error={error}>
|
||||
<Row marginY="4">{message}</Row>
|
||||
<FormButtons>
|
||||
<Button onPress={onClose}>{formatMessage(labels.cancel)}</Button>
|
||||
<FormSubmitButton isLoading={isLoading} variant={buttonVariant}>
|
||||
{buttonLabel || formatMessage(labels.ok)}
|
||||
</LoadingButton>
|
||||
<Button onClick={onClose}>{formatMessage(labels.cancel)}</Button>
|
||||
</FormSubmitButton>
|
||||
</FormButtons>
|
||||
</Form>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,10 @@
|
|||
import { ReactNode } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Loading, SearchField } from 'react-basics';
|
||||
import { Loading, SearchField, Row, Column } from '@umami/react-zen';
|
||||
import { useMessages, useNavigation } from '@/components/hooks';
|
||||
import { Empty } from '@/components/common/Empty';
|
||||
import { Pager } from '@/components/common/Pager';
|
||||
import { PagedQueryResult } from '@/lib/types';
|
||||
import styles from './DataTable.module.css';
|
||||
import { LoadingPanel } from '@/components/common/LoadingPanel';
|
||||
import { PagedQueryResult } from '@/lib/types';
|
||||
|
||||
const DEFAULT_SEARCH_DELAY = 600;
|
||||
|
||||
|
|
@ -20,7 +18,7 @@ export interface DataTableProps {
|
|||
children: ReactNode | ((data: any) => ReactNode);
|
||||
}
|
||||
|
||||
export function DataTable({
|
||||
export function DataGrid({
|
||||
queryResult,
|
||||
searchDelay = 600,
|
||||
allowSearch = true,
|
||||
|
|
@ -30,12 +28,8 @@ export function DataTable({
|
|||
children,
|
||||
}: DataTableProps) {
|
||||
const { formatMessage, labels, messages } = useMessages();
|
||||
const {
|
||||
result,
|
||||
params,
|
||||
setParams,
|
||||
query: { error, isLoading, isFetched },
|
||||
} = queryResult || {};
|
||||
const { result, params, setParams, query } = queryResult || {};
|
||||
const { error, isLoading, isFetched } = query || {};
|
||||
const { page, pageSize, count, data } = result || {};
|
||||
const { search } = params || {};
|
||||
const hasData = Boolean(!isLoading && data?.length);
|
||||
|
|
@ -43,45 +37,38 @@ export function DataTable({
|
|||
const { router, renderUrl } = useNavigation();
|
||||
|
||||
const handleSearch = (search: string) => {
|
||||
setParams({ ...params, search, page: params.page ? page : 1 });
|
||||
setParams({ ...params, search });
|
||||
};
|
||||
|
||||
const handlePageChange = (page: number) => {
|
||||
setParams({ ...params, search, page });
|
||||
setParams({ ...params, page });
|
||||
router.push(renderUrl({ page }));
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{allowSearch && (hasData || search) && (
|
||||
<SearchField
|
||||
className={styles.search}
|
||||
value={search}
|
||||
onSearch={handleSearch}
|
||||
delay={searchDelay || DEFAULT_SEARCH_DELAY}
|
||||
autoFocus={autoFocus}
|
||||
placeholder={formatMessage(labels.search)}
|
||||
/>
|
||||
<Row width="280px" alignItems="center" marginBottom="6">
|
||||
<SearchField
|
||||
value={search}
|
||||
onSearch={handleSearch}
|
||||
delay={searchDelay || DEFAULT_SEARCH_DELAY}
|
||||
autoFocus={autoFocus}
|
||||
placeholder={formatMessage(labels.search)}
|
||||
/>
|
||||
</Row>
|
||||
)}
|
||||
<LoadingPanel data={data} isLoading={isLoading} isFetched={isFetched} error={error}>
|
||||
<div
|
||||
className={classNames(styles.body, {
|
||||
[styles.status]: isLoading || noResults || !hasData,
|
||||
})}
|
||||
>
|
||||
<Column>
|
||||
{hasData ? (typeof children === 'function' ? children(result) : children) : null}
|
||||
{isLoading && <Loading position="page" />}
|
||||
{!isLoading && !hasData && !search && (renderEmpty ? renderEmpty() : <Empty />)}
|
||||
{!isLoading && noResults && <Empty message={formatMessage(messages.noResultsFound)} />}
|
||||
</div>
|
||||
</Column>
|
||||
{allowPaging && hasData && (
|
||||
<Pager
|
||||
className={styles.pager}
|
||||
page={page}
|
||||
pageSize={pageSize}
|
||||
count={count}
|
||||
onPageChange={handlePageChange}
|
||||
/>
|
||||
<Row marginTop="6">
|
||||
<Pager page={page} pageSize={pageSize} count={count} onPageChange={handlePageChange} />
|
||||
</Row>
|
||||
)}
|
||||
</LoadingPanel>
|
||||
</>
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { ReactNode } from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { Loading } from 'react-basics';
|
||||
import { Loading } from '@umami/react-zen';
|
||||
import { ErrorMessage } from '@/components/common/ErrorMessage';
|
||||
import { Empty } from '@/components/common/Empty';
|
||||
import styles from './LoadingPanel.module.css';
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
import classNames from 'classnames';
|
||||
import { Button, Icon, Icons } from 'react-basics';
|
||||
import { Button, Icon, Icons, Row, Text } from '@umami/react-zen';
|
||||
import { useMessages } from '@/components/hooks';
|
||||
import styles from './Pager.module.css';
|
||||
|
||||
export interface PagerProps {
|
||||
page: string | number;
|
||||
|
|
@ -11,7 +9,7 @@ export interface PagerProps {
|
|||
className?: string;
|
||||
}
|
||||
|
||||
export function Pager({ page, pageSize, count, onPageChange, className }: PagerProps) {
|
||||
export function Pager({ page, pageSize, count, onPageChange }: PagerProps) {
|
||||
const { formatMessage, labels } = useMessages();
|
||||
const maxPage = pageSize && count ? Math.ceil(+count / +pageSize) : 0;
|
||||
const lastPage = page === maxPage;
|
||||
|
|
@ -34,24 +32,21 @@ export function Pager({ page, pageSize, count, onPageChange, className }: PagerP
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={classNames(styles.pager, className)}>
|
||||
<div className={styles.count}>{formatMessage(labels.numberOfRecords, { x: count })}</div>
|
||||
<div className={styles.nav}>
|
||||
<Button onClick={() => handlePageChange(-1)} disabled={firstPage}>
|
||||
<Icon rotate={90}>
|
||||
<Icons.ChevronDown />
|
||||
<Row alignItems="center" justifyContent="space-between" gap="3" flexGrow={1}>
|
||||
<Text>{formatMessage(labels.numberOfRecords, { x: count })}</Text>
|
||||
<Row alignItems="center" justifyContent="flex-end" gap="3">
|
||||
<Text>{formatMessage(labels.pageOf, { current: page, total: maxPage })}</Text>
|
||||
<Button onPress={() => handlePageChange(-1)} isDisabled={firstPage}>
|
||||
<Icon size="sm" rotate={180}>
|
||||
<Icons.Chevron />
|
||||
</Icon>
|
||||
</Button>
|
||||
<div className={styles.text}>
|
||||
{formatMessage(labels.pageOf, { current: page, total: maxPage })}
|
||||
</div>
|
||||
<Button onClick={() => handlePageChange(1)} disabled={lastPage}>
|
||||
<Icon rotate={270}>
|
||||
<Icons.ChevronDown />
|
||||
<Button onPress={() => handlePageChange(1)} isDisabled={lastPage}>
|
||||
<Icon size="sm">
|
||||
<Icons.Chevron />
|
||||
</Icon>
|
||||
</Button>
|
||||
</div>
|
||||
<div></div>
|
||||
</div>
|
||||
</Row>
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue