From b132a3ba1304156d8e0c1bd8337b8021de615794 Mon Sep 17 00:00:00 2001 From: tianlinzhong <673359306@qq.com> Date: Mon, 14 Feb 2022 17:06:46 +0800 Subject: [PATCH 1/3] fixed Web UI Notification bug --- myems-api/core/webmessage.py | 112 +++++++++++++++ .../MyEMS/Notification/Notification.js | 128 +++++++++++++++++- .../components/navbar/NotificationDropdown.js | 53 +++++++- 3 files changed, 287 insertions(+), 6 deletions(-) diff --git a/myems-api/core/webmessage.py b/myems-api/core/webmessage.py index a24b2961..ac75d902 100644 --- a/myems-api/core/webmessage.py +++ b/myems-api/core/webmessage.py @@ -245,6 +245,118 @@ class WebMessageStatusNewCollection: resp.text = json.dumps(result) + @staticmethod + @user_logger + def on_put(req, resp): + """Handles PUT requests""" + try: + raw_json = req.stream.read().decode('utf-8') + except Exception as ex: + raise falcon.HTTPError(falcon.HTTP_400, title='API.EXCEPTION', description=ex) + + new_values = json.loads(raw_json) + + if 'status' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['status'], str) or \ + len(str.strip(new_values['data']['status'])) == 0 or \ + str.strip(new_values['data']['status']) not in ('new', 'acknowledged', 'read'): + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_STATUS') + status = str.strip(new_values['data']['status']) + + # reply is required for 'acknowledged' status + if status == 'acknowledged' and \ + ('reply' not in new_values['data'].keys() or + not isinstance(new_values['data']['reply'], str) or + len(str.strip(new_values['data']['reply'])) == 0): + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_REPLY') + reply = str.strip(new_values['data']['reply']) + else: + reply = None + + # Verify User Session + token = req.headers.get('TOKEN') + user_uuid = req.headers.get('USER-UUID') + if token is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.TOKEN_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN') + if user_uuid is None: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.USER_UUID_NOT_FOUND_IN_HEADERS_PLEASE_LOGIN') + + cnx = mysql.connector.connect(**config.myems_user_db) + cursor = cnx.cursor(dictionary=True) + + query = (" SELECT utc_expires " + " FROM tbl_sessions " + " WHERE user_uuid = %s AND token = %s") + cursor.execute(query, (user_uuid, token,)) + row = cursor.fetchone() + + if row is None: + if cursor: + cursor.close() + if cnx: + cnx.disconnect() + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_SESSION_PLEASE_RE_LOGIN') + else: + utc_expires = row['utc_expires'] + if datetime.utcnow() > utc_expires: + if cursor: + cursor.close() + if cnx: + cnx.disconnect() + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.USER_SESSION_TIMEOUT') + + cursor.execute(" SELECT id " + " FROM tbl_users " + " WHERE uuid = %s ", + (user_uuid,)) + row = cursor.fetchone() + if row is None: + if cursor: + cursor.close() + if cnx: + cnx.disconnect() + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', + description='API.INVALID_USER_PLEASE_RE_LOGIN') + else: + user_id = row['id'] + + if cursor: + cursor.close() + if cnx: + cnx.disconnect() + + cnx = mysql.connector.connect(**config.myems_fdd_db) + cursor = cnx.cursor() + + cursor.execute(" SELECT user_id " + " FROM tbl_web_messages " + " WHERE status = %s AND user_id = %s ", ('new', user_id)) + if cursor.fetchall() is None: + cursor.close() + cnx.disconnect() + raise falcon.HTTPError(falcon.HTTP_404, title='API.NOT_FOUND', + description='API.WEB_MESSAGE_NOT_FOUND') + + update_row = (" UPDATE tbl_web_messages " + " SET status = %s, reply = %s " + " WHERE status = %s AND user_id = %s ") + cursor.execute(update_row, (status, + reply, + 'new', + user_id,)) + cnx.commit() + + cursor.close() + cnx.disconnect() + + resp.status = falcon.HTTP_200 + class WebMessageItem: @staticmethod diff --git a/web/src/components/MyEMS/Notification/Notification.js b/web/src/components/MyEMS/Notification/Notification.js index c5de3b4b..377610b5 100644 --- a/web/src/components/MyEMS/Notification/Notification.js +++ b/web/src/components/MyEMS/Notification/Notification.js @@ -273,7 +273,49 @@ const Notification = ({ setRedirect, setRedirectUrl, t }) => { }).then(json => { console.log(isResponseOK); if (isResponseOK) { - + let isResponseOK = false; + fetch(APIBaseURL + '/webmessages?' + + 'startdatetime=' + startDatetime.format('YYYY-MM-DDTHH:mm:ss') + + '&enddatetime=' + endDatetime.format('YYYY-MM-DDTHH:mm:ss'), { + method: 'GET', + headers: { + "Content-type": "application/json", + "User-UUID": getCookieValue('user_uuid'), + "Token": getCookieValue('token') + }, + body: null, + + }).then(response => { + if (response.ok) { + isResponseOK = true; + } + return response.json(); + }).then(json => { + if (isResponseOK) { + console.log(json); + setFetchSuccess(true); + + let notificationList = [] + + if (json.length > 0) { + json.forEach((currentValue, index) => { + let notification = {} + notification['id'] = json[index]['id']; + notification['subject'] = json[index]['subject']; + notification['created_datetime'] = moment(parseInt(json[index]['created_datetime'])) + .format("YYYY-MM-DD HH:mm:ss"); + notification['message'] = json[index]['message']; + notification['status'] = json[index]['status']; + notification['url'] = json[index]['url']; + + notificationList.push(notification); + }); + } + + setNotifications(notificationList); + setSpinnerHidden(true); + } + }); } else { toast.error(json.description) } @@ -308,7 +350,49 @@ const Notification = ({ setRedirect, setRedirectUrl, t }) => { }).then(json => { console.log(isResponseOK); if (isResponseOK) { + let isResponseOK = false; + fetch(APIBaseURL + '/webmessages?' + + 'startdatetime=' + startDatetime.format('YYYY-MM-DDTHH:mm:ss') + + '&enddatetime=' + endDatetime.format('YYYY-MM-DDTHH:mm:ss'), { + method: 'GET', + headers: { + "Content-type": "application/json", + "User-UUID": getCookieValue('user_uuid'), + "Token": getCookieValue('token') + }, + body: null, + }).then(response => { + if (response.ok) { + isResponseOK = true; + } + return response.json(); + }).then(json => { + if (isResponseOK) { + console.log(json); + setFetchSuccess(true); + + let notificationList = [] + + if (json.length > 0) { + json.forEach((currentValue, index) => { + let notification = {} + notification['id'] = json[index]['id']; + notification['subject'] = json[index]['subject']; + notification['created_datetime'] = moment(parseInt(json[index]['created_datetime'])) + .format("YYYY-MM-DD HH:mm:ss"); + notification['message'] = json[index]['message']; + notification['status'] = json[index]['status']; + notification['url'] = json[index]['url']; + + notificationList.push(notification); + }); + } + + setNotifications(notificationList); + setSpinnerHidden(true); + } + }); } else { toast.error(json.description) } @@ -338,7 +422,49 @@ const Notification = ({ setRedirect, setRedirectUrl, t }) => { }).then(json => { console.log(isResponseOK); if (isResponseOK) { + let isResponseOK = false; + fetch(APIBaseURL + '/webmessages?' + + 'startdatetime=' + startDatetime.format('YYYY-MM-DDTHH:mm:ss') + + '&enddatetime=' + endDatetime.format('YYYY-MM-DDTHH:mm:ss'), { + method: 'GET', + headers: { + "Content-type": "application/json", + "User-UUID": getCookieValue('user_uuid'), + "Token": getCookieValue('token') + }, + body: null, + }).then(response => { + if (response.ok) { + isResponseOK = true; + } + return response.json(); + }).then(json => { + if (isResponseOK) { + console.log(json); + setFetchSuccess(true); + + let notificationList = [] + + if (json.length > 0) { + json.forEach((currentValue, index) => { + let notification = {} + notification['id'] = json[index]['id']; + notification['subject'] = json[index]['subject']; + notification['created_datetime'] = moment(parseInt(json[index]['created_datetime'])) + .format("YYYY-MM-DD HH:mm:ss"); + notification['message'] = json[index]['message']; + notification['status'] = json[index]['status']; + notification['url'] = json[index]['url']; + + notificationList.push(notification); + }); + } + + setNotifications(notificationList); + setSpinnerHidden(true); + } + }); } else { toast.error(json.description) } diff --git a/web/src/components/navbar/NotificationDropdown.js b/web/src/components/navbar/NotificationDropdown.js index 002a0f89..ff718680 100644 --- a/web/src/components/navbar/NotificationDropdown.js +++ b/web/src/components/navbar/NotificationDropdown.js @@ -83,10 +83,9 @@ const NotificationDropdown = ({ t }) => { const markAsRead = e => { e.preventDefault(); - rawNewNotificationschild.map((notification,index) => { - console.log('Mark As Read: ', notification["id"]) - let isResponseOK = false; - fetch(APIBaseURL + '/webmessages/' + notification["id"], { + + let isResponseOK = false; + fetch(APIBaseURL + '/webmessagesnew', { method: 'PUT', headers: { "Content-type": "application/json", @@ -108,14 +107,58 @@ const NotificationDropdown = ({ t }) => { }).then(json => { console.log(isResponseOK); if (isResponseOK) { + let isResponseOK = false; + fetch(APIBaseURL + '/webmessagesnew', { + method: 'GET', + headers: { + "Content-type": "application/json", + "User-UUID": getCookieValue('user_uuid'), + "Token": getCookieValue('token') + }, + body: null, + }).then(response => { + console.log(response); + if (response.ok) { + isResponseOK = true; + } + return response.json(); + }).then(json => { + console.log(json) + if (isResponseOK) { + let NewnotificationList = [] + if (json.length > 0) { + json.forEach((currentValue, index) => { + let notification = {} + notification['id'] = json[index]['id']; + notification['status'] = json[index]['status']; + notification['subject'] = json[index]['subject'] + notification['message'] = json[index]['message']; + notification['created_datetime'] = moment(parseInt(json[index]['created_datetime'])) + .format("YYYY-MM-DD HH:mm:ss"); + if (NewnotificationList.length > 3 ){ + return true + } + if (notification['message'].length > 40){ + notification['message'] = notification['message'].substring(0,30) + "..."; + } + if (notification["status"] === "new"){ + NewnotificationList.push(notification); + } + + }); + } + setRawNewNotificationschild(NewnotificationList); + } + }).catch(err => { + console.log(err); + }); } else { toast.error(json.description) } }).catch(err => { console.log(err); }); - }); }; From 93f9641d8b693c2e4be9db55c683cc94f5c2eb23 Mon Sep 17 00:00:00 2001 From: "13621160019@163.com" <13621160019@163.com> Date: Thu, 17 Feb 2022 18:54:54 +0800 Subject: [PATCH 2/3] added Mark All As Read action to notification --- myems-api/MyEMS.postman_collection.json | 68 +++++++++++++++++++++++++ myems-api/core/webmessage.py | 28 +++++----- 2 files changed, 82 insertions(+), 14 deletions(-) diff --git a/myems-api/MyEMS.postman_collection.json b/myems-api/MyEMS.postman_collection.json index ffabe142..3fa925ce 100644 --- a/myems-api/MyEMS.postman_collection.json +++ b/myems-api/MyEMS.postman_collection.json @@ -9655,6 +9655,74 @@ }, "response": [] }, + { + "name": "PUT Update All New Web Messages (Mark All As Read)", + "request": { + "method": "PUT", + "header": [ + { + "key": "User-UUID", + "value": "dcdb67d1-6116-4987-916f-6fc6cf2bc0e4", + "type": "text", + "description": "Any admin users' UUID" + }, + { + "key": "Token", + "value": "597881540b33791a032b95aa48e0de098dc95ec0b813edd8a92cee87ee5eed1b8db7856a047ed06324c333bf2c98f0c7613e346ae25d1bcae3994f30b4562dfb", + "type": "text", + "description": "Login to get a valid token" + } + ], + "body": { + "mode": "raw", + "raw": "{\"data\":{\"status\":\"read\"}}" + }, + "url": { + "raw": "{{base_url}}/webmessagesnew", + "host": [ + "{{base_url}}" + ], + "path": [ + "webmessagesnew" + ] + } + }, + "response": [] + }, + { + "name": "PUT Update All New Web Messages (Acknowledge All)", + "request": { + "method": "PUT", + "header": [ + { + "key": "User-UUID", + "value": "dcdb67d1-6116-4987-916f-6fc6cf2bc0e4", + "type": "text", + "description": "Any admin users' UUID" + }, + { + "key": "Token", + "value": "597881540b33791a032b95aa48e0de098dc95ec0b813edd8a92cee87ee5eed1b8db7856a047ed06324c333bf2c98f0c7613e346ae25d1bcae3994f30b4562dfb", + "type": "text", + "description": "Login to get a valid token" + } + ], + "body": { + "mode": "raw", + "raw": "{\"data\":{\"status\":\"acknowledged\", \"reply\":\"OK\"}}" + }, + "url": { + "raw": "{{base_url}}/webmessagesnew", + "host": [ + "{{base_url}}" + ], + "path": [ + "webmessagesnew" + ] + } + }, + "response": [] + }, { "name": "GET a Web Message by ID", "request": { diff --git a/myems-api/core/webmessage.py b/myems-api/core/webmessage.py index ac75d902..6475495a 100644 --- a/myems-api/core/webmessage.py +++ b/myems-api/core/webmessage.py @@ -265,13 +265,13 @@ class WebMessageStatusNewCollection: status = str.strip(new_values['data']['status']) # reply is required for 'acknowledged' status - if status == 'acknowledged' and \ - ('reply' not in new_values['data'].keys() or - not isinstance(new_values['data']['reply'], str) or - len(str.strip(new_values['data']['reply'])) == 0): - raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', - description='API.INVALID_REPLY') - reply = str.strip(new_values['data']['reply']) + if status == 'acknowledged': + if 'reply' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['reply'], str) or \ + len(str.strip(new_values['data']['reply'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_REPLY') + else: + reply = str.strip(new_values['data']['reply']) else: reply = None @@ -485,13 +485,13 @@ class WebMessageItem: status = str.strip(new_values['data']['status']) # reply is required for 'acknowledged' status - if status == 'acknowledged' and \ - ('reply' not in new_values['data'].keys() or - not isinstance(new_values['data']['reply'], str) or - len(str.strip(new_values['data']['reply'])) == 0): - raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', - description='API.INVALID_REPLY') - reply = str.strip(new_values['data']['reply']) + if status == 'acknowledged': + if 'reply' not in new_values['data'].keys() or \ + not isinstance(new_values['data']['reply'], str) or \ + len(str.strip(new_values['data']['reply'])) == 0: + raise falcon.HTTPError(falcon.HTTP_400, title='API.BAD_REQUEST', description='API.INVALID_REPLY') + else: + reply = str.strip(new_values['data']['reply']) else: reply = None From 8ac293d4b300912a20197dc7a1e6f6a7a6111fb7 Mon Sep 17 00:00:00 2001 From: "13621160019@163.com" <13621160019@163.com> Date: Thu, 17 Feb 2022 18:55:31 +0800 Subject: [PATCH 3/3] added Mark All As Read action to notification --- .../components/navbar/NotificationDropdown.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/web/src/components/navbar/NotificationDropdown.js b/web/src/components/navbar/NotificationDropdown.js index ff718680..2b300d02 100644 --- a/web/src/components/navbar/NotificationDropdown.js +++ b/web/src/components/navbar/NotificationDropdown.js @@ -42,7 +42,7 @@ const NotificationDropdown = ({ t }) => { }).then(json => { console.log(json) if (isResponseOK) { - let NewnotificationList = [] + let NewNotificationList = [] if (json.length > 0) { json.forEach((currentValue, index) => { let notification = {} @@ -52,19 +52,19 @@ const NotificationDropdown = ({ t }) => { notification['message'] = json[index]['message']; notification['created_datetime'] = moment(parseInt(json[index]['created_datetime'])) .format("YYYY-MM-DD HH:mm:ss"); - if (NewnotificationList.length > 3 ){ + if (NewNotificationList.length > 3 ){ return true } if (notification['message'].length > 40){ notification['message'] = notification['message'].substring(0,30) + "..."; } if (notification["status"] === "new"){ - NewnotificationList.push(notification); + NewNotificationList.push(notification); } }); } - setRawNewNotificationschild(NewnotificationList); + setRawNewNotificationschild(NewNotificationList); } }).catch(err => { console.log(err); @@ -126,7 +126,7 @@ const NotificationDropdown = ({ t }) => { }).then(json => { console.log(json) if (isResponseOK) { - let NewnotificationList = [] + let NewNotificationList = [] if (json.length > 0) { json.forEach((currentValue, index) => { let notification = {} @@ -136,19 +136,19 @@ const NotificationDropdown = ({ t }) => { notification['message'] = json[index]['message']; notification['created_datetime'] = moment(parseInt(json[index]['created_datetime'])) .format("YYYY-MM-DD HH:mm:ss"); - if (NewnotificationList.length > 3 ){ + if (NewNotificationList.length > 3 ){ return true } if (notification['message'].length > 40){ notification['message'] = notification['message'].substring(0,30) + "..."; } if (notification["status"] === "new"){ - NewnotificationList.push(notification); + NewNotificationList.push(notification); } }); } - setRawNewNotificationschild(NewnotificationList); + setRawNewNotificationschild(NewNotificationList); } }).catch(err => { console.log(err);