From 967517316fdc926ee38ef6f356b3af592e73bf00 Mon Sep 17 00:00:00 2001
From: Ildar Kamalov <i.kamalov@adguard.com>
Date: Fri, 17 May 2019 18:17:17 +0300
Subject: [PATCH] * client: add link to the update error

---
 client/src/__locales/en.json           |  3 +--
 client/src/actions/index.js            |  7 +++----
 client/src/components/Toasts/Toast.css |  6 ++++++
 client/src/components/Toasts/Toast.js  | 21 +++++++++++++++++----
 client/src/reducers/toasts.js          | 12 +++++++++++-
 5 files changed, 38 insertions(+), 11 deletions(-)

diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json
index 8204cc0f..e0cf54e7 100644
--- a/client/src/__locales/en.json
+++ b/client/src/__locales/en.json
@@ -262,7 +262,6 @@
     "fix": "Fix",
     "dns_providers": "Here is a <0>list of known DNS providers</0> to choose from.",
     "update_now": "Update now",
-    "update_failed": "Update failed",
-    "update_failed_try_later": "Update failed, please try again later",
+    "update_failed": "Auto-update failed. Please <a href='https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#update'>follow the steps<\/a> to update manually.",
     "processing_update": "Please wait, AdGuard Home is being updated"
 }
\ No newline at end of file
diff --git a/client/src/actions/index.js b/client/src/actions/index.js
index 184f43ae..070c9324 100644
--- a/client/src/actions/index.js
+++ b/client/src/actions/index.js
@@ -12,6 +12,7 @@ const apiClient = new Api();
 
 export const addErrorToast = createAction('ADD_ERROR_TOAST');
 export const addSuccessToast = createAction('ADD_SUCCESS_TOAST');
+export const addNoticeToast = createAction('ADD_NOTICE_TOAST');
 export const removeToast = createAction('REMOVE_TOAST');
 
 export const toggleSettingStatus = createAction('SETTING_STATUS_TOGGLE');
@@ -169,7 +170,7 @@ export const getUpdate = () => async (dispatch) => {
             let timeout;
 
             if (count > 60) {
-                dispatch(addErrorToast({ error: 'update_failed_try_later' }));
+                dispatch(addNoticeToast({ error: 'update_failed' }));
                 dispatch(getUpdateFailure());
                 return false;
             }
@@ -181,8 +182,6 @@ export const getUpdate = () => async (dispatch) => {
                 ...args,
             );
 
-            console.log(count);
-
             axios.get('control/status')
                 .then((response) => {
                     rmTimeout(timeout);
@@ -202,7 +201,7 @@ export const getUpdate = () => async (dispatch) => {
 
         checkUpdate();
     } catch (error) {
-        dispatch(addErrorToast({ error: 'update_failed' }));
+        dispatch(addNoticeToast({ error: 'update_failed' }));
         dispatch(getUpdateFailure());
     }
 };
diff --git a/client/src/components/Toasts/Toast.css b/client/src/components/Toasts/Toast.css
index dd4f3c1b..c9496dba 100644
--- a/client/src/components/Toasts/Toast.css
+++ b/client/src/components/Toasts/Toast.css
@@ -32,6 +32,12 @@
     overflow: hidden;
 }
 
+.toast__content a {
+    font-weight: 600;
+    color: #fff;
+    text-decoration: underline;
+}
+
 .toast__dismiss {
     display: block;
     flex: 0 0 auto;
diff --git a/client/src/components/Toasts/Toast.js b/client/src/components/Toasts/Toast.js
index 0e951f09..ca9e1dd8 100644
--- a/client/src/components/Toasts/Toast.js
+++ b/client/src/components/Toasts/Toast.js
@@ -4,7 +4,7 @@ import { Trans, withNamespaces } from 'react-i18next';
 
 class Toast extends Component {
     componentDidMount() {
-        const timeout = this.props.type === 'error' ? 30000 : 5000;
+        const timeout = this.props.type === 'success' ? 5000 : 30000;
 
         setTimeout(() => {
             this.props.removeToast(this.props.id);
@@ -15,13 +15,25 @@ class Toast extends Component {
         return false;
     }
 
+    showMessage(t, type, message) {
+        if (type === 'notice') {
+            return <span dangerouslySetInnerHTML={{ __html: t(message) }} />;
+        }
+
+        return <Trans>{message}</Trans>;
+    }
+
     render() {
+        const {
+            type, id, t, message,
+        } = this.props;
+
         return (
-            <div className={`toast toast--${this.props.type}`}>
+            <div className={`toast toast--${type}`}>
                 <p className="toast__content">
-                    <Trans>{this.props.message}</Trans>
+                    {this.showMessage(t, type, message)}
                 </p>
-                <button className="toast__dismiss" onClick={() => this.props.removeToast(this.props.id)}>
+                <button className="toast__dismiss" onClick={() => this.props.removeToast(id)}>
                     <svg stroke="#fff" fill="none" width="20" height="20" strokeWidth="2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="m18 6-12 12"/><path d="m6 6 12 12"/></svg>
                 </button>
             </div>
@@ -30,6 +42,7 @@ class Toast extends Component {
 }
 
 Toast.propTypes = {
+    t: PropTypes.func.isRequired,
     id: PropTypes.string.isRequired,
     message: PropTypes.string.isRequired,
     type: PropTypes.string.isRequired,
diff --git a/client/src/reducers/toasts.js b/client/src/reducers/toasts.js
index c56085d3..34698480 100644
--- a/client/src/reducers/toasts.js
+++ b/client/src/reducers/toasts.js
@@ -1,7 +1,7 @@
 import { handleActions } from 'redux-actions';
 import nanoid from 'nanoid';
 
-import { addErrorToast, addSuccessToast, removeToast } from '../actions';
+import { addErrorToast, addSuccessToast, addNoticeToast, removeToast } from '../actions';
 
 const toasts = handleActions({
     [addErrorToast]: (state, { payload }) => {
@@ -24,6 +24,16 @@ const toasts = handleActions({
         const newState = { ...state, notices: [...state.notices, successToast] };
         return newState;
     },
+    [addNoticeToast]: (state, { payload }) => {
+        const noticeToast = {
+            id: nanoid(),
+            message: payload.error.toString(),
+            type: 'notice',
+        };
+
+        const newState = { ...state, notices: [...state.notices, noticeToast] };
+        return newState;
+    },
     [removeToast]: (state, { payload }) => {
         const filtered = state.notices.filter(notice => notice.id !== payload);
         const newState = { ...state, notices: filtered };