diff --git a/Containers/UserSettings/AppriseAlertSettings/AppriseAlertSettings.js b/Containers/UserSettings/AppriseAlertSettings/AppriseAlertSettings.js
new file mode 100644
index 0000000..e62a41f
--- /dev/null
+++ b/Containers/UserSettings/AppriseAlertSettings/AppriseAlertSettings.js
@@ -0,0 +1,210 @@
+//Lib
+import { useEffect } from 'react';
+import { toast } from 'react-toastify';
+import 'react-toastify/dist/ReactToastify.css';
+import classes from '../UserSettings.module.css';
+import { useState } from 'react';
+import { SpinnerCircularFixed } from 'spinners-react';
+
+//Components
+import Error from '../../../Components/UI/Error/Error';
+import Switch from '../../../Components/UI/Switch/Switch';
+import AppriseURLs from './AppriseURLs/AppriseURLs';
+import AppriseMode from './AppriseMode/AppriseMode';
+
+export default function AppriseAlertSettings() {
+ //Var
+ const toastOptions = {
+ position: 'top-right',
+ autoClose: 5000,
+ hideProgressBar: false,
+ closeOnClick: true,
+ pauseOnHover: true,
+ draggable: true,
+ progress: undefined,
+ //Callback > re-enabled button after notification.
+ onClose: () => setDisabled(false),
+ };
+
+ ////State
+ const [checkIsLoading, setCheckIsLoading] = useState(true);
+ const [error, setError] = useState();
+ const [disabled, setDisabled] = useState(false);
+ const [checked, setChecked] = useState();
+ const [testIsLoading, setTestIsLoading] = useState(false);
+ const [info, setInfo] = useState(false);
+
+ ////LifeCycle
+ //Component did mount
+ useEffect(() => {
+ //Initial fetch to get the status of Apprise Alert
+ const getAppriseAlert = async () => {
+ try {
+ const response = await fetch('/api/account/getAppriseAlert', {
+ method: 'GET',
+ headers: {
+ 'Content-type': 'application/json',
+ },
+ });
+ setChecked((await response.json()).appriseAlert);
+ setCheckIsLoading(false);
+ } catch (error) {
+ setError(
+ 'Fetching apprise alert setting failed. Contact your administrator.'
+ );
+ console.log('Fetching apprise alert setting failed.');
+ setCheckIsLoading(false);
+ }
+ };
+ getAppriseAlert();
+ }, []);
+
+ ////Functions
+ //Switch to enable/disable Apprise notifications
+ const onChangeSwitchHandler = async (data) => {
+ //Remove old error
+ setError();
+ //Disabled button
+ setDisabled(true);
+ await fetch('/api/account/updateAppriseAlert', {
+ method: 'PUT',
+ headers: {
+ 'Content-type': 'application/json',
+ },
+ body: JSON.stringify(data),
+ })
+ .then((response) => {
+ console.log(response);
+ if (response.ok) {
+ if (data.appriseAlert) {
+ setChecked(!checked);
+ toast.success(
+ 'Apprise notifications enabled.',
+ toastOptions
+ );
+ } else {
+ setChecked(!checked);
+ toast.success(
+ 'Apprise notifications disabled.',
+ toastOptions
+ );
+ }
+ } else {
+ setError('Update apprise alert setting failed.');
+ setTimeout(() => {
+ setError();
+ setDisabled(false);
+ }, 4000);
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ setError('Update Apprise failed. Contact your administrator.');
+ setTimeout(() => {
+ setError();
+ setDisabled(false);
+ }, 4000);
+ });
+ };
+
+ //Send Apprise test notification to services
+ const onSendTestAppriseHandler = async () => {
+ //Loading
+ setTestIsLoading(true);
+ //Remove old error
+ setError();
+ try {
+ const response = await fetch('/api/account/sendTestApprise', {
+ method: 'POST',
+ headers: {
+ 'Content-type': 'application/json',
+ },
+ body: JSON.stringify({ sendTestApprise: true }),
+ });
+ const result = await response.json();
+ if (!response.ok) {
+ setTestIsLoading(false);
+ setError(result.message);
+ } else {
+ setTestIsLoading(false);
+ setInfo(true);
+ setTimeout(() => {
+ setInfo(false);
+ }, 4000);
+ }
+ } catch (error) {
+ setTestIsLoading(false);
+ console.log(error);
+ setError('Send notification failed. Contact your administrator.');
+ setTimeout(() => {
+ setError();
+ }, 4000);
+ }
+ };
+
+ return (
+ <>
+ {/* APPRISE ALERT */}
+
+
+
Apprise alert
+
+
+
+ {/* NOTIFY SWITCH */}
+ {checkIsLoading ? (
+
+ ) : (
+
+ onChangeSwitchHandler({ appriseAlert: e })
+ }
+ />
+ )}
+ {/* APPRISE SERVICES URLS */}
+
+ {/* APPRISE MODE SELECTION */}
+
+ {/* APPRISE TEST BUTTON */}
+ {testIsLoading ? (
+
+ ) : (
+
+ )}
+ {info && (
+
+ Notification successfully sent.
+
+ )}
+ {error && }
+
+
+
+ >
+ );
+}
diff --git a/Containers/UserSettings/AppriseAlertSettings/AppriseMode/AppriseMode.js b/Containers/UserSettings/AppriseAlertSettings/AppriseMode/AppriseMode.js
new file mode 100644
index 0000000..029cbf8
--- /dev/null
+++ b/Containers/UserSettings/AppriseAlertSettings/AppriseMode/AppriseMode.js
@@ -0,0 +1,173 @@
+//Lib
+import { useEffect } from 'react';
+import classes from '../../UserSettings.module.css';
+import { useState } from 'react';
+import { SpinnerCircularFixed } from 'spinners-react';
+import { useForm } from 'react-hook-form';
+
+//Components
+import Error from '../../../../Components/UI/Error/Error';
+
+export default function AppriseMode() {
+ //Var
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({ mode: 'onBlur' });
+
+ ////State
+ const [formIsLoading, setFormIsLoading] = useState(false);
+ const [modeFormIsSaved, setModeFormIsSaved] = useState(false);
+ const [error, setError] = useState(false);
+ const [displayStatelessURL, setDisplayStatelessURL] = useState(false);
+ const [appriseMode, setAppriseMode] = useState('');
+ const [appriseStatelessURL, setAppriseStatelessURL] = useState();
+
+ ////LifeCycle
+ //Component did mount
+ useEffect(() => {
+ //Initial fetch to get Apprise Mode enabled
+ const getAppriseMode = async () => {
+ try {
+ const response = await fetch('/api/account/getAppriseMode', {
+ method: 'GET',
+ headers: {
+ 'Content-type': 'application/json',
+ },
+ });
+ const { appriseStatelessURL, appriseMode } =
+ await response.json();
+ setAppriseMode(appriseMode);
+ if (appriseMode == 'stateless') {
+ setAppriseStatelessURL(appriseStatelessURL);
+ setDisplayStatelessURL(true);
+ }
+ } catch (error) {
+ console.log('Fetching Apprise Mode failed.');
+ }
+ };
+ getAppriseMode();
+ }, []);
+
+ ////Functions
+ //Form submit handler to modify Apprise Mode
+ const modeFormSubmitHandler = async (data) => {
+ //Remove old error
+ setError();
+ //Loading button on submit to avoid multiple send.
+ setFormIsLoading(true);
+ //POST API to update Apprise Mode
+ try {
+ const response = await fetch('/api/account/updateAppriseMode', {
+ method: 'PUT',
+ headers: {
+ 'Content-type': 'application/json',
+ },
+ body: JSON.stringify(data),
+ });
+ const result = await response.json();
+
+ if (!response.ok) {
+ setFormIsLoading(false);
+ setError(result.message);
+ setTimeout(() => setError(), 4000);
+ } else {
+ setFormIsLoading(false);
+ setModeFormIsSaved(true);
+ setTimeout(() => setModeFormIsSaved(false), 3000);
+ }
+ } catch (error) {
+ setFormIsLoading(false);
+ setError('Change mode failed. Contact your administrator.');
+ setTimeout(() => {
+ setError();
+ }, 4000);
+ }
+ };
+
+ return (
+ <>
+ {/* APPRISE MODE SELECTION */}
+
+
Apprise mode
+
+ {formIsLoading && (
+
+ )}
+ {modeFormIsSaved && (
+
+ ✅ Apprise mode has been saved.
+
+ )}
+
+
+ {error && }
+
+ >
+ );
+}
diff --git a/Containers/UserSettings/AppriseAlertSettings/AppriseURLs/AppriseURLs.js b/Containers/UserSettings/AppriseAlertSettings/AppriseURLs/AppriseURLs.js
new file mode 100644
index 0000000..2962ac7
--- /dev/null
+++ b/Containers/UserSettings/AppriseAlertSettings/AppriseURLs/AppriseURLs.js
@@ -0,0 +1,162 @@
+//Lib
+import { useEffect } from 'react';
+import classes from '../../UserSettings.module.css';
+import { useState } from 'react';
+import { SpinnerCircularFixed } from 'spinners-react';
+import { useForm } from 'react-hook-form';
+
+//Components
+import Error from '../../../../Components/UI/Error/Error';
+
+export default function AppriseURLs() {
+ //Var
+ const {
+ register,
+ handleSubmit,
+ formState: { errors },
+ } = useForm({ mode: 'onBlur' });
+
+ ////State
+ const [formIsLoading, setFormIsLoading] = useState(false);
+ const [urlsFormIsSaved, setUrlsFormIsSaved] = useState(false);
+ const [appriseServicesList, setAppriseServicesList] = useState();
+ const [error, setError] = useState();
+
+ ////LifeCycle
+ //Component did mount
+ useEffect(() => {
+ //Initial fetch to build the list of Apprise Services enabled
+ const getAppriseServices = async () => {
+ try {
+ const response = await fetch(
+ '/api/account/getAppriseServices',
+ {
+ method: 'GET',
+ headers: {
+ 'Content-type': 'application/json',
+ },
+ }
+ );
+ let servicesArray = (await response.json()).appriseServices;
+ const AppriseServicesListToText = () => {
+ let list = '';
+ for (let service of servicesArray) {
+ list += service + '\n';
+ }
+ return list;
+ };
+ setAppriseServicesList(AppriseServicesListToText());
+ } catch (error) {
+ console.log('Fetching Apprise services list failed.');
+ }
+ };
+ getAppriseServices();
+ }, []);
+
+ ////Functions
+ //Form submit handler to modify Apprise services
+ const urlsFormSubmitHandler = async (data) => {
+ //Remove old error
+ setError();
+ //Loading button on submit to avoid multiple send.
+ setFormIsLoading(true);
+ //POST API to update Apprise Services
+ try {
+ const response = await fetch('/api/account/updateAppriseServices', {
+ method: 'PUT',
+ headers: {
+ 'Content-type': 'application/json',
+ },
+ body: JSON.stringify(data),
+ });
+ const result = await response.json();
+
+ if (!response.ok) {
+ setFormIsLoading(false);
+ setError(result.message);
+ setTimeout(() => setError(), 4000);
+ } else {
+ setFormIsLoading(false);
+ setUrlsFormIsSaved(true);
+ setTimeout(() => setUrlsFormIsSaved(false), 3000);
+ }
+ } catch (error) {
+ setFormIsLoading(false);
+ setError(
+ 'Failed to update your services. Contact your administrator.'
+ );
+ setTimeout(() => {
+ setError();
+ }, 4000);
+ }
+ };
+
+ return (
+ <>
+ {/* APPRISE SERVICES URLS */}
+
+
Apprise URLs
+ {error &&
}
+
+ {formIsLoading && (
+
+ )}
+ {urlsFormIsSaved && (
+
+ ✅ Apprise configuration has been saved.
+
+ )}
+
+
+
+
+ Use{' '}
+
+ Apprise URLs
+ {' '}
+ to send a notification to any service. Only one URL per line.
+
+ >
+ );
+}
diff --git a/Containers/UserSettings/EmailAlertSettings/EmailAlertSettings.js b/Containers/UserSettings/EmailAlertSettings/EmailAlertSettings.js
index 3781162..a600691 100644
--- a/Containers/UserSettings/EmailAlertSettings/EmailAlertSettings.js
+++ b/Containers/UserSettings/EmailAlertSettings/EmailAlertSettings.js
@@ -10,7 +10,7 @@ import { SpinnerCircularFixed } from 'spinners-react';
import Error from '../../../Components/UI/Error/Error';
import Switch from '../../../Components/UI/Switch/Switch';
-export default function EmailAlertSettings(props) {
+export default function EmailAlertSettings() {
//Var
const toastOptions = {
position: 'top-right',
@@ -46,64 +46,96 @@ export default function EmailAlertSettings(props) {
setChecked((await response.json()).emailAlert);
setIsLoading(false);
} catch (error) {
+ setError(
+ 'Fetching email alert setting failed. Contact your administrator.'
+ );
console.log('Fetching email alert setting failed.');
+ setIsLoading(false);
}
};
dataFetch();
}, []);
////Functions
+ //Switch to enable/disable Email notifications
const onChangeSwitchHandler = async (data) => {
//Remove old error
setError();
//Disabled button
setDisabled(true);
- const response = await fetch('/api/account/updateEmailAlert', {
+ await fetch('/api/account/updateEmailAlert', {
method: 'PUT',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify(data),
- });
- const result = await response.json();
-
- if (!response.ok) {
- setError(result.message);
- setTimeout(() => {
- setError();
- setDisabled(false);
- }, 4000);
- } else {
- if (data.emailAlert) {
- setChecked(!checked);
- toast.success('Email notification enabled !', toastOptions);
- } else {
- setChecked(!checked);
- toast.success('Email notification disabled !', toastOptions);
- }
- }
+ })
+ .then((response) => {
+ console.log(response);
+ if (response.ok) {
+ if (data.emailAlert) {
+ setChecked(!checked);
+ toast.success(
+ 'Email notification enabled !',
+ toastOptions
+ );
+ } else {
+ setChecked(!checked);
+ toast.success(
+ 'Email notification disabled !',
+ toastOptions
+ );
+ }
+ } else {
+ setError('Update email alert setting failed.');
+ setTimeout(() => {
+ setError();
+ setDisabled(false);
+ }, 4000);
+ }
+ })
+ .catch((error) => {
+ console.log(error);
+ setError('Update failed. Contact your administrator.');
+ setTimeout(() => {
+ setError();
+ setDisabled(false);
+ }, 4000);
+ });
};
+ //Send a test notification by email
const onSendTestMailHandler = async () => {
//Loading
setTestIsLoading(true);
//Remove old error
setError();
- const response = await fetch('/api/account/sendTestEmail', {
+ await fetch('/api/account/sendTestEmail', {
method: 'POST',
- });
- const result = await response.json();
-
- if (!response.ok) {
- setTestIsLoading(false);
- setError(result.message);
- } else {
- setTestIsLoading(false);
- setInfo(true);
- setTimeout(() => {
- setInfo(false);
- }, 4000);
- }
+ })
+ .then((response) => {
+ if (!response.ok) {
+ setTestIsLoading(false);
+ setError('Failed to send the notification.');
+ setTimeout(() => {
+ setError();
+ }, 4000);
+ } else {
+ setTestIsLoading(false);
+ setInfo(true);
+ setTimeout(() => {
+ setInfo(false);
+ }, 4000);
+ }
+ })
+ .catch((error) => {
+ setTestIsLoading(false);
+ console.log(error);
+ setError('Send email failed. Contact your administrator.');
+ setTimeout(() => {
+ setError();
+ }, 4000);
+ });
};
return (
@@ -111,7 +143,7 @@ export default function EmailAlertSettings(props) {
{/* EMAIL ALERT */}
-
Alerting
+ Email alert
@@ -127,7 +159,7 @@ export default function EmailAlertSettings(props) {
onChangeSwitchHandler({ emailAlert: e })
diff --git a/Containers/UserSettings/EmailSettings/EmailSettings.js b/Containers/UserSettings/EmailSettings/EmailSettings.js
index cfed37b..71731f2 100644
--- a/Containers/UserSettings/EmailSettings/EmailSettings.js
+++ b/Containers/UserSettings/EmailSettings/EmailSettings.js
@@ -41,26 +41,33 @@ export default function EmailSettings(props) {
setError();
//Loading button on submit to avoid multiple send.
setIsLoading(true);
- //POST API to send the new and old password
- const response = await fetch('/api/account/updateEmail', {
- method: 'PUT',
- headers: {
- 'Content-type': 'application/json',
- },
- body: JSON.stringify(data),
- });
- const result = await response.json();
+ //POST API to send the new mail address
+ try {
+ const response = await fetch('/api/account/updateEmail', {
+ method: 'PUT',
+ headers: {
+ 'Content-type': 'application/json',
+ },
+ body: JSON.stringify(data),
+ });
+ const result = await response.json();
- if (!response.ok) {
- setIsLoading(false);
+ if (!response.ok) {
+ setIsLoading(false);
+ reset();
+ setError(result.message);
+ setTimeout(() => setError(), 4000);
+ } else {
+ reset();
+ setIsLoading(false);
+ setInfo(true);
+ toast.success('Email edited !', toastOptions);
+ }
+ } catch (error) {
reset();
- setError(result.message);
+ setIsLoading(false);
+ setError("Can't update your email. Contact your administrator.");
setTimeout(() => setError(), 4000);
- } else {
- reset();
- setIsLoading(false);
- setInfo(true);
- toast.success('Email edited !', toastOptions);
}
};
return (
@@ -107,7 +114,7 @@ export default function EmailSettings(props) {
)}