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

[INV-3576][INV-3488] Use of Recordsets when offline #3714

Merged
merged 19 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
90e81b8
Filter out non-cached recordsets when offline
LocalNewsTV Nov 25, 2024
ccb47f6
Refactor RecordTableHelpers.tsx to support cached records
LocalNewsTV Nov 25, 2024
87faa29
Create stubbed interface for UserRecords
LocalNewsTV Nov 26, 2024
43bfb8a
Add idList to cacheMetadata
LocalNewsTV Nov 26, 2024
0ca8c72
Pass cachedIdList to fulfilled action
LocalNewsTV Nov 26, 2024
e384580
Flip import to utils useSelector, reduce ternary to single render
LocalNewsTV Nov 26, 2024
1f736bf
update reducers to persist cacheList in recordset
LocalNewsTV Nov 26, 2024
a52fc52
remove explicit returns, use typed selector, use PropTypes
LocalNewsTV Nov 26, 2024
858cac4
set key to readonly, add fetchPaginatedCachedRecords method
LocalNewsTV Nov 26, 2024
113041d
Add offline path for activity_table_rows, improve typing/safety in file
LocalNewsTV Nov 26, 2024
5a87072
Disable filter buttons / sort when user mobile & offline
LocalNewsTV Nov 26, 2024
ce62e58
Fix old bug where limit/page evaluated 0 as false
LocalNewsTV Nov 26, 2024
17ecc00
use destructured values in dataAccess
LocalNewsTV Nov 26, 2024
725f508
Implement fetchPaginatedCachedRecords in sqlite-cache
LocalNewsTV Nov 26, 2024
4fc78fc
Revert nesting button in Records li tag
LocalNewsTV Nov 26, 2024
76d9ce6
Remove unused import
LocalNewsTV Nov 26, 2024
ed4ad23
Reduce filterRecordsetsByNetworkState
LocalNewsTV Nov 26, 2024
7dd37f0
reduce if to use optional chain
LocalNewsTV Nov 27, 2024
2ce96d8
Merge branch 'dev' into 3576-3488-block&use-recordsets-while-offline
plasticviking Nov 27, 2024
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
6 changes: 5 additions & 1 deletion app/src/UI/Map2/LayerPicker/LpRecordSet/LpRecordSet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import './LpRecordSet.css';
import LpRecordSetOption from './LpRecordSetOption';
import UserSettings from 'state/actions/userSettings/UserSettings';
import { UserRecordSet } from 'interfaces/UserRecordSet';
import filterRecordsetsByNetworkState from 'utils/filterRecordsetsByNetworkState';
import { MOBILE } from 'state/build-time-config';

type PropTypes = {
closePicker: () => void;
Expand All @@ -17,12 +19,14 @@ const LpRecordSet = ({ closePicker }: PropTypes) => {
const handleToggleVisibility = (id: string) => dispatch(UserSettings.RecordSet.toggleVisibility(id));
const handleCycleColour = (id: string) => dispatch(UserSettings.RecordSet.cycleColourById(id));
const handleToggleLabels = (id: string) => dispatch(UserSettings.RecordSet.toggleLabelVisibility(id));
const connected = useSelector((state) => state.Network.connected);
const recordSets = useSelector((state) => state.UserSettings?.recordSets);
const defaultRecordSets: UserRecordSet[] = [];
const customRecordSets: UserRecordSet[] = [];

const dispatch = useDispatch();
Object.keys(recordSets).forEach((recordSet) => {
const userIsMobileAndOffline = MOBILE && !connected;
filterRecordsetsByNetworkState(recordSets, userIsMobileAndOffline).forEach((recordSet) => {
if (DEFAULT_RECORD_TYPES.includes(recordSet)) {
defaultRecordSets.push({ ...recordSets[recordSet], id: recordSet });
} else {
Expand Down
12 changes: 6 additions & 6 deletions app/src/UI/Overlay/Records/Record.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useRef } from 'react';

import './Record.css';
import { Route, useHistory } from 'react-router';
import { useSelector } from 'react-redux';
import { useSelector } from 'utils/use_selector';
import { ActivityForm } from './Activity/Form';
import { ActivityPhotos } from './Activity/Photos';
import { OverlayHeader } from '../OverlayHeader';
Expand All @@ -19,12 +19,12 @@ export const Activity = (props) => {

const history = useHistory();
const id = history.location.pathname.split(':')[1]?.split('/')[0];
const failCode = useSelector((state: any) => state.ActivityPage?.failCode);
const activity_ID = useSelector((state: any) => state.ActivityPage?.activity?.activity_id);
const failCode = useSelector((state) => state.ActivityPage?.failCode);
const activity_ID = useSelector((state) => state.ActivityPage?.activity?.activity_id);

const loading = useSelector((state: any) => state.ActivityPage?.loading);
const apiDocsWithSelectOptions = useSelector((state: any) => state.UserSettings?.apiDocsWithSelectOptions);
const apiDocsWithViewOptions = useSelector((state: any) => state.UserSettings?.apiDocsWithViewOptions);
const loading = useSelector((state) => state.ActivityPage?.loading);
const apiDocsWithSelectOptions = useSelector((state) => state.UserSettings?.apiDocsWithSelectOptions);
const apiDocsWithViewOptions = useSelector((state) => state.UserSettings?.apiDocsWithViewOptions);

return (
<div className="records__activity">
Expand Down
37 changes: 28 additions & 9 deletions app/src/UI/Overlay/Records/RecordSet/Filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import debounce from 'lodash.debounce';
type PropTypes = {
setID: string;
id: string;
userOfflineMobile: boolean;
};

const Filter = ({ setID, id }: PropTypes) => {
const Filter = ({ setID, id, userOfflineMobile }: PropTypes) => {
const TIME_TO_AUTO_UPDATE_IN_SECONDS = 0.75;

/**
Expand Down Expand Up @@ -69,13 +70,22 @@ const Filter = ({ setID, id }: PropTypes) => {
const getFilterType = (filterTypeInState: string) => {
switch (filterTypeInState) {
case 'tableFilter':
return <input key={id} className="filterSelect" onChange={handleInputChange} type="text" value={inputValue} />;
return (
<input
className="filterSelect"
disabled={userOfflineMobile}
onChange={handleInputChange}
type="text"
value={inputValue}
/>
);
case 'spatialFilterUploaded':
return (
<select
className="filterSelect"
value={valueInState}
disabled={userOfflineMobile}
onChange={(e) => updateFilter({ filter: e.target.value })}
value={valueInState}
>
{serverBoundariesToDisplay?.map((option) => (
<option key={option.value + option.label} value={option.value}>
Expand All @@ -88,8 +98,9 @@ const Filter = ({ setID, id }: PropTypes) => {
return (
<select
className="filterSelect"
value={valueInState}
disabled={userOfflineMobile}
onChange={(e) => updateFilter({ filter: e.target.value })}
value={valueInState}
>
{clientBoundariesToDisplay?.map((option) => (
<option key={option.value + option.label} value={option.value}>
Expand Down Expand Up @@ -134,8 +145,9 @@ const Filter = ({ setID, id }: PropTypes) => {
<td>
<select
className="filterSelect"
value={operator2InState}
disabled={userOfflineMobile}
onChange={(e) => updateFilter({ operator2: e.target.value })}
value={operator2InState}
>
{
{
Expand Down Expand Up @@ -176,8 +188,9 @@ const Filter = ({ setID, id }: PropTypes) => {
<td>
<select
className="filterSelect"
value={operatorInState}
disabled={userOfflineMobile}
onChange={(e) => updateFilter({ operator: e.target.value })}
value={operatorInState}
>
{
{
Expand Down Expand Up @@ -218,7 +231,7 @@ const Filter = ({ setID, id }: PropTypes) => {
<td>
<select
className="filterTypeSelect"
value={filterTypeInState}
disabled={userOfflineMobile}
onChange={(e) => {
const payload = {
filterType: e.target.value,
Expand All @@ -232,9 +245,9 @@ const Filter = ({ setID, id }: PropTypes) => {
if (e.target.value === 'spatialFilterDrawn') {
payload.filter = clientBoundariesToDisplay[0].value;
}

updateFilter({ ...payload });
}}
value={filterTypeInState}
>
<option value={'tableFilter'} label={'Field/Column'}>
Field/Column
Expand All @@ -258,6 +271,7 @@ const Filter = ({ setID, id }: PropTypes) => {
<td>
<select
className="filterSelect"
disabled={userOfflineMobile}
value={typeInState}
onChange={(e) => updateFilter({ filterID: id, field: e.target.value, filterType: 'tableFilter' })}
>
Expand All @@ -277,7 +291,12 @@ const Filter = ({ setID, id }: PropTypes) => {
<td>{input}</td>
<td className="deleteButtonCell">
<Tooltip classes={{ tooltip: 'toolTip' }} title="Delete the filter in this row, data will be refetched.">
<Button className={'deleteButton'} variant="contained" onClick={() => removeFilter('tableFilter')}>
<Button
className={'deleteButton'}
disabled={userOfflineMobile}
onClick={() => removeFilter('tableFilter')}
variant="contained"
>
Delete
</Button>
</Tooltip>
Expand Down
33 changes: 24 additions & 9 deletions app/src/UI/Overlay/Records/RecordSet/RecordSet.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { useDispatch, useSelector } from 'react-redux';
import { useDispatch } from 'react-redux';
import './RecordSet.css';
import Button from '@mui/material/Button';
import { useHistory } from 'react-router';
Expand All @@ -15,19 +15,26 @@ import FilterAltOffIcon from '@mui/icons-material/FilterAltOff';
import ExcelExporter from '../ExcelExporter';
import RecordSetFooter from './RecordSetFooter';
import Filter from './Filter';
import { useSelector } from 'utils/use_selector';
import { MOBILE } from 'state/build-time-config';
import { useEffect, useState } from 'react';

export const RecordSet = (props) => {
const viewFilters = useSelector((state: any) => state.Map.viewFilters);
const viewFilters = useSelector((state) => state.Map.viewFilters);
const connected = useSelector((state) => state.Network.connected);
const history = useHistory();
const dispatch = useDispatch();

const onClickBackButton = () => {
history.push('/Records');
};

const recordSet = useSelector((state: any) => state.UserSettings?.recordSets?.[props.setID]);
const [userOfflineMobile, setUserOfflineMobile] = useState<boolean>(!connected && MOBILE);
const recordSet = useSelector((state) => state.UserSettings?.recordSets?.[props.setID]);
const tableType = recordSet?.recordSetType;

useEffect(() => {
setUserOfflineMobile(MOBILE && !connected);
}, [connected]);
const onlyFilterIsForDrafts =
recordSet?.tableFilters?.length === 1 && recordSet?.tableFilters[0]?.field === 'form_status';
if (!recordSet) {
Expand All @@ -51,6 +58,7 @@ export const RecordSet = (props) => {
<Tooltip classes={{ tooltip: 'toolTip' }} title="Clear all filters and refetch all data for this layer.">
<Button
size={'small'}
disabled={userOfflineMobile}
onClick={() => {
dispatch({
type: RECORDSET_CLEAR_FILTERS,
Expand All @@ -70,6 +78,7 @@ export const RecordSet = (props) => {
<Tooltip classes={{ tooltip: 'toolTip' }} title="Toggle hiding filters - does not toggle applying them.">
<Button
size={'small'}
disabled={userOfflineMobile}
onClick={() => {
dispatch({
type: RECORDSETS_TOGGLE_VIEW_FILTER
Expand Down Expand Up @@ -103,6 +112,7 @@ export const RecordSet = (props) => {
>
<Button
size={'small'}
disabled={userOfflineMobile}
onClick={() => {
dispatch({
type: RECORDSET_ADD_FILTER,
Expand All @@ -126,7 +136,7 @@ export const RecordSet = (props) => {
</div>
<div className="recordSet_filters_container">
<div className="recordSet_filters">
{recordSet?.tableFilters?.length > 0 && !onlyFilterIsForDrafts && viewFilters ? (
{recordSet?.tableFilters?.length > 0 && !onlyFilterIsForDrafts && viewFilters && (
<table className="recordSetFilterTable">
<thead>
<tr>
Expand All @@ -140,17 +150,22 @@ export const RecordSet = (props) => {
<tbody>
{recordSet?.tableFilters.map((filter: any, i) => {
if (filter.field !== 'form_status')
return <Filter key={'filterIndex' + i} setID={props.setID} id={filter.id} />;
return (
<Filter
key={'filterIndex' + i}
setID={props.setID}
id={filter.id}
userOfflineMobile={userOfflineMobile}
/>
);
})}
</tbody>
</table>
) : (
<></>
)}
<ExcelExporter setName={props.setID} />
</div>
</div>
<RecordTable setID={props.setID} />
<RecordTable setID={props.setID} userOfflineMobile={userOfflineMobile} />
<RecordSetFooter setID={props.setID} />
</div>
);
Expand Down
Loading
Loading