From 4017fb8a3b1c5fe941582e41280623dafcdbb640 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:33:50 +0300 Subject: [PATCH 01/49] chore: install @monokle/synchronizer --- package-lock.json | 105 ++++++++++++++++++++++++++++++++++++++++++---- package.json | 1 + 2 files changed, 99 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index e25cce182d..ba3196cf1c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@dnd-kit/sortable": "7.0.2", "@kubernetes/client-node": "0.18.1", "@monokle/components": "1.7.0", + "@monokle/synchronizer": "^0.3.1", "@monokle/validation": "0.24.2", "@open-policy-agent/opa-wasm": "1.8.0", "@reduxjs/toolkit": "1.9.5", @@ -4701,6 +4702,91 @@ "use-debounced-effect": "2.0.1" } }, + "node_modules/@monokle/synchronizer": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@monokle/synchronizer/-/synchronizer-0.3.1.tgz", + "integrity": "sha512-Fu5/sy2RGz23UedlWxDIbFde2DG+dtNQAm0LF60i/TslALLjqDI2NzTjS0fWUR1Uqa2Ylhm4FdmviU5V0ewqXA==", + "dependencies": { + "@monokle/types": "*", + "env-paths": "^2.2.1", + "git-url-parse": "^13.1.0", + "mkdirp": "^3.0.1", + "node-fetch": "^2.6.13", + "normalize-url": "^4.5.1", + "openid-client": "^5.4.3", + "simple-git": "^3.19.1", + "slugify": "^1.6.6", + "yaml": "^2.3.1" + } + }, + "node_modules/@monokle/synchronizer/node_modules/mkdirp": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", + "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@monokle/synchronizer/node_modules/node-fetch": { + "version": "2.6.13", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.13.tgz", + "integrity": "sha512-StxNAxh15zr77QvvkmveSQ8uCQ4+v5FkvNTj0OESmiHu+VRi/gXArXtkWMElOsOUNLtUEvI4yS+rdtOHZTwlQA==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/@monokle/synchronizer/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@monokle/synchronizer/node_modules/simple-git": { + "version": "3.19.1", + "resolved": "https://registry.npmjs.org/simple-git/-/simple-git-3.19.1.tgz", + "integrity": "sha512-Ck+rcjVaE1HotraRAS8u/+xgTvToTuoMkT9/l9lvuP5jftwnYUp6DwuJzsKErHgfyRk8IB8pqGHWEbM3tLgV1w==", + "dependencies": { + "@kwsites/file-exists": "^1.1.1", + "@kwsites/promise-deferred": "^1.1.1", + "debug": "^4.3.4" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/git-js?sponsor=1" + } + }, + "node_modules/@monokle/synchronizer/node_modules/yaml": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/@monokle/types": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@monokle/types/-/types-0.2.0.tgz", + "integrity": "sha512-6Sld9+1p+W6kRWkdNpNVQCSgAjSPZu8EiIq8ANT9+RfA1rKlYuouOdaadGqtPUsD75lOl67r5Wzn3IxTm34gmw==" + }, "node_modules/@monokle/validation": { "version": "0.24.2", "resolved": "https://registry.npmjs.org/@monokle/validation/-/validation-0.24.2.tgz", @@ -17491,7 +17577,6 @@ "node_modules/jose": { "version": "4.14.4", "license": "MIT", - "optional": true, "funding": { "url": "https://github.com/sponsors/panva" } @@ -20294,7 +20379,6 @@ "node_modules/object-hash": { "version": "2.2.0", "license": "MIT", - "optional": true, "engines": { "node": ">= 6" } @@ -20430,7 +20514,6 @@ "node_modules/oidc-token-hash": { "version": "5.0.3", "license": "MIT", - "optional": true, "engines": { "node": "^10.13.0 || >=12.0.0" } @@ -20531,11 +20614,11 @@ } }, "node_modules/openid-client": { - "version": "5.4.2", - "license": "MIT", - "optional": true, + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.4.3.tgz", + "integrity": "sha512-sVQOvjsT/sbSfYsQI/9liWQGVZH/Pp3rrtlGEwgk/bbHfrUDZ24DN57lAagIwFtuEu+FM9Ev7r85s8S/yPjimQ==", "dependencies": { - "jose": "^4.14.1", + "jose": "^4.14.4", "lru-cache": "^6.0.0", "object-hash": "^2.2.0", "oidc-token-hash": "^5.0.3" @@ -24901,6 +24984,14 @@ "node": ">=8" } }, + "node_modules/slugify": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", + "integrity": "sha512-h+z7HKHYXj6wJU+AnS/+IH8Uh9fdcX1Lrhg1/VMdf9PwoBQXFcXiAdsy2tSK0P6gKwJLXp02r90ahUCqHk9rrw==", + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/smart-buffer": { "version": "4.2.0", "dev": true, diff --git a/package.json b/package.json index 37c1ffcbc5..c5c71387b0 100644 --- a/package.json +++ b/package.json @@ -101,6 +101,7 @@ "@dnd-kit/sortable": "7.0.2", "@kubernetes/client-node": "0.18.1", "@monokle/components": "1.7.0", + "@monokle/synchronizer": "^0.3.1", "@monokle/validation": "0.24.2", "@open-policy-agent/opa-wasm": "1.8.0", "@reduxjs/toolkit": "1.9.5", From 428ec0d0f53451021e9bc9e9fefebf1b404bdf5e Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:34:18 +0300 Subject: [PATCH 02/49] refactor: update types for cloud sync --- src/shared/models/cloud.ts | 10 ++++++++++ src/shared/models/validation.ts | 2 ++ src/shared/utils/types.ts | 7 +++++++ 3 files changed, 19 insertions(+) create mode 100644 src/shared/models/cloud.ts diff --git a/src/shared/models/cloud.ts b/src/shared/models/cloud.ts new file mode 100644 index 0000000000..11b7760f54 --- /dev/null +++ b/src/shared/models/cloud.ts @@ -0,0 +1,10 @@ +/** + * This type is used by the renderer so it doesn't need to have all the properties of the User class + */ +export type CloudUser = { + readonly email: string; +}; + +export type CloudLoginResponse = { + user: CloudUser; +}; diff --git a/src/shared/models/validation.ts b/src/shared/models/validation.ts index 8e4380a989..facd3dab07 100644 --- a/src/shared/models/validation.ts +++ b/src/shared/models/validation.ts @@ -1,4 +1,5 @@ import type {ValidationFiltersValueType} from '@monokle/components'; +import type {PolicyData} from '@monokle/synchronizer'; import type { Config, PluginMetadataWithConfig, @@ -21,6 +22,7 @@ export type SelectedProblem = { export type ValidationState = { config: Config; + cloudPolicy?: PolicyData; status: Initialization; lastResponse?: ValidationResponse; loadRequestId?: string; diff --git a/src/shared/utils/types.ts b/src/shared/utils/types.ts index 129def2ad2..6b6c703abe 100644 --- a/src/shared/utils/types.ts +++ b/src/shared/utils/types.ts @@ -13,3 +13,10 @@ export type DeepPartial = T extends object [P in keyof T]?: DeepPartial; } : T; + +export type ExtractProperties = Pick< + ObjectType, + { + [Property in keyof ObjectType]: ObjectType[Property] extends (...params: unknown[]) => unknown ? never : Property; + }[keyof ObjectType] +>; From 9941ff98855709ec5a4c62afc5aa49d99038e9fe Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:34:38 +0300 Subject: [PATCH 03/49] feat: setup cloud authenticator --- electron/app/services/cloud/authenticator.ts | 22 ++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 electron/app/services/cloud/authenticator.ts diff --git a/electron/app/services/cloud/authenticator.ts b/electron/app/services/cloud/authenticator.ts new file mode 100644 index 0000000000..168f37b1b4 --- /dev/null +++ b/electron/app/services/cloud/authenticator.ts @@ -0,0 +1,22 @@ +import {app} from 'electron'; + +import {join} from 'path'; + +import {Authenticator, StorageHandlerAuth, createDefaultMonokleAuthenticator} from '@monokle/synchronizer'; + +let authenticator: Authenticator | undefined; + +const initAuthenticator = async (cloudStorageDir: string) => { + const newAuthenticator = createDefaultMonokleAuthenticator(new StorageHandlerAuth(cloudStorageDir)); + authenticator = newAuthenticator; + return newAuthenticator; +}; + +export const getAuthenticator = async () => { + const userDataDir = app.getPath('userData'); + const cloudStorageDir = join(userDataDir, 'cloud'); + if (!authenticator) { + await initAuthenticator(cloudStorageDir); + } + return authenticator; +}; From c1039ee710902017879328be2dda19333501fab7 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:34:49 +0300 Subject: [PATCH 04/49] feat: setup cloud synchronizer --- electron/app/services/cloud/synchronizer.ts | 22 +++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 electron/app/services/cloud/synchronizer.ts diff --git a/electron/app/services/cloud/synchronizer.ts b/electron/app/services/cloud/synchronizer.ts new file mode 100644 index 0000000000..262b672caf --- /dev/null +++ b/electron/app/services/cloud/synchronizer.ts @@ -0,0 +1,22 @@ +import {app} from 'electron'; + +import {join} from 'path'; + +import {StorageHandlerPolicy, Synchronizer, createDefaultMonokleSynchronizer} from '@monokle/synchronizer'; + +let synchronizer: Synchronizer | undefined; + +const initSynchronizer = async (cloudStorageDir: string) => { + const newSynchronizer = createDefaultMonokleSynchronizer(new StorageHandlerPolicy(cloudStorageDir)); + synchronizer = newSynchronizer; + return newSynchronizer; +}; + +export const getSynchronizer = async () => { + const userDataDir = app.getPath('userData'); + const cloudStorageDir = join(userDataDir, 'cloud'); + if (!synchronizer) { + await initSynchronizer(cloudStorageDir); + } + return synchronizer; +}; From 95d2702311777223dd656d01037ba30116e80b0f Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:35:31 +0300 Subject: [PATCH 05/49] feat: cloud login --- electron/app/services/cloud/login.ts | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 electron/app/services/cloud/login.ts diff --git a/electron/app/services/cloud/login.ts b/electron/app/services/cloud/login.ts new file mode 100644 index 0000000000..4cf7e5f7db --- /dev/null +++ b/electron/app/services/cloud/login.ts @@ -0,0 +1,23 @@ +import {shell} from 'electron'; + +import {CloudLoginResponse} from '@shared/models/cloud'; + +import {getAuthenticator} from './authenticator'; +import {serializeUser} from './user'; + +export const cloudLogin = async (): Promise => { + const authenticator = await getAuthenticator(); + if (!authenticator) { + throw new Error('Something went wrong with the authenticator'); + } + const loginResponse = await authenticator.login('device code'); + if (!loginResponse.handle) { + throw new Error('Something went wrong with the login response'); + } + shell.openExternal(loginResponse.handle.verification_uri_complete); + const user = await loginResponse.onDone; + if (!user) { + throw new Error('Login to Cloud has failed'); + } + return {user: serializeUser(user)}; +}; From 47df5989e562c37f733f19dfd573a31688049b73 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:35:47 +0300 Subject: [PATCH 06/49] feat: fetch policy --- electron/app/services/cloud/policy.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 electron/app/services/cloud/policy.ts diff --git a/electron/app/services/cloud/policy.ts b/electron/app/services/cloud/policy.ts new file mode 100644 index 0000000000..1d94065e6d --- /dev/null +++ b/electron/app/services/cloud/policy.ts @@ -0,0 +1,26 @@ +import log from 'loglevel'; + +import {getAuthenticator} from './authenticator'; +import {getSynchronizer} from './synchronizer'; + +export const getPolicy = async (repoPath: string) => { + const authenticator = await getAuthenticator(); + const synchronizer = await getSynchronizer(); + + const user = await authenticator?.getUser(); + + if (!user?.token || !synchronizer) { + return undefined; + } + + try { + const policy = await synchronizer.synchronize(repoPath, user.token); + return policy; + } catch (e: any) { + if (e instanceof Error) { + console.log(e.message); + } + log.error('Failed to synchronize policy'); + } + return undefined; +}; From e5828f9b0a63ec54f6e12183b7d9eec26a9244dc Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:36:07 +0300 Subject: [PATCH 07/49] feat: fetch cloud user --- electron/app/services/cloud/user.ts | 30 +++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 electron/app/services/cloud/user.ts diff --git a/electron/app/services/cloud/user.ts b/electron/app/services/cloud/user.ts new file mode 100644 index 0000000000..97e260a1c7 --- /dev/null +++ b/electron/app/services/cloud/user.ts @@ -0,0 +1,30 @@ +import {User} from '@monokle/synchronizer'; +import {CloudUser} from '@shared/models/cloud'; + +import {getAuthenticator} from './authenticator'; + +export const getUser = async (): Promise => { + const authenticator = await getAuthenticator(); + if (!authenticator) { + return undefined; + } + const user = await authenticator.getUser(); + if (!user.isAuthenticated) { + return undefined; + } + try { + const serializedUser = serializeUser(user); + return serializedUser; + } catch { + return undefined; + } +}; + +export const serializeUser = (user: User): CloudUser => { + if (!user.email) { + throw new Error('User not found'); + } + return { + email: user.email, + }; +}; From ee3abdd7191a993d47911dfab3ee4dc6be442b2e Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:36:29 +0300 Subject: [PATCH 08/49] feat: cloud ipc --- electron/app/ipc/ipcListeners.ts | 1 + electron/app/services/cloud/ipc.ts | 8 ++++++++ src/redux/cloud/ipc.ts | 8 ++++++++ 3 files changed, 17 insertions(+) create mode 100644 electron/app/services/cloud/ipc.ts create mode 100644 src/redux/cloud/ipc.ts diff --git a/electron/app/ipc/ipcListeners.ts b/electron/app/ipc/ipcListeners.ts index 43cecb2dab..b783325518 100644 --- a/electron/app/ipc/ipcListeners.ts +++ b/electron/app/ipc/ipcListeners.ts @@ -45,6 +45,7 @@ import { selectFileDialog, } from '../commands'; import {ProjectNameChange, StorePropagation} from '../models'; +import '../services/cloud/ipc'; import '../services/cluster/ipc'; import {downloadPlugin, updatePlugin} from '../services/pluginService'; import { diff --git a/electron/app/services/cloud/ipc.ts b/electron/app/services/cloud/ipc.ts new file mode 100644 index 0000000000..9c48c28c47 --- /dev/null +++ b/electron/app/services/cloud/ipc.ts @@ -0,0 +1,8 @@ +import {handleIpc} from '../../utils/ipc'; +import {cloudLogin} from './login'; +import {getPolicy} from './policy'; +import {getUser} from './user'; + +handleIpc('cloud:login', cloudLogin); +handleIpc('cloud:getUser', getUser); +handleIpc('cloud:getPolicy', getPolicy); diff --git a/src/redux/cloud/ipc.ts b/src/redux/cloud/ipc.ts new file mode 100644 index 0000000000..37d17e99fd --- /dev/null +++ b/src/redux/cloud/ipc.ts @@ -0,0 +1,8 @@ +import {invokeIpc} from '@utils/ipc'; + +import type {PolicyData} from '@monokle/synchronizer'; +import {CloudLoginResponse, CloudUser} from '@shared/models/cloud'; + +export const startCloudLogin = invokeIpc('cloud:login'); +export const getCloudUser = invokeIpc('cloud:getUser'); +export const getCloudPolicy = invokeIpc('cloud:getPolicy'); From 90cdfc6189a8b301d51c902c2cc504c04ac7d989 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:36:57 +0300 Subject: [PATCH 09/49] chore: add Cloud svg icons --- src/assets/CloudIcon.svg | 14 ++++++ src/assets/CloudSync.svg | 101 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100644 src/assets/CloudIcon.svg create mode 100644 src/assets/CloudSync.svg diff --git a/src/assets/CloudIcon.svg b/src/assets/CloudIcon.svg new file mode 100644 index 0000000000..254e144f15 --- /dev/null +++ b/src/assets/CloudIcon.svg @@ -0,0 +1,14 @@ + + + + diff --git a/src/assets/CloudSync.svg b/src/assets/CloudSync.svg new file mode 100644 index 0000000000..67219002df --- /dev/null +++ b/src/assets/CloudSync.svg @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 188689c6dfbc6c82a4a25a43c056cfd34021b42c Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:37:52 +0300 Subject: [PATCH 10/49] refactor: validation services --- src/redux/validation/validation.hooks.ts | 68 +++++++++++++++++++++++ src/redux/validation/validation.slice.ts | 9 +++ src/redux/validation/validation.thunks.ts | 7 ++- 3 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 src/redux/validation/validation.hooks.ts diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts new file mode 100644 index 0000000000..c19c296b38 --- /dev/null +++ b/src/redux/validation/validation.hooks.ts @@ -0,0 +1,68 @@ +import {useCallback, useState} from 'react'; +import {useStore} from 'react-redux'; +import {useAsync, useInterval} from 'react-use'; + +import {isEqual} from 'lodash'; +import {Store} from 'redux'; + +import {getCloudPolicy, getCloudUser, startCloudLogin} from '@redux/cloud/ipc'; + +import {ROOT_FILE_ENTRY} from '@shared/constants/fileEntry'; +import {CloudUser} from '@shared/models/cloud'; +import {RootState} from '@shared/models/rootState'; + +import {setCloudPolicy} from './validation.slice'; + +const pollCloudPolicy = async (store: Store) => { + const rootFileEntry = store.getState().main.fileMap[ROOT_FILE_ENTRY]; + const rootFolderPath = rootFileEntry?.filePath; + const cloudPolicy = rootFolderPath ? await getCloudPolicy(rootFolderPath) : undefined; + + if (!cloudPolicy) { + return; + } + + const previousCloudPolicy = store.getState().validation.cloudPolicy; + + if (previousCloudPolicy && isEqual(previousCloudPolicy, cloudPolicy)) { + return; + } + + store.dispatch(setCloudPolicy(cloudPolicy)); +}; + +export const useCloudPolicy = () => { + const store = useStore(); + const foundPolicy = store.getState().validation.cloudPolicy !== undefined; + useInterval(() => { + pollCloudPolicy(store); + }, 60 * 1000); + return {foundPolicy}; +}; + +export const useCloudUser = () => { + const [isInitializing, setIsInitializing] = useState(false); + const [isConnecting, setIsConnecting] = useState(false); + const [cloudUser, setCloudUser] = useState(); + + useAsync(async () => { + setIsInitializing(true); + const user = await getCloudUser(undefined); + setCloudUser(user); + setIsInitializing(false); + }, []); + + const connect = useCallback(async () => { + setIsConnecting(true); + const {user} = await startCloudLogin(undefined); + setCloudUser(user); + setIsConnecting(false); + }, []); + + return { + connect, + cloudUser, + isInitializing, + isConnecting, + }; +}; diff --git a/src/redux/validation/validation.slice.ts b/src/redux/validation/validation.slice.ts index ff746c5997..26f55df162 100644 --- a/src/redux/validation/validation.slice.ts +++ b/src/redux/validation/validation.slice.ts @@ -7,6 +7,7 @@ import {stopClusterConnection} from '@redux/thunks/cluster'; import {setRootFolder} from '@redux/thunks/setRootFolder'; import {ValidationFiltersValueType} from '@monokle/components'; +import type {PolicyData} from '@monokle/synchronizer'; import {CORE_PLUGINS, PluginMetadataWithConfig} from '@monokle/validation'; import {SelectedProblem, ValidationState} from '@shared/models/validation'; import {CustomValidationPlugin} from '@shared/models/validationPlugins'; @@ -174,6 +175,10 @@ export const validationSlice = createSlice({ state.config.plugins = pick(state.config.plugins, CORE_PLUGINS); } }, + + setCloudPolicy(state, {payload}: PayloadAction) { + state.cloudPolicy = payload; + }, }, extraReducers: builder => { builder.addCase(setRootFolder.fulfilled, state => { @@ -195,6 +200,9 @@ export const validationSlice = createSlice({ builder.addCase(loadValidation.fulfilled, (state, {payload}) => { state.status = 'loaded'; + if (!payload) { + return; + } state.metadata = payload.metadata; state.rules = payload.rules as any; // See NOTE_TS }); @@ -237,5 +245,6 @@ export const { updateSelectedPluginConfiguration, addValidationPlugin, removeValidationPlugin, + setCloudPolicy, } = validationSlice.actions; export default validationSlice.reducer; diff --git a/src/redux/validation/validation.thunks.ts b/src/redux/validation/validation.thunks.ts index 9ce6f7a5e1..55adcc6836 100644 --- a/src/redux/validation/validation.thunks.ts +++ b/src/redux/validation/validation.thunks.ts @@ -18,11 +18,16 @@ import {isDefined} from '@shared/utils/filter'; import {VALIDATOR} from './validator'; -export const loadValidation = createAsyncThunk( +export const loadValidation = createAsyncThunk( 'validation/load', async (_action, {getState}) => { const state = getState().validation; + if (state.cloudPolicy?.policy && state.cloudPolicy.valid) { + await VALIDATOR.loadValidation({config: state.cloudPolicy.policy}); + return; + } + // Ensure that these plugins are always get loaded. let config = { plugins: Object.fromEntries(CORE_PLUGINS.map(p => [p, false])), From 691a8c7dd112a9a090a2d248884ee2052199b4a8 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:38:05 +0300 Subject: [PATCH 11/49] feat: CloudConnect component --- .../CloudConnect/CloudConnect.styled.tsx | 26 +++++++ .../CloudConnect/CloudConnect.tsx | 71 +++++++++++++++++++ .../SettingsPane/CloudConnect/index.tsx | 1 + 3 files changed, 98 insertions(+) create mode 100644 src/components/organisms/SettingsPane/CloudConnect/CloudConnect.styled.tsx create mode 100644 src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx create mode 100644 src/components/organisms/SettingsPane/CloudConnect/index.tsx diff --git a/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.styled.tsx b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.styled.tsx new file mode 100644 index 0000000000..eeb7a64d1d --- /dev/null +++ b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.styled.tsx @@ -0,0 +1,26 @@ +import {Row as RawRow} from 'antd'; + +import styled from 'styled-components'; + +import {Colors} from '@shared/styles/colors'; + +export const Row = styled(RawRow)` + overflow: hidden; + padding: 24px; + background: linear-gradient(94.81deg, rgba(42, 56, 90, 0.4) 7%, rgba(53, 35, 60, 0.4) 101.38%); +`; + +export const Heading = styled.h1` + font-size: 24px; + font-weight: 700; + color: ${Colors.geekblue8}; +`; + +export const Subheading = styled.h2` + font-weight: 700; + font-size: 14px; +`; + +export const Paragraph = styled.p` + font-size: 12px; +`; diff --git a/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx new file mode 100644 index 0000000000..3982f6d723 --- /dev/null +++ b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx @@ -0,0 +1,71 @@ +import {Button, Col} from 'antd'; + +import {useCloudUser} from '@redux/validation/validation.hooks'; + +import CloudSync from '@assets/CloudSync.svg'; + +import {Spinner} from '@monokle/components'; + +import * as S from './CloudConnect.styled'; + +export default function CloudConnect() { + const {connect, cloudUser, isInitializing, isConnecting} = useCloudUser(); + + if (isInitializing) { + return ( + + + + ); + } + + return ( + + + {cloudUser ? ( + <> + Connected to Monokle Cloud 🟢 + + E-mail: {cloudUser.email} + + + Thank you for syncing Monokle Desktop with Monokle Cloud.
+ Your validation policies are now unified and synchronized across platforms. +
+ + ) : ( + <> + Connect with Monokle Cloud + What is Monokle Cloud? + + Monokle Cloud is our comprehensive cloud-based solution designed to seamlessly synchronize, validate, and + manage your Kubernetes configurations. By working hand-in-hand with Monokle Desktop, it ensures that your + configurations remain consistent and error-free + + Why connect? +
    +
  • + Unified Validation: Ensure that the same validation policies applied in the cloud are consistent with + those in your local projects. +
  • +
  • + Sync Seamlessly: Automatically synchronize and update your validation rules and policies between Monokle + Cloud and Desktop. +
  • +
  • + Collaborate Efficiently: Work in tandem with your team, ensuring everyone adheres to the latest and most + accurate configuration standards. +
  • +
+ + + )} + + + + +
+ ); +} diff --git a/src/components/organisms/SettingsPane/CloudConnect/index.tsx b/src/components/organisms/SettingsPane/CloudConnect/index.tsx new file mode 100644 index 0000000000..a8fe49271f --- /dev/null +++ b/src/components/organisms/SettingsPane/CloudConnect/index.tsx @@ -0,0 +1 @@ +export {default} from './CloudConnect'; From d634e8361f5359361ec68d3e231d73f687f39f17 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:38:15 +0300 Subject: [PATCH 12/49] feat: CloudSync component --- .../PageHeader/CloudSync/CloudSync.tsx | 80 +++++++++++++++++++ .../organisms/PageHeader/CloudSync/index.tsx | 1 + 2 files changed, 81 insertions(+) create mode 100644 src/components/organisms/PageHeader/CloudSync/CloudSync.tsx create mode 100644 src/components/organisms/PageHeader/CloudSync/index.tsx diff --git a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx new file mode 100644 index 0000000000..9f918969b9 --- /dev/null +++ b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx @@ -0,0 +1,80 @@ +import {useCallback} from 'react'; + +import {Button, Dropdown} from 'antd'; + +import styled from 'styled-components'; + +import {useCloudPolicy, useCloudUser} from '@redux/validation/validation.hooks'; + +import CloudIcon from '@assets/CloudIcon.svg'; + +import {Colors} from '@monokle/components'; + +const CloudSync = () => { + const {connect, cloudUser, isConnecting} = useCloudUser(); + const {foundPolicy} = useCloudPolicy(); + + const dropdownRender = useCallback(() => { + if (cloudUser) { + return ( + +

Connected to Monokle Cloud

+ + E-mail: {cloudUser.email} + +

+ {foundPolicy + ? 'Monokle Desktop is now using the Policy that was set for this repository in Monokle Cloud.' + : 'No Policy was found in Monokle Cloud for the current repository.'} +

+
+ ); + } + return ( + +

Not connected to Monokle Cloud.

+ +
+ ); + }, [connect, cloudUser, isConnecting, foundPolicy]); + + return ( + + document.getElementById('monokleCloudSync')!} + > + + +
+ + ); +}; + +export default CloudSync; + +const Container = styled.div` + display: flex; + align-items: center; + border-radius: 4px; + padding: 0.3rem 0.5rem; + background: ${Colors.grey3b}; + border: none; + min-width: fit-content; +`; + +const Image = styled.img` + cursor: pointer; + height: 20px; + width: 20px; +`; + +const DropdownContent = styled.div` + padding: 20px; + margin-top: 10px; + background-color: ${Colors.grey1}; +`; diff --git a/src/components/organisms/PageHeader/CloudSync/index.tsx b/src/components/organisms/PageHeader/CloudSync/index.tsx new file mode 100644 index 0000000000..b93a69bf74 --- /dev/null +++ b/src/components/organisms/PageHeader/CloudSync/index.tsx @@ -0,0 +1 @@ +export {default} from './CloudSync'; From c33aee39bb9d1e334b159d2ea1fe8b9021d6a2bf Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:38:26 +0300 Subject: [PATCH 13/49] refactor: add CloudConnect to SettingsPane --- .../organisms/SettingsPane/SettingsPane.tsx | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/components/organisms/SettingsPane/SettingsPane.tsx b/src/components/organisms/SettingsPane/SettingsPane.tsx index ee72cadcea..c980478885 100644 --- a/src/components/organisms/SettingsPane/SettingsPane.tsx +++ b/src/components/organisms/SettingsPane/SettingsPane.tsx @@ -10,6 +10,7 @@ import {TitleBar} from '@monokle/components'; import {SettingsPanel} from '@shared/models/config'; import ValidationSettings from '../ValidationSettings'; +import CloudConnect from './CloudConnect'; import {CurrentProjectSettings} from './CurrentProjectSettings/CurrentProjectSettings'; import {DefaultProjectSettings} from './DefaultProjectSettings/DefaultProjectSettings'; import {GlobalSettings} from './GlobalSettings/GlobalSettings'; @@ -94,6 +95,18 @@ const SettingsPane = () => { }, ] : []), + + ...[ + { + key: 'cloud-connect', + label: Sync with Cloud, + children: ( + + + + ), + }, + ], ], [activeProject, isInQuickClusterMode, isOnStartProjectPage, isStartProjectPaneVisible] ); From 9294ce9a2b807da98e05aa85bcc1c1b6e0fc5c26 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:38:40 +0300 Subject: [PATCH 14/49] refactor: add CloudSync to PageHeader --- src/components/organisms/PageHeader/PageHeader.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/components/organisms/PageHeader/PageHeader.tsx b/src/components/organisms/PageHeader/PageHeader.tsx index 5872f5e978..ac11e4356d 100644 --- a/src/components/organisms/PageHeader/PageHeader.tsx +++ b/src/components/organisms/PageHeader/PageHeader.tsx @@ -42,6 +42,7 @@ import {Icon} from '@monokle/components'; import {isInClusterModeSelector, isInPreviewModeSelector} from '@shared/utils/selectors'; import {trackEvent} from '@shared/utils/telemetry'; +import CloudSync from './CloudSync'; import {ClusterControls} from './ClusterControl/ClusterControls'; import DownloadProgress from './DownloadProgress'; import {K8sVersionSelection} from './K8sVersionSelection'; @@ -281,6 +282,7 @@ const PageHeader = () => {
+ {isInPreviewMode ? : } From 0df3e16a73f88d7bef831ccaf7736aa506580d2e Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Thu, 24 Aug 2023 12:39:02 +0300 Subject: [PATCH 15/49] refactor: enforce cloud policy --- electron/app/services/cloud/policy.ts | 6 ++--- package-lock.json | 8 +++---- package.json | 2 +- .../ValidationCustom/ValidationCustom.tsx | 17 +++++++++----- .../ValidationOverview/ValidationCard.tsx | 12 +++++++--- src/redux/validation/validation.hooks.ts | 20 +++++++++-------- src/redux/validation/validation.listeners.tsx | 11 ++++++++++ src/redux/validation/validation.selectors.ts | 8 ++++++- src/redux/validation/validation.slice.ts | 3 --- src/redux/validation/validation.thunks.ts | 22 +++++++++---------- 10 files changed, 68 insertions(+), 41 deletions(-) diff --git a/electron/app/services/cloud/policy.ts b/electron/app/services/cloud/policy.ts index 1d94065e6d..6855e5cc62 100644 --- a/electron/app/services/cloud/policy.ts +++ b/electron/app/services/cloud/policy.ts @@ -14,13 +14,13 @@ export const getPolicy = async (repoPath: string) => { } try { - const policy = await synchronizer.synchronize(repoPath, user.token); + const policy = await synchronizer.getPolicy(repoPath, true, user.token); return policy; } catch (e: any) { if (e instanceof Error) { - console.log(e.message); + log.warn(e.message); } - log.error('Failed to synchronize policy'); + log.warn('Failed to synchronize policy'); } return undefined; }; diff --git a/package-lock.json b/package-lock.json index ba3196cf1c..d22b1e1c18 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@dnd-kit/sortable": "7.0.2", "@kubernetes/client-node": "0.18.1", "@monokle/components": "1.7.0", - "@monokle/synchronizer": "^0.3.1", + "@monokle/synchronizer": "^0.4.0", "@monokle/validation": "0.24.2", "@open-policy-agent/opa-wasm": "1.8.0", "@reduxjs/toolkit": "1.9.5", @@ -4703,9 +4703,9 @@ } }, "node_modules/@monokle/synchronizer": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@monokle/synchronizer/-/synchronizer-0.3.1.tgz", - "integrity": "sha512-Fu5/sy2RGz23UedlWxDIbFde2DG+dtNQAm0LF60i/TslALLjqDI2NzTjS0fWUR1Uqa2Ylhm4FdmviU5V0ewqXA==", + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@monokle/synchronizer/-/synchronizer-0.4.0.tgz", + "integrity": "sha512-bkrCvk/vyKX9bmmZyuTP4nMhQ/dPTC7AIhFChkP6RFf9C1kNng2X3Kuz/YsGebVWDRtEjiI5wFM8+oi1Uiu9xQ==", "dependencies": { "@monokle/types": "*", "env-paths": "^2.2.1", diff --git a/package.json b/package.json index c5c71387b0..21970ef23c 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@dnd-kit/sortable": "7.0.2", "@kubernetes/client-node": "0.18.1", "@monokle/components": "1.7.0", - "@monokle/synchronizer": "^0.3.1", + "@monokle/synchronizer": "^0.4.0", "@monokle/validation": "0.24.2", "@open-policy-agent/opa-wasm": "1.8.0", "@reduxjs/toolkit": "1.9.5", diff --git a/src/components/organisms/ValidationSettings/ValidationCustom/ValidationCustom.tsx b/src/components/organisms/ValidationSettings/ValidationCustom/ValidationCustom.tsx index 07b683e833..a5e0126795 100644 --- a/src/components/organisms/ValidationSettings/ValidationCustom/ValidationCustom.tsx +++ b/src/components/organisms/ValidationSettings/ValidationCustom/ValidationCustom.tsx @@ -1,10 +1,11 @@ import {useCallback, useLayoutEffect} from 'react'; -import {Space, Switch, Tooltip} from 'antd'; +import {Button, Space, Switch, Tooltip} from 'antd'; import {TOOLTIP_DELAY} from '@constants/constants'; -import {useAppDispatch} from '@redux/hooks'; +import {useAppDispatch, useAppSelector} from '@redux/hooks'; +import {isUsingCloudPolicySelector} from '@redux/validation/validation.selectors'; import {toggleRule, toggleValidation} from '@redux/validation/validation.slice'; import {PluginMetadataWithConfig} from '@monokle/validation'; @@ -23,6 +24,8 @@ const ValidationCustom: React.FC = props => { const dispatch = useAppDispatch(); + const isUsingCloudPolicy = useAppSelector(isUsingCloudPolicySelector); + const toggleEnabled = useCallback(() => { dispatch(toggleValidation(name)); trackEvent('configure/toggle_validation', {id: name}); @@ -57,13 +60,17 @@ const ValidationCustom: React.FC = props => { Enable plugin - + - Enable all - Disable all + + diff --git a/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCard.tsx b/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCard.tsx index 7c76015a30..d3094afb26 100644 --- a/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCard.tsx +++ b/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCard.tsx @@ -2,8 +2,12 @@ import {shell} from 'electron'; import {useCallback, useState} from 'react'; -import {useAppDispatch} from '@redux/hooks'; -import {pluginRulesSelector, useValidationSelector} from '@redux/validation/validation.selectors'; +import {useAppDispatch, useAppSelector} from '@redux/hooks'; +import { + isUsingCloudPolicySelector, + pluginRulesSelector, + useValidationSelector, +} from '@redux/validation/validation.selectors'; import {toggleValidation, updateSelectedPluginConfiguration} from '@redux/validation/validation.slice'; import {IconNames} from '@monokle/components'; @@ -31,6 +35,8 @@ const ValidationCard: React.FC = ({configurable, plugin}) => { const dispatch = useAppDispatch(); const hasRules = useValidationSelector(s => pluginRulesSelector(s, name).length > 0); + const isUsingCloudPolicy = useAppSelector(isUsingCloudPolicySelector); + const [isChecked, setIsChecked] = useState(enabled); const openLearnMore = useCallback(() => shell.openExternal(learnMoreUrl || ''), [learnMoreUrl]); @@ -65,7 +71,7 @@ const ValidationCard: React.FC = ({configurable, plugin}) => { )} - + ); }; diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index c19c296b38..b422b8f47b 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -1,42 +1,44 @@ import {useCallback, useState} from 'react'; import {useStore} from 'react-redux'; -import {useAsync, useInterval} from 'react-use'; +import {useAsync, useInterval, useMount} from 'react-use'; import {isEqual} from 'lodash'; -import {Store} from 'redux'; import {getCloudPolicy, getCloudUser, startCloudLogin} from '@redux/cloud/ipc'; import {ROOT_FILE_ENTRY} from '@shared/constants/fileEntry'; +import {AppDispatch} from '@shared/models/appDispatch'; import {CloudUser} from '@shared/models/cloud'; import {RootState} from '@shared/models/rootState'; import {setCloudPolicy} from './validation.slice'; -const pollCloudPolicy = async (store: Store) => { - const rootFileEntry = store.getState().main.fileMap[ROOT_FILE_ENTRY]; +export const pollCloudPolicy = async (state: RootState, dispatch: AppDispatch) => { + const rootFileEntry = state.main.fileMap[ROOT_FILE_ENTRY]; const rootFolderPath = rootFileEntry?.filePath; const cloudPolicy = rootFolderPath ? await getCloudPolicy(rootFolderPath) : undefined; + const previousCloudPolicy = state.validation.cloudPolicy; if (!cloudPolicy) { return; } - const previousCloudPolicy = store.getState().validation.cloudPolicy; - if (previousCloudPolicy && isEqual(previousCloudPolicy, cloudPolicy)) { return; } - store.dispatch(setCloudPolicy(cloudPolicy)); + dispatch(setCloudPolicy(cloudPolicy)); }; export const useCloudPolicy = () => { const store = useStore(); const foundPolicy = store.getState().validation.cloudPolicy !== undefined; + useMount(() => { + pollCloudPolicy(store.getState(), store.dispatch); + }); useInterval(() => { - pollCloudPolicy(store); - }, 60 * 1000); + pollCloudPolicy(store.getState(), store.dispatch); + }, 10 * 1000); return {foundPolicy}; }; diff --git a/src/redux/validation/validation.listeners.tsx b/src/redux/validation/validation.listeners.tsx index 850db102c2..0657545540 100644 --- a/src/redux/validation/validation.listeners.tsx +++ b/src/redux/validation/validation.listeners.tsx @@ -50,6 +50,7 @@ import {isDefined} from '@shared/utils/filter'; import {isEqual} from '@shared/utils/isEqual'; import {trackEvent} from '@shared/utils/telemetry'; +import {pollCloudPolicy} from './validation.hooks'; import { addValidationPlugin, changeRuleLevel, @@ -71,6 +72,15 @@ let incrementalValidationStatus: IncrementalValidationStatus = { nextBatch: [], }; +const pullCloudPolicyListener: AppListenerFn = listen => { + listen({ + matcher: isAnyOf(setRootFolder.fulfilled), + async effect(_action, {getState, dispatch}) { + pollCloudPolicy(getState(), dispatch); + }, + }); +}; + const loadListener: AppListenerFn = listen => { listen({ matcher: isAnyOf( @@ -344,4 +354,5 @@ export const validationListeners = [ loadListener, validateListener, incrementalValidationListener, + pullCloudPolicyListener, ]; diff --git a/src/redux/validation/validation.selectors.ts b/src/redux/validation/validation.selectors.ts index ec64e7742b..30a9552525 100644 --- a/src/redux/validation/validation.selectors.ts +++ b/src/redux/validation/validation.selectors.ts @@ -219,7 +219,8 @@ export const activePluginsSelector = createDeepEqualSelector( ); export const pluginEnabledSelector = createDeepEqualSelector( - (state: RootState, id: string) => state.validation.config?.plugins?.[id], + (state: RootState, id: string) => + state.validation.cloudPolicy?.policy?.plugins?.[id] ?? state.validation.config?.plugins?.[id], (_: RootState, id: string) => id, (_config, id): boolean => VALIDATOR.getPlugin(id)?.enabled ?? false ); @@ -280,3 +281,8 @@ export const problemResourceAndRangeSelector = createDeepEqualSelector( return {resourceId, storage, range}; } ); + +export const isUsingCloudPolicySelector = createSelector( + (state: RootState) => state.validation.cloudPolicy, + cloudPolicy => Boolean(cloudPolicy?.policy && cloudPolicy?.valid) +); diff --git a/src/redux/validation/validation.slice.ts b/src/redux/validation/validation.slice.ts index 26f55df162..d50089e13d 100644 --- a/src/redux/validation/validation.slice.ts +++ b/src/redux/validation/validation.slice.ts @@ -200,9 +200,6 @@ export const validationSlice = createSlice({ builder.addCase(loadValidation.fulfilled, (state, {payload}) => { state.status = 'loaded'; - if (!payload) { - return; - } state.metadata = payload.metadata; state.rules = payload.rules as any; // See NOTE_TS }); diff --git a/src/redux/validation/validation.thunks.ts b/src/redux/validation/validation.thunks.ts index 55adcc6836..b33cd271c2 100644 --- a/src/redux/validation/validation.thunks.ts +++ b/src/redux/validation/validation.thunks.ts @@ -9,7 +9,7 @@ import {activeResourceStorageSelector} from '@redux/selectors/resourceMapSelecto import {getResourceKindHandler} from '@src/kindhandlers'; -import {CORE_PLUGINS, ResourceRefType, ValidationResponse} from '@monokle/validation'; +import {CORE_PLUGINS, Config, ResourceRefType, ValidationResponse} from '@monokle/validation'; import {K8sResource, ResourceMeta} from '@shared/models/k8sResource'; import type {ThunkApi} from '@shared/models/thunk'; import type {LoadValidationResult, ValidationArgs, ValidationResource} from '@shared/models/validation'; @@ -18,26 +18,24 @@ import {isDefined} from '@shared/utils/filter'; import {VALIDATOR} from './validator'; -export const loadValidation = createAsyncThunk( +export const loadValidation = createAsyncThunk( 'validation/load', async (_action, {getState}) => { const state = getState().validation; - if (state.cloudPolicy?.policy && state.cloudPolicy.valid) { - await VALIDATOR.loadValidation({config: state.cloudPolicy.policy}); - return; - } - // Ensure that these plugins are always get loaded. - let config = { + let localConfig = { plugins: Object.fromEntries(CORE_PLUGINS.map(p => [p, false])), }; + merge(localConfig, state.config); + electronStore.set('validation.config', localConfig); - merge(config, state.config); - - electronStore.set('validation.config', config); + let cloudConfig: Config | undefined; + if (state.cloudPolicy?.policy && state.cloudPolicy.valid) { + cloudConfig = state.cloudPolicy.policy; + } - await VALIDATOR.loadValidation({config}); + await VALIDATOR.loadValidation({config: cloudConfig ?? localConfig}); return { metadata: VALIDATOR.metadata, From d1a83ba0f83882c7c4d55f9e6e0898bd06acb186 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Thu, 24 Aug 2023 12:53:36 +0300 Subject: [PATCH 16/49] feat: notify policy in overview --- .../ValidationCardPolicy.tsx | 76 +++++++++++++++++++ .../ValidationOverview/ValidationOverview.tsx | 7 +- 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 src/components/organisms/ValidationSettings/ValidationOverview/ValidationCardPolicy.tsx diff --git a/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCardPolicy.tsx b/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCardPolicy.tsx new file mode 100644 index 0000000000..f2fc1b757a --- /dev/null +++ b/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCardPolicy.tsx @@ -0,0 +1,76 @@ +import AntdIcon from '@ant-design/icons'; + +import styled from 'styled-components'; + +import {Colors} from '@shared/styles'; + +const DESCRIPTION = + "Policies add compliancy across your project's repositories by providing consistent validation. Config can no longer be adjusted in this pane. Set up below is read-only."; + +export function ValidationCardPolicy() { + return ( + + + + A Monokle Cloud policy manages this repository + + {DESCRIPTION} + + ); +} + +const CardContainer = styled.div` + border-radius: 2px; + background-color: ${Colors.geekblue4}; + padding: 12px; + display: flex; + flex-direction: column; + gap: 12px; + margin-bottom: 20px; +`; + +const Description = styled.div` + color: ${Colors.grey9}; + line-height: 22px; + + & span { + color: ${Colors.blue7}; + font-weight: 700; + cursor: pointer; + transition: all 0.2s ease-in; + + &:hover { + color: ${Colors.blue6}; + } + } +`; + +const Title = styled.div` + font-weight: 600; + line-height: 22px; + color: ${Colors.whitePure}; +`; + +export function PolicySvg() { + return ( + + + + + + + + + ); +} diff --git a/src/components/organisms/ValidationSettings/ValidationOverview/ValidationOverview.tsx b/src/components/organisms/ValidationSettings/ValidationOverview/ValidationOverview.tsx index 33f538c31b..8336b73f86 100644 --- a/src/components/organisms/ValidationSettings/ValidationOverview/ValidationOverview.tsx +++ b/src/components/organisms/ValidationSettings/ValidationOverview/ValidationOverview.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import {useValidationSelector} from '@redux/validation/validation.selectors'; +import {useAppSelector} from '@redux/hooks'; +import {isUsingCloudPolicySelector, useValidationSelector} from '@redux/validation/validation.selectors'; import {CRD_SCHEMA_INTEGRATION} from '@shared/models/validationPlugins'; @@ -8,14 +9,18 @@ import {VALIDATION_CONFIGURATION_COMPONENTS} from './ConfigurationComponents'; import CustomValidationCard from './CustomValidationCard'; import ValidationCard from './ValidationCard'; import {ValidationCardPlugins} from './ValidationCardPlugins'; +import {ValidationCardPolicy} from './ValidationCardPolicy'; import ValidationCardUpNext from './ValidationCardUpNext'; import * as S from './ValidationOverview.styled'; const ValidationOverview: React.FC = () => { const plugins = useValidationSelector(s => Object.values(s.metadata ?? {})); + const isUsingCloudPolicy = useAppSelector(isUsingCloudPolicySelector); return ( + {isUsingCloudPolicy && } + {plugins.map(plugin => ( Date: Thu, 24 Aug 2023 12:53:57 +0300 Subject: [PATCH 17/49] refactor: small improvements --- .../PageHeader/CloudSync/CloudSync.tsx | 19 ++++++++++++++++--- src/redux/validation/validation.hooks.ts | 6 ++++-- src/redux/validation/validation.listeners.tsx | 4 +++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx index 9f918969b9..97ed4c4b9b 100644 --- a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx +++ b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx @@ -1,6 +1,8 @@ import {useCallback} from 'react'; -import {Button, Dropdown} from 'antd'; +import {Button, Dropdown, Spin} from 'antd'; + +import {LoadingOutlined} from '@ant-design/icons'; import styled from 'styled-components'; @@ -10,11 +12,22 @@ import CloudIcon from '@assets/CloudIcon.svg'; import {Colors} from '@monokle/components'; +const LoadingIcon = ; + const CloudSync = () => { - const {connect, cloudUser, isConnecting} = useCloudUser(); + const {connect, cloudUser, isConnecting, isInitializing} = useCloudUser(); const {foundPolicy} = useCloudPolicy(); const dropdownRender = useCallback(() => { + if (isInitializing) { + return ( + + + Initializing... + + ); + } + if (cloudUser) { return ( @@ -38,7 +51,7 @@ const CloudSync = () => { ); - }, [connect, cloudUser, isConnecting, foundPolicy]); + }, [connect, cloudUser, isConnecting, foundPolicy, isInitializing]); return ( diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index b422b8f47b..dfd588ec39 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -5,6 +5,7 @@ import {useAsync, useInterval, useMount} from 'react-use'; import {isEqual} from 'lodash'; import {getCloudPolicy, getCloudUser, startCloudLogin} from '@redux/cloud/ipc'; +import {useAppSelector} from '@redux/hooks'; import {ROOT_FILE_ENTRY} from '@shared/constants/fileEntry'; import {AppDispatch} from '@shared/models/appDispatch'; @@ -32,13 +33,14 @@ export const pollCloudPolicy = async (state: RootState, dispatch: AppDispatch) = export const useCloudPolicy = () => { const store = useStore(); - const foundPolicy = store.getState().validation.cloudPolicy !== undefined; + const foundPolicy = useAppSelector(state => state.validation.cloudPolicy !== undefined); + useMount(() => { pollCloudPolicy(store.getState(), store.dispatch); }); useInterval(() => { pollCloudPolicy(store.getState(), store.dispatch); - }, 10 * 1000); + }, 30 * 1000); return {foundPolicy}; }; diff --git a/src/redux/validation/validation.listeners.tsx b/src/redux/validation/validation.listeners.tsx index 0657545540..24f341bdd1 100644 --- a/src/redux/validation/validation.listeners.tsx +++ b/src/redux/validation/validation.listeners.tsx @@ -55,6 +55,7 @@ import { addValidationPlugin, changeRuleLevel, removeValidationPlugin, + setCloudPolicy, setConfigK8sSchemaVersion, toggleRule, toggleValidation, @@ -91,7 +92,8 @@ const loadListener: AppListenerFn = listen => { toggleValidation, changeRuleLevel, addValidationPlugin, - removeValidationPlugin + removeValidationPlugin, + setCloudPolicy ), async effect(_action, {dispatch, delay, signal, cancelActiveListeners}) { trackEvent('validation/load_config', {actionType: _action.type}); From 7dd8d4e7e35a88c70e4a8293f5cc43d1ce834181 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Fri, 25 Aug 2023 10:00:21 +0300 Subject: [PATCH 18/49] feat: Cloud disconnect --- electron/app/services/cloud/ipc.ts | 3 ++- electron/app/services/cloud/login.ts | 5 +++++ .../SettingsPane/CloudConnect/CloudConnect.tsx | 13 +++++++++++-- src/redux/cloud/ipc.ts | 1 + src/redux/validation/validation.hooks.ts | 12 +++++++++++- 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/electron/app/services/cloud/ipc.ts b/electron/app/services/cloud/ipc.ts index 9c48c28c47..6098aff45f 100644 --- a/electron/app/services/cloud/ipc.ts +++ b/electron/app/services/cloud/ipc.ts @@ -1,8 +1,9 @@ import {handleIpc} from '../../utils/ipc'; -import {cloudLogin} from './login'; +import {cloudLogin, cloudLogout} from './login'; import {getPolicy} from './policy'; import {getUser} from './user'; handleIpc('cloud:login', cloudLogin); +handleIpc('cloud:logout', cloudLogout); handleIpc('cloud:getUser', getUser); handleIpc('cloud:getPolicy', getPolicy); diff --git a/electron/app/services/cloud/login.ts b/electron/app/services/cloud/login.ts index 4cf7e5f7db..fde7fe4891 100644 --- a/electron/app/services/cloud/login.ts +++ b/electron/app/services/cloud/login.ts @@ -21,3 +21,8 @@ export const cloudLogin = async (): Promise => { } return {user: serializeUser(user)}; }; + +export const cloudLogout = async (): Promise => { + const authenticator = await getAuthenticator(); + await authenticator?.logout(); +}; diff --git a/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx index 3982f6d723..26ef580baa 100644 --- a/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx +++ b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx @@ -1,4 +1,4 @@ -import {Button, Col} from 'antd'; +import {Button, Col, Popconfirm} from 'antd'; import {useCloudUser} from '@redux/validation/validation.hooks'; @@ -9,7 +9,7 @@ import {Spinner} from '@monokle/components'; import * as S from './CloudConnect.styled'; export default function CloudConnect() { - const {connect, cloudUser, isInitializing, isConnecting} = useCloudUser(); + const {connect, disconnect, cloudUser, isInitializing, isConnecting, isDisconnecting} = useCloudUser(); if (isInitializing) { return ( @@ -32,6 +32,15 @@ export default function CloudConnect() { Thank you for syncing Monokle Desktop with Monokle Cloud.
Your validation policies are now unified and synchronized across platforms. + + + ) : ( <> diff --git a/src/redux/cloud/ipc.ts b/src/redux/cloud/ipc.ts index 37d17e99fd..61e9ec803c 100644 --- a/src/redux/cloud/ipc.ts +++ b/src/redux/cloud/ipc.ts @@ -4,5 +4,6 @@ import type {PolicyData} from '@monokle/synchronizer'; import {CloudLoginResponse, CloudUser} from '@shared/models/cloud'; export const startCloudLogin = invokeIpc('cloud:login'); +export const logoutFromCloud = invokeIpc('cloud:logout'); export const getCloudUser = invokeIpc('cloud:getUser'); export const getCloudPolicy = invokeIpc('cloud:getPolicy'); diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index dfd588ec39..f1330f7109 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -4,7 +4,7 @@ import {useAsync, useInterval, useMount} from 'react-use'; import {isEqual} from 'lodash'; -import {getCloudPolicy, getCloudUser, startCloudLogin} from '@redux/cloud/ipc'; +import {getCloudPolicy, getCloudUser, logoutFromCloud, startCloudLogin} from '@redux/cloud/ipc'; import {useAppSelector} from '@redux/hooks'; import {ROOT_FILE_ENTRY} from '@shared/constants/fileEntry'; @@ -47,6 +47,7 @@ export const useCloudPolicy = () => { export const useCloudUser = () => { const [isInitializing, setIsInitializing] = useState(false); const [isConnecting, setIsConnecting] = useState(false); + const [isDisconnecting, setIsDisconnecting] = useState(false); const [cloudUser, setCloudUser] = useState(); useAsync(async () => { @@ -63,10 +64,19 @@ export const useCloudUser = () => { setIsConnecting(false); }, []); + const disconnect = useCallback(async () => { + setIsDisconnecting(true); + await logoutFromCloud(undefined); + setCloudUser(undefined); + setIsDisconnecting(false); + }, []); + return { connect, + disconnect, cloudUser, isInitializing, isConnecting, + isDisconnecting, }; }; From b6cc53cb96c6cddf3b6f8bc2f2923519099d033e Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Fri, 25 Aug 2023 15:47:09 +0300 Subject: [PATCH 19/49] feat: display cloud project for policy --- electron/app/services/cloud/ipc.ts | 2 ++ electron/app/services/cloud/policy.ts | 4 +-- electron/app/services/cloud/project.ts | 20 +++++++++++ package-lock.json | 8 ++--- package.json | 2 +- .../PageHeader/CloudSync/CloudSync.tsx | 35 +++++++++++++------ .../ValidationCustom/useValidationTable.tsx | 11 +++--- src/redux/cloud/ipc.ts | 5 +-- src/redux/validation/validation.hooks.ts | 30 +++++++++++++--- src/redux/validation/validation.listeners.tsx | 11 ------ src/redux/validation/validation.slice.ts | 1 + 11 files changed, 90 insertions(+), 39 deletions(-) create mode 100644 electron/app/services/cloud/project.ts diff --git a/electron/app/services/cloud/ipc.ts b/electron/app/services/cloud/ipc.ts index 6098aff45f..f8d87b3fbc 100644 --- a/electron/app/services/cloud/ipc.ts +++ b/electron/app/services/cloud/ipc.ts @@ -1,9 +1,11 @@ import {handleIpc} from '../../utils/ipc'; import {cloudLogin, cloudLogout} from './login'; import {getPolicy} from './policy'; +import {getProjectInfo} from './project'; import {getUser} from './user'; handleIpc('cloud:login', cloudLogin); handleIpc('cloud:logout', cloudLogout); handleIpc('cloud:getUser', getUser); handleIpc('cloud:getPolicy', getPolicy); +handleIpc('cloud:getProjectInfo', getProjectInfo); diff --git a/electron/app/services/cloud/policy.ts b/electron/app/services/cloud/policy.ts index 6855e5cc62..783b925504 100644 --- a/electron/app/services/cloud/policy.ts +++ b/electron/app/services/cloud/policy.ts @@ -10,7 +10,7 @@ export const getPolicy = async (repoPath: string) => { const user = await authenticator?.getUser(); if (!user?.token || !synchronizer) { - return undefined; + return null; } try { @@ -22,5 +22,5 @@ export const getPolicy = async (repoPath: string) => { } log.warn('Failed to synchronize policy'); } - return undefined; + return null; }; diff --git a/electron/app/services/cloud/project.ts b/electron/app/services/cloud/project.ts new file mode 100644 index 0000000000..938da6430d --- /dev/null +++ b/electron/app/services/cloud/project.ts @@ -0,0 +1,20 @@ +import {getAuthenticator} from './authenticator'; +import {getSynchronizer} from './synchronizer'; + +export const getProjectInfo = async (repoPath: string) => { + const authenticator = await getAuthenticator(); + const synchronizer = await getSynchronizer(); + + const user = await authenticator?.getUser(); + + if (!user?.token || !synchronizer) { + return null; + } + + try { + const project = await synchronizer?.getProjectInfo(repoPath, user.token, true); + return project; + } catch { + return null; + } +}; diff --git a/package-lock.json b/package-lock.json index d22b1e1c18..63151e60da 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,7 @@ "@dnd-kit/sortable": "7.0.2", "@kubernetes/client-node": "0.18.1", "@monokle/components": "1.7.0", - "@monokle/synchronizer": "^0.4.0", + "@monokle/synchronizer": "^0.6.0", "@monokle/validation": "0.24.2", "@open-policy-agent/opa-wasm": "1.8.0", "@reduxjs/toolkit": "1.9.5", @@ -4703,9 +4703,9 @@ } }, "node_modules/@monokle/synchronizer": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/@monokle/synchronizer/-/synchronizer-0.4.0.tgz", - "integrity": "sha512-bkrCvk/vyKX9bmmZyuTP4nMhQ/dPTC7AIhFChkP6RFf9C1kNng2X3Kuz/YsGebVWDRtEjiI5wFM8+oi1Uiu9xQ==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@monokle/synchronizer/-/synchronizer-0.6.0.tgz", + "integrity": "sha512-CoFzrikvXUOa2PEzsoegERHN1OZ+mNzXfup1FJvNG59VvWTJ2pFZNppfzM2pJMmp07FiHqads2T4yFOWn5Cl9A==", "dependencies": { "@monokle/types": "*", "env-paths": "^2.2.1", diff --git a/package.json b/package.json index 21970ef23c..cc20717a2d 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,7 @@ "@dnd-kit/sortable": "7.0.2", "@kubernetes/client-node": "0.18.1", "@monokle/components": "1.7.0", - "@monokle/synchronizer": "^0.4.0", + "@monokle/synchronizer": "^0.6.0", "@monokle/validation": "0.24.2", "@open-policy-agent/opa-wasm": "1.8.0", "@reduxjs/toolkit": "1.9.5", diff --git a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx index 97ed4c4b9b..acfaa5fc9b 100644 --- a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx +++ b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx @@ -16,7 +16,7 @@ const LoadingIcon = ; const CloudSync = () => { const {connect, cloudUser, isConnecting, isInitializing} = useCloudUser(); - const {foundPolicy} = useCloudPolicy(); + const {cloudPolicy, projectInfo} = useCloudPolicy(); const dropdownRender = useCallback(() => { if (isInitializing) { @@ -32,12 +32,19 @@ const CloudSync = () => { return (

Connected to Monokle Cloud

- +

E-mail: {cloudUser.email} - +

+ {cloudPolicy && projectInfo ? ( +

+ Project: {projectInfo.name} +

+ ) : ( +

Project: Not found

+ )}

- {foundPolicy - ? 'Monokle Desktop is now using the Policy that was set for this repository in Monokle Cloud.' + {cloudPolicy + ? 'Monokle Desktop is using the Policy from the Monokle Cloud project.' : 'No Policy was found in Monokle Cloud for the current repository.'}

@@ -51,17 +58,20 @@ const CloudSync = () => { ); - }, [connect, cloudUser, isConnecting, foundPolicy, isInitializing]); + }, [connect, cloudUser, isConnecting, cloudPolicy, isInitializing, projectInfo]); return ( - + document.getElementById('monokleCloudSync')!} > - +
+ + {projectInfo && {projectInfo.name}} +
@@ -70,11 +80,11 @@ const CloudSync = () => { export default CloudSync; -const Container = styled.div` +const Container = styled.div<{$hasText: boolean}>` display: flex; align-items: center; border-radius: 4px; - padding: 0.3rem 0.5rem; + padding: 0 0.5rem; background: ${Colors.grey3b}; border: none; min-width: fit-content; @@ -91,3 +101,8 @@ const DropdownContent = styled.div` margin-top: 10px; background-color: ${Colors.grey1}; `; + +const ProjectName = styled.span` + margin-left: 4px; + cursor: pointer; +`; diff --git a/src/components/organisms/ValidationSettings/ValidationCustom/useValidationTable.tsx b/src/components/organisms/ValidationSettings/ValidationCustom/useValidationTable.tsx index 71692e7a13..02803d930d 100644 --- a/src/components/organisms/ValidationSettings/ValidationCustom/useValidationTable.tsx +++ b/src/components/organisms/ValidationSettings/ValidationCustom/useValidationTable.tsx @@ -7,7 +7,8 @@ import styled from 'styled-components'; import {TOOLTIP_DELAY} from '@constants/constants'; -import {useAppDispatch} from '@redux/hooks'; +import {useAppDispatch, useAppSelector} from '@redux/hooks'; +import {isUsingCloudPolicySelector} from '@redux/validation/validation.selectors'; import {changeRuleLevel, toggleRule} from '@redux/validation/validation.slice'; import {Icon, IconNames} from '@monokle/components'; @@ -24,6 +25,8 @@ const VALIDATION_HIDING_LABELS_WIDTH = 450; export function useValidationTable(plugin: PluginMetadataWithConfig, width: number) { const dispatch = useAppDispatch(); + const isUsingCloudPolicy = useAppSelector(isUsingCloudPolicySelector); + const handleToggle = useCallback( (rule: Rule) => { dispatch(toggleRule({plugin: plugin.name, rule: rule.name})); @@ -91,14 +94,14 @@ export function useValidationTable(plugin: PluginMetadataWithConfig, width: numb return ( handleToggle(rule)} /> @@ -109,7 +112,7 @@ export function useValidationTable(plugin: PluginMetadataWithConfig, width: numb }), }, ]; - }, [width, plugin.configuration.enabled, changeLevel, handleToggle]); + }, [width, plugin.configuration.enabled, changeLevel, handleToggle, isUsingCloudPolicy]); return columns; } diff --git a/src/redux/cloud/ipc.ts b/src/redux/cloud/ipc.ts index 61e9ec803c..16147b6843 100644 --- a/src/redux/cloud/ipc.ts +++ b/src/redux/cloud/ipc.ts @@ -1,9 +1,10 @@ import {invokeIpc} from '@utils/ipc'; -import type {PolicyData} from '@monokle/synchronizer'; +import type {PolicyData, ProjectInfo} from '@monokle/synchronizer'; import {CloudLoginResponse, CloudUser} from '@shared/models/cloud'; export const startCloudLogin = invokeIpc('cloud:login'); export const logoutFromCloud = invokeIpc('cloud:logout'); export const getCloudUser = invokeIpc('cloud:getUser'); -export const getCloudPolicy = invokeIpc('cloud:getPolicy'); +export const getCloudPolicy = invokeIpc('cloud:getPolicy'); +export const getCloudProjectInfo = invokeIpc('cloud:getProjectInfo'); diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index f1330f7109..3ff11d325f 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -1,12 +1,14 @@ -import {useCallback, useState} from 'react'; +import {useCallback, useEffect, useState} from 'react'; import {useStore} from 'react-redux'; import {useAsync, useInterval, useMount} from 'react-use'; import {isEqual} from 'lodash'; -import {getCloudPolicy, getCloudUser, logoutFromCloud, startCloudLogin} from '@redux/cloud/ipc'; +import {getCloudPolicy, getCloudProjectInfo, getCloudUser, logoutFromCloud, startCloudLogin} from '@redux/cloud/ipc'; import {useAppSelector} from '@redux/hooks'; +import {rootFolderSelector} from '@redux/selectors'; +import {ProjectInfo} from '@monokle/synchronizer'; import {ROOT_FILE_ENTRY} from '@shared/constants/fileEntry'; import {AppDispatch} from '@shared/models/appDispatch'; import {CloudUser} from '@shared/models/cloud'; @@ -20,6 +22,8 @@ export const pollCloudPolicy = async (state: RootState, dispatch: AppDispatch) = const cloudPolicy = rootFolderPath ? await getCloudPolicy(rootFolderPath) : undefined; const previousCloudPolicy = state.validation.cloudPolicy; + console.log('POLL CLOUD POLICY'); + if (!cloudPolicy) { return; } @@ -33,15 +37,31 @@ export const pollCloudPolicy = async (state: RootState, dispatch: AppDispatch) = export const useCloudPolicy = () => { const store = useStore(); - const foundPolicy = useAppSelector(state => state.validation.cloudPolicy !== undefined); + const cloudPolicy = useAppSelector(state => state.validation.cloudPolicy); + const rootFolderPath = useAppSelector(rootFolderSelector); + const [projectInfo, setProjectInfo] = useState(); + + const updateProjectInfo = useCallback(async () => { + const info = await getCloudProjectInfo(rootFolderPath); + setProjectInfo(info); + }, [rootFolderPath]); useMount(() => { pollCloudPolicy(store.getState(), store.dispatch); + updateProjectInfo(); }); + + useEffect(() => { + pollCloudPolicy(store.getState(), store.dispatch); + updateProjectInfo(); + }, [store, rootFolderPath, updateProjectInfo]); + useInterval(() => { pollCloudPolicy(store.getState(), store.dispatch); - }, 30 * 1000); - return {foundPolicy}; + updateProjectInfo(); + }, 10 * 1000); + + return {cloudPolicy, projectInfo}; }; export const useCloudUser = () => { diff --git a/src/redux/validation/validation.listeners.tsx b/src/redux/validation/validation.listeners.tsx index 24f341bdd1..bb56d12c7e 100644 --- a/src/redux/validation/validation.listeners.tsx +++ b/src/redux/validation/validation.listeners.tsx @@ -50,7 +50,6 @@ import {isDefined} from '@shared/utils/filter'; import {isEqual} from '@shared/utils/isEqual'; import {trackEvent} from '@shared/utils/telemetry'; -import {pollCloudPolicy} from './validation.hooks'; import { addValidationPlugin, changeRuleLevel, @@ -73,15 +72,6 @@ let incrementalValidationStatus: IncrementalValidationStatus = { nextBatch: [], }; -const pullCloudPolicyListener: AppListenerFn = listen => { - listen({ - matcher: isAnyOf(setRootFolder.fulfilled), - async effect(_action, {getState, dispatch}) { - pollCloudPolicy(getState(), dispatch); - }, - }); -}; - const loadListener: AppListenerFn = listen => { listen({ matcher: isAnyOf( @@ -356,5 +346,4 @@ export const validationListeners = [ loadListener, validateListener, incrementalValidationListener, - pullCloudPolicyListener, ]; diff --git a/src/redux/validation/validation.slice.ts b/src/redux/validation/validation.slice.ts index d50089e13d..451428e108 100644 --- a/src/redux/validation/validation.slice.ts +++ b/src/redux/validation/validation.slice.ts @@ -184,6 +184,7 @@ export const validationSlice = createSlice({ builder.addCase(setRootFolder.fulfilled, state => { state.validationOverview.selectedProblem = undefined; state.lastResponse = undefined; + state.cloudPolicy = undefined; state.validationOverview.newProblemsIntroducedType = 'initial'; }); From 0b15fbad815442479ee6c487066d20568e7e9b63 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Fri, 25 Aug 2023 15:59:43 +0300 Subject: [PATCH 20/49] chore: add telemetry --- src/redux/validation/validation.hooks.ts | 17 ++++++++++++++--- src/shared/models/telemetry.ts | 3 +++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index 3ff11d325f..17e180ad11 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -13,17 +13,21 @@ import {ROOT_FILE_ENTRY} from '@shared/constants/fileEntry'; import {AppDispatch} from '@shared/models/appDispatch'; import {CloudUser} from '@shared/models/cloud'; import {RootState} from '@shared/models/rootState'; +import {trackEvent} from '@shared/utils'; import {setCloudPolicy} from './validation.slice'; +/** + * Used as a telemetry cache to avoid sending multiple events for the same project + */ +const cloudProjectsThisSession = new Set(); + export const pollCloudPolicy = async (state: RootState, dispatch: AppDispatch) => { const rootFileEntry = state.main.fileMap[ROOT_FILE_ENTRY]; const rootFolderPath = rootFileEntry?.filePath; const cloudPolicy = rootFolderPath ? await getCloudPolicy(rootFolderPath) : undefined; const previousCloudPolicy = state.validation.cloudPolicy; - console.log('POLL CLOUD POLICY'); - if (!cloudPolicy) { return; } @@ -44,7 +48,12 @@ export const useCloudPolicy = () => { const updateProjectInfo = useCallback(async () => { const info = await getCloudProjectInfo(rootFolderPath); setProjectInfo(info); - }, [rootFolderPath]); + + if (cloudPolicy && info && !cloudProjectsThisSession.has(info.slug)) { + trackEvent('cloud_sync/policy', {projectSlug: info.slug}); + cloudProjectsThisSession.add(info.slug); + } + }, [rootFolderPath, cloudPolicy]); useMount(() => { pollCloudPolicy(store.getState(), store.dispatch); @@ -80,6 +89,7 @@ export const useCloudUser = () => { const connect = useCallback(async () => { setIsConnecting(true); const {user} = await startCloudLogin(undefined); + trackEvent('cloud_sync/login'); setCloudUser(user); setIsConnecting(false); }, []); @@ -87,6 +97,7 @@ export const useCloudUser = () => { const disconnect = useCallback(async () => { setIsDisconnecting(true); await logoutFromCloud(undefined); + trackEvent('cloud_sync/logout'); setCloudUser(undefined); setIsDisconnecting(false); }, []); diff --git a/src/shared/models/telemetry.ts b/src/shared/models/telemetry.ts index 73f6007c9b..e4f02128a5 100644 --- a/src/shared/models/telemetry.ts +++ b/src/shared/models/telemetry.ts @@ -195,6 +195,9 @@ export type EventMap = { 'project_summary/new_empty_resource': undefined; 'project_summary/new_ai_resource': undefined; 'project_summary/select_explorer_section': {section: string}; + 'cloud_sync/login': undefined; + 'cloud_sync/logout': undefined; + 'cloud_sync/policy': {projectSlug: string}; }; export const APP_INSTALLED = 'APP_INSTALLED'; From 2519e7cf9e90affd4f8a40fd92c36abe43a8d97e Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 11 Sep 2023 14:55:04 +0300 Subject: [PATCH 21/49] fix: get not-namespaced cluster resources --- .../thunks/cluster/loadClusterResources.ts | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/redux/thunks/cluster/loadClusterResources.ts b/src/redux/thunks/cluster/loadClusterResources.ts index ec487f7a59..ec8aa1e2b6 100644 --- a/src/redux/thunks/cluster/loadClusterResources.ts +++ b/src/redux/thunks/cluster/loadClusterResources.ts @@ -26,18 +26,25 @@ import {trackEvent} from '@shared/utils/telemetry'; import {findDefaultVersionForCRD} from './findDefaultVersionForCRD'; const getNonCustomClusterObjects = async (kc: any, namespace?: string, allNamespaces?: boolean) => { + const registeredHandlers = getRegisteredKindHandlers(); + const filteredHandlers = registeredHandlers.filter(handler => { + if (handler.isCustom) { + return false; + } + if (allNamespaces) { + return true; + } + if (namespace === '') { + return !handler.isNamespaced; + } + return handler.isNamespaced; + }); return Promise.allSettled( - getRegisteredKindHandlers() - .filter( - handler => - !handler.isCustom && - (allNamespaces ? true : namespace === '' ? !handler.isNamespaced : handler.isNamespaced) - ) - .map(resourceKindHandler => - resourceKindHandler - .listResourcesInCluster(kc, {namespace}) - .then(items => getK8sObjectsAsYaml(items, resourceKindHandler.kind, resourceKindHandler.clusterApiVersion)) - ) + filteredHandlers.map(resourceKindHandler => + resourceKindHandler + .listResourcesInCluster(kc, {namespace}) + .then(items => getK8sObjectsAsYaml(items, resourceKindHandler.kind, resourceKindHandler.clusterApiVersion)) + ) ); }; @@ -121,8 +128,6 @@ const loadClusterResourcesHandler = async ( if (currentNamespace === '') { results = await getNonCustomClusterObjects(kc, undefined, true); - } else if (currentNamespace === '') { - results = await getNonCustomClusterObjects(kc); } else { results = await getNonCustomClusterObjects(kc, currentNamespace); } From 71973d297775f0a70053cb5f3fecff5b52d147e8 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 11 Sep 2023 14:58:55 +0300 Subject: [PATCH 22/49] fix: helm error when not-namespaced selected --- src/redux/thunks/cluster/loadClusterHelmReleases.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/redux/thunks/cluster/loadClusterHelmReleases.ts b/src/redux/thunks/cluster/loadClusterHelmReleases.ts index eb16b25e44..f287a85f8d 100644 --- a/src/redux/thunks/cluster/loadClusterHelmReleases.ts +++ b/src/redux/thunks/cluster/loadClusterHelmReleases.ts @@ -18,7 +18,10 @@ export const loadClusterHelmReleases = createAsyncThunk', '')}) + listHelmReleasesCommand({ + filter: helmRepoSearch, + namespace: selectedNamespace?.replace('', '').replace('', ''), + }) ); if (result.stderr) { dispatch(setAlert(errorAlert("Couldn't load cluster helm releases", result.stderr))); From 478ff3a0dd29652181c7b1ff5e0f018793f7a049 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:04:41 +0300 Subject: [PATCH 23/49] fix: user expired cloud token --- electron/app/services/cloud/ipc.ts | 4 ++-- electron/app/services/cloud/policy.ts | 7 ++----- electron/app/services/cloud/project.ts | 7 ++----- electron/app/services/cloud/user.ts | 21 ++++++++++++++++++--- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/electron/app/services/cloud/ipc.ts b/electron/app/services/cloud/ipc.ts index f8d87b3fbc..8152a5b016 100644 --- a/electron/app/services/cloud/ipc.ts +++ b/electron/app/services/cloud/ipc.ts @@ -2,10 +2,10 @@ import {handleIpc} from '../../utils/ipc'; import {cloudLogin, cloudLogout} from './login'; import {getPolicy} from './policy'; import {getProjectInfo} from './project'; -import {getUser} from './user'; +import {getSerializedUser} from './user'; handleIpc('cloud:login', cloudLogin); handleIpc('cloud:logout', cloudLogout); -handleIpc('cloud:getUser', getUser); +handleIpc('cloud:getUser', getSerializedUser); handleIpc('cloud:getPolicy', getPolicy); handleIpc('cloud:getProjectInfo', getProjectInfo); diff --git a/electron/app/services/cloud/policy.ts b/electron/app/services/cloud/policy.ts index 783b925504..c52744605a 100644 --- a/electron/app/services/cloud/policy.ts +++ b/electron/app/services/cloud/policy.ts @@ -1,14 +1,11 @@ import log from 'loglevel'; -import {getAuthenticator} from './authenticator'; import {getSynchronizer} from './synchronizer'; +import {getUser} from './user'; export const getPolicy = async (repoPath: string) => { - const authenticator = await getAuthenticator(); const synchronizer = await getSynchronizer(); - - const user = await authenticator?.getUser(); - + const user = await getUser(); if (!user?.token || !synchronizer) { return null; } diff --git a/electron/app/services/cloud/project.ts b/electron/app/services/cloud/project.ts index 938da6430d..95507c7b78 100644 --- a/electron/app/services/cloud/project.ts +++ b/electron/app/services/cloud/project.ts @@ -1,12 +1,9 @@ -import {getAuthenticator} from './authenticator'; import {getSynchronizer} from './synchronizer'; +import {getUser} from './user'; export const getProjectInfo = async (repoPath: string) => { - const authenticator = await getAuthenticator(); const synchronizer = await getSynchronizer(); - - const user = await authenticator?.getUser(); - + const user = await getUser(); if (!user?.token || !synchronizer) { return null; } diff --git a/electron/app/services/cloud/user.ts b/electron/app/services/cloud/user.ts index 97e260a1c7..528118b292 100644 --- a/electron/app/services/cloud/user.ts +++ b/electron/app/services/cloud/user.ts @@ -1,15 +1,30 @@ +import log from 'loglevel'; + import {User} from '@monokle/synchronizer'; import {CloudUser} from '@shared/models/cloud'; import {getAuthenticator} from './authenticator'; -export const getUser = async (): Promise => { +export const getUser = async (): Promise => { const authenticator = await getAuthenticator(); if (!authenticator) { return undefined; } - const user = await authenticator.getUser(); - if (!user.isAuthenticated) { + try { + const user = await authenticator.getUser(); + if (!user.isAuthenticated) { + return undefined; + } + return user; + } catch (e: any) { + log.warn(e.message); + return undefined; + } +}; + +export const getSerializedUser = async (): Promise => { + const user = await getUser(); + if (!user) { return undefined; } try { From 44a58f9868d7cbb8f75e474d4a3f1c0660a889b5 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:35:15 +0300 Subject: [PATCH 24/49] feat: select namespace for dry-run config deploy --- .../ActionsPane/ActionsPaneHeader.tsx | 46 +++++++++++++------ src/redux/thunks/runPreviewConfiguration.ts | 15 +++++- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/components/organisms/ActionsPane/ActionsPaneHeader.tsx b/src/components/organisms/ActionsPane/ActionsPaneHeader.tsx index f46348e636..191d61e7ce 100644 --- a/src/components/organisms/ActionsPane/ActionsPaneHeader.tsx +++ b/src/components/organisms/ActionsPane/ActionsPaneHeader.tsx @@ -1,6 +1,6 @@ -import {useCallback, useMemo} from 'react'; +import {useCallback, useMemo, useState} from 'react'; -import {Button, Dropdown, Modal, Tooltip} from 'antd'; +import {Button, Dropdown, Tooltip} from 'antd'; import {LeftOutlined, RightOutlined} from '@ant-design/icons'; @@ -21,6 +21,7 @@ import {runPreviewConfiguration} from '@redux/thunks/runPreviewConfiguration'; import {selectFromHistory} from '@redux/thunks/selectFromHistory'; import {TitleBarWrapper} from '@components/atoms'; +import {HelmChartModalConfirmWithNamespaceSelect} from '@components/molecules'; import {useRefSelector} from '@utils/hooks'; @@ -50,6 +51,8 @@ const ActionsPaneHeader: React.FC = props => { const selectedHelmConfig = useAppSelector(selectedHelmConfigSelector); const selectedImage = useAppSelector(selectedImageSelector); + const [isHelmChartApplyModalVisible, setIsHelmChartApplyModalVisible] = useState(false); + const onClickEditPreviewConfiguration = useCallback(() => { if (!selectedHelmConfig) { return; @@ -74,18 +77,23 @@ const ActionsPaneHeader: React.FC = props => { dispatch(startPreview({type: 'helm-config', configId: selectedHelmConfig.id})); }, [dispatch, selectedHelmConfig]); - const onClickInstallPreviewConfiguration = useCallback(() => { - Modal.confirm({ - title: 'Install Helm Chart', - content: `Are you sure you want to install the ${selectedHelmConfig?.name} configuration to the cluster?`, - onOk: () => { - if (!selectedHelmConfig) { - return; - } - dispatch(runPreviewConfiguration({helmConfigId: selectedHelmConfig.id, performDeploy: true})); - }, - }); - }, [dispatch, selectedHelmConfig]); + const onConfirmInstallPreviewConfiguration = useCallback( + (selectedNamespace?: string, shouldCreateNamespace?: boolean) => { + if (!selectedHelmConfig) { + return; + } + dispatch( + runPreviewConfiguration({ + helmConfigId: selectedHelmConfig.id, + performDeploy: true, + selectedNamespace, + shouldCreateNamespace, + }) + ); + setIsHelmChartApplyModalVisible(false); + }, + [dispatch, selectedHelmConfig] + ); const onClickLeftArrow = useCallback(() => { dispatch(selectFromHistory('left')); @@ -135,6 +143,14 @@ const ActionsPaneHeader: React.FC = props => { if (selectedHelmConfig) { return ( + { + setIsHelmChartApplyModalVisible(false); + }} + /> = props => { title={InstallPreviewConfigurationTooltip} placement="bottomLeft" > - diff --git a/src/redux/thunks/runPreviewConfiguration.ts b/src/redux/thunks/runPreviewConfiguration.ts index 9a7590dbcf..0f06354b98 100644 --- a/src/redux/thunks/runPreviewConfiguration.ts +++ b/src/redux/thunks/runPreviewConfiguration.ts @@ -36,12 +36,15 @@ export const runPreviewConfiguration = createAsyncThunk< { helmConfigId: string; performDeploy?: boolean; + selectedNamespace?: string; + shouldCreateNamespace?: boolean; }, { dispatch: AppDispatch; state: RootState; } ->('main/runPreviewConfiguration', async ({helmConfigId, performDeploy}, thunkAPI) => { +>('main/runPreviewConfiguration', async (props, thunkAPI) => { + const {helmConfigId, performDeploy, selectedNamespace, shouldCreateNamespace} = props; const startTime = new Date().getTime(); const configState = thunkAPI.getState().config; const mainState = thunkAPI.getState().main; @@ -133,6 +136,16 @@ export const runPreviewConfiguration = createAsyncThunk< env: {KUBECONFIG: kubeconfig.path}, }; + if (selectedNamespace) { + if (!commandOptions.args.some(arg => arg.includes('--namespace'))) { + commandOptions.args.push(...['--namespace', selectedNamespace]); + } + + if (shouldCreateNamespace && !commandOptions.args.some(arg => arg.includes('--create-namespace'))) { + commandOptions.args.push('--create-namespace'); + } + } + const result = await runCommandInMainThread(commandOptions); if (result.error || result.stderr) { From d39168300194c00bb8222e4241fe70d23c9de525 Mon Sep 17 00:00:00 2001 From: Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 12:37:01 +0300 Subject: [PATCH 25/49] Update CODEOWNERS --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 05685a4945..2b46d5492b 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -1,3 +1,3 @@ docs/* @jfermi -* @devcatalin @topliceanurazvan @mortada-codes @olensmar +* @devcatalin @topliceanurazvan @olensmar From ae718717032f7a91df9ffec98902ead75e716ae6 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 13:59:25 +0300 Subject: [PATCH 26/49] refactor: CloudConnect UI --- .../CloudConnect/CloudConnect.tsx | 119 +++++++++--------- .../organisms/SettingsPane/SettingsPane.tsx | 2 +- 2 files changed, 63 insertions(+), 58 deletions(-) diff --git a/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx index 26ef580baa..a5b8586973 100644 --- a/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx +++ b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx @@ -1,4 +1,4 @@ -import {Button, Col, Popconfirm} from 'antd'; +import {Button, Col, Popconfirm, Row} from 'antd'; import {useCloudUser} from '@redux/validation/validation.hooks'; @@ -8,7 +8,8 @@ import {Spinner} from '@monokle/components'; import * as S from './CloudConnect.styled'; -export default function CloudConnect() { +export default function CloudConnect(props: {wide: boolean}) { + const {wide} = props; const {connect, disconnect, cloudUser, isInitializing, isConnecting, isDisconnecting} = useCloudUser(); if (isInitializing) { @@ -20,61 +21,65 @@ export default function CloudConnect() { } return ( - - - {cloudUser ? ( - <> - Connected to Monokle Cloud 🟢 - - E-mail: {cloudUser.email} - - - Thank you for syncing Monokle Desktop with Monokle Cloud.
- Your validation policies are now unified and synchronized across platforms. -
- - - - - ) : ( - <> - Connect with Monokle Cloud - What is Monokle Cloud? - - Monokle Cloud is our comprehensive cloud-based solution designed to seamlessly synchronize, validate, and - manage your Kubernetes configurations. By working hand-in-hand with Monokle Desktop, it ensures that your - configurations remain consistent and error-free - - Why connect? -
    -
  • - Unified Validation: Ensure that the same validation policies applied in the cloud are consistent with - those in your local projects. -
  • -
  • - Sync Seamlessly: Automatically synchronize and update your validation rules and policies between Monokle - Cloud and Desktop. -
  • -
  • - Collaborate Efficiently: Work in tandem with your team, ensuring everyone adheres to the latest and most - accurate configuration standards. -
  • -
- - - )} + + + + + {cloudUser ? ( + <> + Connected to Monokle Cloud 🟢 + + E-mail: {cloudUser.email} + + + Thank you for syncing Monokle Desktop with Monokle Cloud.
+ Your validation policies are now unified and synchronized across platforms. +
+ + + + + ) : ( + <> + Connect with Monokle Cloud + What is Monokle Cloud? + + Monokle Cloud is our comprehensive cloud-based solution designed to seamlessly synchronize, validate, + and manage your Kubernetes configurations. By working hand-in-hand with Monokle Desktop, it ensures + that your configurations remain consistent and error-free + + Why connect? +
    +
  • + Unified Validation: Ensure that the same validation policies applied in the cloud are consistent + with those in your local projects. +
  • +
  • + Sync Seamlessly: Automatically synchronize and update your validation rules and policies between + Monokle Cloud and Desktop. +
  • +
  • + Collaborate Efficiently: Work in tandem with your team, ensuring everyone adheres to the latest and + most accurate configuration standards. +
  • +
+ + + )} + + + + +
- - - -
+ ); } diff --git a/src/components/organisms/SettingsPane/SettingsPane.tsx b/src/components/organisms/SettingsPane/SettingsPane.tsx index c980478885..50e43336b9 100644 --- a/src/components/organisms/SettingsPane/SettingsPane.tsx +++ b/src/components/organisms/SettingsPane/SettingsPane.tsx @@ -102,7 +102,7 @@ const SettingsPane = () => { label: Sync with Cloud, children: ( - + ), }, From cee9eaaf1cd0938143c1209a309738b5db364cc0 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 14:09:17 +0300 Subject: [PATCH 27/49] fix: CloudSync icon UI --- src/assets/CloudIconWhite.svg | 4 ++++ src/components/organisms/PageHeader/CloudSync/CloudSync.tsx | 6 +++--- 2 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 src/assets/CloudIconWhite.svg diff --git a/src/assets/CloudIconWhite.svg b/src/assets/CloudIconWhite.svg new file mode 100644 index 0000000000..761e49df82 --- /dev/null +++ b/src/assets/CloudIconWhite.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx index acfaa5fc9b..5655fcd8ca 100644 --- a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx +++ b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx @@ -9,6 +9,7 @@ import styled from 'styled-components'; import {useCloudPolicy, useCloudUser} from '@redux/validation/validation.hooks'; import CloudIcon from '@assets/CloudIcon.svg'; +import CloudIconWhite from '@assets/CloudIconWhite.svg'; import {Colors} from '@monokle/components'; @@ -61,7 +62,7 @@ const CloudSync = () => { }, [connect, cloudUser, isConnecting, cloudPolicy, isInitializing, projectInfo]); return ( - + { getPopupContainer={() => document.getElementById('monokleCloudSync')!} >
- - {projectInfo && {projectInfo.name}} +
From cd991ebe29287518da36e16a54a6897d6e26f8b9 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 14:16:21 +0300 Subject: [PATCH 28/49] fix: policy hooks --- src/redux/validation/validation.hooks.ts | 11 ++++++----- src/redux/validation/validation.slice.ts | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index 17e180ad11..89121b64f5 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -29,6 +29,7 @@ export const pollCloudPolicy = async (state: RootState, dispatch: AppDispatch) = const previousCloudPolicy = state.validation.cloudPolicy; if (!cloudPolicy) { + dispatch(setCloudPolicy(undefined)); return; } @@ -77,7 +78,7 @@ export const useCloudUser = () => { const [isInitializing, setIsInitializing] = useState(false); const [isConnecting, setIsConnecting] = useState(false); const [isDisconnecting, setIsDisconnecting] = useState(false); - const [cloudUser, setCloudUser] = useState(); + const [cloudUser, setCloudUser] = useState(); useAsync(async () => { setIsInitializing(true); @@ -86,21 +87,21 @@ export const useCloudUser = () => { setIsInitializing(false); }, []); - const connect = useCallback(async () => { + const connect = async () => { setIsConnecting(true); const {user} = await startCloudLogin(undefined); trackEvent('cloud_sync/login'); setCloudUser(user); setIsConnecting(false); - }, []); + }; - const disconnect = useCallback(async () => { + const disconnect = async () => { setIsDisconnecting(true); await logoutFromCloud(undefined); trackEvent('cloud_sync/logout'); setCloudUser(undefined); setIsDisconnecting(false); - }, []); + }; return { connect, diff --git a/src/redux/validation/validation.slice.ts b/src/redux/validation/validation.slice.ts index 451428e108..e988816037 100644 --- a/src/redux/validation/validation.slice.ts +++ b/src/redux/validation/validation.slice.ts @@ -176,7 +176,7 @@ export const validationSlice = createSlice({ } }, - setCloudPolicy(state, {payload}: PayloadAction) { + setCloudPolicy(state, {payload}: PayloadAction) { state.cloudPolicy = payload; }, }, From 0f1ed29b6a5eae8d18095fe8bf64412dbc2794f2 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 15:24:44 +0300 Subject: [PATCH 29/49] refactor: use redux for cloud user --- src/redux/initialState.ts | 4 ++++ src/redux/reducers/cloud.ts | 18 ++++++++++++++++++ src/redux/store.ts | 2 ++ src/redux/validation/validation.hooks.ts | 13 +++++++------ src/shared/models/cloud.ts | 4 ++++ src/shared/models/rootState.ts | 2 ++ 6 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 src/redux/reducers/cloud.ts diff --git a/src/redux/initialState.ts b/src/redux/initialState.ts index 2ee12b58dc..0fbcc6f3a8 100644 --- a/src/redux/initialState.ts +++ b/src/redux/initialState.ts @@ -5,6 +5,7 @@ import {DEFAULT_PANE_CONFIGURATION} from '@constants/constants'; import {PREDEFINED_K8S_VERSION} from '@shared/constants/k8s'; import {AlertState} from '@shared/models/alert'; import {AppState} from '@shared/models/appState'; +import {CloudState} from '@shared/models/cloud'; import {AppConfig, NewVersionCode, SettingsPanel} from '@shared/models/config'; import {ExtensionState} from '@shared/models/extension'; import {TerminalState} from '@shared/models/terminal'; @@ -269,6 +270,8 @@ const initialTerminalState: TerminalState = { terminalsMap: {}, }; +const initialCloudState: CloudState = {}; + export default { alert: initialAlertState, config: initialAppConfigState, @@ -276,4 +279,5 @@ export default { main: initialAppState, terminal: initialTerminalState, ui: initialUiState, + cloud: initialCloudState, }; diff --git a/src/redux/reducers/cloud.ts b/src/redux/reducers/cloud.ts new file mode 100644 index 0000000000..450127cbac --- /dev/null +++ b/src/redux/reducers/cloud.ts @@ -0,0 +1,18 @@ +import {Draft, PayloadAction, createSlice} from '@reduxjs/toolkit'; + +import initialState from '@redux/initialState'; + +import {CloudState, CloudUser} from '@shared/models/cloud'; + +export const cloudSlice = createSlice({ + name: 'cloud', + initialState: initialState.cloud, + reducers: { + setCloudUser: (state: Draft, action: PayloadAction) => { + state.user = action.payload; + }, + }, +}); + +export const {setCloudUser} = cloudSlice.actions; +export default cloudSlice.reducer; diff --git a/src/redux/store.ts b/src/redux/store.ts index 3e40aa80b9..602b8c0ed6 100644 --- a/src/redux/store.ts +++ b/src/redux/store.ts @@ -16,6 +16,7 @@ import {formSlice} from './forms'; import {gitSlice} from './git'; import {combineListeners, listenerMiddleware} from './listeners/base'; import {alertSlice} from './reducers/alert'; +import {cloudSlice} from './reducers/cloud'; import {extensionSlice} from './reducers/extension'; import {mainSlice} from './reducers/main'; import {imageListParserListener} from './reducers/main/mainListeners'; @@ -70,6 +71,7 @@ const appReducer = combineReducers({ dashboard: dashboardSlice.reducer, cluster: clusterSlice.reducer, editor: editorSlice.reducer, + cloud: cloudSlice.reducer, }); const rootReducer: typeof appReducer = (state, action) => { diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index 89121b64f5..b1a54d0dc5 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -5,13 +5,13 @@ import {useAsync, useInterval, useMount} from 'react-use'; import {isEqual} from 'lodash'; import {getCloudPolicy, getCloudProjectInfo, getCloudUser, logoutFromCloud, startCloudLogin} from '@redux/cloud/ipc'; -import {useAppSelector} from '@redux/hooks'; +import {useAppDispatch, useAppSelector} from '@redux/hooks'; +import {setCloudUser} from '@redux/reducers/cloud'; import {rootFolderSelector} from '@redux/selectors'; import {ProjectInfo} from '@monokle/synchronizer'; import {ROOT_FILE_ENTRY} from '@shared/constants/fileEntry'; import {AppDispatch} from '@shared/models/appDispatch'; -import {CloudUser} from '@shared/models/cloud'; import {RootState} from '@shared/models/rootState'; import {trackEvent} from '@shared/utils'; @@ -75,15 +75,16 @@ export const useCloudPolicy = () => { }; export const useCloudUser = () => { + const dispatch = useAppDispatch(); const [isInitializing, setIsInitializing] = useState(false); const [isConnecting, setIsConnecting] = useState(false); const [isDisconnecting, setIsDisconnecting] = useState(false); - const [cloudUser, setCloudUser] = useState(); + const cloudUser = useAppSelector(state => state.cloud.user); useAsync(async () => { setIsInitializing(true); const user = await getCloudUser(undefined); - setCloudUser(user); + dispatch(setCloudUser(user)); setIsInitializing(false); }, []); @@ -91,7 +92,7 @@ export const useCloudUser = () => { setIsConnecting(true); const {user} = await startCloudLogin(undefined); trackEvent('cloud_sync/login'); - setCloudUser(user); + dispatch(setCloudUser(user)); setIsConnecting(false); }; @@ -99,7 +100,7 @@ export const useCloudUser = () => { setIsDisconnecting(true); await logoutFromCloud(undefined); trackEvent('cloud_sync/logout'); - setCloudUser(undefined); + dispatch(setCloudUser(undefined)); setIsDisconnecting(false); }; diff --git a/src/shared/models/cloud.ts b/src/shared/models/cloud.ts index 11b7760f54..4d319d2cca 100644 --- a/src/shared/models/cloud.ts +++ b/src/shared/models/cloud.ts @@ -8,3 +8,7 @@ export type CloudUser = { export type CloudLoginResponse = { user: CloudUser; }; + +export type CloudState = { + user?: CloudUser; +}; diff --git a/src/shared/models/rootState.ts b/src/shared/models/rootState.ts index 1e726e4b32..fe7881f11b 100644 --- a/src/shared/models/rootState.ts +++ b/src/shared/models/rootState.ts @@ -1,5 +1,6 @@ import {AlertState} from './alert'; import {AppState} from './appState'; +import {CloudState} from './cloud'; import {ClusterState} from './clusterState'; import {CompareState} from './compare'; import {AppConfig} from './config'; @@ -28,6 +29,7 @@ type RootState = { validation: ValidationState; dashboard: DashboardState; cluster: ClusterState; + cloud: CloudState; }; type ElectronMenuDataType = { From cf1379c1cdc6843576e079342ae96405bdbf1d0b Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 15:34:23 +0300 Subject: [PATCH 30/49] refactor: get policy deep link --- electron/app/services/cloud/project.ts | 2 +- src/redux/cloud/ipc.ts | 2 +- src/redux/validation/validation.hooks.ts | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/electron/app/services/cloud/project.ts b/electron/app/services/cloud/project.ts index 95507c7b78..73ba5c2cc5 100644 --- a/electron/app/services/cloud/project.ts +++ b/electron/app/services/cloud/project.ts @@ -10,7 +10,7 @@ export const getProjectInfo = async (repoPath: string) => { try { const project = await synchronizer?.getProjectInfo(repoPath, user.token, true); - return project; + return project ? {info: project, link: synchronizer.generateDeepLinkProjectPolicy(project.slug)} : null; } catch { return null; } diff --git a/src/redux/cloud/ipc.ts b/src/redux/cloud/ipc.ts index 16147b6843..775e849f43 100644 --- a/src/redux/cloud/ipc.ts +++ b/src/redux/cloud/ipc.ts @@ -7,4 +7,4 @@ export const startCloudLogin = invokeIpc('cloud:l export const logoutFromCloud = invokeIpc('cloud:logout'); export const getCloudUser = invokeIpc('cloud:getUser'); export const getCloudPolicy = invokeIpc('cloud:getPolicy'); -export const getCloudProjectInfo = invokeIpc('cloud:getProjectInfo'); +export const getCloudProjectInfo = invokeIpc('cloud:getProjectInfo'); diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index b1a54d0dc5..f175491033 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -45,10 +45,12 @@ export const useCloudPolicy = () => { const cloudPolicy = useAppSelector(state => state.validation.cloudPolicy); const rootFolderPath = useAppSelector(rootFolderSelector); const [projectInfo, setProjectInfo] = useState(); + const [policyLink, setPolicyLink] = useState(); const updateProjectInfo = useCallback(async () => { - const info = await getCloudProjectInfo(rootFolderPath); + const {info, link} = (await getCloudProjectInfo(rootFolderPath)) || {}; setProjectInfo(info); + setPolicyLink(link); if (cloudPolicy && info && !cloudProjectsThisSession.has(info.slug)) { trackEvent('cloud_sync/policy', {projectSlug: info.slug}); @@ -71,7 +73,7 @@ export const useCloudPolicy = () => { updateProjectInfo(); }, 10 * 1000); - return {cloudPolicy, projectInfo}; + return {cloudPolicy, projectInfo, policyLink}; }; export const useCloudUser = () => { From 54401a3f534a0901cc9512cc0a346074ac4fe955 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 15:34:41 +0300 Subject: [PATCH 31/49] refactor: CloudSync redesign --- src/assets/CloudSynced.png | Bin 0 -> 4635 bytes src/assets/CloudUnsynced.png | Bin 0 -> 4763 bytes .../PageHeader/CloudSync/CloudSync.tsx | 124 ++++++++++++++---- 3 files changed, 97 insertions(+), 27 deletions(-) create mode 100644 src/assets/CloudSynced.png create mode 100644 src/assets/CloudUnsynced.png diff --git a/src/assets/CloudSynced.png b/src/assets/CloudSynced.png new file mode 100644 index 0000000000000000000000000000000000000000..677b78efc2f7f90a91ef137d8d0cf36941891690 GIT binary patch literal 4635 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 G$^QU>rgY8# literal 0 HcmV?d00001 diff --git a/src/assets/CloudUnsynced.png b/src/assets/CloudUnsynced.png new file mode 100644 index 0000000000000000000000000000000000000000..c0b79f281932794f36067819f07dab353e162028 GIT binary patch literal 4763 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 et$Ia&q; const CloudSync = () => { const {connect, cloudUser, isConnecting, isInitializing} = useCloudUser(); - const {cloudPolicy, projectInfo} = useCloudPolicy(); + const {cloudPolicy, projectInfo, policyLink} = useCloudPolicy(); const dropdownRender = useCallback(() => { if (isInitializing) { @@ -32,34 +37,54 @@ const CloudSync = () => { if (cloudUser) { return ( -

Connected to Monokle Cloud

-

- E-mail: {cloudUser.email} -

- {cloudPolicy && projectInfo ? ( -

- Project: {projectInfo.name} -

- ) : ( -

Project: Not found

- )} -

- {cloudPolicy - ? 'Monokle Desktop is using the Policy from the Monokle Cloud project.' - : 'No Policy was found in Monokle Cloud for the current repository.'} -

+ + + + Connected to Monokle Cloud + + + + + <GreenCircle /> E-mail + + {cloudUser.email} + + + {projectInfo?.name ? <GreenCircle /> : <RedCircle />} Cloud project + {projectInfo?.name || 'Not found'} + + + {cloudPolicy ? <GreenCircle /> : <RedCircle />} Policy + + {cloudPolicy ? ( + openUrlInExternalBrowser(policyLink)} + style={{cursor: 'pointer', color: Colors.blue7}} + > + View project policy + + ) : ( + 'Not found' + )} + +
); } return ( -

Not connected to Monokle Cloud.

+ + + + Not Connected to Monokle Cloud + +
); - }, [connect, cloudUser, isConnecting, cloudPolicy, isInitializing, projectInfo]); + }, [connect, cloudUser, isConnecting, cloudPolicy, isInitializing, projectInfo, policyLink]); return ( @@ -70,7 +95,13 @@ const CloudSync = () => { getPopupContainer={() => document.getElementById('monokleCloudSync')!} >
- + + +
@@ -90,19 +121,58 @@ const Container = styled.div<{$hasText: boolean}>` min-width: fit-content; `; -const Image = styled.img` +const Icon = styled.img` cursor: pointer; height: 20px; width: 20px; `; +const Image = styled.img` + margin-bottom: 8px; + margin-left: -4px; +`; + const DropdownContent = styled.div` padding: 20px; margin-top: 10px; - background-color: ${Colors.grey1}; + background-color: ${Colors.grey2}; `; -const ProjectName = styled.span` - margin-left: 4px; - cursor: pointer; +const GreenSpan = styled.span` + color: ${Colors.polarGreen}; +`; + +const RedSpan = styled.span` + color: ${Colors.red7}; +`; + +const GraySpan = styled.span` + color: ${Colors.grey7}; +`; + +const GreenCircle = styled(CheckCircleFilled)` + color: ${Colors.polarGreen}; +`; + +const RedCircle = styled(CloseCircleFilled)` + color: ${Colors.red7}; +`; + +const Item = styled.div` + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: 8px; +`; + +const Title = styled.div` + width: 110px; + margin-right: 8px; + color: ${Colors.grey7}; +`; + +const Value = styled.div` + flex: 1; + text-align: left; + margin-left: 8px; `; From edbd56643d95eb1fd2cc024119b760363697519e Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 15:56:03 +0300 Subject: [PATCH 32/49] refactor: move cloud project/policy info to redux --- electron/app/services/cloud/ipc.ts | 4 +-- electron/app/services/cloud/project.ts | 11 ++++-- .../PageHeader/CloudSync/CloudSync.tsx | 6 ++-- src/redux/cloud/ipc.ts | 6 ++-- src/redux/reducers/cloud.ts | 11 ++++-- src/redux/validation/validation.hooks.ts | 36 ++++++++++--------- src/shared/models/cloud.ts | 8 +++++ 7 files changed, 54 insertions(+), 28 deletions(-) diff --git a/electron/app/services/cloud/ipc.ts b/electron/app/services/cloud/ipc.ts index 8152a5b016..9bcd315453 100644 --- a/electron/app/services/cloud/ipc.ts +++ b/electron/app/services/cloud/ipc.ts @@ -1,11 +1,11 @@ import {handleIpc} from '../../utils/ipc'; import {cloudLogin, cloudLogout} from './login'; import {getPolicy} from './policy'; -import {getProjectInfo} from './project'; +import {getInfo} from './project'; import {getSerializedUser} from './user'; handleIpc('cloud:login', cloudLogin); handleIpc('cloud:logout', cloudLogout); handleIpc('cloud:getUser', getSerializedUser); handleIpc('cloud:getPolicy', getPolicy); -handleIpc('cloud:getProjectInfo', getProjectInfo); +handleIpc('cloud:getInfo', getInfo); diff --git a/electron/app/services/cloud/project.ts b/electron/app/services/cloud/project.ts index 73ba5c2cc5..78a00eed68 100644 --- a/electron/app/services/cloud/project.ts +++ b/electron/app/services/cloud/project.ts @@ -1,7 +1,12 @@ +import {ProjectInfo} from '@monokle/synchronizer'; +import {CloudPolicyInfo} from '@shared/models/cloud'; + import {getSynchronizer} from './synchronizer'; import {getUser} from './user'; -export const getProjectInfo = async (repoPath: string) => { +export const getInfo = async ( + repoPath: string +): Promise<{projectInfo: ProjectInfo; policyInfo: CloudPolicyInfo} | null> => { const synchronizer = await getSynchronizer(); const user = await getUser(); if (!user?.token || !synchronizer) { @@ -10,7 +15,9 @@ export const getProjectInfo = async (repoPath: string) => { try { const project = await synchronizer?.getProjectInfo(repoPath, user.token, true); - return project ? {info: project, link: synchronizer.generateDeepLinkProjectPolicy(project.slug)} : null; + return project + ? {projectInfo: project, policyInfo: {link: synchronizer.generateDeepLinkProjectPolicy(project.slug)}} + : null; } catch { return null; } diff --git a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx index 37c51ad5c0..f6f51cec38 100644 --- a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx +++ b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx @@ -22,7 +22,7 @@ const LoadingIcon = ; const CloudSync = () => { const {connect, cloudUser, isConnecting, isInitializing} = useCloudUser(); - const {cloudPolicy, projectInfo, policyLink} = useCloudPolicy(); + const {cloudPolicy, projectInfo, policyInfo} = useCloudPolicy(); const dropdownRender = useCallback(() => { if (isInitializing) { @@ -58,7 +58,7 @@ const CloudSync = () => { {cloudPolicy ? ( openUrlInExternalBrowser(policyLink)} + onClick={() => openUrlInExternalBrowser(policyInfo?.link)} style={{cursor: 'pointer', color: Colors.blue7}} > View project policy @@ -84,7 +84,7 @@ const CloudSync = () => { ); - }, [connect, cloudUser, isConnecting, cloudPolicy, isInitializing, projectInfo, policyLink]); + }, [connect, cloudUser, isConnecting, cloudPolicy, isInitializing, projectInfo, policyInfo]); return ( diff --git a/src/redux/cloud/ipc.ts b/src/redux/cloud/ipc.ts index 775e849f43..46f0d99382 100644 --- a/src/redux/cloud/ipc.ts +++ b/src/redux/cloud/ipc.ts @@ -1,10 +1,12 @@ import {invokeIpc} from '@utils/ipc'; import type {PolicyData, ProjectInfo} from '@monokle/synchronizer'; -import {CloudLoginResponse, CloudUser} from '@shared/models/cloud'; +import {CloudLoginResponse, CloudPolicyInfo, CloudUser} from '@shared/models/cloud'; export const startCloudLogin = invokeIpc('cloud:login'); export const logoutFromCloud = invokeIpc('cloud:logout'); export const getCloudUser = invokeIpc('cloud:getUser'); export const getCloudPolicy = invokeIpc('cloud:getPolicy'); -export const getCloudProjectInfo = invokeIpc('cloud:getProjectInfo'); +export const getCloudInfo = invokeIpc( + 'cloud:getInfo' +); diff --git a/src/redux/reducers/cloud.ts b/src/redux/reducers/cloud.ts index 450127cbac..6954ccda12 100644 --- a/src/redux/reducers/cloud.ts +++ b/src/redux/reducers/cloud.ts @@ -2,7 +2,8 @@ import {Draft, PayloadAction, createSlice} from '@reduxjs/toolkit'; import initialState from '@redux/initialState'; -import {CloudState, CloudUser} from '@shared/models/cloud'; +import {ProjectInfo} from '@monokle/synchronizer'; +import {CloudPolicyInfo, CloudState, CloudUser} from '@shared/models/cloud'; export const cloudSlice = createSlice({ name: 'cloud', @@ -11,8 +12,14 @@ export const cloudSlice = createSlice({ setCloudUser: (state: Draft, action: PayloadAction) => { state.user = action.payload; }, + setCloudProjectInfo: (state: Draft, action: PayloadAction) => { + state.projectInfo = action.payload; + }, + setCloudPolicyInfo: (state: Draft, action: PayloadAction) => { + state.policyInfo = action.payload; + }, }, }); -export const {setCloudUser} = cloudSlice.actions; +export const {setCloudUser, setCloudPolicyInfo, setCloudProjectInfo} = cloudSlice.actions; export default cloudSlice.reducer; diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index f175491033..9ce9618c69 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -4,12 +4,11 @@ import {useAsync, useInterval, useMount} from 'react-use'; import {isEqual} from 'lodash'; -import {getCloudPolicy, getCloudProjectInfo, getCloudUser, logoutFromCloud, startCloudLogin} from '@redux/cloud/ipc'; +import {getCloudInfo, getCloudPolicy, getCloudUser, logoutFromCloud, startCloudLogin} from '@redux/cloud/ipc'; import {useAppDispatch, useAppSelector} from '@redux/hooks'; -import {setCloudUser} from '@redux/reducers/cloud'; +import {setCloudPolicyInfo, setCloudProjectInfo, setCloudUser} from '@redux/reducers/cloud'; import {rootFolderSelector} from '@redux/selectors'; -import {ProjectInfo} from '@monokle/synchronizer'; import {ROOT_FILE_ENTRY} from '@shared/constants/fileEntry'; import {AppDispatch} from '@shared/models/appDispatch'; import {RootState} from '@shared/models/rootState'; @@ -41,39 +40,42 @@ export const pollCloudPolicy = async (state: RootState, dispatch: AppDispatch) = }; export const useCloudPolicy = () => { + const dispatch = useAppDispatch(); const store = useStore(); const cloudPolicy = useAppSelector(state => state.validation.cloudPolicy); const rootFolderPath = useAppSelector(rootFolderSelector); - const [projectInfo, setProjectInfo] = useState(); - const [policyLink, setPolicyLink] = useState(); + + const projectInfo = useAppSelector(state => state.cloud.projectInfo); + const policyInfo = useAppSelector(state => state.cloud.policyInfo); const updateProjectInfo = useCallback(async () => { - const {info, link} = (await getCloudProjectInfo(rootFolderPath)) || {}; - setProjectInfo(info); - setPolicyLink(link); + const cloudInfo = await getCloudInfo(rootFolderPath); + dispatch(setCloudProjectInfo(cloudInfo?.projectInfo)); + dispatch(setCloudPolicyInfo(cloudInfo?.policyInfo)); - if (cloudPolicy && info && !cloudProjectsThisSession.has(info.slug)) { - trackEvent('cloud_sync/policy', {projectSlug: info.slug}); - cloudProjectsThisSession.add(info.slug); + if (cloudPolicy && cloudInfo?.projectInfo && !cloudProjectsThisSession.has(cloudInfo.projectInfo.slug)) { + trackEvent('cloud_sync/policy', {projectSlug: cloudInfo.projectInfo.slug}); + cloudProjectsThisSession.add(cloudInfo.projectInfo.slug); } - }, [rootFolderPath, cloudPolicy]); + }, [rootFolderPath, cloudPolicy, dispatch]); useMount(() => { - pollCloudPolicy(store.getState(), store.dispatch); + pollCloudPolicy(store.getState(), dispatch); updateProjectInfo(); }); useEffect(() => { - pollCloudPolicy(store.getState(), store.dispatch); + pollCloudPolicy(store.getState(), dispatch); updateProjectInfo(); - }, [store, rootFolderPath, updateProjectInfo]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [rootFolderPath]); useInterval(() => { - pollCloudPolicy(store.getState(), store.dispatch); + pollCloudPolicy(store.getState(), dispatch); updateProjectInfo(); }, 10 * 1000); - return {cloudPolicy, projectInfo, policyLink}; + return {cloudPolicy, projectInfo, policyInfo}; }; export const useCloudUser = () => { diff --git a/src/shared/models/cloud.ts b/src/shared/models/cloud.ts index 4d319d2cca..ea33499670 100644 --- a/src/shared/models/cloud.ts +++ b/src/shared/models/cloud.ts @@ -1,3 +1,5 @@ +import {ProjectInfo} from '@monokle/synchronizer'; + /** * This type is used by the renderer so it doesn't need to have all the properties of the User class */ @@ -9,6 +11,12 @@ export type CloudLoginResponse = { user: CloudUser; }; +export type CloudPolicyInfo = { + link: string; +}; + export type CloudState = { user?: CloudUser; + projectInfo?: ProjectInfo; + policyInfo?: CloudPolicyInfo; }; From b18462f4e89ecd91e527747b2644ed0e6472dd00 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 16:06:01 +0300 Subject: [PATCH 33/49] refactor: redesign ValidationCardPolicy --- src/assets/CloudManaged.png | Bin 0 -> 7212 bytes .../CloudConnect/CloudConnect.tsx | 2 +- .../ValidationCardPolicy.tsx | 59 +++++++----------- 3 files changed, 25 insertions(+), 36 deletions(-) create mode 100644 src/assets/CloudManaged.png diff --git a/src/assets/CloudManaged.png b/src/assets/CloudManaged.png new file mode 100644 index 0000000000000000000000000000000000000000..88533624efac5c5f5c147893de69908bfb0e594b GIT binary patch literal 7212 zcmbt(cUTk6+I|QvfC8aNQ6z+*Gy$p7LkIyPB_JSOTBy=H(nY#7=}46tiXcTmDI!gp z2!!550qISY&KKYFp7WmH@B8!H>zbWs=eh5BcAnX5XZM~cjE3@6N>)k$0B}`R1*r`H z5a|$X9}pSgTp2^DMyQC~wUrTos-YWegbNF-zN)plI)Im8g8)Pkb^ww;5JF)k6aauE zDI7pfsObm=lSc#~Ce%cK{CU8CBZ+kKi2rQ^d1OBRVdv}w`O~kt zg|nxJEEM`D(0`79-6z(^?w?3b?tc%9FhIdS9>Kc;LW2M4n?RNM(<+6r^T9qgK-xJH z(nE+LcUM?Q<}dvJ^86F=znJ>}FhxZFALf5~{(q*fJJwCn*^v;^L++oM`8(`?JO3ui z2>u!Qe`VrdY5uE~kY_nc8NvU|nH*&|(a=zpRM7Du+A=Y5xi;Y|*Wh555NUY< zV=kfV<%qHjqgS+U-%gK#+{znZuC_@UgVnVtz|xWeq8fiFJ>Rxh^n1bDUny4a|`R>WD(;RQqNvpH>=Y?9E z+~~dPgGRs}rco&srij@CXPS2A~?14lemRHZvRE?xB4v>?p{Ij;U z!L!NU!339Cj{p|IRBlzxW4@g@|J*MOG!lgCAF9$s02B17fYp1fDfaU#?4bl?Cev z3D*#VHpgKnma+x4>V+4@Sk(&e0AD<3%LVXQS`IjjzPxZ|pKzDy|8`p=u|WO$TcI`* z%WJXv3{Z?XN#;Xw+PV;L6N6TlQEVP6|A)?rPut}=W)Yogy0JJ z6zWiSPNpA>v|-@*rYJyceS~O6Aoj4O=^-XL(foYC|19FNUR#brj4RgURJ@#B<^t1a zya`*_9mL~Y_kf;GM~c!c!c5Qv4j=~E{L7I?4XiMl7Yi5Z77cz5zDXgb6hV}+Jx>2a z;FH9-nBChX)RwUDigvv|6I6(XD1k@D%owber7#k=t5QnVeRMg@Vf;nyygto$wl4c) zu3!*7(RENGs(9p9?Cyv?F3~#puHAbF<##!~j)`wJE<^@uCK=6!?Y<8CFFik~(kXM= zAljiBn9xeLpOBjpuq(cJ0yF}JU#Lc0>dqApvjkpj<_xD$Tu|=4l?DZ4-qD;3yRN#F za4lCxl~3#Yf(KhyhPC%*VXjIQxO|HySY3^4OY7OHU{1}tMS`s8ulql?ri!o1@1@2~ zzgDWd(Ix10Iok7zYf)DZ?DJi^(tUdJ2X-sxmC4Myt{Hzy8TZ6pz=Ef@Bfjv&a1*D; zrDO2R(@jNi&hNl&6KKyvbR)hWQ5-5Ap2=)+xS^|?><^yYZRdRex%TLWoEz^#2OHm2 zvRQtRCz@O-BPT#>>Sg#xe_p-EUD?9r=+d~kv<}=;U#kiJ6Ri*M7R~p24L40@qcg)M z4B&9Rv)CU;REPWxxokfzf7*1`@1iUnh6ON@OXGW!QuMLhcUID?LZB?GO{!|8fVHyQ z60A(wb&P_FezwKp3&Fk(EQ*&V(l-lJGjIRU?Ze$xOi@=N(VEDS6}IX)Jmx@w+P-?j z->_%gV+tUb)~&tWnR|I+-}XXAA_~N4HSN87TEvxZ51*ECezIL*cbtUG4l~3JzRMI4 zWI9h9t>?}i1ChZVJY0nA$6%e|)o*r!{2)$mq9;BMf0>!n+RMy);WJ~wEee;wL44e#!;4Z2YCdEdZ$Pcm z8nSPJhAY?r4Y5_ZkDKn?pQNJx(PW6kN%{B;`@C(h_V~H;3#N_0z>V*Sf%E%jF)hrv zUvkG=Gft+-#G_K{t)S47LdF56B8t>^N^Q(4rFJ`r=ARIq$cHoNv{&!S6i~M>Tpz7d zB3y}06S$phA+E7`UD)cK9|>P{Ug(ifrr37l_f?Rkc;U*T17^d>62%d(PggZEZ?5GH z${dcSjauao7zW9@vfCud>V~M@h;C1j8rJygmVxR#3Nx2EkGNoPubP=3yS!)>va*i1#46vR2tQ|lCXfT)$jPZ1FssTQ)&||pEK_^F8DL>q zQIXf%yFN6!D$s-8XuHQt0~^77xS$;{c$~}Dam0t=Ya4CFntTko4>5ViS#Om4D{Rzw zevQ^Pe5N5#T^1KHCyZw%uep;o{-aW}yDmnzxjJ>1XFDF_0!28cbLk|gSAsQ22G9Xf z&zokoi7_tAH5MSCM1!MPMQr<^&?hLfV8--rc*2F8-&(Vj-)3x%@R3)6pOQ&(LL{cd z#v9yewbxlM$e%L5jCE-qyx*Auau;}IIZ=5n%j;sy9?NePZcb|fce{xPrc=BD{7NXL zu?>Zyvq=1*-R#V{o!6o2Plp$WHqos`|ALlyY=usKHa0EiGN0jrNbXg``_TMr?$ROBC-`8~HR9Wz z;43`lE+2@g)OiKhBzM!xK7X++@tk@w9I%x6Z?j)Z1vYb^wMtrM!lA!KBJJ0lbT?Q9eSDtRE1E1B7Fp2etTV6 z4X;B_XHObtRn^$RRV34OJgPn4&|D^3EQ?EA|H3qso-Z9q52IKn|ID{iRHMci1Q}A4 z3aps`fQZFm(h7Ux73Xy>6T%X+buCfu_E#?mLhj&-7Rua`_iPV5ng%3#{rdn1vyq2et!3uebeJ*^F) zX2c;;e1=3m5K|3(d>FP^AJ2d)T{0wP#|x!(&q+^Y&4JAZBW^`!qhNWoq6UxGl98Pz zb=ro60eQSXkYW^|lI3#ZP6yGvJI;?H)@a9*Iqz^Q76gBHk0>;CCqH@y(nmo))z+#D z#*pPxzrSdRid|vD-9KD3Bo$1tm&4r?RKVAas!ZFEEi3QEa^&}AQyz8BT!o-AVyRWC zR^0_MKC;CJ45CR~qcDLdgEgJU`RWCdCq(ShJFb%QHWc`5 z{=Q-5kxw=wOkstqx51I20F)V|0~Wx**>SNNXl0x$#Cot2;tp}3eHkRxZY22A{k2}E zM>3CZ95Pl<3BlNjkaImqQnRIUWx2gXX~=Q577E*JG>*Bxxn=A2e&n`P{^0Vnl)fcN zXhLDUpVmjrg7j>UWb8=ZW1Z*@8uk6%1I77@f!WRX#CL;w4~*}yP}H*`PR=MCJ!7w{ z5rvnofcW^J4D3FtN!3wW3vWV5_aWfOD8N!ex5;yzO3+j{dGydlN&Izh?$^bXOHYND z@EYcu=<ZtD$B zecWv)U#C&wg%h<8D~DFC4bPMmf^8>VH>q#zD=I@JKGy-K1Pp#Jtcdm=PCHNI*-_(UCPS87aDbsbm&9$RtOOnK*BkZ& z@1mZ!l4&aC7RF_?;QRN&pLs2Y26G!->=zo=A9!$Qkl_!upA@TQp3Fg2Tg#_22Wt17sLe9-ra}oB> zZoy}O+9u6w@{TtBXKwIz{3@AxPwnUvAE6W|0-^pT%6Q|3KqAkIT2|{50n+A_7f@&B z*WAmB?e(i0SKDXF@) zLgFANDsZO{L{koOOyJq(qrf9}x@T#Z#5?qLJ99L5<7Ly`N-c=OoA~pxJH&V$LN*xv z4S1H3@Z>~j<)u)v=kMuSi3H4@UrLQSTRSYhCPwP^iFK1deGR7GbZX|Dhwmx0h`H{( zKWmXU`&p38M8wUhT!#QWgE?C=_SLn(vcl|}1eYpft{;wRJ{pSEzl&60sY0iZ2EIJe zIP-gzd35-3I=@YQuIWd7zN*%Ec5QhDLU4&<72KZ85)&l>nTXcAA>Bz^=`G3-TP$=NRqwt{d)b=fCz=tuROW{JVcvrp&45i=bL@ zIo+(7^Q2$57SXu&87Mm?2zNMcAp;V|{1CWVUwZ; zG*Cugrvk))GW7)Rem_o{4`fAV*C$|VQIjv^rTP|m&Ia3RCZ*9{wpXIpe&EE{?WSiR zQn(3wxBn*npjq`JUnYESm+R0Wm%XLIfLz&bxTl2kw0d6G9NqpF_KTFQ*H0(HY{2kPq&93OX_1SUEdiYSHg zBvk%xd`WX!QAgPy^ISfl=w6!mh}cHJSDs(AaQ3cT+KQH!Tgym9eFWBA(tO4wQO@#C z_G_a4rWVb|?;S@)Bp>paOtcQ>J0EW=w#70AGc8xH%e)e}u!!LJ?CR*>AydY(zEP^3 zz!*=xP~4PBPjTT}vv;fKDaA+ggvBCDX%md3jNTJa0>)u6C-erA*Dj{o$?tWF=ut(o z(^6k@rv9E1%e=?M4)e%E`YQ)nZKu-DzMl6?ACWxL)<5I`?J#*8@DzhOU==NsL8VEP zDie8cX?q$Ll1~(Z!wiXkOR0_SOI)P_>@q!EYP8jbN;o&Uob@EIkDt-Re|}sL?)#u( zG@ftR=_8C+eEuio!Syvi>c>~vz&`!oeord|2bR{m3ufC=tiWGU_R_<6-4=54k&5T& zxXUC7`6&2J!hIjWo8tP~6XbczI^doQIS+32QWzIr6Z>$^lfz8>@Csdgn)K^iz&+Z< z1o@k$@1=l1{W%8DdIl(p!^J~8!*7RA^@T7SxH=9Xrn8YC{ITr!j)>lAMdDGL5!Kk? z6r-*|TGv?=oPk88R132tRzurf&Azc)oBBzj&FLDEl?nC1ZJ-tyl8;h~p6Eg>hTn`1 zatm~<5Oo!}@USRrmfCpBdYkPv7tny95Dn7JNqxTFT4bQVXdX%Tuv{u4ebD;~L0Ynu zfR#!;e=ah#AIWBL>%(x+X6{=9F5QH+NqNU_m^L-G4Qy4eS!ZlGp#9VEJe?ewLbE8a&+n;XzsS*}|*iRw7J z-#zPjzi!_Wx4>@R_rzq_+qOvmK>lz(K%vAp78C}Bd1_F@t9Bbm(x7 zNReJ=$LF*-IB_ULQkbQD$IhMfIgUfkOcnDFtJS8%OE%gh(}rnTg&@)FG{PJrq?9Bh zcWHRug|m_n0Sn52o5&Wd}#>NiO9FX zqvPQ3=AA%pC$rdtj2?M9`KGo z|M4fi8&4H?42LqNz#-F0c>zwDn}$wgJb9`J&qhtp$0jzvf;(K~KfkT`m{4txgwO$f zydcER@7dP;jF=KJjvN^Za`J(0x7tr*r>Vi9fY*f2bj+3Z&BU2>h+!FSv%e< z8I5w__EKtx-{zeJH|aVdF()_uSE~<&tQMaiP&yk>5>!h(xV`q9E^#ft}-$S0>{?%s#oc~ksJph8sp>89B{L$r#PVu0P1 zSLzgWr2c&vQu;N>0}l`xoM#bL-8;e&Y(t(|=0Nz+sL!h+dDKKq5a7sKS}5kLhSgMy zN$0LyGvX!Lb~eHJJ!xfLdG~WO0pq@n_Nn!9xPM^`dr8G!_VF_fqnyqs7P4!~By=2r z`>p(buGsV)M-T-*1{J<=ccJ#a^ybdgao!iS7Q@S5G5cx#)nx;jAbn-P#gq$AvTOmF zW=nb8jZ>P{*tam9jkke;;Xgn|;+0x6Zv#E!R3hs2{C++Yxv}&)BDyWI-4WD_U}E|5 zVcg~CWCp_Il~Z})Dx4SLIBdv-l>@5trIkkf9H-jwEIe11s2@n=t^y_^_^{lq$LV`a z;9V$yPD$p$jx9CP4-v5>U3F>f#iNESg^)4pR<9U)eJ6pu36i;Thw#T}8Y_G*@WlBW z>bpUeDCJgnf@wIX+l|~GAi^VCK58SFsM69tw)T5%Eu*r1qJjT`&vCSr5Mg z-z5cBYcD!QL|ff>H!N0`;~SQm6sCN&7G2L3(j6wrG9KFWT2HZzaS=9@#BtaRt_pyo5wRR{8To2LNaP3NgGoY#)A z^Tk<_S;eVYwvX9%_} zQ<9z>(&dd1d>|n&Ql)wHlAzczKxxCTz4wv|wO}!B-*t zPeEh6z}+dQ2`X9cE>3{_B7Z=KYH8Pk0Ql%Y5PB {cloudUser ? ( <> - Connected to Monokle Cloud 🟢 + Connected to Monokle Cloud E-mail: {cloudUser.email} diff --git a/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCardPolicy.tsx b/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCardPolicy.tsx index f2fc1b757a..18e9a29278 100644 --- a/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCardPolicy.tsx +++ b/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCardPolicy.tsx @@ -1,20 +1,23 @@ -import AntdIcon from '@ant-design/icons'; - import styled from 'styled-components'; -import {Colors} from '@shared/styles'; +import CloudManaged from '@assets/CloudManaged.png'; -const DESCRIPTION = - "Policies add compliancy across your project's repositories by providing consistent validation. Config can no longer be adjusted in this pane. Set up below is read-only."; +import {Colors} from '@shared/styles'; export function ValidationCardPolicy() { return ( - + + + +
+ A Monokle Cloud policy manages this repository - A Monokle Cloud policy manages this repository - - {DESCRIPTION} + + Policies add compliancy across your project's repositories by providing consistent validation. The + configuration can no longer be adjusted in this pane. Set up below is read-only. + +
); } @@ -24,9 +27,10 @@ const CardContainer = styled.div` background-color: ${Colors.geekblue4}; padding: 12px; display: flex; - flex-direction: column; gap: 12px; margin-bottom: 20px; + align-items: center; + padding-right: 32px; `; const Description = styled.div` @@ -45,32 +49,17 @@ const Description = styled.div` } `; +const ImageContainer = styled.div` + padding: 24px; +`; + +const Image = styled.img` + height: 60px; +`; + const Title = styled.div` - font-weight: 600; + font-weight: 700; line-height: 22px; color: ${Colors.whitePure}; + margin-bottom: 12px; `; - -export function PolicySvg() { - return ( - - - - - - - - - ); -} From 664b493393f6b90b3fab5beef0ef649a0c2ae2af Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 16:27:55 +0300 Subject: [PATCH 34/49] chore: tooltip messages in CloudSync --- .../PageHeader/CloudSync/CloudSync.tsx | 57 ++++++++++++++++--- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx index f6f51cec38..7c495baa7d 100644 --- a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx +++ b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx @@ -2,7 +2,13 @@ import {useCallback} from 'react'; import {Button, Dropdown, Spin, Tooltip} from 'antd'; -import {ArrowRightOutlined, CheckCircleFilled, CloseCircleFilled, LoadingOutlined} from '@ant-design/icons'; +import { + ArrowRightOutlined, + CheckCircleFilled, + CloseCircleFilled, + InfoCircleFilled, + LoadingOutlined, +} from '@ant-design/icons'; import styled from 'styled-components'; @@ -51,20 +57,38 @@ const CloudSync = () => { {projectInfo?.name ? <GreenCircle /> : <RedCircle />} Cloud project - {projectInfo?.name || 'Not found'} + + {projectInfo?.name ? ( + <> + {projectInfo?.name} + + + ) : ( + <> + Not found + + + )} + {cloudPolicy ? <GreenCircle /> : <RedCircle />} Policy {cloudPolicy ? ( - openUrlInExternalBrowser(policyInfo?.link)} - style={{cursor: 'pointer', color: Colors.blue7}} - > - View project policy - + <> + openUrlInExternalBrowser(policyInfo?.link)} + style={{cursor: 'pointer', color: Colors.blue7}} + > + View project policy + + + ) : ( - 'Not found' + <> + Not found + + )} @@ -111,6 +135,15 @@ const CloudSync = () => { export default CloudSync; +const Info = (props: {description: string}) => { + const {description} = props; + return ( + + + + ); +}; + const Container = styled.div<{$hasText: boolean}>` display: flex; align-items: center; @@ -176,3 +209,9 @@ const Value = styled.div` text-align: left; margin-left: 8px; `; + +const InfoIcon = styled(InfoCircleFilled)` + color: ${Colors.grey6}; + margin-left: 8px; + cursor: pointer; +`; From 8c9fccfebfe8bd1f06dbee4b279722357e0841ea Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Mon, 25 Sep 2023 17:14:44 +0300 Subject: [PATCH 35/49] chore: Cloud Sync UI improvements --- .../PageHeader/CloudSync/CloudSync.tsx | 22 +++++++++---------- .../PageHeader/ClusterControl/Buttons.tsx | 6 ++--- .../PageHeader/K8sVersionSelection.style.tsx | 2 +- .../CloudConnect/CloudConnect.tsx | 2 +- src/redux/validation/validation.hooks.ts | 5 +++++ 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx index 7c495baa7d..9c165d2657 100644 --- a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx +++ b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx @@ -2,13 +2,7 @@ import {useCallback} from 'react'; import {Button, Dropdown, Spin, Tooltip} from 'antd'; -import { - ArrowRightOutlined, - CheckCircleFilled, - CloseCircleFilled, - InfoCircleFilled, - LoadingOutlined, -} from '@ant-design/icons'; +import {CheckCircleFilled, CloseCircleFilled, InfoCircleFilled, LoadingOutlined} from '@ant-design/icons'; import styled from 'styled-components'; @@ -80,7 +74,7 @@ const CloudSync = () => { onClick={() => openUrlInExternalBrowser(policyInfo?.link)} style={{cursor: 'pointer', color: Colors.blue7}} > - View project policy + View project policy
@@ -111,7 +105,7 @@ const CloudSync = () => { }, [connect, cloudUser, isConnecting, cloudPolicy, isInitializing, projectInfo, policyInfo]); return ( - + { placement="bottom" > + {projectInfo?.name}
@@ -158,6 +153,7 @@ const Icon = styled.img` cursor: pointer; height: 20px; width: 20px; + margin-right: 4px; `; const Image = styled.img` @@ -166,7 +162,7 @@ const Image = styled.img` `; const DropdownContent = styled.div` - padding: 20px; + padding: 28px; margin-top: 10px; background-color: ${Colors.grey2}; `; @@ -184,11 +180,15 @@ const GraySpan = styled.span` `; const GreenCircle = styled(CheckCircleFilled)` + font-size: 12px; color: ${Colors.polarGreen}; + margin-right: 4px; `; const RedCircle = styled(CloseCircleFilled)` + font-size: 12px; color: ${Colors.red7}; + margin-right: 4px; `; const Item = styled.div` @@ -199,7 +199,7 @@ const Item = styled.div` `; const Title = styled.div` - width: 110px; + width: 120px; margin-right: 8px; color: ${Colors.grey7}; `; diff --git a/src/components/organisms/PageHeader/ClusterControl/Buttons.tsx b/src/components/organisms/PageHeader/ClusterControl/Buttons.tsx index 38ce9e7220..7317f00785 100644 --- a/src/components/organisms/PageHeader/ClusterControl/Buttons.tsx +++ b/src/components/organisms/PageHeader/ClusterControl/Buttons.tsx @@ -90,12 +90,12 @@ const SquareBtn = styled(Button)` `; const ConnectBtn = styled(SquareBtn)` - border-color: ${Colors.geekblue7}; - background-color: ${Colors.geekblue7}; + border-color: ${Colors.blue6}; + background-color: ${Colors.blue6}; `; const CloseBtn = styled(SquareBtn)` min-width: 20px; border: none; - color: ${Colors.geekblue7}; + color: ${Colors.blue6}; `; diff --git a/src/components/organisms/PageHeader/K8sVersionSelection.style.tsx b/src/components/organisms/PageHeader/K8sVersionSelection.style.tsx index 1550273e4b..7bae10b678 100644 --- a/src/components/organisms/PageHeader/K8sVersionSelection.style.tsx +++ b/src/components/organisms/PageHeader/K8sVersionSelection.style.tsx @@ -76,7 +76,7 @@ export const WarningText = styled(Typography.Text)` `; export const K8sVersionText = styled(Typography.Text)` - color: ${Colors.blue8}; + color: ${Colors.blue6}; `; export const MenuItem = styled(Menu.Item)<{$selected: boolean}>` diff --git a/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx index 66a535eef0..6a424c19f3 100644 --- a/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx +++ b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx @@ -76,7 +76,7 @@ export default function CloudConnect(props: {wide: boolean}) { )} - + diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index 9ce9618c69..d39261bcc5 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -79,6 +79,7 @@ export const useCloudPolicy = () => { }; export const useCloudUser = () => { + const store = useStore(); const dispatch = useAppDispatch(); const [isInitializing, setIsInitializing] = useState(false); const [isConnecting, setIsConnecting] = useState(false); @@ -97,6 +98,7 @@ export const useCloudUser = () => { const {user} = await startCloudLogin(undefined); trackEvent('cloud_sync/login'); dispatch(setCloudUser(user)); + pollCloudPolicy(store.getState(), dispatch); setIsConnecting(false); }; @@ -105,6 +107,9 @@ export const useCloudUser = () => { await logoutFromCloud(undefined); trackEvent('cloud_sync/logout'); dispatch(setCloudUser(undefined)); + dispatch(setCloudPolicy(undefined)); + dispatch(setCloudProjectInfo(undefined)); + dispatch(setCloudPolicyInfo(undefined)); setIsDisconnecting(false); }; From 87b2c347554312c118d0ba353aa5d62166b51f79 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:26:52 +0300 Subject: [PATCH 36/49] chore: change label when using cloud policy --- .../ValidationSettings/ValidationOverview/ValidationCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCard.tsx b/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCard.tsx index d3094afb26..aea1d7708d 100644 --- a/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCard.tsx +++ b/src/components/organisms/ValidationSettings/ValidationOverview/ValidationCard.tsx @@ -67,7 +67,7 @@ const ValidationCard: React.FC = ({configurable, plugin}) => { {hasRules && configurable && ( - Configure + {isUsingCloudPolicy ? 'View' : 'Configure'} )} From 112ff1790fe4c0135c2e6fa0c05348961e2028c8 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:30:41 +0300 Subject: [PATCH 37/49] feat: send notifications about Policy --- src/redux/validation/validation.hooks.ts | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/redux/validation/validation.hooks.ts b/src/redux/validation/validation.hooks.ts index d39261bcc5..4c6d83afa8 100644 --- a/src/redux/validation/validation.hooks.ts +++ b/src/redux/validation/validation.hooks.ts @@ -6,10 +6,12 @@ import {isEqual} from 'lodash'; import {getCloudInfo, getCloudPolicy, getCloudUser, logoutFromCloud, startCloudLogin} from '@redux/cloud/ipc'; import {useAppDispatch, useAppSelector} from '@redux/hooks'; +import {setAlert} from '@redux/reducers/alert'; import {setCloudPolicyInfo, setCloudProjectInfo, setCloudUser} from '@redux/reducers/cloud'; import {rootFolderSelector} from '@redux/selectors'; import {ROOT_FILE_ENTRY} from '@shared/constants/fileEntry'; +import {AlertEnum} from '@shared/models/alert'; import {AppDispatch} from '@shared/models/appDispatch'; import {RootState} from '@shared/models/rootState'; import {trackEvent} from '@shared/utils'; @@ -36,6 +38,25 @@ export const pollCloudPolicy = async (state: RootState, dispatch: AppDispatch) = return; } + if (!previousCloudPolicy) { + dispatch( + setAlert({ + type: AlertEnum.Success, + title: 'Repository connected to Cloud Project', + message: + 'This repository has been connected successfully to a Cloud Project. The Policy is now being synchronized.', + }) + ); + } else { + dispatch( + setAlert({ + type: AlertEnum.Success, + title: 'Cloud Policy updated', + message: 'The Policy has been changed in the Cloud Project and is now being synchronized.', + }) + ); + } + dispatch(setCloudPolicy(cloudPolicy)); }; From d4ea2355d2ddd1eef6aa890bfe7a8d6af24b8198 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:35:25 +0300 Subject: [PATCH 38/49] feat: add link to cloud project --- electron/app/services/cloud/project.ts | 10 ++++++---- .../organisms/PageHeader/CloudSync/CloudSync.tsx | 14 +++++++------- src/redux/cloud/ipc.ts | 6 +++--- src/redux/reducers/cloud.ts | 5 ++--- src/shared/models/cloud.ts | 6 +++++- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/electron/app/services/cloud/project.ts b/electron/app/services/cloud/project.ts index 78a00eed68..ef225e0774 100644 --- a/electron/app/services/cloud/project.ts +++ b/electron/app/services/cloud/project.ts @@ -1,12 +1,11 @@ -import {ProjectInfo} from '@monokle/synchronizer'; -import {CloudPolicyInfo} from '@shared/models/cloud'; +import {CloudPolicyInfo, CloudProjectInfo} from '@shared/models/cloud'; import {getSynchronizer} from './synchronizer'; import {getUser} from './user'; export const getInfo = async ( repoPath: string -): Promise<{projectInfo: ProjectInfo; policyInfo: CloudPolicyInfo} | null> => { +): Promise<{projectInfo: CloudProjectInfo; policyInfo: CloudPolicyInfo} | null> => { const synchronizer = await getSynchronizer(); const user = await getUser(); if (!user?.token || !synchronizer) { @@ -16,7 +15,10 @@ export const getInfo = async ( try { const project = await synchronizer?.getProjectInfo(repoPath, user.token, true); return project - ? {projectInfo: project, policyInfo: {link: synchronizer.generateDeepLinkProjectPolicy(project.slug)}} + ? { + projectInfo: {...project, link: synchronizer.generateDeepLinkProject(project.slug)}, + policyInfo: {link: synchronizer.generateDeepLinkProjectPolicy(project.slug)}, + } : null; } catch { return null; diff --git a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx index 9c165d2657..47c8a39956 100644 --- a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx +++ b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx @@ -54,7 +54,7 @@ const CloudSync = () => { {projectInfo?.name ? ( <> - {projectInfo?.name} + openUrlInExternalBrowser(projectInfo.link)}>{projectInfo.name} ) : ( @@ -70,12 +70,7 @@ const CloudSync = () => { {cloudPolicy ? ( <> - openUrlInExternalBrowser(policyInfo?.link)} - style={{cursor: 'pointer', color: Colors.blue7}} - > - View project policy - + openUrlInExternalBrowser(policyInfo?.link)}>View project policy ) : ( @@ -215,3 +210,8 @@ const InfoIcon = styled(InfoCircleFilled)` margin-left: 8px; cursor: pointer; `; + +const Link = styled.span` + cursor: pointer; + color: ${Colors.blue7}; +`; diff --git a/src/redux/cloud/ipc.ts b/src/redux/cloud/ipc.ts index 46f0d99382..8265258517 100644 --- a/src/redux/cloud/ipc.ts +++ b/src/redux/cloud/ipc.ts @@ -1,12 +1,12 @@ import {invokeIpc} from '@utils/ipc'; -import type {PolicyData, ProjectInfo} from '@monokle/synchronizer'; -import {CloudLoginResponse, CloudPolicyInfo, CloudUser} from '@shared/models/cloud'; +import type {PolicyData} from '@monokle/synchronizer'; +import {CloudLoginResponse, CloudPolicyInfo, CloudProjectInfo, CloudUser} from '@shared/models/cloud'; export const startCloudLogin = invokeIpc('cloud:login'); export const logoutFromCloud = invokeIpc('cloud:logout'); export const getCloudUser = invokeIpc('cloud:getUser'); export const getCloudPolicy = invokeIpc('cloud:getPolicy'); -export const getCloudInfo = invokeIpc( +export const getCloudInfo = invokeIpc( 'cloud:getInfo' ); diff --git a/src/redux/reducers/cloud.ts b/src/redux/reducers/cloud.ts index 6954ccda12..7769e34805 100644 --- a/src/redux/reducers/cloud.ts +++ b/src/redux/reducers/cloud.ts @@ -2,8 +2,7 @@ import {Draft, PayloadAction, createSlice} from '@reduxjs/toolkit'; import initialState from '@redux/initialState'; -import {ProjectInfo} from '@monokle/synchronizer'; -import {CloudPolicyInfo, CloudState, CloudUser} from '@shared/models/cloud'; +import {CloudPolicyInfo, CloudProjectInfo, CloudState, CloudUser} from '@shared/models/cloud'; export const cloudSlice = createSlice({ name: 'cloud', @@ -12,7 +11,7 @@ export const cloudSlice = createSlice({ setCloudUser: (state: Draft, action: PayloadAction) => { state.user = action.payload; }, - setCloudProjectInfo: (state: Draft, action: PayloadAction) => { + setCloudProjectInfo: (state: Draft, action: PayloadAction) => { state.projectInfo = action.payload; }, setCloudPolicyInfo: (state: Draft, action: PayloadAction) => { diff --git a/src/shared/models/cloud.ts b/src/shared/models/cloud.ts index ea33499670..bcf5d13f39 100644 --- a/src/shared/models/cloud.ts +++ b/src/shared/models/cloud.ts @@ -11,12 +11,16 @@ export type CloudLoginResponse = { user: CloudUser; }; +export type CloudProjectInfo = ProjectInfo & { + link: string; +}; + export type CloudPolicyInfo = { link: string; }; export type CloudState = { user?: CloudUser; - projectInfo?: ProjectInfo; + projectInfo?: CloudProjectInfo; policyInfo?: CloudPolicyInfo; }; From a26d21b9721bae88fdb79c2b45f99d4fbdc40c4c Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 27 Sep 2023 10:49:15 +0300 Subject: [PATCH 39/49] chore: wording updates --- electron/app/services/cloud/login.ts | 2 +- src/components/organisms/PageHeader/CloudSync/CloudSync.tsx | 2 +- .../organisms/SettingsPane/CloudConnect/CloudConnect.tsx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/electron/app/services/cloud/login.ts b/electron/app/services/cloud/login.ts index fde7fe4891..8748c9510e 100644 --- a/electron/app/services/cloud/login.ts +++ b/electron/app/services/cloud/login.ts @@ -17,7 +17,7 @@ export const cloudLogin = async (): Promise => { shell.openExternal(loginResponse.handle.verification_uri_complete); const user = await loginResponse.onDone; if (!user) { - throw new Error('Login to Cloud has failed'); + throw new Error('Login to Cloud has failed. Please try again later.'); } return {user: serializeUser(user)}; }; diff --git a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx index 47c8a39956..c5b0d005f7 100644 --- a/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx +++ b/src/components/organisms/PageHeader/CloudSync/CloudSync.tsx @@ -55,7 +55,7 @@ const CloudSync = () => { {projectInfo?.name ? ( <> openUrlInExternalBrowser(projectInfo.link)}>{projectInfo.name} - + ) : ( <> diff --git a/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx index 6a424c19f3..8338858f42 100644 --- a/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx +++ b/src/components/organisms/SettingsPane/CloudConnect/CloudConnect.tsx @@ -32,7 +32,7 @@ export default function CloudConnect(props: {wide: boolean}) { E-mail: {cloudUser.email} - Thank you for syncing Monokle Desktop with Monokle Cloud.
+ You have successfuly connected to your Monokle Cloud Account.
Your validation policies are now unified and synchronized across platforms.
Date: Wed, 27 Sep 2023 11:02:44 +0300 Subject: [PATCH 40/49] chore: update electron dependencies --- electron/app/autoUpdater.ts | 2 +- electron/app/ipc/ipcMainRedux.ts | 7 +- package-lock.json | 684 ++++++++++++++++--------------- package.json | 8 +- 4 files changed, 368 insertions(+), 333 deletions(-) diff --git a/electron/app/autoUpdater.ts b/electron/app/autoUpdater.ts index 3a7dd3ce19..791b6abdca 100644 --- a/electron/app/autoUpdater.ts +++ b/electron/app/autoUpdater.ts @@ -1,6 +1,6 @@ import {AppImageUpdater, MacUpdater, NsisUpdater} from 'electron-updater'; -import {GenericServerOptions} from 'electron-updater/node_modules/builder-util-runtime'; +import {GenericServerOptions} from 'builder-util-runtime'; import {join} from 'path'; const isDev = process.env.NODE_ENV === 'development'; diff --git a/electron/app/ipc/ipcMainRedux.ts b/electron/app/ipc/ipcMainRedux.ts index c5ac97ab65..a3ad19fd77 100644 --- a/electron/app/ipc/ipcMainRedux.ts +++ b/electron/app/ipc/ipcMainRedux.ts @@ -31,7 +31,7 @@ export const createDispatchForWindow = (window: BrowserWindow) => { export const dispatchToFocusedWindow = (action: AnyAction) => { const focusedWebContents = webContents.getFocusedWebContents(); - focusedWebContents.send('redux-dispatch', action); + focusedWebContents?.send('redux-dispatch', action); }; export const fetchStoreState = (contents: WebContents) => { @@ -51,11 +51,6 @@ export const fetchStoreState = (contents: WebContents) => { ); }; -export const fetchFocusedWindowStoreState = () => { - const focusedWebContents = webContents.getFocusedWebContents(); - return fetchStoreState(focusedWebContents); -}; - export const subscribeToStoreStateChanges = ( contents: WebContents, propertiesToPick: string[], diff --git a/package-lock.json b/package-lock.json index 63151e60da..8ddc5c686c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -36,7 +36,7 @@ "electron-devtools-installer": "3.2.0", "electron-log": "4.4.8", "electron-store": "8.1.0", - "electron-updater": "5.3.0", + "electron-updater": "6.1.4", "elkjs": "0.8.2", "execa": "5.1.1", "fast-json-stable-stringify": "2.1.0", @@ -98,7 +98,7 @@ "@commitlint/cli": "17.6.3", "@commitlint/config-conventional": "17.6.3", "@craco/craco": "7.1.0", - "@electron/notarize": "1.2.3", + "@electron/notarize": "2.1.0", "@playwright/test": "1.34.0", "@sentry/webpack-plugin": "1.20.1", "@testing-library/jest-dom": "5.16.5", @@ -135,8 +135,8 @@ "concurrently": "8.0.1", "craco-less": "2.0.0", "cross-env": "7.0.3", - "electron": "24.1.1", - "electron-builder": "23.6.0", + "electron": "26.2.2", + "electron-builder": "24.6.4", "electron-reload": "2.0.0-alpha.1", "eslint-config-airbnb": "19.0.4", "eslint-config-prettier": "8.8.0", @@ -3370,8 +3370,9 @@ }, "node_modules/@develar/schema-utils": { "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", "dev": true, - "license": "MIT", "dependencies": { "ajv": "^6.12.0", "ajv-keywords": "^3.4.1" @@ -3386,8 +3387,9 @@ }, "node_modules/@develar/schema-utils/node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -3401,8 +3403,9 @@ }, "node_modules/@develar/schema-utils/node_modules/json-schema-traverse": { "version": "0.4.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true }, "node_modules/@dnd-kit/accessibility": { "version": "3.0.1", @@ -3449,6 +3452,23 @@ "react": ">=16.8.0" } }, + "node_modules/@electron/asar": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/@electron/asar/-/asar-3.2.7.tgz", + "integrity": "sha512-8FaSCAIiZGYFWyjeevPQt+0e9xCK9YmJ2Rjg5SXgdsXon6cRnU0Yxnbe6CvJbQn26baifur2Y2G5EBayRIsjyg==", + "dev": true, + "dependencies": { + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/@electron/get": { "version": "2.0.2", "dev": true, @@ -3507,12 +3527,14 @@ } }, "node_modules/@electron/notarize": { - "version": "1.2.3", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@electron/notarize/-/notarize-2.1.0.tgz", + "integrity": "sha512-Q02xem1D0sg4v437xHgmBLxI2iz/fc0D4K7fiVWHa/AnW8o7D751xyKNXgziA6HrTOme9ul1JfWN5ark8WH1xA==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^4.1.1", - "fs-extra": "^9.0.1" + "fs-extra": "^9.0.1", + "promise-retry": "^2.0.1" }, "engines": { "node": ">= 10.0.0" @@ -3532,15 +3554,63 @@ "node": ">=10" } }, + "node_modules/@electron/osx-sign": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@electron/osx-sign/-/osx-sign-1.0.5.tgz", + "integrity": "sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==", + "dev": true, + "dependencies": { + "compare-version": "^0.1.2", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "isbinaryfile": "^4.0.8", + "minimist": "^1.2.6", + "plist": "^3.0.5" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/@electron/osx-sign/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@electron/osx-sign/node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, "node_modules/@electron/universal": { - "version": "1.2.1", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.4.1.tgz", + "integrity": "sha512-lE/U3UNw1YHuowNbTmKNs9UlS3En3cPgwM5MI+agIgr/B1hSze9NdOP0qn7boZaI9Lph8IDv3/24g9IxnJP7aQ==", "dev": true, - "license": "MIT", "dependencies": { + "@electron/asar": "^3.2.1", "@malept/cross-spawn-promise": "^1.1.0", - "asar": "^3.1.0", "debug": "^4.3.1", - "dir-compare": "^2.4.0", + "dir-compare": "^3.0.0", "fs-extra": "^9.0.1", "minimatch": "^3.0.4", "plist": "^3.0.4" @@ -3551,8 +3621,9 @@ }, "node_modules/@electron/universal/node_modules/fs-extra": { "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, - "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -4634,6 +4705,8 @@ }, "node_modules/@malept/cross-spawn-promise": { "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", "dev": true, "funding": [ { @@ -4645,7 +4718,6 @@ "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" } ], - "license": "Apache-2.0", "dependencies": { "cross-spawn": "^7.0.1" }, @@ -4655,8 +4727,9 @@ }, "node_modules/@malept/flatpak-bundler": { "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", "dev": true, - "license": "MIT", "dependencies": { "debug": "^4.1.1", "fs-extra": "^9.0.0", @@ -4669,8 +4742,9 @@ }, "node_modules/@malept/flatpak-bundler/node_modules/fs-extra": { "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, - "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -5848,8 +5922,9 @@ }, "node_modules/@tootallnate/once": { "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "dev": true, - "license": "MIT", "engines": { "node": ">= 10" } @@ -6331,9 +6406,10 @@ "license": "MIT" }, "node_modules/@types/plist": { - "version": "3.0.2", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.3.tgz", + "integrity": "sha512-DXkBoKc7jwUR0p439icInmXXMJNhoImdpOrrgA5/nDFK7LVtcJ9MyQNKhJEKpEztnHGWnNWMWLOIR62By0Ln0A==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "@types/node": "*", @@ -6451,6 +6527,7 @@ }, "node_modules/@types/semver": { "version": "7.5.0", + "dev": true, "license": "MIT" }, "node_modules/@types/send": { @@ -6551,9 +6628,10 @@ "license": "MIT" }, "node_modules/@types/verror": { - "version": "1.10.6", + "version": "1.10.7", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.7.tgz", + "integrity": "sha512-4c5F4T0qMSoXq1KHx7WV1FMuD2h0xdaFoJ7HSVWUfQ8w5YbqCwLOA8K7/yy1I+Txuzvm417dnPUaLmqazX1F7g==", "dev": true, - "license": "MIT", "optional": true }, "node_modules/@types/wait-on": { @@ -7110,6 +7188,15 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@xmldom/xmldom": { + "version": "0.8.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", + "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==", + "dev": true, + "engines": { + "node": ">=10.0.0" + } + }, "node_modules/@xobotyi/scrollbar-width": { "version": "1.9.5", "license": "MIT" @@ -7131,8 +7218,9 @@ }, "node_modules/7zip-bin": { "version": "5.1.1", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.1.1.tgz", + "integrity": "sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==", + "dev": true }, "node_modules/abab": { "version": "2.0.6", @@ -7461,61 +7549,72 @@ }, "node_modules/app-builder-bin": { "version": "4.0.0", - "dev": true, - "license": "MIT" + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true }, "node_modules/app-builder-lib": { - "version": "23.6.0", + "version": "24.6.4", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-24.6.4.tgz", + "integrity": "sha512-m9931WXb83teb32N0rKg+ulbn6+Hl8NV5SUpVDOVz9MWOXfhV6AQtTdftf51zJJvCQnQugGtSqoLvgw6mdF/Rg==", "dev": true, - "license": "MIT", "dependencies": { "@develar/schema-utils": "~2.6.5", - "@electron/universal": "1.2.1", + "@electron/notarize": "2.1.0", + "@electron/osx-sign": "1.0.5", + "@electron/universal": "1.4.1", "@malept/flatpak-bundler": "^0.4.0", + "@types/fs-extra": "9.0.13", "7zip-bin": "~5.1.1", "async-exit-hook": "^2.0.1", "bluebird-lst": "^1.0.9", - "builder-util": "23.6.0", - "builder-util-runtime": "9.1.1", + "builder-util": "24.5.0", + "builder-util-runtime": "9.2.1", "chromium-pickle-js": "^0.2.0", "debug": "^4.3.4", - "ejs": "^3.1.7", - "electron-osx-sign": "^0.6.0", - "electron-publish": "23.6.0", + "ejs": "^3.1.8", + "electron-publish": "24.5.0", "form-data": "^4.0.0", "fs-extra": "^10.1.0", "hosted-git-info": "^4.1.0", "is-ci": "^3.0.0", - "isbinaryfile": "^4.0.10", + "isbinaryfile": "^5.0.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", - "minimatch": "^3.1.2", - "read-config-file": "6.2.0", + "minimatch": "^5.1.1", + "read-config-file": "6.3.2", "sanitize-filename": "^1.6.3", - "semver": "^7.3.7", - "tar": "^6.1.11", + "semver": "^7.3.8", + "tar": "^6.1.12", "temp-file": "^3.4.0" }, "engines": { "node": ">=14.0.0" } }, - "node_modules/app-builder-lib/node_modules/builder-util-runtime": { - "version": "9.1.1", + "node_modules/app-builder-lib/node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", "dev": true, - "license": "MIT", "dependencies": { - "debug": "^4.3.4", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" + "@types/node": "*" + } + }, + "node_modules/app-builder-lib/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" } }, "node_modules/app-builder-lib/node_modules/form-data": { "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", "dev": true, - "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -7527,8 +7626,9 @@ }, "node_modules/app-builder-lib/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -7538,6 +7638,18 @@ "node": ">=12" } }, + "node_modules/app-builder-lib/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/append-transform": { "version": "2.0.0", "dev": true, @@ -7752,8 +7864,9 @@ }, "node_modules/async-exit-hook": { "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -8255,6 +8368,8 @@ }, "node_modules/base64-js": { "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true, "funding": [ { @@ -8269,8 +8384,7 @@ "type": "consulting", "url": "https://feross.org/support" } - ], - "license": "MIT" + ] }, "node_modules/batch": { "version": "0.6.1", @@ -8328,8 +8442,9 @@ }, "node_modules/bluebird-lst": { "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", "dev": true, - "license": "MIT", "dependencies": { "bluebird": "^3.5.5" } @@ -8521,6 +8636,8 @@ }, "node_modules/buffer": { "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", "dev": true, "funding": [ { @@ -8536,27 +8653,12 @@ "url": "https://feross.org/support" } ], - "license": "MIT", "optional": true, "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, - "node_modules/buffer-alloc": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-alloc-unsafe": "^1.1.0", - "buffer-fill": "^1.0.0" - } - }, - "node_modules/buffer-alloc-unsafe": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, "node_modules/buffer-crc32": { "version": "0.2.13", "dev": true, @@ -8566,40 +8668,39 @@ } }, "node_modules/buffer-equal": { - "version": "1.0.0", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.1.tgz", + "integrity": "sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==", "dev": true, - "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/buffer-fill": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/buffer-from": { "version": "1.1.2", "dev": true, "license": "MIT" }, "node_modules/builder-util": { - "version": "23.6.0", + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-24.5.0.tgz", + "integrity": "sha512-STnBmZN/M5vGcv01u/K8l+H+kplTaq4PAIn3yeuufUKSpcdro0DhJWxPI81k5XcNfC//bjM3+n9nr8F9uV4uAQ==", "dev": true, - "license": "MIT", "dependencies": { "@types/debug": "^4.1.6", - "@types/fs-extra": "^9.0.11", "7zip-bin": "~5.1.1", "app-builder-bin": "4.0.0", "bluebird-lst": "^1.0.9", - "builder-util-runtime": "9.1.1", - "chalk": "^4.1.1", + "builder-util-runtime": "9.2.1", + "chalk": "^4.1.2", "cross-spawn": "^7.0.3", "debug": "^4.3.4", - "fs-extra": "^10.0.0", + "fs-extra": "^10.1.0", "http-proxy-agent": "^5.0.0", - "https-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.1", "is-ci": "^3.0.0", "js-yaml": "^4.1.0", "source-map-support": "^0.5.19", @@ -8609,27 +8710,6 @@ }, "node_modules/builder-util-runtime": { "version": "9.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/builder-util/node_modules/@types/fs-extra": { - "version": "9.0.13", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/builder-util/node_modules/builder-util-runtime": { - "version": "9.1.1", - "dev": true, "license": "MIT", "dependencies": { "debug": "^4.3.4", @@ -8641,8 +8721,9 @@ }, "node_modules/builder-util/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -9273,14 +9354,6 @@ "dev": true, "license": "MIT" }, - "node_modules/colors": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.1.90" - } - }, "node_modules/combined-stream": { "version": "1.0.8", "license": "MIT", @@ -9335,8 +9408,9 @@ }, "node_modules/compare-version": { "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", "dev": true, - "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9505,6 +9579,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/config-file-ts": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/config-file-ts/-/config-file-ts-0.2.4.tgz", + "integrity": "sha512-cKSW0BfrSaAUnxpgvpXPLaaW/umg4bqg4k3GO1JqlRfpx+d5W0GDXznCMkWotJQek5Mmz1MJVChQnz3IVaeMZQ==", + "dev": true, + "dependencies": { + "glob": "^7.1.6", + "typescript": "^4.0.2" + } + }, + "node_modules/config-file-ts/node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, "node_modules/confusing-browser-globals": { "version": "1.0.11", "dev": true, @@ -10049,8 +10146,9 @@ }, "node_modules/crc": { "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "buffer": "^5.1.0" @@ -11063,39 +11161,13 @@ } }, "node_modules/dir-compare": { - "version": "2.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-equal": "1.0.0", - "colors": "1.0.3", - "commander": "2.9.0", - "minimatch": "3.0.4" - }, - "bin": { - "dircompare": "src/cli/dircompare.js" - } - }, - "node_modules/dir-compare/node_modules/commander": { - "version": "2.9.0", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-readlink": ">= 1.0.0" - }, - "engines": { - "node": ">= 0.6.x" - } - }, - "node_modules/dir-compare/node_modules/minimatch": { - "version": "3.0.4", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-3.3.0.tgz", + "integrity": "sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==", "dev": true, - "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" + "buffer-equal": "^1.0.0", + "minimatch": "^3.0.4" } }, "node_modules/dir-glob": { @@ -11115,14 +11187,15 @@ "license": "MIT" }, "node_modules/dmg-builder": { - "version": "23.6.0", + "version": "24.6.4", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-24.6.4.tgz", + "integrity": "sha512-BNcHRc9CWEuI9qt0E655bUBU/j/3wUCYBVKGu1kVpbN5lcUdEJJJeiO0NHK3dgKmra6LUUZlo+mWqc+OCbi0zw==", "dev": true, - "license": "MIT", "dependencies": { - "app-builder-lib": "23.6.0", - "builder-util": "23.6.0", - "builder-util-runtime": "9.1.1", - "fs-extra": "^10.0.0", + "app-builder-lib": "24.6.4", + "builder-util": "24.5.0", + "builder-util-runtime": "9.2.1", + "fs-extra": "^10.1.0", "iconv-lite": "^0.6.2", "js-yaml": "^4.1.0" }, @@ -11130,22 +11203,11 @@ "dmg-license": "^1.0.11" } }, - "node_modules/dmg-builder/node_modules/builder-util-runtime": { - "version": "9.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/dmg-builder/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -11157,8 +11219,9 @@ }, "node_modules/dmg-license": { "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", "dev": true, - "license": "MIT", "optional": true, "os": [ "darwin" @@ -11182,8 +11245,9 @@ }, "node_modules/dmg-license/node_modules/ajv": { "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "fast-deep-equal": "^3.1.1", @@ -11198,8 +11262,9 @@ }, "node_modules/dmg-license/node_modules/json-schema-traverse": { "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, - "license": "MIT", "optional": true }, "node_modules/dns-equal": { @@ -11459,10 +11524,11 @@ } }, "node_modules/electron": { - "version": "24.1.1", + "version": "26.2.2", + "resolved": "https://registry.npmjs.org/electron/-/electron-26.2.2.tgz", + "integrity": "sha512-Ihb3Zt4XYnHF52DYSq17ySkgFqJV4OT0VnfhUYZASAql7Vembz3VsAq7mB3OALBHXltAW34P8BxTIwTqZaMS3g==", "dev": true, "hasInstallScript": true, - "license": "MIT", "dependencies": { "@electron/get": "^2.0.0", "@types/node": "^18.11.18", @@ -11476,22 +11542,22 @@ } }, "node_modules/electron-builder": { - "version": "23.6.0", + "version": "24.6.4", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-24.6.4.tgz", + "integrity": "sha512-uNWQoU7pE7qOaIQ6CJHpBi44RJFVG8OHRBIadUxrsDJVwLLo8Nma3K/EEtx5/UyWAQYdcK4nVPYKoRqBb20hbA==", "dev": true, - "license": "MIT", "dependencies": { - "@types/yargs": "^17.0.1", - "app-builder-lib": "23.6.0", - "builder-util": "23.6.0", - "builder-util-runtime": "9.1.1", - "chalk": "^4.1.1", - "dmg-builder": "23.6.0", - "fs-extra": "^10.0.0", + "app-builder-lib": "24.6.4", + "builder-util": "24.5.0", + "builder-util-runtime": "9.2.1", + "chalk": "^4.1.2", + "dmg-builder": "24.6.4", + "fs-extra": "^10.1.0", "is-ci": "^3.0.0", "lazy-val": "^1.0.5", - "read-config-file": "6.2.0", - "simple-update-notifier": "^1.0.7", - "yargs": "^17.5.1" + "read-config-file": "6.3.2", + "simple-update-notifier": "2.0.0", + "yargs": "^17.6.2" }, "bin": { "electron-builder": "cli.js", @@ -11501,18 +11567,6 @@ "node": ">=14.0.0" } }, - "node_modules/electron-builder/node_modules/builder-util-runtime": { - "version": "9.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/electron-builder/node_modules/fs-extra": { "version": "10.1.0", "dev": true, @@ -11540,88 +11594,35 @@ "version": "4.4.8", "license": "MIT" }, - "node_modules/electron-osx-sign": { - "version": "0.6.0", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "bluebird": "^3.5.0", - "compare-version": "^0.1.2", - "debug": "^2.6.8", - "isbinaryfile": "^3.0.2", - "minimist": "^1.2.0", - "plist": "^3.0.1" - }, - "bin": { - "electron-osx-flat": "bin/electron-osx-flat.js", - "electron-osx-sign": "bin/electron-osx-sign.js" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/electron-osx-sign/node_modules/debug": { - "version": "2.6.9", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "2.0.0" - } - }, - "node_modules/electron-osx-sign/node_modules/isbinaryfile": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-alloc": "^1.2.0" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/electron-osx-sign/node_modules/ms": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, "node_modules/electron-publish": { - "version": "23.6.0", + "version": "24.5.0", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-24.5.0.tgz", + "integrity": "sha512-zwo70suH15L15B4ZWNDoEg27HIYoPsGJUF7xevLJLSI7JUPC8l2yLBdLGwqueJ5XkDL7ucYyRZzxJVR8ElV9BA==", "dev": true, - "license": "MIT", "dependencies": { "@types/fs-extra": "^9.0.11", - "builder-util": "23.6.0", - "builder-util-runtime": "9.1.1", - "chalk": "^4.1.1", - "fs-extra": "^10.0.0", + "builder-util": "24.5.0", + "builder-util-runtime": "9.2.1", + "chalk": "^4.1.2", + "fs-extra": "^10.1.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" } }, "node_modules/electron-publish/node_modules/@types/fs-extra": { "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", "dev": true, - "license": "MIT", "dependencies": { "@types/node": "*" } }, - "node_modules/electron-publish/node_modules/builder-util-runtime": { - "version": "9.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/electron-publish/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -11666,29 +11667,18 @@ "license": "ISC" }, "node_modules/electron-updater": { - "version": "5.3.0", - "license": "MIT", + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-6.1.4.tgz", + "integrity": "sha512-yYAJc6RQjjV4WtInZVn+ZcLyXRhbVXoomKEfUUwDqIk5s2wxzLhWaor7lrNgxODyODhipjg4SVPMhJHi5EnsCA==", "dependencies": { - "@types/semver": "^7.3.6", - "builder-util-runtime": "9.1.1", - "fs-extra": "^10.0.0", + "builder-util-runtime": "9.2.1", + "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", "lodash.escaperegexp": "^4.1.2", "lodash.isequal": "^4.5.0", - "semver": "^7.3.5", - "typed-emitter": "^2.1.0" - } - }, - "node_modules/electron-updater/node_modules/builder-util-runtime": { - "version": "9.1.1", - "license": "MIT", - "dependencies": { - "debug": "^4.3.4", - "sax": "^1.2.4" - }, - "engines": { - "node": ">=12.0.0" + "semver": "^7.3.8", + "tiny-typed-emitter": "^2.1.0" } }, "node_modules/electron-updater/node_modules/fs-extra": { @@ -11779,6 +11769,12 @@ "node": ">=6" } }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "dev": true + }, "node_modules/errno": { "version": "0.1.8", "dev": true, @@ -14098,11 +14094,6 @@ "version": "4.2.11", "license": "ISC" }, - "node_modules/graceful-readlink": { - "version": "1.0.1", - "dev": true, - "license": "MIT" - }, "node_modules/grapheme-splitter": { "version": "1.0.4", "dev": true, @@ -14585,8 +14576,9 @@ }, "node_modules/http-proxy-agent": { "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "dev": true, - "license": "MIT", "dependencies": { "@tootallnate/once": "2", "agent-base": "6", @@ -14698,8 +14690,9 @@ }, "node_modules/iconv-corefoundation": { "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", "dev": true, - "license": "MIT", "optional": true, "os": [ "darwin" @@ -14752,6 +14745,8 @@ }, "node_modules/ieee754": { "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", "dev": true, "funding": [ { @@ -14767,7 +14762,6 @@ "url": "https://feross.org/support" } ], - "license": "BSD-3-Clause", "optional": true }, "node_modules/ignore": { @@ -15003,8 +14997,9 @@ }, "node_modules/is-ci": { "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", "dev": true, - "license": "MIT", "dependencies": { "ci-info": "^3.2.0" }, @@ -15399,11 +15394,12 @@ "license": "MIT" }, "node_modules/isbinaryfile": { - "version": "4.0.10", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-5.0.0.tgz", + "integrity": "sha512-UDdnyGvMajJUWCkib7Cei/dvyJrrvo4FIrsvSFWdPpXSUorzXrDJ0S+X5Q4ZlasfPjca4yqCNNsjbCeiy8FFeg==", "dev": true, - "license": "MIT", "engines": { - "node": ">= 8.0.0" + "node": ">= 14.0.0" }, "funding": { "url": "https://github.com/sponsors/gjtorikian/" @@ -19640,8 +19636,9 @@ }, "node_modules/mime": { "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", "dev": true, - "license": "MIT", "bin": { "mime": "cli.js" }, @@ -20027,8 +20024,9 @@ }, "node_modules/node-addon-api": { "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", "dev": true, - "license": "MIT", "optional": true }, "node_modules/node-domexception": { @@ -21150,15 +21148,17 @@ } }, "node_modules/plist": { - "version": "3.0.6", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz", + "integrity": "sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==", "dev": true, - "license": "MIT", "dependencies": { + "@xmldom/xmldom": "^0.8.8", "base64-js": "^1.5.1", "xmlbuilder": "^15.1.1" }, "engines": { - "node": ">=6" + "node": ">=10.4.0" } }, "node_modules/polished": { @@ -22471,6 +22471,28 @@ "asap": "~2.0.6" } }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "dev": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promise-retry/node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/prompts": { "version": "2.4.2", "dev": true, @@ -23622,10 +23644,12 @@ } }, "node_modules/read-config-file": { - "version": "6.2.0", + "version": "6.3.2", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.3.2.tgz", + "integrity": "sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==", "dev": true, - "license": "MIT", "dependencies": { + "config-file-ts": "^0.2.4", "dotenv": "^9.0.2", "dotenv-expand": "^5.1.0", "js-yaml": "^4.1.0", @@ -23638,8 +23662,9 @@ }, "node_modules/read-config-file/node_modules/dotenv": { "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", "dev": true, - "license": "BSD-2-Clause", "engines": { "node": ">=10" } @@ -24444,7 +24469,7 @@ }, "node_modules/rxjs": { "version": "7.8.1", - "devOptional": true, + "dev": true, "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" @@ -24514,8 +24539,9 @@ }, "node_modules/sanitize-filename": { "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", "dev": true, - "license": "WTFPL OR ISC", "dependencies": { "truncate-utf8-bytes": "^1.0.0" } @@ -24940,22 +24966,30 @@ } }, "node_modules/simple-update-notifier": { - "version": "1.1.0", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", "dev": true, - "license": "MIT", "dependencies": { - "semver": "~7.0.0" + "semver": "^7.5.3" }, "engines": { - "node": ">=8.10.0" + "node": ">=10" } }, "node_modules/simple-update-notifier/node_modules/semver": { - "version": "7.0.0", + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", "dev": true, - "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, "bin": { "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/sisteransi": { @@ -24994,8 +25028,9 @@ }, "node_modules/smart-buffer": { "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", "dev": true, - "license": "MIT", "optional": true, "engines": { "node": ">= 6.0.0", @@ -25453,8 +25488,9 @@ }, "node_modules/stat-mode": { "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", "dev": true, - "license": "MIT", "engines": { "node": ">= 6" } @@ -26600,8 +26636,9 @@ }, "node_modules/temp-file": { "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", "dev": true, - "license": "MIT", "dependencies": { "async-exit-hook": "^2.0.1", "fs-extra": "^10.0.0" @@ -26609,8 +26646,9 @@ }, "node_modules/temp-file/node_modules/fs-extra": { "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, - "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", @@ -26819,6 +26857,11 @@ "version": "1.3.1", "license": "MIT" }, + "node_modules/tiny-typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-typed-emitter/-/tiny-typed-emitter-2.1.0.tgz", + "integrity": "sha512-qVtvMxeXbVej0cQWKqVSSAHmKZEHAvxdF8HEUBFWts8h+xEo5m/lEiPakuyZ3BnCBjOD8i24kzNOiOLLgsSxhA==" + }, "node_modules/titleize": { "version": "3.0.0", "dev": true, @@ -26952,8 +26995,9 @@ }, "node_modules/truncate-utf8-bytes": { "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", "dev": true, - "license": "WTFPL", "dependencies": { "utf8-byte-length": "^1.0.1" } @@ -27198,13 +27242,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/typed-emitter": { - "version": "2.1.0", - "license": "MIT", - "optionalDependencies": { - "rxjs": "*" - } - }, "node_modules/typedarray": { "version": "0.0.6", "dev": true, @@ -27547,8 +27584,9 @@ }, "node_modules/utf8-byte-length": { "version": "1.0.4", - "dev": true, - "license": "WTFPL" + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==", + "dev": true }, "node_modules/util-deprecate": { "version": "1.0.2", @@ -27694,8 +27732,9 @@ }, "node_modules/verror": { "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", "dev": true, - "license": "MIT", "optional": true, "dependencies": { "assert-plus": "^1.0.0", @@ -28711,8 +28750,9 @@ }, "node_modules/xmlbuilder": { "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", "dev": true, - "license": "MIT", "engines": { "node": ">=8.0" } diff --git a/package.json b/package.json index cc20717a2d..7cbf425314 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "@commitlint/cli": "17.6.3", "@commitlint/config-conventional": "17.6.3", "@craco/craco": "7.1.0", - "@electron/notarize": "1.2.3", + "@electron/notarize": "2.1.0", "@playwright/test": "1.34.0", "@sentry/webpack-plugin": "1.20.1", "@testing-library/jest-dom": "5.16.5", @@ -63,8 +63,8 @@ "concurrently": "8.0.1", "craco-less": "2.0.0", "cross-env": "7.0.3", - "electron": "24.1.1", - "electron-builder": "23.6.0", + "electron": "26.2.2", + "electron-builder": "24.6.4", "electron-reload": "2.0.0-alpha.1", "eslint-config-airbnb": "19.0.4", "eslint-config-prettier": "8.8.0", @@ -123,7 +123,7 @@ "electron-devtools-installer": "3.2.0", "electron-log": "4.4.8", "electron-store": "8.1.0", - "electron-updater": "5.3.0", + "electron-updater": "6.1.4", "elkjs": "0.8.2", "execa": "5.1.1", "fast-json-stable-stringify": "2.1.0", From f46231057dbd6a4accc5a0cb8276dccf5ab5c7ed Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:28:52 +0300 Subject: [PATCH 41/49] chore: add release notes for 2.4 --- resources/releaseNotes/2.4/2.4.json | 9 + resources/releaseNotes/2.4/2.4.md | 6 + resources/releaseNotes/2.4/2.4.svg | 248 ++++++++++++++++++++++++++++ 3 files changed, 263 insertions(+) create mode 100644 resources/releaseNotes/2.4/2.4.json create mode 100644 resources/releaseNotes/2.4/2.4.md create mode 100644 resources/releaseNotes/2.4/2.4.svg diff --git a/resources/releaseNotes/2.4/2.4.json b/resources/releaseNotes/2.4/2.4.json new file mode 100644 index 0000000000..2f959b06c9 --- /dev/null +++ b/resources/releaseNotes/2.4/2.4.json @@ -0,0 +1,9 @@ +{ + "title": "Welcome to Monokle 2.4", + "learnMoreUrl": "https://monokle.io/blog/monokle-2-4-release", + "about": { + "when": "September 2023", + "title": "2.4 focused on:", + "features": ["Sync with Cloud", "Bug fixes", "Stability improvements"] + } +} diff --git a/resources/releaseNotes/2.4/2.4.md b/resources/releaseNotes/2.4/2.4.md new file mode 100644 index 0000000000..15a16dceb3 --- /dev/null +++ b/resources/releaseNotes/2.4/2.4.md @@ -0,0 +1,6 @@ +Here's what we've been working on: +- Seamless connection with Monokle Cloud +- Automatic Policy synchronization +- Cloud connection status indicator +- Minor fixes and UI enhancements +- [Read our blog post for more details →](https://monokle.io/blog/monokle-2-4-release) diff --git a/resources/releaseNotes/2.4/2.4.svg b/resources/releaseNotes/2.4/2.4.svg new file mode 100644 index 0000000000..c827d0d234 --- /dev/null +++ b/resources/releaseNotes/2.4/2.4.svg @@ -0,0 +1,248 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f86db89349a65f609c922ce034ebb75721c66712 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 27 Sep 2023 11:33:53 +0300 Subject: [PATCH 42/49] chore(release): 2.4.0 --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a21d1571e..d197d99d70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,32 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.4.0](https://github.com/kubeshop/monokle/compare/v2.3.4-nightly-2023-09-27.0...v2.4.0) (2023-09-27) + + +### Features + +* add link to cloud project ([d4ea235](https://github.com/kubeshop/monokle/commit/d4ea2355d2ddd1eef6aa890bfe7a8d6af24b8198)) +* Cloud disconnect ([7dd8d4e](https://github.com/kubeshop/monokle/commit/7dd8d4e7e35a88c70e4a8293f5cc43d1ce834181)) +* cloud ipc ([ee3abdd](https://github.com/kubeshop/monokle/commit/ee3abdd7191a993d47911dfab3ee4dc6be442b2e)) +* cloud login ([95d2702](https://github.com/kubeshop/monokle/commit/95d2702311777223dd656d01037ba30116e80b0f)) +* CloudConnect component ([691a8c7](https://github.com/kubeshop/monokle/commit/691a8c7dd112a9a090a2d248884ee2052199b4a8)) +* CloudSync component ([d634e83](https://github.com/kubeshop/monokle/commit/d634e8361f5359361ec68d3e231d73f687f39f17)) +* display cloud project for policy ([b6cc53c](https://github.com/kubeshop/monokle/commit/b6cc53cb96c6cddf3b6f8bc2f2923519099d033e)) +* fetch cloud user ([e5828f9](https://github.com/kubeshop/monokle/commit/e5828f9b0a63ec54f6e12183b7d9eec26a9244dc)) +* fetch policy ([47df598](https://github.com/kubeshop/monokle/commit/47df5989e562c37f733f19dfd573a31688049b73)) +* notify policy in overview ([d1a83ba](https://github.com/kubeshop/monokle/commit/d1a83ba0f83882c7c4d55f9e6e0898bd06acb186)) +* send notifications about Policy ([112ff17](https://github.com/kubeshop/monokle/commit/112ff1790fe4c0135c2e6fa0c05348961e2028c8)) +* setup cloud authenticator ([9941ff9](https://github.com/kubeshop/monokle/commit/9941ff98855709ec5a4c62afc5aa49d99038e9fe)) +* setup cloud synchronizer ([c1039ee](https://github.com/kubeshop/monokle/commit/c1039ee710902017879328be2dda19333501fab7)) + + +### Bug Fixes + +* CloudSync icon UI ([cee9eaa](https://github.com/kubeshop/monokle/commit/cee9eaaf1cd0938143c1209a309738b5db364cc0)) +* policy hooks ([cd991eb](https://github.com/kubeshop/monokle/commit/cd991ebe29287518da36e16a54a6897d6e26f8b9)) +* user expired cloud token ([478ff3a](https://github.com/kubeshop/monokle/commit/478ff3a0dd29652181c7b1ff5e0f018793f7a049)) + ### [2.3.3](https://github.com/kubeshop/monokle/compare/v2.3.3-nightly-2023-07-26.0...v2.3.3) (2023-07-26) diff --git a/package-lock.json b/package-lock.json index 8ddc5c686c..2914f054a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "monokle", - "version": "2.3.3", + "version": "2.4.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "monokle", - "version": "2.3.3", + "version": "2.4.0", "hasInstallScript": true, "dependencies": { "@ant-design/icons": "4.8.0", diff --git a/package.json b/package.json index 7cbf425314..9f261c12ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "monokle", - "version": "2.3.3", + "version": "2.4.0", "author": "Kubeshop", "description": "UI for managing k8s manifests", "homepage": "./", From e94997ccb5654e4c9e7f791b394e701203283731 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Wed, 27 Sep 2023 16:23:42 +0300 Subject: [PATCH 43/49] chore: use notarytool --- notarization/afterSignHook.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/notarization/afterSignHook.js b/notarization/afterSignHook.js index 6fdb5739b2..2f43bcf260 100644 --- a/notarization/afterSignHook.js +++ b/notarization/afterSignHook.js @@ -32,10 +32,11 @@ module.exports = async function (params) { try { await electron_notarize.notarize({ + tool: 'notarytool', appBundleId: appId, appPath: appPath, appleId: process.env.APPLE_ID, - appleIdPassword: process.env.APPLE_ID_PASSWORD, + appleIdPassword: process.env.APPLE_APP_SPECIFIC_PASSWORD, }); } catch (error) { log.error(error); From c9c0a12cb21eb65d99aa315082ff1501ef692b07 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Thu, 28 Sep 2023 14:06:58 +0300 Subject: [PATCH 44/49] feat: compare clusters in quick cluster mode --- .../organisms/PaneManager/activities.tsx | 2 +- .../ResourceSetTypeSelect.tsx | 43 +++++++++++++------ 2 files changed, 31 insertions(+), 14 deletions(-) diff --git a/src/components/organisms/PaneManager/activities.tsx b/src/components/organisms/PaneManager/activities.tsx index 08811a8d01..ed6bc96707 100644 --- a/src/components/organisms/PaneManager/activities.tsx +++ b/src/components/organisms/PaneManager/activities.tsx @@ -38,7 +38,7 @@ export const activities: ActivityType[] = [ icon: () => , component: , useBadge: () => undefined, - isVisible: () => Boolean(useAppSelector(activeProjectSelector)), + isVisible: () => Boolean(useAppSelector(activeProjectSelector)) || Boolean(useAppSelector(isInClusterModeSelector)), }, { type: 'panel', diff --git a/src/components/organisms/ResourceSetSelector/ResourceSetTypeSelect.tsx b/src/components/organisms/ResourceSetSelector/ResourceSetTypeSelect.tsx index d208600cba..661667ed9f 100644 --- a/src/components/organisms/ResourceSetSelector/ResourceSetTypeSelect.tsx +++ b/src/components/organisms/ResourceSetSelector/ResourceSetTypeSelect.tsx @@ -1,4 +1,5 @@ import {useCallback} from 'react'; +import {useMount} from 'react-use'; import {Select} from 'antd'; @@ -19,6 +20,8 @@ type Props = { export const ResourceSetTypeSelect: React.FC = ({side}) => { const dispatch = useAppDispatch(); + const currentContext = useAppSelector(state => state.main.clusterConnection?.context); + const isInQuickClusterMode = useAppSelector(state => state.ui.isInQuickClusterMode); const isGitDisabled = useAppSelector(state => Boolean(!state.git.repo)); const isHelmDisabled = useAppSelector(state => isEmpty(state.main.helmChartMap)); const isCommandDisabled = useAppSelector(state => @@ -29,6 +32,16 @@ export const ResourceSetTypeSelect: React.FC = ({side}) => { const isKustomizeDisabled = useAppSelector(state => isEmpty(kustomizationsSelector(state))); const resourceSet = useAppSelector(state => selectResourceSet(state.compare, side)); + useMount(() => { + if (!isInQuickClusterMode) return; + if (side === 'left') { + dispatch(resourceSetSelected({side, value: {type: 'cluster', context: currentContext}})); + } + if (side === 'right') { + dispatch(resourceSetSelected({side, value: {type: 'cluster'}})); + } + }); + const handleSelectType = useCallback( (type: ResourceSet['type']) => { if (type === 'local' || type === 'git') { @@ -48,22 +61,26 @@ export const ResourceSetTypeSelect: React.FC = ({side}) => { value={resourceSet?.type === 'helm-custom' ? 'helm' : resourceSet?.type} style={{width: 180}} > - Local + {!isInQuickClusterMode && Local} Cluster - - Helm Preview - - - Kustomize Preview - - - Git - - - Command - + {!isInQuickClusterMode && ( + <> + + Helm Preview + + + Kustomize Preview + + + Git + + + Command + + + )} ); From ea3b57e5b5df9b9bd175197f7e1db5f54c25d96b Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Thu, 28 Sep 2023 14:16:36 +0300 Subject: [PATCH 45/49] chore: revert release --- CHANGELOG.md | 26 -------------------------- package.json | 2 +- 2 files changed, 1 insertion(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d197d99d70..1a21d1571e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,32 +2,6 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. -## [2.4.0](https://github.com/kubeshop/monokle/compare/v2.3.4-nightly-2023-09-27.0...v2.4.0) (2023-09-27) - - -### Features - -* add link to cloud project ([d4ea235](https://github.com/kubeshop/monokle/commit/d4ea2355d2ddd1eef6aa890bfe7a8d6af24b8198)) -* Cloud disconnect ([7dd8d4e](https://github.com/kubeshop/monokle/commit/7dd8d4e7e35a88c70e4a8293f5cc43d1ce834181)) -* cloud ipc ([ee3abdd](https://github.com/kubeshop/monokle/commit/ee3abdd7191a993d47911dfab3ee4dc6be442b2e)) -* cloud login ([95d2702](https://github.com/kubeshop/monokle/commit/95d2702311777223dd656d01037ba30116e80b0f)) -* CloudConnect component ([691a8c7](https://github.com/kubeshop/monokle/commit/691a8c7dd112a9a090a2d248884ee2052199b4a8)) -* CloudSync component ([d634e83](https://github.com/kubeshop/monokle/commit/d634e8361f5359361ec68d3e231d73f687f39f17)) -* display cloud project for policy ([b6cc53c](https://github.com/kubeshop/monokle/commit/b6cc53cb96c6cddf3b6f8bc2f2923519099d033e)) -* fetch cloud user ([e5828f9](https://github.com/kubeshop/monokle/commit/e5828f9b0a63ec54f6e12183b7d9eec26a9244dc)) -* fetch policy ([47df598](https://github.com/kubeshop/monokle/commit/47df5989e562c37f733f19dfd573a31688049b73)) -* notify policy in overview ([d1a83ba](https://github.com/kubeshop/monokle/commit/d1a83ba0f83882c7c4d55f9e6e0898bd06acb186)) -* send notifications about Policy ([112ff17](https://github.com/kubeshop/monokle/commit/112ff1790fe4c0135c2e6fa0c05348961e2028c8)) -* setup cloud authenticator ([9941ff9](https://github.com/kubeshop/monokle/commit/9941ff98855709ec5a4c62afc5aa49d99038e9fe)) -* setup cloud synchronizer ([c1039ee](https://github.com/kubeshop/monokle/commit/c1039ee710902017879328be2dda19333501fab7)) - - -### Bug Fixes - -* CloudSync icon UI ([cee9eaa](https://github.com/kubeshop/monokle/commit/cee9eaaf1cd0938143c1209a309738b5db364cc0)) -* policy hooks ([cd991eb](https://github.com/kubeshop/monokle/commit/cd991ebe29287518da36e16a54a6897d6e26f8b9)) -* user expired cloud token ([478ff3a](https://github.com/kubeshop/monokle/commit/478ff3a0dd29652181c7b1ff5e0f018793f7a049)) - ### [2.3.3](https://github.com/kubeshop/monokle/compare/v2.3.3-nightly-2023-07-26.0...v2.3.3) (2023-07-26) diff --git a/package.json b/package.json index 9f261c12ca..7cbf425314 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "monokle", - "version": "2.4.0", + "version": "2.3.3", "author": "Kubeshop", "description": "UI for managing k8s manifests", "homepage": "./", From 905f886356d0ad3ba787b4e8a7e121b463b20790 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Thu, 28 Sep 2023 14:17:25 +0300 Subject: [PATCH 46/49] chore: set env variables for build --- .github/workflows/monokle-build-nightly.yml | 1 + .github/workflows/monokle-publish-downloads.yml | 1 + .github/workflows/monokle-publish-test.yml | 1 + .github/workflows/monokle-publish-updater.yml | 1 + .github/workflows/monokle-publish.yml | 1 + 5 files changed, 5 insertions(+) diff --git a/.github/workflows/monokle-build-nightly.yml b/.github/workflows/monokle-build-nightly.yml index 1fbe0a6439..dc032c4d31 100644 --- a/.github/workflows/monokle-build-nightly.yml +++ b/.github/workflows/monokle-build-nightly.yml @@ -114,6 +114,7 @@ jobs: CSC_KEY_PASSWORD: ${{ secrets.MONOKLE_MACOS_CERTS_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} USE_HARD_LINKS: false - name: Create release and upload artifacts diff --git a/.github/workflows/monokle-publish-downloads.yml b/.github/workflows/monokle-publish-downloads.yml index 6c2270b2c3..9281b0ffa5 100644 --- a/.github/workflows/monokle-publish-downloads.yml +++ b/.github/workflows/monokle-publish-downloads.yml @@ -108,6 +108,7 @@ jobs: CSC_KEY_PASSWORD: ${{ secrets.MONOKLE_MACOS_CERTS_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} USE_HARD_LINKS: false # Check Binary Size diff --git a/.github/workflows/monokle-publish-test.yml b/.github/workflows/monokle-publish-test.yml index 06226dae97..7cc4c359c2 100644 --- a/.github/workflows/monokle-publish-test.yml +++ b/.github/workflows/monokle-publish-test.yml @@ -107,6 +107,7 @@ jobs: CSC_KEY_PASSWORD: ${{ secrets.MONOKLE_MACOS_CERTS_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} USE_HARD_LINKS: false # Check Binary Size diff --git a/.github/workflows/monokle-publish-updater.yml b/.github/workflows/monokle-publish-updater.yml index 04474b3210..1272a7bb9d 100644 --- a/.github/workflows/monokle-publish-updater.yml +++ b/.github/workflows/monokle-publish-updater.yml @@ -107,6 +107,7 @@ jobs: CSC_KEY_PASSWORD: ${{ secrets.MONOKLE_MACOS_CERTS_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} USE_HARD_LINKS: false # Check Binary Size diff --git a/.github/workflows/monokle-publish.yml b/.github/workflows/monokle-publish.yml index 737eb49fd0..4d0ec10c89 100644 --- a/.github/workflows/monokle-publish.yml +++ b/.github/workflows/monokle-publish.yml @@ -102,6 +102,7 @@ jobs: CSC_KEY_PASSWORD: ${{ secrets.MONOKLE_MACOS_CERTS_PASSWORD }} APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} USE_HARD_LINKS: false # Check Binary Size From 02855af18924baa89110be60ebbcab95441c9492 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Thu, 28 Sep 2023 14:17:35 +0300 Subject: [PATCH 47/49] chore(release): 2.4.0 --- CHANGELOG.md | 7 +++++++ package.json | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1a21d1571e..80937fc39a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +## [2.4.0](https://github.com/kubeshop/monokle/compare/v2.4.1-nightly-2023-09-28.0...v2.4.0) (2023-09-28) + + +### Features + +* compare clusters in quick cluster mode ([c9c0a12](https://github.com/kubeshop/monokle/commit/c9c0a12cb21eb65d99aa315082ff1501ef692b07)) + ### [2.3.3](https://github.com/kubeshop/monokle/compare/v2.3.3-nightly-2023-07-26.0...v2.3.3) (2023-07-26) diff --git a/package.json b/package.json index 7cbf425314..9f261c12ca 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "monokle", - "version": "2.3.3", + "version": "2.4.0", "author": "Kubeshop", "description": "UI for managing k8s manifests", "homepage": "./", From eb432808b3e8779856bb3900968893c24fc9b367 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Thu, 28 Sep 2023 15:22:40 +0300 Subject: [PATCH 48/49] fix: macos notarization --- package.json | 1 + 1 file changed, 1 insertion(+) diff --git a/package.json b/package.json index 9f261c12ca..6c27529607 100644 --- a/package.json +++ b/package.json @@ -211,6 +211,7 @@ "productName": "Monokle", "copyright": "Copyright © 2021 ${author}", "mac": { + "notarize": false, "category": "public.app-category.utilities", "icon": "build/icon.png", "hardenedRuntime": true, From d8685973742dd37ec4a5fd470067f94e009d84f6 Mon Sep 17 00:00:00 2001 From: Dev Catalin <20538711+devcatalin@users.noreply.github.com> Date: Thu, 28 Sep 2023 16:04:55 +0300 Subject: [PATCH 49/49] fix: set team id for building --- .github/workflows/monokle-build-nightly.yml | 1 + .github/workflows/monokle-publish-downloads.yml | 1 + .github/workflows/monokle-publish-test.yml | 1 + .github/workflows/monokle-publish-updater.yml | 1 + .github/workflows/monokle-publish.yml | 1 + notarization/afterSignHook.js | 1 + 6 files changed, 6 insertions(+) diff --git a/.github/workflows/monokle-build-nightly.yml b/.github/workflows/monokle-build-nightly.yml index dc032c4d31..b6c01a1f8f 100644 --- a/.github/workflows/monokle-build-nightly.yml +++ b/.github/workflows/monokle-build-nightly.yml @@ -115,6 +115,7 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} USE_HARD_LINKS: false - name: Create release and upload artifacts diff --git a/.github/workflows/monokle-publish-downloads.yml b/.github/workflows/monokle-publish-downloads.yml index 9281b0ffa5..d24139a366 100644 --- a/.github/workflows/monokle-publish-downloads.yml +++ b/.github/workflows/monokle-publish-downloads.yml @@ -109,6 +109,7 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} USE_HARD_LINKS: false # Check Binary Size diff --git a/.github/workflows/monokle-publish-test.yml b/.github/workflows/monokle-publish-test.yml index 7cc4c359c2..8b9b832785 100644 --- a/.github/workflows/monokle-publish-test.yml +++ b/.github/workflows/monokle-publish-test.yml @@ -108,6 +108,7 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} USE_HARD_LINKS: false # Check Binary Size diff --git a/.github/workflows/monokle-publish-updater.yml b/.github/workflows/monokle-publish-updater.yml index 1272a7bb9d..a01a7ec3d4 100644 --- a/.github/workflows/monokle-publish-updater.yml +++ b/.github/workflows/monokle-publish-updater.yml @@ -108,6 +108,7 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} USE_HARD_LINKS: false # Check Binary Size diff --git a/.github/workflows/monokle-publish.yml b/.github/workflows/monokle-publish.yml index 4d0ec10c89..a8ba14ba99 100644 --- a/.github/workflows/monokle-publish.yml +++ b/.github/workflows/monokle-publish.yml @@ -103,6 +103,7 @@ jobs: APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} USE_HARD_LINKS: false # Check Binary Size diff --git a/notarization/afterSignHook.js b/notarization/afterSignHook.js index 2f43bcf260..fd1657c74e 100644 --- a/notarization/afterSignHook.js +++ b/notarization/afterSignHook.js @@ -33,6 +33,7 @@ module.exports = async function (params) { try { await electron_notarize.notarize({ tool: 'notarytool', + teamId: process.env.APPLE_TEAM_ID, appBundleId: appId, appPath: appPath, appleId: process.env.APPLE_ID,