-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: autorefresh fields in form gisce/webclient#1415 * fix: adjust seconds * fix: mantain values touched when autorefreshing gisce/webclient#1415 * chore: remove comment * fix: adjust id retrieval for autoRefresh gisce/webclient#1415 * feat: improve hooks and tree autorefreshable fields gisce/webclient#1415
- Loading branch information
1 parent
89cba68
commit a880c0f
Showing
8 changed files
with
421 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
import { ConnectionProvider } from ".."; | ||
import { useNetworkRequest } from "./useNetworkRequest"; | ||
import { useDeepCompareEffect } from "use-deep-compare"; | ||
import { useRef, useState, useCallback, useEffect } from "react"; | ||
import { useBrowserVisibility } from "./useBrowserVisibility"; | ||
|
||
const AUTOREFRESH_INTERVAL_SECONDS = 3 * 1000; | ||
|
||
export type UseAutorefreshableFormFieldsOpts = { | ||
model: string; | ||
id?: number; | ||
context: any; | ||
autorefreshableFields?: string[]; | ||
fieldDefs: any; | ||
onAutorefreshableFieldsChange: (newValues: any) => void; | ||
isActive?: boolean; | ||
}; | ||
|
||
export const useAutorefreshableFormFields = ( | ||
opts: UseAutorefreshableFormFieldsOpts, | ||
) => { | ||
const { | ||
model, | ||
id, | ||
context, | ||
autorefreshableFields, | ||
fieldDefs, | ||
onAutorefreshableFieldsChange, | ||
isActive, | ||
} = opts; | ||
|
||
const intervalRef = useRef<NodeJS.Timeout | null>(null); | ||
const [internalIsActive, setInternalIsActive] = useState(true); | ||
|
||
const [fetchRequest, cancelRequest] = useNetworkRequest( | ||
ConnectionProvider.getHandler().readObjects, | ||
); | ||
|
||
const tabOrWindowIsVisible = useBrowserVisibility(); | ||
|
||
useEffect(() => { | ||
if (isActive === false) { | ||
pause(); | ||
} | ||
if ( | ||
(isActive === undefined || isActive === true) && | ||
!tabOrWindowIsVisible | ||
) { | ||
pause(); | ||
} | ||
if ((isActive === undefined || isActive === true) && tabOrWindowIsVisible) { | ||
resume(); | ||
} | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [isActive, tabOrWindowIsVisible]); | ||
|
||
const refresh = useCallback(async () => { | ||
if (!id || !autorefreshableFields?.length || !internalIsActive) return; | ||
|
||
try { | ||
const [result] = await fetchRequest({ | ||
model, | ||
ids: [id], | ||
fields: fieldDefs, | ||
fieldsToRetrieve: autorefreshableFields, | ||
context, | ||
}); | ||
onAutorefreshableFieldsChange(result); | ||
} catch (err) { | ||
console.error(err); | ||
} | ||
}, [ | ||
id, | ||
autorefreshableFields, | ||
internalIsActive, | ||
fetchRequest, | ||
model, | ||
fieldDefs, | ||
context, | ||
onAutorefreshableFieldsChange, | ||
]); | ||
|
||
useDeepCompareEffect(() => { | ||
const shouldStart = id && autorefreshableFields?.length && internalIsActive; | ||
|
||
if (shouldStart) { | ||
refresh(); | ||
intervalRef.current = setInterval(refresh, AUTOREFRESH_INTERVAL_SECONDS); | ||
} | ||
|
||
return () => { | ||
cancelRequest(); | ||
if (intervalRef.current) { | ||
clearInterval(intervalRef.current); | ||
intervalRef.current = null; | ||
} | ||
}; | ||
}, [ | ||
autorefreshableFields, | ||
fetchRequest, | ||
fieldDefs, | ||
model, | ||
id, | ||
context, | ||
internalIsActive, | ||
]); | ||
|
||
const pause = useCallback(() => { | ||
setInternalIsActive(false); | ||
if (intervalRef.current) { | ||
clearInterval(intervalRef.current); | ||
intervalRef.current = null; | ||
} | ||
cancelRequest(); | ||
}, [cancelRequest]); | ||
|
||
const resume = useCallback(() => { | ||
setInternalIsActive(true); | ||
}, []); | ||
|
||
return { pause, resume }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
import { ConnectionProvider } from ".."; | ||
import { useNetworkRequest } from "./useNetworkRequest"; | ||
import { useDeepCompareEffect } from "use-deep-compare"; | ||
import { useRef, useState, useCallback, useEffect } from "react"; | ||
import { InfiniteTableRef } from "@gisce/react-formiga-table"; | ||
import { useBrowserVisibility } from "./useBrowserVisibility"; | ||
|
||
const AUTOREFRESH_INTERVAL_SECONDS = 3 * 1000; | ||
|
||
export type UseAutorefreshableTreeFieldsOpts = { | ||
tableRef: React.RefObject<InfiniteTableRef>; | ||
model: string; | ||
context: any; | ||
autorefreshableFields?: string[]; | ||
fieldDefs: any; | ||
isActive?: boolean; | ||
}; | ||
|
||
export const useAutorefreshableTreeFields = ( | ||
opts: UseAutorefreshableTreeFieldsOpts, | ||
) => { | ||
const { | ||
tableRef, | ||
model, | ||
context, | ||
autorefreshableFields, | ||
fieldDefs, | ||
isActive, | ||
} = opts; | ||
|
||
const intervalRef = useRef<NodeJS.Timeout | null>(null); | ||
const [internalIsActive, setInternalIsActive] = useState(true); | ||
|
||
const [fetchRequest, cancelRequest] = useNetworkRequest( | ||
ConnectionProvider.getHandler().readObjects, | ||
); | ||
|
||
const tabOrWindowIsVisible = useBrowserVisibility(); | ||
|
||
useEffect(() => { | ||
if (isActive === false) { | ||
pause(); | ||
} | ||
if ( | ||
(isActive === undefined || isActive === true) && | ||
!tabOrWindowIsVisible | ||
) { | ||
pause(); | ||
} | ||
if ((isActive === undefined || isActive === true) && tabOrWindowIsVisible) { | ||
resume(); | ||
} | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [isActive, tabOrWindowIsVisible]); | ||
|
||
const refresh = useCallback(async () => { | ||
if (!autorefreshableFields?.length || !internalIsActive) return; | ||
|
||
const ids = tableRef.current?.getVisibleRowIds(); | ||
|
||
if (!ids) return; | ||
|
||
try { | ||
const results = await fetchRequest({ | ||
model, | ||
ids, | ||
fields: fieldDefs, | ||
fieldsToRetrieve: autorefreshableFields, | ||
context, | ||
}); | ||
tableRef.current?.updateRows(results); | ||
} catch (err) { | ||
console.error(err); | ||
} | ||
}, [ | ||
autorefreshableFields, | ||
internalIsActive, | ||
tableRef, | ||
fetchRequest, | ||
model, | ||
fieldDefs, | ||
context, | ||
]); | ||
|
||
useDeepCompareEffect(() => { | ||
const shouldStart = autorefreshableFields?.length && internalIsActive; | ||
|
||
if (shouldStart) { | ||
refresh(); | ||
intervalRef.current = setInterval(refresh, AUTOREFRESH_INTERVAL_SECONDS); | ||
} | ||
|
||
return () => { | ||
cancelRequest(); | ||
if (intervalRef.current) { | ||
clearInterval(intervalRef.current); | ||
intervalRef.current = null; | ||
} | ||
}; | ||
}, [ | ||
autorefreshableFields, | ||
fetchRequest, | ||
fieldDefs, | ||
model, | ||
context, | ||
internalIsActive, | ||
]); | ||
|
||
const pause = useCallback(() => { | ||
setInternalIsActive(false); | ||
if (intervalRef.current) { | ||
clearInterval(intervalRef.current); | ||
intervalRef.current = null; | ||
} | ||
cancelRequest(); | ||
}, [cancelRequest]); | ||
|
||
const resume = useCallback(() => { | ||
setInternalIsActive(true); | ||
}, []); | ||
|
||
return { pause, resume }; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { useState, useEffect } from "react"; | ||
|
||
export const useBrowserVisibility = (): boolean => { | ||
const [isVisible, setIsVisible] = useState<boolean>(!document.hidden); | ||
|
||
useEffect(() => { | ||
const handleVisibilityChange = (): void => { | ||
setIsVisible(!document.hidden); | ||
}; | ||
|
||
document.addEventListener("visibilitychange", handleVisibilityChange); | ||
|
||
return (): void => { | ||
document.removeEventListener("visibilitychange", handleVisibilityChange); | ||
}; | ||
}, []); | ||
|
||
return isVisible; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import React, { useContext } from "react"; | ||
import { useContext } from "react"; | ||
|
||
import { | ||
TabManagerContext, | ||
|
Oops, something went wrong.