From 9fe8fb4169bb670fa06c118d9f54ca52be80da5e Mon Sep 17 00:00:00 2001 From: Michael P Date: Tue, 18 Feb 2025 16:31:19 -0500 Subject: [PATCH] Feature: support Todo Sidebar Buttons both in Team Sidebar and Sidebar Header, when applicable --- .gitignore | 1 + plugin.json | 8 +++--- server/configuration.go | 4 +-- server/plugin.go | 6 ++-- webapp/src/action_types.js | 2 +- webapp/src/actions.js | 8 +++--- webapp/src/components/sidebar_header/index.js | 18 ++++++++++++ .../sidebar_header/sidebar_header.jsx | 28 +++++++++++++++++++ webapp/src/components/team_sidebar/index.js | 4 +-- webapp/src/index.js | 7 +++-- webapp/src/reducer.js | 8 +++--- webapp/src/selectors.js | 2 +- 12 files changed, 72 insertions(+), 24 deletions(-) create mode 100644 webapp/src/components/sidebar_header/index.js create mode 100644 webapp/src/components/sidebar_header/sidebar_header.jsx diff --git a/.gitignore b/.gitignore index 9475c727..039bc140 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ dist .DS_Store webapp/src/manifest.ts server/manifest.go +bin \ No newline at end of file diff --git a/plugin.json b/plugin.json index 7a9c5101..45c6e721 100644 --- a/plugin.json +++ b/plugin.json @@ -22,13 +22,13 @@ "footer": "", "settings": [ { - "key": "hide_team_sidebar", - "display_name": "Hide team sidebar buttons:", + "key": "hide_sidebar_buttons", + "display_name": "Hide sidebar buttons:", "type": "bool", - "help_text": "When true, the buttons in the team sidebar on the left toolbar will be hidden.", + "help_text": "When true, the buttons in the sidebar header (or team sidebar when applicable) will be hidden.", "placeholder": "", "default": null } ] } -} +} \ No newline at end of file diff --git a/server/configuration.go b/server/configuration.go index bef4d2f8..aecb9446 100644 --- a/server/configuration.go +++ b/server/configuration.go @@ -20,7 +20,7 @@ import ( // If you add non-reference types to your configuration struct, be sure to rewrite Clone as a deep // copy appropriate for your types. type configuration struct { - HideTeamSidebar bool `json:"hide_team_sidebar"` + HideSidebarButtons bool `json:"hide_sidebar_buttons"` } // Clone shallow copies the configuration. Your implementation may require a deep copy if @@ -77,7 +77,7 @@ func (p *Plugin) setConfiguration(configuration *configuration) { // Check whether client configuration are different func (p *Plugin) hasClientConfigChanged(prev *configuration, current *configuration) bool { - return prev == nil || prev.HideTeamSidebar != current.HideTeamSidebar + return prev == nil || prev.HideSidebarButtons != current.HideSidebarButtons } // OnConfigurationChange is invoked when configuration changes may have been made. diff --git a/server/plugin.go b/server/plugin.go index aa986f2d..ad873ac6 100644 --- a/server/plugin.go +++ b/server/plugin.go @@ -618,9 +618,9 @@ func (p *Plugin) handleConfig(w http.ResponseWriter, r *http.Request) { if p.configuration != nil { // retrieve client only configurations clientConfig := struct { - HideTeamSidebar bool `json:"hide_team_sidebar"` + HideSidebarButtons bool `json:"hide_team_sidebar"` }{ - HideTeamSidebar: p.configuration.HideTeamSidebar, + HideSidebarButtons: p.configuration.HideSidebarButtons, } configJSON, err := json.Marshal(clientConfig) @@ -649,7 +649,7 @@ func (p *Plugin) sendRefreshEvent(userID string, lists []string) { // Publish a WebSocket event to update the client config of the plugin on the webapp end. func (p *Plugin) sendConfigUpdateEvent() { clientConfigMap := map[string]interface{}{ - "hide_team_sidebar": p.configuration.HideTeamSidebar, + "hide_sidebar_buttons": p.configuration.HideSidebarButtons, } p.API.PublishWebSocketEvent( diff --git a/webapp/src/action_types.js b/webapp/src/action_types.js index a3fc6e8f..cf37d661 100644 --- a/webapp/src/action_types.js +++ b/webapp/src/action_types.js @@ -17,4 +17,4 @@ 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'; -export const SET_HIDE_TEAM_SIDEBAR_BUTTONS = pluginId + '_set_hide_team_sidebar'; +export const SET_HIDE_SIDEBAR_BUTTONS = pluginId + '_set_hide_sidebar_buttons'; diff --git a/webapp/src/actions.js b/webapp/src/actions.js index 2fe99a0a..94f17c9f 100644 --- a/webapp/src/actions.js +++ b/webapp/src/actions.js @@ -10,7 +10,7 @@ import { RECEIVED_SHOW_RHS_ACTION, UPDATE_RHS_STATE, SET_RHS_VISIBLE, - SET_HIDE_TEAM_SIDEBAR_BUTTONS, + SET_HIDE_SIDEBAR_BUTTONS, GET_ASSIGNEE, REMOVE_ASSIGNEE, OPEN_ADD_CARD, @@ -194,9 +194,9 @@ export function autocompleteUsers(username) { }; } -export function setHideTeamSidebar(payload) { +export function setHideSidebarButtons(payload) { return { - type: SET_HIDE_TEAM_SIDEBAR_BUTTONS, + type: SET_HIDE_SIDEBAR_BUTTONS, payload, }; } @@ -212,7 +212,7 @@ export const updateConfig = () => async (dispatch, getState) => { return {error}; } - dispatch(setHideTeamSidebar(data.hide_team_sidebar)); + dispatch(setHideSidebarButtons(data.hide_sidebar_buttons)); return {data}; }; diff --git a/webapp/src/components/sidebar_header/index.js b/webapp/src/components/sidebar_header/index.js new file mode 100644 index 00000000..d33040e4 --- /dev/null +++ b/webapp/src/components/sidebar_header/index.js @@ -0,0 +1,18 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import {connect} from 'react-redux'; + +import {isButtonSidebarVisible} from 'selectors'; + +import SidebarHeader from './sidebar_header.jsx'; + +function mapStateToProps(state) { + const members = state.entities.teams.myMembers || {}; + return { + show: Object.keys(members).length > 1, + visible: isButtonSidebarVisible(state), + }; +} + +export default connect(mapStateToProps)(SidebarHeader); diff --git a/webapp/src/components/sidebar_header/sidebar_header.jsx b/webapp/src/components/sidebar_header/sidebar_header.jsx new file mode 100644 index 00000000..9c7f4312 --- /dev/null +++ b/webapp/src/components/sidebar_header/sidebar_header.jsx @@ -0,0 +1,28 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +import React from 'react'; +import PropTypes from 'prop-types'; + +import SidebarButtons from '../sidebar_buttons'; + +export default class SidebarHeader extends React.PureComponent { + static propTypes = { + show: PropTypes.bool.isRequired, + theme: PropTypes.object.isRequired, + visible: PropTypes.bool.isRequired, + }; + + render() { + if (this.props.show || !this.props.visible) { + return null; + } + + return ( + + ); + } +} diff --git a/webapp/src/components/team_sidebar/index.js b/webapp/src/components/team_sidebar/index.js index 120e0582..3eb5f283 100644 --- a/webapp/src/components/team_sidebar/index.js +++ b/webapp/src/components/team_sidebar/index.js @@ -3,7 +3,7 @@ import {connect} from 'react-redux'; -import {isTeamSidebarVisible} from 'selectors'; +import {isButtonSidebarVisible} from 'selectors'; import TeamSidebar from './team_sidebar.jsx'; @@ -11,7 +11,7 @@ function mapStateToProps(state) { const members = state.entities.teams.myMembers || {}; return { show: Object.keys(members).length > 1, - visible: isTeamSidebarVisible(state), + visible: isButtonSidebarVisible(state), }; } diff --git a/webapp/src/index.js b/webapp/src/index.js index 2593d500..4649510a 100644 --- a/webapp/src/index.js +++ b/webapp/src/index.js @@ -6,9 +6,10 @@ import Root from './components/root'; import AssigneeModal from './components/assignee_modal'; import SidebarRight from './components/sidebar_right'; -import {openAddCard, setShowRHSAction, telemetry, updateConfig, setHideTeamSidebar, fetchAllIssueLists} from './actions'; +import {openAddCard, setShowRHSAction, telemetry, updateConfig, setHideSidebarButtons, fetchAllIssueLists} from './actions'; import reducer from './reducer'; import PostTypeTodo from './components/post_type_todo'; +import SidebarHeader from './components/sidebar_header'; import TeamSidebar from './components/team_sidebar'; import ChannelHeaderButton from './components/channel_header_button'; import {getPluginServerRoute} from './selectors'; @@ -25,7 +26,7 @@ export default class Plugin { registry.registerReducer(reducer); registry.registerRootComponent(Root); registry.registerRootComponent(AssigneeModal); - + registry.registerLeftSidebarHeaderComponent(SidebarHeader); registry.registerBottomTeamSidebarComponent(TeamSidebar); registry.registerPostDropdownMenuAction( @@ -65,7 +66,7 @@ export default class Plugin { // register websocket event to track config changes const configUpdate = ({data}) => { - store.dispatch(setHideTeamSidebar(data.hide_team_sidebar)); + store.dispatch(setHideSidebarButtons(data.hide_sidebar_buttons)); }; registry.registerWebSocketEventHandler(`custom_${pluginId}_config_update`, configUpdate); diff --git a/webapp/src/reducer.js b/webapp/src/reducer.js index 259d6820..492fd7f0 100644 --- a/webapp/src/reducer.js +++ b/webapp/src/reducer.js @@ -15,7 +15,7 @@ import { RECEIVED_SHOW_RHS_ACTION, UPDATE_RHS_STATE, SET_RHS_VISIBLE, - SET_HIDE_TEAM_SIDEBAR_BUTTONS, + SET_HIDE_SIDEBAR_BUTTONS, } from './action_types'; const addCardVisible = (state = false, action) => { @@ -120,9 +120,9 @@ function isRhsVisible(state = false, action) { } } -function isTeamSidebarHidden(state = false, action) { +function isButtonSidebarHidden(state = false, action) { switch (action.type) { - case SET_HIDE_TEAM_SIDEBAR_BUTTONS: + case SET_HIDE_SIDEBAR_BUTTONS: return action.payload; default: return state; @@ -140,5 +140,5 @@ export default combineReducers({ rhsState, rhsPluginAction, isRhsVisible, - isTeamSidebarHidden, + isButtonSidebarHidden, }); diff --git a/webapp/src/selectors.js b/webapp/src/selectors.js index cba00e8b..5fe892c9 100644 --- a/webapp/src/selectors.js +++ b/webapp/src/selectors.js @@ -58,4 +58,4 @@ export const getPluginServerRoute = (state) => { }; export const isRhsVisible = (state) => getPluginState(state).isRhsVisible; -export const isTeamSidebarVisible = (state) => !getPluginState(state).isTeamSidebarHidden; +export const isButtonSidebarVisible = (state) => !getPluginState(state).isButtonSidebarHidden;