Compare commits
34 Commits
fix/secret
...
feat/reque
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a3e941271e | ||
|
|
e7fded89d5 | ||
|
|
40c8d7e4b7 | ||
|
|
1d93d9dabe | ||
|
|
e9f1dc7ba1 | ||
|
|
1e906bbec3 | ||
|
|
7776668e40 | ||
|
|
3d38b7678b | ||
|
|
1ca215d887 | ||
|
|
aec04a13e3 | ||
|
|
9a2058bbec | ||
|
|
1c65147a77 | ||
|
|
207eea538f | ||
|
|
e30b59e1b5 | ||
|
|
9704b3324b | ||
|
|
386bb453d4 | ||
|
|
175641246e | ||
|
|
fb615d2d2b | ||
|
|
7685409ee6 | ||
|
|
e01818444e | ||
|
|
52220d9a2e | ||
|
|
82d687f665 | ||
|
|
d44083a380 | ||
|
|
7589c57e86 | ||
|
|
c8009aec77 | ||
|
|
7114f4fd43 | ||
|
|
ca1a4ec31b | ||
|
|
359633102e | ||
|
|
b278691a9d | ||
|
|
c27e1be230 | ||
|
|
11e8ba7bb3 | ||
|
|
2a0000cfc4 | ||
|
|
0ed063724e | ||
|
|
170ec15821 |
14
package.json
14
package.json
@@ -23,13 +23,13 @@
|
|||||||
"./packages/*"
|
"./packages/*"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@commitlint/cli": "16.3.0",
|
"@commitlint/cli": "^16.2.3",
|
||||||
"@commitlint/config-conventional": "16.2.4",
|
"@commitlint/config-conventional": "^16.2.1",
|
||||||
"@hoppscotch/ui": "0.1.0",
|
"@hoppscotch/ui": "^0.1.0",
|
||||||
"@types/node": "17.0.27",
|
"@types/node": "17.0.27",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"http-server": "14.1.1",
|
"http-server": "^14.1.1",
|
||||||
"husky": "7.0.4",
|
"husky": "^7.0.4",
|
||||||
"lint-staged": "12.4.0"
|
"lint-staged": "12.4.0"
|
||||||
},
|
},
|
||||||
"pnpm": {
|
"pnpm": {
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
"vue": "3.3.9"
|
"vue": "3.3.9"
|
||||||
},
|
},
|
||||||
"packageExtensions": {
|
"packageExtensions": {
|
||||||
"httpsnippet@3.0.1": {
|
"httpsnippet@^3.0.1": {
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"ajv": "6.12.3"
|
"ajv": "6.12.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,16 +17,16 @@
|
|||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codemirror/language": "6.10.1",
|
"@codemirror/language": "6.9.3",
|
||||||
"@lezer/highlight": "1.2.0",
|
"@lezer/highlight": "1.2.0",
|
||||||
"@lezer/lr": "1.3.14"
|
"@lezer/lr": "^1.3.14"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@lezer/generator": "1.5.1",
|
"@lezer/generator": "^1.5.1",
|
||||||
"mocha": "9.2.2",
|
"mocha": "^9.2.2",
|
||||||
"rollup": "3.29.4",
|
"rollup": "^3.29.3",
|
||||||
"rollup-plugin-dts": "6.0.2",
|
"rollup-plugin-dts": "^6.0.2",
|
||||||
"rollup-plugin-ts": "3.4.5",
|
"rollup-plugin-ts": "^3.4.5",
|
||||||
"typescript": "5.2.2"
|
"typescript": "^5.2.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hoppscotch-backend",
|
"name": "hoppscotch-backend",
|
||||||
"version": "2024.3.0",
|
"version": "2023.12.6",
|
||||||
"description": "",
|
"description": "",
|
||||||
"author": "",
|
"author": "",
|
||||||
"private": true,
|
"private": true,
|
||||||
@@ -24,83 +24,83 @@
|
|||||||
"do-test": "pnpm run test"
|
"do-test": "pnpm run test"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apollo/server": "4.9.5",
|
"@apollo/server": "^4.9.4",
|
||||||
"@nestjs-modules/mailer": "1.9.1",
|
"@nestjs-modules/mailer": "^1.9.1",
|
||||||
"@nestjs/apollo": "12.0.9",
|
"@nestjs/apollo": "^12.0.9",
|
||||||
"@nestjs/common": "10.2.7",
|
"@nestjs/common": "^10.2.6",
|
||||||
"@nestjs/config": "3.1.1",
|
"@nestjs/config": "^3.1.1",
|
||||||
"@nestjs/core": "10.2.7",
|
"@nestjs/core": "^10.2.6",
|
||||||
"@nestjs/graphql": "12.0.9",
|
"@nestjs/graphql": "^12.0.9",
|
||||||
"@nestjs/jwt": "10.1.1",
|
"@nestjs/jwt": "^10.1.1",
|
||||||
"@nestjs/passport": "10.0.2",
|
"@nestjs/passport": "^10.0.2",
|
||||||
"@nestjs/platform-express": "10.2.7",
|
"@nestjs/platform-express": "^10.2.6",
|
||||||
"@nestjs/schedule": "4.0.1",
|
"@nestjs/schedule": "^4.0.1",
|
||||||
"@nestjs/throttler": "5.0.1",
|
"@nestjs/throttler": "^5.0.0",
|
||||||
"@prisma/client": "5.8.1",
|
"@prisma/client": "^5.8.0",
|
||||||
"argon2": "0.30.3",
|
"argon2": "^0.30.3",
|
||||||
"bcrypt": "5.1.0",
|
"bcrypt": "^5.1.0",
|
||||||
"cookie": "0.5.0",
|
"cookie": "^0.5.0",
|
||||||
"cookie-parser": "1.4.6",
|
"cookie-parser": "^1.4.6",
|
||||||
"cron": "3.1.6",
|
"cron": "^3.1.6",
|
||||||
"express": "4.18.2",
|
"express": "^4.17.1",
|
||||||
"express-session": "1.17.3",
|
"express-session": "^1.17.3",
|
||||||
"fp-ts": "2.13.1",
|
"fp-ts": "^2.13.1",
|
||||||
"graphql": "16.8.1",
|
"graphql": "^16.8.1",
|
||||||
"graphql-query-complexity": "0.12.0",
|
"graphql-query-complexity": "^0.12.0",
|
||||||
"graphql-redis-subscriptions": "2.6.0",
|
"graphql-redis-subscriptions": "^2.6.0",
|
||||||
"graphql-subscriptions": "2.0.0",
|
"graphql-subscriptions": "^2.0.0",
|
||||||
"handlebars": "4.7.7",
|
"handlebars": "^4.7.7",
|
||||||
"io-ts": "2.2.16",
|
"io-ts": "^2.2.16",
|
||||||
"luxon": "3.2.1",
|
"luxon": "^3.2.1",
|
||||||
"nodemailer": "6.9.1",
|
"nodemailer": "^6.9.1",
|
||||||
"passport": "0.6.0",
|
"passport": "^0.6.0",
|
||||||
"passport-github2": "0.1.12",
|
"passport-github2": "^0.1.12",
|
||||||
"passport-google-oauth20": "2.0.0",
|
"passport-google-oauth20": "^2.0.0",
|
||||||
"passport-jwt": "4.0.1",
|
"passport-jwt": "^4.0.1",
|
||||||
"passport-local": "1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"passport-microsoft": "1.0.0",
|
"passport-microsoft": "^1.0.0",
|
||||||
"posthog-node": "3.6.3",
|
"posthog-node": "^3.6.3",
|
||||||
"prisma": "5.8.1",
|
"prisma": "^5.8.0",
|
||||||
"reflect-metadata": "0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"rimraf": "3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"rxjs": "7.6.0"
|
"rxjs": "^7.6.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@nestjs/cli": "10.2.1",
|
"@nestjs/cli": "^10.1.18",
|
||||||
"@nestjs/schematics": "10.0.3",
|
"@nestjs/schematics": "^10.0.2",
|
||||||
"@nestjs/testing": "10.2.7",
|
"@nestjs/testing": "^10.2.6",
|
||||||
"@relmify/jest-fp-ts": "2.0.2",
|
"@relmify/jest-fp-ts": "^2.0.2",
|
||||||
"@types/argon2": "0.15.0",
|
"@types/argon2": "^0.15.0",
|
||||||
"@types/bcrypt": "5.0.0",
|
"@types/bcrypt": "^5.0.0",
|
||||||
"@types/cookie": "0.5.1",
|
"@types/cookie": "^0.5.1",
|
||||||
"@types/cookie-parser": "1.4.3",
|
"@types/cookie-parser": "^1.4.3",
|
||||||
"@types/express": "4.17.14",
|
"@types/express": "^4.17.14",
|
||||||
"@types/jest": "29.4.0",
|
"@types/jest": "^29.4.0",
|
||||||
"@types/luxon": "3.2.0",
|
"@types/luxon": "^3.2.0",
|
||||||
"@types/node": "18.11.10",
|
"@types/node": "^18.11.10",
|
||||||
"@types/nodemailer": "6.4.7",
|
"@types/nodemailer": "^6.4.7",
|
||||||
"@types/passport-github2": "1.2.5",
|
"@types/passport-github2": "^1.2.5",
|
||||||
"@types/passport-google-oauth20": "2.0.11",
|
"@types/passport-google-oauth20": "^2.0.11",
|
||||||
"@types/passport-jwt": "3.0.8",
|
"@types/passport-jwt": "^3.0.8",
|
||||||
"@types/passport-microsoft": "0.0.0",
|
"@types/passport-microsoft": "^0.0.0",
|
||||||
"@types/supertest": "2.0.12",
|
"@types/supertest": "^2.0.12",
|
||||||
"@typescript-eslint/eslint-plugin": "5.45.0",
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||||
"@typescript-eslint/parser": "5.45.0",
|
"@typescript-eslint/parser": "^5.45.0",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "8.29.0",
|
"eslint": "^8.29.0",
|
||||||
"eslint-config-prettier": "8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-prettier": "4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"jest": "29.4.1",
|
"jest": "^29.4.1",
|
||||||
"jest-mock-extended": "3.0.1",
|
"jest-mock-extended": "^3.0.1",
|
||||||
"jwt": "link:@types/nestjs/jwt",
|
"jwt": "link:@types/nestjs/jwt",
|
||||||
"prettier": "2.8.4",
|
"prettier": "^2.8.4",
|
||||||
"source-map-support": "0.5.21",
|
"source-map-support": "^0.5.21",
|
||||||
"supertest": "6.3.2",
|
"supertest": "^6.3.2",
|
||||||
"ts-jest": "29.0.5",
|
"ts-jest": "29.0.5",
|
||||||
"ts-loader": "9.4.2",
|
"ts-loader": "^9.4.2",
|
||||||
"ts-node": "10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"tsconfig-paths": "4.1.1",
|
"tsconfig-paths": "4.1.1",
|
||||||
"typescript": "4.9.3"
|
"typescript": "^4.9.3"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"moduleFileExtensions": [
|
"moduleFileExtensions": [
|
||||||
@@ -121,4 +121,4 @@
|
|||||||
"^src/(.*)$": "<rootDir>/$1"
|
"^src/(.*)$": "<rootDir>/$1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/cli",
|
"name": "@hoppscotch/cli",
|
||||||
"version": "0.7.0",
|
"version": "0.6.0",
|
||||||
"description": "A CLI to run Hoppscotch test scripts in CI environments.",
|
"description": "A CLI to run Hoppscotch test scripts in CI environments.",
|
||||||
"homepage": "https://hoppscotch.io",
|
"homepage": "https://hoppscotch.io",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -41,28 +41,30 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"private": false,
|
"private": false,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "1.6.7",
|
"axios": "^1.6.6",
|
||||||
"chalk": "5.3.0",
|
"chalk": "^5.3.0",
|
||||||
"commander": "11.1.0",
|
"commander": "^11.1.0",
|
||||||
"lodash-es": "4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"qs": "6.11.2",
|
"qs": "^6.11.2",
|
||||||
"verzod": "0.2.2",
|
"zod": "^3.22.4"
|
||||||
"zod": "3.22.4"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@hoppscotch/data": "workspace:^",
|
"@hoppscotch/data": "workspace:^",
|
||||||
"@hoppscotch/js-sandbox": "workspace:^",
|
"@hoppscotch/js-sandbox": "workspace:^",
|
||||||
"@relmify/jest-fp-ts": "2.1.1",
|
"@relmify/jest-fp-ts": "^2.1.1",
|
||||||
"@swc/core": "1.4.2",
|
"@swc/core": "^1.3.105",
|
||||||
"@types/jest": "29.5.12",
|
"@types/jest": "^29.5.11",
|
||||||
"@types/lodash-es": "4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/qs": "6.9.12",
|
"@types/qs": "^6.9.11",
|
||||||
"fp-ts": "2.16.2",
|
"fp-ts": "^2.16.2",
|
||||||
"jest": "29.7.0",
|
"jest": "^29.7.0",
|
||||||
"prettier": "3.2.5",
|
"lodash": "^4.17.21",
|
||||||
"qs": "6.11.2",
|
"prettier": "^3.2.4",
|
||||||
"ts-jest": "29.1.2",
|
"qs": "^6.11.2",
|
||||||
"tsup": "8.0.2",
|
"ts-jest": "^29.1.2",
|
||||||
"typescript": "5.3.3"
|
"tsup": "^8.0.1",
|
||||||
|
"typescript": "^5.3.3",
|
||||||
|
"verzod": "^0.2.2",
|
||||||
|
"zod": "^3.22.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,7 +154,7 @@
|
|||||||
"invalid_name": "Please provide a name for the collection",
|
"invalid_name": "Please provide a name for the collection",
|
||||||
"invalid_root_move": "Collection already in the root",
|
"invalid_root_move": "Collection already in the root",
|
||||||
"moved": "Moved Successfully",
|
"moved": "Moved Successfully",
|
||||||
"my_collections": "Personal Collections",
|
"my_collections": "My Collections",
|
||||||
"name": "My New Collection",
|
"name": "My New Collection",
|
||||||
"name_length_insufficient": "Collection name should be at least 3 characters long",
|
"name_length_insufficient": "Collection name should be at least 3 characters long",
|
||||||
"new": "New Collection",
|
"new": "New Collection",
|
||||||
@@ -166,12 +166,14 @@
|
|||||||
"save_as": "Save as",
|
"save_as": "Save as",
|
||||||
"save_to_collection": "Save to Collection",
|
"save_to_collection": "Save to Collection",
|
||||||
"select": "Select a Collection",
|
"select": "Select a Collection",
|
||||||
"select_location": "Select location"
|
"select_location": "Select location",
|
||||||
|
"select_team": "Select a team",
|
||||||
|
"team_collections": "Team Collections"
|
||||||
},
|
},
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"close_unsaved_tab": "Are you sure you want to close this tab?",
|
"close_unsaved_tab": "Are you sure you want to close this tab?",
|
||||||
"close_unsaved_tabs": "Are you sure you want to close all tabs? {count} unsaved tabs will be lost.",
|
"close_unsaved_tabs": "Are you sure you want to close all tabs? {count} unsaved tabs will be lost.",
|
||||||
"exit_team": "Are you sure you want to leave this workspace?",
|
"exit_team": "Are you sure you want to leave this team?",
|
||||||
"logout": "Are you sure you want to logout?",
|
"logout": "Are you sure you want to logout?",
|
||||||
"remove_collection": "Are you sure you want to permanently delete this collection?",
|
"remove_collection": "Are you sure you want to permanently delete this collection?",
|
||||||
"remove_environment": "Are you sure you want to permanently delete this environment?",
|
"remove_environment": "Are you sure you want to permanently delete this environment?",
|
||||||
@@ -179,7 +181,7 @@
|
|||||||
"remove_history": "Are you sure you want to permanently delete all history?",
|
"remove_history": "Are you sure you want to permanently delete all history?",
|
||||||
"remove_request": "Are you sure you want to permanently delete this request?",
|
"remove_request": "Are you sure you want to permanently delete this request?",
|
||||||
"remove_shared_request": "Are you sure you want to permanently delete this shared request?",
|
"remove_shared_request": "Are you sure you want to permanently delete this shared request?",
|
||||||
"remove_team": "Are you sure you want to delete this workspace?",
|
"remove_team": "Are you sure you want to delete this team?",
|
||||||
"remove_telemetry": "Are you sure you want to opt-out of Telemetry?",
|
"remove_telemetry": "Are you sure you want to opt-out of Telemetry?",
|
||||||
"request_change": "Are you sure you want to discard current request, unsaved changes will be lost.",
|
"request_change": "Are you sure you want to discard current request, unsaved changes will be lost.",
|
||||||
"save_unsaved_tab": "Do you want to save changes made in this tab?",
|
"save_unsaved_tab": "Do you want to save changes made in this tab?",
|
||||||
@@ -232,9 +234,9 @@
|
|||||||
"headers": "This request does not have any headers",
|
"headers": "This request does not have any headers",
|
||||||
"history": "History is empty",
|
"history": "History is empty",
|
||||||
"invites": "Invite list is empty",
|
"invites": "Invite list is empty",
|
||||||
"members": "Workspace is empty",
|
"members": "Team is empty",
|
||||||
"parameters": "This request does not have any parameters",
|
"parameters": "This request does not have any parameters",
|
||||||
"pending_invites": "There are no pending invites for this workspace",
|
"pending_invites": "There are no pending invites for this team",
|
||||||
"profile": "Login to view your profile",
|
"profile": "Login to view your profile",
|
||||||
"protocols": "Protocols are empty",
|
"protocols": "Protocols are empty",
|
||||||
"request_variables": "This request does not have any request variables",
|
"request_variables": "This request does not have any request variables",
|
||||||
@@ -243,8 +245,8 @@
|
|||||||
"shared_requests": "Shared requests are empty",
|
"shared_requests": "Shared requests are empty",
|
||||||
"shared_requests_logout": "Login to view your shared requests or create a new one",
|
"shared_requests_logout": "Login to view your shared requests or create a new one",
|
||||||
"subscription": "Subscriptions are empty",
|
"subscription": "Subscriptions are empty",
|
||||||
"team_name": "Workspace name empty",
|
"team_name": "Team name empty",
|
||||||
"teams": "You don't belong to any workspaces",
|
"teams": "You don't belong to any teams",
|
||||||
"tests": "There are no tests for this request"
|
"tests": "There are no tests for this request"
|
||||||
},
|
},
|
||||||
"environment": {
|
"environment": {
|
||||||
@@ -261,7 +263,7 @@
|
|||||||
"import_or_create": "Import or create a environment",
|
"import_or_create": "Import or create a environment",
|
||||||
"invalid_name": "Please provide a name for the environment",
|
"invalid_name": "Please provide a name for the environment",
|
||||||
"list": "Environment variables",
|
"list": "Environment variables",
|
||||||
"my_environments": "Personal Environments",
|
"my_environments": "My Environments",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"nested_overflow": "nested environment variables are limited to 10 levels",
|
"nested_overflow": "nested environment variables are limited to 10 levels",
|
||||||
"new": "New Environment",
|
"new": "New Environment",
|
||||||
@@ -276,7 +278,7 @@
|
|||||||
"select": "Select environment",
|
"select": "Select environment",
|
||||||
"set": "Set environment",
|
"set": "Set environment",
|
||||||
"set_as_environment": "Set as environment",
|
"set_as_environment": "Set as environment",
|
||||||
"team_environments": "Workspace Environments",
|
"team_environments": "Team Environments",
|
||||||
"title": "Environments",
|
"title": "Environments",
|
||||||
"updated": "Environment updated",
|
"updated": "Environment updated",
|
||||||
"value": "Value",
|
"value": "Value",
|
||||||
@@ -291,8 +293,8 @@
|
|||||||
"check_how_to_add_origin": "Check how you can add an origin",
|
"check_how_to_add_origin": "Check how you can add an origin",
|
||||||
"curl_invalid_format": "cURL is not formatted properly",
|
"curl_invalid_format": "cURL is not formatted properly",
|
||||||
"danger_zone": "Danger zone",
|
"danger_zone": "Danger zone",
|
||||||
"delete_account": "Your account is currently an owner in these workspaces:",
|
"delete_account": "Your account is currently an owner in these teams:",
|
||||||
"delete_account_description": "You must either remove yourself, transfer ownership, or delete these workspaces before you can delete your account.",
|
"delete_account_description": "You must either remove yourself, transfer ownership, or delete these teams before you can delete your account.",
|
||||||
"empty_req_name": "Empty Request Name",
|
"empty_req_name": "Empty Request Name",
|
||||||
"f12_details": "(F12 for details)",
|
"f12_details": "(F12 for details)",
|
||||||
"gql_prettify_invalid_query": "Couldn't prettify an invalid query, solve query syntax errors and try again",
|
"gql_prettify_invalid_query": "Couldn't prettify an invalid query, solve query syntax errors and try again",
|
||||||
@@ -394,8 +396,8 @@
|
|||||||
"from_insomnia_description": "Import from Insomnia collection",
|
"from_insomnia_description": "Import from Insomnia collection",
|
||||||
"from_json": "Import from Hoppscotch",
|
"from_json": "Import from Hoppscotch",
|
||||||
"from_json_description": "Import from Hoppscotch collection file",
|
"from_json_description": "Import from Hoppscotch collection file",
|
||||||
"from_my_collections": "Import from Personal Collections",
|
"from_my_collections": "Import from My Collections",
|
||||||
"from_my_collections_description": "Import from Personal Collections file",
|
"from_my_collections_description": "Import from My Collections file",
|
||||||
"from_openapi": "Import from OpenAPI",
|
"from_openapi": "Import from OpenAPI",
|
||||||
"from_openapi_description": "Import from OpenAPI specification file (YML/JSON)",
|
"from_openapi_description": "Import from OpenAPI specification file (YML/JSON)",
|
||||||
"from_postman": "Import from Postman",
|
"from_postman": "Import from Postman",
|
||||||
@@ -512,7 +514,7 @@
|
|||||||
"email_verification_mail": "A verification email has been sent to your email address. Please click on the link to verify your email address.",
|
"email_verification_mail": "A verification email has been sent to your email address. Please click on the link to verify your email address.",
|
||||||
"no_permission": "You do not have permission to perform this action.",
|
"no_permission": "You do not have permission to perform this action.",
|
||||||
"owner": "Owner",
|
"owner": "Owner",
|
||||||
"owner_description": "Owners can add, edit, and delete requests, collections and workspace members.",
|
"owner_description": "Owners can add, edit, and delete requests, collections and team members.",
|
||||||
"roles": "Roles",
|
"roles": "Roles",
|
||||||
"roles_description": "Roles are used to control access to the shared collections.",
|
"roles_description": "Roles are used to control access to the shared collections.",
|
||||||
"updated": "Profile updated",
|
"updated": "Profile updated",
|
||||||
@@ -817,12 +819,12 @@
|
|||||||
"title": "Tabs"
|
"title": "Tabs"
|
||||||
},
|
},
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"delete": "Delete current workspace",
|
"delete": "Delete current team",
|
||||||
"edit": "Edit current workspace",
|
"edit": "Edit current team",
|
||||||
"invite": "Invite people to workspace",
|
"invite": "Invite people to team",
|
||||||
"new": "Create new workspace",
|
"new": "Create new team",
|
||||||
"switch_to_personal": "Switch to your personal workspace",
|
"switch_to_personal": "Switch to your personal workspace",
|
||||||
"title": "Workspaces"
|
"title": "Teams"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sse": {
|
"sse": {
|
||||||
@@ -879,6 +881,7 @@
|
|||||||
"forum": "Ask questions and get answers",
|
"forum": "Ask questions and get answers",
|
||||||
"github": "Follow us on Github",
|
"github": "Follow us on Github",
|
||||||
"shortcuts": "Browse app faster",
|
"shortcuts": "Browse app faster",
|
||||||
|
"team": "Get in touch with the team",
|
||||||
"title": "Support",
|
"title": "Support",
|
||||||
"twitter": "Follow us on Twitter"
|
"twitter": "Follow us on Twitter"
|
||||||
},
|
},
|
||||||
@@ -909,59 +912,60 @@
|
|||||||
"websocket": "WebSocket"
|
"websocket": "WebSocket"
|
||||||
},
|
},
|
||||||
"team": {
|
"team": {
|
||||||
"already_member": "You are already a member of this workspace. Contact your workspace owner.",
|
"already_member": "You are already a member of this team. Contact your team owner.",
|
||||||
"create_new": "Create new workspace",
|
"create_new": "Create new team",
|
||||||
"deleted": "Workspace deleted",
|
"deleted": "Team deleted",
|
||||||
"edit": "Edit Workspace",
|
"edit": "Edit Team",
|
||||||
"email": "E-mail",
|
"email": "E-mail",
|
||||||
"email_do_not_match": "Email doesn't match with your account details. Contact your workspace owner.",
|
"email_do_not_match": "Email doesn't match with your account details. Contact your team owner.",
|
||||||
"exit": "Exit Workspace",
|
"exit": "Exit Team",
|
||||||
"exit_disabled": "Only owner cannot exit the workspace",
|
"exit_disabled": "Only owner cannot exit the team",
|
||||||
"failed_invites": "Failed invites",
|
"failed_invites": "Failed invites",
|
||||||
"invalid_coll_id": "Invalid collection ID",
|
"invalid_coll_id": "Invalid collection ID",
|
||||||
"invalid_email_format": "Email format is invalid",
|
"invalid_email_format": "Email format is invalid",
|
||||||
"invalid_id": "Invalid workspace ID. Contact your workspace owner.",
|
"invalid_id": "Invalid team ID. Contact your team owner.",
|
||||||
"invalid_invite_link": "Invalid invite link",
|
"invalid_invite_link": "Invalid invite link",
|
||||||
"invalid_invite_link_description": "The link you followed is invalid. Contact your workspace owner.",
|
"invalid_invite_link_description": "The link you followed is invalid. Contact your team owner.",
|
||||||
"invalid_member_permission": "Please provide a valid permission to the workspace member",
|
"invalid_member_permission": "Please provide a valid permission to the team member",
|
||||||
"invite": "Invite",
|
"invite": "Invite",
|
||||||
"invite_more": "Invite more",
|
"invite_more": "Invite more",
|
||||||
"invite_tooltip": "Invite people to this workspace",
|
"invite_tooltip": "Invite people to this workspace",
|
||||||
"invited_to_team": "{owner} invited you to join {workspace}",
|
"invited_to_team": "{owner} invited you to join {team}",
|
||||||
"join": "Invitation accepted",
|
"join": "Invitation accepted",
|
||||||
"join_team": "Join {workspace}",
|
"join_beta": "Join the beta program to access teams.",
|
||||||
"joined_team": "You have joined {workspace}",
|
"join_team": "Join {team}",
|
||||||
"joined_team_description": "You are now a member of this workspace",
|
"joined_team": "You have joined {team}",
|
||||||
"left": "You left the workspace",
|
"joined_team_description": "You are now a member of this team",
|
||||||
|
"left": "You left the team",
|
||||||
"login_to_continue": "Login to continue",
|
"login_to_continue": "Login to continue",
|
||||||
"login_to_continue_description": "You need to be logged in to join a workspace.",
|
"login_to_continue_description": "You need to be logged in to join a team.",
|
||||||
"logout_and_try_again": "Logout and sign in with another account",
|
"logout_and_try_again": "Logout and sign in with another account",
|
||||||
"member_has_invite": "This email ID already has an invite. Contact your workspace owner.",
|
"member_has_invite": "This email ID already has an invite. Contact your team owner.",
|
||||||
"member_not_found": "Member not found. Contact your workspace owner.",
|
"member_not_found": "Member not found. Contact your team owner.",
|
||||||
"member_removed": "User removed",
|
"member_removed": "User removed",
|
||||||
"member_role_updated": "User roles updated",
|
"member_role_updated": "User roles updated",
|
||||||
"members": "Members",
|
"members": "Members",
|
||||||
"more_members": "+{count} more",
|
"more_members": "+{count} more",
|
||||||
"name_length_insufficient": "Workspace name should be at least 6 characters long",
|
"name_length_insufficient": "Team name should be at least 6 characters long",
|
||||||
"name_updated": "Workspace name updated",
|
"name_updated": "Team name updated",
|
||||||
"new": "New Workspace",
|
"new": "New Team",
|
||||||
"new_created": "New workspace created",
|
"new_created": "New team created",
|
||||||
"new_name": "My New Workspace",
|
"new_name": "My New Team",
|
||||||
"no_access": "You do not have edit access to this workspace",
|
"no_access": "You do not have edit access to this team",
|
||||||
"no_invite_found": "Invitation not found. Contact your workspace owner.",
|
"no_invite_found": "Invitation not found. Contact your team owner.",
|
||||||
"no_request_found": "Request not found.",
|
"no_request_found": "Request not found.",
|
||||||
"not_found": "Workspace not found. Contact your workspace owner.",
|
"not_found": "Team not found. Contact your team owner.",
|
||||||
"not_valid_viewer": "You are not a valid viewer. Contact your workspace owner.",
|
"not_valid_viewer": "You are not a valid viewer. Contact your team owner.",
|
||||||
"parent_coll_move": "Cannot move collection to a child collection",
|
"parent_coll_move": "Cannot move collection to a child collection",
|
||||||
"pending_invites": "Pending invites",
|
"pending_invites": "Pending invites",
|
||||||
"permissions": "Permissions",
|
"permissions": "Permissions",
|
||||||
"same_target_destination": "Same target and destination",
|
"same_target_destination": "Same target and destination",
|
||||||
"saved": "Workspace saved",
|
"saved": "Team saved",
|
||||||
"select_a_team": "Select a workspace",
|
"select_a_team": "Select a team",
|
||||||
"success_invites": "Success invites",
|
"success_invites": "Success invites",
|
||||||
"title": "Workspaces",
|
"title": "Teams",
|
||||||
"we_sent_invite_link": "We sent an invite link to all invitees!",
|
"we_sent_invite_link": "We sent an invite link to all invitees!",
|
||||||
"we_sent_invite_link_description": "Ask all invitees to check their inbox. Click on the link to join the workspace."
|
"we_sent_invite_link_description": "Ask all invitees to check their inbox. Click on the link to join the team."
|
||||||
},
|
},
|
||||||
"team_environment": {
|
"team_environment": {
|
||||||
"deleted": "Environment Deleted",
|
"deleted": "Environment Deleted",
|
||||||
@@ -987,14 +991,8 @@
|
|||||||
},
|
},
|
||||||
"workspace": {
|
"workspace": {
|
||||||
"change": "Change workspace",
|
"change": "Change workspace",
|
||||||
"personal": "Personal Workspace",
|
"personal": "My Workspace",
|
||||||
"other_workspaces": "My Workspaces",
|
"team": "Team Workspace",
|
||||||
"team": "Workspace",
|
|
||||||
"title": "Workspaces"
|
"title": "Workspaces"
|
||||||
},
|
|
||||||
"site_protection": {
|
|
||||||
"login_to_continue": "Login to continue",
|
|
||||||
"login_to_continue_description": "You need to be logged in to access this Hoppscotch Enterprise Instance.",
|
|
||||||
"error_fetching_site_protection_status": "Something Went Wrong While Fetching Site Protection Status"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/common",
|
"name": "@hoppscotch/common",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2024.3.0",
|
"version": "2023.12.6",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
||||||
"test": "vitest --run",
|
"test": "vitest --run",
|
||||||
@@ -21,147 +21,147 @@
|
|||||||
"do-lintfix": "pnpm run lintfix"
|
"do-lintfix": "pnpm run lintfix"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apidevtools/swagger-parser": "10.1.0",
|
"@apidevtools/swagger-parser": "^10.1.0",
|
||||||
"@codemirror/autocomplete": "6.13.0",
|
"@codemirror/autocomplete": "^6.11.1",
|
||||||
"@codemirror/commands": "6.3.3",
|
"@codemirror/commands": "^6.3.2",
|
||||||
"@codemirror/lang-javascript": "6.2.2",
|
"@codemirror/lang-javascript": "^6.2.1",
|
||||||
"@codemirror/lang-json": "6.0.1",
|
"@codemirror/lang-json": "^6.0.1",
|
||||||
"@codemirror/lang-xml": "6.1.0",
|
"@codemirror/lang-xml": "^6.0.2",
|
||||||
"@codemirror/language": "6.10.1",
|
"@codemirror/language": "6.9.3",
|
||||||
"@codemirror/legacy-modes": "6.3.3",
|
"@codemirror/legacy-modes": "^6.3.3",
|
||||||
"@codemirror/lint": "6.5.0",
|
"@codemirror/lint": "^6.4.2",
|
||||||
"@codemirror/search": "6.5.6",
|
"@codemirror/search": "^6.5.5",
|
||||||
"@codemirror/state": "6.4.1",
|
"@codemirror/state": "^6.3.3",
|
||||||
"@codemirror/view": "6.25.1",
|
"@codemirror/view": "^6.22.3",
|
||||||
"@hoppscotch/codemirror-lang-graphql": "workspace:^",
|
"@hoppscotch/codemirror-lang-graphql": "workspace:^",
|
||||||
"@hoppscotch/data": "workspace:^",
|
"@hoppscotch/data": "workspace:^",
|
||||||
"@hoppscotch/js-sandbox": "workspace:^",
|
"@hoppscotch/js-sandbox": "workspace:^",
|
||||||
"@hoppscotch/ui": "0.1.0",
|
"@hoppscotch/ui": "^0.1.0",
|
||||||
"@hoppscotch/vue-toasted": "0.1.0",
|
"@hoppscotch/vue-toasted": "^0.1.0",
|
||||||
"@lezer/highlight": "1.2.0",
|
"@lezer/highlight": "1.2.0",
|
||||||
"@unhead/vue": "1.8.8",
|
"@unhead/vue": "^1.8.8",
|
||||||
"@urql/core": "4.2.0",
|
"@urql/core": "^4.2.0",
|
||||||
"@urql/devtools": "2.0.3",
|
"@urql/devtools": "^2.0.3",
|
||||||
"@urql/exchange-auth": "2.1.6",
|
"@urql/exchange-auth": "^2.1.6",
|
||||||
"@urql/exchange-graphcache": "6.4.0",
|
"@urql/exchange-graphcache": "^6.3.3",
|
||||||
"@vitejs/plugin-legacy": "4.1.1",
|
"@vitejs/plugin-legacy": "^4.1.1",
|
||||||
"@vueuse/core": "10.7.0",
|
"@vueuse/core": "^10.6.1",
|
||||||
"acorn-walk": "8.3.0",
|
"acorn-walk": "^8.3.0",
|
||||||
"axios": "1.6.2",
|
"axios": "^1.6.2",
|
||||||
"buffer": "6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"cookie-es": "1.0.0",
|
"cookie-es": "^1.0.0",
|
||||||
"dioc": "1.0.1",
|
"dioc": "^1.0.1",
|
||||||
"esprima": "4.0.1",
|
"esprima": "^4.0.1",
|
||||||
"events": "3.3.0",
|
"events": "^3.3.0",
|
||||||
"fp-ts": "2.16.1",
|
"fp-ts": "^2.16.1",
|
||||||
"globalthis": "1.0.3",
|
"globalthis": "^1.0.3",
|
||||||
"graphql": "16.8.1",
|
"graphql": "^16.8.1",
|
||||||
"graphql-language-service-interface": "2.10.2",
|
"graphql-language-service-interface": "^2.10.2",
|
||||||
"graphql-tag": "2.12.6",
|
"graphql-tag": "^2.12.6",
|
||||||
"httpsnippet": "3.0.1",
|
"httpsnippet": "^3.0.1",
|
||||||
"insomnia-importers": "3.6.0",
|
"insomnia-importers": "^3.6.0",
|
||||||
"io-ts": "2.2.20",
|
"io-ts": "^2.2.20",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
"jsonpath-plus": "7.2.0",
|
"jsonpath-plus": "^7.2.0",
|
||||||
"lodash-es": "4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"lossless-json": "3.0.2",
|
"lossless-json": "^3.0.2",
|
||||||
"minisearch": "6.3.0",
|
"minisearch": "^6.3.0",
|
||||||
"nprogress": "0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"paho-mqtt": "1.1.0",
|
"paho-mqtt": "^1.1.0",
|
||||||
"path": "0.12.7",
|
"path": "^0.12.7",
|
||||||
"postman-collection": "4.3.0",
|
"postman-collection": "^4.3.0",
|
||||||
"process": "0.11.10",
|
"process": "^0.11.10",
|
||||||
"qs": "6.11.2",
|
"qs": "^6.11.2",
|
||||||
"quicktype-core": "23.0.79",
|
"quicktype-core": "^23.0.79",
|
||||||
"rxjs": "7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"set-cookie-parser": "2.6.0",
|
"set-cookie-parser": "^2.6.0",
|
||||||
"set-cookie-parser-es": "1.0.5",
|
"set-cookie-parser-es": "^1.0.5",
|
||||||
"socket.io-client-v2": "npm:socket.io-client@2.4.0",
|
"socket.io-client-v2": "npm:socket.io-client@^2.4.0",
|
||||||
"socket.io-client-v3": "npm:socket.io-client@3.1.3",
|
"socket.io-client-v3": "npm:socket.io-client@^3.1.3",
|
||||||
"socket.io-client-v4": "npm:socket.io-client@4.4.1",
|
"socket.io-client-v4": "npm:socket.io-client@^4.4.1",
|
||||||
"socketio-wildcard": "2.0.0",
|
"socketio-wildcard": "^2.0.0",
|
||||||
"splitpanes": "3.1.5",
|
"splitpanes": "^3.1.5",
|
||||||
"stream-browserify": "3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"subscriptions-transport-ws": "0.11.0",
|
"subscriptions-transport-ws": "^0.11.0",
|
||||||
"tern": "0.24.3",
|
"tern": "^0.24.3",
|
||||||
"timers": "0.1.1",
|
"timers": "^0.1.1",
|
||||||
"tippy.js": "6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"url": "0.11.3",
|
"url": "^0.11.3",
|
||||||
"util": "0.12.5",
|
"util": "^0.12.5",
|
||||||
"uuid": "9.0.1",
|
"uuid": "^9.0.1",
|
||||||
"verzod": "0.2.2",
|
"verzod": "^0.2.0",
|
||||||
"vue": "3.3.9",
|
"vue": "^3.3.8",
|
||||||
"vue-i18n": "9.8.0",
|
"vue-i18n": "^9.7.1",
|
||||||
"vue-pdf-embed": "1.2.1",
|
"vue-pdf-embed": "^1.2.1",
|
||||||
"vue-router": "4.2.5",
|
"vue-router": "^4.2.5",
|
||||||
"vue-tippy": "6.3.1",
|
"vue-tippy": "6.3.1",
|
||||||
"vuedraggable-es": "4.1.1",
|
"vuedraggable-es": "^4.1.1",
|
||||||
"wonka": "6.3.4",
|
"wonka": "^6.3.4",
|
||||||
"workbox-window": "7.0.0",
|
"workbox-window": "^7.0.0",
|
||||||
"xml-formatter": "3.6.0",
|
"xml-formatter": "^3.6.0",
|
||||||
"yargs-parser": "21.1.1",
|
"yargs-parser": "^21.1.1",
|
||||||
"zod": "3.22.4"
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@esbuild-plugins/node-globals-polyfill": "0.2.3",
|
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
|
||||||
"@esbuild-plugins/node-modules-polyfill": "0.2.2",
|
"@esbuild-plugins/node-modules-polyfill": "^0.2.2",
|
||||||
"@graphql-codegen/add": "5.0.0",
|
"@graphql-codegen/add": "^5.0.0",
|
||||||
"@graphql-codegen/cli": "5.0.0",
|
"@graphql-codegen/cli": "^5.0.0",
|
||||||
"@graphql-codegen/typed-document-node": "5.0.1",
|
"@graphql-codegen/typed-document-node": "^5.0.1",
|
||||||
"@graphql-codegen/typescript": "4.0.1",
|
"@graphql-codegen/typescript": "^4.0.1",
|
||||||
"@graphql-codegen/typescript-operations": "4.0.1",
|
"@graphql-codegen/typescript-operations": "^4.0.1",
|
||||||
"@graphql-codegen/typescript-urql-graphcache": "3.0.0",
|
"@graphql-codegen/typescript-urql-graphcache": "^3.0.0",
|
||||||
"@graphql-codegen/urql-introspection": "3.0.0",
|
"@graphql-codegen/urql-introspection": "^3.0.0",
|
||||||
"@graphql-typed-document-node/core": "3.2.0",
|
"@graphql-typed-document-node/core": "^3.2.0",
|
||||||
"@iconify-json/lucide": "1.1.144",
|
"@iconify-json/lucide": "^1.1.141",
|
||||||
"@intlify/vite-plugin-vue-i18n": "7.0.0",
|
"@intlify/vite-plugin-vue-i18n": "^7.0.0",
|
||||||
"@relmify/jest-fp-ts": "2.1.1",
|
"@relmify/jest-fp-ts": "^2.1.1",
|
||||||
"@rushstack/eslint-patch": "1.6.0",
|
"@rushstack/eslint-patch": "^1.6.0",
|
||||||
"@types/har-format": "1.2.15",
|
"@types/har-format": "^1.2.15",
|
||||||
"@types/js-yaml": "4.0.9",
|
"@types/js-yaml": "^4.0.9",
|
||||||
"@types/lodash-es": "4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@types/lossless-json": "1.0.4",
|
"@types/lossless-json": "^1.0.4",
|
||||||
"@types/nprogress": "0.2.3",
|
"@types/nprogress": "^0.2.3",
|
||||||
"@types/paho-mqtt": "1.0.10",
|
"@types/paho-mqtt": "^1.0.10",
|
||||||
"@types/postman-collection": "3.5.10",
|
"@types/postman-collection": "^3.5.10",
|
||||||
"@types/splitpanes": "2.2.6",
|
"@types/splitpanes": "^2.2.6",
|
||||||
"@types/uuid": "9.0.7",
|
"@types/uuid": "^9.0.7",
|
||||||
"@types/yargs-parser": "21.0.3",
|
"@types/yargs-parser": "^21.0.3",
|
||||||
"@typescript-eslint/eslint-plugin": "6.13.2",
|
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||||
"@typescript-eslint/parser": "6.13.2",
|
"@typescript-eslint/parser": "^6.12.0",
|
||||||
"@vitejs/plugin-vue": "4.5.1",
|
"@vitejs/plugin-vue": "^4.5.0",
|
||||||
"@vue/compiler-sfc": "3.3.10",
|
"@vue/compiler-sfc": "^3.3.8",
|
||||||
"@vue/eslint-config-typescript": "12.0.0",
|
"@vue/eslint-config-typescript": "^12.0.0",
|
||||||
"@vue/runtime-core": "3.3.10",
|
"@vue/runtime-core": "^3.3.8",
|
||||||
"autoprefixer": "10.4.16",
|
"autoprefixer": "^10.4.14",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"dotenv": "16.3.1",
|
"dotenv": "^16.3.1",
|
||||||
"eslint": "8.55.0",
|
"eslint": "^8.54.0",
|
||||||
"eslint-plugin-prettier": "5.0.1",
|
"eslint-plugin-prettier": "^5.0.1",
|
||||||
"eslint-plugin-vue": "9.19.2",
|
"eslint-plugin-vue": "^9.18.1",
|
||||||
"glob": "10.3.10",
|
"glob": "^10.3.10",
|
||||||
"npm-run-all": "4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"openapi-types": "12.1.3",
|
"openapi-types": "^12.1.3",
|
||||||
"postcss": "8.4.31",
|
"postcss": "^8.4.23",
|
||||||
"prettier": "3.1.0",
|
"prettier": "^3.1.0",
|
||||||
"prettier-plugin-tailwindcss": "0.5.7",
|
"prettier-plugin-tailwindcss": "^0.5.7",
|
||||||
"rollup-plugin-polyfill-node": "0.13.0",
|
"rollup-plugin-polyfill-node": "^0.13.0",
|
||||||
"sass": "1.69.5",
|
"sass": "^1.69.5",
|
||||||
"tailwindcss": "3.3.5",
|
"tailwindcss": "^3.3.2",
|
||||||
"typescript": "5.3.2",
|
"typescript": "^5.3.2",
|
||||||
"unplugin-fonts": "1.1.1",
|
"unplugin-fonts": "^1.1.1",
|
||||||
"unplugin-icons": "0.17.4",
|
"unplugin-icons": "^0.17.4",
|
||||||
"unplugin-vue-components": "0.25.2",
|
"unplugin-vue-components": "^0.25.2",
|
||||||
"vite": "4.5.0",
|
"vite": "^4.5.0",
|
||||||
"vite-plugin-checker": "0.6.2",
|
"vite-plugin-checker": "^0.6.2",
|
||||||
"vite-plugin-fonts": "0.7.0",
|
"vite-plugin-fonts": "^0.7.0",
|
||||||
"vite-plugin-html-config": "1.0.11",
|
"vite-plugin-html-config": "^1.0.11",
|
||||||
"vite-plugin-inspect": "0.7.42",
|
"vite-plugin-inspect": "^0.7.42",
|
||||||
"vite-plugin-pages": "0.31.0",
|
"vite-plugin-pages": "^0.31.0",
|
||||||
"vite-plugin-pages-sitemap": "1.6.1",
|
"vite-plugin-pages-sitemap": "^1.6.1",
|
||||||
"vite-plugin-pwa": "0.17.3",
|
"vite-plugin-pwa": "^0.17.0",
|
||||||
"vite-plugin-vue-layouts": "0.8.0",
|
"vite-plugin-vue-layouts": "^0.8.0",
|
||||||
"vitest": "0.34.6",
|
"vitest": "^0.34.6",
|
||||||
"vue-tsc": "1.8.24"
|
"vue-tsc": "^1.8.22"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
409
packages/hoppscotch-common/src/components.d.ts
vendored
409
packages/hoppscotch-common/src/components.d.ts
vendored
@@ -1,214 +1,213 @@
|
|||||||
// generated by unplugin-vue-components
|
// generated by unplugin-vue-components
|
||||||
// We suggest you to commit this file into source control
|
// We suggest you to commit this file into source control
|
||||||
// Read more: https://github.com/vuejs/core/pull/3399
|
// Read more: https://github.com/vuejs/core/pull/3399
|
||||||
import "@vue/runtime-core"
|
import '@vue/runtime-core'
|
||||||
|
|
||||||
export {}
|
export {}
|
||||||
|
|
||||||
declare module "@vue/runtime-core" {
|
declare module '@vue/runtime-core' {
|
||||||
export interface GlobalComponents {
|
export interface GlobalComponents {
|
||||||
AppActionHandler: (typeof import("./components/app/ActionHandler.vue"))["default"]
|
AppActionHandler: typeof import('./components/app/ActionHandler.vue')['default']
|
||||||
AppBanner: (typeof import("./components/app/Banner.vue"))["default"]
|
AppBanner: typeof import('./components/app/Banner.vue')['default']
|
||||||
AppContextMenu: (typeof import("./components/app/ContextMenu.vue"))["default"]
|
AppContextMenu: typeof import('./components/app/ContextMenu.vue')['default']
|
||||||
AppDeveloperOptions: (typeof import("./components/app/DeveloperOptions.vue"))["default"]
|
AppDeveloperOptions: typeof import('./components/app/DeveloperOptions.vue')['default']
|
||||||
AppFooter: (typeof import("./components/app/Footer.vue"))["default"]
|
AppFooter: typeof import('./components/app/Footer.vue')['default']
|
||||||
AppGitHubStarButton: (typeof import("./components/app/GitHubStarButton.vue"))["default"]
|
AppGitHubStarButton: typeof import('./components/app/GitHubStarButton.vue')['default']
|
||||||
AppHeader: (typeof import("./components/app/Header.vue"))["default"]
|
AppHeader: typeof import('./components/app/Header.vue')['default']
|
||||||
AppInspection: (typeof import("./components/app/Inspection.vue"))["default"]
|
AppInspection: typeof import('./components/app/Inspection.vue')['default']
|
||||||
AppInterceptor: (typeof import("./components/app/Interceptor.vue"))["default"]
|
AppInterceptor: typeof import('./components/app/Interceptor.vue')['default']
|
||||||
AppLogo: (typeof import("./components/app/Logo.vue"))["default"]
|
AppLogo: typeof import('./components/app/Logo.vue')['default']
|
||||||
AppOptions: (typeof import("./components/app/Options.vue"))["default"]
|
AppOptions: typeof import('./components/app/Options.vue')['default']
|
||||||
AppPaneLayout: (typeof import("./components/app/PaneLayout.vue"))["default"]
|
AppPaneLayout: typeof import('./components/app/PaneLayout.vue')['default']
|
||||||
AppShare: (typeof import("./components/app/Share.vue"))["default"]
|
AppShare: typeof import('./components/app/Share.vue')['default']
|
||||||
AppShortcuts: (typeof import("./components/app/Shortcuts.vue"))["default"]
|
AppShortcuts: typeof import('./components/app/Shortcuts.vue')['default']
|
||||||
AppShortcutsEntry: (typeof import("./components/app/ShortcutsEntry.vue"))["default"]
|
AppShortcutsEntry: typeof import('./components/app/ShortcutsEntry.vue')['default']
|
||||||
AppShortcutsPrompt: (typeof import("./components/app/ShortcutsPrompt.vue"))["default"]
|
AppShortcutsPrompt: typeof import('./components/app/ShortcutsPrompt.vue')['default']
|
||||||
AppSidenav: (typeof import("./components/app/Sidenav.vue"))["default"]
|
AppSidenav: typeof import('./components/app/Sidenav.vue')['default']
|
||||||
AppSpotlight: (typeof import("./components/app/spotlight/index.vue"))["default"]
|
AppSpotlight: typeof import('./components/app/spotlight/index.vue')['default']
|
||||||
AppSpotlightEntry: (typeof import("./components/app/spotlight/Entry.vue"))["default"]
|
AppSpotlightEntry: typeof import('./components/app/spotlight/Entry.vue')['default']
|
||||||
AppSpotlightEntryGQLHistory: (typeof import("./components/app/spotlight/entry/GQLHistory.vue"))["default"]
|
AppSpotlightEntryGQLHistory: typeof import('./components/app/spotlight/entry/GQLHistory.vue')['default']
|
||||||
AppSpotlightEntryGQLRequest: (typeof import("./components/app/spotlight/entry/GQLRequest.vue"))["default"]
|
AppSpotlightEntryGQLRequest: typeof import('./components/app/spotlight/entry/GQLRequest.vue')['default']
|
||||||
AppSpotlightEntryIconSelected: (typeof import("./components/app/spotlight/entry/IconSelected.vue"))["default"]
|
AppSpotlightEntryIconSelected: typeof import('./components/app/spotlight/entry/IconSelected.vue')['default']
|
||||||
AppSpotlightEntryRESTHistory: (typeof import("./components/app/spotlight/entry/RESTHistory.vue"))["default"]
|
AppSpotlightEntryRESTHistory: typeof import('./components/app/spotlight/entry/RESTHistory.vue')['default']
|
||||||
AppSpotlightEntryRESTRequest: (typeof import("./components/app/spotlight/entry/RESTRequest.vue"))["default"]
|
AppSpotlightEntryRESTRequest: typeof import('./components/app/spotlight/entry/RESTRequest.vue')['default']
|
||||||
AppSupport: (typeof import("./components/app/Support.vue"))["default"]
|
AppSupport: typeof import('./components/app/Support.vue')['default']
|
||||||
Collections: (typeof import("./components/collections/index.vue"))["default"]
|
Collections: typeof import('./components/collections/index.vue')['default']
|
||||||
CollectionsAdd: (typeof import("./components/collections/Add.vue"))["default"]
|
CollectionsAdd: typeof import('./components/collections/Add.vue')['default']
|
||||||
CollectionsAddFolder: (typeof import("./components/collections/AddFolder.vue"))["default"]
|
CollectionsAddFolder: typeof import('./components/collections/AddFolder.vue')['default']
|
||||||
CollectionsAddRequest: (typeof import("./components/collections/AddRequest.vue"))["default"]
|
CollectionsAddRequest: typeof import('./components/collections/AddRequest.vue')['default']
|
||||||
CollectionsCollection: (typeof import("./components/collections/Collection.vue"))["default"]
|
CollectionsCollection: typeof import('./components/collections/Collection.vue')['default']
|
||||||
CollectionsEdit: (typeof import("./components/collections/Edit.vue"))["default"]
|
CollectionsEdit: typeof import('./components/collections/Edit.vue')['default']
|
||||||
CollectionsEditFolder: (typeof import("./components/collections/EditFolder.vue"))["default"]
|
CollectionsEditFolder: typeof import('./components/collections/EditFolder.vue')['default']
|
||||||
CollectionsEditRequest: (typeof import("./components/collections/EditRequest.vue"))["default"]
|
CollectionsEditRequest: typeof import('./components/collections/EditRequest.vue')['default']
|
||||||
CollectionsGraphql: (typeof import("./components/collections/graphql/index.vue"))["default"]
|
CollectionsGraphql: typeof import('./components/collections/graphql/index.vue')['default']
|
||||||
CollectionsGraphqlAdd: (typeof import("./components/collections/graphql/Add.vue"))["default"]
|
CollectionsGraphqlAdd: typeof import('./components/collections/graphql/Add.vue')['default']
|
||||||
CollectionsGraphqlAddFolder: (typeof import("./components/collections/graphql/AddFolder.vue"))["default"]
|
CollectionsGraphqlAddFolder: typeof import('./components/collections/graphql/AddFolder.vue')['default']
|
||||||
CollectionsGraphqlAddRequest: (typeof import("./components/collections/graphql/AddRequest.vue"))["default"]
|
CollectionsGraphqlAddRequest: typeof import('./components/collections/graphql/AddRequest.vue')['default']
|
||||||
CollectionsGraphqlCollection: (typeof import("./components/collections/graphql/Collection.vue"))["default"]
|
CollectionsGraphqlCollection: typeof import('./components/collections/graphql/Collection.vue')['default']
|
||||||
CollectionsGraphqlEdit: (typeof import("./components/collections/graphql/Edit.vue"))["default"]
|
CollectionsGraphqlEdit: typeof import('./components/collections/graphql/Edit.vue')['default']
|
||||||
CollectionsGraphqlEditFolder: (typeof import("./components/collections/graphql/EditFolder.vue"))["default"]
|
CollectionsGraphqlEditFolder: typeof import('./components/collections/graphql/EditFolder.vue')['default']
|
||||||
CollectionsGraphqlEditRequest: (typeof import("./components/collections/graphql/EditRequest.vue"))["default"]
|
CollectionsGraphqlEditRequest: typeof import('./components/collections/graphql/EditRequest.vue')['default']
|
||||||
CollectionsGraphqlFolder: (typeof import("./components/collections/graphql/Folder.vue"))["default"]
|
CollectionsGraphqlFolder: typeof import('./components/collections/graphql/Folder.vue')['default']
|
||||||
CollectionsGraphqlImportExport: (typeof import("./components/collections/graphql/ImportExport.vue"))["default"]
|
CollectionsGraphqlImportExport: typeof import('./components/collections/graphql/ImportExport.vue')['default']
|
||||||
CollectionsGraphqlRequest: (typeof import("./components/collections/graphql/Request.vue"))["default"]
|
CollectionsGraphqlRequest: typeof import('./components/collections/graphql/Request.vue')['default']
|
||||||
CollectionsImportExport: (typeof import("./components/collections/ImportExport.vue"))["default"]
|
CollectionsImportExport: typeof import('./components/collections/ImportExport.vue')['default']
|
||||||
CollectionsMyCollections: (typeof import("./components/collections/MyCollections.vue"))["default"]
|
CollectionsMyCollections: typeof import('./components/collections/MyCollections.vue')['default']
|
||||||
CollectionsProperties: (typeof import("./components/collections/Properties.vue"))["default"]
|
CollectionsProperties: typeof import('./components/collections/Properties.vue')['default']
|
||||||
CollectionsRequest: (typeof import("./components/collections/Request.vue"))["default"]
|
CollectionsRequest: typeof import('./components/collections/Request.vue')['default']
|
||||||
CollectionsSaveRequest: (typeof import("./components/collections/SaveRequest.vue"))["default"]
|
CollectionsSaveRequest: typeof import('./components/collections/SaveRequest.vue')['default']
|
||||||
CollectionsTeamCollections: (typeof import("./components/collections/TeamCollections.vue"))["default"]
|
CollectionsTeamCollections: typeof import('./components/collections/TeamCollections.vue')['default']
|
||||||
CookiesAllModal: (typeof import("./components/cookies/AllModal.vue"))["default"]
|
CookiesAllModal: typeof import('./components/cookies/AllModal.vue')['default']
|
||||||
CookiesEditCookie: (typeof import("./components/cookies/EditCookie.vue"))["default"]
|
CookiesEditCookie: typeof import('./components/cookies/EditCookie.vue')['default']
|
||||||
Embeds: (typeof import("./components/embeds/index.vue"))["default"]
|
Embeds: typeof import('./components/embeds/index.vue')['default']
|
||||||
Environments: (typeof import("./components/environments/index.vue"))["default"]
|
Environments: typeof import('./components/environments/index.vue')['default']
|
||||||
EnvironmentsAdd: (typeof import("./components/environments/Add.vue"))["default"]
|
EnvironmentsAdd: typeof import('./components/environments/Add.vue')['default']
|
||||||
EnvironmentsImportExport: (typeof import("./components/environments/ImportExport.vue"))["default"]
|
EnvironmentsImportExport: typeof import('./components/environments/ImportExport.vue')['default']
|
||||||
EnvironmentsMy: (typeof import("./components/environments/my/index.vue"))["default"]
|
EnvironmentsMy: typeof import('./components/environments/my/index.vue')['default']
|
||||||
EnvironmentsMyDetails: (typeof import("./components/environments/my/Details.vue"))["default"]
|
EnvironmentsMyDetails: typeof import('./components/environments/my/Details.vue')['default']
|
||||||
EnvironmentsMyEnvironment: (typeof import("./components/environments/my/Environment.vue"))["default"]
|
EnvironmentsMyEnvironment: typeof import('./components/environments/my/Environment.vue')['default']
|
||||||
EnvironmentsSelector: (typeof import("./components/environments/Selector.vue"))["default"]
|
EnvironmentsSelector: typeof import('./components/environments/Selector.vue')['default']
|
||||||
EnvironmentsTeams: (typeof import("./components/environments/teams/index.vue"))["default"]
|
EnvironmentsTeams: typeof import('./components/environments/teams/index.vue')['default']
|
||||||
EnvironmentsTeamsDetails: (typeof import("./components/environments/teams/Details.vue"))["default"]
|
EnvironmentsTeamsDetails: typeof import('./components/environments/teams/Details.vue')['default']
|
||||||
EnvironmentsTeamsEnvironment: (typeof import("./components/environments/teams/Environment.vue"))["default"]
|
EnvironmentsTeamsEnvironment: typeof import('./components/environments/teams/Environment.vue')['default']
|
||||||
FirebaseLogin: (typeof import("./components/firebase/Login.vue"))["default"]
|
FirebaseLogin: typeof import('./components/firebase/Login.vue')['default']
|
||||||
FirebaseLogout: (typeof import("./components/firebase/Logout.vue"))["default"]
|
FirebaseLogout: typeof import('./components/firebase/Logout.vue')['default']
|
||||||
GraphqlAuthorization: (typeof import("./components/graphql/Authorization.vue"))["default"]
|
GraphqlAuthorization: typeof import('./components/graphql/Authorization.vue')['default']
|
||||||
GraphqlField: (typeof import("./components/graphql/Field.vue"))["default"]
|
GraphqlField: typeof import('./components/graphql/Field.vue')['default']
|
||||||
GraphqlHeaders: (typeof import("./components/graphql/Headers.vue"))["default"]
|
GraphqlHeaders: typeof import('./components/graphql/Headers.vue')['default']
|
||||||
GraphqlQuery: (typeof import("./components/graphql/Query.vue"))["default"]
|
GraphqlQuery: typeof import('./components/graphql/Query.vue')['default']
|
||||||
GraphqlRequest: (typeof import("./components/graphql/Request.vue"))["default"]
|
GraphqlRequest: typeof import('./components/graphql/Request.vue')['default']
|
||||||
GraphqlRequestOptions: (typeof import("./components/graphql/RequestOptions.vue"))["default"]
|
GraphqlRequestOptions: typeof import('./components/graphql/RequestOptions.vue')['default']
|
||||||
GraphqlRequestTab: (typeof import("./components/graphql/RequestTab.vue"))["default"]
|
GraphqlRequestTab: typeof import('./components/graphql/RequestTab.vue')['default']
|
||||||
GraphqlResponse: (typeof import("./components/graphql/Response.vue"))["default"]
|
GraphqlResponse: typeof import('./components/graphql/Response.vue')['default']
|
||||||
GraphqlSidebar: (typeof import("./components/graphql/Sidebar.vue"))["default"]
|
GraphqlSidebar: typeof import('./components/graphql/Sidebar.vue')['default']
|
||||||
GraphqlSubscriptionLog: (typeof import("./components/graphql/SubscriptionLog.vue"))["default"]
|
GraphqlSubscriptionLog: typeof import('./components/graphql/SubscriptionLog.vue')['default']
|
||||||
GraphqlTabHead: (typeof import("./components/graphql/TabHead.vue"))["default"]
|
GraphqlTabHead: typeof import('./components/graphql/TabHead.vue')['default']
|
||||||
GraphqlType: (typeof import("./components/graphql/Type.vue"))["default"]
|
GraphqlType: typeof import('./components/graphql/Type.vue')['default']
|
||||||
GraphqlTypeLink: (typeof import("./components/graphql/TypeLink.vue"))["default"]
|
GraphqlTypeLink: typeof import('./components/graphql/TypeLink.vue')['default']
|
||||||
GraphqlVariable: (typeof import("./components/graphql/Variable.vue"))["default"]
|
GraphqlVariable: typeof import('./components/graphql/Variable.vue')['default']
|
||||||
History: (typeof import("./components/history/index.vue"))["default"]
|
History: typeof import('./components/history/index.vue')['default']
|
||||||
HistoryGraphqlCard: (typeof import("./components/history/graphql/Card.vue"))["default"]
|
HistoryGraphqlCard: typeof import('./components/history/graphql/Card.vue')['default']
|
||||||
HistoryRestCard: (typeof import("./components/history/rest/Card.vue"))["default"]
|
HistoryRestCard: typeof import('./components/history/rest/Card.vue')['default']
|
||||||
HoppButtonPrimary: (typeof import("@hoppscotch/ui"))["HoppButtonPrimary"]
|
HoppButtonPrimary: typeof import('@hoppscotch/ui')['HoppButtonPrimary']
|
||||||
HoppButtonSecondary: (typeof import("@hoppscotch/ui"))["HoppButtonSecondary"]
|
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary']
|
||||||
HoppSmartAnchor: (typeof import("@hoppscotch/ui"))["HoppSmartAnchor"]
|
HoppSmartAnchor: typeof import('@hoppscotch/ui')['HoppSmartAnchor']
|
||||||
HoppSmartCheckbox: (typeof import("@hoppscotch/ui"))["HoppSmartCheckbox"]
|
HoppSmartCheckbox: typeof import('@hoppscotch/ui')['HoppSmartCheckbox']
|
||||||
HoppSmartConfirmModal: (typeof import("@hoppscotch/ui"))["HoppSmartConfirmModal"]
|
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal']
|
||||||
HoppSmartExpand: (typeof import("@hoppscotch/ui"))["HoppSmartExpand"]
|
HoppSmartExpand: typeof import('@hoppscotch/ui')['HoppSmartExpand']
|
||||||
HoppSmartFileChip: (typeof import("@hoppscotch/ui"))["HoppSmartFileChip"]
|
HoppSmartFileChip: typeof import('@hoppscotch/ui')['HoppSmartFileChip']
|
||||||
HoppSmartInput: (typeof import("@hoppscotch/ui"))["HoppSmartInput"]
|
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput']
|
||||||
HoppSmartIntersection: (typeof import("@hoppscotch/ui"))["HoppSmartIntersection"]
|
HoppSmartIntersection: typeof import('@hoppscotch/ui')['HoppSmartIntersection']
|
||||||
HoppSmartItem: (typeof import("@hoppscotch/ui"))["HoppSmartItem"]
|
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
|
||||||
HoppSmartLink: (typeof import("@hoppscotch/ui"))["HoppSmartLink"]
|
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink']
|
||||||
HoppSmartModal: (typeof import("@hoppscotch/ui"))["HoppSmartModal"]
|
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
|
||||||
HoppSmartPicture: (typeof import("@hoppscotch/ui"))["HoppSmartPicture"]
|
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture']
|
||||||
HoppSmartPlaceholder: (typeof import("@hoppscotch/ui"))["HoppSmartPlaceholder"]
|
HoppSmartPlaceholder: typeof import('@hoppscotch/ui')['HoppSmartPlaceholder']
|
||||||
HoppSmartProgressRing: (typeof import("@hoppscotch/ui"))["HoppSmartProgressRing"]
|
HoppSmartProgressRing: typeof import('@hoppscotch/ui')['HoppSmartProgressRing']
|
||||||
HoppSmartRadio: (typeof import("@hoppscotch/ui"))["HoppSmartRadio"]
|
HoppSmartRadio: typeof import('@hoppscotch/ui')['HoppSmartRadio']
|
||||||
HoppSmartRadioGroup: (typeof import("@hoppscotch/ui"))["HoppSmartRadioGroup"]
|
HoppSmartRadioGroup: typeof import('@hoppscotch/ui')['HoppSmartRadioGroup']
|
||||||
HoppSmartSelectWrapper: (typeof import("@hoppscotch/ui"))["HoppSmartSelectWrapper"]
|
HoppSmartSelectWrapper: typeof import('@hoppscotch/ui')['HoppSmartSelectWrapper']
|
||||||
HoppSmartSlideOver: (typeof import("@hoppscotch/ui"))["HoppSmartSlideOver"]
|
HoppSmartSlideOver: typeof import('@hoppscotch/ui')['HoppSmartSlideOver']
|
||||||
HoppSmartSpinner: (typeof import("@hoppscotch/ui"))["HoppSmartSpinner"]
|
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
|
||||||
HoppSmartTab: (typeof import("@hoppscotch/ui"))["HoppSmartTab"]
|
HoppSmartTab: typeof import('@hoppscotch/ui')['HoppSmartTab']
|
||||||
HoppSmartTabs: (typeof import("@hoppscotch/ui"))["HoppSmartTabs"]
|
HoppSmartTabs: typeof import('@hoppscotch/ui')['HoppSmartTabs']
|
||||||
HoppSmartToggle: (typeof import("@hoppscotch/ui"))["HoppSmartToggle"]
|
HoppSmartToggle: typeof import('@hoppscotch/ui')['HoppSmartToggle']
|
||||||
HoppSmartTree: (typeof import("@hoppscotch/ui"))["HoppSmartTree"]
|
HoppSmartTree: typeof import('@hoppscotch/ui')['HoppSmartTree']
|
||||||
HoppSmartWindow: (typeof import("@hoppscotch/ui"))["HoppSmartWindow"]
|
HoppSmartWindow: typeof import('@hoppscotch/ui')['HoppSmartWindow']
|
||||||
HoppSmartWindows: (typeof import("@hoppscotch/ui"))["HoppSmartWindows"]
|
HoppSmartWindows: typeof import('@hoppscotch/ui')['HoppSmartWindows']
|
||||||
HttpAuthorization: (typeof import("./components/http/Authorization.vue"))["default"]
|
HttpAuthorization: typeof import('./components/http/Authorization.vue')['default']
|
||||||
HttpAuthorizationApiKey: (typeof import("./components/http/authorization/ApiKey.vue"))["default"]
|
HttpAuthorizationApiKey: typeof import('./components/http/authorization/ApiKey.vue')['default']
|
||||||
HttpAuthorizationBasic: (typeof import("./components/http/authorization/Basic.vue"))["default"]
|
HttpAuthorizationBasic: typeof import('./components/http/authorization/Basic.vue')['default']
|
||||||
HttpBody: (typeof import("./components/http/Body.vue"))["default"]
|
HttpBody: typeof import('./components/http/Body.vue')['default']
|
||||||
HttpBodyParameters: (typeof import("./components/http/BodyParameters.vue"))["default"]
|
HttpBodyParameters: typeof import('./components/http/BodyParameters.vue')['default']
|
||||||
HttpCodegenModal: (typeof import("./components/http/CodegenModal.vue"))["default"]
|
HttpCodegenModal: typeof import('./components/http/CodegenModal.vue')['default']
|
||||||
HttpHeaders: (typeof import("./components/http/Headers.vue"))["default"]
|
HttpHeaders: typeof import('./components/http/Headers.vue')['default']
|
||||||
HttpImportCurl: (typeof import("./components/http/ImportCurl.vue"))["default"]
|
HttpImportCurl: typeof import('./components/http/ImportCurl.vue')['default']
|
||||||
HttpOAuth2Authorization: (typeof import("./components/http/OAuth2Authorization.vue"))["default"]
|
HttpOAuth2Authorization: typeof import('./components/http/OAuth2Authorization.vue')['default']
|
||||||
HttpParameters: (typeof import("./components/http/Parameters.vue"))["default"]
|
HttpParameters: typeof import('./components/http/Parameters.vue')['default']
|
||||||
HttpPreRequestScript: (typeof import("./components/http/PreRequestScript.vue"))["default"]
|
HttpPreRequestScript: typeof import('./components/http/PreRequestScript.vue')['default']
|
||||||
HttpRawBody: (typeof import("./components/http/RawBody.vue"))["default"]
|
HttpRawBody: typeof import('./components/http/RawBody.vue')['default']
|
||||||
HttpReqChangeConfirmModal: (typeof import("./components/http/ReqChangeConfirmModal.vue"))["default"]
|
HttpReqChangeConfirmModal: typeof import('./components/http/ReqChangeConfirmModal.vue')['default']
|
||||||
HttpRequest: (typeof import("./components/http/Request.vue"))["default"]
|
HttpRequest: typeof import('./components/http/Request.vue')['default']
|
||||||
HttpRequestOptions: (typeof import("./components/http/RequestOptions.vue"))["default"]
|
HttpRequestOptions: typeof import('./components/http/RequestOptions.vue')['default']
|
||||||
HttpRequestTab: (typeof import("./components/http/RequestTab.vue"))["default"]
|
HttpRequestTab: typeof import('./components/http/RequestTab.vue')['default']
|
||||||
HttpResponse: (typeof import("./components/http/Response.vue"))["default"]
|
HttpResponse: typeof import('./components/http/Response.vue')['default']
|
||||||
HttpResponseMeta: (typeof import("./components/http/ResponseMeta.vue"))["default"]
|
HttpResponseMeta: typeof import('./components/http/ResponseMeta.vue')['default']
|
||||||
HttpSidebar: (typeof import("./components/http/Sidebar.vue"))["default"]
|
HttpSidebar: typeof import('./components/http/Sidebar.vue')['default']
|
||||||
HttpTabHead: (typeof import("./components/http/TabHead.vue"))["default"]
|
HttpTabHead: typeof import('./components/http/TabHead.vue')['default']
|
||||||
HttpTestResult: (typeof import("./components/http/TestResult.vue"))["default"]
|
HttpTestResult: typeof import('./components/http/TestResult.vue')['default']
|
||||||
HttpTestResultEntry: (typeof import("./components/http/TestResultEntry.vue"))["default"]
|
HttpTestResultEntry: typeof import('./components/http/TestResultEntry.vue')['default']
|
||||||
HttpTestResultEnv: (typeof import("./components/http/TestResultEnv.vue"))["default"]
|
HttpTestResultEnv: typeof import('./components/http/TestResultEnv.vue')['default']
|
||||||
HttpTestResultReport: (typeof import("./components/http/TestResultReport.vue"))["default"]
|
HttpTestResultReport: typeof import('./components/http/TestResultReport.vue')['default']
|
||||||
HttpTests: (typeof import("./components/http/Tests.vue"))["default"]
|
HttpTests: typeof import('./components/http/Tests.vue')['default']
|
||||||
HttpURLEncodedParams: (typeof import("./components/http/URLEncodedParams.vue"))["default"]
|
HttpURLEncodedParams: typeof import('./components/http/URLEncodedParams.vue')['default']
|
||||||
IconLucideActivity: (typeof import("~icons/lucide/activity"))["default"]
|
IconLucideActivity: typeof import('~icons/lucide/activity')['default']
|
||||||
IconLucideAlertTriangle: (typeof import("~icons/lucide/alert-triangle"))["default"]
|
IconLucideAlertTriangle: typeof import('~icons/lucide/alert-triangle')['default']
|
||||||
IconLucideArrowLeft: (typeof import("~icons/lucide/arrow-left"))["default"]
|
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
||||||
IconLucideArrowUpRight: (typeof import("~icons/lucide/arrow-up-right"))["default"]
|
IconLucideArrowUpRight: typeof import('~icons/lucide/arrow-up-right')['default']
|
||||||
IconLucideBrush: (typeof import("~icons/lucide/brush"))["default"]
|
IconLucideCheckCircle: typeof import('~icons/lucide/check-circle')['default']
|
||||||
IconLucideCheckCircle: (typeof import("~icons/lucide/check-circle"))["default"]
|
IconLucideChevronRight: typeof import('~icons/lucide/chevron-right')['default']
|
||||||
IconLucideChevronRight: (typeof import("~icons/lucide/chevron-right"))["default"]
|
IconLucideGlobe: typeof import('~icons/lucide/globe')['default']
|
||||||
IconLucideGlobe: (typeof import("~icons/lucide/globe"))["default"]
|
IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['default']
|
||||||
IconLucideHelpCircle: (typeof import("~icons/lucide/help-circle"))["default"]
|
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
||||||
IconLucideInbox: (typeof import("~icons/lucide/inbox"))["default"]
|
IconLucideInfo: typeof import('~icons/lucide/info')['default']
|
||||||
IconLucideInfo: (typeof import("~icons/lucide/info"))["default"]
|
IconLucideLayers: typeof import('~icons/lucide/layers')['default']
|
||||||
IconLucideLayers: (typeof import("~icons/lucide/layers"))["default"]
|
IconLucideListEnd: typeof import('~icons/lucide/list-end')['default']
|
||||||
IconLucideListEnd: (typeof import("~icons/lucide/list-end"))["default"]
|
IconLucideMinus: typeof import('~icons/lucide/minus')['default']
|
||||||
IconLucideMinus: (typeof import("~icons/lucide/minus"))["default"]
|
IconLucideSearch: typeof import('~icons/lucide/search')['default']
|
||||||
IconLucideRss: (typeof import("~icons/lucide/rss"))["default"]
|
IconLucideUsers: typeof import('~icons/lucide/users')['default']
|
||||||
IconLucideSearch: (typeof import("~icons/lucide/search"))["default"]
|
IconLucideX: typeof import('~icons/lucide/x')['default']
|
||||||
IconLucideUsers: (typeof import("~icons/lucide/users"))["default"]
|
ImportExportBase: typeof import('./components/importExport/Base.vue')['default']
|
||||||
IconLucideX: (typeof import("~icons/lucide/x"))["default"]
|
ImportExportImportExportList: typeof import('./components/importExport/ImportExportList.vue')['default']
|
||||||
ImportExportBase: (typeof import("./components/importExport/Base.vue"))["default"]
|
ImportExportImportExportSourcesList: typeof import('./components/importExport/ImportExportSourcesList.vue')['default']
|
||||||
ImportExportImportExportList: (typeof import("./components/importExport/ImportExportList.vue"))["default"]
|
ImportExportImportExportStepsFileImport: typeof import('./components/importExport/ImportExportSteps/FileImport.vue')['default']
|
||||||
ImportExportImportExportSourcesList: (typeof import("./components/importExport/ImportExportSourcesList.vue"))["default"]
|
ImportExportImportExportStepsMyCollectionImport: typeof import('./components/importExport/ImportExportSteps/MyCollectionImport.vue')['default']
|
||||||
ImportExportImportExportStepsFileImport: (typeof import("./components/importExport/ImportExportSteps/FileImport.vue"))["default"]
|
ImportExportImportExportStepsUrlImport: typeof import('./components/importExport/ImportExportSteps/UrlImport.vue')['default']
|
||||||
ImportExportImportExportStepsMyCollectionImport: (typeof import("./components/importExport/ImportExportSteps/MyCollectionImport.vue"))["default"]
|
InterceptorsErrorPlaceholder: typeof import('./components/interceptors/ErrorPlaceholder.vue')['default']
|
||||||
ImportExportImportExportStepsUrlImport: (typeof import("./components/importExport/ImportExportSteps/UrlImport.vue"))["default"]
|
InterceptorsExtensionSubtitle: typeof import('./components/interceptors/ExtensionSubtitle.vue')['default']
|
||||||
InterceptorsErrorPlaceholder: (typeof import("./components/interceptors/ErrorPlaceholder.vue"))["default"]
|
LensesHeadersRenderer: typeof import('./components/lenses/HeadersRenderer.vue')['default']
|
||||||
InterceptorsExtensionSubtitle: (typeof import("./components/interceptors/ExtensionSubtitle.vue"))["default"]
|
LensesHeadersRendererEntry: typeof import('./components/lenses/HeadersRendererEntry.vue')['default']
|
||||||
LensesHeadersRenderer: (typeof import("./components/lenses/HeadersRenderer.vue"))["default"]
|
LensesRenderersAudioLensRenderer: typeof import('./components/lenses/renderers/AudioLensRenderer.vue')['default']
|
||||||
LensesHeadersRendererEntry: (typeof import("./components/lenses/HeadersRendererEntry.vue"))["default"]
|
LensesRenderersHTMLLensRenderer: typeof import('./components/lenses/renderers/HTMLLensRenderer.vue')['default']
|
||||||
LensesRenderersAudioLensRenderer: (typeof import("./components/lenses/renderers/AudioLensRenderer.vue"))["default"]
|
LensesRenderersImageLensRenderer: typeof import('./components/lenses/renderers/ImageLensRenderer.vue')['default']
|
||||||
LensesRenderersHTMLLensRenderer: (typeof import("./components/lenses/renderers/HTMLLensRenderer.vue"))["default"]
|
LensesRenderersJSONLensRenderer: typeof import('./components/lenses/renderers/JSONLensRenderer.vue')['default']
|
||||||
LensesRenderersImageLensRenderer: (typeof import("./components/lenses/renderers/ImageLensRenderer.vue"))["default"]
|
LensesRenderersPDFLensRenderer: typeof import('./components/lenses/renderers/PDFLensRenderer.vue')['default']
|
||||||
LensesRenderersJSONLensRenderer: (typeof import("./components/lenses/renderers/JSONLensRenderer.vue"))["default"]
|
LensesRenderersRawLensRenderer: typeof import('./components/lenses/renderers/RawLensRenderer.vue')['default']
|
||||||
LensesRenderersPDFLensRenderer: (typeof import("./components/lenses/renderers/PDFLensRenderer.vue"))["default"]
|
LensesRenderersVideoLensRenderer: typeof import('./components/lenses/renderers/VideoLensRenderer.vue')['default']
|
||||||
LensesRenderersRawLensRenderer: (typeof import("./components/lenses/renderers/RawLensRenderer.vue"))["default"]
|
LensesRenderersXMLLensRenderer: typeof import('./components/lenses/renderers/XMLLensRenderer.vue')['default']
|
||||||
LensesRenderersVideoLensRenderer: (typeof import("./components/lenses/renderers/VideoLensRenderer.vue"))["default"]
|
LensesResponseBodyRenderer: typeof import('./components/lenses/ResponseBodyRenderer.vue')['default']
|
||||||
LensesRenderersXMLLensRenderer: (typeof import("./components/lenses/renderers/XMLLensRenderer.vue"))["default"]
|
ProfileUserDelete: typeof import('./components/profile/UserDelete.vue')['default']
|
||||||
LensesResponseBodyRenderer: (typeof import("./components/lenses/ResponseBodyRenderer.vue"))["default"]
|
RealtimeCommunication: typeof import('./components/realtime/Communication.vue')['default']
|
||||||
ProfileUserDelete: (typeof import("./components/profile/UserDelete.vue"))["default"]
|
RealtimeConnectionConfig: typeof import('./components/realtime/ConnectionConfig.vue')['default']
|
||||||
RealtimeCommunication: (typeof import("./components/realtime/Communication.vue"))["default"]
|
RealtimeLog: typeof import('./components/realtime/Log.vue')['default']
|
||||||
RealtimeConnectionConfig: (typeof import("./components/realtime/ConnectionConfig.vue"))["default"]
|
RealtimeLogEntry: typeof import('./components/realtime/LogEntry.vue')['default']
|
||||||
RealtimeLog: (typeof import("./components/realtime/Log.vue"))["default"]
|
RealtimeSubscription: typeof import('./components/realtime/Subscription.vue')['default']
|
||||||
RealtimeLogEntry: (typeof import("./components/realtime/LogEntry.vue"))["default"]
|
SettingsExtension: typeof import('./components/settings/Extension.vue')['default']
|
||||||
RealtimeSubscription: (typeof import("./components/realtime/Subscription.vue"))["default"]
|
SettingsProxy: typeof import('./components/settings/Proxy.vue')['default']
|
||||||
SettingsExtension: (typeof import("./components/settings/Extension.vue"))["default"]
|
Share: typeof import('./components/share/index.vue')['default']
|
||||||
SettingsProxy: (typeof import("./components/settings/Proxy.vue"))["default"]
|
ShareCreateModal: typeof import('./components/share/CreateModal.vue')['default']
|
||||||
Share: (typeof import("./components/share/index.vue"))["default"]
|
ShareCustomizeModal: typeof import('./components/share/CustomizeModal.vue')['default']
|
||||||
ShareCreateModal: (typeof import("./components/share/CreateModal.vue"))["default"]
|
ShareModal: typeof import('./components/share/Modal.vue')['default']
|
||||||
ShareCustomizeModal: (typeof import("./components/share/CustomizeModal.vue"))["default"]
|
ShareRequest: typeof import('./components/share/Request.vue')['default']
|
||||||
ShareModal: (typeof import("./components/share/Modal.vue"))["default"]
|
ShareTemplatesButton: typeof import('./components/share/templates/Button.vue')['default']
|
||||||
ShareRequest: (typeof import("./components/share/Request.vue"))["default"]
|
ShareTemplatesEmbeds: typeof import('./components/share/templates/Embeds.vue')['default']
|
||||||
ShareTemplatesButton: (typeof import("./components/share/templates/Button.vue"))["default"]
|
ShareTemplatesLink: typeof import('./components/share/templates/Link.vue')['default']
|
||||||
ShareTemplatesEmbeds: (typeof import("./components/share/templates/Embeds.vue"))["default"]
|
SmartAccentModePicker: typeof import('./components/smart/AccentModePicker.vue')['default']
|
||||||
ShareTemplatesLink: (typeof import("./components/share/templates/Link.vue"))["default"]
|
SmartChangeLanguage: typeof import('./components/smart/ChangeLanguage.vue')['default']
|
||||||
SmartAccentModePicker: (typeof import("./components/smart/AccentModePicker.vue"))["default"]
|
SmartColorModePicker: typeof import('./components/smart/ColorModePicker.vue')['default']
|
||||||
SmartChangeLanguage: (typeof import("./components/smart/ChangeLanguage.vue"))["default"]
|
SmartEnvInput: typeof import('./components/smart/EnvInput.vue')['default']
|
||||||
SmartColorModePicker: (typeof import("./components/smart/ColorModePicker.vue"))["default"]
|
TabPrimary: typeof import('./components/tab/Primary.vue')['default']
|
||||||
SmartEnvInput: (typeof import("./components/smart/EnvInput.vue"))["default"]
|
TabSecondary: typeof import('./components/tab/Secondary.vue')['default']
|
||||||
TabPrimary: (typeof import("./components/tab/Primary.vue"))["default"]
|
Teams: typeof import('./components/teams/index.vue')['default']
|
||||||
TabSecondary: (typeof import("./components/tab/Secondary.vue"))["default"]
|
TeamsAdd: typeof import('./components/teams/Add.vue')['default']
|
||||||
Teams: (typeof import("./components/teams/index.vue"))["default"]
|
TeamsEdit: typeof import('./components/teams/Edit.vue')['default']
|
||||||
TeamsAdd: (typeof import("./components/teams/Add.vue"))["default"]
|
TeamsInvite: typeof import('./components/teams/Invite.vue')['default']
|
||||||
TeamsEdit: (typeof import("./components/teams/Edit.vue"))["default"]
|
TeamsMemberStack: typeof import('./components/teams/MemberStack.vue')['default']
|
||||||
TeamsInvite: (typeof import("./components/teams/Invite.vue"))["default"]
|
TeamsModal: typeof import('./components/teams/Modal.vue')['default']
|
||||||
TeamsMemberStack: (typeof import("./components/teams/MemberStack.vue"))["default"]
|
TeamsTeam: typeof import('./components/teams/Team.vue')['default']
|
||||||
TeamsModal: (typeof import("./components/teams/Modal.vue"))["default"]
|
Tippy: typeof import('vue-tippy')['Tippy']
|
||||||
TeamsTeam: (typeof import("./components/teams/Team.vue"))["default"]
|
WorkspaceCurrent: typeof import('./components/workspace/Current.vue')['default']
|
||||||
Tippy: (typeof import("vue-tippy"))["Tippy"]
|
WorkspaceSelector: typeof import('./components/workspace/Selector.vue')['default']
|
||||||
WorkspaceCurrent: (typeof import("./components/workspace/Current.vue"))["default"]
|
|
||||||
WorkspaceSelector: (typeof import("./components/workspace/Selector.vue"))["default"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
ref="contextMenuRef"
|
ref="contextMenuRef"
|
||||||
class="fixed transform -translate-x-10 -translate-y-8 rounded border border-dividerDark bg-popover p-2 shadow-lg"
|
class="fixed translate-y-8 transform rounded border border-dividerDark bg-popover p-2 shadow-lg"
|
||||||
:style="`top: ${position.top}px; left: ${position.left}px; z-index: 100;`"
|
:style="`top: ${position.top}px; left: ${position.left}px; z-index: 1000;`"
|
||||||
>
|
>
|
||||||
<div v-if="contextMenuOptions" class="flex flex-col">
|
<div v-if="contextMenuOptions" class="flex flex-col">
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -330,11 +330,11 @@ const myTeams = useReadonlyStream(teamListAdapter.teamList$, null)
|
|||||||
|
|
||||||
const workspace = workspaceService.currentWorkspace
|
const workspace = workspaceService.currentWorkspace
|
||||||
|
|
||||||
const workspaceName = computed(() => {
|
const workspaceName = computed(() =>
|
||||||
return workspace.value.type === "personal"
|
workspace.value.type === "personal"
|
||||||
? t("workspace.personal")
|
? t("workspace.personal")
|
||||||
: workspace.value.teamName
|
: workspace.value.teamName
|
||||||
})
|
)
|
||||||
|
|
||||||
const refetchTeams = () => {
|
const refetchTeams = () => {
|
||||||
teamListAdapter.fetchList()
|
teamListAdapter.fetchList()
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ import { environmentsStore } from "~/newstore/environments"
|
|||||||
import { platform } from "~/platform"
|
import { platform } from "~/platform"
|
||||||
import { useService } from "dioc/vue"
|
import { useService } from "dioc/vue"
|
||||||
import { SecretEnvironmentService } from "~/services/secret-environment.service"
|
import { SecretEnvironmentService } from "~/services/secret-environment.service"
|
||||||
import { uniqueID } from "~/helpers/utils/uniqueID"
|
import { uniqueId } from "lodash-es"
|
||||||
|
|
||||||
type EnvironmentVariable = {
|
type EnvironmentVariable = {
|
||||||
id: number
|
id: number
|
||||||
@@ -277,7 +277,7 @@ const workingEnv = computed(() => {
|
|||||||
} as Environment
|
} as Environment
|
||||||
} else if (props.action === "new") {
|
} else if (props.action === "new") {
|
||||||
return {
|
return {
|
||||||
id: uniqueID(),
|
id: uniqueId(),
|
||||||
name: "",
|
name: "",
|
||||||
variables: props.envVars(),
|
variables: props.envVars(),
|
||||||
}
|
}
|
||||||
@@ -331,7 +331,7 @@ watch(
|
|||||||
: "variables"
|
: "variables"
|
||||||
|
|
||||||
if (props.editingEnvironmentIndex !== "Global") {
|
if (props.editingEnvironmentIndex !== "Global") {
|
||||||
editingID.value = workingEnv.value?.id || uniqueID()
|
editingID.value = workingEnv.value?.id ?? uniqueId()
|
||||||
}
|
}
|
||||||
vars.value = pipe(
|
vars.value = pipe(
|
||||||
workingEnv.value?.variables ?? [],
|
workingEnv.value?.variables ?? [],
|
||||||
@@ -416,12 +416,14 @@ const saveEnvironment = () => {
|
|||||||
|
|
||||||
const variables = pipe(
|
const variables = pipe(
|
||||||
filteredVariables,
|
filteredVariables,
|
||||||
A.map((e) => (e.secret ? { key: e.key, secret: e.secret } : e))
|
A.map((e) =>
|
||||||
|
e.secret ? { key: e.key, secret: e.secret, value: undefined } : e
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
const environmentUpdated: Environment = {
|
const environmentUpdated: Environment = {
|
||||||
v: 1,
|
v: 1,
|
||||||
id: uniqueID(),
|
id: uniqueId(),
|
||||||
name: editingName.value,
|
name: editingName.value,
|
||||||
variables,
|
variables,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -360,7 +360,7 @@ const saveEnvironment = async () => {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const filteredVariables = pipe(
|
const filterdVariables = pipe(
|
||||||
vars.value,
|
vars.value,
|
||||||
A.filterMap(
|
A.filterMap(
|
||||||
flow(
|
flow(
|
||||||
@@ -371,15 +371,17 @@ const saveEnvironment = async () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const secretVariables = pipe(
|
const secretVariables = pipe(
|
||||||
filteredVariables,
|
filterdVariables,
|
||||||
A.filterMapWithIndex((i, e) =>
|
A.filterMapWithIndex((i, e) =>
|
||||||
e.secret ? O.some({ key: e.key, value: e.value, varIndex: i }) : O.none
|
e.secret ? O.some({ key: e.key, value: e.value, varIndex: i }) : O.none
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
const variables = pipe(
|
const variables = pipe(
|
||||||
filteredVariables,
|
filterdVariables,
|
||||||
A.map((e) => (e.secret ? { key: e.key, secret: e.secret } : e))
|
A.map((e) =>
|
||||||
|
e.secret ? { key: e.key, secret: e.secret, value: undefined } : e
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
const environmentUpdated: Environment = {
|
const environmentUpdated: Environment = {
|
||||||
|
|||||||
@@ -417,9 +417,7 @@ function handleTextSelection() {
|
|||||||
const { from, to } = selection
|
const { from, to } = selection
|
||||||
if (from === to) return
|
if (from === to) return
|
||||||
const text = view.value?.state.doc.sliceString(from, to)
|
const text = view.value?.state.doc.sliceString(from, to)
|
||||||
const coords = view.value?.coordsAtPos(from)
|
const { top, left } = view.value?.coordsAtPos(from)
|
||||||
const top = coords?.top ?? 0
|
|
||||||
const left = coords?.left ?? 0
|
|
||||||
if (text) {
|
if (text) {
|
||||||
invokeAction("contextmenu.open", {
|
invokeAction("contextmenu.open", {
|
||||||
position: {
|
position: {
|
||||||
@@ -441,17 +439,16 @@ function handleTextSelection() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debounce to prevent double click from selecting the word
|
|
||||||
const debouncedTextSelection = (time: number) =>
|
|
||||||
useDebounceFn(() => {
|
|
||||||
handleTextSelection()
|
|
||||||
}, time)
|
|
||||||
|
|
||||||
const initView = (el: any) => {
|
const initView = (el: any) => {
|
||||||
|
// Debounce to prevent double click from selecting the word
|
||||||
|
const debounceFn = useDebounceFn(() => {
|
||||||
|
handleTextSelection()
|
||||||
|
}, 140)
|
||||||
|
|
||||||
// Only add event listeners if context menu is enabled in the component
|
// Only add event listeners if context menu is enabled in the component
|
||||||
if (props.contextMenuEnabled) {
|
if (props.contextMenuEnabled) {
|
||||||
el.addEventListener("mouseup", debouncedTextSelection(140))
|
el.addEventListener("mouseup", debounceFn)
|
||||||
el.addEventListener("keyup", debouncedTextSelection(140))
|
el.addEventListener("keyup", debounceFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
const extensions: Extension = getExtensions(props.readonly || isSecret.value)
|
const extensions: Extension = getExtensions(props.readonly || isSecret.value)
|
||||||
@@ -501,8 +498,7 @@ const getExtensions = (readonly: boolean): Extension => {
|
|||||||
},
|
},
|
||||||
scroll(event) {
|
scroll(event) {
|
||||||
if (event.target && props.contextMenuEnabled) {
|
if (event.target && props.contextMenuEnabled) {
|
||||||
// Debounce to make the performance better
|
handleTextSelection()
|
||||||
debouncedTextSelection(30)()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -27,10 +27,13 @@ const workspaceService = useService(WorkspaceService)
|
|||||||
const workspace = workspaceService.currentWorkspace
|
const workspace = workspaceService.currentWorkspace
|
||||||
|
|
||||||
const currentWorkspace = computed(() => {
|
const currentWorkspace = computed(() => {
|
||||||
if (props.isOnlyPersonal || workspace.value.type === "personal") {
|
if (props.isOnlyPersonal) {
|
||||||
return t("workspace.personal")
|
return `${t("workspace.personal")}`
|
||||||
}
|
}
|
||||||
return teamWorkspaceName.value
|
if (workspace.value.type === "team") {
|
||||||
|
return teamWorkspaceName.value
|
||||||
|
}
|
||||||
|
return `${t("workspace.personal")}`
|
||||||
})
|
})
|
||||||
|
|
||||||
const teamWorkspaceName = computed(() => {
|
const teamWorkspaceName = computed(() => {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<HoppSmartItem
|
<HoppSmartItem
|
||||||
:label="t('workspace.personal')"
|
label="My Workspace"
|
||||||
:icon="IconUser"
|
:icon="IconUser"
|
||||||
:info-icon="workspace.type === 'personal' ? IconDone : undefined"
|
:info-icon="workspace.type === 'personal' ? IconDone : undefined"
|
||||||
:active-info-icon="workspace.type === 'personal'"
|
:active-info-icon="workspace.type === 'personal'"
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
class="sticky top-0 z-10 mb-2 flex items-center justify-between bg-popover py-2 pl-2"
|
class="sticky top-0 z-10 mb-2 flex items-center justify-between bg-popover py-2 pl-2"
|
||||||
>
|
>
|
||||||
<div class="flex items-center px-2 font-semibold text-secondaryLight">
|
<div class="flex items-center px-2 font-semibold text-secondaryLight">
|
||||||
{{ t("workspace.other_workspaces") }}
|
{{ t("team.title") }}
|
||||||
</div>
|
</div>
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
|
|||||||
@@ -242,9 +242,7 @@ export function useCodemirror(
|
|||||||
const { from, to } = selection
|
const { from, to } = selection
|
||||||
if (from === to) return
|
if (from === to) return
|
||||||
const text = view.value?.state.doc.sliceString(from, to)
|
const text = view.value?.state.doc.sliceString(from, to)
|
||||||
const coords = view.value?.coordsAtPos(from)
|
const { top, left } = view.value?.coordsAtPos(from)
|
||||||
const top = coords?.top ?? 0
|
|
||||||
const left = coords?.left ?? 0
|
|
||||||
if (text?.trim()) {
|
if (text?.trim()) {
|
||||||
invokeAction("contextmenu.open", {
|
invokeAction("contextmenu.open", {
|
||||||
position: {
|
position: {
|
||||||
@@ -265,12 +263,6 @@ export function useCodemirror(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debounce to prevent double click from selecting the word
|
|
||||||
const debouncedTextSelection = (time: number) =>
|
|
||||||
useDebounceFn(() => {
|
|
||||||
handleTextSelection()
|
|
||||||
}, time)
|
|
||||||
|
|
||||||
const initView = (el: any) => {
|
const initView = (el: any) => {
|
||||||
if (el) platform.ui?.onCodemirrorInstanceMount?.(el)
|
if (el) platform.ui?.onCodemirrorInstanceMount?.(el)
|
||||||
|
|
||||||
@@ -282,10 +274,15 @@ export function useCodemirror(
|
|||||||
ViewPlugin.fromClass(
|
ViewPlugin.fromClass(
|
||||||
class {
|
class {
|
||||||
update(update: ViewUpdate) {
|
update(update: ViewUpdate) {
|
||||||
|
// Debounce to prevent double click from selecting the word
|
||||||
|
const debounceFn = useDebounceFn(() => {
|
||||||
|
handleTextSelection()
|
||||||
|
}, 140)
|
||||||
|
|
||||||
// Only add event listeners if context menu is enabled in the editor
|
// Only add event listeners if context menu is enabled in the editor
|
||||||
if (options.contextMenuEnabled) {
|
if (options.contextMenuEnabled) {
|
||||||
el.addEventListener("mouseup", debouncedTextSelection(140))
|
el.addEventListener("mouseup", debounceFn)
|
||||||
el.addEventListener("keyup", debouncedTextSelection(140))
|
el.addEventListener("keyup", debounceFn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.onUpdate) {
|
if (options.onUpdate) {
|
||||||
@@ -327,8 +324,7 @@ export function useCodemirror(
|
|||||||
EditorView.domEventHandlers({
|
EditorView.domEventHandlers({
|
||||||
scroll(event) {
|
scroll(event) {
|
||||||
if (event.target && options.contextMenuEnabled) {
|
if (event.target && options.contextMenuEnabled) {
|
||||||
// Debounce to make the performance better
|
handleTextSelection()
|
||||||
debouncedTextSelection(30)()
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -4,12 +4,11 @@ import * as O from "fp-ts/Option"
|
|||||||
import * as RA from "fp-ts/ReadonlyArray"
|
import * as RA from "fp-ts/ReadonlyArray"
|
||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
import { translateToNewRESTCollection, HoppCollection } from "@hoppscotch/data"
|
import { translateToNewRESTCollection, HoppCollection } from "@hoppscotch/data"
|
||||||
|
import { isPlainObject as _isPlainObject } from "lodash-es"
|
||||||
|
|
||||||
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||||
import { safeParseJSON } from "~/helpers/functional/json"
|
import { safeParseJSON } from "~/helpers/functional/json"
|
||||||
import { translateToNewGQLCollection } from "@hoppscotch/data"
|
import { translateToNewGQLCollection } from "@hoppscotch/data"
|
||||||
import { entityReference } from "verzod"
|
|
||||||
import { z } from "zod"
|
|
||||||
|
|
||||||
export const hoppRESTImporter = (content: string[]) =>
|
export const hoppRESTImporter = (content: string[]) =>
|
||||||
pipe(
|
pipe(
|
||||||
@@ -27,14 +26,26 @@ export const hoppRESTImporter = (content: string[]) =>
|
|||||||
TE.fromOption(() => IMPORTER_INVALID_FILE_FORMAT)
|
TE.fromOption(() => IMPORTER_INVALID_FILE_FORMAT)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if a value is a plain object
|
||||||
|
*/
|
||||||
|
const isPlainObject = (value: any): value is object => _isPlainObject(value)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks if a collection matches the schema for a hoppscotch collection.
|
||||||
|
* here 2 is the latest version of the schema.
|
||||||
|
*/
|
||||||
|
const isValidCollection = (collection: unknown): collection is HoppCollection =>
|
||||||
|
isPlainObject(collection) && "v" in collection && collection.v === 2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* checks if a collection is a valid hoppscotch collection.
|
* checks if a collection is a valid hoppscotch collection.
|
||||||
* else translate it into one.
|
* else translate it into one.
|
||||||
*/
|
*/
|
||||||
const validateCollection = (collection: unknown) => {
|
const validateCollection = (collection: unknown) => {
|
||||||
const result = entityReference(HoppCollection).safeParse(collection)
|
if (isValidCollection(collection)) {
|
||||||
if (result.success) return O.some(result.data)
|
return O.some(collection)
|
||||||
|
}
|
||||||
return O.some(translateToNewRESTCollection(collection))
|
return O.some(translateToNewRESTCollection(collection))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,9 +75,8 @@ export const hoppGQLImporter = (content: string) =>
|
|||||||
* @returns the collection if it is valid, else a translated version of the collection
|
* @returns the collection if it is valid, else a translated version of the collection
|
||||||
*/
|
*/
|
||||||
export const validateGQLCollection = (collection: unknown) => {
|
export const validateGQLCollection = (collection: unknown) => {
|
||||||
const result = z.array(entityReference(HoppCollection)).safeParse(collection)
|
if (isValidCollection(collection)) {
|
||||||
|
return O.some(collection)
|
||||||
if (result.success) return O.some(result.data)
|
}
|
||||||
|
|
||||||
return O.some(translateToNewGQLCollection(collection))
|
return O.some(translateToNewGQLCollection(collection))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
import { NonSecretEnvironment } from "@hoppscotch/data"
|
import { NonSecretEnvironment } from "@hoppscotch/data"
|
||||||
import { safeParseJSONOrYAML } from "~/helpers/functional/yaml"
|
import { safeParseJSONOrYAML } from "~/helpers/functional/yaml"
|
||||||
import { uniqueID } from "~/helpers/utils/uniqueID"
|
import { uniqueId } from "lodash-es"
|
||||||
|
|
||||||
const insomniaResourcesSchema = z.object({
|
const insomniaResourcesSchema = z.object({
|
||||||
resources: z.array(
|
resources: z.array(
|
||||||
@@ -67,7 +67,7 @@ export const insomniaEnvImporter = (contents: string[]) => {
|
|||||||
|
|
||||||
if (parsedInsomniaEnv.success) {
|
if (parsedInsomniaEnv.success) {
|
||||||
const environment: NonSecretEnvironment = {
|
const environment: NonSecretEnvironment = {
|
||||||
id: uniqueID(),
|
id: uniqueId(),
|
||||||
v: 1,
|
v: 1,
|
||||||
name: parsedInsomniaEnv.data.name,
|
name: parsedInsomniaEnv.data.name,
|
||||||
variables: Object.entries(parsedInsomniaEnv.data.data).map(
|
variables: Object.entries(parsedInsomniaEnv.data.data).map(
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import {
|
|||||||
HoppCollection,
|
HoppCollection,
|
||||||
makeCollection,
|
makeCollection,
|
||||||
HoppRESTRequestVariable,
|
HoppRESTRequestVariable,
|
||||||
HoppRESTRequest,
|
|
||||||
} from "@hoppscotch/data"
|
} from "@hoppscotch/data"
|
||||||
import { pipe, flow } from "fp-ts/function"
|
import { pipe, flow } from "fp-ts/function"
|
||||||
import * as A from "fp-ts/Array"
|
import * as A from "fp-ts/Array"
|
||||||
@@ -26,7 +25,6 @@ import * as O from "fp-ts/Option"
|
|||||||
import * as TE from "fp-ts/TaskEither"
|
import * as TE from "fp-ts/TaskEither"
|
||||||
import * as RA from "fp-ts/ReadonlyArray"
|
import * as RA from "fp-ts/ReadonlyArray"
|
||||||
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||||
import { cloneDeep } from "lodash-es"
|
|
||||||
|
|
||||||
export const OPENAPI_DEREF_ERROR = "openapi/deref_error" as const
|
export const OPENAPI_DEREF_ERROR = "openapi/deref_error" as const
|
||||||
|
|
||||||
@@ -582,42 +580,30 @@ const convertPathToHoppReqs = (
|
|||||||
? openAPIUrl + openAPIPath.slice(1)
|
? openAPIUrl + openAPIPath.slice(1)
|
||||||
: openAPIUrl + openAPIPath
|
: openAPIUrl + openAPIPath
|
||||||
|
|
||||||
const res: {
|
return makeRESTRequest({
|
||||||
request: HoppRESTRequest
|
name: info.operationId ?? info.summary ?? "Untitled Request",
|
||||||
metadata: {
|
method: method.toUpperCase(),
|
||||||
tags: string[]
|
endpoint,
|
||||||
}
|
|
||||||
} = {
|
|
||||||
request: makeRESTRequest({
|
|
||||||
name: info.operationId ?? info.summary ?? "Untitled Request",
|
|
||||||
method: method.toUpperCase(),
|
|
||||||
endpoint,
|
|
||||||
|
|
||||||
// We don't need to worry about reference types as the Dereferencing pass should remove them
|
// We don't need to worry about reference types as the Dereferencing pass should remove them
|
||||||
params: parseOpenAPIParams(
|
params: parseOpenAPIParams(
|
||||||
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
||||||
),
|
),
|
||||||
headers: parseOpenAPIHeaders(
|
headers: parseOpenAPIHeaders(
|
||||||
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
||||||
),
|
),
|
||||||
|
|
||||||
auth: parseOpenAPIAuth(doc, info),
|
auth: parseOpenAPIAuth(doc, info),
|
||||||
|
|
||||||
body: parseOpenAPIBody(doc, info),
|
body: parseOpenAPIBody(doc, info),
|
||||||
|
|
||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
|
|
||||||
requestVariables: parseOpenAPIVariables(
|
requestVariables: parseOpenAPIVariables(
|
||||||
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
(info.parameters as OpenAPIParamsType[] | undefined) ?? []
|
||||||
),
|
),
|
||||||
}),
|
})
|
||||||
metadata: {
|
|
||||||
tags: info.tags ?? [],
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
return res
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Disable Readonly
|
// Disable Readonly
|
||||||
@@ -636,38 +622,10 @@ const convertOpenApiDocsToHopp = (
|
|||||||
)
|
)
|
||||||
.flat()
|
.flat()
|
||||||
|
|
||||||
const requestsByTags: Record<string, Array<HoppRESTRequest>> = {}
|
|
||||||
const requestsWithoutTags: Array<HoppRESTRequest> = []
|
|
||||||
|
|
||||||
paths.forEach(({ metadata, request }) => {
|
|
||||||
const tags = metadata.tags
|
|
||||||
|
|
||||||
if (tags.length === 0) {
|
|
||||||
requestsWithoutTags.push(request)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const tag of tags) {
|
|
||||||
if (!requestsByTags[tag]) {
|
|
||||||
requestsByTags[tag] = []
|
|
||||||
}
|
|
||||||
|
|
||||||
requestsByTags[tag].push(cloneDeep(request))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
return makeCollection({
|
return makeCollection({
|
||||||
name,
|
name,
|
||||||
folders: Object.entries(requestsByTags).map(([name, paths]) =>
|
folders: [],
|
||||||
makeCollection({
|
requests: paths,
|
||||||
name,
|
|
||||||
requests: paths,
|
|
||||||
folders: [],
|
|
||||||
auth: { authType: "inherit", authActive: true },
|
|
||||||
headers: [],
|
|
||||||
})
|
|
||||||
),
|
|
||||||
requests: requestsWithoutTags,
|
|
||||||
auth: { authType: "inherit", authActive: true },
|
auth: { authType: "inherit", authActive: true },
|
||||||
headers: [],
|
headers: [],
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import { Environment } from "@hoppscotch/data"
|
import { Environment } from "@hoppscotch/data"
|
||||||
import * as O from "fp-ts/Option"
|
import * as O from "fp-ts/Option"
|
||||||
import * as TE from "fp-ts/TaskEither"
|
import * as TE from "fp-ts/TaskEither"
|
||||||
|
import { uniqueId } from "lodash-es"
|
||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import { safeParseJSON } from "~/helpers/functional/json"
|
import { safeParseJSON } from "~/helpers/functional/json"
|
||||||
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
import { IMPORTER_INVALID_FILE_FORMAT } from "."
|
||||||
import { uniqueID } from "~/helpers/utils/uniqueID"
|
|
||||||
|
|
||||||
const postmanEnvSchema = z.object({
|
const postmanEnvSchema = z.object({
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
@@ -49,7 +49,7 @@ export const postmanEnvImporter = (contents: string[]) => {
|
|||||||
// Convert `values` to `variables` to match the format expected by the system
|
// Convert `values` to `variables` to match the format expected by the system
|
||||||
const environments: Environment[] = validationResult.data.map(
|
const environments: Environment[] = validationResult.data.map(
|
||||||
({ name, values }) => ({
|
({ name, values }) => ({
|
||||||
id: uniqueID(),
|
id: uniqueId(),
|
||||||
v: 1,
|
v: 1,
|
||||||
name,
|
name,
|
||||||
variables: values.map((entires) => ({ ...entires, secret: false })),
|
variables: values.map((entires) => ({ ...entires, secret: false })),
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
export const uniqueID = (length = 16) => {
|
|
||||||
return Math.random().toString(36).substring(2, length)
|
|
||||||
}
|
|
||||||
@@ -34,7 +34,7 @@ export type HoppModule = {
|
|||||||
to: RouteLocationNormalized,
|
to: RouteLocationNormalized,
|
||||||
from: RouteLocationNormalized,
|
from: RouteLocationNormalized,
|
||||||
router: Router
|
router: Router
|
||||||
) => void | Promise<void>
|
) => void
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the router to tell all the modules that a route navigation has completed
|
* Called by the router to tell all the modules that a route navigation has completed
|
||||||
|
|||||||
@@ -47,21 +47,15 @@ export default <HoppModule>{
|
|||||||
routes,
|
routes,
|
||||||
})
|
})
|
||||||
|
|
||||||
router.beforeEach(async (to, from) => {
|
router.beforeEach((to, from) => {
|
||||||
_isLoadingInitialRoute.value = isInitialRoute(from)
|
_isLoadingInitialRoute.value = isInitialRoute(from)
|
||||||
|
|
||||||
const onBeforeRouteChangePromises: Promise<any>[] = []
|
|
||||||
|
|
||||||
HOPP_MODULES.forEach((mod) => {
|
HOPP_MODULES.forEach((mod) => {
|
||||||
const res = mod.onBeforeRouteChange?.(to, from, router)
|
mod.onBeforeRouteChange?.(to, from, router)
|
||||||
if (res) onBeforeRouteChangePromises.push(res)
|
|
||||||
})
|
})
|
||||||
platform.addedHoppModules?.forEach((mod) => {
|
platform.addedHoppModules?.forEach((mod) => {
|
||||||
const res = mod.onBeforeRouteChange?.(to, from, router)
|
mod.onBeforeRouteChange?.(to, from, router)
|
||||||
if (res) onBeforeRouteChangePromises.push(res)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
await Promise.all(onBeforeRouteChangePromises)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
// Instead of this a better architecture is for the router
|
// Instead of this a better architecture is for the router
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import { Environment } from "@hoppscotch/data"
|
import { Environment } from "@hoppscotch/data"
|
||||||
import { cloneDeep, isEqual } from "lodash-es"
|
import { cloneDeep, isEqual, uniqueId } from "lodash-es"
|
||||||
import { combineLatest, Observable } from "rxjs"
|
import { combineLatest, Observable } from "rxjs"
|
||||||
import { distinctUntilChanged, map, pluck } from "rxjs/operators"
|
import { distinctUntilChanged, map, pluck } from "rxjs/operators"
|
||||||
import { uniqueID } from "~/helpers/utils/uniqueID"
|
|
||||||
import { getService } from "~/modules/dioc"
|
import { getService } from "~/modules/dioc"
|
||||||
import DispatchingStore, {
|
import DispatchingStore, {
|
||||||
defineDispatchers,
|
defineDispatchers,
|
||||||
@@ -23,7 +22,7 @@ const defaultEnvironmentsState = {
|
|||||||
environments: [
|
environments: [
|
||||||
{
|
{
|
||||||
v: 1,
|
v: 1,
|
||||||
id: uniqueID(),
|
id: uniqueId(),
|
||||||
name: "My Environment Variables",
|
name: "My Environment Variables",
|
||||||
variables: [],
|
variables: [],
|
||||||
},
|
},
|
||||||
@@ -101,7 +100,7 @@ const dispatchers = defineDispatchers({
|
|||||||
}
|
}
|
||||||
: {
|
: {
|
||||||
v: 1,
|
v: 1,
|
||||||
id: uniqueID(),
|
id: "",
|
||||||
name,
|
name,
|
||||||
variables,
|
variables,
|
||||||
},
|
},
|
||||||
@@ -124,7 +123,7 @@ const dispatchers = defineDispatchers({
|
|||||||
...environments,
|
...environments,
|
||||||
{
|
{
|
||||||
...cloneDeep(newEnvironment),
|
...cloneDeep(newEnvironment),
|
||||||
id: uniqueID(),
|
id: uniqueId(),
|
||||||
name: `${newEnvironment.name} - Duplicate`,
|
name: `${newEnvironment.name} - Duplicate`,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -44,5 +44,4 @@ export default defineComponent({
|
|||||||
<route lang="yaml">
|
<route lang="yaml">
|
||||||
meta:
|
meta:
|
||||||
layout: empty
|
layout: empty
|
||||||
onlyGuest: true
|
|
||||||
</route>
|
</route>
|
||||||
|
|||||||
@@ -71,7 +71,7 @@
|
|||||||
<h1 class="heading">
|
<h1 class="heading">
|
||||||
{{
|
{{
|
||||||
t("team.join_team", {
|
t("team.join_team", {
|
||||||
workspace: inviteDetails.data.right.teamInvitation.team.name,
|
team: inviteDetails.data.right.teamInvitation.team.name,
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
</h1>
|
</h1>
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
owner:
|
owner:
|
||||||
inviteDetails.data.right.teamInvitation.creator.displayName ??
|
inviteDetails.data.right.teamInvitation.creator.displayName ??
|
||||||
inviteDetails.data.right.teamInvitation.creator.email,
|
inviteDetails.data.right.teamInvitation.creator.email,
|
||||||
workspace: inviteDetails.data.right.teamInvitation.team.name,
|
team: inviteDetails.data.right.teamInvitation.team.name,
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
<HoppButtonPrimary
|
<HoppButtonPrimary
|
||||||
:label="
|
:label="
|
||||||
t('team.join_team', {
|
t('team.join_team', {
|
||||||
workspace: inviteDetails.data.right.teamInvitation.team.name,
|
team: inviteDetails.data.right.teamInvitation.team.name,
|
||||||
})
|
})
|
||||||
"
|
"
|
||||||
:loading="loading"
|
:loading="loading"
|
||||||
@@ -109,14 +109,14 @@
|
|||||||
<h1 class="heading">
|
<h1 class="heading">
|
||||||
{{
|
{{
|
||||||
t("team.joined_team", {
|
t("team.joined_team", {
|
||||||
workspace: inviteDetails.data.right.teamInvitation.team.name,
|
team: inviteDetails.data.right.teamInvitation.team.name,
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
</h1>
|
</h1>
|
||||||
<p class="mt-2 text-secondaryLight">
|
<p class="mt-2 text-secondaryLight">
|
||||||
{{
|
{{
|
||||||
t("team.joined_team_description", {
|
t("team.joined_team_description", {
|
||||||
workspace: inviteDetails.data.right.teamInvitation.team.name,
|
team: inviteDetails.data.right.teamInvitation.team.name,
|
||||||
})
|
})
|
||||||
}}
|
}}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -34,16 +34,16 @@
|
|||||||
},
|
},
|
||||||
"homepage": "https://github.com/hoppscotch/hoppscotch#readme",
|
"homepage": "https://github.com/hoppscotch/hoppscotch#readme",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/lodash": "4.14.200",
|
"@types/lodash": "^4.14.200",
|
||||||
"typescript": "5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"vite": "4.5.0"
|
"vite": "^4.5.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"fp-ts": "2.16.1",
|
"fp-ts": "^2.16.1",
|
||||||
"io-ts": "2.2.20",
|
"io-ts": "^2.2.20",
|
||||||
"lodash": "4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"parser-ts": "0.7.0",
|
"parser-ts": "^0.7.0",
|
||||||
"verzod": "0.2.2",
|
"verzod": "^0.2.2",
|
||||||
"zod": "3.22.4"
|
"zod": "^3.22.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,6 +52,8 @@ export function makeCollection(x: Omit<HoppCollection, "v">): HoppCollection {
|
|||||||
* @returns The proper new collection format
|
* @returns The proper new collection format
|
||||||
*/
|
*/
|
||||||
export function translateToNewRESTCollection(x: any): HoppCollection {
|
export function translateToNewRESTCollection(x: any): HoppCollection {
|
||||||
|
if (x.v && x.v === CollectionSchemaVersion) return x
|
||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
const name = x.name ?? "Untitled"
|
const name = x.name ?? "Untitled"
|
||||||
const folders = (x.folders ?? []).map(translateToNewRESTCollection)
|
const folders = (x.folders ?? []).map(translateToNewRESTCollection)
|
||||||
@@ -79,6 +81,8 @@ export function translateToNewRESTCollection(x: any): HoppCollection {
|
|||||||
* @returns The proper new collection format
|
* @returns The proper new collection format
|
||||||
*/
|
*/
|
||||||
export function translateToNewGQLCollection(x: any): HoppCollection {
|
export function translateToNewGQLCollection(x: any): HoppCollection {
|
||||||
|
if (x.v && x.v === CollectionSchemaVersion) return x
|
||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
const name = x.name ?? "Untitled"
|
const name = x.name ?? "Untitled"
|
||||||
const folders = (x.folders ?? []).map(translateToNewGQLCollection)
|
const folders = (x.folders ?? []).map(translateToNewGQLCollection)
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { InferredEntity, createVersionedEntity } from "verzod"
|
|||||||
import { z } from "zod"
|
import { z } from "zod"
|
||||||
|
|
||||||
import V0_VERSION from "./v/0"
|
import V0_VERSION from "./v/0"
|
||||||
import V1_VERSION, { uniqueID } from "./v/1"
|
import V1_VERSION from "./v/1"
|
||||||
|
|
||||||
const versionedObject = z.object({
|
const versionedObject = z.object({
|
||||||
v: z.number(),
|
v: z.number(),
|
||||||
@@ -165,7 +165,7 @@ export const translateToNewEnvironment = (x: any): Environment => {
|
|||||||
if (x.v && x.v === EnvironmentSchemaVersion) return x
|
if (x.v && x.v === EnvironmentSchemaVersion) return x
|
||||||
|
|
||||||
// Legacy
|
// Legacy
|
||||||
const id = x.id || uniqueID()
|
const id = x.id ?? ""
|
||||||
const name = x.name ?? "Untitled"
|
const name = x.name ?? "Untitled"
|
||||||
const variables = (x.variables ?? []).map(translateToNewEnvironmentVariables)
|
const variables = (x.variables ?? []).map(translateToNewEnvironmentVariables)
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,6 @@ import { z } from "zod"
|
|||||||
import { defineVersion } from "verzod"
|
import { defineVersion } from "verzod"
|
||||||
import { V0_SCHEMA } from "./0"
|
import { V0_SCHEMA } from "./0"
|
||||||
|
|
||||||
export const uniqueID = () => Math.random().toString(36).substring(2, 16)
|
|
||||||
|
|
||||||
export const V1_SCHEMA = z.object({
|
export const V1_SCHEMA = z.object({
|
||||||
v: z.literal(1),
|
v: z.literal(1),
|
||||||
id: z.string(),
|
id: z.string(),
|
||||||
@@ -30,7 +28,7 @@ export default defineVersion({
|
|||||||
const result: z.infer<typeof V1_SCHEMA> = {
|
const result: z.infer<typeof V1_SCHEMA> = {
|
||||||
...old,
|
...old,
|
||||||
v: 1,
|
v: 1,
|
||||||
id: old.id || uniqueID(),
|
id: old.id ?? "",
|
||||||
variables: old.variables.map((variable) => {
|
variables: old.variables.map((variable) => {
|
||||||
return {
|
return {
|
||||||
...variable,
|
...variable,
|
||||||
|
|||||||
@@ -18,8 +18,22 @@ export const HoppRESTRequestVariables = z.array(
|
|||||||
|
|
||||||
export type HoppRESTRequestVariables = z.infer<typeof HoppRESTRequestVariables>
|
export type HoppRESTRequestVariables = z.infer<typeof HoppRESTRequestVariables>
|
||||||
|
|
||||||
const V2_SCHEMA = V1_SCHEMA.extend({
|
const V2_SCHEMA = z.object({
|
||||||
v: z.literal("2"),
|
v: z.literal("2"),
|
||||||
|
id: z.optional(z.string()), // Firebase Firestore ID
|
||||||
|
|
||||||
|
name: z.string(),
|
||||||
|
method: z.string(),
|
||||||
|
endpoint: z.string(),
|
||||||
|
params: HoppRESTParams,
|
||||||
|
headers: HoppRESTHeaders,
|
||||||
|
preRequestScript: z.string().catch(""),
|
||||||
|
testScript: z.string().catch(""),
|
||||||
|
|
||||||
|
auth: HoppRESTAuth,
|
||||||
|
|
||||||
|
body: HoppRESTReqBody,
|
||||||
|
|
||||||
requestVariables: HoppRESTRequestVariables,
|
requestVariables: HoppRESTRequestVariables,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -52,27 +52,27 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hoppscotch/data": "workspace:^",
|
"@hoppscotch/data": "workspace:^",
|
||||||
"@types/lodash-es": "4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"fp-ts": "2.12.1",
|
"fp-ts": "^2.11.10",
|
||||||
"lodash": "4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"lodash-es": "4.17.21"
|
"lodash-es": "^4.17.21"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@digitak/esrun": "3.2.8",
|
"@digitak/esrun": "^3.1.2",
|
||||||
"@relmify/jest-fp-ts": "2.0.2",
|
"@relmify/jest-fp-ts": "^2.0.1",
|
||||||
"@types/jest": "27.5.2",
|
"@types/jest": "^27.4.1",
|
||||||
"@types/lodash": "4.14.182",
|
"@types/lodash": "^4.14.181",
|
||||||
"@types/node": "17.0.45",
|
"@types/node": "^17.0.24",
|
||||||
"@typescript-eslint/eslint-plugin": "5.30.6",
|
"@typescript-eslint/eslint-plugin": "^5.19.0",
|
||||||
"@typescript-eslint/parser": "5.30.6",
|
"@typescript-eslint/parser": "^5.19.0",
|
||||||
"eslint": "8.19.0",
|
"eslint": "^8.13.0",
|
||||||
"eslint-config-prettier": "8.6.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-prettier": "4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"io-ts": "2.2.16",
|
"io-ts": "^2.2.16",
|
||||||
"jest": "27.5.1",
|
"jest": "^27.5.1",
|
||||||
"prettier": "2.8.4",
|
"prettier": "^2.8.4",
|
||||||
"ts-jest": "27.1.5",
|
"ts-jest": "^27.1.4",
|
||||||
"typescript": "4.9.5",
|
"typescript": "^4.6.3",
|
||||||
"vite": "5.0.5"
|
"vite": "^5.0.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/selfhost-desktop",
|
"name": "@hoppscotch/selfhost-desktop",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2024.3.0",
|
"version": "2023.12.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:vite": "vite",
|
"dev:vite": "vite",
|
||||||
@@ -13,69 +13,69 @@
|
|||||||
"gql-codegen": "graphql-codegen --require dotenv/config --config gql-codegen.yml dotenv_config_path=\"../../.env\""
|
"gql-codegen": "graphql-codegen --require dotenv/config --config gql-codegen.yml dotenv_config_path=\"../../.env\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource-variable/inter": "5.0.15",
|
"@fontsource-variable/inter": "^5.0.5",
|
||||||
"@fontsource-variable/material-symbols-rounded": "5.0.16",
|
"@fontsource-variable/material-symbols-rounded": "^5.0.5",
|
||||||
"@fontsource-variable/roboto-mono": "5.0.16",
|
"@fontsource-variable/roboto-mono": "^5.0.6",
|
||||||
"@hoppscotch/common": "workspace:^",
|
"@hoppscotch/common": "workspace:^",
|
||||||
"@platform/auth": "0.1.106",
|
"@platform/auth": "^0.1.106",
|
||||||
"@tauri-apps/api": "1.5.1",
|
"@tauri-apps/api": "^1.3.0",
|
||||||
"@tauri-apps/cli": "1.5.6",
|
"@tauri-apps/cli": "^1.3.0",
|
||||||
"@vueuse/core": "10.5.0",
|
"@vueuse/core": "^10.4.1",
|
||||||
"axios": "0.21.4",
|
"axios": "^0.21.4",
|
||||||
"buffer": "6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"dioc": "1.0.1",
|
"dioc": "^1.0.1",
|
||||||
"environments.api": "link:@platform/environments/environments.api",
|
"environments.api": "link:@platform/environments/environments.api",
|
||||||
"event": "link:@tauri-apps/api/event",
|
"event": "link:@tauri-apps/api/event",
|
||||||
"fp-ts": "2.16.1",
|
"fp-ts": "^2.16.0",
|
||||||
"lodash-es": "4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"process": "0.11.10",
|
"process": "^0.11.10",
|
||||||
"rxjs": "7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"shell": "link:@tauri-apps/api/shell",
|
"shell": "link:@tauri-apps/api/shell",
|
||||||
"stream-browserify": "3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"tauri": "link:@tauri-apps/api/tauri",
|
"tauri": "link:@tauri-apps/api/tauri",
|
||||||
"tauri-plugin-store-api": "0.0.0",
|
"tauri-plugin-store-api": "github:tauri-apps/tauri-plugin-store#v1",
|
||||||
"util": "0.12.5",
|
"util": "^0.12.4",
|
||||||
"vue": "3.3.9",
|
"vue": "^3.2.45",
|
||||||
"workbox-window": "6.6.0"
|
"workbox-window": "^6.5.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@graphql-codegen/add": "5.0.0",
|
"@graphql-codegen/add": "^5.0.0",
|
||||||
"@graphql-codegen/cli": "5.0.0",
|
"@graphql-codegen/cli": "^5.0.0",
|
||||||
"@graphql-codegen/typed-document-node": "5.0.1",
|
"@graphql-codegen/typed-document-node": "^5.0.1",
|
||||||
"@graphql-codegen/typescript": "4.0.1",
|
"@graphql-codegen/typescript": "^4.0.1",
|
||||||
"@graphql-codegen/typescript-operations": "4.0.1",
|
"@graphql-codegen/typescript-operations": "^4.0.1",
|
||||||
"@graphql-codegen/typescript-urql-graphcache": "2.4.5",
|
"@graphql-codegen/typescript-urql-graphcache": "^2.4.5",
|
||||||
"@graphql-codegen/urql-introspection": "2.2.1",
|
"@graphql-codegen/urql-introspection": "^2.2.1",
|
||||||
"@graphql-typed-document-node/core": "3.2.0",
|
"@graphql-typed-document-node/core": "^3.2.0",
|
||||||
"@intlify/vite-plugin-vue-i18n": "6.0.1",
|
"@intlify/vite-plugin-vue-i18n": "^6.0.1",
|
||||||
"@rushstack/eslint-patch": "1.3.3",
|
"@rushstack/eslint-patch": "^1.1.4",
|
||||||
"@types/lodash-es": "4.17.10",
|
"@types/lodash-es": "^4.17.9",
|
||||||
"@types/node": "18.18.8",
|
"@types/node": "^18.7.10",
|
||||||
"@typescript-eslint/eslint-plugin": "5.62.0",
|
"@typescript-eslint/eslint-plugin": "^5.19.0",
|
||||||
"@typescript-eslint/parser": "5.62.0",
|
"@typescript-eslint/parser": "^5.19.0",
|
||||||
"@vitejs/plugin-legacy": "2.3.0",
|
"@vitejs/plugin-legacy": "^2.3.0",
|
||||||
"@vitejs/plugin-vue": "4.3.1",
|
"@vitejs/plugin-vue": "^4.0.0",
|
||||||
"@vue/eslint-config-typescript": "11.0.3",
|
"@vue/eslint-config-typescript": "^11.0.1",
|
||||||
"autoprefixer": "10.4.16",
|
"autoprefixer": "^10.4.14",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "8.47.0",
|
"eslint": "^8.28.0",
|
||||||
"eslint-plugin-prettier": "4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"eslint-plugin-vue": "9.17.0",
|
"eslint-plugin-vue": "^9.5.1",
|
||||||
"npm-run-all": "4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"postcss": "8.4.32",
|
"postcss": "^8.4.23",
|
||||||
"tailwindcss": "3.3.6",
|
"tailwindcss": "^3.3.6",
|
||||||
"typescript": "4.9.5",
|
"typescript": "^4.9.5",
|
||||||
"unplugin-fonts": "1.1.1",
|
"unplugin-fonts": "^1.1.1",
|
||||||
"unplugin-icons": "0.14.9",
|
"unplugin-icons": "^0.14.9",
|
||||||
"unplugin-vue-components": "0.21.0",
|
"unplugin-vue-components": "^0.21.0",
|
||||||
"vite": "4.5.0",
|
"vite": "^4.2.1",
|
||||||
"vite-plugin-html-config": "1.0.11",
|
"vite-plugin-html-config": "^1.0.10",
|
||||||
"vite-plugin-inspect": "0.7.38",
|
"vite-plugin-inspect": "^0.7.4",
|
||||||
"vite-plugin-pages": "0.26.0",
|
"vite-plugin-pages": "^0.26.0",
|
||||||
"vite-plugin-pages-sitemap": "1.6.1",
|
"vite-plugin-pages-sitemap": "^1.4.0",
|
||||||
"vite-plugin-pwa": "0.13.1",
|
"vite-plugin-pwa": "^0.13.1",
|
||||||
"vite-plugin-static-copy": "0.12.0",
|
"vite-plugin-static-copy": "^0.12.0",
|
||||||
"vite-plugin-vue-layouts": "0.7.0",
|
"vite-plugin-vue-layouts": "^0.7.0",
|
||||||
"vue-tsc": "1.8.8"
|
"vue-tsc": "^1.0.11"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1260,7 +1260,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hoppscotch-desktop"
|
name = "hoppscotch-desktop"
|
||||||
version = "24.3.0"
|
version = "23.12.6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cocoa 0.25.0",
|
"cocoa 0.25.0",
|
||||||
"hex_color",
|
"hex_color",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "hoppscotch-desktop"
|
name = "hoppscotch-desktop"
|
||||||
version = "24.3.0"
|
version = "23.12.6"
|
||||||
description = "A Tauri App"
|
description = "A Tauri App"
|
||||||
authors = ["you"]
|
authors = ["you"]
|
||||||
license = ""
|
license = ""
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
},
|
},
|
||||||
"package": {
|
"package": {
|
||||||
"productName": "Hoppscotch",
|
"productName": "Hoppscotch",
|
||||||
"version": "24.3.0"
|
"version": "23.12.6"
|
||||||
},
|
},
|
||||||
"tauri": {
|
"tauri": {
|
||||||
"allowlist": {
|
"allowlist": {
|
||||||
|
|||||||
@@ -112,15 +112,10 @@ function exportedCollectionToHoppCollection(
|
|||||||
folders: restCollection.folders.map((folder) =>
|
folders: restCollection.folders.map((folder) =>
|
||||||
exportedCollectionToHoppCollection(folder, collectionType)
|
exportedCollectionToHoppCollection(folder, collectionType)
|
||||||
),
|
),
|
||||||
requests: restCollection.requests.map((request) => {
|
requests: restCollection.requests.map(
|
||||||
const requestParsedResult = HoppRESTRequest.safeParse(request)
|
({
|
||||||
if (requestParsedResult.type === "ok") {
|
|
||||||
return requestParsedResult.value
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
v,
|
|
||||||
id,
|
id,
|
||||||
|
v,
|
||||||
auth,
|
auth,
|
||||||
body,
|
body,
|
||||||
endpoint,
|
endpoint,
|
||||||
@@ -130,23 +125,20 @@ function exportedCollectionToHoppCollection(
|
|||||||
params,
|
params,
|
||||||
preRequestScript,
|
preRequestScript,
|
||||||
testScript,
|
testScript,
|
||||||
requestVariables,
|
}) => ({
|
||||||
} = request
|
|
||||||
return {
|
|
||||||
v,
|
|
||||||
id,
|
id,
|
||||||
name,
|
v,
|
||||||
endpoint,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
requestVariables: requestVariables,
|
|
||||||
auth,
|
auth,
|
||||||
headers,
|
|
||||||
body,
|
body,
|
||||||
|
endpoint,
|
||||||
|
headers,
|
||||||
|
method,
|
||||||
|
name,
|
||||||
|
params,
|
||||||
preRequestScript,
|
preRequestScript,
|
||||||
testScript,
|
testScript,
|
||||||
}
|
})
|
||||||
}),
|
),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const gqlCollection = collection as ExportedUserCollectionGQL
|
const gqlCollection = collection as ExportedUserCollectionGQL
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@hoppscotch/selfhost-web",
|
"name": "@hoppscotch/selfhost-web",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2024.3.0",
|
"version": "2023.12.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:vite": "vite",
|
"dev:vite": "vite",
|
||||||
@@ -23,62 +23,62 @@
|
|||||||
"postinstall": "pnpm run gql-codegen"
|
"postinstall": "pnpm run gql-codegen"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource-variable/inter": "5.0.15",
|
"@fontsource-variable/inter": "^5.0.15",
|
||||||
"@fontsource-variable/material-symbols-rounded": "5.0.16",
|
"@fontsource-variable/material-symbols-rounded": "^5.0.16",
|
||||||
"@fontsource-variable/roboto-mono": "5.0.16",
|
"@fontsource-variable/roboto-mono": "^5.0.16",
|
||||||
"@hoppscotch/common": "workspace:^",
|
"@hoppscotch/common": "workspace:^",
|
||||||
"@hoppscotch/data": "workspace:^",
|
"@hoppscotch/data": "workspace:^",
|
||||||
"@hoppscotch/ui": "0.1.0",
|
"@hoppscotch/ui": "^0.1.0",
|
||||||
"@import-meta-env/unplugin": "0.4.10",
|
"@import-meta-env/unplugin": "^0.4.10",
|
||||||
"axios": "1.6.2",
|
"axios": "^1.6.2",
|
||||||
"buffer": "6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"fp-ts": "2.16.1",
|
"fp-ts": "^2.16.1",
|
||||||
"process": "0.11.10",
|
"process": "^0.11.10",
|
||||||
"rxjs": "7.8.1",
|
"rxjs": "^7.8.1",
|
||||||
"stream-browserify": "3.0.0",
|
"stream-browserify": "^3.0.0",
|
||||||
"util": "0.12.5",
|
"util": "^0.12.5",
|
||||||
"vue": "3.3.9",
|
"vue": "^3.3.8",
|
||||||
"workbox-window": "7.0.0",
|
"workbox-window": "^7.0.0",
|
||||||
"zod": "3.22.4"
|
"zod": "^3.22.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@graphql-codegen/add": "5.0.0",
|
"@graphql-codegen/add": "^5.0.0",
|
||||||
"@graphql-codegen/cli": "5.0.0",
|
"@graphql-codegen/cli": "^5.0.0",
|
||||||
"@graphql-codegen/typed-document-node": "5.0.1",
|
"@graphql-codegen/typed-document-node": "^5.0.1",
|
||||||
"@graphql-codegen/typescript": "4.0.1",
|
"@graphql-codegen/typescript": "^4.0.1",
|
||||||
"@graphql-codegen/typescript-operations": "4.0.1",
|
"@graphql-codegen/typescript-operations": "^4.0.1",
|
||||||
"@graphql-codegen/typescript-urql-graphcache": "3.0.0",
|
"@graphql-codegen/typescript-urql-graphcache": "^3.0.0",
|
||||||
"@graphql-codegen/urql-introspection": "3.0.0",
|
"@graphql-codegen/urql-introspection": "^3.0.0",
|
||||||
"@graphql-typed-document-node/core": "3.2.0",
|
"@graphql-typed-document-node/core": "^3.2.0",
|
||||||
"@intlify/vite-plugin-vue-i18n": "7.0.0",
|
"@intlify/vite-plugin-vue-i18n": "^7.0.0",
|
||||||
"@rushstack/eslint-patch": "1.6.0",
|
"@rushstack/eslint-patch": "^1.6.0",
|
||||||
"@typescript-eslint/eslint-plugin": "6.13.2",
|
"@typescript-eslint/eslint-plugin": "^6.12.0",
|
||||||
"@typescript-eslint/parser": "6.13.2",
|
"@typescript-eslint/parser": "^6.12.0",
|
||||||
"@vitejs/plugin-legacy": "4.1.1",
|
"@vitejs/plugin-legacy": "^4.1.1",
|
||||||
"@vitejs/plugin-vue": "4.5.1",
|
"@vitejs/plugin-vue": "^4.5.0",
|
||||||
"@vue/eslint-config-typescript": "12.0.0",
|
"@vue/eslint-config-typescript": "^12.0.0",
|
||||||
"autoprefixer": "10.4.16",
|
"autoprefixer": "^10.4.14",
|
||||||
"cross-env": "7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"eslint": "8.55.0",
|
"eslint": "^8.54.0",
|
||||||
"eslint-plugin-prettier": "5.0.1",
|
"eslint-plugin-prettier": "^5.0.1",
|
||||||
"eslint-plugin-vue": "9.19.2",
|
"eslint-plugin-vue": "^9.18.1",
|
||||||
"npm-run-all": "4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"postcss": "8.4.31",
|
"postcss": "^8.4.23",
|
||||||
"prettier-plugin-tailwindcss": "0.5.7",
|
"prettier-plugin-tailwindcss": "^0.5.7",
|
||||||
"tailwindcss": "3.3.5",
|
"tailwindcss": "^3.3.2",
|
||||||
"typescript": "5.3.2",
|
"typescript": "^5.3.2",
|
||||||
"unplugin-fonts": "1.1.1",
|
"unplugin-fonts": "^1.1.1",
|
||||||
"unplugin-icons": "0.17.4",
|
"unplugin-icons": "^0.17.4",
|
||||||
"unplugin-vue-components": "0.25.2",
|
"unplugin-vue-components": "^0.25.2",
|
||||||
"vite": "4.5.0",
|
"vite": "^4.5.0",
|
||||||
"vite-plugin-fonts": "0.7.0",
|
"vite-plugin-fonts": "^0.7.0",
|
||||||
"vite-plugin-html-config": "1.0.11",
|
"vite-plugin-html-config": "^1.0.11",
|
||||||
"vite-plugin-inspect": "0.7.42",
|
"vite-plugin-inspect": "^0.7.42",
|
||||||
"vite-plugin-pages": "0.31.0",
|
"vite-plugin-pages": "^0.31.0",
|
||||||
"vite-plugin-pages-sitemap": "1.6.1",
|
"vite-plugin-pages-sitemap": "^1.6.1",
|
||||||
"vite-plugin-pwa": "0.17.3",
|
"vite-plugin-pwa": "^0.17.0",
|
||||||
"vite-plugin-static-copy": "0.17.1",
|
"vite-plugin-static-copy": "^0.17.1",
|
||||||
"vite-plugin-vue-layouts": "0.8.0",
|
"vite-plugin-vue-layouts": "^0.8.0",
|
||||||
"vue-tsc": "1.8.24"
|
"vue-tsc": "^1.8.22"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -120,15 +120,10 @@ function exportedCollectionToHoppCollection(
|
|||||||
folders: restCollection.folders.map((folder) =>
|
folders: restCollection.folders.map((folder) =>
|
||||||
exportedCollectionToHoppCollection(folder, collectionType)
|
exportedCollectionToHoppCollection(folder, collectionType)
|
||||||
),
|
),
|
||||||
requests: restCollection.requests.map((request) => {
|
requests: restCollection.requests.map(
|
||||||
const requestParsedResult = HoppRESTRequest.safeParse(request)
|
({
|
||||||
if (requestParsedResult.type === "ok") {
|
|
||||||
return requestParsedResult.value
|
|
||||||
}
|
|
||||||
|
|
||||||
const {
|
|
||||||
v,
|
|
||||||
id,
|
id,
|
||||||
|
v,
|
||||||
auth,
|
auth,
|
||||||
body,
|
body,
|
||||||
endpoint,
|
endpoint,
|
||||||
@@ -139,22 +134,21 @@ function exportedCollectionToHoppCollection(
|
|||||||
preRequestScript,
|
preRequestScript,
|
||||||
testScript,
|
testScript,
|
||||||
requestVariables,
|
requestVariables,
|
||||||
} = request
|
}) => ({
|
||||||
return {
|
|
||||||
v,
|
|
||||||
id,
|
id,
|
||||||
name,
|
v,
|
||||||
endpoint,
|
|
||||||
method,
|
|
||||||
params,
|
|
||||||
requestVariables: requestVariables,
|
|
||||||
auth,
|
auth,
|
||||||
headers,
|
|
||||||
body,
|
body,
|
||||||
|
endpoint,
|
||||||
|
headers,
|
||||||
|
method,
|
||||||
|
name,
|
||||||
|
params,
|
||||||
preRequestScript,
|
preRequestScript,
|
||||||
testScript,
|
testScript,
|
||||||
}
|
requestVariables,
|
||||||
}),
|
})
|
||||||
|
),
|
||||||
auth: data.auth,
|
auth: data.auth,
|
||||||
headers: data.headers,
|
headers: data.headers,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,12 +10,9 @@
|
|||||||
},
|
},
|
||||||
"configs": {
|
"configs": {
|
||||||
"auth_providers": {
|
"auth_providers": {
|
||||||
"callback_url": "CALLBACK URL",
|
|
||||||
"client_id": "CLIENT ID",
|
"client_id": "CLIENT ID",
|
||||||
"client_secret": "CLIENT SECRET",
|
"client_secret": "CLIENT SECRET",
|
||||||
"description": "Configure authentication providers for your server",
|
"description": "Configure authentication providers for your server",
|
||||||
"scope": "SCOPE",
|
|
||||||
"tenant": "TENANT",
|
|
||||||
"title": "Authentication Providers",
|
"title": "Authentication Providers",
|
||||||
"update_failure": "Failed to update authentication provider configurations!!"
|
"update_failure": "Failed to update authentication provider configurations!!"
|
||||||
},
|
},
|
||||||
@@ -106,18 +103,8 @@
|
|||||||
"admin_failure": "Failed to make user an admin!!",
|
"admin_failure": "Failed to make user an admin!!",
|
||||||
"admin_success": "User is now an admin!!",
|
"admin_success": "User is now an admin!!",
|
||||||
"and": "and",
|
"and": "and",
|
||||||
"clear_selection": "Clear Selection",
|
|
||||||
"configure_auth": "Check out the documentation to configure auth providers.",
|
"configure_auth": "Check out the documentation to configure auth providers.",
|
||||||
"confirm_admin_to_user": "Do you want to remove admin status from this user?",
|
|
||||||
"confirm_admins_to_users": "Do you want to remove admin status from selected users?",
|
|
||||||
"confirm_delete_invite": "Do you want to revoke the selected invite?",
|
|
||||||
"confirm_delete_invites": "Do you want to revoke selected invites?",
|
|
||||||
"confirm_user_deletion": "Confirm user deletion?",
|
|
||||||
"confirm_users_deletion": "Do you want to delete selected users?",
|
|
||||||
"confirm_user_to_admin": "Do you want to make this user into an admin?",
|
|
||||||
"confirm_users_to_admin": "Do you want to make selected users into admins?",
|
|
||||||
"confirm_logout": "Confirm Logout",
|
"confirm_logout": "Confirm Logout",
|
||||||
"created_on": "Created On",
|
|
||||||
"continue_email": "Continue with Email",
|
"continue_email": "Continue with Email",
|
||||||
"continue_github": "Continue with Github",
|
"continue_github": "Continue with Github",
|
||||||
"continue_google": "Continue with Google",
|
"continue_google": "Continue with Google",
|
||||||
@@ -126,21 +113,12 @@
|
|||||||
"create_team_failure": "Failed to create workspace!!",
|
"create_team_failure": "Failed to create workspace!!",
|
||||||
"create_team_success": "Workspace created successfully!!",
|
"create_team_success": "Workspace created successfully!!",
|
||||||
"data_sharing_failure": "Failed to update data sharing settings",
|
"data_sharing_failure": "Failed to update data sharing settings",
|
||||||
"delete_invite_failure": "Failed to delete invite!!",
|
|
||||||
"delete_invites_failure": "Failed to delete selected invites!!",
|
|
||||||
"delete_invite_success": "Invite deleted successfully!!",
|
|
||||||
"delete_invites_success": "Selected invites deleted successfully!!",
|
|
||||||
"delete_request_failure": "Shared Request deletion failed!!",
|
"delete_request_failure": "Shared Request deletion failed!!",
|
||||||
"delete_request_success": "Shared Request deleted successfully!!",
|
"delete_request_success": "Shared Request deleted successfully!!",
|
||||||
"delete_team_failure": "Workspace deletion failed!!",
|
"delete_team_failure": "Workspace deletion failed!!",
|
||||||
"delete_team_success": "Workspace deleted successfully!!",
|
"delete_team_success": "Workspace deleted successfully!!",
|
||||||
"delete_some_users_failure": "Number of Users Not Deleted: {count}",
|
|
||||||
"delete_some_users_success": "Number of Users Deleted: {count}",
|
|
||||||
"delete_user_failed_only_one_admin": "Failed to delete user. There should be atleast one admin!!",
|
|
||||||
"delete_user_failure": "User deletion failed!!",
|
"delete_user_failure": "User deletion failed!!",
|
||||||
"delete_users_failure": "Failed to delete selected users!!",
|
|
||||||
"delete_user_success": "User deleted successfully!!",
|
"delete_user_success": "User deleted successfully!!",
|
||||||
"delete_users_success": "Selected users deleted successfully!!",
|
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"email_failure": "Failed to send invitation",
|
"email_failure": "Failed to send invitation",
|
||||||
"email_signin_failure": "Failed to login with Email",
|
"email_signin_failure": "Failed to login with Email",
|
||||||
@@ -165,22 +143,16 @@
|
|||||||
"reenter_email": "Re-enter email",
|
"reenter_email": "Re-enter email",
|
||||||
"remove_admin_failure": "Failed to remove admin status!!",
|
"remove_admin_failure": "Failed to remove admin status!!",
|
||||||
"remove_admin_success": "Admin status removed!!",
|
"remove_admin_success": "Admin status removed!!",
|
||||||
"remove_admin_from_users_failure": "Failed to remove admin status from selected users!!",
|
|
||||||
"remove_admin_from_users_success": "Admin status removed from selected users!!",
|
|
||||||
"remove_admin_to_delete_user": "Remove admin privilege to delete the user!!",
|
"remove_admin_to_delete_user": "Remove admin privilege to delete the user!!",
|
||||||
"remove_admin_for_deletion": "Remove admin status before attempting deletion!!",
|
|
||||||
"remove_invitee_failure": "Removal of invitee failed!!",
|
"remove_invitee_failure": "Removal of invitee failed!!",
|
||||||
"remove_invitee_success": "Removal of invitee is successfull!!",
|
"remove_invitee_success": "Removal of invitee is successfull!!",
|
||||||
"remove_member_failure": "Member couldn't be removed!!",
|
"remove_member_failure": "Member couldn't be removed!!",
|
||||||
"remove_member_success": "Member removed successfully!!",
|
"remove_member_success": "Member removed successfully!!",
|
||||||
"rename_team_failure": "Failed to rename workspace!!",
|
"rename_team_failure": "Failed to rename workspace!!",
|
||||||
"rename_team_success": "Workspace renamed successfully!",
|
"rename_team_success": "Workspace renamed successfully!",
|
||||||
"rename_user_failure": "Failed to rename user!!",
|
|
||||||
"rename_user_success": "User renamed successfully!!",
|
|
||||||
"require_auth_provider": "You need to set atleast one authentication provider to log in.",
|
"require_auth_provider": "You need to set atleast one authentication provider to log in.",
|
||||||
"role_update_failed": "Roles updation has failed!!",
|
"role_update_failed": "Roles updation has failed!!",
|
||||||
"role_update_success": "Roles updated successfully!!",
|
"role_update_success": "Roles updated successfully!!",
|
||||||
"selected": "{count} selected",
|
|
||||||
"self_host_docs": "Self Host Documentation",
|
"self_host_docs": "Self Host Documentation",
|
||||||
"send_magic_link": "Send magic link",
|
"send_magic_link": "Send magic link",
|
||||||
"setup_failure": "Setup has failed!!",
|
"setup_failure": "Setup has failed!!",
|
||||||
@@ -189,11 +161,7 @@
|
|||||||
"sign_in_options": "All sign in option",
|
"sign_in_options": "All sign in option",
|
||||||
"sign_out": "Sign out",
|
"sign_out": "Sign out",
|
||||||
"team_name_too_short": "Workspace name should be atleast 6 characters long!!",
|
"team_name_too_short": "Workspace name should be atleast 6 characters long!!",
|
||||||
"team_name_long": "Workspace name should be atleast 6 characters long!!",
|
"user_not_found": "User not found in the infra!!"
|
||||||
"user_already_invited": "Failed to send invite. User is already invited!!",
|
|
||||||
"user_not_found": "User not found in the infra!!",
|
|
||||||
"users_to_admin_success": "Selected users are elevated to admin status!!",
|
|
||||||
"users_to_admin_failure": "Failed to elevate selected users to admin status!!"
|
|
||||||
},
|
},
|
||||||
"teams": {
|
"teams": {
|
||||||
"add_member": "Add Member",
|
"add_member": "Add Member",
|
||||||
@@ -230,7 +198,7 @@
|
|||||||
"name": "Workspace Name",
|
"name": "Workspace Name",
|
||||||
"no_members": "No members in this workspace. Add members to this workspace to collaborate",
|
"no_members": "No members in this workspace. Add members to this workspace to collaborate",
|
||||||
"no_pending_invites": "No pending invites",
|
"no_pending_invites": "No pending invites",
|
||||||
"no_teams": "No workspaces found..",
|
"no_teams": "No workspaces found",
|
||||||
"pending_invites": "Pending invites",
|
"pending_invites": "Pending invites",
|
||||||
"roles": "Roles",
|
"roles": "Roles",
|
||||||
"roles_description": "Roles are used to control access to the shared collections.",
|
"roles_description": "Roles are used to control access to the shared collections.",
|
||||||
@@ -255,17 +223,16 @@
|
|||||||
"admin": "Admin",
|
"admin": "Admin",
|
||||||
"admin_email": "Admin Email",
|
"admin_email": "Admin Email",
|
||||||
"admin_id": "Admin ID",
|
"admin_id": "Admin ID",
|
||||||
"cancel": "Cancel",
|
"confirm_admin_to_user": "Do you want to remove admin status from this user?",
|
||||||
|
"confirm_user_deletion": "Confirm user deletion?",
|
||||||
|
"confirm_user_to_admin": "Do you want to make this user into an admin?",
|
||||||
"created_on": "Created On",
|
"created_on": "Created On",
|
||||||
"date": "Date",
|
"date": "Date",
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"delete_user": "Delete User",
|
"delete_user": "Delete User",
|
||||||
"delete_users": "Delete Users",
|
|
||||||
"details": "Details",
|
"details": "Details",
|
||||||
"edit": "Edit",
|
|
||||||
"email": "Email",
|
"email": "Email",
|
||||||
"email_address": "Email Address",
|
"email_address": "Email Address",
|
||||||
"empty_name": "Name cannot be empty!!",
|
|
||||||
"id": "User ID",
|
"id": "User ID",
|
||||||
"invalid_user": "Invalid User",
|
"invalid_user": "Invalid User",
|
||||||
"invite_load_list_error": "Unable to Load Invited Users List",
|
"invite_load_list_error": "Unable to Load Invited Users List",
|
||||||
@@ -275,18 +242,14 @@
|
|||||||
"invitee_email": "Invitee Email",
|
"invitee_email": "Invitee Email",
|
||||||
"load_info_error": "Unable to load user info",
|
"load_info_error": "Unable to load user info",
|
||||||
"load_list_error": "Unable to Load Users List",
|
"load_list_error": "Unable to Load Users List",
|
||||||
"make_admin": "Make Admin",
|
"make_admin": "Make admin",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"no_invite": "No pending invites found",
|
"no_invite": "No invited users found",
|
||||||
"no_shared_requests": "No shared requests created by the user",
|
"no_shared_requests": "No shared requests created by the user",
|
||||||
"no_users": "No users found",
|
"no_users": "No users found",
|
||||||
"not_found": "User not found",
|
"not_found": "User not found",
|
||||||
"pending_invites": "Pending Invites",
|
|
||||||
"remove_admin_privilege": "Remove Admin Privilege",
|
"remove_admin_privilege": "Remove Admin Privilege",
|
||||||
"remove_admin_status": "Remove Admin Status",
|
"remove_admin_status": "Remove Admin Status",
|
||||||
"rename": "Rename",
|
|
||||||
"revoke_invitation": "Revoke Invitation",
|
|
||||||
"searchbar_placeholder": "Search by name or email..",
|
|
||||||
"send_invite": "Send Invite",
|
"send_invite": "Send Invite",
|
||||||
"show_more": "Show more",
|
"show_more": "Show more",
|
||||||
"uid": "UID",
|
"uid": "UID",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "hoppscotch-sh-admin",
|
"name": "hoppscotch-sh-admin",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "2024.3.0",
|
"version": "2023.12.6",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
"dev": "pnpm exec npm-run-all -p -l dev:*",
|
||||||
@@ -13,66 +13,66 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource-variable/inter": "5.0.5",
|
"@fontsource-variable/inter": "^5.0.5",
|
||||||
"@fontsource-variable/material-symbols-rounded": "5.0.5",
|
"@fontsource-variable/material-symbols-rounded": "^5.0.5",
|
||||||
"@fontsource-variable/roboto-mono": "5.0.6",
|
"@fontsource-variable/roboto-mono": "^5.0.6",
|
||||||
"@graphql-typed-document-node/core": "3.1.1",
|
"@graphql-typed-document-node/core": "^3.1.1",
|
||||||
"@hoppscotch/ui": "0.1.2",
|
"@hoppscotch/ui": "^0.1.0",
|
||||||
"@hoppscotch/vue-toasted": "0.1.0",
|
"@hoppscotch/vue-toasted": "^0.1.0",
|
||||||
"@intlify/unplugin-vue-i18n": "1.2.0",
|
"@intlify/unplugin-vue-i18n": "^1.2.0",
|
||||||
"@types/cors": "2.8.13",
|
"@types/cors": "^2.8.13",
|
||||||
"@types/express": "4.17.16",
|
"@types/express": "^4.17.15",
|
||||||
"@urql/exchange-auth": "2.1.6",
|
"@urql/exchange-auth": "^2.1.6",
|
||||||
"@urql/vue": "1.1.2",
|
"@urql/vue": "^1.1.2",
|
||||||
"@vueuse/core": "9.12.0",
|
"@vueuse/core": "^9.10.0",
|
||||||
"axios": "0.21.4",
|
"axios": "^0.21.4",
|
||||||
"cors": "2.8.5",
|
"cors": "^2.8.5",
|
||||||
"date-fns": "2.29.3",
|
"date-fns": "^2.29.3",
|
||||||
"express": "4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-graphql": "0.12.0",
|
"express-graphql": "^0.12.0",
|
||||||
"fp-ts": "2.13.1",
|
"fp-ts": "^2.13.1",
|
||||||
"graphql": "16.6.0",
|
"graphql": "^16.6.0",
|
||||||
"io-ts": "2.2.16",
|
"io-ts": "^2.2.16",
|
||||||
"lodash-es": "4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"postcss": "8.4.31",
|
"postcss": "^8.4.23",
|
||||||
"prettier-plugin-tailwindcss": "0.5.7",
|
"prettier-plugin-tailwindcss": "^0.5.6",
|
||||||
"rxjs": "7.8.0",
|
"rxjs": "^7.8.0",
|
||||||
"tailwindcss": "3.3.5",
|
"tailwindcss": "^3.3.5",
|
||||||
"tippy.js": "6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
"ts-node-dev": "2.0.0",
|
"ts-node-dev": "^2.0.0",
|
||||||
"unplugin-icons": "0.14.9",
|
"unplugin-icons": "^0.14.9",
|
||||||
"unplugin-vue-components": "0.21.0",
|
"unplugin-vue-components": "^0.21.0",
|
||||||
"vue": "3.3.9",
|
"vue": "^3.2.6",
|
||||||
"vue-i18n": "9.2.2",
|
"vue-i18n": "^9.2.2",
|
||||||
"vue-router": "4.1.0",
|
"vue-router": "4",
|
||||||
"vue-tippy": "6.0.0-alpha.58"
|
"vue-tippy": "6.0.0-alpha.58"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"hoppscotch-backend": "workspace:^",
|
"hoppscotch-backend": "workspace:^",
|
||||||
"@graphql-codegen/cli": "3.0.0",
|
"@graphql-codegen/cli": "3.0.0",
|
||||||
"@graphql-codegen/client-preset": "2.1.0",
|
"@graphql-codegen/client-preset": "^2.0.0",
|
||||||
"@graphql-codegen/introspection": "3.0.0",
|
"@graphql-codegen/introspection": "3.0.0",
|
||||||
"@graphql-codegen/typed-document-node": "2.3.1",
|
"@graphql-codegen/typed-document-node": "^2.3.1",
|
||||||
"@graphql-codegen/typescript": "3.0.0",
|
"@graphql-codegen/typescript": "3.0.0",
|
||||||
"@graphql-codegen/typescript-document-nodes": "3.0.0",
|
"@graphql-codegen/typescript-document-nodes": "3.0.0",
|
||||||
"@graphql-codegen/typescript-operations": "3.0.0",
|
"@graphql-codegen/typescript-operations": "3.0.0",
|
||||||
"@graphql-codegen/urql-introspection": "2.2.1",
|
"@graphql-codegen/urql-introspection": "2.2.1",
|
||||||
"@import-meta-env/cli": "0.6.3",
|
"@import-meta-env/cli": "^0.6.3",
|
||||||
"@import-meta-env/unplugin": "0.4.8",
|
"@import-meta-env/unplugin": "^0.4.8",
|
||||||
"@types/lodash-es": "4.17.12",
|
"@types/lodash-es": "^4.17.12",
|
||||||
"@vitejs/plugin-vue": "3.2.0",
|
"@vitejs/plugin-vue": "^3.1.0",
|
||||||
"@vue/compiler-sfc": "3.2.45",
|
"@vue/compiler-sfc": "^3.2.6",
|
||||||
"dotenv": "16.3.1",
|
"dotenv": "^16.0.3",
|
||||||
"graphql-tag": "2.12.6",
|
"graphql-tag": "^2.12.6",
|
||||||
"npm-run-all": "4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"sass": "1.58.0",
|
"sass": "^1.57.1",
|
||||||
"ts-node": "10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"typescript": "4.9.3",
|
"typescript": "^4.9.3",
|
||||||
"unplugin-fonts": "1.0.3",
|
"unplugin-fonts": "^1.0.3",
|
||||||
"vite": "3.2.4",
|
"vite": "^3.1.4",
|
||||||
"vite-plugin-pages": "0.26.0",
|
"vite-plugin-pages": "^0.26.0",
|
||||||
"vite-plugin-vue-layouts": "0.7.0",
|
"vite-plugin-vue-layouts": "^0.7.0",
|
||||||
"vue-tsc": "0.3.0"
|
"vue-tsc": "^0.3.0"
|
||||||
},
|
},
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"singleQuote": true,
|
"singleQuote": true,
|
||||||
|
|||||||
10
packages/hoppscotch-sh-admin/src/components.d.ts
vendored
10
packages/hoppscotch-sh-admin/src/components.d.ts
vendored
@@ -17,23 +17,14 @@ declare module '@vue/runtime-core' {
|
|||||||
HoppButtonPrimary: typeof import('@hoppscotch/ui')['HoppButtonPrimary']
|
HoppButtonPrimary: typeof import('@hoppscotch/ui')['HoppButtonPrimary']
|
||||||
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary']
|
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary']
|
||||||
HoppSmartAnchor: typeof import('@hoppscotch/ui')['HoppSmartAnchor']
|
HoppSmartAnchor: typeof import('@hoppscotch/ui')['HoppSmartAnchor']
|
||||||
HoppSmartAutoComplete: typeof import('@hoppscotch/ui')['HoppSmartAutoComplete']
|
|
||||||
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal']
|
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal']
|
||||||
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput']
|
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput']
|
||||||
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
|
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
|
||||||
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink']
|
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink']
|
||||||
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
|
|
||||||
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture']
|
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture']
|
||||||
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
|
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner']
|
||||||
HoppSmartTab: typeof import('@hoppscotch/ui')['HoppSmartTab']
|
|
||||||
HoppSmartTable: typeof import('@hoppscotch/ui')['HoppSmartTable']
|
|
||||||
HoppSmartTabs: typeof import('@hoppscotch/ui')['HoppSmartTabs']
|
|
||||||
HoppSmartToggle: typeof import('@hoppscotch/ui')['HoppSmartToggle']
|
HoppSmartToggle: typeof import('@hoppscotch/ui')['HoppSmartToggle']
|
||||||
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
|
||||||
IconLucideChevronDown: typeof import('~icons/lucide/chevron-down')['default']
|
|
||||||
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
||||||
IconLucideSearch: typeof import('~icons/lucide/search')['default']
|
|
||||||
IconLucideUser: typeof import('~icons/lucide/user')['default']
|
|
||||||
SettingsAuthProvider: typeof import('./components/settings/AuthProvider.vue')['default']
|
SettingsAuthProvider: typeof import('./components/settings/AuthProvider.vue')['default']
|
||||||
SettingsConfigurations: typeof import('./components/settings/Configurations.vue')['default']
|
SettingsConfigurations: typeof import('./components/settings/Configurations.vue')['default']
|
||||||
SettingsDataSharing: typeof import('./components/settings/DataSharing.vue')['default']
|
SettingsDataSharing: typeof import('./components/settings/DataSharing.vue')['default']
|
||||||
@@ -51,7 +42,6 @@ declare module '@vue/runtime-core' {
|
|||||||
UsersDetails: typeof import('./components/users/Details.vue')['default']
|
UsersDetails: typeof import('./components/users/Details.vue')['default']
|
||||||
UsersInviteModal: typeof import('./components/users/InviteModal.vue')['default']
|
UsersInviteModal: typeof import('./components/users/InviteModal.vue')['default']
|
||||||
UsersSharedRequests: typeof import('./components/users/SharedRequests.vue')['default']
|
UsersSharedRequests: typeof import('./components/users/SharedRequests.vue')['default']
|
||||||
UsersTable: typeof import('./components/users/Table.vue')['default']
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,28 +35,25 @@
|
|||||||
:key="field.key"
|
:key="field.key"
|
||||||
class="mt-5"
|
class="mt-5"
|
||||||
>
|
>
|
||||||
<template
|
<label>{{ field.name }}</label>
|
||||||
v-if="field.applicableProviders.includes(provider.name)"
|
<span class="flex">
|
||||||
>
|
<HoppSmartInput
|
||||||
<label>{{ field.name }}</label>
|
v-model="provider.fields[field.key]"
|
||||||
<span class="flex max-w-lg">
|
:type="
|
||||||
<HoppSmartInput
|
isMasked(provider.name, field.key) ? 'password' : 'text'
|
||||||
v-model="provider.fields[field.key as keyof typeof provider['fields']]"
|
"
|
||||||
:type="
|
:disabled="isMasked(provider.name, field.key)"
|
||||||
isMasked(provider.name, field.key) ? 'password' : 'text'
|
:autofocus="false"
|
||||||
"
|
class="!my-2 !bg-primaryLight"
|
||||||
:autofocus="false"
|
/>
|
||||||
class="!my-2 !bg-primaryLight flex-1"
|
<HoppButtonSecondary
|
||||||
/>
|
:icon="
|
||||||
<HoppButtonSecondary
|
isMasked(provider.name, field.key) ? IconEye : IconEyeOff
|
||||||
:icon="
|
"
|
||||||
isMasked(provider.name, field.key) ? IconEye : IconEyeOff
|
class="bg-primaryLight h-9 mt-2"
|
||||||
"
|
@click="toggleMask(provider.name, field.key)"
|
||||||
class="bg-primaryLight h-9 mt-2"
|
/>
|
||||||
@click="toggleMask(provider.name, field.key)"
|
</span>
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -89,76 +86,47 @@ const workingConfigs = useVModel(props, 'config', emit);
|
|||||||
const capitalize = (text: string) =>
|
const capitalize = (text: string) =>
|
||||||
text.charAt(0).toUpperCase() + text.slice(1);
|
text.charAt(0).toUpperCase() + text.slice(1);
|
||||||
|
|
||||||
// Union type for all possible field keys
|
// Masking sensitive fields
|
||||||
type ProviderFieldKeys = keyof ProviderFields;
|
type Field = {
|
||||||
|
|
||||||
type ProviderFields = {
|
|
||||||
[Field in keyof Config['providers'][SsoAuthProviders]['fields']]: boolean;
|
|
||||||
} & Partial<{ tenant: boolean }>;
|
|
||||||
|
|
||||||
type ProviderFieldMetadata = {
|
|
||||||
name: string;
|
name: string;
|
||||||
key: ProviderFieldKeys;
|
key: keyof Config['providers']['google' | 'github' | 'microsoft']['fields'];
|
||||||
applicableProviders: SsoAuthProviders[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const providerConfigFields = <ProviderFieldMetadata[]>[
|
const providerConfigFields = reactive<Field[]>([
|
||||||
{
|
{ name: t('configs.auth_providers.client_id'), key: 'client_id' },
|
||||||
name: t('configs.auth_providers.client_id'),
|
{ name: t('configs.auth_providers.client_secret'), key: 'client_secret' },
|
||||||
key: 'client_id',
|
]);
|
||||||
applicableProviders: ['google', 'github', 'microsoft'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: t('configs.auth_providers.client_secret'),
|
|
||||||
key: 'client_secret',
|
|
||||||
applicableProviders: ['google', 'github', 'microsoft'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: t('configs.auth_providers.callback_url'),
|
|
||||||
key: 'callback_url',
|
|
||||||
applicableProviders: ['google', 'github', 'microsoft'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: t('configs.auth_providers.scope'),
|
|
||||||
key: 'scope',
|
|
||||||
applicableProviders: ['google', 'github', 'microsoft'],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: t('configs.auth_providers.tenant'),
|
|
||||||
key: 'tenant',
|
|
||||||
applicableProviders: ['microsoft'],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const maskState = reactive<Record<SsoAuthProviders, ProviderFields>>({
|
const maskState = reactive({
|
||||||
google: {
|
google: {
|
||||||
client_id: true,
|
client_id: true,
|
||||||
client_secret: true,
|
client_secret: true,
|
||||||
callback_url: true,
|
|
||||||
scope: true,
|
|
||||||
},
|
},
|
||||||
github: {
|
github: {
|
||||||
client_id: true,
|
client_id: true,
|
||||||
client_secret: true,
|
client_secret: true,
|
||||||
callback_url: true,
|
|
||||||
scope: true,
|
|
||||||
},
|
},
|
||||||
microsoft: {
|
microsoft: {
|
||||||
client_id: true,
|
client_id: true,
|
||||||
client_secret: true,
|
client_secret: true,
|
||||||
callback_url: true,
|
|
||||||
scope: true,
|
|
||||||
tenant: true,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggleMask = (
|
const toggleMask = (
|
||||||
provider: SsoAuthProviders,
|
provider: SsoAuthProviders,
|
||||||
fieldKey: ProviderFieldKeys
|
fieldKey: keyof Config['providers'][
|
||||||
|
| 'google'
|
||||||
|
| 'github'
|
||||||
|
| 'microsoft']['fields']
|
||||||
) => {
|
) => {
|
||||||
maskState[provider][fieldKey] = !maskState[provider][fieldKey];
|
maskState[provider][fieldKey] = !maskState[provider][fieldKey];
|
||||||
};
|
};
|
||||||
|
|
||||||
const isMasked = (provider: SsoAuthProviders, fieldKey: ProviderFieldKeys) =>
|
const isMasked = (
|
||||||
maskState[provider][fieldKey];
|
provider: SsoAuthProviders,
|
||||||
|
fieldKey: keyof Config['providers'][
|
||||||
|
| 'google'
|
||||||
|
| 'github'
|
||||||
|
| 'microsoft']['fields']
|
||||||
|
) => maskState[provider][fieldKey];
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -21,12 +21,13 @@
|
|||||||
</HoppSmartToggle>
|
</HoppSmartToggle>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- TODO: Update the link below -->
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
outline
|
outline
|
||||||
filled
|
filled
|
||||||
:icon="IconShieldQuestion"
|
:icon="IconShieldQuestion"
|
||||||
:label="t('configs.data_sharing.see_shared')"
|
:label="t('configs.data_sharing.see_shared')"
|
||||||
to="https://docs.hoppscotch.io/documentation/self-host/community-edition/telemetry"
|
to="http://docs.hoppscotch.io"
|
||||||
blank
|
blank
|
||||||
class="w-min my-2"
|
class="w-min my-2"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -33,12 +33,13 @@
|
|||||||
class="mt-5"
|
class="mt-5"
|
||||||
>
|
>
|
||||||
<label>{{ field.name }}</label>
|
<label>{{ field.name }}</label>
|
||||||
<span class="flex max-w-lg">
|
<span class="flex">
|
||||||
<HoppSmartInput
|
<HoppSmartInput
|
||||||
v-model="smtpConfigs.fields[field.key]"
|
v-model="smtpConfigs.fields[field.key]"
|
||||||
:type="isMasked(field.key) ? 'password' : 'text'"
|
:type="isMasked(field.key) ? 'password' : 'text'"
|
||||||
|
:disabled="isMasked(field.key)"
|
||||||
:autofocus="false"
|
:autofocus="false"
|
||||||
class="!my-2 !bg-primaryLight flex-1"
|
class="!my-2 !bg-primaryLight"
|
||||||
/>
|
/>
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
:icon="isMasked(field.key) ? IconEye : IconEyeOff"
|
:icon="isMasked(field.key) ? IconEye : IconEyeOff"
|
||||||
|
|||||||
@@ -28,9 +28,10 @@
|
|||||||
>
|
>
|
||||||
{{ t('data_sharing.toggle_description') }}
|
{{ t('data_sharing.toggle_description') }}
|
||||||
</HoppSmartToggle>
|
</HoppSmartToggle>
|
||||||
|
<!-- TODO: Update link -->
|
||||||
<HoppSmartAnchor
|
<HoppSmartAnchor
|
||||||
blank
|
blank
|
||||||
to="https://docs.hoppscotch.io/documentation/self-host/community-edition/telemetry"
|
to="http://docs.hoppscotch.io"
|
||||||
:label="t('data_sharing.see_shared')"
|
:label="t('data_sharing.see_shared')"
|
||||||
class="underline"
|
class="underline"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -24,40 +24,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<template v-for="(info, key) in userInfo" :key="key">
|
<template v-for="(info, key) in userInfo" :key="key">
|
||||||
<div v-if="key === 'displayName'" class="flex flex-col space-y-3">
|
<div v-if="info.condition">
|
||||||
<label class="text-accentContrast" for="teamname"
|
|
||||||
>{{ t('users.name') }}
|
|
||||||
</label>
|
|
||||||
<div
|
|
||||||
class="flex bg-divider rounded-md items-stretch flex-1 border border-divider"
|
|
||||||
:class="{
|
|
||||||
'!border-accent': isNameBeingEdited,
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
<HoppSmartInput
|
|
||||||
v-model="updatedUserName"
|
|
||||||
styles="bg-transparent flex-1 rounded-md !rounded-r-none disabled:select-none border-r-0 disabled:cursor-default disabled:opacity-50"
|
|
||||||
:placeholder="t('users.name')"
|
|
||||||
:disabled="!isNameBeingEdited"
|
|
||||||
>
|
|
||||||
<template #button>
|
|
||||||
<HoppButtonPrimary
|
|
||||||
class="!rounded-l-none"
|
|
||||||
filled
|
|
||||||
:icon="isNameBeingEdited ? IconSave : IconEdit"
|
|
||||||
:label="
|
|
||||||
isNameBeingEdited ? t('users.rename') : t('users.edit')
|
|
||||||
"
|
|
||||||
@click="handleNameEdit"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</HoppSmartInput>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-else-if="info.condition">
|
|
||||||
<label class="text-secondaryDark" :for="key">{{ info.label }}</label>
|
<label class="text-secondaryDark" :for="key">{{ info.label }}</label>
|
||||||
<div class="w-full p-3 mt-2 bg-divider border-gray-600 rounded-md">
|
<div
|
||||||
|
class="w-full p-3 mt-2 bg-divider border-gray-600 rounded-md focus:border-emerald-600 focus:ring focus:ring-opacity-40 focus:ring-emerald-500"
|
||||||
|
>
|
||||||
<span>{{ info.value }}</span>
|
<span>{{ info.value }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -99,17 +70,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useMutation } from '@urql/vue';
|
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { computed, onMounted, ref } from 'vue';
|
|
||||||
import { useI18n } from '~/composables/i18n';
|
import { useI18n } from '~/composables/i18n';
|
||||||
import { useToast } from '~/composables/toast';
|
import { useToast } from '~/composables/toast';
|
||||||
import {
|
import { UserInfoQuery } from '~/helpers/backend/graphql';
|
||||||
UpdateUserDisplayNameByAdminDocument,
|
|
||||||
UserInfoQuery,
|
|
||||||
} from '~/helpers/backend/graphql';
|
|
||||||
import IconEdit from '~icons/lucide/edit';
|
|
||||||
import IconSave from '~icons/lucide/save';
|
|
||||||
import IconTrash from '~icons/lucide/trash';
|
import IconTrash from '~icons/lucide/trash';
|
||||||
import IconUserCheck from '~icons/lucide/user-check';
|
import IconUserCheck from '~icons/lucide/user-check';
|
||||||
import IconUserMinus from '~icons/lucide/user-minus';
|
import IconUserMinus from '~icons/lucide/user-minus';
|
||||||
@@ -125,7 +89,6 @@ const emit = defineEmits<{
|
|||||||
(event: 'delete-user', userID: string): void;
|
(event: 'delete-user', userID: string): void;
|
||||||
(event: 'make-admin', userID: string): void;
|
(event: 'make-admin', userID: string): void;
|
||||||
(event: 'remove-admin', userID: string): void;
|
(event: 'remove-admin', userID: string): void;
|
||||||
(event: 'update-user-name', newName: string): void;
|
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
// Get Proper Date Formats
|
// Get Proper Date Formats
|
||||||
@@ -157,62 +120,4 @@ const userInfo = {
|
|||||||
value: getCreatedDateAndTime(createdOn),
|
value: getCreatedDateAndTime(createdOn),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Contains the actual user name
|
|
||||||
const userName = computed({
|
|
||||||
get: () => props.user.displayName,
|
|
||||||
set: (value) => {
|
|
||||||
return value;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Contains the stored user name from the actual name before being edited
|
|
||||||
const currentUserName = ref('');
|
|
||||||
|
|
||||||
// Set the current user name to the actual user name
|
|
||||||
onMounted(() => {
|
|
||||||
if (displayName) currentUserName.value = displayName;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Contains the user name that is being edited
|
|
||||||
const updatedUserName = computed({
|
|
||||||
get: () => currentUserName.value,
|
|
||||||
set: (value) => {
|
|
||||||
currentUserName.value = value;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Rename the user
|
|
||||||
const isNameBeingEdited = ref(false);
|
|
||||||
const userRename = useMutation(UpdateUserDisplayNameByAdminDocument);
|
|
||||||
|
|
||||||
const handleNameEdit = () => {
|
|
||||||
if (isNameBeingEdited.value) {
|
|
||||||
// If the name is not changed, then return control
|
|
||||||
if (userName.value !== updatedUserName.value) {
|
|
||||||
renameUserName();
|
|
||||||
} else isNameBeingEdited.value = false;
|
|
||||||
} else {
|
|
||||||
isNameBeingEdited.value = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const renameUserName = async () => {
|
|
||||||
if (updatedUserName.value?.trim() === '') {
|
|
||||||
toast.error(t('users.empty_name'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const variables = { userUID: uid, name: updatedUserName.value as string };
|
|
||||||
const result = await userRename.executeMutation(variables);
|
|
||||||
|
|
||||||
if (result.error) {
|
|
||||||
toast.error(t('state.rename_user_failure'));
|
|
||||||
} else {
|
|
||||||
isNameBeingEdited.value = false;
|
|
||||||
toast.success(t('state.rename_user_success'));
|
|
||||||
emit('update-user-name', updatedUserName.value as string);
|
|
||||||
userName.value = updatedUserName.value;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
v-model="email"
|
v-model="email"
|
||||||
:label="t('users.email_address')"
|
:label="t('users.email_address')"
|
||||||
input-styles="floating-input"
|
input-styles="floating-input"
|
||||||
@submit="sendInvite"
|
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
@@ -19,12 +18,7 @@
|
|||||||
:label="t('users.send_invite')"
|
:label="t('users.send_invite')"
|
||||||
@click="sendInvite"
|
@click="sendInvite"
|
||||||
/>
|
/>
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary label="Cancel" outline filled @click="hideModal" />
|
||||||
:label="t('users.cancel')"
|
|
||||||
outline
|
|
||||||
filled
|
|
||||||
@click="hideModal"
|
|
||||||
/>
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</HoppSmartModal>
|
</HoppSmartModal>
|
||||||
|
|||||||
@@ -1,68 +1,78 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="px-4 mt-7">
|
<div class="px-4">
|
||||||
<div v-if="fetching" class="flex justify-center">
|
<div v-if="fetching" class="flex justify-center">
|
||||||
<HoppSmartSpinner />
|
<HoppSmartSpinner />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="error">{{ t('shared_requests.load_list_error') }}</div>
|
<div v-else-if="error">{{ t('shared_requests.load_list_error') }}</div>
|
||||||
|
|
||||||
<div v-else-if="sharedRequests.length === 0">
|
<div v-else-if="sharedRequests.length === 0" class="mt-5">
|
||||||
{{ t('users.no_shared_requests') }}
|
{{ t('users.no_shared_requests') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<HoppSmartTable v-else :headings="headings" :list="sharedRequests">
|
<HoppSmartTable v-else class="mt-8" :list="sharedRequests">
|
||||||
<template #head>
|
<template #head>
|
||||||
<th class="px-6 py-2">{{ t('shared_requests.id') }}</th>
|
<tr
|
||||||
<th class="px-6 py-2 w-30">{{ t('shared_requests.url') }}</th>
|
class="text-secondary border-b border-dividerDark text-sm text-left bg-primaryLight"
|
||||||
<th class="px-6 py-2">{{ t('shared_requests.created_on') }}</th>
|
>
|
||||||
<!-- Empty Heading for the Action Button -->
|
<th class="px-6 py-2">{{ t('shared_requests.id') }}</th>
|
||||||
<th class="px-6 py-2 text-center">
|
<th class="px-6 py-2 w-30">{{ t('shared_requests.url') }}</th>
|
||||||
{{ t('shared_requests.action') }}
|
<th class="px-6 py-2">{{ t('shared_requests.created_on') }}</th>
|
||||||
</th>
|
<!-- Empty Heading for the Action Button -->
|
||||||
|
<th class="px-6 py-2 text-center">
|
||||||
|
{{ t('shared_requests.action') }}
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ row: sharedRequest }">
|
<template #body="{ list: sharedRequests }">
|
||||||
<td class="flex py-4 px-7 max-w-50">
|
<tr
|
||||||
<span class="truncate">
|
v-for="request in sharedRequests"
|
||||||
{{ sharedRequest.id }}
|
:key="request.id"
|
||||||
</span>
|
class="text-secondaryDark hover:bg-divider hover:cursor-pointer rounded-xl"
|
||||||
</td>
|
>
|
||||||
|
<td class="flex py-4 px-7 max-w-50">
|
||||||
|
<span class="truncate">
|
||||||
|
{{ request.id }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td class="py-4 px-7 w-96">
|
<td class="py-4 px-7 w-96">
|
||||||
{{ sharedRequestURL(sharedRequest.request) }}
|
{{ sharedRequestURL(request.request) }}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="py-2 px-7">
|
<td class="py-2 px-7">
|
||||||
{{ getCreatedDate(sharedRequest.createdOn) }}
|
{{ getCreatedDate(request.createdOn) }}
|
||||||
<div class="text-gray-400 text-tiny">
|
<div class="text-gray-400 text-tiny">
|
||||||
{{ getCreatedTime(sharedRequest.createdOn) }}
|
{{ getCreatedTime(request.createdOn) }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="flex justify-center">
|
<td class="flex justify-center">
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="t('shared_requests.open_request')"
|
:title="t('shared_requests.open_request')"
|
||||||
:to="`${shortcodeBaseURL}/r/${sharedRequest.id}`"
|
:to="`${shortcodeBaseURL}/r/${request.id}`"
|
||||||
:blank="true"
|
:blank="true"
|
||||||
:icon="IconExternalLink"
|
:icon="IconExternalLink"
|
||||||
class="px-3 text-emerald-500 hover:text-accent"
|
class="px-3 text-emerald-500 hover:text-accent"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<UiAutoResetIcon
|
<UiAutoResetIcon
|
||||||
:title="t('shared_requests.copy')"
|
:title="t('shared_requests.copy')"
|
||||||
:icon="{ default: IconCopy, temporary: IconCheck }"
|
:icon="{ default: IconCopy, temporary: IconCheck }"
|
||||||
@click="copySharedRequest(sharedRequest.id)"
|
@click="copySharedRequest(request.id)"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:title="t('shared_requests.delete')"
|
:title="t('shared_requests.delete')"
|
||||||
:icon="IconTrash"
|
:icon="IconTrash"
|
||||||
color="red"
|
color="red"
|
||||||
class="px-3"
|
class="px-3"
|
||||||
@click="deleteSharedRequest(sharedRequest.id)"
|
@click="deleteSharedRequest(request.id)"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
</HoppSmartTable>
|
</HoppSmartTable>
|
||||||
|
|
||||||
@@ -126,18 +136,11 @@ const {
|
|||||||
} = usePagedQuery(
|
} = usePagedQuery(
|
||||||
SharedRequestsDocument,
|
SharedRequestsDocument,
|
||||||
(x) => x.infra.allShortcodes,
|
(x) => x.infra.allShortcodes,
|
||||||
|
(x) => x.id,
|
||||||
sharedRequestsPerPage,
|
sharedRequestsPerPage,
|
||||||
{ cursor: undefined, take: sharedRequestsPerPage, email: props.email },
|
{ cursor: undefined, take: sharedRequestsPerPage, email: props.email }
|
||||||
(x) => x.id
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const headings = [
|
|
||||||
{ key: 'id', label: t('shared_requests.id') },
|
|
||||||
{ key: 'request', label: t('shared_requests.url') },
|
|
||||||
{ key: 'createdOn', label: t('shared_requests.created_on') },
|
|
||||||
{ key: 'action', label: t('shared_requests.action') },
|
|
||||||
];
|
|
||||||
|
|
||||||
// Return request endpoint from the request object
|
// Return request endpoint from the request object
|
||||||
const sharedRequestURL = (request: string) => {
|
const sharedRequestURL = (request: string) => {
|
||||||
const parsedRequest = JSON.parse(request);
|
const parsedRequest = JSON.parse(request);
|
||||||
@@ -171,17 +174,17 @@ const deleteSharedRequestMutation = async (id: string | null) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const variables = { codeID: id };
|
const variables = { codeID: id };
|
||||||
const result = await sharedRequestDeletion.executeMutation(variables);
|
await sharedRequestDeletion.executeMutation(variables).then((result) => {
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
toast.error(t('state.delete_request_failure'));
|
toast.error(t('state.delete_request_failure'));
|
||||||
} else {
|
} else {
|
||||||
sharedRequests.value = sharedRequests.value.filter(
|
sharedRequests.value = sharedRequests.value.filter(
|
||||||
(request) => request.id !== id
|
(request) => request.id !== id
|
||||||
);
|
);
|
||||||
refetch();
|
refetch();
|
||||||
toast.success(t('state.delete_request_success'));
|
toast.success(t('state.delete_request_success'));
|
||||||
}
|
}
|
||||||
|
});
|
||||||
confirmDeletion.value = false;
|
confirmDeletion.value = false;
|
||||||
deleteSharedRequestID.value = null;
|
deleteSharedRequestID.value = null;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -27,8 +27,6 @@ export type Config = {
|
|||||||
fields: {
|
fields: {
|
||||||
client_id: string;
|
client_id: string;
|
||||||
client_secret: string;
|
client_secret: string;
|
||||||
callback_url: string;
|
|
||||||
scope: string;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
github: {
|
github: {
|
||||||
@@ -37,8 +35,6 @@ export type Config = {
|
|||||||
fields: {
|
fields: {
|
||||||
client_id: string;
|
client_id: string;
|
||||||
client_secret: string;
|
client_secret: string;
|
||||||
callback_url: string;
|
|
||||||
scope: string;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
microsoft: {
|
microsoft: {
|
||||||
@@ -47,9 +43,6 @@ export type Config = {
|
|||||||
fields: {
|
fields: {
|
||||||
client_id: string;
|
client_id: string;
|
||||||
client_secret: string;
|
client_secret: string;
|
||||||
callback_url: string;
|
|
||||||
scope: string;
|
|
||||||
tenant: string;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -93,17 +86,10 @@ export function useConfigHandler(updatedConfigs?: Config) {
|
|||||||
configNames: [
|
configNames: [
|
||||||
'GOOGLE_CLIENT_ID',
|
'GOOGLE_CLIENT_ID',
|
||||||
'GOOGLE_CLIENT_SECRET',
|
'GOOGLE_CLIENT_SECRET',
|
||||||
'GOOGLE_CALLBACK_URL',
|
|
||||||
'GOOGLE_SCOPE',
|
|
||||||
'MICROSOFT_CLIENT_ID',
|
'MICROSOFT_CLIENT_ID',
|
||||||
'MICROSOFT_CLIENT_SECRET',
|
'MICROSOFT_CLIENT_SECRET',
|
||||||
'MICROSOFT_CALLBACK_URL',
|
|
||||||
'MICROSOFT_SCOPE',
|
|
||||||
'MICROSOFT_TENANT',
|
|
||||||
'GITHUB_CLIENT_ID',
|
'GITHUB_CLIENT_ID',
|
||||||
'GITHUB_CLIENT_SECRET',
|
'GITHUB_CLIENT_SECRET',
|
||||||
'GITHUB_CALLBACK_URL',
|
|
||||||
'GITHUB_SCOPE',
|
|
||||||
'MAILER_SMTP_URL',
|
'MAILER_SMTP_URL',
|
||||||
'MAILER_ADDRESS_FROM',
|
'MAILER_ADDRESS_FROM',
|
||||||
'ALLOW_ANALYTICS_COLLECTION',
|
'ALLOW_ANALYTICS_COLLECTION',
|
||||||
@@ -132,9 +118,6 @@ export function useConfigHandler(updatedConfigs?: Config) {
|
|||||||
await fetchInfraConfigs();
|
await fetchInfraConfigs();
|
||||||
await fetchAllowedAuthProviders();
|
await fetchAllowedAuthProviders();
|
||||||
|
|
||||||
const getFieldValue = (name: string) =>
|
|
||||||
infraConfigs.value.find((x) => x.name === name)?.value ?? '';
|
|
||||||
|
|
||||||
// Transforming the fetched data into a Configs object
|
// Transforming the fetched data into a Configs object
|
||||||
currentConfigs.value = {
|
currentConfigs.value = {
|
||||||
providers: {
|
providers: {
|
||||||
@@ -142,31 +125,37 @@ export function useConfigHandler(updatedConfigs?: Config) {
|
|||||||
name: 'google',
|
name: 'google',
|
||||||
enabled: allowedAuthProviders.value.includes('GOOGLE'),
|
enabled: allowedAuthProviders.value.includes('GOOGLE'),
|
||||||
fields: {
|
fields: {
|
||||||
client_id: getFieldValue('GOOGLE_CLIENT_ID'),
|
client_id:
|
||||||
client_secret: getFieldValue('GOOGLE_CLIENT_SECRET'),
|
infraConfigs.value.find((x) => x.name === 'GOOGLE_CLIENT_ID')
|
||||||
callback_url: getFieldValue('GOOGLE_CALLBACK_URL'),
|
?.value ?? '',
|
||||||
scope: getFieldValue('GOOGLE_SCOPE'),
|
client_secret:
|
||||||
|
infraConfigs.value.find((x) => x.name === 'GOOGLE_CLIENT_SECRET')
|
||||||
|
?.value ?? '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
github: {
|
github: {
|
||||||
name: 'github',
|
name: 'github',
|
||||||
enabled: allowedAuthProviders.value.includes('GITHUB'),
|
enabled: allowedAuthProviders.value.includes('GITHUB'),
|
||||||
fields: {
|
fields: {
|
||||||
client_id: getFieldValue('GITHUB_CLIENT_ID'),
|
client_id:
|
||||||
client_secret: getFieldValue('GITHUB_CLIENT_SECRET'),
|
infraConfigs.value.find((x) => x.name === 'GITHUB_CLIENT_ID')
|
||||||
callback_url: getFieldValue('GITHUB_CALLBACK_URL'),
|
?.value ?? '',
|
||||||
scope: getFieldValue('GITHUB_SCOPE'),
|
client_secret:
|
||||||
|
infraConfigs.value.find((x) => x.name === 'GITHUB_CLIENT_SECRET')
|
||||||
|
?.value ?? '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
microsoft: {
|
microsoft: {
|
||||||
name: 'microsoft',
|
name: 'microsoft',
|
||||||
enabled: allowedAuthProviders.value.includes('MICROSOFT'),
|
enabled: allowedAuthProviders.value.includes('MICROSOFT'),
|
||||||
fields: {
|
fields: {
|
||||||
client_id: getFieldValue('MICROSOFT_CLIENT_ID'),
|
client_id:
|
||||||
client_secret: getFieldValue('MICROSOFT_CLIENT_SECRET'),
|
infraConfigs.value.find((x) => x.name === 'MICROSOFT_CLIENT_ID')
|
||||||
callback_url: getFieldValue('MICROSOFT_CALLBACK_URL'),
|
?.value ?? '',
|
||||||
scope: getFieldValue('MICROSOFT_SCOPE'),
|
client_secret:
|
||||||
tenant: getFieldValue('MICROSOFT_TENANT'),
|
infraConfigs.value.find(
|
||||||
|
(x) => x.name === 'MICROSOFT_CLIENT_SECRET'
|
||||||
|
)?.value ?? '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -174,8 +163,12 @@ export function useConfigHandler(updatedConfigs?: Config) {
|
|||||||
name: 'email',
|
name: 'email',
|
||||||
enabled: allowedAuthProviders.value.includes('EMAIL'),
|
enabled: allowedAuthProviders.value.includes('EMAIL'),
|
||||||
fields: {
|
fields: {
|
||||||
mailer_smtp_url: getFieldValue('MAILER_SMTP_URL'),
|
mailer_smtp_url:
|
||||||
mailer_from_address: getFieldValue('MAILER_ADDRESS_FROM'),
|
infraConfigs.value.find((x) => x.name === 'MAILER_SMTP_URL')
|
||||||
|
?.value ?? '',
|
||||||
|
mailer_from_address:
|
||||||
|
infraConfigs.value.find((x) => x.name === 'MAILER_ADDRESS_FROM')
|
||||||
|
?.value ?? '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
dataSharingConfigs: {
|
dataSharingConfigs: {
|
||||||
@@ -191,7 +184,7 @@ export function useConfigHandler(updatedConfigs?: Config) {
|
|||||||
workingConfigs.value = cloneDeep(currentConfigs.value);
|
workingConfigs.value = cloneDeep(currentConfigs.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Transforming the working configs back into the format required by the mutations
|
// Trasforming the working configs back into the format required by the mutations
|
||||||
const updatedInfraConfigs = computed(() => {
|
const updatedInfraConfigs = computed(() => {
|
||||||
let config: UpdatedConfigs[] = [
|
let config: UpdatedConfigs[] = [
|
||||||
{
|
{
|
||||||
@@ -209,23 +202,13 @@ export function useConfigHandler(updatedConfigs?: Config) {
|
|||||||
{
|
{
|
||||||
name: 'GOOGLE_CLIENT_SECRET',
|
name: 'GOOGLE_CLIENT_SECRET',
|
||||||
value: updatedConfigs?.providers.google.fields.client_secret ?? '',
|
value: updatedConfigs?.providers.google.fields.client_secret ?? '',
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'GOOGLE_CALLBACK_URL',
|
|
||||||
value: updatedConfigs?.providers.google.fields.callback_url ?? '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'GOOGLE_SCOPE',
|
|
||||||
value: updatedConfigs?.providers.google.fields.scope ?? '',
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
config = config.filter(
|
config = config.filter(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.name !== 'GOOGLE_CLIENT_ID' &&
|
item.name !== 'GOOGLE_CLIENT_ID' &&
|
||||||
item.name !== 'GOOGLE_CLIENT_SECRET' &&
|
item.name !== 'GOOGLE_CLIENT_SECRET'
|
||||||
item.name !== 'GOOGLE_CALLBACK_URL' &&
|
|
||||||
item.name !== 'GOOGLE_SCOPE'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (updatedConfigs?.providers.microsoft.enabled) {
|
if (updatedConfigs?.providers.microsoft.enabled) {
|
||||||
@@ -237,28 +220,13 @@ export function useConfigHandler(updatedConfigs?: Config) {
|
|||||||
{
|
{
|
||||||
name: 'MICROSOFT_CLIENT_SECRET',
|
name: 'MICROSOFT_CLIENT_SECRET',
|
||||||
value: updatedConfigs?.providers.microsoft.fields.client_secret ?? '',
|
value: updatedConfigs?.providers.microsoft.fields.client_secret ?? '',
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'MICROSOFT_CALLBACK_URL',
|
|
||||||
value: updatedConfigs?.providers.microsoft.fields.callback_url ?? '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'MICROSOFT_SCOPE',
|
|
||||||
value: updatedConfigs?.providers.microsoft.fields.scope ?? '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'MICROSOFT_TENANT',
|
|
||||||
value: updatedConfigs?.providers.microsoft.fields.tenant ?? '',
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
config = config.filter(
|
config = config.filter(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.name !== 'MICROSOFT_CLIENT_ID' &&
|
item.name !== 'MICROSOFT_CLIENT_ID' &&
|
||||||
item.name !== 'MICROSOFT_CLIENT_SECRET' &&
|
item.name !== 'MICROSOFT_CLIENT_SECRET'
|
||||||
item.name !== 'MICROSOFT_CALLBACK_URL' &&
|
|
||||||
item.name !== 'MICROSOFT_SCOPE' &&
|
|
||||||
item.name !== 'MICROSOFT_TENANT'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,23 +239,13 @@ export function useConfigHandler(updatedConfigs?: Config) {
|
|||||||
{
|
{
|
||||||
name: 'GITHUB_CLIENT_SECRET',
|
name: 'GITHUB_CLIENT_SECRET',
|
||||||
value: updatedConfigs?.providers.github.fields.client_secret ?? '',
|
value: updatedConfigs?.providers.github.fields.client_secret ?? '',
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'GITHUB_CALLBACK_URL',
|
|
||||||
value: updatedConfigs?.providers.github.fields.callback_url ?? '',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'GITHUB_SCOPE',
|
|
||||||
value: updatedConfigs?.providers.github.fields.scope ?? '',
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
config = config.filter(
|
config = config.filter(
|
||||||
(item) =>
|
(item) =>
|
||||||
item.name !== 'GITHUB_CLIENT_ID' &&
|
item.name !== 'GITHUB_CLIENT_ID' &&
|
||||||
item.name !== 'GITHUB_CLIENT_SECRET' &&
|
item.name !== 'GITHUB_CLIENT_SECRET'
|
||||||
item.name !== 'GITHUB_CALLBACK_URL' &&
|
|
||||||
item.name !== 'GITHUB_SCOPE'
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { onMounted, ref, Ref } from 'vue';
|
import { Ref, onMounted, ref } from 'vue';
|
||||||
import { DocumentNode } from 'graphql';
|
import { DocumentNode } from 'graphql';
|
||||||
import { TypedDocumentNode, useClientHandle } from '@urql/vue';
|
import { TypedDocumentNode, useClientHandle } from '@urql/vue';
|
||||||
|
|
||||||
@@ -9,9 +9,9 @@ export function usePagedQuery<
|
|||||||
>(
|
>(
|
||||||
query: string | TypedDocumentNode<Result, Vars> | DocumentNode,
|
query: string | TypedDocumentNode<Result, Vars> | DocumentNode,
|
||||||
getList: (result: Result) => ListItem[],
|
getList: (result: Result) => ListItem[],
|
||||||
|
getCursor: (value: ListItem) => string,
|
||||||
itemsPerPage: number,
|
itemsPerPage: number,
|
||||||
baseVariables: Vars,
|
variables: Vars
|
||||||
getCursor?: (value: ListItem) => string
|
|
||||||
) {
|
) {
|
||||||
const { client } = useClientHandle();
|
const { client } = useClientHandle();
|
||||||
const fetching = ref(true);
|
const fetching = ref(true);
|
||||||
@@ -20,25 +20,21 @@ export function usePagedQuery<
|
|||||||
const currentPage = ref(0);
|
const currentPage = ref(0);
|
||||||
const hasNextPage = ref(true);
|
const hasNextPage = ref(true);
|
||||||
|
|
||||||
const fetchNextPage = async (additionalVariables?: Vars) => {
|
const fetchNextPage = async () => {
|
||||||
let variables = { ...baseVariables };
|
|
||||||
|
|
||||||
fetching.value = true;
|
fetching.value = true;
|
||||||
|
|
||||||
// Cursor based pagination
|
const cursor =
|
||||||
if (getCursor) {
|
list.value.length > 0 ? getCursor(list.value.at(-1)!) : undefined;
|
||||||
const cursor =
|
const variablesForPagination = {
|
||||||
list.value.length > 0
|
...variables,
|
||||||
? getCursor(list.value.at(-1) as ListItem)
|
take: itemsPerPage,
|
||||||
: undefined;
|
cursor,
|
||||||
variables = { ...variables, cursor };
|
};
|
||||||
}
|
|
||||||
// Offset based pagination
|
const result = await client
|
||||||
else if (additionalVariables) {
|
.query(query, variablesForPagination)
|
||||||
variables = { ...variables, ...additionalVariables };
|
.toPromise();
|
||||||
}
|
|
||||||
|
|
||||||
const result = await client.query(query, variables).toPromise();
|
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
error.value = true;
|
error.value = true;
|
||||||
fetching.value = false;
|
fetching.value = false;
|
||||||
@@ -67,14 +63,11 @@ export function usePagedQuery<
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const refetch = async (variables?: Vars) => {
|
const refetch = async () => {
|
||||||
currentPage.value = 0;
|
currentPage.value = 0;
|
||||||
hasNextPage.value = true;
|
hasNextPage.value = true;
|
||||||
list.value = [];
|
list.value = [];
|
||||||
|
await fetchNextPage();
|
||||||
if (hasNextPage.value) {
|
|
||||||
variables ? await fetchNextPage(variables) : await fetchNextPage();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
mutation DemoteUsersByAdmin($userUIDs: [ID!]!) {
|
|
||||||
demoteUsersByAdmin(userUIDs: $userUIDs)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
mutation MakeUserAdmin($uid: ID!) {
|
||||||
|
makeUserAdmin(userUID: $uid)
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
mutation MakeUsersAdmin($userUIDs: [ID!]!) {
|
|
||||||
makeUsersAdmin(userUIDs: $userUIDs)
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
mutation RemoveUserAsAdmin($uid: ID!) {
|
||||||
|
removeUserAsAdmin(userUID: $uid)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
mutation RemoveUserByAdmin($uid: ID!) {
|
||||||
|
removeUserByAdmin(userUID: $uid)
|
||||||
|
}
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
mutation RemoveUsersByAdmin($userUIDs: [ID!]!) {
|
|
||||||
removeUsersByAdmin(userUIDs: $userUIDs) {
|
|
||||||
userUID
|
|
||||||
isDeleted
|
|
||||||
errorMessage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
mutation RevokeUserInvitationsByAdmin($inviteeEmails: [String!]!) {
|
|
||||||
revokeUserInvitationsByAdmin(inviteeEmails: $inviteeEmails)
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
mutation UpdateUserDisplayNameByAdmin($userUID: ID!, $name: String!) {
|
|
||||||
updateUserDisplayNameByAdmin(userUID: $userUID, displayName: $name)
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
query UsersListV2($searchString: String, $skip: Int, $take: Int) {
|
|
||||||
infra {
|
|
||||||
allUsersV2(searchString: $searchString, skip: $skip, take: $take) {
|
|
||||||
uid
|
|
||||||
displayName
|
|
||||||
email
|
|
||||||
isAdmin
|
|
||||||
photoURL
|
|
||||||
createdOn
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,13 +7,3 @@ export const UNAUTHORIZED = 'Unauthorized' as const;
|
|||||||
|
|
||||||
// Sometimes the backend returns Unauthorized error message as follows:
|
// Sometimes the backend returns Unauthorized error message as follows:
|
||||||
export const GRAPHQL_UNAUTHORIZED = '[GraphQL] Unauthorized' as const;
|
export const GRAPHQL_UNAUTHORIZED = '[GraphQL] Unauthorized' as const;
|
||||||
|
|
||||||
export const DELETE_USER_FAILED_ONLY_ONE_ADMIN =
|
|
||||||
'admin/only_one_admin_account_found' as const;
|
|
||||||
|
|
||||||
export const ADMIN_CANNOT_BE_DELETED =
|
|
||||||
'admin/admin_can_not_be_deleted' as const;
|
|
||||||
|
|
||||||
// When trying to invite a user that is already invited
|
|
||||||
export const USER_ALREADY_INVITED =
|
|
||||||
'[GraphQL] admin/user_already_invited' as const;
|
|
||||||
|
|||||||
@@ -18,83 +18,89 @@
|
|||||||
|
|
||||||
<div v-else-if="error">{{ t('teams.load_list_error') }}</div>
|
<div v-else-if="error">{{ t('teams.load_list_error') }}</div>
|
||||||
|
|
||||||
<HoppSmartTable
|
<HoppSmartTable v-else-if="teamsList.length" :list="teamsList">
|
||||||
v-else-if="teamsList.length"
|
|
||||||
:headings="headings"
|
|
||||||
:list="teamsList"
|
|
||||||
@onRowClicked="goToTeamDetails"
|
|
||||||
>
|
|
||||||
<template #head>
|
<template #head>
|
||||||
<th class="px-6 py-2">{{ t('teams.id') }}</th>
|
<tr
|
||||||
<th class="px-6 py-2">{{ t('teams.name') }}</th>
|
class="text-secondary border-b border-dividerDark text-sm text-left bg-primaryLight"
|
||||||
<th class="px-6 py-2">{{ t('teams.members') }}</th>
|
>
|
||||||
<!-- Empty Heading for the Action Button -->
|
<th class="px-6 py-2">{{ t('teams.id') }}</th>
|
||||||
<th class="px-6 py-2"></th>
|
<th class="px-6 py-2">{{ t('teams.name') }}</th>
|
||||||
|
<th class="px-6 py-2">{{ t('teams.members') }}</th>
|
||||||
|
<!-- Empty Heading for the Action Button -->
|
||||||
|
<th class="px-6 py-2"></th>
|
||||||
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ row: team }">
|
<template #body="{ list }">
|
||||||
<td class="flex py-4 px-7 max-w-[16rem]">
|
<tr
|
||||||
<span class="truncate">
|
v-for="team in list"
|
||||||
{{ team.id }}
|
:key="team.id"
|
||||||
</span>
|
class="text-secondaryDark hover:bg-divider hover:cursor-pointer rounded-xl"
|
||||||
</td>
|
@click="goToTeamDetails(team.id)"
|
||||||
|
>
|
||||||
|
<td class="flex py-4 px-7 max-w-[16rem]">
|
||||||
|
<span class="truncate">
|
||||||
|
{{ team.id }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td class="py-4 px-7 min-w-[20rem]">
|
<td class="py-4 px-7 min-w-[20rem]">
|
||||||
<span
|
<span
|
||||||
class="flex items-center truncate"
|
class="flex items-center truncate"
|
||||||
:class="{ truncate: team.name }"
|
:class="{ truncate: team.name }"
|
||||||
>
|
>
|
||||||
{{ team.name ?? t('teams.unnamed') }}
|
{{ team.name ?? t('teams.unnamed') }}
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class="py-4 px-8">
|
<td class="py-4 px-7">
|
||||||
{{ team.members?.length }}
|
{{ team.members?.length }}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td @click.stop class="flex justify-end mr-10">
|
<td @click.stop>
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<tippy interactive trigger="click" theme="popover">
|
<tippy interactive trigger="click" theme="popover">
|
||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
:icon="IconMoreHorizontal"
|
:icon="IconMoreHorizontal"
|
||||||
/>
|
/>
|
||||||
<template #content="{ hide }">
|
<template #content="{ hide }">
|
||||||
<div
|
<div
|
||||||
ref="tippyActions"
|
ref="tippyActions"
|
||||||
class="flex flex-col focus:outline-none"
|
class="flex flex-col focus:outline-none"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
@keyup.escape="hide()"
|
@keyup.escape="hide()"
|
||||||
>
|
>
|
||||||
<HoppSmartItem
|
<HoppSmartItem
|
||||||
:icon="IconTrash"
|
:icon="IconTrash"
|
||||||
:label="t('teams.delete_team')"
|
:label="t('teams.delete_team')"
|
||||||
class="!hover:bg-red-600 w-full"
|
class="!hover:bg-red-600 w-full"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
deleteTeam(team.id);
|
deleteTeam(team.id);
|
||||||
hide();
|
hide();
|
||||||
}
|
}
|
||||||
"
|
"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</tippy>
|
</tippy>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
</HoppSmartTable>
|
</HoppSmartTable>
|
||||||
|
|
||||||
<div v-else class="px-2">
|
<div v-else class="px-2 text-lg">
|
||||||
{{ t('teams.no_teams') }}
|
{{ t('teams.no_teams') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="hasNextPage && teamsList.length >= teamsPerPage"
|
v-if="hasNextPage && teamsList.length >= teamsPerPage"
|
||||||
class="flex items-center w-28 px-3 py-2 mt-5 mx-auto font-semibold text-secondaryDark bg-divider hover:bg-dividerDark rounded-3xl cursor-pointer"
|
class="flex justify-center my-5 px-3 py-2 cursor-pointer font-semibold rounded-3xl bg-dividerDark hover:bg-divider transition mx-auto w-38 text-secondaryDark"
|
||||||
@click="fetchNextTeams"
|
@click="fetchNextTeams"
|
||||||
>
|
>
|
||||||
<span>{{ t('teams.show_more') }}</span>
|
<span>{{ t('teams.show_more') }}</span>
|
||||||
<icon-lucide-chevron-down class="ml-2" />
|
<icon-lucide-chevron-down class="ml-2 text-lg" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -129,7 +135,6 @@ import {
|
|||||||
CreateTeamDocument,
|
CreateTeamDocument,
|
||||||
MetricsDocument,
|
MetricsDocument,
|
||||||
RemoveTeamDocument,
|
RemoveTeamDocument,
|
||||||
TeamInfoQuery,
|
|
||||||
TeamListDocument,
|
TeamListDocument,
|
||||||
UsersListDocument,
|
UsersListDocument,
|
||||||
} from '../../helpers/backend/graphql';
|
} from '../../helpers/backend/graphql';
|
||||||
@@ -144,9 +149,9 @@ const usersPerPage = computed(() => data.value?.infra.usersCount || 10000);
|
|||||||
const { list: usersList } = usePagedQuery(
|
const { list: usersList } = usePagedQuery(
|
||||||
UsersListDocument,
|
UsersListDocument,
|
||||||
(x) => x.infra.allUsers,
|
(x) => x.infra.allUsers,
|
||||||
|
(x) => x.uid,
|
||||||
usersPerPage.value,
|
usersPerPage.value,
|
||||||
{ cursor: undefined, take: usersPerPage.value },
|
{ cursor: undefined, take: usersPerPage.value }
|
||||||
(x) => x.uid
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const allUsersEmail = computed(() => usersList.value.map((user) => user.email));
|
const allUsersEmail = computed(() => usersList.value.map((user) => user.email));
|
||||||
@@ -163,19 +168,11 @@ const {
|
|||||||
} = usePagedQuery(
|
} = usePagedQuery(
|
||||||
TeamListDocument,
|
TeamListDocument,
|
||||||
(x) => x.infra.allTeams,
|
(x) => x.infra.allTeams,
|
||||||
|
(x) => x.id,
|
||||||
teamsPerPage,
|
teamsPerPage,
|
||||||
{ cursor: undefined, take: teamsPerPage },
|
{ cursor: undefined, take: teamsPerPage }
|
||||||
(x) => x.id
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Table Headings
|
|
||||||
const headings = [
|
|
||||||
{ key: 'id', label: t('teams.id') },
|
|
||||||
{ key: 'name', label: t('teams.name') },
|
|
||||||
{ key: 'members', label: t('teams.members') },
|
|
||||||
{ key: 'actions', label: '' },
|
|
||||||
];
|
|
||||||
|
|
||||||
// Create Team
|
// Create Team
|
||||||
const showCreateTeamModal = ref(false);
|
const showCreateTeamModal = ref(false);
|
||||||
const createTeamLoading = ref(false);
|
const createTeamLoading = ref(false);
|
||||||
@@ -215,8 +212,7 @@ const createTeam = async (newTeamName: string, ownerEmail: string) => {
|
|||||||
|
|
||||||
// Go To Individual Team Details Page
|
// Go To Individual Team Details Page
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const goToTeamDetails = (team: TeamInfoQuery['infra']['teamInfo']) =>
|
const goToTeamDetails = (teamId: string) => router.push('/teams/' + teamId);
|
||||||
router.push('/teams/' + team.id);
|
|
||||||
|
|
||||||
// Team Deletion
|
// Team Deletion
|
||||||
const confirmDeletion = ref(false);
|
const confirmDeletion = ref(false);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<div class="flex items-center space-x-3">
|
<div class="flex items-center space-x-3">
|
||||||
<h1 class="text-lg text-accentContrast">
|
<h1 class="text-lg text-accentContrast">
|
||||||
{{ userName }}
|
{{ user.displayName }}
|
||||||
</h1>
|
</h1>
|
||||||
<span>/</span>
|
<span>/</span>
|
||||||
<h2 class="text-lg text-accentContrast">
|
<h2 class="text-lg text-accentContrast">
|
||||||
@@ -29,7 +29,6 @@
|
|||||||
@delete-user="deleteUser"
|
@delete-user="deleteUser"
|
||||||
@make-admin="makeUserAdmin"
|
@make-admin="makeUserAdmin"
|
||||||
@remove-admin="makeAdminToUser"
|
@remove-admin="makeAdminToUser"
|
||||||
@update-user-name="(name: string) => (userName = name)"
|
|
||||||
class="py-8 px-4"
|
class="py-8 px-4"
|
||||||
/>
|
/>
|
||||||
</HoppSmartTab>
|
</HoppSmartTab>
|
||||||
@@ -41,19 +40,19 @@
|
|||||||
|
|
||||||
<HoppSmartConfirmModal
|
<HoppSmartConfirmModal
|
||||||
:show="confirmDeletion"
|
:show="confirmDeletion"
|
||||||
:title="t('state.confirm_user_deletion')"
|
:title="t('users.confirm_user_deletion')"
|
||||||
@hide-modal="confirmDeletion = false"
|
@hide-modal="confirmDeletion = false"
|
||||||
@resolve="deleteUserMutation(deleteUserUID)"
|
@resolve="deleteUserMutation(deleteUserUID)"
|
||||||
/>
|
/>
|
||||||
<HoppSmartConfirmModal
|
<HoppSmartConfirmModal
|
||||||
:show="confirmUserToAdmin"
|
:show="confirmUserToAdmin"
|
||||||
:title="t('state.confirm_user_to_admin')"
|
:title="t('users.confirm_user_to_admin')"
|
||||||
@hide-modal="confirmUserToAdmin = false"
|
@hide-modal="confirmUserToAdmin = false"
|
||||||
@resolve="makeUserAdminMutation(userToAdminUID)"
|
@resolve="makeUserAdminMutation(userToAdminUID)"
|
||||||
/>
|
/>
|
||||||
<HoppSmartConfirmModal
|
<HoppSmartConfirmModal
|
||||||
:show="confirmAdminToUser"
|
:show="confirmAdminToUser"
|
||||||
:title="t('state.confirm_admin_to_user')"
|
:title="t('users.confirm_admin_to_user')"
|
||||||
@hide-modal="confirmAdminToUser = false"
|
@hide-modal="confirmAdminToUser = false"
|
||||||
@resolve="makeAdminToUserMutation(adminToUserUID)"
|
@resolve="makeAdminToUserMutation(adminToUserUID)"
|
||||||
/>
|
/>
|
||||||
@@ -68,12 +67,11 @@ import { useI18n } from '~/composables/i18n';
|
|||||||
import { useToast } from '~/composables/toast';
|
import { useToast } from '~/composables/toast';
|
||||||
import { useClientHandler } from '~/composables/useClientHandler';
|
import { useClientHandler } from '~/composables/useClientHandler';
|
||||||
import {
|
import {
|
||||||
DemoteUsersByAdminDocument,
|
MakeUserAdminDocument,
|
||||||
MakeUsersAdminDocument,
|
RemoveUserAsAdminDocument,
|
||||||
RemoveUsersByAdminDocument,
|
RemoveUserByAdminDocument,
|
||||||
UserInfoDocument,
|
UserInfoDocument,
|
||||||
} from '~/helpers/backend/graphql';
|
} from '~/helpers/backend/graphql';
|
||||||
import { ADMIN_CANNOT_BE_DELETED } from '~/helpers/errors';
|
|
||||||
|
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const toast = useToast();
|
const toast = useToast();
|
||||||
@@ -106,15 +104,6 @@ onMounted(async () => {
|
|||||||
await fetchData();
|
await fetchData();
|
||||||
});
|
});
|
||||||
|
|
||||||
const userName = computed({
|
|
||||||
get: () => data.value?.infra.userInfo.displayName,
|
|
||||||
set: (value) => {
|
|
||||||
if (value) {
|
|
||||||
data.value!.infra.userInfo.displayName = value;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
const user = computed({
|
const user = computed({
|
||||||
get: () => data.value?.infra.userInfo,
|
get: () => data.value?.infra.userInfo,
|
||||||
set: (value) => {
|
set: (value) => {
|
||||||
@@ -124,69 +113,9 @@ const user = computed({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const confirmUserToAdmin = ref(false);
|
|
||||||
const userToAdminUID = ref<string | null>(null);
|
|
||||||
const usersToAdmin = useMutation(MakeUsersAdminDocument);
|
|
||||||
|
|
||||||
const makeUserAdmin = (id: string | null) => {
|
|
||||||
confirmUserToAdmin.value = true;
|
|
||||||
userToAdminUID.value = id;
|
|
||||||
};
|
|
||||||
|
|
||||||
const makeUserAdminMutation = async (id: string | null) => {
|
|
||||||
if (!id) {
|
|
||||||
confirmUserToAdmin.value = false;
|
|
||||||
toast.error(t('state.admin_failure'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userUIDs = [id];
|
|
||||||
const variables = { userUIDs };
|
|
||||||
const result = await usersToAdmin.executeMutation(variables);
|
|
||||||
|
|
||||||
if (result.error) {
|
|
||||||
toast.error(t('state.admin_failure'));
|
|
||||||
} else {
|
|
||||||
toast.success(t('state.admin_success'));
|
|
||||||
user.value!.isAdmin = true;
|
|
||||||
}
|
|
||||||
confirmUserToAdmin.value = false;
|
|
||||||
userToAdminUID.value = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remove Admin Status from a current admin user
|
|
||||||
const adminToUser = useMutation(DemoteUsersByAdminDocument);
|
|
||||||
const confirmAdminToUser = ref(false);
|
|
||||||
const adminToUserUID = ref<string | null>(null);
|
|
||||||
|
|
||||||
const makeAdminToUser = (id: string) => {
|
|
||||||
confirmAdminToUser.value = true;
|
|
||||||
adminToUserUID.value = id;
|
|
||||||
};
|
|
||||||
|
|
||||||
const makeAdminToUserMutation = async (id: string | null) => {
|
|
||||||
if (!id) {
|
|
||||||
confirmAdminToUser.value = false;
|
|
||||||
toast.error(t('state.remove_admin_failure'));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const userUIDs = [id];
|
|
||||||
const variables = { userUIDs };
|
|
||||||
const result = await adminToUser.executeMutation(variables);
|
|
||||||
if (result.error) {
|
|
||||||
toast.error(t('state.remove_admin_failure'));
|
|
||||||
} else {
|
|
||||||
toast.success(t('state.remove_admin_success'));
|
|
||||||
user.value!.isAdmin = false;
|
|
||||||
}
|
|
||||||
confirmAdminToUser.value = false;
|
|
||||||
adminToUserUID.value = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// User Deletion
|
// User Deletion
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const userDeletion = useMutation(RemoveUsersByAdminDocument);
|
const userDeletion = useMutation(RemoveUserByAdminDocument);
|
||||||
const confirmDeletion = ref(false);
|
const confirmDeletion = ref(false);
|
||||||
const deleteUserUID = ref<string | null>(null);
|
const deleteUserUID = ref<string | null>(null);
|
||||||
|
|
||||||
@@ -201,25 +130,73 @@ const deleteUserMutation = async (id: string | null) => {
|
|||||||
toast.error(t('state.delete_user_failure'));
|
toast.error(t('state.delete_user_failure'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const userUIDs = [id];
|
const variables = { uid: id };
|
||||||
const variables = { userUIDs };
|
|
||||||
const result = await userDeletion.executeMutation(variables);
|
const result = await userDeletion.executeMutation(variables);
|
||||||
|
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
toast.error(t('state.delete_user_failure'));
|
toast.error(t('state.delete_user_failure'));
|
||||||
} else {
|
} else {
|
||||||
const deletedUsers = result.data?.removeUsersByAdmin || [];
|
toast.success(t('state.delete_user_success'));
|
||||||
|
|
||||||
const isAdminError = deletedUsers.some(
|
|
||||||
(user) => user.errorMessage === ADMIN_CANNOT_BE_DELETED
|
|
||||||
);
|
|
||||||
|
|
||||||
isAdminError
|
|
||||||
? toast.error(t('state.delete_user_failed_only_one_admin'))
|
|
||||||
: toast.success(t('state.delete_user_success'));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
confirmDeletion.value = false;
|
confirmDeletion.value = false;
|
||||||
deleteUserUID.value = null;
|
deleteUserUID.value = null;
|
||||||
router.push('/users');
|
router.push('/users');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Make User Admin
|
||||||
|
const userToAdmin = useMutation(MakeUserAdminDocument);
|
||||||
|
const confirmUserToAdmin = ref(false);
|
||||||
|
const userToAdminUID = ref<string | null>(null);
|
||||||
|
|
||||||
|
const makeUserAdmin = (id: string) => {
|
||||||
|
confirmUserToAdmin.value = true;
|
||||||
|
userToAdminUID.value = id;
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeUserAdminMutation = async (id: string | null) => {
|
||||||
|
if (!id) {
|
||||||
|
confirmUserToAdmin.value = false;
|
||||||
|
toast.error(t('state.admin_failure'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const variables = { uid: id };
|
||||||
|
const result = await userToAdmin.executeMutation(variables);
|
||||||
|
if (result.error) {
|
||||||
|
toast.error(t('state.admin_failure'));
|
||||||
|
} else {
|
||||||
|
user.value!.isAdmin = true;
|
||||||
|
toast.success(t('state.admin_success'));
|
||||||
|
}
|
||||||
|
confirmUserToAdmin.value = false;
|
||||||
|
userToAdminUID.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove Admin Status from a current admin user
|
||||||
|
const adminToUser = useMutation(RemoveUserAsAdminDocument);
|
||||||
|
const confirmAdminToUser = ref(false);
|
||||||
|
const adminToUserUID = ref<string | null>(null);
|
||||||
|
|
||||||
|
const makeAdminToUser = (id: string) => {
|
||||||
|
confirmAdminToUser.value = true;
|
||||||
|
adminToUserUID.value = id;
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeAdminToUserMutation = async (id: string | null) => {
|
||||||
|
if (!id) {
|
||||||
|
confirmAdminToUser.value = false;
|
||||||
|
toast.error(t('state.remove_admin_failure'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const variables = { uid: id };
|
||||||
|
const result = await adminToUser.executeMutation(variables);
|
||||||
|
if (result.error) {
|
||||||
|
toast.error(t('state.remove_admin_failure'));
|
||||||
|
} else {
|
||||||
|
user.value!.isAdmin = false;
|
||||||
|
toast.error(t('state.remove_admin_success'));
|
||||||
|
}
|
||||||
|
confirmAdminToUser.value = false;
|
||||||
|
adminToUserUID.value = null;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
<h1 class="text-lg font-bold text-secondaryDark">
|
<h1 class="text-lg font-bold text-secondaryDark">
|
||||||
{{ t('users.users') }}
|
{{ t('users.users') }}
|
||||||
</h1>
|
</h1>
|
||||||
<div class="flex items-center space-x-4 mt-10 mb-5">
|
<div class="flex items-center space-x-4 py-10">
|
||||||
<HoppButtonPrimary
|
<HoppButtonPrimary
|
||||||
:label="t('users.invite_user')"
|
:label="t('users.invite_user')"
|
||||||
@click="showInviteUserModal = true"
|
@click="showInviteUserModal = true"
|
||||||
@@ -15,189 +15,132 @@
|
|||||||
<HoppButtonSecondary
|
<HoppButtonSecondary
|
||||||
outline
|
outline
|
||||||
filled
|
filled
|
||||||
:label="t('users.pending_invites')"
|
:label="t('users.invited_users')"
|
||||||
:to="'/users/invited'"
|
:to="'/users/invited'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="overflow-x-auto">
|
<div class="overflow-x-auto">
|
||||||
<div class="mb-3 flex items-center justify-end">
|
<div v-if="fetching" class="flex justify-center">
|
||||||
<HoppButtonSecondary
|
<HoppSmartSpinner />
|
||||||
outline
|
|
||||||
filled
|
|
||||||
:icon="IconLeft"
|
|
||||||
:disabled="page === 1"
|
|
||||||
@click="changePage(PageDirection.Previous)"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div class="flex h-full w-10 items-center justify-center">
|
|
||||||
<span>{{ page }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<HoppButtonSecondary
|
|
||||||
outline
|
|
||||||
filled
|
|
||||||
:icon="IconRight"
|
|
||||||
:disabled="page >= totalPages"
|
|
||||||
@click="changePage(PageDirection.Next)"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<HoppSmartTable
|
<div v-else-if="error">{{ t('users.load_list_error') }}</div>
|
||||||
v-model:list="finalUsersList"
|
|
||||||
v-model:selected-rows="selectedRows"
|
<HoppSmartTable v-else-if="usersList.length" :list="usersList">
|
||||||
:headings="headings"
|
|
||||||
:loading="showSpinner"
|
|
||||||
@onRowClicked="goToUserDetails"
|
|
||||||
>
|
|
||||||
<template #extension>
|
|
||||||
<div class="flex w-full items-center bg-primary">
|
|
||||||
<icon-lucide-search class="mx-3 text-xs" />
|
|
||||||
<HoppSmartInput
|
|
||||||
v-model="query"
|
|
||||||
styles="w-full bg-primary py-1"
|
|
||||||
input-styles="h-full border-none"
|
|
||||||
:placeholder="t('users.searchbar_placeholder')"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template #head>
|
<template #head>
|
||||||
<th class="px-6 py-2">{{ t('users.id') }}</th>
|
<tr
|
||||||
<th class="px-6 py-2">{{ t('users.name') }}</th>
|
class="text-secondary border-b border-dividerDark text-sm text-left bg-primaryLight"
|
||||||
<th class="px-6 py-2">{{ t('users.email') }}</th>
|
>
|
||||||
<th class="px-6 py-2">{{ t('users.date') }}</th>
|
<th class="px-6 py-2">{{ t('users.id') }}</th>
|
||||||
<!-- Empty header for Action Button -->
|
<th class="px-6 py-2">{{ t('users.name') }}</th>
|
||||||
<th class="w-20 px-6 py-2"></th>
|
<th class="px-6 py-2">{{ t('users.email') }}</th>
|
||||||
|
<th class="px-6 py-2">{{ t('users.date') }}</th>
|
||||||
|
<!-- Empty header for Action Button -->
|
||||||
|
<th class="px-6 py-2"></th>
|
||||||
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #empty-state>
|
<template #body="{ list }">
|
||||||
<td colspan="6">
|
<tr
|
||||||
<span class="flex justify-center p-3">
|
v-for="user in list"
|
||||||
{{ error ? t('users.load_list_error') : t('users.no_users') }}
|
:key="user.uid"
|
||||||
</span>
|
class="text-secondaryDark hover:bg-divider hover:cursor-pointer rounded-xl"
|
||||||
</td>
|
@click="goToUserDetails(user.uid)"
|
||||||
</template>
|
>
|
||||||
|
<td class="py-2 px-7 max-w-[8rem] truncate">
|
||||||
|
{{ user.uid }}
|
||||||
|
</td>
|
||||||
|
|
||||||
<template #body="{ row: user }">
|
<td class="py-2 px-7">
|
||||||
<td class="py-2 px-7 max-w-[8rem] truncate">
|
<div class="flex items-center space-x-2">
|
||||||
{{ user.uid }}
|
<span>
|
||||||
</td>
|
{{ user.displayName ?? t('users.unnamed') }}
|
||||||
|
</span>
|
||||||
|
|
||||||
<td class="py-2 px-7">
|
<span
|
||||||
<div class="flex items-center space-x-2">
|
v-if="user.isAdmin"
|
||||||
<span>
|
class="text-xs font-medium px-3 py-0.5 rounded-full bg-green-900 text-green-300"
|
||||||
{{ user.displayName ?? t('users.unnamed') }}
|
>
|
||||||
</span>
|
{{ t('users.admin') }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
<span
|
<td class="py-2 px-7">
|
||||||
v-if="user.isAdmin"
|
{{ user.email }}
|
||||||
class="text-xs font-medium px-3 py-0.5 rounded-full bg-green-900 text-green-300"
|
</td>
|
||||||
>
|
|
||||||
{{ t('users.admin') }}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
<td class="py-2 px-7 truncate">
|
<td class="py-2 px-7">
|
||||||
{{ user.email }}
|
{{ getCreatedDate(user.createdOn) }}
|
||||||
</td>
|
<div class="text-gray-400 text-tiny">
|
||||||
|
{{ getCreatedTime(user.createdOn) }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td class="py-2 px-7">
|
<td @click.stop>
|
||||||
{{ getCreatedDate(user.createdOn) }}
|
<div class="relative">
|
||||||
<div class="text-gray-400 text-tiny">
|
<tippy interactive trigger="click" theme="popover">
|
||||||
{{ getCreatedTime(user.createdOn) }}
|
<HoppButtonSecondary
|
||||||
</div>
|
v-tippy="{ theme: 'tooltip' }"
|
||||||
</td>
|
:icon="IconMoreHorizontal"
|
||||||
|
/>
|
||||||
<td @click.stop class="flex justify-end w-20">
|
<template #content="{ hide }">
|
||||||
<div class="mt-2 mr-5">
|
<div
|
||||||
<tippy interactive trigger="click" theme="popover">
|
ref="tippyActions"
|
||||||
<HoppButtonSecondary
|
class="flex flex-col focus:outline-none"
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
tabindex="0"
|
||||||
:icon="IconMoreHorizontal"
|
@keyup.escape="hide()"
|
||||||
/>
|
>
|
||||||
<template #content="{ hide }">
|
<HoppSmartItem
|
||||||
<div
|
:icon="user.isAdmin ? IconUserMinus : IconUserCheck"
|
||||||
ref="tippyActions"
|
:label="
|
||||||
class="flex flex-col focus:outline-none"
|
|
||||||
tabindex="0"
|
|
||||||
@keyup.escape="hide()"
|
|
||||||
>
|
|
||||||
<HoppSmartItem
|
|
||||||
:icon="user.isAdmin ? IconUserMinus : IconUserCheck"
|
|
||||||
:label="
|
|
||||||
user.isAdmin
|
|
||||||
? t('users.remove_admin_status')
|
|
||||||
: t('users.make_admin')
|
|
||||||
"
|
|
||||||
class="!hover:bg-emerald-600"
|
|
||||||
@click="
|
|
||||||
() => {
|
|
||||||
user.isAdmin
|
user.isAdmin
|
||||||
? confirmAdminToUser(user.uid)
|
? t('users.remove_admin_status')
|
||||||
: confirmUserToAdmin(user.uid);
|
: t('users.make_admin')
|
||||||
hide();
|
"
|
||||||
}
|
class="!hover:bg-emerald-600"
|
||||||
"
|
@click="
|
||||||
/>
|
() => {
|
||||||
<HoppSmartItem
|
user.isAdmin
|
||||||
v-if="!user.isAdmin"
|
? makeAdminToUser(user.uid)
|
||||||
:icon="IconTrash"
|
: makeUserAdmin(user.uid);
|
||||||
:label="t('users.delete_user')"
|
hide();
|
||||||
class="!hover:bg-red-600"
|
}
|
||||||
@click="
|
"
|
||||||
() => {
|
/>
|
||||||
confirmUserDeletion(user.uid);
|
<HoppSmartItem
|
||||||
hide();
|
v-if="!user.isAdmin"
|
||||||
}
|
:icon="IconTrash"
|
||||||
"
|
:label="t('users.delete_user')"
|
||||||
/>
|
class="!hover:bg-red-600"
|
||||||
</div>
|
@click="
|
||||||
</template>
|
() => {
|
||||||
</tippy>
|
deleteUser(user.uid);
|
||||||
</div>
|
hide();
|
||||||
</td>
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</tippy>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</template>
|
</template>
|
||||||
</HoppSmartTable>
|
</HoppSmartTable>
|
||||||
|
|
||||||
<!-- Actions for Selected Rows -->
|
<div v-else-if="usersList.length === 0" class="flex justify-center">
|
||||||
|
{{ t('users.no_users') }}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
v-if="selectedRows.length"
|
v-if="hasNextPage && usersList.length >= usersPerPage"
|
||||||
class="fixed m-2 bottom-0 left-40 right-0 w-min mx-auto shadow-2xl"
|
class="flex justify-center my-5 px-3 py-2 cursor-pointer font-semibold rounded-3xl bg-dividerDark hover:bg-divider transition mx-auto w-38 text-secondaryDark"
|
||||||
|
@click="fetchNextUsers"
|
||||||
>
|
>
|
||||||
<div
|
<span>{{ t('users.show_more') }}</span>
|
||||||
class="flex justify-center items-end bg-primaryLight border border-divider rounded-md mb-5"
|
<icon-lucide-chevron-down class="ml-2 text-lg" />
|
||||||
>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
:icon="IconCheck"
|
|
||||||
:label="t('state.selected', { count: selectedRows.length })"
|
|
||||||
class="py-4 border-divider rounded-r-none bg-emerald-800 text-secondaryDark"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
:icon="IconUserCheck"
|
|
||||||
:label="t('users.make_admin')"
|
|
||||||
class="py-4 border-divider border-r-1 rounded-none hover:bg-emerald-600"
|
|
||||||
@click="confirmUsersToAdmin = true"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
:icon="IconUserMinus"
|
|
||||||
:label="t('users.remove_admin_status')"
|
|
||||||
class="py-4 border-divider border-r-1 rounded-none hover:bg-orange-500"
|
|
||||||
@click="confirmAdminsToUsers = true"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
:icon="IconTrash"
|
|
||||||
:label="t('users.delete_users')"
|
|
||||||
class="py-4 border-divider rounded-none hover:bg-red-500"
|
|
||||||
@click="confirmUsersDeletion = true"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
:icon="IconX"
|
|
||||||
:label="t('state.clear_selection')"
|
|
||||||
class="py-4 border-divider rounded-l-none text-secondaryDark bg-red-600 hover:bg-red-500"
|
|
||||||
@click="selectedRows.splice(0, selectedRows.length)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -208,70 +151,46 @@
|
|||||||
@send-invite="sendInvite"
|
@send-invite="sendInvite"
|
||||||
/>
|
/>
|
||||||
<HoppSmartConfirmModal
|
<HoppSmartConfirmModal
|
||||||
:show="confirmUsersToAdmin"
|
:show="confirmDeletion"
|
||||||
:title="
|
:title="t('users.confirm_user_deletion')"
|
||||||
AreMultipleUsersSelected
|
@hide-modal="confirmDeletion = false"
|
||||||
? t('state.confirm_users_to_admin')
|
@resolve="deleteUserMutation(deleteUserUID)"
|
||||||
: t('state.confirm_user_to_admin')
|
|
||||||
"
|
|
||||||
@hide-modal="resetConfirmUserToAdmin"
|
|
||||||
@resolve="makeUsersToAdmin(usersToAdminUID)"
|
|
||||||
/>
|
/>
|
||||||
<HoppSmartConfirmModal
|
<HoppSmartConfirmModal
|
||||||
:show="confirmAdminsToUsers"
|
:show="confirmUserToAdmin"
|
||||||
:title="
|
:title="t('users.confirm_user_to_admin')"
|
||||||
AreMultipleUsersSelectedToAdmin
|
@hide-modal="confirmUserToAdmin = false"
|
||||||
? t('state.confirm_admins_to_users')
|
@resolve="makeUserAdminMutation(userToAdminUID)"
|
||||||
: t('state.confirm_admin_to_user')
|
|
||||||
"
|
|
||||||
@hide-modal="resetConfirmAdminToUser"
|
|
||||||
@resolve="makeAdminsToUsers(adminsToUserUID)"
|
|
||||||
/>
|
/>
|
||||||
<HoppSmartConfirmModal
|
<HoppSmartConfirmModal
|
||||||
:show="confirmUsersDeletion"
|
:show="confirmAdminToUser"
|
||||||
:title="
|
:title="t('users.confirm_admin_to_user')"
|
||||||
AreMultipleUsersSelectedForDeletion
|
@hide-modal="confirmAdminToUser = false"
|
||||||
? t('state.confirm_users_deletion')
|
@resolve="makeAdminToUserMutation(adminToUserUID)"
|
||||||
: t('state.confirm_user_deletion')
|
|
||||||
"
|
|
||||||
@hide-modal="resetConfirmUserDeletion"
|
|
||||||
@resolve="deleteUsers(deleteUserUID)"
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useMutation, useQuery } from '@urql/vue';
|
import { useMutation } from '@urql/vue';
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { computed, onUnmounted, ref, watch } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useI18n } from '~/composables/i18n';
|
import { useI18n } from '~/composables/i18n';
|
||||||
import { useToast } from '~/composables/toast';
|
import { useToast } from '~/composables/toast';
|
||||||
import { usePagedQuery } from '~/composables/usePagedQuery';
|
import { usePagedQuery } from '~/composables/usePagedQuery';
|
||||||
import {
|
|
||||||
DemoteUsersByAdminDocument,
|
|
||||||
InviteNewUserDocument,
|
|
||||||
MakeUsersAdminDocument,
|
|
||||||
MetricsDocument,
|
|
||||||
RemoveUsersByAdminDocument,
|
|
||||||
UserInfoQuery,
|
|
||||||
UsersListQuery,
|
|
||||||
UsersListV2Document,
|
|
||||||
} from '~/helpers/backend/graphql';
|
|
||||||
import {
|
|
||||||
ADMIN_CANNOT_BE_DELETED,
|
|
||||||
DELETE_USER_FAILED_ONLY_ONE_ADMIN,
|
|
||||||
USER_ALREADY_INVITED,
|
|
||||||
} from '~/helpers/errors';
|
|
||||||
import IconCheck from '~icons/lucide/check';
|
|
||||||
import IconLeft from '~icons/lucide/chevron-left';
|
|
||||||
import IconRight from '~icons/lucide/chevron-right';
|
|
||||||
import IconMoreHorizontal from '~icons/lucide/more-horizontal';
|
import IconMoreHorizontal from '~icons/lucide/more-horizontal';
|
||||||
import IconTrash from '~icons/lucide/trash';
|
import IconTrash from '~icons/lucide/trash';
|
||||||
import IconUserCheck from '~icons/lucide/user-check';
|
import IconUserCheck from '~icons/lucide/user-check';
|
||||||
import IconUserMinus from '~icons/lucide/user-minus';
|
import IconUserMinus from '~icons/lucide/user-minus';
|
||||||
import IconAddUser from '~icons/lucide/user-plus';
|
import IconAddUser from '~icons/lucide/user-plus';
|
||||||
import IconX from '~icons/lucide/x';
|
import {
|
||||||
|
InviteNewUserDocument,
|
||||||
|
MakeUserAdminDocument,
|
||||||
|
RemoveUserAsAdminDocument,
|
||||||
|
RemoveUserByAdminDocument,
|
||||||
|
UsersListDocument,
|
||||||
|
} from '~/helpers/backend/graphql';
|
||||||
|
|
||||||
// Get Proper Date Formats
|
// Get Proper Date Formats
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
@@ -280,165 +199,25 @@ const toast = useToast();
|
|||||||
const getCreatedDate = (date: string) => format(new Date(date), 'dd-MM-yyyy');
|
const getCreatedDate = (date: string) => format(new Date(date), 'dd-MM-yyyy');
|
||||||
const getCreatedTime = (date: string) => format(new Date(date), 'hh:mm a');
|
const getCreatedTime = (date: string) => format(new Date(date), 'hh:mm a');
|
||||||
|
|
||||||
// Table Headings
|
|
||||||
const headings = [
|
|
||||||
{ key: 'uid', label: t('users.id') },
|
|
||||||
{ key: 'displayName', label: t('users.name') },
|
|
||||||
{ key: 'email', label: t('users.email') },
|
|
||||||
{ key: 'createdOn', label: t('users.date') },
|
|
||||||
{ key: '', label: '' },
|
|
||||||
];
|
|
||||||
|
|
||||||
// Get Paginated Results of all the users in the infra
|
// Get Paginated Results of all the users in the infra
|
||||||
const usersPerPage = 20;
|
const usersPerPage = 20;
|
||||||
const {
|
const {
|
||||||
fetching,
|
fetching,
|
||||||
error,
|
error,
|
||||||
refetch,
|
goToNextPage: fetchNextUsers,
|
||||||
list: usersList,
|
list: usersList,
|
||||||
|
hasNextPage,
|
||||||
} = usePagedQuery(
|
} = usePagedQuery(
|
||||||
UsersListV2Document,
|
UsersListDocument,
|
||||||
(x) => x.infra.allUsersV2,
|
(x) => x.infra.allUsers,
|
||||||
|
(x) => x.uid,
|
||||||
usersPerPage,
|
usersPerPage,
|
||||||
{ searchString: '', take: usersPerPage, skip: 0 }
|
{ cursor: undefined, take: usersPerPage }
|
||||||
);
|
);
|
||||||
|
|
||||||
// Selected Rows
|
|
||||||
const selectedRows = ref<UsersListQuery['infra']['allUsers']>([]);
|
|
||||||
|
|
||||||
// Ensure this variable is declared outside the debounce function
|
|
||||||
let debounceTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
||||||
|
|
||||||
let toastTimeout: ReturnType<typeof setTimeout> | null = null;
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
if (debounceTimeout) {
|
|
||||||
clearTimeout(debounceTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toastTimeout) {
|
|
||||||
clearTimeout(toastTimeout);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Debounce Function
|
|
||||||
const debounce = (func: () => void, delay: number) => {
|
|
||||||
if (debounceTimeout) clearTimeout(debounceTimeout);
|
|
||||||
debounceTimeout = setTimeout(func, delay);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Search
|
|
||||||
|
|
||||||
const query = ref('');
|
|
||||||
// Query which is sent to the backend after debouncing
|
|
||||||
const searchQuery = ref('');
|
|
||||||
|
|
||||||
const handleSearch = async (input: string) => {
|
|
||||||
searchQuery.value = input;
|
|
||||||
|
|
||||||
if (input.length === 0) {
|
|
||||||
await refetch({
|
|
||||||
searchString: '',
|
|
||||||
take: usersPerPage,
|
|
||||||
skip: (page.value - 1) * usersPerPage,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// If search query is present, fetch all the users filtered by the search query
|
|
||||||
await refetch({ searchString: input, take: usersCount.value!, skip: 0 });
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the page to 1 when the search query changes
|
|
||||||
page.value = 1;
|
|
||||||
};
|
|
||||||
|
|
||||||
watch(query, () => {
|
|
||||||
if (query.value.length === 0) {
|
|
||||||
handleSearch(query.value);
|
|
||||||
} else {
|
|
||||||
debounce(() => {
|
|
||||||
handleSearch(query.value);
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Final Users List after Search and Pagination operations
|
|
||||||
const finalUsersList = computed(() =>
|
|
||||||
// If search query is present, filter the list based on the search query and return the paginated results
|
|
||||||
// Else just return the paginated results directly
|
|
||||||
searchQuery.value.length > 0
|
|
||||||
? usersList.value.slice(
|
|
||||||
(page.value - 1) * usersPerPage,
|
|
||||||
page.value * usersPerPage
|
|
||||||
)
|
|
||||||
: usersList.value
|
|
||||||
);
|
|
||||||
|
|
||||||
// Spinner
|
|
||||||
const showSpinner = ref(false);
|
|
||||||
|
|
||||||
watch(fetching, (fetching) => {
|
|
||||||
if (fetching) {
|
|
||||||
showSpinner.value = true;
|
|
||||||
debounce(() => {
|
|
||||||
showSpinner.value = false;
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Pagination
|
|
||||||
enum PageDirection {
|
|
||||||
Previous,
|
|
||||||
Next,
|
|
||||||
}
|
|
||||||
|
|
||||||
const page = ref(1);
|
|
||||||
const { data } = useQuery({ query: MetricsDocument });
|
|
||||||
const usersCount = computed(() => data?.value?.infra.usersCount);
|
|
||||||
|
|
||||||
const changePage = (direction: PageDirection) => {
|
|
||||||
const isPrevious = direction === PageDirection.Previous;
|
|
||||||
|
|
||||||
const isValidPreviousAction = isPrevious && page.value > 1;
|
|
||||||
const isValidNextAction = !isPrevious && page.value < totalPages.value;
|
|
||||||
|
|
||||||
if (isValidNextAction || isValidPreviousAction) {
|
|
||||||
page.value += isPrevious ? -1 : 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const totalPages = computed(() => {
|
|
||||||
if (!usersCount.value) return 0;
|
|
||||||
if (query.value.length > 0) {
|
|
||||||
return Math.ceil(usersList.value.length / usersPerPage);
|
|
||||||
}
|
|
||||||
return Math.ceil(usersCount.value / usersPerPage);
|
|
||||||
});
|
|
||||||
|
|
||||||
watch(page, async () => {
|
|
||||||
if (page.value < 1 || page.value > totalPages.value) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Show spinner when moving to a different page when search query is present
|
|
||||||
else if (query.value.length > 0) {
|
|
||||||
showSpinner.value = true;
|
|
||||||
debounce(() => (showSpinner.value = false), 500);
|
|
||||||
} else {
|
|
||||||
await refetch({
|
|
||||||
searchString: '',
|
|
||||||
take: usersPerPage,
|
|
||||||
skip: (page.value - 1) * usersPerPage,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Go to Individual User Details Page
|
|
||||||
const router = useRouter();
|
|
||||||
const goToUserDetails = (user: UserInfoQuery['infra']['userInfo']) =>
|
|
||||||
router.push('/users/' + user.uid);
|
|
||||||
|
|
||||||
// Send Invitation through Email
|
// Send Invitation through Email
|
||||||
const showInviteUserModal = ref(false);
|
|
||||||
const sendInvitation = useMutation(InviteNewUserDocument);
|
const sendInvitation = useMutation(InviteNewUserDocument);
|
||||||
|
const showInviteUserModal = ref(false);
|
||||||
|
|
||||||
const sendInvite = async (email: string) => {
|
const sendInvite = async (email: string) => {
|
||||||
if (!email.trim()) {
|
if (!email.trim()) {
|
||||||
@@ -448,172 +227,104 @@ const sendInvite = async (email: string) => {
|
|||||||
const variables = { inviteeEmail: email.trim() };
|
const variables = { inviteeEmail: email.trim() };
|
||||||
const result = await sendInvitation.executeMutation(variables);
|
const result = await sendInvitation.executeMutation(variables);
|
||||||
if (result.error) {
|
if (result.error) {
|
||||||
if (result.error.message === USER_ALREADY_INVITED)
|
toast.error(t('state.email_failure'));
|
||||||
toast.error(t('state.user_already_invited'));
|
|
||||||
else toast.error(t('state.email_failure'));
|
|
||||||
} else {
|
} else {
|
||||||
toast.success(t('state.email_success'));
|
toast.success(t('state.email_success'));
|
||||||
showInviteUserModal.value = false;
|
showInviteUserModal.value = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make Multiple Users Admin
|
// Go to Individual User Details Page
|
||||||
const confirmUsersToAdmin = ref(false);
|
const router = useRouter();
|
||||||
const usersToAdminUID = ref<string | null>(null);
|
const goToUserDetails = (uid: string) => router.push('/users/' + uid);
|
||||||
const usersToAdmin = useMutation(MakeUsersAdminDocument);
|
|
||||||
|
|
||||||
const AreMultipleUsersSelected = computed(() => selectedRows.value.length > 1);
|
// User Deletion
|
||||||
|
const userDeletion = useMutation(RemoveUserByAdminDocument);
|
||||||
const confirmUserToAdmin = (id: string | null) => {
|
const confirmDeletion = ref(false);
|
||||||
confirmUsersToAdmin.value = true;
|
|
||||||
usersToAdminUID.value = id;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Resets variables if user cancels the confirmation
|
|
||||||
const resetConfirmUserToAdmin = () => {
|
|
||||||
confirmUsersToAdmin.value = false;
|
|
||||||
usersToAdminUID.value = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const makeUsersToAdmin = async (id: string | null) => {
|
|
||||||
const userUIDs = id ? [id] : selectedRows.value.map((user) => user.uid);
|
|
||||||
const variables = { userUIDs };
|
|
||||||
const result = await usersToAdmin.executeMutation(variables);
|
|
||||||
|
|
||||||
if (result.error) {
|
|
||||||
toast.error(
|
|
||||||
id ? t('state.admin_failure') : t('state.users_to_admin_failure')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
toast.success(
|
|
||||||
id ? t('state.admin_success') : t('state.users_to_admin_success')
|
|
||||||
);
|
|
||||||
usersList.value = usersList.value.map((user) => ({
|
|
||||||
...user,
|
|
||||||
isAdmin: userUIDs.includes(user.uid) ? true : user.isAdmin,
|
|
||||||
}));
|
|
||||||
selectedRows.value.splice(0, selectedRows.value.length);
|
|
||||||
}
|
|
||||||
confirmUsersToAdmin.value = false;
|
|
||||||
usersToAdminUID.value = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Remove Admin Status from Multiple Users
|
|
||||||
const confirmAdminsToUsers = ref(false);
|
|
||||||
const adminsToUserUID = ref<string | null>(null);
|
|
||||||
const adminsToUser = useMutation(DemoteUsersByAdminDocument);
|
|
||||||
|
|
||||||
const confirmAdminToUser = (id: string | null) => {
|
|
||||||
confirmAdminsToUsers.value = true;
|
|
||||||
adminsToUserUID.value = id;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Resets variables if user cancels the confirmation
|
|
||||||
const resetConfirmAdminToUser = () => {
|
|
||||||
confirmAdminsToUsers.value = false;
|
|
||||||
adminsToUserUID.value = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
const AreMultipleUsersSelectedToAdmin = computed(
|
|
||||||
() => selectedRows.value.length > 1
|
|
||||||
);
|
|
||||||
|
|
||||||
const makeAdminsToUsers = async (id: string | null) => {
|
|
||||||
const userUIDs = id ? [id] : selectedRows.value.map((user) => user.uid);
|
|
||||||
|
|
||||||
const variables = { userUIDs };
|
|
||||||
const result = await adminsToUser.executeMutation(variables);
|
|
||||||
if (result.error) {
|
|
||||||
toast.error(
|
|
||||||
id
|
|
||||||
? t('state.remove_admin_failure')
|
|
||||||
: t('state.remove_admin_from_users_failure')
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
toast.success(
|
|
||||||
id
|
|
||||||
? t('state.remove_admin_success')
|
|
||||||
: t('state.remove_admin_from_users_success')
|
|
||||||
);
|
|
||||||
usersList.value = usersList.value.map((user) => ({
|
|
||||||
...user,
|
|
||||||
isAdmin: userUIDs.includes(user.uid) ? false : user.isAdmin,
|
|
||||||
}));
|
|
||||||
|
|
||||||
selectedRows.value.splice(0, selectedRows.value.length);
|
|
||||||
}
|
|
||||||
confirmAdminsToUsers.value = false;
|
|
||||||
adminsToUserUID.value = null;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Delete Multiple Users
|
|
||||||
const confirmUsersDeletion = ref(false);
|
|
||||||
const deleteUserUID = ref<string | null>(null);
|
const deleteUserUID = ref<string | null>(null);
|
||||||
const usersDeletion = useMutation(RemoveUsersByAdminDocument);
|
|
||||||
|
|
||||||
const confirmUserDeletion = (id: string | null) => {
|
const deleteUserMutation = async (id: string | null) => {
|
||||||
confirmUsersDeletion.value = true;
|
if (!id) {
|
||||||
|
confirmDeletion.value = false;
|
||||||
|
toast.error(t('state.delete_user_failure'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const variables = { uid: id };
|
||||||
|
const result = await userDeletion.executeMutation(variables);
|
||||||
|
if (result.error) {
|
||||||
|
toast.error(t('state.delete_user_failure'));
|
||||||
|
} else {
|
||||||
|
toast.success(t('state.delete_user_success'));
|
||||||
|
usersList.value = usersList.value.filter((user) => user.uid !== id);
|
||||||
|
}
|
||||||
|
confirmDeletion.value = false;
|
||||||
|
deleteUserUID.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Make User Admin
|
||||||
|
const userToAdmin = useMutation(MakeUserAdminDocument);
|
||||||
|
const confirmUserToAdmin = ref(false);
|
||||||
|
const userToAdminUID = ref<string | null>(null);
|
||||||
|
|
||||||
|
const makeUserAdmin = (id: string) => {
|
||||||
|
confirmUserToAdmin.value = true;
|
||||||
|
userToAdminUID.value = id;
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeUserAdminMutation = async (id: string | null) => {
|
||||||
|
if (!id) {
|
||||||
|
confirmUserToAdmin.value = false;
|
||||||
|
toast.error(t('state.admin_failure'));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const variables = { uid: id };
|
||||||
|
const result = await userToAdmin.executeMutation(variables);
|
||||||
|
if (result.error) {
|
||||||
|
toast.error(t('state.admin_failure'));
|
||||||
|
} else {
|
||||||
|
toast.success(t('state.admin_success'));
|
||||||
|
usersList.value = usersList.value.map((user) => ({
|
||||||
|
...user,
|
||||||
|
isAdmin: user.uid === id ? true : user.isAdmin,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
confirmUserToAdmin.value = false;
|
||||||
|
userToAdminUID.value = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Remove Admin Status from a current Admin
|
||||||
|
const adminToUser = useMutation(RemoveUserAsAdminDocument);
|
||||||
|
const confirmAdminToUser = ref(false);
|
||||||
|
const adminToUserUID = ref<string | null>(null);
|
||||||
|
|
||||||
|
const makeAdminToUser = (id: string) => {
|
||||||
|
confirmAdminToUser.value = true;
|
||||||
|
adminToUserUID.value = id;
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteUser = (id: string) => {
|
||||||
|
confirmDeletion.value = true;
|
||||||
deleteUserUID.value = id;
|
deleteUserUID.value = id;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Resets variables if user cancels the confirmation
|
const makeAdminToUserMutation = async (id: string | null) => {
|
||||||
const resetConfirmUserDeletion = () => {
|
if (!id) {
|
||||||
confirmUsersDeletion.value = false;
|
confirmAdminToUser.value = false;
|
||||||
deleteUserUID.value = null;
|
toast.error(t('state.remove_admin_failure'));
|
||||||
};
|
return;
|
||||||
|
|
||||||
const AreMultipleUsersSelectedForDeletion = computed(
|
|
||||||
() => selectedRows.value.length > 1
|
|
||||||
);
|
|
||||||
|
|
||||||
const deleteUsers = async (id: string | null) => {
|
|
||||||
const userUIDs = id ? [id] : selectedRows.value.map((user) => user.uid);
|
|
||||||
const variables = { userUIDs };
|
|
||||||
const result = await usersDeletion.executeMutation(variables);
|
|
||||||
|
|
||||||
if (result.error) {
|
|
||||||
const errorMessage =
|
|
||||||
result.error.message === DELETE_USER_FAILED_ONLY_ONE_ADMIN
|
|
||||||
? t('state.delete_user_failed_only_one_admin')
|
|
||||||
: id
|
|
||||||
? t('state.delete_user_failure')
|
|
||||||
: t('state.delete_users_failure');
|
|
||||||
toast.error(errorMessage);
|
|
||||||
} else {
|
|
||||||
const deletedUsers = result.data?.removeUsersByAdmin || [];
|
|
||||||
const deletedIDs = deletedUsers
|
|
||||||
.filter((user) => user.isDeleted)
|
|
||||||
.map((user) => user.userUID);
|
|
||||||
|
|
||||||
const isAdminError = deletedUsers.some(
|
|
||||||
(user) => user.errorMessage === ADMIN_CANNOT_BE_DELETED
|
|
||||||
);
|
|
||||||
|
|
||||||
usersList.value = usersList.value.filter(
|
|
||||||
(user) => !deletedIDs.includes(user.uid)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isAdminError) {
|
|
||||||
toast.success(
|
|
||||||
t('state.delete_some_users_success', { count: deletedIDs.length })
|
|
||||||
);
|
|
||||||
toast.error(
|
|
||||||
t('state.delete_some_users_failure', {
|
|
||||||
count: deletedUsers.length - deletedIDs.length,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
toastTimeout = setTimeout(() => {
|
|
||||||
toast.error(t('state.remove_admin_for_deletion'));
|
|
||||||
}, 2000);
|
|
||||||
} else {
|
|
||||||
toast.success(
|
|
||||||
id ? t('state.delete_user_success') : t('state.delete_users_success')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
selectedRows.value.splice(0, selectedRows.value.length);
|
|
||||||
}
|
}
|
||||||
confirmUsersDeletion.value = false;
|
const variables = { uid: id };
|
||||||
deleteUserUID.value = null;
|
const result = await adminToUser.executeMutation(variables);
|
||||||
|
if (result.error) {
|
||||||
|
toast.error(t('state.remove_admin_failure'));
|
||||||
|
} else {
|
||||||
|
toast.success(t('state.remove_admin_success'));
|
||||||
|
usersList.value = usersList.value.map((user) => ({
|
||||||
|
...user,
|
||||||
|
isAdmin: user.uid === id ? false : user.isAdmin,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
confirmAdminToUser.value = false;
|
||||||
|
adminToUserUID.value = null;
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -6,29 +6,24 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3 class="text-lg font-bold text-accentContrast pt-6 pb-4">
|
<h3 class="text-lg font-bold text-accentContrast py-6">
|
||||||
{{ t('users.pending_invites') }}
|
{{ t('users.invited_users') }}
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="relative py-2 overflow-x-auto">
|
<div class="py-2 overflow-x-auto">
|
||||||
<div v-if="fetching" class="flex justify-center">
|
<div v-if="fetching" class="flex justify-center">
|
||||||
<HoppSmartSpinner />
|
<HoppSmartSpinner />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="error">
|
<div v-else-if="error" class="text-xl">
|
||||||
{{ t('users.invite_load_list_error') }}
|
{{ t('users.invite_load_list_error') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-else-if="pendingInvites?.length === 0">
|
|
||||||
{{ t('users.no_invite') }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<HoppSmartTable
|
<HoppSmartTable
|
||||||
v-else
|
v-else-if="invitedUsers?.length"
|
||||||
|
:list="invitedUsers"
|
||||||
:headings="headings"
|
:headings="headings"
|
||||||
:list="pendingInvites"
|
|
||||||
:selected-rows="selectedRows"
|
|
||||||
>
|
>
|
||||||
<template #invitedOn="{ item }">
|
<template #invitedOn="{ item }">
|
||||||
<div v-if="item" class="pr-2 truncate">
|
<div v-if="item" class="pr-2 truncate">
|
||||||
@@ -42,91 +37,32 @@
|
|||||||
</div>
|
</div>
|
||||||
<span v-else> - </span>
|
<span v-else> - </span>
|
||||||
</template>
|
</template>
|
||||||
<template #action="{ item }">
|
|
||||||
<div v-if="item" class="my-1 mr-2">
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-if="xlAndLarger"
|
|
||||||
:icon="IconTrash"
|
|
||||||
:label="t('users.revoke_invitation')"
|
|
||||||
class="text-secondaryDark bg-red-500 hover:bg-red-600"
|
|
||||||
@click="confirmInviteDeletion(item.inviteeEmail)"
|
|
||||||
/>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
v-else
|
|
||||||
v-tippy="{ theme: 'tooltip' }"
|
|
||||||
:icon="IconTrash"
|
|
||||||
:title="t('users.revoke_invitation')"
|
|
||||||
class="ml-2 !text-red-500"
|
|
||||||
@click="confirmInviteDeletion(item.inviteeEmail)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</HoppSmartTable>
|
</HoppSmartTable>
|
||||||
|
|
||||||
<div
|
<div v-else class="text-lg">{{ t('users.no_invite') }}</div>
|
||||||
v-if="selectedRows.length"
|
|
||||||
class="fixed m-2 bottom-0 left-40 right-0 w-min mx-auto shadow-2xl"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex justify-center items-end bg-primaryLight border border-divider rounded-md mb-5"
|
|
||||||
>
|
|
||||||
<HoppButtonSecondary
|
|
||||||
:label="t('state.selected', { count: selectedRows.length })"
|
|
||||||
class="py-4 border-divider rounded-r-none bg-emerald-800 text-secondaryDark"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<HoppButtonSecondary
|
|
||||||
:icon="IconTrash"
|
|
||||||
:label="t('users.revoke_invitation')"
|
|
||||||
class="py-4 border-divider rounded-l-none hover:bg-red-500"
|
|
||||||
@click="confirmDeletion = true"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<HoppSmartConfirmModal
|
|
||||||
:show="confirmDeletion"
|
|
||||||
:title="
|
|
||||||
selectedRows.length > 0
|
|
||||||
? t('state.confirm_delete_invites')
|
|
||||||
: t('state.confirm_delete_invite')
|
|
||||||
"
|
|
||||||
@hide-modal="confirmDeletion = false"
|
|
||||||
@resolve="deleteInvitation(inviteToBeDeleted)"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useMutation, useQuery } from '@urql/vue';
|
import { useQuery } from '@urql/vue';
|
||||||
import { breakpointsTailwind, useBreakpoints } from '@vueuse/core';
|
|
||||||
import { format } from 'date-fns';
|
import { format } from 'date-fns';
|
||||||
import { computed, ref } from 'vue';
|
import { computed } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useI18n } from '~/composables/i18n';
|
import { useI18n } from '~/composables/i18n';
|
||||||
import { useToast } from '~/composables/toast';
|
import { InvitedUsersDocument } from '~/helpers/backend/graphql';
|
||||||
import IconTrash from '~icons/lucide/trash';
|
|
||||||
import {
|
|
||||||
InvitedUsersDocument,
|
|
||||||
InvitedUsersQuery,
|
|
||||||
RevokeUserInvitationsByAdminDocument,
|
|
||||||
} from '../../helpers/backend/graphql';
|
|
||||||
|
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
const toast = useToast();
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const breakpoints = useBreakpoints(breakpointsTailwind);
|
|
||||||
const xlAndLarger = breakpoints.greater('xl');
|
|
||||||
|
|
||||||
// Get Proper Date Formats
|
// Get Proper Date Formats
|
||||||
const getCreatedDate = (date: string) => format(new Date(date), 'dd-MM-yyyy');
|
const getCreatedDate = (date: string) => format(new Date(date), 'dd-MM-yyyy');
|
||||||
const getCreatedTime = (date: string) => format(new Date(date), 'hh:mm a');
|
const getCreatedTime = (date: string) => format(new Date(date), 'hh:mm a');
|
||||||
|
|
||||||
// Get Invited Users
|
// Get Invited Users
|
||||||
const { fetching, error, data } = useQuery({ query: InvitedUsersDocument });
|
const { fetching, error, data } = useQuery({ query: InvitedUsersDocument });
|
||||||
|
const invitedUsers = computed(() => data?.value?.infra.invitedUsers);
|
||||||
|
|
||||||
// Table Headings
|
// Table Headings
|
||||||
const headings = [
|
const headings = [
|
||||||
@@ -134,56 +70,5 @@ const headings = [
|
|||||||
{ key: 'adminEmail', label: t('users.admin_email') },
|
{ key: 'adminEmail', label: t('users.admin_email') },
|
||||||
{ key: 'inviteeEmail', label: t('users.invitee_email') },
|
{ key: 'inviteeEmail', label: t('users.invitee_email') },
|
||||||
{ key: 'invitedOn', label: t('users.invited_on') },
|
{ key: 'invitedOn', label: t('users.invited_on') },
|
||||||
{ key: 'action', label: 'Action' },
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Selected Rows
|
|
||||||
const selectedRows = ref<InvitedUsersQuery['infra']['invitedUsers']>([]);
|
|
||||||
|
|
||||||
// Invited Users
|
|
||||||
const pendingInvites = computed({
|
|
||||||
get: () => data.value?.infra.invitedUsers,
|
|
||||||
set: (value) => {
|
|
||||||
if (!value) return;
|
|
||||||
data.value!.infra.invitedUsers = value;
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Delete Invite
|
|
||||||
const confirmDeletion = ref(false);
|
|
||||||
const inviteToBeDeleted = ref<string | null>(null);
|
|
||||||
const deleteInvitationMutation = useMutation(
|
|
||||||
RevokeUserInvitationsByAdminDocument
|
|
||||||
);
|
|
||||||
|
|
||||||
const confirmInviteDeletion = (inviteeEmail: string | null) => {
|
|
||||||
confirmDeletion.value = true;
|
|
||||||
inviteToBeDeleted.value = inviteeEmail;
|
|
||||||
};
|
|
||||||
|
|
||||||
const deleteInvitation = async (email: string | null) => {
|
|
||||||
const inviteeEmails = email
|
|
||||||
? [email]
|
|
||||||
: selectedRows.value.map((row) => row.inviteeEmail);
|
|
||||||
|
|
||||||
const variables = { inviteeEmails };
|
|
||||||
const result = await deleteInvitationMutation.executeMutation(variables);
|
|
||||||
|
|
||||||
if (result.error) {
|
|
||||||
email
|
|
||||||
? toast.error(t('state.delete_invite_failure'))
|
|
||||||
: toast.error(t('state.delete_invites_failure'));
|
|
||||||
} else {
|
|
||||||
pendingInvites.value = pendingInvites.value?.filter(
|
|
||||||
(user) => !inviteeEmails.includes(user.inviteeEmail)
|
|
||||||
);
|
|
||||||
selectedRows.value.splice(0, selectedRows.value.length);
|
|
||||||
email
|
|
||||||
? toast.success(t('state.delete_invite_success'))
|
|
||||||
: toast.success(t('state.delete_invites_success'));
|
|
||||||
}
|
|
||||||
|
|
||||||
confirmDeletion.value = false;
|
|
||||||
inviteToBeDeleted.value = null;
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
6175
pnpm-lock.yaml
generated
6175
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user