diff --git a/plugin.json b/plugin.json index 539a1a67c..8c3c5eec5 100644 --- a/plugin.json +++ b/plugin.json @@ -171,6 +171,12 @@ "value": "UserPrincipalName" } ] + },{ + "key": "enableRhs", + "display_name": "Enable RHS", + "type": "bool", + "help_text": "When true, user will be able to view RHS (right hand sidebar).", + "default": false },{ "key": "appManifestDownload", "display_name": "Download Manifest", diff --git a/server/api.go b/server/api.go index 1876bd1b9..c34bafdf7 100644 --- a/server/api.go +++ b/server/api.go @@ -95,7 +95,7 @@ func NewAPI(p *Plugin, store store.Store) *API { router.HandleFunc("/oauth-redirect", api.oauthRedirectHandler).Methods(http.MethodGet) router.HandleFunc("/connected-users", api.getConnectedUsers).Methods(http.MethodGet) router.HandleFunc("/connected-users/download", api.getConnectedUsersFile).Methods(http.MethodGet) - router.HandleFunc("/whitelist-user", api.handleAuthRequired(api.whitelistUser)).Methods(http.MethodGet) + router.HandleFunc("/rhs-enabled", api.handleAuthRequired(api.rhsEnabled)).Methods(http.MethodGet) channelsRouter.HandleFunc("/link", api.handleAuthRequired(api.checkUserConnected(api.linkChannels))).Methods(http.MethodPost) channelsRouter.HandleFunc(fmt.Sprintf("/{%s}/unlink", PathParamChannelID), api.handleAuthRequired(api.unlinkChannels)).Methods(http.MethodDelete) @@ -892,17 +892,9 @@ func (a *API) getConnectedUsersFile(w http.ResponseWriter, r *http.Request) { } } -func (a *API) whitelistUser(w http.ResponseWriter, r *http.Request) { - userID := r.Header.Get(HeaderMattermostUserID) - presentInWhitelist, err := a.p.store.IsUserPresentInWhitelist(userID) - if err != nil { - a.p.API.LogError("Error in checking if a user is present in whitelist", "UserID", userID, "Error", err.Error()) - http.Error(w, "error in checking if a user is present in whitelist", http.StatusInternalServerError) - return - } - +func (a *API) rhsEnabled(w http.ResponseWriter, r *http.Request) { response := map[string]bool{ - "presentInWhitelist": presentInWhitelist, + "rhsEnabled": a.p.getConfiguration().EnableRHS, } w.Header().Set("Content-Type", "application/json") diff --git a/server/api_test.go b/server/api_test.go index e1d800698..5d55a95c8 100644 --- a/server/api_test.go +++ b/server/api_test.go @@ -1813,64 +1813,36 @@ func TestUnlinkChannels(t *testing.T) { } } -func TestWhitelistUser(t *testing.T) { +func TestRhsEnabled(t *testing.T) { for _, test := range []struct { Name string - SetupPlugin func(*plugintest.API) - SetupStore func(*storemocks.Store) - SetupMetrics func(*metricsmocks.Metrics) + SetupPlugin func(*Plugin) ExpectedResult string ExpectedStatusCode int }{ { - Name: "WhitelistUser: unable to check user in the whitelist", - SetupPlugin: func(api *plugintest.API) { - api.On("LogError", "Error in checking if a user is present in whitelist", "UserID", testutils.GetUserID(), "Error", "unable to check user in the whitelist").Times(1) - }, - SetupStore: func(store *storemocks.Store) { - store.On("IsUserPresentInWhitelist", testutils.GetUserID()).Return(false, errors.New("unable to check user in the whitelist")).Times(1) - }, - SetupMetrics: func(mockmetrics *metricsmocks.Metrics) { - mockmetrics.On("IncrementHTTPErrors").Times(1) + Name: "RhsEnabled: rhs is enabled", + SetupPlugin: func(p *Plugin) { + p.configuration.EnableRHS = true }, - ExpectedResult: "error in checking if a user is present in whitelist\n", - ExpectedStatusCode: http.StatusInternalServerError, - }, - { - Name: "WhitelistUser: user is not present in whitelist", - SetupPlugin: func(api *plugintest.API) {}, - SetupStore: func(store *storemocks.Store) { - store.On("IsUserPresentInWhitelist", testutils.GetUserID()).Return(false, nil).Times(1) - }, - SetupMetrics: func(mockmetrics *metricsmocks.Metrics) {}, - ExpectedResult: `{"presentInWhitelist":false}`, + ExpectedResult: `{"rhsEnabled":true}`, ExpectedStatusCode: http.StatusOK, }, { - Name: "WhitelistUser: user present in whitelist", - SetupPlugin: func(api *plugintest.API) {}, - SetupStore: func(store *storemocks.Store) { - store.On("IsUserPresentInWhitelist", testutils.GetUserID()).Return(true, nil).Times(1) - }, - SetupMetrics: func(mockmetrics *metricsmocks.Metrics) {}, - ExpectedResult: `{"presentInWhitelist":true}`, + Name: "RhsEnabled: rhs is not enabled", + SetupPlugin: func(p *Plugin) {}, + ExpectedResult: `{"rhsEnabled":false}`, ExpectedStatusCode: http.StatusOK, }, } { t.Run(test.Name, func(t *testing.T) { assert := assert.New(t) plugin := newTestPlugin(t) - mockAPI := &plugintest.API{} - plugin.SetAPI(mockAPI) - defer mockAPI.AssertExpectations(t) - - test.SetupPlugin(mockAPI) - test.SetupStore(plugin.store.(*storemocks.Store)) - test.SetupMetrics(plugin.metricsService.(*metricsmocks.Metrics)) + test.SetupPlugin(plugin) w := httptest.NewRecorder() - r := httptest.NewRequest(http.MethodGet, "/whitelist-user", nil) + r := httptest.NewRequest(http.MethodGet, "/rhs-enabled", nil) r.Header.Add(HeaderMattermostUserID, testutils.GetUserID()) plugin.ServeHTTP(nil, w, r) diff --git a/server/configuration.go b/server/configuration.go index 702775c51..1fb391bc2 100644 --- a/server/configuration.go +++ b/server/configuration.go @@ -41,6 +41,7 @@ type configuration struct { SyntheticUserAuthService string `json:"syntheticUserAuthService"` SyntheticUserAuthData string `json:"syntheticUserAuthData"` AutomaticallyPromoteSyntheticUsers bool `json:"automaticallyPromoteSyntheticUsers"` + EnableRHS bool `json:"enableRhs"` } func (c *configuration) ProcessConfiguration() { diff --git a/webapp/src/App.tsx b/webapp/src/App.tsx index 62a9523c0..12aa00b83 100644 --- a/webapp/src/App.tsx +++ b/webapp/src/App.tsx @@ -7,7 +7,7 @@ import {GlobalState} from 'mattermost-redux/types/store'; import {RhsTitle} from 'components'; import {pluginApiServiceConfigs} from 'constants/apiService.constant'; -import {defaultPage, defaultPerPage, pluginTitle} from 'constants/common.constants'; +import {defaultPage, defaultPerPage, pluginTitle, rhsButtonId} from 'constants/common.constants'; import {iconUrl} from 'constants/illustrations.constants'; import {Rhs} from 'containers'; @@ -28,11 +28,10 @@ import 'styles/main.scss'; const App = ({registry, store}:{registry: PluginRegistry, store: Store>>}): JSX.Element => { const dispatch = useDispatch(); const {makeApiRequestWithCompletionStatus, getApiState} = usePluginApi(); - useEffect(() => { const linkedChannelsParams: SearchLinkedChannelParams = {page: defaultPage, per_page: defaultPerPage}; - makeApiRequestWithCompletionStatus(pluginApiServiceConfigs.whitelistUser.apiServiceName); + makeApiRequestWithCompletionStatus(pluginApiServiceConfigs.rhsEnabled.apiServiceName); makeApiRequestWithCompletionStatus(pluginApiServiceConfigs.needsConnect.apiServiceName); makeApiRequestWithCompletionStatus(pluginApiServiceConfigs.getLinkedChannels.apiServiceName, linkedChannelsParams); }, []); @@ -43,7 +42,7 @@ const App = ({registry, store}:{registry: PluginRegistry, store: Store { - const {presentInWhitelist} = whitelistUserData as WhitelistUserResponse; + const {rhsEnabled} = rhsEnabledData as RhsEnabledResponse; + const rhsButtonData = localStorage.getItem(rhsButtonId); + if (rhsButtonData) { + const data = JSON.parse(rhsButtonData); + registry.unregisterComponent(data.headerId); + registry.unregisterComponent(data.appBarId); + localStorage.removeItem(rhsButtonId); + } - // Register the channel header button and app bar if the user is a whitelist user - if (presentInWhitelist) { + if (rhsEnabled) { + let appBarId; const {_, toggleRHSPlugin} = registry.registerRightHandSidebarComponent(Rhs, ); - registry.registerChannelHeaderButtonAction( + const headerId = registry.registerChannelHeaderButtonAction( , () => store.dispatch(toggleRHSPlugin), null, pluginTitle); if (registry.registerAppBarComponent) { - registry.registerAppBarComponent(iconUrl, () => store.dispatch(toggleRHSPlugin), pluginTitle); + appBarId = registry.registerAppBarComponent(iconUrl, () => store.dispatch(toggleRHSPlugin), pluginTitle); } + localStorage.setItem(rhsButtonId, JSON.stringify({ + headerId, + appBarId, + })); } }, }); diff --git a/webapp/src/components/LinkedChannelCard/LinkedChannelCard.component.tsx b/webapp/src/components/LinkedChannelCard/LinkedChannelCard.component.tsx index 5094c2661..1a2ae474c 100644 --- a/webapp/src/components/LinkedChannelCard/LinkedChannelCard.component.tsx +++ b/webapp/src/components/LinkedChannelCard/LinkedChannelCard.component.tsx @@ -7,21 +7,23 @@ import {LinkedChannelCardProps} from './LinkedChannelCard.types'; import './LinkedChannelCard.styles.scss'; export const LinkedChannelCard = ({msTeamsChannelName, msTeamsTeamName, mattermostChannelName, mattermostTeamName}: LinkedChannelCardProps) => ( -
-
- -
-
-
- {/* TODO: Update icon on basis of channel type */} - -
{mattermostChannelName}
-
{mattermostTeamName}
+
+
+
+
-
- -
{msTeamsChannelName}
-
{msTeamsTeamName}
+
+
+ {/* TODO: Update icon on basis of channel type */} + +
{mattermostChannelName}
+
{mattermostTeamName}
+
+
+ +
{msTeamsChannelName}
+
{msTeamsTeamName}
+
diff --git a/webapp/src/components/RhsTitle/RhsTitle.component.tsx b/webapp/src/components/RhsTitle/RhsTitle.component.tsx index 4901fb902..cfa6fffb8 100644 --- a/webapp/src/components/RhsTitle/RhsTitle.component.tsx +++ b/webapp/src/components/RhsTitle/RhsTitle.component.tsx @@ -4,12 +4,14 @@ import {iconUrl} from 'constants/illustrations.constants'; import {pluginTitle} from 'constants/common.constants'; export const RhsTitle = () => ( - - - {pluginTitle} - +
+ + + {pluginTitle} + +
); diff --git a/webapp/src/components/Snackbar/Snackbar.component.tsx b/webapp/src/components/Snackbar/Snackbar.component.tsx index a81ebc381..f4cf4a25e 100644 --- a/webapp/src/components/Snackbar/Snackbar.component.tsx +++ b/webapp/src/components/Snackbar/Snackbar.component.tsx @@ -47,26 +47,28 @@ export const Snackbar = () => { }; return ( -
-
- -
{message}
-
- +
+ +
{message}
+
+ +
); }; diff --git a/webapp/src/constants/apiService.constant.ts b/webapp/src/constants/apiService.constant.ts index e341b450f..7037676c0 100644 --- a/webapp/src/constants/apiService.constant.ts +++ b/webapp/src/constants/apiService.constant.ts @@ -10,10 +10,10 @@ export const pluginApiServiceConfigs: Record = { success: 'success', diff --git a/webapp/src/containers/Rhs/Rhs.container.tsx b/webapp/src/containers/Rhs/Rhs.container.tsx index 1f577d31c..c5b77bf91 100644 --- a/webapp/src/containers/Rhs/Rhs.container.tsx +++ b/webapp/src/containers/Rhs/Rhs.container.tsx @@ -22,11 +22,8 @@ export const Rhs = () => { const {isOpen} = getSnackbarState(state); - const {data} = getApiState(pluginApiServiceConfigs.whitelistUser.apiServiceName); const {data: linkedChannels} = getApiState(pluginApiServiceConfigs.getLinkedChannels.apiServiceName); - const {presentInWhitelist} = data as WhitelistUserResponse; - // NOTE: Commented out on purpose.This is part of Phase-II // const isAnyChannelLinked = useMemo(() => Boolean((linkedChannels as ChannelLinkData[])?.length), [linkedChannels]); const isAnyChannelLinked = false; @@ -34,8 +31,10 @@ export const Rhs = () => { const getRhsView = useCallback(() => { if (isRhsLoading) { return ( -
- +
+
+ +
); } @@ -57,10 +56,7 @@ export const Rhs = () => { return ( <> - { - presentInWhitelist ? - getRhsView() : 'MS Teams Sync plugin' - } + {getRhsView()} {isOpen && } ); diff --git a/webapp/src/containers/Rhs/views/ConnectAccount/ConnectAccount.container.tsx b/webapp/src/containers/Rhs/views/ConnectAccount/ConnectAccount.container.tsx index 8c56be765..1d097bc76 100644 --- a/webapp/src/containers/Rhs/views/ConnectAccount/ConnectAccount.container.tsx +++ b/webapp/src/containers/Rhs/views/ConnectAccount/ConnectAccount.container.tsx @@ -25,31 +25,33 @@ export const ConnectAccount = () => { }); return ( -
-
-
- -

{Constants.connectAccountMsg}

+
+
+
+
+ +

{Constants.connectAccountMsg}

+
+ +
+
+
+
{Constants.listTitle}
+
    + {Constants.connectAccountFeatures.map(({icon, text}) => ( +
  • + +
    {text}
    +
  • + )) } +
- -
-
-
-
{Constants.listTitle}
-
    - {Constants.connectAccountFeatures.map(({icon, text}) => ( -
  • - -
    {text}
    -
  • - )) } -
); diff --git a/webapp/src/containers/Rhs/views/ConnectedAccount/ConnectedAccount.container.tsx b/webapp/src/containers/Rhs/views/ConnectedAccount/ConnectedAccount.container.tsx index 99e9fb697..381fe3f18 100644 --- a/webapp/src/containers/Rhs/views/ConnectedAccount/ConnectedAccount.container.tsx +++ b/webapp/src/containers/Rhs/views/ConnectedAccount/ConnectedAccount.container.tsx @@ -57,47 +57,49 @@ export const ConnectedAccount = () => { }, [connected, isAlreadyConnected]); return ( -
-
- {/* TODO: Refactor user Avatar */} -
- +
+
+ {/* TODO: Refactor user Avatar */} +
+ > + +
+
+
{'Connected as '}{username}
+ +
-
-
{'Connected as '}{username}
- -
-
-
- {/* NOTE: Part of Phase-II */} - {/* +
+ {/* NOTE: Part of Phase-II */} + {/*

{'There are no linked channels yet'}

*/} +
+
-
); }; diff --git a/webapp/src/containers/Rhs/views/LinkedChannels/LinkedChannels.container.tsx b/webapp/src/containers/Rhs/views/LinkedChannels/LinkedChannels.container.tsx index 0e6b0e345..db1468f46 100644 --- a/webapp/src/containers/Rhs/views/LinkedChannels/LinkedChannels.container.tsx +++ b/webapp/src/containers/Rhs/views/LinkedChannels/LinkedChannels.container.tsx @@ -53,38 +53,40 @@ export const LinkedChannels = () => { ), [totalLinkedChannels]); return ( -
-
- -
-

{channelListTitle}

-
- } - endMessage={ -

- {noMoreChannelsText} -

- } - scrollableTarget='scrollableArea' +
+
+
+ +
+

{channelListTitle}

+
- {totalLinkedChannels.map(({msTeamsChannelID, ...rest}) => ( - - )) - } - + } + endMessage={ +

+ {noMoreChannelsText} +

+ } + scrollableTarget='scrollableArea' + > + {totalLinkedChannels.map(({msTeamsChannelID, ...rest}) => ( + + )) + } +
+
); diff --git a/webapp/src/services/index.ts b/webapp/src/services/index.ts index 47e2a0c9d..68530417d 100644 --- a/webapp/src/services/index.ts +++ b/webapp/src/services/index.ts @@ -30,10 +30,10 @@ export const msTeamsPluginApi = createApi({ method: pluginApiServiceConfigs.connect.method, }), }), - [pluginApiServiceConfigs.whitelistUser.apiServiceName]: builder.query({ + [pluginApiServiceConfigs.rhsEnabled.apiServiceName]: builder.query({ query: () => ({ - url: pluginApiServiceConfigs.whitelistUser.path, - method: pluginApiServiceConfigs.whitelistUser.method, + url: pluginApiServiceConfigs.rhsEnabled.path, + method: pluginApiServiceConfigs.rhsEnabled.method, }), }), [pluginApiServiceConfigs.getLinkedChannels.apiServiceName]: builder.query({ diff --git a/webapp/src/styles/_utils.scss b/webapp/src/styles/_utils.scss index a6dad31ca..1add83c65 100644 --- a/webapp/src/styles/_utils.scss +++ b/webapp/src/styles/_utils.scss @@ -1,217 +1,219 @@ -// display -@each $display in $display-styles { - .d-#{$display} { - display: $display !important; +.msteams-sync-utils { + // display + @each $display in $display-styles { + .d-#{$display} { + display: $display !important; + } } -} -// gap -@each $size in $sizes { - .gap-#{$size} { - gap: #{$size}px !important; + // gap + @each $size in $sizes { + .gap-#{$size} { + gap: #{$size}px !important; + } } -} -// font-weights -@each $font-weight in $font-weights { - .wt-#{$font-weight} { - font-weight: $font-weight !important; + // font-weights + @each $font-weight in $font-weights { + .wt-#{$font-weight} { + font-weight: $font-weight !important; + } } -} -// font sizes -@each $font-size in $font-sizes { - .font-#{$font-size} { - font-size: #{$font-size}px !important; + // font sizes + @each $font-size in $font-sizes { + .font-#{$font-size} { + font-size: #{$font-size}px !important; + } } -} -// border radius -@each $size in $sizes { - .rounded-#{$size} { - border-radius: #{$size}px !important; + // border radius + @each $size in $sizes { + .rounded-#{$size} { + border-radius: #{$size}px !important; + } } -} -// padding -@each $size in $sizes { - .p-#{$size} { - padding: #{$size}px !important; + // padding + @each $size in $sizes { + .p-#{$size} { + padding: #{$size}px !important; + } } -} -// margin -@each $size in $sizes { - .m-#{$size} { - margin: #{$size}px !important; + // margin + @each $size in $sizes { + .m-#{$size} { + margin: #{$size}px !important; + } } -} -// margin block -@each $size in $sizes { - .my-#{$size} { - margin-block: #{$size}px !important; + // margin block + @each $size in $sizes { + .my-#{$size} { + margin-block: #{$size}px !important; + } } -} -// padding block -@each $size in $sizes { - .py-#{$size} { - padding-block: #{$size}px !important; + // padding block + @each $size in $sizes { + .py-#{$size} { + padding-block: #{$size}px !important; + } } -} -// padding inline -@each $size in $sizes { - .px-#{$size} { - padding-inline: #{$size}px !important; + // padding inline + @each $size in $sizes { + .px-#{$size} { + padding-inline: #{$size}px !important; + } } -} -// line height -@each $line-height in $line-heights { - .lh-#{$line-height} { - line-height: #{$line-height}px !important; + // line height + @each $line-height in $line-heights { + .lh-#{$line-height} { + line-height: #{$line-height}px !important; + } } -} -// positions -@each $size in $sizes { - .top-#{$size} { - top: #{$size}px; - } + // positions + @each $size in $sizes { + .top-#{$size} { + top: #{$size}px; + } - .right-#{$size} { - right: #{$size}px; - } + .right-#{$size} { + right: #{$size}px; + } - .bottom-#{$size} { - bottom: #{$size}px; - } + .bottom-#{$size} { + bottom: #{$size}px; + } - .left-#{$size} { - left: #{$size}px; + .left-#{$size} { + left: #{$size}px; + } } -} -@each $position in $positions { - .#{$position} { - position: $position !important; + @each $position in $positions { + .#{$position} { + position: $position !important; + } } -} - -.mt-0 { - margin-top: 0; -} -.align-items-center { - align-items: center; -} + .mt-0 { + margin-top: 0; + } -.align-items-start { - align-items: flex-start; -} + .align-items-center { + align-items: center; + } -.align-items-end { - align-items: flex-end; -} + .align-items-start { + align-items: flex-start; + } -.justify-center { - justify-content: center; -} + .align-items-end { + align-items: flex-end; + } -.justify-start { - justify-content: flex-start; -} + .justify-center { + justify-content: center; + } -.justify-end { - justify-content: flex-end; -} + .justify-start { + justify-content: flex-start; + } -.justify-between { - justify-content: space-between; -} + .justify-end { + justify-content: flex-end; + } -.flex-1 { - flex: 1 -} + .justify-between { + justify-content: space-between; + } -.flex-2 { - flex: 2 -} + .flex-1 { + flex: 1 + } -.flex-1-0-0 { - flex: 1 0 0; -} + .flex-2 { + flex: 2 + } -.flex-column { - flex-direction: column; -} + .flex-1-0-0 { + flex: 1 0 0; + } -.w-full { - width: 100% -} + .flex-column { + flex-direction: column; + } -.h-full { - height: 100%; -} + .w-full { + width: 100% + } -.text-center { - text-align: center; -} + .h-full { + height: 100%; + } -.overflow-y-auto { - overflow-y: auto; -} + .text-center { + text-align: center; + } -.border-t-1 { - border-top-width: 1px; - border-top-style: solid; - border-top-color: rgba(var(--center-channel-color-rgb), 0.12); -} + .overflow-y-auto { + overflow-y: auto; + } -.border-y-1 { - border-block-width: 1px; - border-block-style: solid; - border-block-color: rgba(var(--center-channel-color-rgb), 0.12); -} + .border-t-1 { + border-top-width: 1px; + border-top-style: solid; + border-top-color: rgba(var(--center-channel-color-rgb), 0.12); + } -.opacity-6 { - opacity: 0.6; -} + .border-y-1 { + border-block-width: 1px; + border-block-style: solid; + border-block-color: rgba(var(--center-channel-color-rgb), 0.12); + } -.text-white { - color: var(--button-color) -} + .opacity-6 { + opacity: 0.6; + } -.icon-white { - & path, & rect, & circle { - fill: var(--button-color), + .text-white { + color: var(--button-color) } -} -.icon-16 { - height: 16px; - width: 16px; + .icon-white { + & path, & rect, & circle { + fill: var(--button-color), + } + } - svg { + .icon-16 { height: 16px; width: 16px; + + svg { + height: 16px; + width: 16px; + } } -} -.elevation-2 { - box-shadow: var(--elevation-2); -} + .elevation-2 { + box-shadow: var(--elevation-2); + } -.bg-success { - background-color: var(--online-indicator); -} + .bg-success { + background-color: var(--online-indicator); + } -.bg-default { - background-color: var(--center-channel-color); -} + .bg-default { + background-color: var(--center-channel-color); + } -.bg-error { - background-color: var(--error-text); + .bg-error { + background-color: var(--error-text); + } } diff --git a/webapp/src/types/common/index.d.ts b/webapp/src/types/common/index.d.ts index 6d62d3bb7..d7e200dcd 100644 --- a/webapp/src/types/common/index.d.ts +++ b/webapp/src/types/common/index.d.ts @@ -15,8 +15,8 @@ type WebsocketEventParams = { data: Record, } -type WhitelistUserResponse= { - presentInWhitelist: boolean +type RhsEnabledResponse= { + rhsEnabled: boolean } type ChannelLinkData = { diff --git a/webapp/src/types/common/service.d.ts b/webapp/src/types/common/service.d.ts index 50313008f..9c1db5846 100644 --- a/webapp/src/types/common/service.d.ts +++ b/webapp/src/types/common/service.d.ts @@ -1,6 +1,6 @@ type HttpMethod = 'GET' | 'POST' | 'PATCH' | 'DELETE'; -type PluginApiServiceName = 'needsConnect' | 'connect' | 'whitelistUser' | 'getLinkedChannels' | 'disconnectUser' ; +type PluginApiServiceName = 'needsConnect' | 'connect' | 'rhsEnabled' | 'getLinkedChannels' | 'disconnectUser' ; type PluginApiService = { path: string, diff --git a/webapp/src/types/common/store.d.ts b/webapp/src/types/common/store.d.ts index 624e752a2..7188c4854 100644 --- a/webapp/src/types/common/store.d.ts +++ b/webapp/src/types/common/store.d.ts @@ -24,6 +24,10 @@ type ConnectedState = { msteamsUserId: string; }; +type CanSeeRhsState = { + canSeeRhs: boolean; +} + type NeedsConnectState = { needsConnect: boolean; }; diff --git a/webapp/src/types/mattermost-webapp/index.d.ts b/webapp/src/types/mattermost-webapp/index.d.ts index 5af2c2143..7ff95ef58 100644 --- a/webapp/src/types/mattermost-webapp/index.d.ts +++ b/webapp/src/types/mattermost-webapp/index.d.ts @@ -7,6 +7,7 @@ interface PluginRegistry { registerAppBarComponent(iconUrl: string, action: () => void, tooltipText: string) registerReducer(reducer) registerWebSocketEventHandler(event: string, handler: (msg: WebsocketEventParams) => void) + unregisterComponent(id: string) // Add more if needed from https://developers.mattermost.com/extend/plugins/webapp/reference }