From 7e75e291e26fed2e4c983d7580b076fbbb9aad0e Mon Sep 17 00:00:00 2001 From: Darya Plotnytska Date: Thu, 7 Mar 2024 11:09:34 +0100 Subject: [PATCH 1/6] console: Add store for user preferences --- pkg/webui/console/store/middleware/logics/init.js | 1 + pkg/webui/console/store/selectors/logout.js | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/pkg/webui/console/store/middleware/logics/init.js b/pkg/webui/console/store/middleware/logics/init.js index d64916a0b9..6d0f6608cc 100644 --- a/pkg/webui/console/store/middleware/logics/init.js +++ b/pkg/webui/console/store/middleware/logics/init.js @@ -66,6 +66,7 @@ const consoleAppLogic = createRequestLogic({ 'name', 'primary_email_address_validated_at', 'profile_picture', + 'console_preferences', ]) userResult.isAdmin = info.is_admin || false dispatch(user.getUserMeSuccess(userResult)) diff --git a/pkg/webui/console/store/selectors/logout.js b/pkg/webui/console/store/selectors/logout.js index 73c0bf21cf..fa05ac9aa4 100644 --- a/pkg/webui/console/store/selectors/logout.js +++ b/pkg/webui/console/store/selectors/logout.js @@ -52,3 +52,9 @@ export const selectUserIsAdmin = state => { } export const selectUserRights = state => selectUserStore(state).rights + +export const selectUserPreferences = state => { + const user = selectUser(state) + + return user ? user.console_preferences : undefined +} From 70127540a75263a52aa3333ad0dc7c965c80d38e Mon Sep 17 00:00:00 2001 From: Darya Plotnytska Date: Mon, 11 Mar 2024 13:15:50 +0100 Subject: [PATCH 2/6] console: Add bookmark store --- .../console/store/actions/user-preferences.js | 41 ++++++++++++++ .../console/store/middleware/logics/index.js | 2 + .../middleware/logics/user-preferences.js | 56 +++++++++++++++++++ pkg/webui/console/store/reducers/index.js | 2 + .../store/reducers/user-preferences.js | 37 ++++++++++++ sdk/js/src/service/users.js | 39 +++++++++++++ sdk/js/src/util/marshaler.js | 8 +++ 7 files changed, 185 insertions(+) create mode 100644 pkg/webui/console/store/actions/user-preferences.js create mode 100644 pkg/webui/console/store/middleware/logics/user-preferences.js create mode 100644 pkg/webui/console/store/reducers/user-preferences.js diff --git a/pkg/webui/console/store/actions/user-preferences.js b/pkg/webui/console/store/actions/user-preferences.js new file mode 100644 index 0000000000..ef172fa152 --- /dev/null +++ b/pkg/webui/console/store/actions/user-preferences.js @@ -0,0 +1,41 @@ +// Copyright © 2024 The Things Network Foundation, The Things Industries B.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import createRequestActions from '@ttn-lw/lib/store/actions/create-request-actions' +import { + createPaginationBaseActionType, + createPaginationByIdRequestActions, +} from '@ttn-lw/lib/store/actions/pagination' + +export const GET_BOOKMARKS_LIST_BASE = createPaginationBaseActionType('BOOKMARKS') +export const [ + { + request: GET_BOOKMARKS_LIST, + success: GET_BOOKMARKS_LIST_SUCCESS, + failure: GET_BOOKMARKS_LIST_FAILURE, + }, + { request: getBookmarksList, success: getBookmarksListSuccess, failure: getBookmarksListFailure }, +] = createPaginationByIdRequestActions('BOOKMARKS') + +export const ADD_BOOKMARK_BASE = 'ADD_BOOKMARK' +export const [ + { request: ADD_BOOKMARK, success: ADD_BOOKMARK_SUCCESS, failure: ADD_BOOKMARK_FAILURE }, + { request: addBookmark, success: addBookmarkSuccess, failure: addBookmarkFailure }, +] = createRequestActions(ADD_BOOKMARK_BASE, (userId, entity) => ({ userId, entity })) + +export const DELETE_BOOKMARK_BASE = 'DELETE_BOOKMARK' +export const [ + { request: DELETE_BOOKMARK, success: DELETE_BOOKMARK_SUCCESS, failure: DELETE_BOOKMARK_FAILURE }, + { request: deleteBookmark, success: deleteBookmarkSuccess, failure: deleteBookmarkFailure }, +] = createRequestActions(DELETE_BOOKMARK_BASE, (userId, entity) => ({ userId, entity })) diff --git a/pkg/webui/console/store/middleware/logics/index.js b/pkg/webui/console/store/middleware/logics/index.js index 1dc26adeb1..8a0e5d27b8 100644 --- a/pkg/webui/console/store/middleware/logics/index.js +++ b/pkg/webui/console/store/middleware/logics/index.js @@ -37,6 +37,7 @@ import networkServer from './network-server' import qrCodeGenerator from './qr-code-generator' import searchAccounts from './search-accounts' import notifications from './notifications' +import userPreferences from './user-preferences' export default [ ...status, @@ -63,4 +64,5 @@ export default [ ...qrCodeGenerator, ...searchAccounts, ...notifications, + ...userPreferences, ] diff --git a/pkg/webui/console/store/middleware/logics/user-preferences.js b/pkg/webui/console/store/middleware/logics/user-preferences.js new file mode 100644 index 0000000000..34c7345371 --- /dev/null +++ b/pkg/webui/console/store/middleware/logics/user-preferences.js @@ -0,0 +1,56 @@ +// Copyright © 2019 The Things Network Foundation, The Things Industries B.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import tts from '@console/api/tts' + +import createRequestLogic from '@ttn-lw/lib/store/logics/create-request-logic' + +import * as userPreferences from '@console/store/actions/user-preferences' + +const getBookmarksListLogic = createRequestLogic({ + type: userPreferences.GET_BOOKMARKS_LIST, + process: async ({ action }) => { + const { + id: userId, + params: { page, limit, order, deleted }, + } = action.payload + const data = await tts.Users.getBookmarks(userId, { page, limit, order, deleted }) + + return { entities: data.bookmarks, totalCount: data.totalCount } + }, +}) + +const addBookmarkLogic = createRequestLogic({ + type: userPreferences.ADD_BOOKMARK, + process: async ({ action }) => { + const { + payload: { userId, entity }, + } = action + + return await tts.Users.addBookmark(userId, entity) + }, +}) + +const deleteBookmarkLogic = createRequestLogic({ + type: userPreferences.DELETE_BOOKMARK, + process: async ({ action }) => { + const { + payload: { userId, entity }, + } = action + + return await tts.Users.deleteBookmark(userId, entity) + }, +}) + +export default [getBookmarksListLogic, addBookmarkLogic, deleteBookmarkLogic] diff --git a/pkg/webui/console/store/reducers/index.js b/pkg/webui/console/store/reducers/index.js index ff7187ff6a..52a529420b 100644 --- a/pkg/webui/console/store/reducers/index.js +++ b/pkg/webui/console/store/reducers/index.js @@ -64,6 +64,7 @@ import deviceRepository from './device-repository' import packetBroker from './packet-broker' import ns from './network-server' import notifications from './notifications' +import userPreferences from './user-preferences' export default combineReducers({ user, @@ -123,4 +124,5 @@ export default combineReducers({ ns, searchAccounts, notifications, + userPreferences, }) diff --git a/pkg/webui/console/store/reducers/user-preferences.js b/pkg/webui/console/store/reducers/user-preferences.js new file mode 100644 index 0000000000..4e513362c1 --- /dev/null +++ b/pkg/webui/console/store/reducers/user-preferences.js @@ -0,0 +1,37 @@ +// Copyright © 2024 The Things Network Foundation, The Things Industries B.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import { GET_BOOKMARKS_LIST_SUCCESS } from '@console/store/actions/user-preferences' + +const initialState = { + bookmarks: { + bookmarks: [], + totalCount: 0, + }, +} + +const userPreferences = (state = initialState, { type, payload }) => { + switch (type) { + case GET_BOOKMARKS_LIST_SUCCESS: + return { + ...state, + bookmarks: payload.entities, + totalCount: payload.totalCount, + } + default: + return state + } +} + +export default userPreferences diff --git a/sdk/js/src/service/users.js b/sdk/js/src/service/users.js index 1b6d67c848..26e605965e 100644 --- a/sdk/js/src/service/users.js +++ b/sdk/js/src/service/users.js @@ -202,6 +202,45 @@ class Users { return Marshaler.unwrapInvitation(response) } + + // Preferences - Bookmarks. + async getBookmarks(userId, params) { + const response = await this._api.UserBookmarkRegistry.List( + { + routeParams: { 'user_ids.user_id': userId }, + }, + { + ...params, + }, + ) + + return Marshaler.unwrapBookmarks(response) + } + + async addBookmark(userId, entity) { + const response = await this._api.UserBookmarkRegistry.Create(undefined, { + user_ids: { user_id: userId }, + entity_ids: entity, + }) + + return Marshaler.unwrapBookmark(response) + } + + async deleteBookmark(userId, entity) { + const entityIdRoute = `entity_ids.${entity.name}_ids.${entity.name}_id` + const routeParams = { + 'user_ids.user_id': userId, + [entityIdRoute]: entity.id, + } + if (entity === 'device') { + routeParams['entity_ids.device_ids.application_ids.application_id'] = entity.applicationId + } + const response = await this._api.UserBookmarkRegistry.Delete({ + routeParams, + }) + + return Marshaler.unwrapBookmark(response) + } } export default Users diff --git a/sdk/js/src/util/marshaler.js b/sdk/js/src/util/marshaler.js index 4a8b189ecf..84b75a121d 100644 --- a/sdk/js/src/util/marshaler.js +++ b/sdk/js/src/util/marshaler.js @@ -130,6 +130,14 @@ class Marshaler { return this.payloadSingleResponse(result) } + static unwrapBookmarks(result) { + return this.payloadListResponse('bookmarks', result) + } + + static unwrapBookmark(result) { + return this.payloadSingleResponse(result) + } + static fieldMaskFromPatch(patch, whitelist, remaps = []) { const paths = [] From b855cb1123dcbf3ca2c8decc283675632f080158 Mon Sep 17 00:00:00 2001 From: Darya Plotnytska Date: Mon, 11 Mar 2024 13:32:46 +0100 Subject: [PATCH 3/6] console: Centralize user preferences --- pkg/webui/console/store/reducers/user-preferences.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pkg/webui/console/store/reducers/user-preferences.js b/pkg/webui/console/store/reducers/user-preferences.js index 4e513362c1..9a45d6952f 100644 --- a/pkg/webui/console/store/reducers/user-preferences.js +++ b/pkg/webui/console/store/reducers/user-preferences.js @@ -13,12 +13,16 @@ // limitations under the License. import { GET_BOOKMARKS_LIST_SUCCESS } from '@console/store/actions/user-preferences' +import { GET_USER_ME_SUCCESS } from '@console/store/actions/logout' const initialState = { bookmarks: { bookmarks: [], totalCount: 0, }, + consoleTheme: 'CONSOLE_THEME_SYSTEM', + dashboardLayouts: {}, + sortBy: {}, } const userPreferences = (state = initialState, { type, payload }) => { @@ -29,6 +33,13 @@ const userPreferences = (state = initialState, { type, payload }) => { bookmarks: payload.entities, totalCount: payload.totalCount, } + case GET_USER_ME_SUCCESS: + return { + ...state, + consoleTheme: payload.console_preferences.console_theme || 'CONSOLE_THEME_SYSTEM', + dashboardLayouts: payload.console_preferences.dashboard_layout || {}, + sortBy: payload.console_preferences.sort_by || {}, + } default: return state } From 15e13c03d72730e24fa5e3007300f57603b2f807 Mon Sep 17 00:00:00 2001 From: Darya Plotnytska Date: Mon, 11 Mar 2024 13:38:39 +0100 Subject: [PATCH 4/6] console: Add selectors --- .../store/reducers/user-preferences.js | 11 ++++----- pkg/webui/console/store/selectors/logout.js | 6 ----- .../store/selectors/user-preferences.js | 23 +++++++++++++++++++ 3 files changed, 28 insertions(+), 12 deletions(-) create mode 100644 pkg/webui/console/store/selectors/user-preferences.js diff --git a/pkg/webui/console/store/reducers/user-preferences.js b/pkg/webui/console/store/reducers/user-preferences.js index 9a45d6952f..d338bdde8b 100644 --- a/pkg/webui/console/store/reducers/user-preferences.js +++ b/pkg/webui/console/store/reducers/user-preferences.js @@ -20,9 +20,7 @@ const initialState = { bookmarks: [], totalCount: 0, }, - consoleTheme: 'CONSOLE_THEME_SYSTEM', - dashboardLayouts: {}, - sortBy: {}, + consolePreferences: {}, } const userPreferences = (state = initialState, { type, payload }) => { @@ -36,9 +34,10 @@ const userPreferences = (state = initialState, { type, payload }) => { case GET_USER_ME_SUCCESS: return { ...state, - consoleTheme: payload.console_preferences.console_theme || 'CONSOLE_THEME_SYSTEM', - dashboardLayouts: payload.console_preferences.dashboard_layout || {}, - sortBy: payload.console_preferences.sort_by || {}, + consolePreferences: { + ...state.consolePreferences, + ...payload.console_preferences, + }, } default: return state diff --git a/pkg/webui/console/store/selectors/logout.js b/pkg/webui/console/store/selectors/logout.js index fa05ac9aa4..73c0bf21cf 100644 --- a/pkg/webui/console/store/selectors/logout.js +++ b/pkg/webui/console/store/selectors/logout.js @@ -52,9 +52,3 @@ export const selectUserIsAdmin = state => { } export const selectUserRights = state => selectUserStore(state).rights - -export const selectUserPreferences = state => { - const user = selectUser(state) - - return user ? user.console_preferences : undefined -} diff --git a/pkg/webui/console/store/selectors/user-preferences.js b/pkg/webui/console/store/selectors/user-preferences.js new file mode 100644 index 0000000000..008cf112da --- /dev/null +++ b/pkg/webui/console/store/selectors/user-preferences.js @@ -0,0 +1,23 @@ +// Copyright © 2024 The Things Network Foundation, The Things Industries B.V. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +const selectUserPreferencesStore = state => state.userPreferences + +export const selectConsolePreferences = state => + selectUserPreferencesStore(state).consolePreferences + +export const selectBookmarksList = state => selectUserPreferencesStore(state).bookmarks.bookmarks + +export const selectBookmarksTotalCount = state => + selectUserPreferencesStore(state).bookmarks.totalCount From 654d15d99cbc657dadd7ce258a7e353ac726e0ec Mon Sep 17 00:00:00 2001 From: Darya Plotnytska <56658938+ryaplots@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:17:30 +0100 Subject: [PATCH 5/6] console: Fix reducer --- pkg/webui/console/store/reducers/user-preferences.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/pkg/webui/console/store/reducers/user-preferences.js b/pkg/webui/console/store/reducers/user-preferences.js index d338bdde8b..4ca500aa8d 100644 --- a/pkg/webui/console/store/reducers/user-preferences.js +++ b/pkg/webui/console/store/reducers/user-preferences.js @@ -28,8 +28,11 @@ const userPreferences = (state = initialState, { type, payload }) => { case GET_BOOKMARKS_LIST_SUCCESS: return { ...state, - bookmarks: payload.entities, - totalCount: payload.totalCount, + bookmarks: { + ...state.bookmarks, + bookmarks: payload.entities, + totalCount: payload.totalCount, + }, } case GET_USER_ME_SUCCESS: return { From b32d330fb41d702f8ad83234c6567b115dae939a Mon Sep 17 00:00:00 2001 From: Darya Plotnytska <56658938+ryaplots@users.noreply.github.com> Date: Mon, 11 Mar 2024 17:18:27 +0100 Subject: [PATCH 6/6] console: Update date --- pkg/webui/console/store/middleware/logics/user-preferences.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/webui/console/store/middleware/logics/user-preferences.js b/pkg/webui/console/store/middleware/logics/user-preferences.js index 34c7345371..6c6ef01255 100644 --- a/pkg/webui/console/store/middleware/logics/user-preferences.js +++ b/pkg/webui/console/store/middleware/logics/user-preferences.js @@ -1,4 +1,4 @@ -// Copyright © 2019 The Things Network Foundation, The Things Industries B.V. +// Copyright © 2024 The Things Network Foundation, The Things Industries B.V. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License.