feat(sh-admin): introducing infra-tokens to admin dashboard (#4202)
Co-authored-by: nivedin <nivedinp@gmail.com>
This commit is contained in:
committed by
GitHub
parent
783d911f8d
commit
c24d5c5302
39
packages/hoppscotch-sh-admin/assets/images/pack.svg
Normal file
39
packages/hoppscotch-sh-admin/assets/images/pack.svg
Normal file
@@ -0,0 +1,39 @@
|
||||
<svg width="145" height="120" viewBox="0 0 145 120" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M130.648 59.7265C130.648 72.9542 126.219 85.3837 118.837 95.1904C114.748 100.55 109.865 105.225 104.187 108.874C95.1014 114.918 84.0855 118.339 72.3882 118.339C40.249 118.453 14.1288 92.2256 14.1288 59.7265C14.1288 27.3414 40.1355 1 72.3882 1C84.0855 1 94.9879 4.42096 104.187 10.4647C109.865 14.1137 114.748 18.789 118.837 24.1485C126.219 34.0693 130.648 46.3847 130.648 59.7265Z" fill="#1A1A1A" stroke="#3E3E3E" stroke-width="2" stroke-miterlimit="10"/>
|
||||
<path d="M28.0197 51.8744H27.3164C26.7889 51.8744 26.4372 51.7103 26.4372 51.4641C26.4372 51.2179 26.7889 51.0538 27.3164 51.0538H28.0197C28.5472 51.0538 28.8989 51.2179 28.8989 51.4641C28.8989 51.7103 28.5472 51.8744 28.0197 51.8744Z" fill="#777777"/>
|
||||
<path d="M28.0197 55.1566H27.3164C26.7889 55.1566 26.4372 54.9925 26.4372 54.7463C26.4372 54.5002 26.7889 54.3361 27.3164 54.3361H28.0197C28.5472 54.3361 28.8989 54.5002 28.8989 54.7463C28.8989 54.9925 28.5472 55.1566 28.0197 55.1566Z" fill="#777777"/>
|
||||
<path d="M28.0197 58.4388H27.3164C26.7889 58.4388 26.4372 58.2747 26.4372 58.0286C26.4372 57.7824 26.7889 57.6183 27.3164 57.6183H28.0197C28.5472 57.6183 28.8989 57.7824 28.8989 58.0286C28.8989 58.2747 28.5472 58.4388 28.0197 58.4388Z" fill="#777777"/>
|
||||
<path d="M28.0197 61.7211H27.3164C26.7889 61.7211 26.4372 61.557 26.4372 61.3108C26.4372 61.0646 26.7889 60.9005 27.3164 60.9005H28.0197C28.5472 60.9005 28.8989 61.0646 28.8989 61.3108C28.8989 61.557 28.5472 61.7211 28.0197 61.7211Z" fill="#777777"/>
|
||||
<path d="M60.119 51.8744H48.5531C48.0842 51.8744 47.7716 51.7103 47.7716 51.4641C47.7716 51.2179 48.0842 51.0538 48.5531 51.0538H60.119C60.5879 51.0538 60.9005 51.2179 60.9005 51.4641C60.9005 51.7103 60.5879 51.8744 60.119 51.8744Z" fill="white"/>
|
||||
<path d="M84.7622 61.7211H48.5265C48.0736 61.7211 47.7716 61.557 47.7716 61.3108C47.7716 61.0646 48.0736 60.9005 48.5265 60.9005H84.7622C85.2152 60.9005 85.5171 61.0646 85.5171 61.3108C85.5171 61.557 85.2152 61.7211 84.7622 61.7211Z" fill="url(#paint0_linear_595_1292)"/>
|
||||
<path d="M60.1641 55.1566H44.4052C43.9634 55.1566 43.6688 54.9925 43.6688 54.7463C43.6688 54.5002 43.9634 54.3361 44.4052 54.3361H60.1641C60.6059 54.3361 60.9005 54.5002 60.9005 54.7463C60.9005 54.9925 60.6059 55.1566 60.1641 55.1566Z" fill="#777777"/>
|
||||
<path d="M72.474 58.4388H44.4036C43.9628 58.4388 43.6688 58.2747 43.6688 58.0286C43.6688 57.7824 43.9628 57.6183 44.4036 57.6183H72.474C72.9149 57.6183 73.2088 57.7824 73.2088 58.0286C73.0618 58.2747 72.7679 58.4388 72.474 58.4388Z" fill="#777777"/>
|
||||
<path d="M84.7179 58.4388H74.008C73.5285 58.4388 73.2088 58.2747 73.2088 58.0286C73.2088 57.7824 73.5285 57.6183 74.008 57.6183H84.7179C85.1974 57.6183 85.5171 57.7824 85.5171 58.0286C85.5171 58.2747 85.1974 58.4388 84.7179 58.4388Z" fill="white"/>
|
||||
<path d="M91.3054 58.4388H87.1139C86.6482 58.4388 86.3377 58.2747 86.3377 58.0286C86.3377 57.7824 86.6482 57.6183 87.1139 57.6183H91.3054C91.7711 57.6183 92.0816 57.7824 92.0816 58.0286C92.0816 58.2747 91.7711 58.4388 91.3054 58.4388Z" fill="url(#paint1_linear_595_1292)"/>
|
||||
<path d="M1 103.569H138.853" stroke="#3E3E3E" stroke-width="2" stroke-miterlimit="10" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M97.8254 51.0538V103.569H23.3714C20.4344 103.569 18.2316 101.209 18.2316 98.4063V51.0538H97.8254Z" fill="#1A1A1A" stroke="#3E3E3E" stroke-width="1.5905" stroke-miterlimit="10" stroke-linejoin="round"/>
|
||||
<path d="M127.365 51.0538V98.4063C127.365 101.357 124.916 103.569 122.008 103.569H97.8254V51.0538H127.365Z" fill="#E7E7E7"/>
|
||||
<path d="M127.365 51.0538V98.4063C127.365 101.357 124.916 103.569 122.008 103.569H97.8254V51.0538H127.365Z" fill="#1A1A1A" stroke="#3E3E3E" stroke-width="2" stroke-miterlimit="10"/>
|
||||
<path d="M46.951 51.0538L62.6072 26.4372H142.956L126.857 51.0538H46.951Z" fill="#D9D9D9"/>
|
||||
<path d="M46.951 51.0538L62.6072 26.4372H142.956L126.857 51.0538H46.951Z" fill="#1A1A1A" stroke="#3E3E3E" stroke-width="2" stroke-miterlimit="10"/>
|
||||
<path opacity="0.3" d="M127.365 51.1976V78.9527H105.826C103.826 78.9527 102.441 77.6584 102.133 75.7889L97.8254 51.0538L127.365 51.1976Z" fill="url(#paint2_linear_595_1292)"/>
|
||||
<path d="M126.746 51.0538H97.8254L112.511 73.312C113.56 74.786 115.208 75.6705 116.856 75.6705H139.334C140.832 75.6705 141.881 73.9016 140.982 72.7224L126.746 51.0538Z" fill="#1A1A1A" stroke="#3E3E3E" stroke-width="1.5905" stroke-miterlimit="10" stroke-linejoin="round"/>
|
||||
<path d="M97.8254 51.0538L82.0597 26.4372H1L17.3607 51.0538H97.8254Z" fill="#1A1A1A" stroke="#3E3E3E" stroke-width="1.5905" stroke-miterlimit="10" stroke-linejoin="round"/>
|
||||
<path d="M57.9543 81.4144H26.9217C26.1967 81.4144 25.6166 80.8673 25.6166 80.1835C25.6166 79.4997 26.1967 78.9527 26.9217 78.9527H57.9543C58.6793 78.9527 59.2594 79.4997 59.2594 80.1835C59.1144 80.8673 58.6793 81.4144 57.9543 81.4144Z" fill="#3E3E3E"/>
|
||||
<path d="M57.9543 87.1583H26.9217C26.1967 87.1583 25.6166 86.7936 25.6166 86.3377C25.6166 85.8818 26.1967 85.5172 26.9217 85.5172H57.9543C58.6793 85.5172 59.2594 85.8818 59.2594 86.3377C59.1144 86.7936 58.6793 87.1583 57.9543 87.1583Z" fill="#3E3E3E"/>
|
||||
<path d="M41.5228 93.7227H26.9422C26.2058 93.7227 25.6166 93.358 25.6166 92.9021C25.6166 92.4462 26.2058 92.0815 26.9422 92.0815H41.5228C42.2592 92.0815 42.8483 92.4462 42.8483 92.9021C42.701 93.358 42.1119 93.7227 41.5228 93.7227Z" fill="#3E3E3E"/>
|
||||
<defs>
|
||||
<linearGradient id="paint0_linear_595_1292" x1="47.9412" y1="61.3274" x2="85.5609" y2="61.3274" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#A2A2A2"/>
|
||||
<stop offset="1" stop-color="#252525"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint1_linear_595_1292" x1="86.3761" y1="58.0035" x2="92.0805" y2="58.0035" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#9A9A9A"/>
|
||||
<stop offset="1" stop-color="#545454"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_595_1292" x1="112.602" y1="79.5253" x2="112.602" y2="54.1128" gradientUnits="userSpaceOnUse">
|
||||
<stop offset="0.00289017" stop-opacity="0"/>
|
||||
<stop offset="1"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.9 KiB |
@@ -1,4 +1,13 @@
|
||||
{
|
||||
"action": {
|
||||
"cancel": "Cancel",
|
||||
"confirm": "Confirm",
|
||||
"close": "Close",
|
||||
"delete": "Delete",
|
||||
"edit": "Edit",
|
||||
"label": "Label",
|
||||
"save": "Save"
|
||||
},
|
||||
"app": {
|
||||
"collapse_sidebar": "Collapse Sidebar",
|
||||
"continue_to_dashboard": "Continue to Dashboard",
|
||||
@@ -73,6 +82,26 @@
|
||||
"title": "Make Hoppscotch Better",
|
||||
"welcome": "Welcome to"
|
||||
},
|
||||
"infra_tokens": {
|
||||
"copy_token_warning": "Make sure to copy your infra token now. You won't be able to see it again!",
|
||||
"deletion_success": "The infra token {label} has been deleted",
|
||||
"empty": "Infra tokens are empty",
|
||||
"expired": "Expired",
|
||||
"expiration_label": "Expiration",
|
||||
"expires_on": "Expires on",
|
||||
"generate_modal_title": "New Infra Token",
|
||||
"generate_new_token": "Generate new token",
|
||||
"generate_token": "Generate Token",
|
||||
"invalid_label": "Please provide a label for the token",
|
||||
"last_used_on": "Last used on",
|
||||
"no_expiration": "No expiration",
|
||||
"no_expiration_verbose": "This token will never expire!",
|
||||
"section_description": "Manage your Hoppscotch users through APIs with Infra tokens",
|
||||
"section_title": "Infra Tokens",
|
||||
"tab_title": "Infra Tokens",
|
||||
"token_expires_on": "This token will expire on",
|
||||
"token_purpose": "Enter a label to identify this token"
|
||||
},
|
||||
"metrics": {
|
||||
"dashboard": "Dashboard",
|
||||
"no_metrics": "No metrics found",
|
||||
@@ -121,6 +150,7 @@
|
||||
"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_infra_token": "Are you sure you want to delete the infra token {tokenLabel}?",
|
||||
"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?",
|
||||
@@ -137,6 +167,7 @@
|
||||
"create_team_failure": "Failed to create workspace!!",
|
||||
"create_team_success": "Workspace created successfully!!",
|
||||
"data_sharing_failure": "Failed to update data sharing settings",
|
||||
"delete_infra_token_failure": "Something went wrong while deleting the infra token",
|
||||
"delete_invite_failure": "Failed to delete invite!!",
|
||||
"delete_invites_failure": "Failed to delete selected invites!!",
|
||||
"delete_invite_success": "Invite deleted successfully!!",
|
||||
@@ -160,8 +191,10 @@
|
||||
"enter_team_email": "Please enter email of workspace owner!!",
|
||||
"error": "Something went wrong",
|
||||
"error_auth_providers": "Unable to load auth providers",
|
||||
"generate_infra_token_failure": "Something went wrong while generating the infra token",
|
||||
"github_signin_failure": "Failed to login with Github",
|
||||
"google_signin_failure": "Failed to login with Google",
|
||||
"infra_token_label_short": "Infra Token Label character length is too short!!",
|
||||
"invalid_email": "Please enter a valid email address",
|
||||
"link_copied_to_clipboard": "Link copied to clipboard",
|
||||
"logged_out": "Logged out",
|
||||
@@ -207,6 +240,7 @@
|
||||
"sign_in_agreement": "By signing in, you are agreeing to our",
|
||||
"sign_in_options": "All sign in option",
|
||||
"sign_out": "Sign out",
|
||||
"something_went_wrong": "Something went wrong",
|
||||
"team_name_too_short": "Workspace name should be atleast 6 characters long!!",
|
||||
"user_already_invited": "Failed to send invite. User is already invited!!",
|
||||
"user_not_found": "User not found in the infra!!",
|
||||
|
||||
112
packages/hoppscotch-sh-admin/src/components.d.ts
vendored
112
packages/hoppscotch-sh-admin/src/components.d.ts
vendored
@@ -1,63 +1,67 @@
|
||||
// generated by unplugin-vue-components
|
||||
// We suggest you to commit this file into source control
|
||||
// Read more: https://github.com/vuejs/core/pull/3399
|
||||
import '@vue/runtime-core'
|
||||
import '@vue/runtime-core';
|
||||
|
||||
export {}
|
||||
export {};
|
||||
|
||||
declare module '@vue/runtime-core' {
|
||||
export interface GlobalComponents {
|
||||
AppHeader: typeof import('./components/app/Header.vue')['default']
|
||||
AppLogin: typeof import('./components/app/Login.vue')['default']
|
||||
AppLogout: typeof import('./components/app/Logout.vue')['default']
|
||||
AppModal: typeof import('./components/app/Modal.vue')['default']
|
||||
AppSidebar: typeof import('./components/app/Sidebar.vue')['default']
|
||||
AppToast: typeof import('./components/app/Toast.vue')['default']
|
||||
DashboardMetricsCard: typeof import('./components/dashboard/MetricsCard.vue')['default']
|
||||
HoppButtonPrimary: typeof import('@hoppscotch/ui')['HoppButtonPrimary']
|
||||
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary']
|
||||
HoppSmartAnchor: typeof import('@hoppscotch/ui')['HoppSmartAnchor']
|
||||
HoppSmartAutoComplete: typeof import('@hoppscotch/ui')['HoppSmartAutoComplete']
|
||||
HoppSmartCheckbox: typeof import('@hoppscotch/ui')['HoppSmartCheckbox']
|
||||
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal']
|
||||
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput']
|
||||
HoppSmartIntersection: typeof import('@hoppscotch/ui')['HoppSmartIntersection']
|
||||
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem']
|
||||
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink']
|
||||
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
|
||||
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture']
|
||||
HoppSmartPlaceholder: typeof import('@hoppscotch/ui')['HoppSmartPlaceholder']
|
||||
HoppSmartSelectWrapper: typeof import('@hoppscotch/ui')['HoppSmartSelectWrapper']
|
||||
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']
|
||||
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default']
|
||||
IconLucideCheck: typeof import('~icons/lucide/check')['default']
|
||||
IconLucideChevronDown: typeof import('~icons/lucide/chevron-down')['default']
|
||||
IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['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']
|
||||
SettingsConfigurations: typeof import('./components/settings/Configurations.vue')['default']
|
||||
SettingsDataSharing: typeof import('./components/settings/DataSharing.vue')['default']
|
||||
SettingsReset: typeof import('./components/settings/Reset.vue')['default']
|
||||
SettingsServerRestart: typeof import('./components/settings/ServerRestart.vue')['default']
|
||||
SettingsSmtpConfiguration: typeof import('./components/settings/SmtpConfiguration.vue')['default']
|
||||
SetupDataSharingAndNewsletter: typeof import('./components/setup/DataSharingAndNewsletter.vue')['default']
|
||||
TeamsAdd: typeof import('./components/teams/Add.vue')['default']
|
||||
TeamsDetails: typeof import('./components/teams/Details.vue')['default']
|
||||
TeamsInvite: typeof import('./components/teams/Invite.vue')['default']
|
||||
TeamsMembers: typeof import('./components/teams/Members.vue')['default']
|
||||
TeamsPendingInvites: typeof import('./components/teams/PendingInvites.vue')['default']
|
||||
Tippy: typeof import('vue-tippy')['Tippy']
|
||||
UiAutoResetIcon: typeof import('./components/ui/AutoResetIcon.vue')['default']
|
||||
UsersDetails: typeof import('./components/users/Details.vue')['default']
|
||||
UsersInviteModal: typeof import('./components/users/InviteModal.vue')['default']
|
||||
UsersSharedRequests: typeof import('./components/users/SharedRequests.vue')['default']
|
||||
UsersSuccessInviteModal: typeof import('./components/users/SuccessInviteModal.vue')['default']
|
||||
AppHeader: typeof import('./components/app/Header.vue')['default'];
|
||||
AppLogin: typeof import('./components/app/Login.vue')['default'];
|
||||
AppLogout: typeof import('./components/app/Logout.vue')['default'];
|
||||
AppModal: typeof import('./components/app/Modal.vue')['default'];
|
||||
AppSidebar: typeof import('./components/app/Sidebar.vue')['default'];
|
||||
AppToast: typeof import('./components/app/Toast.vue')['default'];
|
||||
DashboardMetricsCard: typeof import('./components/dashboard/MetricsCard.vue')['default'];
|
||||
HoppButtonPrimary: typeof import('@hoppscotch/ui')['HoppButtonPrimary'];
|
||||
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary'];
|
||||
HoppSmartAnchor: typeof import('@hoppscotch/ui')['HoppSmartAnchor'];
|
||||
HoppSmartAutoComplete: typeof import('@hoppscotch/ui')['HoppSmartAutoComplete'];
|
||||
HoppSmartCheckbox: typeof import('@hoppscotch/ui')['HoppSmartCheckbox'];
|
||||
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal'];
|
||||
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput'];
|
||||
HoppSmartIntersection: typeof import('@hoppscotch/ui')['HoppSmartIntersection'];
|
||||
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem'];
|
||||
HoppSmartLink: typeof import('@hoppscotch/ui')['HoppSmartLink'];
|
||||
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal'];
|
||||
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture'];
|
||||
HoppSmartPlaceholder: typeof import('@hoppscotch/ui')['HoppSmartPlaceholder'];
|
||||
HoppSmartSelectWrapper: typeof import('@hoppscotch/ui')['HoppSmartSelectWrapper'];
|
||||
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'];
|
||||
IconLucideArrowLeft: typeof import('~icons/lucide/arrow-left')['default'];
|
||||
IconLucideCheck: typeof import('~icons/lucide/check')['default'];
|
||||
IconLucideChevronDown: typeof import('~icons/lucide/chevron-down')['default'];
|
||||
IconLucideHelpCircle: typeof import('~icons/lucide/help-circle')['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'];
|
||||
SettingsConfigurations: typeof import('./components/settings/Configurations.vue')['default'];
|
||||
SettingsDataSharing: typeof import('./components/settings/DataSharing.vue')['default'];
|
||||
SettingsReset: typeof import('./components/settings/Reset.vue')['default'];
|
||||
SettingsServerRestart: typeof import('./components/settings/ServerRestart.vue')['default'];
|
||||
SettingsSmtpConfiguration: typeof import('./components/settings/SmtpConfiguration.vue')['default'];
|
||||
SetupDataSharingAndNewsletter: typeof import('./components/setup/DataSharingAndNewsletter.vue')['default'];
|
||||
TeamsAdd: typeof import('./components/teams/Add.vue')['default'];
|
||||
TeamsDetails: typeof import('./components/teams/Details.vue')['default'];
|
||||
TeamsInvite: typeof import('./components/teams/Invite.vue')['default'];
|
||||
TeamsMembers: typeof import('./components/teams/Members.vue')['default'];
|
||||
TeamsPendingInvites: typeof import('./components/teams/PendingInvites.vue')['default'];
|
||||
Tippy: typeof import('vue-tippy')['Tippy'];
|
||||
Tokens: typeof import('./components/tokens/index.vue')['default'];
|
||||
TokensGenerateModal: typeof import('./components/tokens/GenerateModal.vue')['default'];
|
||||
TokensList: typeof import('./components/tokens/List.vue')['default'];
|
||||
TokensOverview: typeof import('./components/tokens/Overview.vue')['default'];
|
||||
TokensToken: typeof import('./components/tokens/Token.vue')['default'];
|
||||
UiAutoResetIcon: typeof import('./components/ui/AutoResetIcon.vue')['default'];
|
||||
UsersDetails: typeof import('./components/users/Details.vue')['default'];
|
||||
UsersInviteModal: typeof import('./components/users/InviteModal.vue')['default'];
|
||||
UsersSharedRequests: typeof import('./components/users/SharedRequests.vue')['default'];
|
||||
UsersSuccessInviteModal: typeof import('./components/users/SuccessInviteModal.vue')['default'];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="workingConfigs"
|
||||
class="md:grid md:grid-cols-3 md:gap-4 border-divider border-b"
|
||||
>
|
||||
<div class="pb-8 px-8 md:col-span-1">
|
||||
<div v-if="workingConfigs" class="grid md:grid-cols-3 gap-8 md:gap-4">
|
||||
<div class="md:col-span-1">
|
||||
<h3 class="heading">{{ t('configs.auth_providers.title') }}</h3>
|
||||
<p class="my-1 text-secondaryLight">
|
||||
{{ t('configs.auth_providers.description') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-8 p-8 md:col-span-2">
|
||||
<div class="space-y-8 sm:px-8 md:col-span-2">
|
||||
<section>
|
||||
<h4 class="font-semibold text-secondaryDark">
|
||||
{{ t('configs.auth_providers.title') }}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="flex flex-col space-y-8 divide-y divide-divider">
|
||||
<SettingsAuthProvider v-model:config="workingConfigs" />
|
||||
<SettingsSmtpConfiguration v-model:config="workingConfigs" />
|
||||
<SettingsDataSharing v-model:config="workingConfigs" />
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div class="md:grid md:grid-cols-3 md:gap-4 border-divider border-b py-8">
|
||||
<div class="px-8 md:col-span-1">
|
||||
<div class="grid md:grid-cols-3 gap-8 md:gap-4 pt-8">
|
||||
<div class="md:col-span-1">
|
||||
<h3 class="heading">{{ t('configs.data_sharing.title') }}</h3>
|
||||
<p class="my-1 text-secondaryLight">
|
||||
{{ t('configs.data_sharing.description') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="mx-8 md:col-span-2">
|
||||
<div class="sm:px-8 md:col-span-2">
|
||||
<h4 class="font-semibold text-secondaryDark">
|
||||
{{ t('configs.data_sharing.title') }}
|
||||
</h4>
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<template>
|
||||
<div class="md:grid md:grid-cols-3 md:gap-4">
|
||||
<div class="p-8 md:col-span-1">
|
||||
<div class="grid md:grid-cols-3 gap-8 md:gap-4 pt-8">
|
||||
<div class="md:col-span-1">
|
||||
<h3 class="heading">{{ t('configs.reset.title') }}</h3>
|
||||
<p class="my-1 text-secondaryLight">
|
||||
{{ t('configs.reset.description') }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="space-y-8 p-8 md:col-span-2">
|
||||
<div class="space-y-8 sm:px-8 md:col-span-2">
|
||||
<section>
|
||||
<h4 class="font-semibold text-secondaryDark">
|
||||
{{ t('configs.reset.info') }}
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
<template>
|
||||
<div
|
||||
v-if="smtpConfigs"
|
||||
class="md:grid md:grid-cols-3 md:gap-4 border-divider border-b"
|
||||
>
|
||||
<div class="p-8 px-8 md:col-span-1">
|
||||
<div v-if="smtpConfigs" class="grid md:grid-cols-3 gap-4 md:gap-4 pt-8">
|
||||
<div class="md:col-span-1">
|
||||
<h3 class="heading">{{ t('configs.mail_configs.title') }}</h3>
|
||||
<p class="my-1 text-secondaryLight">
|
||||
{{ t('configs.mail_configs.description') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="space-y-8 p-8 md:col-span-2">
|
||||
<div class="space-y-8 sm:px-8 md:col-span-2">
|
||||
<section>
|
||||
<h4 class="font-semibold text-secondaryDark">
|
||||
{{ t('configs.mail_configs.title') }}
|
||||
|
||||
@@ -0,0 +1,210 @@
|
||||
<template>
|
||||
<HoppSmartModal
|
||||
dialog
|
||||
:title="t('infra_tokens.generate_modal_title')"
|
||||
@close="hideModal"
|
||||
>
|
||||
<template #body>
|
||||
<template v-if="infraToken">
|
||||
<p class="p-4 mb-4 border rounded-md text-amber-500 border-amber-600">
|
||||
{{ t('infra_tokens.copy_token_warning') }}
|
||||
</p>
|
||||
|
||||
<div
|
||||
class="flex items-center justify-between p-4 mt-4 rounded-md bg-primaryLight"
|
||||
>
|
||||
<div class="text-secondaryDark">{{ infraToken }}</div>
|
||||
<HoppButtonSecondary
|
||||
outline
|
||||
filled
|
||||
:icon="copyIcon"
|
||||
@click="copyInfraToken"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-else class="space-y-4">
|
||||
<div class="space-y-2">
|
||||
<div class="font-semibold text-secondaryDark">
|
||||
{{ t('action.label') }}
|
||||
</div>
|
||||
<HoppSmartInput
|
||||
v-model="infraTokenLabel"
|
||||
:placeholder="t('infra_tokens.token_purpose')"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="space-y-2">
|
||||
<label for="expiration" class="font-semibold text-secondaryDark">{{
|
||||
t('infra_tokens.expiration_label')
|
||||
}}</label>
|
||||
|
||||
<div class="grid items-center grid-cols-2 gap-x-2">
|
||||
<tippy
|
||||
interactive
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
:on-shown="() => tippyActions?.focus()"
|
||||
>
|
||||
<HoppSmartSelectWrapper>
|
||||
<input
|
||||
id="expiration"
|
||||
:value="expiration"
|
||||
readonly
|
||||
class="flex flex-1 px-4 py-2 bg-transparent border rounded cursor-pointer border-divider"
|
||||
/>
|
||||
</HoppSmartSelectWrapper>
|
||||
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="tippyActions"
|
||||
tabindex="0"
|
||||
role="menu"
|
||||
class="flex flex-col focus:outline-none"
|
||||
@keyup.escape="hide"
|
||||
>
|
||||
<HoppSmartItem
|
||||
v-for="expirationOption in Object.keys(expirationOptions)"
|
||||
:key="expirationOption"
|
||||
:label="expirationOption"
|
||||
:icon="
|
||||
expirationOption === expiration
|
||||
? IconCircleDot
|
||||
: IconCircle
|
||||
"
|
||||
:active="expirationOption === expiration"
|
||||
:aria-selected="expirationOption === expiration"
|
||||
@click="
|
||||
() => {
|
||||
expiration = expirationOption;
|
||||
hide();
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
|
||||
<span class="text-secondaryLight">{{ expirationDateText }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #footer>
|
||||
<HoppButtonSecondary
|
||||
v-if="infraToken"
|
||||
:label="t('action.close')"
|
||||
outline
|
||||
filled
|
||||
@click="hideModal"
|
||||
/>
|
||||
|
||||
<div v-else class="flex items-center gap-x-2">
|
||||
<HoppButtonPrimary
|
||||
:loading="tokenGenerateActionLoading"
|
||||
filled
|
||||
outline
|
||||
:label="t('infra_tokens.generate_token')"
|
||||
@click="generateInfraToken"
|
||||
/>
|
||||
|
||||
<HoppButtonSecondary
|
||||
:label="t('action.cancel')"
|
||||
outline
|
||||
filled
|
||||
@click="hideModal"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</HoppSmartModal>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { refAutoReset } from '@vueuse/core';
|
||||
import { VNodeRef, computed, ref } from 'vue';
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
import { useToast } from '~/composables/toast';
|
||||
|
||||
import { copyToClipboard } from '~/helpers/utils/clipboard';
|
||||
import { shortDateTime } from '~/helpers/utils/date';
|
||||
|
||||
import IconCheck from '~icons/lucide/check';
|
||||
import IconCircle from '~icons/lucide/circle';
|
||||
import IconCircleDot from '~icons/lucide/circle-dot';
|
||||
import IconCopy from '~icons/lucide/copy';
|
||||
|
||||
const t = useI18n();
|
||||
const toast = useToast();
|
||||
|
||||
const props = defineProps<{
|
||||
tokenGenerateActionLoading: boolean;
|
||||
infraToken: string | null;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'hide-modal'): void;
|
||||
(
|
||||
e: 'generate-infra-token',
|
||||
{ label, expiryInDays }: { label: string; expiryInDays: number | null }
|
||||
): void;
|
||||
}>();
|
||||
|
||||
// Template refs
|
||||
const tippyActions = ref<VNodeRef | null>(null);
|
||||
|
||||
const copyIcon = refAutoReset<typeof IconCopy | typeof IconCheck>(
|
||||
IconCopy,
|
||||
1000
|
||||
);
|
||||
|
||||
const infraTokenLabel = ref<string>('');
|
||||
const expiration = ref<string>('30 days');
|
||||
|
||||
const expirationOptions: Record<string, number | null> = {
|
||||
'7 days': 7,
|
||||
'30 days': 30,
|
||||
'60 days': 60,
|
||||
'90 days': 90,
|
||||
'No expiration': null,
|
||||
};
|
||||
|
||||
const expirationDateText = computed(() => {
|
||||
const chosenExpiryInDays = expirationOptions[expiration.value];
|
||||
|
||||
if (chosenExpiryInDays === null) {
|
||||
return t('infra_tokens.no_expiration_verbose');
|
||||
}
|
||||
|
||||
const currentDate = new Date();
|
||||
currentDate.setDate(currentDate.getDate() + chosenExpiryInDays);
|
||||
|
||||
const expirationDate = shortDateTime(currentDate, false);
|
||||
return `${t('infra_tokens.token_expires_on')} ${expirationDate}`;
|
||||
});
|
||||
|
||||
const copyInfraToken = () => {
|
||||
if (!props.infraToken) {
|
||||
toast.error('state.something_went_wrong');
|
||||
return;
|
||||
}
|
||||
|
||||
copyToClipboard(props.infraToken);
|
||||
copyIcon.value = IconCheck;
|
||||
|
||||
toast.success(t('state.copied_to_clipboard'));
|
||||
};
|
||||
|
||||
const generateInfraToken = async () => {
|
||||
if (!infraTokenLabel.value) {
|
||||
toast.error(t('infra_tokens.invalid_label'));
|
||||
return;
|
||||
}
|
||||
|
||||
emit('generate-infra-token', {
|
||||
label: infraTokenLabel.value,
|
||||
expiryInDays: expirationOptions[expiration.value],
|
||||
});
|
||||
};
|
||||
|
||||
const hideModal = () => emit('hide-modal');
|
||||
</script>
|
||||
130
packages/hoppscotch-sh-admin/src/components/tokens/List.vue
Normal file
130
packages/hoppscotch-sh-admin/src/components/tokens/List.vue
Normal file
@@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<div class="flex flex-col px-4">
|
||||
<div v-if="isInitialPageLoad" class="flex flex-col items-center py-3">
|
||||
<HoppSmartSpinner />
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-else-if="initialPageLoadHasError"
|
||||
class="flex flex-col items-center py-4"
|
||||
>
|
||||
<icon-lucide-help-circle class="mb-4 svg-icons" />
|
||||
{{ t('state.something_went_wrong') }}
|
||||
</div>
|
||||
|
||||
<HoppSmartPlaceholder
|
||||
v-else-if="infraTokens.length === 0"
|
||||
:src="noTokensImage"
|
||||
:alt="`${t('infra_tokens.empty')}`"
|
||||
:text="t('infra_tokens.empty')"
|
||||
@drop.stop
|
||||
/>
|
||||
|
||||
<div v-else class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
|
||||
<div
|
||||
v-for="{ id, label, lastUsedOn, expiresOn } in infraTokens"
|
||||
:key="id"
|
||||
class="flex flex-col items-center gap-4 p-4 border rounded border-divider"
|
||||
>
|
||||
<div class="w-full text-sm font-semibold truncate text-secondaryDark">
|
||||
{{ label }}
|
||||
</div>
|
||||
|
||||
<div class="flex items-center justify-between w-full gap-x-4">
|
||||
<div class="space-y-1 text-secondaryLight">
|
||||
<div class="space-x-1">
|
||||
<span class="font-semibold"
|
||||
>{{ t('infra_tokens.last_used_on') }}:</span
|
||||
>
|
||||
<span>
|
||||
{{ shortDateTime(lastUsedOn, false) }}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="space-x-1">
|
||||
<span class="font-semibold"
|
||||
>{{ t('infra_tokens.expires_on') }}:</span
|
||||
>
|
||||
<span>
|
||||
{{ getTokenExpiryText(expiresOn) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<HoppButtonSecondary
|
||||
:label="t('action.delete')"
|
||||
filled
|
||||
outline
|
||||
@click="
|
||||
emit('delete-infra-token', {
|
||||
tokenId: id,
|
||||
tokenLabel: label,
|
||||
})
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<HoppSmartIntersection
|
||||
v-if="hasMoreTokens"
|
||||
@intersecting="emit('fetch-more-tokens')"
|
||||
>
|
||||
<div v-if="loading" class="flex flex-col items-center py-3">
|
||||
<HoppSmartSpinner />
|
||||
</div>
|
||||
|
||||
<div v-else-if="hasError" class="flex flex-col items-center py-4">
|
||||
<icon-lucide-help-circle class="mb-4 svg-icons" />
|
||||
{{ t('state.something_went_wrong') }}
|
||||
</div>
|
||||
</HoppSmartIntersection>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
|
||||
import { InfraTokensQuery } from '~/helpers/backend/graphql';
|
||||
import { shortDateTime } from '~/helpers/utils/date';
|
||||
|
||||
const t = useI18n();
|
||||
|
||||
const props = defineProps<{
|
||||
infraTokens: InfraTokensQuery['infraTokens'];
|
||||
hasMoreTokens: boolean;
|
||||
loading: boolean;
|
||||
hasError: boolean;
|
||||
}>();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'fetch-more-tokens'): void;
|
||||
(
|
||||
e: 'delete-infra-token',
|
||||
{ tokenId, tokenLabel }: { tokenId: string; tokenLabel: string }
|
||||
): void;
|
||||
}>();
|
||||
|
||||
const noTokensImage = `${
|
||||
import.meta.env.VITE_ADMIN_URL
|
||||
}/assets/images/pack.svg`;
|
||||
|
||||
const isInitialPageLoad = computed(() => props.loading && !props.hasMoreTokens);
|
||||
const initialPageLoadHasError = computed(
|
||||
() => props.hasError && !props.hasMoreTokens
|
||||
);
|
||||
|
||||
const getTokenExpiryText = (tokenExpiresOn: string | null) => {
|
||||
if (!tokenExpiresOn) {
|
||||
return t('infra_tokens.no_expiration');
|
||||
}
|
||||
|
||||
const isTokenExpired =
|
||||
new Date(tokenExpiresOn).toISOString() > tokenExpiresOn;
|
||||
|
||||
return isTokenExpired
|
||||
? t('infra_tokens.expired')
|
||||
: shortDateTime(tokenExpiresOn, false);
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,30 @@
|
||||
<template>
|
||||
<div class="px-4 py-6 space-y-4 flex flex-col items-start">
|
||||
<div class="space-y-1">
|
||||
<h4 class="font-bold text-secondaryDark heading mt-2">
|
||||
{{ t('infra_tokens.section_title') }}
|
||||
</h4>
|
||||
|
||||
<p class="text-secondaryLight">
|
||||
{{ t('infra_tokens.section_description') }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<HoppButtonSecondary
|
||||
filled
|
||||
outline
|
||||
:label="t('infra_tokens.generate_new_token')"
|
||||
@click="emit('show-infra-tokens-generate-modal')"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
|
||||
const t = useI18n();
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'show-infra-tokens-generate-modal'): void;
|
||||
}>();
|
||||
</script>
|
||||
188
packages/hoppscotch-sh-admin/src/components/tokens/index.vue
Normal file
188
packages/hoppscotch-sh-admin/src/components/tokens/index.vue
Normal file
@@ -0,0 +1,188 @@
|
||||
<template>
|
||||
<TokensOverview
|
||||
@show-infra-tokens-generate-modal="showInfraTokensGenerateModal = true"
|
||||
/>
|
||||
|
||||
<TokensList
|
||||
:infra-tokens="infraTokens"
|
||||
:has-error="tokensListFetchErrored"
|
||||
:has-more-tokens="hasMoreTokens"
|
||||
:loading="tokensListLoading"
|
||||
@delete-infra-token="displayDeleteInfraTokenConfirmationModal"
|
||||
@fetch-more-tokens="fetchMoreInfraTokens"
|
||||
/>
|
||||
|
||||
<TokensGenerateModal
|
||||
v-if="showInfraTokensGenerateModal"
|
||||
:infra-token="infraToken"
|
||||
:token-generate-action-loading="tokenGenerateActionLoading"
|
||||
@generate-infra-token="generateInfraToken"
|
||||
@hide-modal="hideInfraTokenGenerateModal"
|
||||
/>
|
||||
|
||||
<HoppSmartConfirmModal
|
||||
:show="confirmDeleteInfraToken"
|
||||
:loading-state="tokenDeleteActionLoading"
|
||||
:title="
|
||||
t('state.confirm_delete_infra_token', {
|
||||
tokenLabel: tokenToDelete?.label,
|
||||
})
|
||||
"
|
||||
@hide-modal="confirmDeleteInfraToken = false"
|
||||
@resolve="deleteInfraToken"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useMutation } from '@urql/vue';
|
||||
import { Ref, ref, watch } from 'vue';
|
||||
import { useI18n } from '~/composables/i18n';
|
||||
import { useToast } from '~/composables/toast';
|
||||
import { usePagedQuery } from '~/composables/usePagedQuery';
|
||||
import {
|
||||
CreateInfraTokenDocument,
|
||||
InfraTokensDocument,
|
||||
InfraTokensQuery,
|
||||
RevokeInfraTokenDocument,
|
||||
} from '~/helpers/backend/graphql';
|
||||
import { getCompiledErrorMessage } from '~/helpers/errors';
|
||||
|
||||
const t = useI18n();
|
||||
const toast = useToast();
|
||||
|
||||
const confirmDeleteInfraToken = ref(false);
|
||||
const hasMoreTokens = ref(false);
|
||||
const showInfraTokensGenerateModal = ref(false);
|
||||
const tokenDeleteActionLoading = ref(false);
|
||||
const tokenGenerateActionLoading = ref(false);
|
||||
const tokenToDelete = ref<{ id: string; label: string } | null>(null);
|
||||
|
||||
const infraToken: Ref<string | null> = ref(null);
|
||||
const infraTokens: Ref<InfraTokensQuery['infraTokens']> = ref([]);
|
||||
|
||||
let offset = 0;
|
||||
const tokensPerPage = 12;
|
||||
|
||||
const {
|
||||
fetching: tokensListLoading,
|
||||
error: tokensListFetchErrored,
|
||||
list: tokensList,
|
||||
refetch,
|
||||
} = usePagedQuery(InfraTokensDocument, (x) => x.infraTokens, tokensPerPage, {
|
||||
skip: offset,
|
||||
take: tokensPerPage,
|
||||
});
|
||||
|
||||
const fetchMoreInfraTokens = async () =>
|
||||
await refetch({ skip: offset, take: tokensPerPage });
|
||||
|
||||
// Update the infraTokens list whenever tokensList is fetched
|
||||
watch(tokensListLoading, (fetching) => {
|
||||
if (fetching) return;
|
||||
else {
|
||||
infraTokens.value.push(...tokensList.value);
|
||||
if (tokensList.value.length > 0) offset += tokensList.value.length;
|
||||
hasMoreTokens.value = tokensList.value.length === tokensPerPage;
|
||||
}
|
||||
});
|
||||
|
||||
const createInfraTokens = useMutation(CreateInfraTokenDocument);
|
||||
|
||||
const generateInfraToken = async ({
|
||||
label,
|
||||
expiryInDays,
|
||||
}: {
|
||||
label: string;
|
||||
expiryInDays: number | null;
|
||||
}) => {
|
||||
tokenGenerateActionLoading.value = true;
|
||||
|
||||
const variables = {
|
||||
label,
|
||||
expiryInDays,
|
||||
};
|
||||
|
||||
const result = await createInfraTokens.executeMutation(variables);
|
||||
|
||||
if (result.error) {
|
||||
const { message } = result.error;
|
||||
const compiledErrorMessage = getCompiledErrorMessage(message);
|
||||
|
||||
compiledErrorMessage
|
||||
? toast.error(t(compiledErrorMessage))
|
||||
: toast.error(t('state.generate_infra_token_failure'));
|
||||
|
||||
showInfraTokensGenerateModal.value = false;
|
||||
} else {
|
||||
infraTokens.value.unshift(result.data!.createInfraToken.info);
|
||||
infraToken.value = result.data!.createInfraToken.token;
|
||||
offset += 1;
|
||||
|
||||
if (tokensListFetchErrored.value) {
|
||||
tokensListFetchErrored.value = false;
|
||||
}
|
||||
}
|
||||
tokenGenerateActionLoading.value = false;
|
||||
};
|
||||
|
||||
const revokeInfraToken = useMutation(RevokeInfraTokenDocument);
|
||||
|
||||
const deleteInfraToken = async () => {
|
||||
if (tokenToDelete.value === null) {
|
||||
toast.error(t('state.something_went_wrong'));
|
||||
return;
|
||||
}
|
||||
|
||||
const { id: tokenIdToDelete, label: tokenLabelToDelete } =
|
||||
tokenToDelete.value;
|
||||
|
||||
tokenDeleteActionLoading.value = true;
|
||||
|
||||
const result = await revokeInfraToken.executeMutation({
|
||||
id: tokenIdToDelete,
|
||||
});
|
||||
|
||||
if (result.error) {
|
||||
toast.error(t('state.delete_infra_token_failure'));
|
||||
} else {
|
||||
infraTokens.value = infraTokens.value.filter(
|
||||
(token) => token.id !== tokenIdToDelete
|
||||
);
|
||||
|
||||
offset = offset > 0 ? offset - 1 : offset;
|
||||
|
||||
toast.success(
|
||||
t('infra_tokens.deletion_success', { label: tokenLabelToDelete })
|
||||
);
|
||||
|
||||
if (tokensListFetchErrored.value) {
|
||||
tokensListFetchErrored.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
tokenDeleteActionLoading.value = false;
|
||||
confirmDeleteInfraToken.value = false;
|
||||
tokenToDelete.value = null;
|
||||
};
|
||||
|
||||
const hideInfraTokenGenerateModal = () => {
|
||||
// Reset the reactive state variable holding infra token value and hide the modal
|
||||
infraToken.value = null;
|
||||
showInfraTokensGenerateModal.value = false;
|
||||
};
|
||||
|
||||
const displayDeleteInfraTokenConfirmationModal = ({
|
||||
tokenId,
|
||||
tokenLabel,
|
||||
}: {
|
||||
tokenId: string;
|
||||
tokenLabel: string;
|
||||
}) => {
|
||||
confirmDeleteInfraToken.value = true;
|
||||
|
||||
tokenToDelete.value = {
|
||||
id: tokenId,
|
||||
label: tokenLabel,
|
||||
};
|
||||
};
|
||||
</script>
|
||||
@@ -0,0 +1,12 @@
|
||||
mutation CreateInfraToken($label: String!, $expiryInDays: Int) {
|
||||
createInfraToken(label: $label, expiryInDays: $expiryInDays) {
|
||||
info {
|
||||
id
|
||||
label
|
||||
lastUsedOn
|
||||
createdOn
|
||||
expiresOn
|
||||
}
|
||||
token
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
mutation RevokeInfraToken($id: ID!) {
|
||||
revokeInfraToken(id: $id)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
query InfraTokens($skip: Int, $take: Int) {
|
||||
infraTokens(skip: $skip, take: $take) {
|
||||
id
|
||||
label
|
||||
createdOn
|
||||
lastUsedOn
|
||||
expiresOn
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,9 @@ export const AUTH_PROVIDER_NOT_SPECIFIED =
|
||||
export const BOTH_EMAILS_CANNOT_BE_SAME =
|
||||
'[GraphQL] email/both_emails_cannot_be_same' as const;
|
||||
|
||||
export const INFRA_TOKEN_LABEL_SHORT =
|
||||
'[GraphQL] infra_token/label_too_short' as const;
|
||||
|
||||
type ErrorMessages = {
|
||||
message: string;
|
||||
alternateMessage?: string;
|
||||
@@ -68,6 +71,9 @@ const ERROR_MESSAGES: Record<string, ErrorMessages> = {
|
||||
[BOTH_EMAILS_CANNOT_BE_SAME]: {
|
||||
message: 'state.emails_cannot_be_same',
|
||||
},
|
||||
[INFRA_TOKEN_LABEL_SHORT]: {
|
||||
message: 'state.infra_token_label_short',
|
||||
},
|
||||
};
|
||||
|
||||
export const getCompiledErrorMessage = (name: string, altMessage = false) => {
|
||||
|
||||
17
packages/hoppscotch-sh-admin/src/helpers/utils/date.ts
Normal file
17
packages/hoppscotch-sh-admin/src/helpers/utils/date.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
export function shortDateTime(
|
||||
date: string | number | Date,
|
||||
includeTime: boolean = true
|
||||
) {
|
||||
return new Date(date).toLocaleString("en-US", {
|
||||
year: "numeric",
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
...(includeTime
|
||||
? {
|
||||
hour: "numeric",
|
||||
minute: "numeric",
|
||||
second: "numeric",
|
||||
}
|
||||
: {}),
|
||||
})
|
||||
}
|
||||
@@ -24,6 +24,9 @@
|
||||
class="py-8 px-4"
|
||||
/>
|
||||
</HoppSmartTab>
|
||||
<HoppSmartTab :id="'token'" :label="t('infra_tokens.tab_title')">
|
||||
<Tokens />
|
||||
</HoppSmartTab>
|
||||
</HoppSmartTabs>
|
||||
</div>
|
||||
|
||||
@@ -62,7 +65,7 @@ const showSaveChangesModal = ref(false);
|
||||
const initiateServerRestart = ref(false);
|
||||
|
||||
// Tabs
|
||||
type OptionTabs = 'config';
|
||||
type OptionTabs = 'config' | 'token';
|
||||
const selectedOptionTab = ref<OptionTabs>('config');
|
||||
|
||||
// Obtain the current and working configs from the useConfigHandler composable
|
||||
|
||||
Reference in New Issue
Block a user