Skip to content

Commit

Permalink
feat: add loader header band
Browse files Browse the repository at this point in the history
  • Loading branch information
hel-axelor committed Feb 28, 2024
1 parent 58fc104 commit 5ba16aa
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 35 deletions.
4 changes: 2 additions & 2 deletions packages/apps/stock/src/screens/loader/LoaderScreen.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ const LoaderScreen = () => {
setTimeout(() => {
resolve('Process completed');
// reject('Process failed');
}, 10000);
}, 15000);
});

const handleSuccessAction = () => {
Expand Down Expand Up @@ -76,7 +76,7 @@ const LoaderScreen = () => {
onSuccess={handleSuccessAction}
onError={handleErrorAction}
disabled={false}
autoLeave={true}
autoLeave={false}
/>
</View>
</Screen>
Expand Down
14 changes: 14 additions & 0 deletions packages/core/src/app/RootNavigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {useTranslator} from '../i18n';
import {showToastMessage} from '../utils';
import {logout} from '../features/authSlice';
import {useSessionExpired} from '../apiProviders/config';
import {useLoaderListener} from '../components';

const {Navigator, Screen} = createNativeStackNavigator();

Expand All @@ -49,6 +50,7 @@ const RootNavigator = ({

const {sessionExpired} = useSessionExpired();
const {registerHeaderBand} = useHeaderBand();
const {numberProcesses} = useLoaderListener();

const {logged} = useSelector(state => state.auth);

Expand Down Expand Up @@ -121,6 +123,18 @@ const RootNavigator = ({
}
}, [handleSessionExpired, sessionExpired]);

useEffect(() => {
registerHeaderBand({
key: 'loader',
text: I18n.t('Base_Loader_ProccessesInBackground', {
numberProcesses,
}),
color: Colors.cautionColor,
order: 15,
showIf: numberProcesses > 0,
});
}, [I18n, Colors, registerHeaderBand, numberProcesses]);

return (
<Navigator screenOptions={{headerShown: false}}>
{!logged ? (
Expand Down
4 changes: 2 additions & 2 deletions packages/core/src/components/templates/Loader/LoaderPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
} from '@axelor/aos-mobile-ui';
import {useTranslator} from '../../../i18n';
import {useNavigation} from '../../../hooks/use-navigation';
import useLoaderListner from './use-loader-listener';
import useProcessRegister from './use-process-register';
import {processProvider} from './ProcessProvider';

interface LoaderPopupProps {
Expand Down Expand Up @@ -60,7 +60,7 @@ const LoaderPopup = ({

const timeoutRef = useRef(null);

const {processItem, loading} = useLoaderListner(
const {processItem, loading} = useProcessRegister(
{
disabled,
process,
Expand Down
24 changes: 23 additions & 1 deletion packages/core/src/components/templates/Loader/ProcessProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,16 @@ import {
class ProcessProvider {
private _events: Map<string, Event>;
private _processMap: Map<string, ProcessItem>;
private _numberOfRunningProcess: number;

constructor() {
this._events = new Map();
this._processMap = new Map();
this._numberOfRunningProcess = 0;
}

get numberOfRunningProcess() {
return this._numberOfRunningProcess;
}

on(key: string, e: EventType, c: callBack) {
Expand Down Expand Up @@ -80,7 +86,8 @@ class ProcessProvider {
}

notifyMe(p: ProcessItem) {
this._processMap.set(p.key, {...p, notifyMe: true});
p.notifyMe = true;
this._processMap.set(p.key, p);
}

async runProcess(p: ProcessItem, I18n: TranslatorProps) {
Expand All @@ -106,6 +113,8 @@ class ProcessProvider {
completed: true,
});

this.decrementNumberOfRunningProcess();

this.emit(
p.key,
status === ProcessStatus.COMPLETED
Expand Down Expand Up @@ -148,13 +157,26 @@ class ProcessProvider {
}
}

private incrementNumberOfRunningProcess() {
this._numberOfRunningProcess++;
}

private decrementNumberOfRunningProcess() {
this._numberOfRunningProcess = Math.max(
0,
this._numberOfRunningProcess - 1,
);
}

private onStart(p: ProcessItem) {
this._processMap.set(p.key, {
...p,
loading: true,
status: ProcessStatus.RUNNING,
});

this.incrementNumberOfRunningProcess();

this.on(p.key, EventType.COMPLETED, this.onCompleted);
this.on(p.key, EventType.FAILED, this.onFailed);
this.emit(p.key, EventType.STARTED);
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/components/templates/Loader/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@
export {default as LoaderPopup} from './LoaderPopup';
export * from './ProcessProvider';
export * from './types';
export {default as useLoaderListner} from './use-loader-listener';
export {default as useLoaderListener} from './use-loader-listener';
export {default as useProcessRegister} from './use-process-register';
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,17 @@
*/

import {useEffect, useMemo, useState} from 'react';
import {EventType, ProcessItem, ProcessOption} from './types';
import {processProvider} from './ProcessProvider';
import {generateUniqueID} from './loader-helper';

const useLoaderListner = (
processOptions: ProcessOption,
onFinish = () => {},
) => {
const [key, setKey] = useState<string>();
const [loading, setLoading] = useState<boolean>(false);
const [processItem, setProcessItem] = useState<ProcessItem>();

const onFinishCallback = () => {
setLoading(false);
onFinish();
};
const useLoaderListener = () => {
const [numberProcesses, setNumberProcesses] = useState<number>(0);

useEffect(() => {
const unid = generateUniqueID();
const p = processProvider.registerProcess(unid, processOptions);

processProvider.on(unid, EventType.STARTED, () => setLoading(true));
processProvider.on(unid, EventType.COMPLETED, onFinishCallback);
processProvider.on(unid, EventType.FAILED, onFinishCallback);

setKey(unid);
setProcessItem(p);
setNumberProcesses(processProvider.numberOfRunningProcess);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}, [processProvider.numberOfRunningProcess]);

return useMemo(
() => ({key, processItem, loading}),
[key, processItem, loading],
);
return useMemo(() => ({numberProcesses}), [numberProcesses]);
};

export default useLoaderListner;
export default useLoaderListener;
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Axelor Business Solutions
*
* Copyright (C) 2024 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

import {useEffect, useMemo, useState} from 'react';
import {EventType, ProcessItem, ProcessOption} from './types';
import {processProvider} from './ProcessProvider';
import {generateUniqueID} from './loader-helper';

const useProcessRegister = (
processOptions: ProcessOption,
onFinish = () => {},
) => {
const [key, setKey] = useState<string>();
const [loading, setLoading] = useState<boolean>(false);
const [processItem, setProcessItem] = useState<ProcessItem>();

const onFinishCallback = () => {
setLoading(false);
onFinish();
};

useEffect(() => {
const unid = generateUniqueID();
const p = processProvider.registerProcess(unid, processOptions);

processProvider.on(unid, EventType.STARTED, () => setLoading(true));
processProvider.on(unid, EventType.COMPLETED, onFinishCallback);
processProvider.on(unid, EventType.FAILED, onFinishCallback);

setKey(unid);
setProcessItem(p);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return useMemo(
() => ({key, processItem, loading}),
[key, processItem, loading],
);
};

export default useProcessRegister;
1 change: 1 addition & 0 deletions packages/core/src/i18n/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
"Base_Loader_DoNotCloseTheApp": "Do not close the application until the process is done.",
"Base_Loader_NotifyMe": "Notify me when it's ready",
"Base_Loader_LoadingInProgress": "Loading in progress",
"Base_Loader_ProccessesInBackground": "{{numberProcesses}} processes are running in background. Do not close the application.",
"Base_SliceAction_FetchAttachedFiles": "fetch attached files",
"Base_SliceAction_FetchFilesDetails": "fetch file details",
"Base_SliceAction_FetchMetaModule": "fetch meta modules",
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/i18n/translations/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@
"Base_Loader_DoNotCloseTheApp": "Veuillez ne pas fermer l'application avant que le processus soit terminé.",
"Base_Loader_NotifyMe": "M'avertir lorsqu'il est prêt",
"Base_Loader_LoadingInProgress": "Chargement en cours",
"Base_Loader_ProccessesInBackground": "{{numberProcesses}} processus sont en cours d'exécution en arrière-plan. Veuillez ne pas fermer l'application.",
"Base_SliceAction_FetchAttachedFiles": "récupération des fichiers joints",
"Base_SliceAction_FetchFilesDetails": "récupération des détails du fichier",
"Base_SliceAction_FetchMetaModule": "récupération des modules",
Expand Down

0 comments on commit 5ba16aa

Please sign in to comment.