Skip to content
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

feat(APW): Refresh content review - pull data on every 10s #3506

Merged
merged 14 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from 13 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
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from "react";
import { Routes, Route } from "@webiny/react-router";
import { Route, Routes } from "@webiny/react-router";
import styled from "@emotion/styled";
import { List } from "@webiny/ui/List";
import { ButtonIcon, ButtonSecondary } from "@webiny/ui/Button";
Expand All @@ -17,6 +17,7 @@ import { Box } from "../Layout";
import { PanelBox } from "./Styled";
import { RightPanel } from "./RightPanel";
import { PlaceholderBox } from "./PlaceholderBox";
import { useFetchInterval } from "~/hooks/useFetchInterval";

const t = i18n.ns("app-apw/admin/content-reviews/editor");

Expand Down Expand Up @@ -65,14 +66,25 @@ const CreateChangeRequest: React.FC<CreateChangeRequestProps> = ({ create, disab
);
};

const CHANGE_REQUESTS_REFRESH_INTERVAL = 10000; // 10s

export const CenterPanel = () => {
const { setOpen } = useChangeRequestDialog();
const { changeRequests, loading } = useChangeRequestsList({ sorters: [] });
const { changeRequests, loading, refetch } = useChangeRequestsList({
sorters: []
});
const { currentStep, changeRequestsPending } = useCurrentStep();

useFetchInterval({
interval: CHANGE_REQUESTS_REFRESH_INTERVAL,
callback: refetch,
loading
});

if (loading) {
return <Typography use={"caption"}>Loading Change requests...</Typography>;
}

return (
<>
<PanelBox flex={"1 1 22%"}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import { Box, Columns, Stack } from "~/components/Layout";
import { fromNow } from "~/utils";
import { Avatar } from "~/views/publishingWorkflows/components/ReviewersList";
import { useCommentsList } from "~/hooks/useCommentsList";
import { TypographyBody, TypographySecondary, AuthorName, richTextWrapperStyles } from "../Styled";
import { AuthorName, richTextWrapperStyles, TypographyBody, TypographySecondary } from "../Styled";
import { CommentFile } from "../ChangeRequest/ApwFile";
import { FileWithOverlay } from "../ChangeRequest/ChangeRequestMedia";
import { useFetchInterval } from "~/hooks/useFetchInterval";

const HEADER_HEIGHT = "65px";
const CR_DETAIL_HEIGHT = "179px";
Expand Down Expand Up @@ -68,8 +69,16 @@ const Comment: React.FC<CommentProps> = props => {
);
};

const COMMENTS_REFRESH_INTERVAL = 10000; // 10s

export const Comments = React.forwardRef<HTMLDivElement>(function comments(_, ref) {
const { comments } = useCommentsList();
const { comments, refetch, loading } = useCommentsList();

useFetchInterval({
interval: COMMENTS_REFRESH_INTERVAL,
callback: refetch,
loading
});

return (
<CommentsBox space={6} paddingX={6} paddingY={5}>
Expand Down
6 changes: 4 additions & 2 deletions packages/app-apw/src/hooks/useChangeRequestsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ interface UseChangeRequestsListHook {
setSort: (sort: string) => void;
serializeSorters: (data: Record<string, string>) => string;
editContentReview: (id: string) => void;
refetch: () => Promise<any>;
};
}

Expand All @@ -49,7 +50,7 @@ export const useChangeRequestsList: UseChangeRequestsListHook = (config: Config)
}
};

const { data, loading } = useQuery<
const { data, loading, refetch } = useQuery<
ListChangeRequestsQueryResponse,
ListChangeRequestsQueryVariables
>(LIST_CHANGE_REQUESTS_QUERY, {
Expand All @@ -70,6 +71,7 @@ export const useChangeRequestsList: UseChangeRequestsListHook = (config: Config)
sort,
setSort,
serializeSorters,
editContentReview
editContentReview,
refetch
};
};
17 changes: 10 additions & 7 deletions packages/app-apw/src/hooks/useCommentsList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { useCurrentChangeRequestId } from "~/hooks/useCurrentChangeRequestId";
interface UseCommentsListResult {
loading: boolean;
comments: Array<ApwComment>;
refetch: () => Promise<any>;
}

/**
Expand Down Expand Up @@ -40,17 +41,19 @@ export const useListCommentsVariables = () => {

export const useCommentsList = (): UseCommentsListResult => {
const variables = useListCommentsVariables();
const { data, loading } = useQuery<ListCommentsQueryResponse, ListCommentsQueryVariables>(
LIST_COMMENTS_QUERY,
{
variables
}
);

const { data, loading, refetch } = useQuery<
ListCommentsQueryResponse,
ListCommentsQueryVariables
>(LIST_COMMENTS_QUERY, {
variables
});

const comments = dotPropImmutable.get(data, "apw.listComments.data", []);

return {
comments,
loading
loading,
refetch
};
};
7 changes: 5 additions & 2 deletions packages/app-apw/src/hooks/useContentReview.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,24 @@ interface UseContentReviewParams {
interface UseContentReviewResult {
contentReview: ApwContentReview;
loading: boolean;
refetch: () => Promise<any>;
}

export function useContentReview(params: UseContentReviewParams): UseContentReviewResult {
const id = decodeURIComponent(params.id);

const { data, loading } = useQuery<
const { data, loading, refetch } = useQuery<
GetContentReviewQueryResponse,
GetContentReviewQueryVariables
>(GET_CONTENT_REVIEW_QUERY, {
variables: { id },
skip: !id
});

return {
contentReview: dotPropImmutable.get(data, "apw.getContentReview.data"),
loading
loading,
refetch
};
}

Expand Down
9 changes: 6 additions & 3 deletions packages/app-apw/src/hooks/useContentReviewsList.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useCallback, useState, useMemo, useEffect } from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import debounce from "lodash/debounce";
import { useNavigate } from "@webiny/react-router";
import { useQuery } from "@apollo/react-hooks";
Expand Down Expand Up @@ -37,6 +37,7 @@ interface UseContentReviewsListHook {
editContentReview: (item: ApwContentReviewListItem) => void;
status: ApwContentReviewStatus | "all";
setStatus: (status: ApwContentReviewStatus | "all") => void;
refetch: () => Promise<any>;
};
}

Expand Down Expand Up @@ -69,7 +70,8 @@ export const useContentReviewsList: UseContentReviewsListHook = (config: Config)
const {
data,
loading,
fetchMore: queryMore
fetchMore: queryMore,
refetch
} = useQuery<ListContentReviewsQueryResponse, ListContentReviewsQueryVariables>(
LIST_CONTENT_REVIEWS_QUERY,
{
Expand Down Expand Up @@ -150,6 +152,7 @@ export const useContentReviewsList: UseContentReviewsListHook = (config: Config)
serializeSorters,
editContentReview,
status,
setStatus
setStatus,
refetch
};
};
13 changes: 12 additions & 1 deletion packages/app-apw/src/hooks/useCurrentStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ import { useMemo } from "react";
import { useContentReview } from "~/hooks/useContentReview";
import { useContentReviewId, useCurrentStepId } from "./useContentReviewId";
import { ApwContentReviewStep } from "~/types";
import { useFetchInterval } from "~/hooks/useFetchInterval";

interface UseCurrentStepResult {
currentStep: ApwContentReviewStep | null;
changeRequestsPending: boolean;
}

const CONTENT_REVIEW_REFRESH_INTERVAL = 10000; // 10s

export const useCurrentStep = (): UseCurrentStepResult => {
const contentReviewId = useContentReviewId();
if (!contentReviewId) {
Expand All @@ -17,7 +20,15 @@ export const useCurrentStep = (): UseCurrentStepResult => {
};
}
const { id: stepId } = useCurrentStepId();
const { contentReview } = useContentReview({ id: contentReviewId.id });
const { contentReview, refetch, loading } = useContentReview({
id: contentReviewId.id
});

useFetchInterval({
callback: refetch,
interval: CONTENT_REVIEW_REFRESH_INTERVAL,
loading
});

const currentStep = useMemo(() => {
let currentStep;
Expand Down
77 changes: 77 additions & 0 deletions packages/app-apw/src/hooks/useFetchInterval.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { useCallback, useEffect, useRef, useState } from "react";

interface UseFetchDataProps {
callback: () => Promise<any>;
interval: number;
loading: boolean;
}

interface UseFetchDataResult {
error: Record<string, any> | null;
}

export const useFetchInterval = ({
callback,
interval,
loading
}: UseFetchDataProps): UseFetchDataResult => {
const [error, setError] = useState<Record<string, any> | null>(null);
const timer = useRef<string | number | NodeJS.Timeout | undefined>(undefined);

const [initiallyLoaded, setInitiallyLoaded] = useState<boolean>(false);
brunozoric marked this conversation as resolved.
Show resolved Hide resolved

// Recursive function which will not execute until api call is finished + the delay
const getData = useCallback(async () => {
try {
await callback();
clearTimeout(timer.current);
timer.current = setTimeout(() => {
getData();
}, interval);
} catch (e) {
setError(e);
}
}, []);

useEffect(() => {
/**
* We do not want to do anything if initial load was already done.
*/
if (initiallyLoaded === true) {
return;
}
/**
* When initiallyLoaded is false and loading is false, it means the initial loading was done so we can mark it.
*/
//
else if (initiallyLoaded === false && loading === false) {
setInitiallyLoaded(true);
}
/**
* When initiallyLoaded is false and loading is true, it means that this is the initial load.
*/
//
else if (!initiallyLoaded && loading === true) {
setInitiallyLoaded(false);
}
}, [loading]);

useEffect(() => {
if (initiallyLoaded !== true) {
return;
}
getData().catch(e => {
setError(e);
// do nothing
console.warn("Could not fetch the data:");
console.log(e);
});
return () => {
clearTimeout(timer.current);
};
}, [initiallyLoaded]);

return {
error
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, { useCallback } from "react";
import debounce from "lodash/debounce";
import SearchUI from "@webiny/app-admin/components/SearchUI";
import styled from "@emotion/styled";
import { DataList, List, DataListModalOverlayAction, ListItem } from "@webiny/ui/List";
import { DataList, DataListModalOverlayAction, List, ListItem } from "@webiny/ui/List";
import { i18n } from "@webiny/app/i18n";
import { ReactComponent as FilterIcon } from "@webiny/app-admin/assets/icons/filter-24px.svg";
import { ApwContentReviewListItem } from "~/types";
Expand All @@ -11,6 +11,7 @@ import { useContentReviewsList } from "~/hooks/useContentReviewsList";
import { ContentReviewsFilterModal } from "./components/ContentReviewsFilterOverlay";
import { Scrollbar } from "@webiny/ui/Scrollbar";
import { Typography } from "@webiny/ui/Typography";
import { useFetchInterval } from "~/hooks/useFetchInterval";

const t = i18n.ns("app-apw/admin/content-reviews/datalist");

Expand Down Expand Up @@ -51,6 +52,8 @@ const InlineLoaderWrapper = styled("div")({
backgroundColor: "var(--mdc-theme-surface)"
});

const CONTENT_REVIEW_LIST_REFRESH_INTERVAL = 10000;

export const ContentReviewDataList: React.FC = () => {
const {
contentReviews,
Expand All @@ -63,7 +66,8 @@ export const ContentReviewDataList: React.FC = () => {
setStatus,
setFilter,
fetchMore,
filter
filter,
refetch
} = useContentReviewsList({
sorters: SORTERS
});
Expand All @@ -78,6 +82,12 @@ export const ContentReviewDataList: React.FC = () => {
[loading, fetchMore]
);

useFetchInterval({
callback: refetch,
interval: CONTENT_REVIEW_LIST_REFRESH_INTERVAL,
loading
});

return (
<DataList
loading={loading}
Expand Down
Loading