diff --git a/packages/nc-gui-v2/components.d.ts b/packages/nc-gui-v2/components.d.ts index 72c980072e..f5e940f2ba 100644 --- a/packages/nc-gui-v2/components.d.ts +++ b/packages/nc-gui-v2/components.d.ts @@ -19,6 +19,7 @@ declare module '@vue/runtime-core' { ADatePicker: typeof import('ant-design-vue/es')['DatePicker'] ADivider: typeof import('ant-design-vue/es')['Divider'] ADropdown: typeof import('ant-design-vue/es')['Dropdown'] + ADropdownButton: typeof import('ant-design-vue/es')['DropdownButton'] AForm: typeof import('ant-design-vue/es')['Form'] AFormItem: typeof import('ant-design-vue/es')['FormItem'] AInput: typeof import('ant-design-vue/es')['Input'] diff --git a/packages/nc-gui-v2/components/dashboard/settings/SettingsModal.vue b/packages/nc-gui-v2/components/dashboard/settings/SettingsModal.vue index b3eb076fa7..207152df00 100644 --- a/packages/nc-gui-v2/components/dashboard/settings/SettingsModal.vue +++ b/packages/nc-gui-v2/components/dashboard/settings/SettingsModal.vue @@ -4,6 +4,7 @@ import AuditTab from './AuditTab.vue' import AppStore from './AppStore.vue' import Metadata from './Metadata.vue' import UIAcl from './UIAcl.vue' +import UserManagement from './UserManagement.vue' import StoreFrontOutline from '~icons/mdi/storefront-outline' import TeamFillIcon from '~icons/ri/team-fill' import MultipleTableIcon from '~icons/mdi/table-multiple' @@ -39,7 +40,7 @@ const tabsInfo: TabGroup = { subTabs: { usersManagement: { title: 'Users Management', - body: () => AuditTab, + body: () => UserManagement, }, apiTokenManagement: { title: 'API Token Management', diff --git a/packages/nc-gui-v2/components/dashboard/settings/UserManagement.vue b/packages/nc-gui-v2/components/dashboard/settings/UserManagement.vue new file mode 100644 index 0000000000..dd7c683ac1 --- /dev/null +++ b/packages/nc-gui-v2/components/dashboard/settings/UserManagement.vue @@ -0,0 +1,247 @@ + + + + + diff --git a/packages/nc-gui-v2/components/dashboard/settings/userManagement/ShareBase.vue b/packages/nc-gui-v2/components/dashboard/settings/userManagement/ShareBase.vue new file mode 100644 index 0000000000..54cf704f0e --- /dev/null +++ b/packages/nc-gui-v2/components/dashboard/settings/userManagement/ShareBase.vue @@ -0,0 +1,209 @@ + + + + + diff --git a/packages/nc-gui-v2/components/dashboard/settings/userManagement/UsersModal.vue b/packages/nc-gui-v2/components/dashboard/settings/userManagement/UsersModal.vue new file mode 100644 index 0000000000..3f14d324b0 --- /dev/null +++ b/packages/nc-gui-v2/components/dashboard/settings/userManagement/UsersModal.vue @@ -0,0 +1,215 @@ + + + + + diff --git a/packages/nc-gui-v2/lib/enums.ts b/packages/nc-gui-v2/lib/enums.ts index d2705374bc..11acd9ae1c 100644 --- a/packages/nc-gui-v2/lib/enums.ts +++ b/packages/nc-gui-v2/lib/enums.ts @@ -4,6 +4,13 @@ export enum Role { User = 'user', } +export enum ProjectRole { + Owner = 'owner', + Editor = 'editor', + User = 'user', + Guest = 'guest', +} + export enum ClientType { MYSQL = 'mysql2', MSSQL = 'mssql', diff --git a/packages/nc-gui-v2/package-lock.json b/packages/nc-gui-v2/package-lock.json index b80358c982..8a97243ea7 100644 --- a/packages/nc-gui-v2/package-lock.json +++ b/packages/nc-gui-v2/package-lock.json @@ -26,7 +26,9 @@ "devDependencies": { "@antfu/eslint-config": "^0.25.2", "@iconify-json/clarity": "^1.1.4", + "@iconify-json/eva": "^1.1.2", "@iconify-json/ic": "^1.1.7", + "@iconify-json/lucide": "^1.1.36", "@iconify-json/material-symbols": "^1.1.8", "@iconify-json/mdi": "^1.1.25", "@iconify-json/ri": "^1.1.3", @@ -10427,6 +10429,15 @@ "@iconify/types": "*" } }, + "node_modules/@iconify-json/eva": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@iconify-json/eva/-/eva-1.1.2.tgz", + "integrity": "sha512-4n3sAzXYH4vX2ehi2+kMPP7VHM1TTZ2AKJyUrAogAdbEKWhHr891huFhOSZPRJ9F2/4D4Us8SjRxBHYyUvX80w==", + "dev": true, + "dependencies": { + "@iconify/types": "*" + } + }, "node_modules/@iconify-json/ic": { "version": "1.1.7", "dev": true, @@ -10435,6 +10446,15 @@ "@iconify/types": "*" } }, + "node_modules/@iconify-json/lucide": { + "version": "1.1.37", + "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.1.37.tgz", + "integrity": "sha512-GfeDEy61ols35CYLfNxQWCIWdVTf/V0GI29D5IT74ToxcwqjtInQ6YVeNJCfKSGsTnnuyG+M6drd6YXLEfdjvQ==", + "dev": true, + "dependencies": { + "@iconify/types": "*" + } + }, "node_modules/@iconify-json/material-symbols": { "version": "1.1.8", "dev": true, @@ -23062,6 +23082,15 @@ "@iconify/types": "*" } }, + "@iconify-json/eva": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@iconify-json/eva/-/eva-1.1.2.tgz", + "integrity": "sha512-4n3sAzXYH4vX2ehi2+kMPP7VHM1TTZ2AKJyUrAogAdbEKWhHr891huFhOSZPRJ9F2/4D4Us8SjRxBHYyUvX80w==", + "dev": true, + "requires": { + "@iconify/types": "*" + } + }, "@iconify-json/ic": { "version": "1.1.7", "dev": true, @@ -23069,6 +23098,15 @@ "@iconify/types": "*" } }, + "@iconify-json/lucide": { + "version": "1.1.37", + "resolved": "https://registry.npmjs.org/@iconify-json/lucide/-/lucide-1.1.37.tgz", + "integrity": "sha512-GfeDEy61ols35CYLfNxQWCIWdVTf/V0GI29D5IT74ToxcwqjtInQ6YVeNJCfKSGsTnnuyG+M6drd6YXLEfdjvQ==", + "dev": true, + "requires": { + "@iconify/types": "*" + } + }, "@iconify-json/material-symbols": { "version": "1.1.8", "dev": true, diff --git a/packages/nc-gui-v2/package.json b/packages/nc-gui-v2/package.json index 2ade8b06ff..38f3be3d54 100644 --- a/packages/nc-gui-v2/package.json +++ b/packages/nc-gui-v2/package.json @@ -32,7 +32,9 @@ "devDependencies": { "@antfu/eslint-config": "^0.25.2", "@iconify-json/clarity": "^1.1.4", + "@iconify-json/eva": "^1.1.2", "@iconify-json/ic": "^1.1.7", + "@iconify-json/lucide": "^1.1.36", "@iconify-json/material-symbols": "^1.1.8", "@iconify-json/mdi": "^1.1.25", "@iconify-json/ri": "^1.1.3", diff --git a/packages/nc-gui-v2/utils/miscUtils.ts b/packages/nc-gui-v2/utils/miscUtils.ts new file mode 100644 index 0000000000..6506fd9df7 --- /dev/null +++ b/packages/nc-gui-v2/utils/miscUtils.ts @@ -0,0 +1,56 @@ +export const copyTextToClipboard = (text: string) => { + const textArea = document.createElement('textarea') + + // + // *** This styling is an extra step which is likely not required. *** + // + // Why is it here? To ensure: + // 1. the element is able to have focus and selection. + // 2. if element was to flash render it has minimal visual impact. + // 3. less flakyness with selection and copying which **might** occur if + // the textarea element is not visible. + // + // The likelihood is the element won't even render, not even a + // flash, so some of these are just precautions. However in + // Internet Explorer the element is visible whilst the popup + // box asking the user for permission for the web page to + // copy to the clipboard. + // + + // Place in top-left corner of screen regardless of scroll position. + textArea.style.position = 'fixed' + textArea.style.top = '0' + textArea.style.left = '0' + + // Ensure it has a small width and height. Setting to 1px / 1em + // doesn't work as this gives a negative w/h on some browsers. + textArea.style.width = '2em' + textArea.style.height = '2em' + + // We don't need padding, reducing the size if it does flash render. + textArea.style.padding = '0' + + // Clean up any borders. + textArea.style.border = 'none' + textArea.style.outline = 'none' + textArea.style.boxShadow = 'none' + + // Avoid flash of white box if rendered for any reason. + textArea.style.background = 'transparent' + + textArea.addEventListener('focusin', (e) => e.stopPropagation()) + + textArea.value = text + + document.body.appendChild(textArea) + textArea.focus() + textArea.select() + + try { + document.execCommand('copy') + } catch (err) { + console.log('Oops, unable to copy') + } + + document.body.removeChild(textArea) +} diff --git a/packages/nc-gui-v2/utils/urlUtils.ts b/packages/nc-gui-v2/utils/urlUtils.ts index c43f9a1efc..5f71c720a1 100644 --- a/packages/nc-gui-v2/utils/urlUtils.ts +++ b/packages/nc-gui-v2/utils/urlUtils.ts @@ -17,6 +17,10 @@ export const replaceUrlsWithLink = (text: string): boolean | string => { return found && out } +export const dashboardUrl = () => { + return `${location.origin}${location.pathname || ''}` +} + // ref : https://stackoverflow.com/a/5717133 export const isValidURL = (str: string) => { const pattern = diff --git a/packages/nc-gui-v2/utils/userUtils.ts b/packages/nc-gui-v2/utils/userUtils.ts new file mode 100644 index 0000000000..27f70ef391 --- /dev/null +++ b/packages/nc-gui-v2/utils/userUtils.ts @@ -0,0 +1,8 @@ +import { ProjectRole } from '~/lib/enums' + +export const projectRoleTagColors = { + [ProjectRole.Owner]: '#cfdffe', + [ProjectRole.Editor]: '#c2f5e8', + [ProjectRole.User]: '#4caf50', + [ProjectRole.Guest]: '#9e9e9e', +}