From bdb189c57dc7e57b027f26aa5d97d736e592a87c Mon Sep 17 00:00:00 2001 From: Julien Fabre Date: Thu, 26 Oct 2023 02:26:01 +0200 Subject: [PATCH 1/8] feat: add count ressource for counter --- server/issue.go | 7 +++++ server/list.go | 7 +++++ server/plugin.go | 27 +++++++++++++++++++ server/store.go | 22 +++++++++++++++ webapp/src/action_types.js | 1 + webapp/src/actions.js | 21 +++++++++++++++ .../src/components/sidebar_buttons/index.js | 10 +++---- .../sidebar_buttons/sidebar_buttons.jsx | 16 +++++------ webapp/src/index.js | 6 ++--- webapp/src/reducer.js | 11 ++++++++ webapp/src/selectors.js | 1 + 11 files changed, 109 insertions(+), 20 deletions(-) diff --git a/server/issue.go b/server/issue.go index d366b785..95749975 100644 --- a/server/issue.go +++ b/server/issue.go @@ -24,6 +24,13 @@ type ExtendedIssue struct { ForeignPosition int `json:"position"` } +// CountIssue for all counter issues +type CountIssue struct { + In int `json:"in"` + My int `json:"my"` + Out int `json:"out"` +} + func newIssue(message string, description, postID string) *Issue { return &Issue{ ID: model.NewId(), diff --git a/server/list.go b/server/list.go index b6b65240..94665d3a 100644 --- a/server/list.go +++ b/server/list.go @@ -43,6 +43,9 @@ type ListStore interface { // GetList returns the list of IssueRef in listID for userID GetList(userID, listID string) ([]*IssueRef, error) + + // CountIssues returns all counter issues + CountIssues(userID string) (*CountIssue, error) } type listManager struct { @@ -135,6 +138,10 @@ func (l *listManager) GetIssueList(userID, listID string) ([]*ExtendedIssue, err return extendedIssues, nil } +func (l *listManager) CountIssues(userID string) (countIssues *CountIssue, err error) { + return l.store.CountIssues(userID) +} + func (l *listManager) CompleteIssue(userID, issueID string) (issue *Issue, foreignID string, listToUpdate string, err error) { issueList, ir, _ := l.store.GetIssueListAndReference(userID, issueID) if ir == nil { diff --git a/server/plugin.go b/server/plugin.go index d545bfeb..499ad4ee 100644 --- a/server/plugin.go +++ b/server/plugin.go @@ -32,6 +32,8 @@ type ListManager interface { SendIssue(senderID, receiverID, message, description, postID string) (string, error) // GetIssueList gets the todos on listID for userID GetIssueList(userID, listID string) ([]*ExtendedIssue, error) + // CountIssues get counter all issues + CountIssues(userID string) (*CountIssue, error) // CompleteIssue completes the todo issueID for userID, and returns the issue and the foreign ID if any CompleteIssue(userID, issueID string) (issue *Issue, foreignID string, listToUpdate string, err error) // AcceptIssue moves one the todo issueID of userID from inbox to myList, and returns the message and the foreignUserID if any @@ -116,6 +118,7 @@ func (p *Plugin) initializeAPI() { p.router.HandleFunc("/add", p.checkAuth(p.handleAdd)).Methods(http.MethodPost) p.router.HandleFunc("/list", p.checkAuth(p.handleList)).Methods(http.MethodGet) + p.router.HandleFunc("/count", p.checkAuth(p.handleCount)).Methods(http.MethodGet) p.router.HandleFunc("/remove", p.checkAuth(p.handleRemove)).Methods(http.MethodPost) p.router.HandleFunc("/complete", p.checkAuth(p.handleComplete)).Methods(http.MethodPost) p.router.HandleFunc("/accept", p.checkAuth(p.handleAccept)).Methods(http.MethodPost) @@ -340,6 +343,30 @@ func (p *Plugin) handleList(w http.ResponseWriter, r *http.Request) { } } +func (p *Plugin) handleCount(w http.ResponseWriter, r *http.Request) { + userID := r.Header.Get("Mattermost-User-ID") + + countIssues, err := p.listManager.CountIssues(userID) + if err != nil { + p.API.LogError("Unable to get issues for user err=" + err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to get issues for user", err) + return + } + + countIssuesJSON, err := json.Marshal(countIssues) + if err != nil { + p.API.LogError("Unable marhsal count issue list to json err=" + err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable marhsal count issue list to json", err) + return + } + + _, err = w.Write(countIssuesJSON) + if err != nil { + p.API.LogError("Unable to write json response err=" + err.Error()) + } + +} + func (p *Plugin) handleEdit(w http.ResponseWriter, r *http.Request) { userID := r.Header.Get("Mattermost-User-ID") diff --git a/server/store.go b/server/store.go index c49d9e2d..3c7cc8b2 100644 --- a/server/store.go +++ b/server/store.go @@ -327,6 +327,28 @@ func (l *listStore) getList(userID, listID string) ([]*IssueRef, []byte, error) return list, originalJSONList, nil } +func (l *listStore) CountIssues(userID string) (*CountIssue, error) { + myList, err := l.GetList(userID, MyListKey) + if err != nil { + return nil, err + } + inList, err := l.GetList(userID, InListKey) + if err != nil { + return nil, err + } + outList, err := l.GetList(userID, OutListKey) + if err != nil { + return nil, err + } + + return &CountIssue{ + In: len(inList), + My: len(myList), + Out: len(outList), + }, nil + +} + func (l *listStore) saveList(userID, listID string, list []*IssueRef, originalJSONList []byte) (bool, error) { newJSONList, jsonErr := json.Marshal(list) if jsonErr != nil { diff --git a/webapp/src/action_types.js b/webapp/src/action_types.js index 8d38db63..e8a61cfb 100644 --- a/webapp/src/action_types.js +++ b/webapp/src/action_types.js @@ -15,6 +15,7 @@ export const REMOVE_ASSIGNEE = pluginId + '_remove_assignee'; export const GET_ISSUES = pluginId + '_get_issues'; export const GET_OUT_ISSUES = pluginId + '_get_out_issues'; export const GET_IN_ISSUES = pluginId + '_get_in_issues'; +export const GET_COUNT_ISSUES = pluginId + '_get_count_issues'; export const RECEIVED_SHOW_RHS_ACTION = pluginId + '_show_rhs'; export const UPDATE_RHS_STATE = pluginId + '_update_rhs_state'; export const SET_RHS_VISIBLE = pluginId + '_set_rhs_visible'; diff --git a/webapp/src/actions.js b/webapp/src/actions.js index 3c1d29ef..518f9ba7 100644 --- a/webapp/src/actions.js +++ b/webapp/src/actions.js @@ -20,6 +20,7 @@ import { CLOSE_ADD_CARD, SET_EDITING_TODO, REMOVE_EDITING_TODO, + GET_COUNT_ISSUES, } from './action_types'; import {getPluginServerRoute} from './selectors'; @@ -174,6 +175,26 @@ export const list = (reminder = false, listName = 'my') => async (dispatch, getS return {data}; }; +export const count = () => async (dispatch, getState) => { + let resp; + let data; + try { + resp = await fetch(getPluginServerRoute(getState()) + '/count', Client4.getOptions({ + method: 'get', + })); + data = await resp.json(); + } catch (error) { + return {error}; + } + + dispatch({ + type: GET_COUNT_ISSUES, + data, + }); + + return {data}; +}; + export const remove = (id) => async (dispatch, getState) => { await fetch(getPluginServerRoute(getState()) + '/remove', Client4.getOptions({ method: 'post', diff --git a/webapp/src/components/sidebar_buttons/index.js b/webapp/src/components/sidebar_buttons/index.js index 81bd3a10..4c24e131 100644 --- a/webapp/src/components/sidebar_buttons/index.js +++ b/webapp/src/components/sidebar_buttons/index.js @@ -4,15 +4,13 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {list, updateRhsState, telemetry} from '../../actions'; +import {count, updateRhsState, telemetry} from '../../actions'; import SidebarButtons from './sidebar_buttons.jsx'; function mapStateToProps(state) { return { - issues: state['plugins-com.mattermost.plugin-todo'].issues, - inIssues: state['plugins-com.mattermost.plugin-todo'].inIssues, - outIssues: state['plugins-com.mattermost.plugin-todo'].outIssues, + countIssues: state['plugins-com.mattermost.plugin-todo'].countIssues, showRHSPlugin: state['plugins-com.mattermost.plugin-todo'].rhsPluginAction, }; } @@ -20,11 +18,11 @@ function mapStateToProps(state) { function mapDispatchToProps(dispatch) { return { actions: bindActionCreators({ - list, + count, updateRhsState, telemetry, }, dispatch), }; } -export default connect(mapStateToProps, mapDispatchToProps)(SidebarButtons); \ No newline at end of file +export default connect(mapStateToProps, mapDispatchToProps)(SidebarButtons); diff --git a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx index 0ef2e505..cffd08f4 100644 --- a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx +++ b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx @@ -13,11 +13,9 @@ export default class SidebarButtons extends React.PureComponent { theme: PropTypes.object.isRequired, isTeamSidebar: PropTypes.bool, showRHSPlugin: PropTypes.func.isRequired, - issues: PropTypes.arrayOf(PropTypes.object), - inIssues: PropTypes.arrayOf(PropTypes.object), - outIssues: PropTypes.arrayOf(PropTypes.object), + countIssues: PropTypes.object, actions: PropTypes.shape({ - list: PropTypes.func.isRequired, + count: PropTypes.func.isRequired, updateRhsState: PropTypes.func.isRequired, telemetry: PropTypes.func.isRequired, }).isRequired, @@ -49,9 +47,7 @@ export default class SidebarButtons extends React.PureComponent { container = style.containerTeam; } - const issues = this.props.issues || []; - const inIssues = this.props.inIssues || []; - const outIssues = this.props.outIssues || []; + const countIssues = this.props.countIssues; return (
@@ -68,7 +64,7 @@ export default class SidebarButtons extends React.PureComponent { }} > - {' ' + issues.length} + {' ' + countIssues.my} - {' ' + inIssues.length} + {' ' + countIssues.in} - {' ' + outIssues.length} + {' ' + countIssues.out}
diff --git a/webapp/src/index.js b/webapp/src/index.js index 3e3d21dc..d059563c 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -6,7 +6,7 @@ import Root from './components/root'; import AssigneeModal from './components/assignee_modal'; import SidebarRight from './components/sidebar_right'; -import {openAddCard, list, setShowRHSAction, telemetry, updateConfig, setHideTeamSidebar} from './actions'; +import {openAddCard, list, setShowRHSAction, telemetry, updateConfig, setHideTeamSidebar, count} from './actions'; import reducer from './reducer'; import PostTypeTodo from './components/post_type_todo'; import TeamSidebar from './components/team_sidebar'; @@ -83,9 +83,7 @@ export default class Plugin { registry.registerWebSocketEventHandler(`custom_${pluginId}_refresh`, refresh); registry.registerReconnectHandler(refreshAll); - store.dispatch(list(true)); - store.dispatch(list(false, 'in')); - store.dispatch(list(false, 'out')); + store.dispatch(count()); // register websocket event to track config changes const configUpdate = ({data}) => { diff --git a/webapp/src/reducer.js b/webapp/src/reducer.js index b186be16..dabafc8b 100644 --- a/webapp/src/reducer.js +++ b/webapp/src/reducer.js @@ -12,6 +12,7 @@ import { GET_ISSUES, SET_EDITING_TODO, REMOVE_EDITING_TODO, + GET_COUNT_ISSUES, GET_IN_ISSUES, GET_OUT_ISSUES, RECEIVED_SHOW_RHS_ACTION, @@ -113,6 +114,15 @@ const outIssues = (state = [], action) => { } }; +const countIssues = (state = {}, action) => { + switch (action.type) { + case GET_COUNT_ISSUES: + return action.data; + default: + return state; + } +}; + function rhsPluginAction(state = null, action) { switch (action.type) { case RECEIVED_SHOW_RHS_ACTION: @@ -159,6 +169,7 @@ export default combineReducers({ issues, inIssues, outIssues, + countIssues, rhsState, rhsPluginAction, isRhsVisible, diff --git a/webapp/src/selectors.js b/webapp/src/selectors.js index 8755de99..0dd7e78e 100644 --- a/webapp/src/selectors.js +++ b/webapp/src/selectors.js @@ -27,6 +27,7 @@ export const getMessage = (state) => { export const getIssues = (state) => getPluginState(state).issues; export const getInIssues = (state) => getPluginState(state).inIssues; export const getOutIssues = (state) => getPluginState(state).outIssues; +export const getCountIssues = (state) => getPluginState(state).countIssues; export const getCurrentTeamRoute = (state) => { const basePath = getSiteURL(state); const teamName = state.entities.teams.teams[state.entities.teams.currentTeamId].name; From 80d96b773310cce360449739cc2c86e5cd7307fe Mon Sep 17 00:00:00 2001 From: Julien Fabre Date: Thu, 26 Oct 2023 02:46:24 +0200 Subject: [PATCH 2/8] chore: add count to update or add list --- webapp/src/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/webapp/src/index.js b/webapp/src/index.js index d059563c..d806e484 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -66,11 +66,15 @@ export default class Plugin { return frontendListName; }; - const refresh = ({data: {lists}}) => lists.forEach((listName) => store.dispatch(list(false, getFrontendListName(listName)))); + const refresh = ({data: {lists}}) => { + lists.forEach((listName) => store.dispatch(list(false, getFrontendListName(listName)))); + store.dispatch(count()); + }; const refreshAll = () => { store.dispatch(list(false)); store.dispatch(list(false, 'in')); store.dispatch(list(false, 'out')); + store.dispatch(count()); }; const iconURL = getPluginServerRoute(store.getState()) + '/public/app-bar-icon.png'; From 49f7ffc8b7de82ed4fe9cd3e66d5e2a5ac213a9a Mon Sep 17 00:00:00 2001 From: Julien Fabre Date: Tue, 31 Oct 2023 23:04:47 +0100 Subject: [PATCH 3/8] fix: review --- server/plugin.go | 128 +++++++++++------- webapp/src/actions.js | 5 +- .../src/components/sidebar_buttons/index.js | 4 +- .../sidebar_buttons/sidebar_buttons.jsx | 1 - webapp/src/index.js | 8 +- 5 files changed, 85 insertions(+), 61 deletions(-) diff --git a/server/plugin.go b/server/plugin.go index 499ad4ee..931ac61e 100644 --- a/server/plugin.go +++ b/server/plugin.go @@ -32,7 +32,7 @@ type ListManager interface { SendIssue(senderID, receiverID, message, description, postID string) (string, error) // GetIssueList gets the todos on listID for userID GetIssueList(userID, listID string) ([]*ExtendedIssue, error) - // CountIssues get counter all issues + // CountIssues get all counter issues CountIssues(userID string) (*CountIssue, error) // CompleteIssue completes the todo issueID for userID, and returns the issue and the foreign ID if any CompleteIssue(userID, issueID string) (issue *Issue, foreignID string, listToUpdate string, err error) @@ -171,8 +171,9 @@ func (p *Plugin) handleTelemetry(w http.ResponseWriter, r *http.Request) { telemetryRequest, err := GetTelemetryPayloadFromJSON(r.Body) if err != nil { - p.API.LogError("Unable to get telemetry payload from JSON err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusBadRequest, "Unable to get telemetry payload from JSON.", err) + msg := "Unable to get telemetry payload from JSON" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusBadRequest, msg, err) return } @@ -191,8 +192,9 @@ func (p *Plugin) handleAdd(w http.ResponseWriter, r *http.Request) { addRequest, err := GetAddIssuePayloadFromJSON(r.Body) if err != nil { - p.API.LogError("Unable to get add issue payload from JSON err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusBadRequest, "Unable to get add issue payload from JSON.", err) + msg := "Unable to get add issue payload from JSON" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusBadRequest, msg, err) return } @@ -206,8 +208,9 @@ func (p *Plugin) handleAdd(w http.ResponseWriter, r *http.Request) { if addRequest.SendTo == "" { _, err = p.listManager.AddIssue(userID, addRequest.Message, addRequest.Description, addRequest.PostID) if err != nil { - p.API.LogError("Unable to add issue err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to add issue", err) + msg := "Unable to add issue" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -223,16 +226,18 @@ func (p *Plugin) handleAdd(w http.ResponseWriter, r *http.Request) { receiver, appErr := p.API.GetUserByUsername(addRequest.SendTo) if appErr != nil { - p.API.LogError("username not valid, err=" + appErr.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to find user", appErr) + msg := "Unable to find user" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } if receiver.Id == userID { _, err = p.listManager.AddIssue(userID, addRequest.Message, addRequest.Description, addRequest.PostID) if err != nil { - p.API.LogError("Unable to add issue err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to add issue", err) + msg := "Unable to add issue" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -258,8 +263,9 @@ func (p *Plugin) handleAdd(w http.ResponseWriter, r *http.Request) { issueID, err := p.listManager.SendIssue(userID, receiver.Id, addRequest.Message, addRequest.Description, addRequest.PostID) if err != nil { - p.API.LogError("Unable to send issue err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to send issue", err) + msg := "Unable to send issue" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -298,8 +304,9 @@ func (p *Plugin) handleList(w http.ResponseWriter, r *http.Request) { issues, err := p.listManager.GetIssueList(userID, listID) if err != nil { - p.API.LogError("Unable to get issues for user err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to get issues for user", err) + msg := "Unable to get issues for user" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -307,8 +314,9 @@ func (p *Plugin) handleList(w http.ResponseWriter, r *http.Request) { var lastReminderAt int64 lastReminderAt, err = p.getLastReminderTimeForUser(userID) if err != nil { - p.API.LogError("Unable to send reminder err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to send reminder", err) + msg := "Unable to send reminder" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -332,8 +340,9 @@ func (p *Plugin) handleList(w http.ResponseWriter, r *http.Request) { issuesJSON, err := json.Marshal(issues) if err != nil { - p.API.LogError("Unable marhsal issues list to json err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable marhsal issues list to json", err) + msg := "Unable marhsal count issue list to json" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -348,15 +357,17 @@ func (p *Plugin) handleCount(w http.ResponseWriter, r *http.Request) { countIssues, err := p.listManager.CountIssues(userID) if err != nil { - p.API.LogError("Unable to get issues for user err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to get issues for user", err) + msg := "Unable to get issues for user" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } countIssuesJSON, err := json.Marshal(countIssues) if err != nil { - p.API.LogError("Unable marhsal count issue list to json err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable marhsal count issue list to json", err) + msg := "Unable marhsal count issue list to json" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -364,7 +375,6 @@ func (p *Plugin) handleCount(w http.ResponseWriter, r *http.Request) { if err != nil { p.API.LogError("Unable to write json response err=" + err.Error()) } - } func (p *Plugin) handleEdit(w http.ResponseWriter, r *http.Request) { @@ -372,8 +382,9 @@ func (p *Plugin) handleEdit(w http.ResponseWriter, r *http.Request) { editRequest, err := GetEditIssuePayloadFromJSON(r.Body) if err != nil { - p.API.LogError("Unable to get edit issue payload from JSON err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusBadRequest, "Unable to get edit issue payload from JSON.", err) + msg := "Unable to get edit issue payload from JSON" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusBadRequest, msg, err) return } @@ -384,8 +395,9 @@ func (p *Plugin) handleEdit(w http.ResponseWriter, r *http.Request) { foreignUserID, list, oldMessage, err := p.listManager.EditIssue(userID, editRequest.ID, editRequest.Message, editRequest.Description) if err != nil { - p.API.LogError("Unable to edit message: err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to edit issue", err) + msg := "Unable to edit message" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -412,8 +424,9 @@ func (p *Plugin) handleChangeAssignment(w http.ResponseWriter, r *http.Request) changeRequest, err := GetChangeAssignmentPayloadFromJSON(r.Body) if err != nil { - p.API.LogError("Unable to get change request payload from JSON err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusBadRequest, "Unable to get change request from JSON.", err) + msg := "Unable to get change request payload from JSON" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusBadRequest, msg, err) return } @@ -424,15 +437,17 @@ func (p *Plugin) handleChangeAssignment(w http.ResponseWriter, r *http.Request) receiver, appErr := p.API.GetUserByUsername(changeRequest.SendTo) if appErr != nil { - p.API.LogError("username not valid, err=" + appErr.Error()) - p.handleErrorWithCode(w, http.StatusNotFound, "Unable to find user", appErr) + msg := "username not valid" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusNotFound, msg, err) return } issueMessage, oldOwner, err := p.listManager.ChangeAssignment(changeRequest.ID, userID, receiver.Id) if err != nil { - p.API.LogError("Unable to change the assignment of an issue: err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to change the assignment", err) + msg := "Unable to change the assignment of an issue" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -458,8 +473,9 @@ func (p *Plugin) handleAccept(w http.ResponseWriter, r *http.Request) { acceptRequest, err := GetAcceptRequestPayloadFromJSON(r.Body) if err != nil { - p.API.LogError("Unable to get accept request payload from JSON err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusBadRequest, "Unable to get accept request from JSON.", err) + msg := "Unable to get accept request payload from JSON" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusBadRequest, msg, err) return } @@ -470,8 +486,9 @@ func (p *Plugin) handleAccept(w http.ResponseWriter, r *http.Request) { todoMessage, sender, err := p.listManager.AcceptIssue(userID, acceptRequest.ID) if err != nil { - p.API.LogError("Unable to accept issue err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to accept issue", err) + msg := "Unable to accept issue" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -490,8 +507,9 @@ func (p *Plugin) handleComplete(w http.ResponseWriter, r *http.Request) { completeRequest, err := GetCompleteIssuePayloadFromJSON(r.Body) if err != nil { - p.API.LogError("Unable to get complete issue request payload from JSON err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusBadRequest, "Unable to get complete issue request from JSON.", err) + msg := "Unable to get complete issue request payload from JSON" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusBadRequest, msg, err) return } @@ -502,8 +520,9 @@ func (p *Plugin) handleComplete(w http.ResponseWriter, r *http.Request) { issue, foreignID, listToUpdate, err := p.listManager.CompleteIssue(userID, completeRequest.ID) if err != nil { - p.API.LogError("Unable to complete issue err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to complete issue", err) + msg := "Unable to complete issue" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -530,8 +549,9 @@ func (p *Plugin) handleRemove(w http.ResponseWriter, r *http.Request) { removeRequest, err := GetRemoveIssuePayloadFromJSON(r.Body) if err != nil { - p.API.LogError("Unable to get remove issue request payload from JSON err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusBadRequest, "Unable to get remove issue request from JSON.", err) + msg := "Unable to get remove issue request payload from JSON" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusBadRequest, msg, err) return } @@ -542,8 +562,9 @@ func (p *Plugin) handleRemove(w http.ResponseWriter, r *http.Request) { issue, foreignID, isSender, listToUpdate, err := p.listManager.RemoveIssue(userID, removeRequest.ID) if err != nil { - p.API.LogError("Unable to remove issue, err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to remove issue", err) + msg := "Unable to remove issue" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } p.sendRefreshEvent(userID, []string{listToUpdate}) @@ -576,8 +597,9 @@ func (p *Plugin) handleBump(w http.ResponseWriter, r *http.Request) { bumpRequest, err := GetBumpIssuePayloadFromJSON(r.Body) if err != nil { - p.API.LogError("Unable to get bump issue request payload from JSON err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusBadRequest, "Unable to get bump issue request from JSON.", err) + msg := "Unable to get bump issue request payload from JSON" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusBadRequest, msg, err) return } @@ -588,8 +610,9 @@ func (p *Plugin) handleBump(w http.ResponseWriter, r *http.Request) { todoMessage, foreignUser, foreignIssueID, err := p.listManager.BumpIssue(userID, bumpRequest.ID) if err != nil { - p.API.LogError("Unable to bump issue, err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to bump issue", err) + msg := "Unable to bump issue" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } @@ -623,8 +646,9 @@ func (p *Plugin) handleConfig(w http.ResponseWriter, r *http.Request) { configJSON, err := json.Marshal(clientConfig) if err != nil { - p.API.LogError("Unable to marshal plugin configuration to json err=" + err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, "Unable to marshal plugin configuration to json", err) + msg := "Unable to marshal plugin configuration to json" + p.API.LogError(msg, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } diff --git a/webapp/src/actions.js b/webapp/src/actions.js index 518f9ba7..9c484b19 100644 --- a/webapp/src/actions.js +++ b/webapp/src/actions.js @@ -175,11 +175,10 @@ export const list = (reminder = false, listName = 'my') => async (dispatch, getS return {data}; }; -export const count = () => async (dispatch, getState) => { - let resp; +export const fetchIssueCounts = () => async (dispatch, getState) => { let data; try { - resp = await fetch(getPluginServerRoute(getState()) + '/count', Client4.getOptions({ + const resp = await fetch(getPluginServerRoute(getState()) + '/count', Client4.getOptions({ method: 'get', })); data = await resp.json(); diff --git a/webapp/src/components/sidebar_buttons/index.js b/webapp/src/components/sidebar_buttons/index.js index 4c24e131..580a285b 100644 --- a/webapp/src/components/sidebar_buttons/index.js +++ b/webapp/src/components/sidebar_buttons/index.js @@ -4,7 +4,7 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {count, updateRhsState, telemetry} from '../../actions'; +import {fetchIssueCounts, updateRhsState, telemetry} from '../../actions'; import SidebarButtons from './sidebar_buttons.jsx'; @@ -18,7 +18,7 @@ function mapStateToProps(state) { function mapDispatchToProps(dispatch) { return { actions: bindActionCreators({ - count, + fetchIssueCounts, updateRhsState, telemetry, }, dispatch), diff --git a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx index cffd08f4..f40a2b4e 100644 --- a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx +++ b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx @@ -15,7 +15,6 @@ export default class SidebarButtons extends React.PureComponent { showRHSPlugin: PropTypes.func.isRequired, countIssues: PropTypes.object, actions: PropTypes.shape({ - count: PropTypes.func.isRequired, updateRhsState: PropTypes.func.isRequired, telemetry: PropTypes.func.isRequired, }).isRequired, diff --git a/webapp/src/index.js b/webapp/src/index.js index d806e484..feedd837 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -66,9 +66,11 @@ export default class Plugin { return frontendListName; }; - const refresh = ({data: {lists}}) => { - lists.forEach((listName) => store.dispatch(list(false, getFrontendListName(listName)))); - store.dispatch(count()); + const refresh = (payload) => { + if (payload.data && payload.data.lists) { + payload.data.lists.forEach((listName) => store.dispatch(list(false, getFrontendListName(listName)))); + store.dispatch(count()); + } }; const refreshAll = () => { store.dispatch(list(false)); From e822f5192f88776be6f21a3113e9b364576bc968 Mon Sep 17 00:00:00 2001 From: Julien Fabre Date: Tue, 31 Oct 2023 23:36:35 +0100 Subject: [PATCH 4/8] fix: count to fetchIssueCounts --- webapp/src/actions.js | 3 +-- webapp/src/index.js | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/webapp/src/actions.js b/webapp/src/actions.js index 9c484b19..c81e1689 100644 --- a/webapp/src/actions.js +++ b/webapp/src/actions.js @@ -238,10 +238,9 @@ export function setHideTeamSidebar(payload) { } export const updateConfig = () => async (dispatch, getState) => { - let resp; let data; try { - resp = await fetch(getPluginServerRoute(getState()) + '/config', Client4.getOptions({ + const resp = await fetch(getPluginServerRoute(getState()) + '/config', Client4.getOptions({ method: 'get', })); data = await resp.json(); diff --git a/webapp/src/index.js b/webapp/src/index.js index feedd837..f2d25141 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -6,7 +6,7 @@ import Root from './components/root'; import AssigneeModal from './components/assignee_modal'; import SidebarRight from './components/sidebar_right'; -import {openAddCard, list, setShowRHSAction, telemetry, updateConfig, setHideTeamSidebar, count} from './actions'; +import {openAddCard, list, setShowRHSAction, telemetry, updateConfig, setHideTeamSidebar, fetchIssueCounts} from './actions'; import reducer from './reducer'; import PostTypeTodo from './components/post_type_todo'; import TeamSidebar from './components/team_sidebar'; @@ -69,14 +69,14 @@ export default class Plugin { const refresh = (payload) => { if (payload.data && payload.data.lists) { payload.data.lists.forEach((listName) => store.dispatch(list(false, getFrontendListName(listName)))); - store.dispatch(count()); + store.dispatch(fetchIssueCounts()); } }; const refreshAll = () => { store.dispatch(list(false)); store.dispatch(list(false, 'in')); store.dispatch(list(false, 'out')); - store.dispatch(count()); + store.dispatch(fetchIssueCounts()); }; const iconURL = getPluginServerRoute(store.getState()) + '/public/app-bar-icon.png'; @@ -89,7 +89,7 @@ export default class Plugin { registry.registerWebSocketEventHandler(`custom_${pluginId}_refresh`, refresh); registry.registerReconnectHandler(refreshAll); - store.dispatch(count()); + store.dispatch(fetchIssueCounts()); // register websocket event to track config changes const configUpdate = ({data}) => { From 662456562a5b60049fe2f004293852dc25a55f6d Mon Sep 17 00:00:00 2001 From: Julien Fabre Date: Thu, 2 Nov 2023 01:18:56 +0100 Subject: [PATCH 5/8] chore: review count in one request and lists --- server/issue.go | 7 ++++++ server/list.go | 25 +++++++++++++------ server/plugin.go | 16 ++++++------ server/store.go | 22 ---------------- webapp/src/action_types.js | 1 + webapp/src/actions.js | 8 +++--- .../src/components/sidebar_buttons/index.js | 6 ++--- .../sidebar_buttons/sidebar_buttons.jsx | 10 ++++---- webapp/src/components/sidebar_right/index.js | 10 +++----- .../sidebar_right/sidebar_right.jsx | 22 +++++++--------- webapp/src/index.js | 16 ++++-------- webapp/src/reducer.js | 8 +++--- webapp/src/selectors.js | 2 +- 13 files changed, 69 insertions(+), 84 deletions(-) diff --git a/server/issue.go b/server/issue.go index 95749975..e10d8729 100644 --- a/server/issue.go +++ b/server/issue.go @@ -24,6 +24,13 @@ type ExtendedIssue struct { ForeignPosition int `json:"position"` } +// ListsIssue for all list issues +type ListsIssue struct { + In []*ExtendedIssue `json:"in"` + My []*ExtendedIssue `json:"my"` + Out []*ExtendedIssue `json:"out"` +} + // CountIssue for all counter issues type CountIssue struct { In int `json:"in"` diff --git a/server/list.go b/server/list.go index 94665d3a..fbb1a104 100644 --- a/server/list.go +++ b/server/list.go @@ -35,17 +35,12 @@ type ListStore interface { PopReference(userID, listID string) (*IssueRef, error) // BumpReference moves the Issue reference for issueID in listID for userID to the beginning of the list BumpReference(userID, issueID, listID string) error - // GetIssueReference gets the IssueRef and position of the issue issueID on user userID's list listID GetIssueReference(userID, issueID, listID string) (*IssueRef, int, error) // GetIssueListAndReference gets the issue list, IssueRef and position for user userID GetIssueListAndReference(userID, issueID string) (string, *IssueRef, int) - // GetList returns the list of IssueRef in listID for userID GetList(userID, listID string) ([]*IssueRef, error) - - // CountIssues returns all counter issues - CountIssues(userID string) (*CountIssue, error) } type listManager struct { @@ -138,8 +133,24 @@ func (l *listManager) GetIssueList(userID, listID string) ([]*ExtendedIssue, err return extendedIssues, nil } -func (l *listManager) CountIssues(userID string) (countIssues *CountIssue, err error) { - return l.store.CountIssues(userID) +func (l *listManager) GetAllList(userID string) (listsIssue *ListsIssue, err error) { + inListIssue, err := l.GetIssueList(userID, InListKey) + if err != nil { + return nil, err + } + myListIssue, err := l.GetIssueList(userID, MyListKey) + if err != nil { + return nil, err + } + outListIssue, err := l.GetIssueList(userID, OutListKey) + if err != nil { + return nil, err + } + return &ListsIssue{ + In: inListIssue, + My: myListIssue, + Out: outListIssue, + }, nil } func (l *listManager) CompleteIssue(userID, issueID string) (issue *Issue, foreignID string, listToUpdate string, err error) { diff --git a/server/plugin.go b/server/plugin.go index 931ac61e..80c152cc 100644 --- a/server/plugin.go +++ b/server/plugin.go @@ -32,8 +32,8 @@ type ListManager interface { SendIssue(senderID, receiverID, message, description, postID string) (string, error) // GetIssueList gets the todos on listID for userID GetIssueList(userID, listID string) ([]*ExtendedIssue, error) - // CountIssues get all counter issues - CountIssues(userID string) (*CountIssue, error) + // GetAllList get all issues + GetAllList(userID string) (*ListsIssue, error) // CompleteIssue completes the todo issueID for userID, and returns the issue and the foreign ID if any CompleteIssue(userID, issueID string) (issue *Issue, foreignID string, listToUpdate string, err error) // AcceptIssue moves one the todo issueID of userID from inbox to myList, and returns the message and the foreignUserID if any @@ -118,7 +118,7 @@ func (p *Plugin) initializeAPI() { p.router.HandleFunc("/add", p.checkAuth(p.handleAdd)).Methods(http.MethodPost) p.router.HandleFunc("/list", p.checkAuth(p.handleList)).Methods(http.MethodGet) - p.router.HandleFunc("/count", p.checkAuth(p.handleCount)).Methods(http.MethodGet) + p.router.HandleFunc("/lists", p.checkAuth(p.handleLists)).Methods(http.MethodGet) p.router.HandleFunc("/remove", p.checkAuth(p.handleRemove)).Methods(http.MethodPost) p.router.HandleFunc("/complete", p.checkAuth(p.handleComplete)).Methods(http.MethodPost) p.router.HandleFunc("/accept", p.checkAuth(p.handleAccept)).Methods(http.MethodPost) @@ -352,10 +352,10 @@ func (p *Plugin) handleList(w http.ResponseWriter, r *http.Request) { } } -func (p *Plugin) handleCount(w http.ResponseWriter, r *http.Request) { +func (p *Plugin) handleLists(w http.ResponseWriter, r *http.Request) { userID := r.Header.Get("Mattermost-User-ID") - countIssues, err := p.listManager.CountIssues(userID) + allListIssue, err := p.listManager.GetAllList(userID) if err != nil { msg := "Unable to get issues for user" p.API.LogError(msg, "err", err.Error()) @@ -363,15 +363,15 @@ func (p *Plugin) handleCount(w http.ResponseWriter, r *http.Request) { return } - countIssuesJSON, err := json.Marshal(countIssues) + allListIssueJSON, err := json.Marshal(allListIssue) if err != nil { - msg := "Unable marhsal count issue list to json" + msg := "Unable marhsal all lists issues to json" p.API.LogError(msg, "err", err.Error()) p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) return } - _, err = w.Write(countIssuesJSON) + _, err = w.Write(allListIssueJSON) if err != nil { p.API.LogError("Unable to write json response err=" + err.Error()) } diff --git a/server/store.go b/server/store.go index 3c7cc8b2..c49d9e2d 100644 --- a/server/store.go +++ b/server/store.go @@ -327,28 +327,6 @@ func (l *listStore) getList(userID, listID string) ([]*IssueRef, []byte, error) return list, originalJSONList, nil } -func (l *listStore) CountIssues(userID string) (*CountIssue, error) { - myList, err := l.GetList(userID, MyListKey) - if err != nil { - return nil, err - } - inList, err := l.GetList(userID, InListKey) - if err != nil { - return nil, err - } - outList, err := l.GetList(userID, OutListKey) - if err != nil { - return nil, err - } - - return &CountIssue{ - In: len(inList), - My: len(myList), - Out: len(outList), - }, nil - -} - func (l *listStore) saveList(userID, listID string, list []*IssueRef, originalJSONList []byte) (bool, error) { newJSONList, jsonErr := json.Marshal(list) if jsonErr != nil { diff --git a/webapp/src/action_types.js b/webapp/src/action_types.js index e8a61cfb..f7752e71 100644 --- a/webapp/src/action_types.js +++ b/webapp/src/action_types.js @@ -16,6 +16,7 @@ export const GET_ISSUES = pluginId + '_get_issues'; export const GET_OUT_ISSUES = pluginId + '_get_out_issues'; export const GET_IN_ISSUES = pluginId + '_get_in_issues'; export const GET_COUNT_ISSUES = pluginId + '_get_count_issues'; +export const GET_ALL_ISSUES = pluginId + '_get_all_issues'; export const RECEIVED_SHOW_RHS_ACTION = pluginId + '_show_rhs'; export const UPDATE_RHS_STATE = pluginId + '_update_rhs_state'; export const SET_RHS_VISIBLE = pluginId + '_set_rhs_visible'; diff --git a/webapp/src/actions.js b/webapp/src/actions.js index c81e1689..479a135e 100644 --- a/webapp/src/actions.js +++ b/webapp/src/actions.js @@ -20,7 +20,7 @@ import { CLOSE_ADD_CARD, SET_EDITING_TODO, REMOVE_EDITING_TODO, - GET_COUNT_ISSUES, + GET_ALL_ISSUES, } from './action_types'; import {getPluginServerRoute} from './selectors'; @@ -175,10 +175,10 @@ export const list = (reminder = false, listName = 'my') => async (dispatch, getS return {data}; }; -export const fetchIssueCounts = () => async (dispatch, getState) => { +export const fetchAllIssue = () => async (dispatch, getState) => { let data; try { - const resp = await fetch(getPluginServerRoute(getState()) + '/count', Client4.getOptions({ + const resp = await fetch(getPluginServerRoute(getState()) + '/lists', Client4.getOptions({ method: 'get', })); data = await resp.json(); @@ -187,7 +187,7 @@ export const fetchIssueCounts = () => async (dispatch, getState) => { } dispatch({ - type: GET_COUNT_ISSUES, + type: GET_ALL_ISSUES, data, }); diff --git a/webapp/src/components/sidebar_buttons/index.js b/webapp/src/components/sidebar_buttons/index.js index 580a285b..d5a5973c 100644 --- a/webapp/src/components/sidebar_buttons/index.js +++ b/webapp/src/components/sidebar_buttons/index.js @@ -4,13 +4,13 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {fetchIssueCounts, updateRhsState, telemetry} from '../../actions'; +import {fetchAllIssue, updateRhsState, telemetry} from '../../actions'; import SidebarButtons from './sidebar_buttons.jsx'; function mapStateToProps(state) { return { - countIssues: state['plugins-com.mattermost.plugin-todo'].countIssues, + allIssues: state['plugins-com.mattermost.plugin-todo'].allIssues, showRHSPlugin: state['plugins-com.mattermost.plugin-todo'].rhsPluginAction, }; } @@ -18,7 +18,7 @@ function mapStateToProps(state) { function mapDispatchToProps(dispatch) { return { actions: bindActionCreators({ - fetchIssueCounts, + fetchAllIssue, updateRhsState, telemetry, }, dispatch), diff --git a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx index f40a2b4e..8a79dc05 100644 --- a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx +++ b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx @@ -13,7 +13,7 @@ export default class SidebarButtons extends React.PureComponent { theme: PropTypes.object.isRequired, isTeamSidebar: PropTypes.bool, showRHSPlugin: PropTypes.func.isRequired, - countIssues: PropTypes.object, + allIssues: PropTypes.object, actions: PropTypes.shape({ updateRhsState: PropTypes.func.isRequired, telemetry: PropTypes.func.isRequired, @@ -46,7 +46,7 @@ export default class SidebarButtons extends React.PureComponent { container = style.containerTeam; } - const countIssues = this.props.countIssues; + const allIssues = this.props.allIssues; return (
@@ -63,7 +63,7 @@ export default class SidebarButtons extends React.PureComponent { }} > - {' ' + countIssues.my} + {' ' + allIssues && allIssues.my ? allIssues.my.length : 0} - {' ' + countIssues.in} + {' ' + allIssues && allIssues.in ? allIssues.in.length : 0} - {' ' + countIssues.out} + {' ' + allIssues && allIssues.out ? allIssues.out.length : 0}
diff --git a/webapp/src/components/sidebar_right/index.js b/webapp/src/components/sidebar_right/index.js index 8eb8f512..27c12e01 100644 --- a/webapp/src/components/sidebar_right/index.js +++ b/webapp/src/components/sidebar_right/index.js @@ -4,17 +4,15 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {getIssues, getInIssues, getOutIssues, getSiteURL, getTodoToast} from '../../selectors'; -import {remove, list, openAssigneeModal, openAddCard, closeAddCard, complete, bump, accept, telemetry, setRhsVisible} from '../../actions'; +import {getSiteURL, getTodoToast} from '../../selectors'; +import {remove, fetchAllIssue, openAssigneeModal, openAddCard, closeAddCard, complete, bump, accept, telemetry, setRhsVisible} from '../../actions'; import SidebarRight from './sidebar_right.jsx'; function mapStateToProps(state) { return { - todos: getIssues(state), + allIssues: state['plugins-com.mattermost.plugin-todo'].allIssues, todoToast: getTodoToast(state), - inTodos: getInIssues(state), - outTodos: getOutIssues(state), siteURL: getSiteURL(state), rhsState: state['plugins-com.mattermost.plugin-todo'].rhsState, }; @@ -27,7 +25,7 @@ function mapDispatchToProps(dispatch) { complete, accept, bump, - list, + fetchAllIssue, openAddCard, closeAddCard, openAssigneeModal, diff --git a/webapp/src/components/sidebar_right/sidebar_right.jsx b/webapp/src/components/sidebar_right/sidebar_right.jsx index 5d059ff1..fba90a45 100644 --- a/webapp/src/components/sidebar_right/sidebar_right.jsx +++ b/webapp/src/components/sidebar_right/sidebar_right.jsx @@ -51,9 +51,7 @@ const InListName = 'in'; export default class SidebarRight extends React.PureComponent { static propTypes = { - todos: PropTypes.arrayOf(PropTypes.object), - inTodos: PropTypes.arrayOf(PropTypes.object), - outTodos: PropTypes.arrayOf(PropTypes.object), + allIssues: PropTypes.arrayOf(PropTypes.object), todoToast: PropTypes.object, theme: PropTypes.object.isRequired, siteURL: PropTypes.string.isRequired, @@ -63,7 +61,7 @@ export default class SidebarRight extends React.PureComponent { complete: PropTypes.func.isRequired, accept: PropTypes.func.isRequired, bump: PropTypes.func.isRequired, - list: PropTypes.func.isRequired, + fetchAllIssue: PropTypes.func.isRequired, openAddCard: PropTypes.func.isRequired, closeAddCard: PropTypes.func.isRequired, openAssigneeModal: PropTypes.func.isRequired, @@ -101,9 +99,7 @@ export default class SidebarRight extends React.PureComponent { componentDidMount() { document.addEventListener('keydown', this.handleKeypress); - this.props.actions.list(false, 'my'); - this.props.actions.list(false, 'in'); - this.props.actions.list(false, 'out'); + this.props.actions.fetchAllIssue(); this.props.actions.setVisible(true); } @@ -126,15 +122,15 @@ export default class SidebarRight extends React.PureComponent { } getInIssues() { - return this.props.inTodos.length; + return this.props.allIssues.in.length; } getOutIssues() { - return this.props.outTodos.length; + return this.props.allIssues.out.length; } getMyIssues() { - return this.props.todos.length; + return this.props.allIssues.my.length; } addTodoItem() { @@ -154,12 +150,12 @@ export default class SidebarRight extends React.PureComponent { switch (this.state.list) { case MyListName: - todos = this.props.todos || []; + todos = this.props.allIssues.my || []; addButton = 'Add Todo'; - inboxList = this.props.inTodos || []; + inboxList = this.props.allIssues.in || []; break; case OutListName: - todos = this.props.outTodos || []; + todos = this.props.allIssues.out || []; listHeading = 'Sent Todos'; addButton = 'Request a Todo from someone'; break; diff --git a/webapp/src/index.js b/webapp/src/index.js index f2d25141..a4996f42 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -6,7 +6,7 @@ import Root from './components/root'; import AssigneeModal from './components/assignee_modal'; import SidebarRight from './components/sidebar_right'; -import {openAddCard, list, setShowRHSAction, telemetry, updateConfig, setHideTeamSidebar, fetchIssueCounts} from './actions'; +import {openAddCard, list, setShowRHSAction, telemetry, updateConfig, setHideTeamSidebar, fetchAllIssue} from './actions'; import reducer from './reducer'; import PostTypeTodo from './components/post_type_todo'; import TeamSidebar from './components/team_sidebar'; @@ -66,17 +66,11 @@ export default class Plugin { return frontendListName; }; - const refresh = (payload) => { - if (payload.data && payload.data.lists) { - payload.data.lists.forEach((listName) => store.dispatch(list(false, getFrontendListName(listName)))); - store.dispatch(fetchIssueCounts()); - } + const refresh = () => { + store.dispatch(fetchAllIssue()); }; const refreshAll = () => { - store.dispatch(list(false)); - store.dispatch(list(false, 'in')); - store.dispatch(list(false, 'out')); - store.dispatch(fetchIssueCounts()); + store.dispatch(fetchAllIssue()); }; const iconURL = getPluginServerRoute(store.getState()) + '/public/app-bar-icon.png'; @@ -89,7 +83,7 @@ export default class Plugin { registry.registerWebSocketEventHandler(`custom_${pluginId}_refresh`, refresh); registry.registerReconnectHandler(refreshAll); - store.dispatch(fetchIssueCounts()); + store.dispatch(fetchAllIssue()); // register websocket event to track config changes const configUpdate = ({data}) => { diff --git a/webapp/src/reducer.js b/webapp/src/reducer.js index dabafc8b..589c2ae1 100644 --- a/webapp/src/reducer.js +++ b/webapp/src/reducer.js @@ -12,7 +12,7 @@ import { GET_ISSUES, SET_EDITING_TODO, REMOVE_EDITING_TODO, - GET_COUNT_ISSUES, + GET_ALL_ISSUES, GET_IN_ISSUES, GET_OUT_ISSUES, RECEIVED_SHOW_RHS_ACTION, @@ -114,9 +114,9 @@ const outIssues = (state = [], action) => { } }; -const countIssues = (state = {}, action) => { +const allIssues = (state = {}, action) => { switch (action.type) { - case GET_COUNT_ISSUES: + case GET_ALL_ISSUES: return action.data; default: return state; @@ -169,7 +169,7 @@ export default combineReducers({ issues, inIssues, outIssues, - countIssues, + allIssues, rhsState, rhsPluginAction, isRhsVisible, diff --git a/webapp/src/selectors.js b/webapp/src/selectors.js index 0dd7e78e..e3c23303 100644 --- a/webapp/src/selectors.js +++ b/webapp/src/selectors.js @@ -27,7 +27,7 @@ export const getMessage = (state) => { export const getIssues = (state) => getPluginState(state).issues; export const getInIssues = (state) => getPluginState(state).inIssues; export const getOutIssues = (state) => getPluginState(state).outIssues; -export const getCountIssues = (state) => getPluginState(state).countIssues; +export const getAllIssues = (state) => getPluginState(state).allIssues; export const getCurrentTeamRoute = (state) => { const basePath = getSiteURL(state); const teamName = state.entities.teams.teams[state.entities.teams.currentTeamId].name; From cd53a4ba9155057033c2888ddb0cbf18d5e06b56 Mon Sep 17 00:00:00 2001 From: Julien Fabre Date: Wed, 8 Nov 2023 00:34:34 +0100 Subject: [PATCH 6/8] fix: review --- server/issue.go | 7 --- server/plugin.go | 43 ++----------------- webapp/src/action_types.js | 4 -- webapp/src/actions.js | 40 +---------------- webapp/src/components/post_type_todo/index.js | 4 +- .../src/components/sidebar_buttons/index.js | 10 +++-- .../sidebar_buttons/sidebar_buttons.jsx | 14 +++--- webapp/src/components/sidebar_right/index.js | 10 +++-- .../sidebar_right/sidebar_right.jsx | 20 +++++---- webapp/src/index.js | 29 +++---------- webapp/src/reducer.js | 37 +--------------- webapp/src/selectors.js | 6 +-- 12 files changed, 51 insertions(+), 173 deletions(-) diff --git a/server/issue.go b/server/issue.go index e10d8729..7cf4834b 100644 --- a/server/issue.go +++ b/server/issue.go @@ -31,13 +31,6 @@ type ListsIssue struct { Out []*ExtendedIssue `json:"out"` } -// CountIssue for all counter issues -type CountIssue struct { - In int `json:"in"` - My int `json:"my"` - Out int `json:"out"` -} - func newIssue(message string, description, postID string) *Issue { return &Issue{ ID: model.NewId(), diff --git a/server/plugin.go b/server/plugin.go index 80c152cc..f9d9b4cb 100644 --- a/server/plugin.go +++ b/server/plugin.go @@ -117,7 +117,6 @@ func (p *Plugin) initializeAPI() { p.router.Use(p.withRecovery) p.router.HandleFunc("/add", p.checkAuth(p.handleAdd)).Methods(http.MethodPost) - p.router.HandleFunc("/list", p.checkAuth(p.handleList)).Methods(http.MethodGet) p.router.HandleFunc("/lists", p.checkAuth(p.handleLists)).Methods(http.MethodGet) p.router.HandleFunc("/remove", p.checkAuth(p.handleRemove)).Methods(http.MethodPost) p.router.HandleFunc("/complete", p.checkAuth(p.handleComplete)).Methods(http.MethodPost) @@ -290,19 +289,10 @@ func (p *Plugin) postReplyIfNeeded(postID, message, todo string) { } } -func (p *Plugin) handleList(w http.ResponseWriter, r *http.Request) { +func (p *Plugin) handleLists(w http.ResponseWriter, r *http.Request) { userID := r.Header.Get("Mattermost-User-ID") - listInput := r.URL.Query().Get("list") - listID := MyListKey - switch listInput { - case OutFlag: - listID = OutListKey - case InFlag: - listID = InListKey - } - - issues, err := p.listManager.GetIssueList(userID, listID) + allListIssue, err := p.listManager.GetAllList(userID) if err != nil { msg := "Unable to get issues for user" p.API.LogError(msg, "err", err.Error()) @@ -310,7 +300,7 @@ func (p *Plugin) handleList(w http.ResponseWriter, r *http.Request) { return } - if len(issues) > 0 && r.URL.Query().Get("reminder") == "true" && p.getReminderPreference(userID) { + if allListIssue != nil && len(allListIssue.My) > 0 && r.URL.Query().Get("reminder") == "true" && p.getReminderPreference(userID) { var lastReminderAt int64 lastReminderAt, err = p.getLastReminderTimeForUser(userID) if err != nil { @@ -329,7 +319,7 @@ func (p *Plugin) handleList(w http.ResponseWriter, r *http.Request) { nt := time.Unix(now/1000, 0).In(timezone) lt := time.Unix(lastReminderAt/1000, 0).In(timezone) if nt.Sub(lt).Hours() >= 1 && (nt.Day() != lt.Day() || nt.Month() != lt.Month() || nt.Year() != lt.Year()) { - p.PostBotDM(userID, "Daily Reminder:\n\n"+issuesListToString(issues)) + p.PostBotDM(userID, "Daily Reminder:\n\n"+issuesListToString(allListIssue.My)) p.trackDailySummary(userID) err = p.saveLastReminderTimeForUser(userID) if err != nil { @@ -338,31 +328,6 @@ func (p *Plugin) handleList(w http.ResponseWriter, r *http.Request) { } } - issuesJSON, err := json.Marshal(issues) - if err != nil { - msg := "Unable marhsal count issue list to json" - p.API.LogError(msg, "err", err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) - return - } - - _, err = w.Write(issuesJSON) - if err != nil { - p.API.LogError("Unable to write json response err=" + err.Error()) - } -} - -func (p *Plugin) handleLists(w http.ResponseWriter, r *http.Request) { - userID := r.Header.Get("Mattermost-User-ID") - - allListIssue, err := p.listManager.GetAllList(userID) - if err != nil { - msg := "Unable to get issues for user" - p.API.LogError(msg, "err", err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) - return - } - allListIssueJSON, err := json.Marshal(allListIssue) if err != nil { msg := "Unable marhsal all lists issues to json" diff --git a/webapp/src/action_types.js b/webapp/src/action_types.js index f7752e71..9ff64ecf 100644 --- a/webapp/src/action_types.js +++ b/webapp/src/action_types.js @@ -12,10 +12,6 @@ export const GET_ASSIGNEE = pluginId + '_get_assignee'; export const SET_EDITING_TODO = pluginId + '_set_editing_todo'; export const REMOVE_EDITING_TODO = pluginId + '_remove_editing_todo'; export const REMOVE_ASSIGNEE = pluginId + '_remove_assignee'; -export const GET_ISSUES = pluginId + '_get_issues'; -export const GET_OUT_ISSUES = pluginId + '_get_out_issues'; -export const GET_IN_ISSUES = pluginId + '_get_in_issues'; -export const GET_COUNT_ISSUES = pluginId + '_get_count_issues'; export const GET_ALL_ISSUES = pluginId + '_get_all_issues'; export const RECEIVED_SHOW_RHS_ACTION = pluginId + '_show_rhs'; export const UPDATE_RHS_STATE = pluginId + '_update_rhs_state'; diff --git a/webapp/src/actions.js b/webapp/src/actions.js index 479a135e..80843d38 100644 --- a/webapp/src/actions.js +++ b/webapp/src/actions.js @@ -8,9 +8,6 @@ import { OPEN_TODO_TOAST, CLOSE_TODO_TOAST, RECEIVED_SHOW_RHS_ACTION, - GET_ISSUES, - GET_IN_ISSUES, - GET_OUT_ISSUES, UPDATE_RHS_STATE, SET_RHS_VISIBLE, SET_HIDE_TEAM_SIDEBAR_BUTTONS, @@ -142,43 +139,10 @@ export const changeAssignee = (id, assignee) => async (dispatch, getState) => { })); }; -export const list = (reminder = false, listName = 'my') => async (dispatch, getState) => { - let resp; +export const fetchAllIssueLists = (reminder = false) => async (dispatch, getState) => { let data; try { - resp = await fetch(getPluginServerRoute(getState()) + '/list?reminder=' + reminder + '&list=' + listName, Client4.getOptions({ - method: 'get', - })); - data = await resp.json(); - } catch (error) { - return {error}; - } - - let actionType = GET_ISSUES; - switch (listName) { - case 'my': - actionType = GET_ISSUES; - break; - case 'in': - actionType = GET_IN_ISSUES; - break; - case 'out': - actionType = GET_OUT_ISSUES; - break; - } - - dispatch({ - type: actionType, - data, - }); - - return {data}; -}; - -export const fetchAllIssue = () => async (dispatch, getState) => { - let data; - try { - const resp = await fetch(getPluginServerRoute(getState()) + '/lists', Client4.getOptions({ + const resp = await fetch(getPluginServerRoute(getState()) + '/lists?reminder=' + reminder, Client4.getOptions({ method: 'get', })); data = await resp.json(); diff --git a/webapp/src/components/post_type_todo/index.js b/webapp/src/components/post_type_todo/index.js index 1cbb7fc9..518b3120 100644 --- a/webapp/src/components/post_type_todo/index.js +++ b/webapp/src/components/post_type_todo/index.js @@ -5,7 +5,7 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; import {remove, complete, accept, telemetry} from '../../actions'; -import {getSiteURL} from '../../selectors'; +import {getInIssues, getSiteURL} from '../../selectors'; import PostTypeTodo from './post_type_todo'; @@ -13,7 +13,7 @@ function mapStateToProps(state, ownProps) { return { ...ownProps, siteURL: getSiteURL(state), - pendingAnswer: state['plugins-com.mattermost.plugin-todo'].inIssues.some((issue) => issue.id === ownProps.post.props.issueId), + pendingAnswer: getInIssues(state).some((issue) => issue.id === ownProps.post.props.issueId), }; } diff --git a/webapp/src/components/sidebar_buttons/index.js b/webapp/src/components/sidebar_buttons/index.js index d5a5973c..b0004ec5 100644 --- a/webapp/src/components/sidebar_buttons/index.js +++ b/webapp/src/components/sidebar_buttons/index.js @@ -4,13 +4,17 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {fetchAllIssue, updateRhsState, telemetry} from '../../actions'; +import {fetchAllIssueLists, updateRhsState, telemetry} from '../../actions'; + +import {getIssues, getInIssues, getOutIssues} from '../../selectors'; import SidebarButtons from './sidebar_buttons.jsx'; function mapStateToProps(state) { return { - allIssues: state['plugins-com.mattermost.plugin-todo'].allIssues, + myIssues: getIssues(state), + inIssues: getInIssues(state), + outIssues: getOutIssues(state), showRHSPlugin: state['plugins-com.mattermost.plugin-todo'].rhsPluginAction, }; } @@ -18,7 +22,7 @@ function mapStateToProps(state) { function mapDispatchToProps(dispatch) { return { actions: bindActionCreators({ - fetchAllIssue, + fetchAllIssueLists, updateRhsState, telemetry, }, dispatch), diff --git a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx index 8a79dc05..6312937e 100644 --- a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx +++ b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx @@ -13,7 +13,9 @@ export default class SidebarButtons extends React.PureComponent { theme: PropTypes.object.isRequired, isTeamSidebar: PropTypes.bool, showRHSPlugin: PropTypes.func.isRequired, - allIssues: PropTypes.object, + myIssues: PropTypes.array, + inIssues: PropTypes.array, + outIssues: PropTypes.array, actions: PropTypes.shape({ updateRhsState: PropTypes.func.isRequired, telemetry: PropTypes.func.isRequired, @@ -46,7 +48,9 @@ export default class SidebarButtons extends React.PureComponent { container = style.containerTeam; } - const allIssues = this.props.allIssues; + const myIssues = this.props.myIssues; + const inIssues = this.props.inIssues; + const outIssues = this.props.outIssues; return (
@@ -63,7 +67,7 @@ export default class SidebarButtons extends React.PureComponent { }} > - {' ' + allIssues && allIssues.my ? allIssues.my.length : 0} + {' ' + myIssues ? myIssues.length : 0} - {' ' + allIssues && allIssues.in ? allIssues.in.length : 0} + {' ' + inIssues ? inIssues.length : 0} - {' ' + allIssues && allIssues.out ? allIssues.out.length : 0} + {' ' + outIssues ? outIssues.length : 0}
diff --git a/webapp/src/components/sidebar_right/index.js b/webapp/src/components/sidebar_right/index.js index 27c12e01..56d80d07 100644 --- a/webapp/src/components/sidebar_right/index.js +++ b/webapp/src/components/sidebar_right/index.js @@ -4,14 +4,16 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {getSiteURL, getTodoToast} from '../../selectors'; -import {remove, fetchAllIssue, openAssigneeModal, openAddCard, closeAddCard, complete, bump, accept, telemetry, setRhsVisible} from '../../actions'; +import {getSiteURL, getTodoToast, getIssues, getInIssues, getOutIssues} from '../../selectors'; +import {remove, fetchAllIssueLists, openAssigneeModal, openAddCard, closeAddCard, complete, bump, accept, telemetry, setRhsVisible} from '../../actions'; import SidebarRight from './sidebar_right.jsx'; function mapStateToProps(state) { return { - allIssues: state['plugins-com.mattermost.plugin-todo'].allIssues, + myIssues: getIssues(state), + inIssues: getInIssues(state), + outIssues: getOutIssues(state), todoToast: getTodoToast(state), siteURL: getSiteURL(state), rhsState: state['plugins-com.mattermost.plugin-todo'].rhsState, @@ -25,7 +27,7 @@ function mapDispatchToProps(dispatch) { complete, accept, bump, - fetchAllIssue, + fetchAllIssueLists, openAddCard, closeAddCard, openAssigneeModal, diff --git a/webapp/src/components/sidebar_right/sidebar_right.jsx b/webapp/src/components/sidebar_right/sidebar_right.jsx index fba90a45..4f49868e 100644 --- a/webapp/src/components/sidebar_right/sidebar_right.jsx +++ b/webapp/src/components/sidebar_right/sidebar_right.jsx @@ -51,7 +51,9 @@ const InListName = 'in'; export default class SidebarRight extends React.PureComponent { static propTypes = { - allIssues: PropTypes.arrayOf(PropTypes.object), + myIssues: PropTypes.array, + inIssues: PropTypes.array, + outIssues: PropTypes.array, todoToast: PropTypes.object, theme: PropTypes.object.isRequired, siteURL: PropTypes.string.isRequired, @@ -61,7 +63,7 @@ export default class SidebarRight extends React.PureComponent { complete: PropTypes.func.isRequired, accept: PropTypes.func.isRequired, bump: PropTypes.func.isRequired, - fetchAllIssue: PropTypes.func.isRequired, + fetchAllIssueLists: PropTypes.func.isRequired, openAddCard: PropTypes.func.isRequired, closeAddCard: PropTypes.func.isRequired, openAssigneeModal: PropTypes.func.isRequired, @@ -99,7 +101,7 @@ export default class SidebarRight extends React.PureComponent { componentDidMount() { document.addEventListener('keydown', this.handleKeypress); - this.props.actions.fetchAllIssue(); + this.props.actions.fetchAllIssueLists(); this.props.actions.setVisible(true); } @@ -122,15 +124,15 @@ export default class SidebarRight extends React.PureComponent { } getInIssues() { - return this.props.allIssues.in.length; + return this.props.inIssues.length; } getOutIssues() { - return this.props.allIssues.out.length; + return this.props.outIssues.length; } getMyIssues() { - return this.props.allIssues.my.length; + return this.props.myIssues.length; } addTodoItem() { @@ -150,12 +152,12 @@ export default class SidebarRight extends React.PureComponent { switch (this.state.list) { case MyListName: - todos = this.props.allIssues.my || []; + todos = this.props.myIssues || []; addButton = 'Add Todo'; - inboxList = this.props.allIssues.in || []; + inboxList = this.props.inIssues || []; break; case OutListName: - todos = this.props.allIssues.out || []; + todos = this.props.outIssues || []; listHeading = 'Sent Todos'; addButton = 'Request a Todo from someone'; break; diff --git a/webapp/src/index.js b/webapp/src/index.js index a4996f42..b32c1bf3 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -6,7 +6,7 @@ import Root from './components/root'; import AssigneeModal from './components/assignee_modal'; import SidebarRight from './components/sidebar_right'; -import {openAddCard, list, setShowRHSAction, telemetry, updateConfig, setHideTeamSidebar, fetchAllIssue} from './actions'; +import {openAddCard, setShowRHSAction, telemetry, updateConfig, setHideTeamSidebar, fetchAllIssueLists} from './actions'; import reducer from './reducer'; import PostTypeTodo from './components/post_type_todo'; import TeamSidebar from './components/team_sidebar'; @@ -47,30 +47,11 @@ export default class Plugin { 'Open your list of Todo issues', ); - const getFrontendListName = (backendListName) => { - let frontendListName = 'my'; - switch (backendListName) { - case '': - frontendListName = 'my'; - break; - case '_in': - frontendListName = 'in'; - break; - case '_out': - frontendListName = 'out'; - break; - default: - frontendListName = 'my'; - break; - } - return frontendListName; - }; - const refresh = () => { - store.dispatch(fetchAllIssue()); + store.dispatch(fetchAllIssueLists()); }; const refreshAll = () => { - store.dispatch(fetchAllIssue()); + store.dispatch(fetchAllIssueLists()); }; const iconURL = getPluginServerRoute(store.getState()) + '/public/app-bar-icon.png'; @@ -83,7 +64,7 @@ export default class Plugin { registry.registerWebSocketEventHandler(`custom_${pluginId}_refresh`, refresh); registry.registerReconnectHandler(refreshAll); - store.dispatch(fetchAllIssue()); + store.dispatch(fetchAllIssueLists(true)); // register websocket event to track config changes const configUpdate = ({data}) => { @@ -97,7 +78,7 @@ export default class Plugin { activityFunc = () => { const now = new Date().getTime(); if (now - lastActivityTime > activityTimeout) { - store.dispatch(list(true)); + store.dispatch(fetchAllIssueLists(true)); } lastActivityTime = now; }; diff --git a/webapp/src/reducer.js b/webapp/src/reducer.js index 589c2ae1..259d6820 100644 --- a/webapp/src/reducer.js +++ b/webapp/src/reducer.js @@ -9,12 +9,9 @@ import { CLOSE_TODO_TOAST, OPEN_ADD_CARD, CLOSE_ADD_CARD, - GET_ISSUES, SET_EDITING_TODO, REMOVE_EDITING_TODO, GET_ALL_ISSUES, - GET_IN_ISSUES, - GET_OUT_ISSUES, RECEIVED_SHOW_RHS_ACTION, UPDATE_RHS_STATE, SET_RHS_VISIBLE, @@ -87,37 +84,10 @@ const postID = (state = '', action) => { } }; -const issues = (state = [], action) => { - switch (action.type) { - case GET_ISSUES: - return action.data; - default: - return state; - } -}; - -const inIssues = (state = [], action) => { - switch (action.type) { - case GET_IN_ISSUES: - return action.data; - default: - return state; - } -}; - -const outIssues = (state = [], action) => { - switch (action.type) { - case GET_OUT_ISSUES: - return action.data; - default: - return state; - } -}; - -const allIssues = (state = {}, action) => { +const allIssues = (state = {my: [], in: [], out: []}, action) => { switch (action.type) { case GET_ALL_ISSUES: - return action.data; + return action.data ?? state; default: return state; } @@ -166,9 +136,6 @@ export default combineReducers({ todoToast, editingTodo, postID, - issues, - inIssues, - outIssues, allIssues, rhsState, rhsPluginAction, diff --git a/webapp/src/selectors.js b/webapp/src/selectors.js index e3c23303..3f4bd26f 100644 --- a/webapp/src/selectors.js +++ b/webapp/src/selectors.js @@ -24,9 +24,9 @@ export const getMessage = (state) => { } return post.message; }; -export const getIssues = (state) => getPluginState(state).issues; -export const getInIssues = (state) => getPluginState(state).inIssues; -export const getOutIssues = (state) => getPluginState(state).outIssues; +export const getIssues = (state) => getAllIssues(state).my; +export const getInIssues = (state) => getAllIssues(state).in; +export const getOutIssues = (state) => getAllIssues(state).out; export const getAllIssues = (state) => getPluginState(state).allIssues; export const getCurrentTeamRoute = (state) => { const basePath = getSiteURL(state); From 2d27842ba4368f729a0ef71f496c168f02629345 Mon Sep 17 00:00:00 2001 From: Julien Fabre Date: Wed, 8 Nov 2023 00:55:06 +0100 Subject: [PATCH 7/8] fix: remove useless refreshAll --- webapp/src/index.js | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/webapp/src/index.js b/webapp/src/index.js index b32c1bf3..b2bbfa09 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -47,13 +47,6 @@ export default class Plugin { 'Open your list of Todo issues', ); - const refresh = () => { - store.dispatch(fetchAllIssueLists()); - }; - const refreshAll = () => { - store.dispatch(fetchAllIssueLists()); - }; - const iconURL = getPluginServerRoute(store.getState()) + '/public/app-bar-icon.png'; registry.registerAppBarComponent( iconURL, @@ -61,8 +54,11 @@ export default class Plugin { 'Open your list of Todo issues', ); + const refresh = () => { + store.dispatch(fetchAllIssueLists()); + }; registry.registerWebSocketEventHandler(`custom_${pluginId}_refresh`, refresh); - registry.registerReconnectHandler(refreshAll); + registry.registerReconnectHandler(refresh); store.dispatch(fetchAllIssueLists(true)); From 99b959cc3f1debc42df265e3b37982f245b29c3d Mon Sep 17 00:00:00 2001 From: Julien Fabre Date: Thu, 9 Nov 2023 23:51:31 +0100 Subject: [PATCH 8/8] fix: new review --- server/plugin.go | 20 ++++++++-------- .../src/components/sidebar_buttons/index.js | 4 ++-- .../sidebar_buttons/sidebar_buttons.jsx | 12 +++++----- webapp/src/components/sidebar_right/index.js | 4 ++-- .../sidebar_right/sidebar_right.jsx | 24 +++++-------------- webapp/src/selectors.js | 2 +- 6 files changed, 27 insertions(+), 39 deletions(-) diff --git a/server/plugin.go b/server/plugin.go index f9d9b4cb..1c2c089b 100644 --- a/server/plugin.go +++ b/server/plugin.go @@ -22,6 +22,8 @@ const ( // WSEventConfigUpdate is the WebSocket event to update the Todo list's configurations on webapp WSEventConfigUpdate = "config_update" + + ErrorMsgAddIssue = "Unable to add issue" ) // ListManager represents the logic on the lists @@ -207,9 +209,8 @@ func (p *Plugin) handleAdd(w http.ResponseWriter, r *http.Request) { if addRequest.SendTo == "" { _, err = p.listManager.AddIssue(userID, addRequest.Message, addRequest.Description, addRequest.PostID) if err != nil { - msg := "Unable to add issue" - p.API.LogError(msg, "err", err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) + p.API.LogError(ErrorMsgAddIssue, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, ErrorMsgAddIssue, err) return } @@ -226,17 +227,16 @@ func (p *Plugin) handleAdd(w http.ResponseWriter, r *http.Request) { receiver, appErr := p.API.GetUserByUsername(addRequest.SendTo) if appErr != nil { msg := "Unable to find user" - p.API.LogError(msg, "err", err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) + p.API.LogError(msg, "err", appErr.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, msg, appErr) return } if receiver.Id == userID { _, err = p.listManager.AddIssue(userID, addRequest.Message, addRequest.Description, addRequest.PostID) if err != nil { - msg := "Unable to add issue" - p.API.LogError(msg, "err", err.Error()) - p.handleErrorWithCode(w, http.StatusInternalServerError, msg, err) + p.API.LogError(ErrorMsgAddIssue, "err", err.Error()) + p.handleErrorWithCode(w, http.StatusInternalServerError, ErrorMsgAddIssue, err) return } @@ -403,8 +403,8 @@ func (p *Plugin) handleChangeAssignment(w http.ResponseWriter, r *http.Request) receiver, appErr := p.API.GetUserByUsername(changeRequest.SendTo) if appErr != nil { msg := "username not valid" - p.API.LogError(msg, "err", err.Error()) - p.handleErrorWithCode(w, http.StatusNotFound, msg, err) + p.API.LogError(msg, "err", appErr.Error()) + p.handleErrorWithCode(w, http.StatusNotFound, msg, appErr) return } diff --git a/webapp/src/components/sidebar_buttons/index.js b/webapp/src/components/sidebar_buttons/index.js index b0004ec5..0fbd3bb4 100644 --- a/webapp/src/components/sidebar_buttons/index.js +++ b/webapp/src/components/sidebar_buttons/index.js @@ -6,13 +6,13 @@ import {bindActionCreators} from 'redux'; import {fetchAllIssueLists, updateRhsState, telemetry} from '../../actions'; -import {getIssues, getInIssues, getOutIssues} from '../../selectors'; +import {getMyIssues, getInIssues, getOutIssues} from '../../selectors'; import SidebarButtons from './sidebar_buttons.jsx'; function mapStateToProps(state) { return { - myIssues: getIssues(state), + myIssues: getMyIssues(state), inIssues: getInIssues(state), outIssues: getOutIssues(state), showRHSPlugin: state['plugins-com.mattermost.plugin-todo'].rhsPluginAction, diff --git a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx index 6312937e..6dc5fc38 100644 --- a/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx +++ b/webapp/src/components/sidebar_buttons/sidebar_buttons.jsx @@ -13,9 +13,9 @@ export default class SidebarButtons extends React.PureComponent { theme: PropTypes.object.isRequired, isTeamSidebar: PropTypes.bool, showRHSPlugin: PropTypes.func.isRequired, - myIssues: PropTypes.array, - inIssues: PropTypes.array, - outIssues: PropTypes.array, + myIssues: PropTypes.array.isRequired, + inIssues: PropTypes.array.isRequired, + outIssues: PropTypes.array.isRequired, actions: PropTypes.shape({ updateRhsState: PropTypes.func.isRequired, telemetry: PropTypes.func.isRequired, @@ -67,7 +67,7 @@ export default class SidebarButtons extends React.PureComponent { }} > - {' ' + myIssues ? myIssues.length : 0} + {' ' + myIssues.length } - {' ' + inIssues ? inIssues.length : 0} + {' ' + inIssues.length } - {' ' + outIssues ? outIssues.length : 0} + {' ' + outIssues.length } diff --git a/webapp/src/components/sidebar_right/index.js b/webapp/src/components/sidebar_right/index.js index 56d80d07..568d43ee 100644 --- a/webapp/src/components/sidebar_right/index.js +++ b/webapp/src/components/sidebar_right/index.js @@ -4,14 +4,14 @@ import {connect} from 'react-redux'; import {bindActionCreators} from 'redux'; -import {getSiteURL, getTodoToast, getIssues, getInIssues, getOutIssues} from '../../selectors'; +import {getSiteURL, getTodoToast, getMyIssues, getInIssues, getOutIssues} from '../../selectors'; import {remove, fetchAllIssueLists, openAssigneeModal, openAddCard, closeAddCard, complete, bump, accept, telemetry, setRhsVisible} from '../../actions'; import SidebarRight from './sidebar_right.jsx'; function mapStateToProps(state) { return { - myIssues: getIssues(state), + myIssues: getMyIssues(state), inIssues: getInIssues(state), outIssues: getOutIssues(state), todoToast: getTodoToast(state), diff --git a/webapp/src/components/sidebar_right/sidebar_right.jsx b/webapp/src/components/sidebar_right/sidebar_right.jsx index 4f49868e..6eda2d25 100644 --- a/webapp/src/components/sidebar_right/sidebar_right.jsx +++ b/webapp/src/components/sidebar_right/sidebar_right.jsx @@ -51,9 +51,9 @@ const InListName = 'in'; export default class SidebarRight extends React.PureComponent { static propTypes = { - myIssues: PropTypes.array, - inIssues: PropTypes.array, - outIssues: PropTypes.array, + myIssues: PropTypes.array.isRequired, + inIssues: PropTypes.array.isRequired, + outIssues: PropTypes.array.isRequired, todoToast: PropTypes.object, theme: PropTypes.object.isRequired, siteURL: PropTypes.string.isRequired, @@ -123,18 +123,6 @@ export default class SidebarRight extends React.PureComponent { } } - getInIssues() { - return this.props.inIssues.length; - } - - getOutIssues() { - return this.props.outIssues.length; - } - - getMyIssues() { - return this.props.myIssues.length; - } - addTodoItem() { this.props.actions.openAddCard(''); } @@ -152,12 +140,12 @@ export default class SidebarRight extends React.PureComponent { switch (this.state.list) { case MyListName: - todos = this.props.myIssues || []; + todos = this.props.myIssues; addButton = 'Add Todo'; - inboxList = this.props.inIssues || []; + inboxList = this.props.inIssues; break; case OutListName: - todos = this.props.outIssues || []; + todos = this.props.outIssues; listHeading = 'Sent Todos'; addButton = 'Request a Todo from someone'; break; diff --git a/webapp/src/selectors.js b/webapp/src/selectors.js index 3f4bd26f..19f9df7d 100644 --- a/webapp/src/selectors.js +++ b/webapp/src/selectors.js @@ -24,7 +24,7 @@ export const getMessage = (state) => { } return post.message; }; -export const getIssues = (state) => getAllIssues(state).my; +export const getMyIssues = (state) => getAllIssues(state).my; export const getInIssues = (state) => getAllIssues(state).in; export const getOutIssues = (state) => getAllIssues(state).out; export const getAllIssues = (state) => getPluginState(state).allIssues;