Skip to content

Commit

Permalink
Merge branch 'develop' into cypress-parallel
Browse files Browse the repository at this point in the history
  • Loading branch information
khavinshankar authored Sep 14, 2023
2 parents 843428d + c5f3b79 commit f7c832d
Show file tree
Hide file tree
Showing 11 changed files with 479 additions and 174 deletions.
167 changes: 167 additions & 0 deletions src/CAREUI/misc/PaginatedList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
import { createContext, useContext, useState } from "react";
import { PaginatedResponse, QueryRoute } from "../../Utils/request/types";
import useQuery, { QueryOptions } from "../../Utils/request/useQuery";
import ButtonV2, {
CommonButtonProps,
} from "../../Components/Common/components/ButtonV2";
import CareIcon from "../icons/CareIcon";
import { classNames } from "../../Utils/utils";
import Pagination from "../../Components/Common/Pagination";

const DEFAULT_PER_PAGE_LIMIT = 14;

interface PaginatedListContext<TItem>
extends ReturnType<typeof useQuery<PaginatedResponse<TItem>>> {
items: TItem[];
perPage: number;
currentPage: number;
setPage: (page: number) => void;
}

const context = createContext<PaginatedListContext<object> | null>(null);

function useContextualized<TItem>() {
const ctx = useContext(context);

if (ctx === null) {
throw new Error("PaginatedList must be used within a PaginatedList");
}

return ctx as PaginatedListContext<TItem>;
}

interface Props<TItem> extends QueryOptions {
route: QueryRoute<PaginatedResponse<TItem>>;
perPage?: number;
children: (ctx: PaginatedListContext<TItem>) => JSX.Element | JSX.Element[];
}

export default function PaginatedList<TItem extends object>({
children,
route,
perPage = DEFAULT_PER_PAGE_LIMIT,
...queryOptions
}: Props<TItem>) {
const query = useQuery(route, {
...queryOptions,
query: { ...queryOptions.query, limit: perPage },
});
const [currentPage, setPage] = useState(1);

const items = query.data?.results ?? [];

return (
<context.Provider
value={{ ...query, items, perPage, currentPage, setPage }}
>
<context.Consumer>
{(ctx) => children(ctx as PaginatedListContext<TItem>)}
</context.Consumer>
</context.Provider>
);
}

interface WhenEmptyProps {
className?: string;
children: JSX.Element | JSX.Element[];
}

const WhenEmpty = <TItem extends object>(props: WhenEmptyProps) => {
const { items, loading } = useContextualized<TItem>();

if (loading || items.length > 0) {
return null;
}

return <div className={props.className}>{props.children}</div>;
};

PaginatedList.WhenEmpty = WhenEmpty;

const WhenLoading = <TItem extends object>(props: WhenEmptyProps) => {
const { loading } = useContextualized<TItem>();

if (!loading) {
return null;
}

return <div className={props.className}>{props.children}</div>;
};

PaginatedList.WhenLoading = WhenLoading;

const Refresh = ({ label = "Refresh", ...props }: CommonButtonProps) => {
const { loading, refetch } = useContextualized<object>();

return (
<ButtonV2
variant="secondary"
border
{...props}
onClick={() => refetch()}
disabled={loading}
>
<CareIcon
icon="l-sync"
className={classNames("text-lg", loading && "animate-spin")}
/>
<span>{label}</span>
</ButtonV2>
);
};

PaginatedList.Refresh = Refresh;

interface ItemsProps<TItem> {
className?: string;
children: (item: TItem) => JSX.Element | JSX.Element[];
shimmer?: JSX.Element;
shimmerCount?: number;
}

const Items = <TItem extends object>(props: ItemsProps<TItem>) => {
const { loading, items } = useContextualized<TItem>();

return (
<ul className={props.className}>
{loading && props.shimmer
? Array.from({ length: props.shimmerCount ?? 8 }).map((_, i) => (
<li key={i} className="w-full">
{props.shimmer}
</li>
))
: items.map((item, index) => (
<li key={index} className="w-full">
{props.children(item)}
</li>
))}
</ul>
);
};

PaginatedList.Items = Items;

interface PaginatorProps {
className?: string;
hideIfSinglePage?: boolean;
}

const Paginator = ({ className, hideIfSinglePage }: PaginatorProps) => {
const { data, perPage, currentPage, setPage } = useContextualized<object>();

if (hideIfSinglePage && (data?.count ?? 0) <= perPage) {
return null;
}

return (
<Pagination
className={className}
cPage={currentPage}
data={{ totalCount: data?.count ?? 0 }}
defaultPerPage={perPage}
onChange={setPage}
/>
);
};

PaginatedList.Paginator = Paginator;
7 changes: 4 additions & 3 deletions src/Common/hooks/useAppHistory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@ export default function useAppHistory() {
const resetHistory = useContext(ResetHistoryContext);

const goBack = (fallbackUrl?: string) => {
if (fallbackUrl)
// use provided fallback url if provided.
return navigate(fallbackUrl);
if (history.length > 1)
// Otherwise, navigate to history present in the app navigation history stack.
return navigate(history[1]);

if (fallbackUrl)
// use provided fallback url if provided.
return navigate(fallbackUrl);
// Otherwise, fallback to browser's go back behaviour.
window.history.back();
};
Expand Down
4 changes: 3 additions & 1 deletion src/Components/Assets/AssetType/ONVIFCamera.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ const ONVIFCamera = (props: ONVIFCameraProps) => {
const [refreshPresetsHash, setRefreshPresetsHash] = useState(
Number(new Date())
);
const [refreshHash, setRefreshHash] = useState(Number(new Date()));
const dispatch = useDispatch<any>();

useEffect(() => {
Expand Down Expand Up @@ -89,7 +90,7 @@ const ONVIFCamera = (props: ONVIFCameraProps) => {
Notification.Success({
msg: "Asset Configured Successfully",
});
window.location.reload();
setRefreshHash(Number(new Date()));
} else {
Notification.Error({
msg: "Something went wrong..!",
Expand Down Expand Up @@ -200,6 +201,7 @@ const ONVIFCamera = (props: ONVIFCameraProps) => {

{assetType === "ONVIF" ? (
<CameraConfigure
key={refreshHash}
asset={asset as AssetData}
bed={bed}
setBed={setBed}
Expand Down
2 changes: 1 addition & 1 deletion src/Components/Common/components/ButtonV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ export default ButtonV2;

// Common buttons

type CommonButtonProps = ButtonProps & { label?: string };
export type CommonButtonProps = ButtonProps & { label?: string };

export const Submit = ({ label = "Submit", ...props }: CommonButtonProps) => {
const { t } = useTranslation();
Expand Down
Loading

0 comments on commit f7c832d

Please sign in to comment.