Compare commits
7 Commits
2023.12.2
...
fix/disabl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
51ebc198de | ||
|
|
7406a241e6 | ||
|
|
f51196604a | ||
|
|
c0dbcc901f | ||
|
|
ba52c8cc37 | ||
|
|
d1f6f40ef8 | ||
|
|
99f5070f71 |
@@ -187,7 +187,7 @@ import IconClock from "~icons/lucide/clock"
|
|||||||
import IconCopy from "~icons/lucide/copy"
|
import IconCopy from "~icons/lucide/copy"
|
||||||
import IconBox from "~icons/lucide/box"
|
import IconBox from "~icons/lucide/box"
|
||||||
import { computed, nextTick, reactive, ref } from "vue"
|
import { computed, nextTick, reactive, ref } from "vue"
|
||||||
import { GraphQLField, GraphQLType } from "graphql"
|
import { GraphQLField, GraphQLType, getNamedType } from "graphql"
|
||||||
import { refAutoReset } from "@vueuse/core"
|
import { refAutoReset } from "@vueuse/core"
|
||||||
import { useCodemirror } from "@composables/codemirror"
|
import { useCodemirror } from "@composables/codemirror"
|
||||||
import { copyToClipboard } from "@helpers/utils/clipboard"
|
import { copyToClipboard } from "@helpers/utils/clipboard"
|
||||||
@@ -260,12 +260,6 @@ function getFilteredGraphqlTypes(filterText: string, types: GraphQLType[]) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveRootType(type: GraphQLType) {
|
|
||||||
let t: any = type
|
|
||||||
while (t.ofType) t = t.ofType
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
const toast = useToast()
|
const toast = useToast()
|
||||||
|
|
||||||
const downloadSchemaIcon = refAutoReset<typeof IconDownload | typeof IconCheck>(
|
const downloadSchemaIcon = refAutoReset<typeof IconDownload | typeof IconCheck>(
|
||||||
@@ -331,7 +325,7 @@ const handleJumpToType = async (type: GraphQLType) => {
|
|||||||
selectedGqlTab.value = "types"
|
selectedGqlTab.value = "types"
|
||||||
await nextTick()
|
await nextTick()
|
||||||
|
|
||||||
const rootTypeName = resolveRootType(type).name
|
const rootTypeName = getNamedType(type).name
|
||||||
const target = document.getElementById(`type_${rootTypeName}`)
|
const target = document.getElementById(`type_${rootTypeName}`)
|
||||||
if (target) {
|
if (target) {
|
||||||
target.scrollIntoView({ block: "center", behavior: "smooth" })
|
target.scrollIntoView({ block: "center", behavior: "smooth" })
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { GraphQLScalarType, GraphQLType } from "graphql"
|
import { GraphQLScalarType, GraphQLType, getNamedType } from "graphql"
|
||||||
import { computed } from "vue"
|
import { computed } from "vue"
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
@@ -21,15 +21,9 @@ const emit = defineEmits<{
|
|||||||
|
|
||||||
const typeString = computed(() => `${props.gqlType}`)
|
const typeString = computed(() => `${props.gqlType}`)
|
||||||
const isScalar = computed(() => {
|
const isScalar = computed(() => {
|
||||||
return resolveRootType(props.gqlType) instanceof GraphQLScalarType
|
return getNamedType(props.gqlType) instanceof GraphQLScalarType
|
||||||
})
|
})
|
||||||
|
|
||||||
function resolveRootType(type: GraphQLType) {
|
|
||||||
let t = type as any
|
|
||||||
while (t.ofType !== null) t = t.ofType
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
|
|
||||||
function jumpToType() {
|
function jumpToType() {
|
||||||
if (isScalar.value) return
|
if (isScalar.value) return
|
||||||
emit("jump-to-type", props.gqlType)
|
emit("jump-to-type", props.gqlType)
|
||||||
|
|||||||
@@ -99,6 +99,7 @@ useCodemirror(
|
|||||||
linter,
|
linter,
|
||||||
completer,
|
completer,
|
||||||
environmentHighlights: false,
|
environmentHighlights: false,
|
||||||
|
contextMenuEnabled: false,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -95,6 +95,7 @@ useCodemirror(
|
|||||||
linter,
|
linter,
|
||||||
completer,
|
completer,
|
||||||
environmentHighlights: false,
|
environmentHighlights: false,
|
||||||
|
contextMenuEnabled: false,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -79,6 +79,7 @@ const props = withDefaults(
|
|||||||
readonly?: boolean
|
readonly?: boolean
|
||||||
autoCompleteSource?: string[]
|
autoCompleteSource?: string[]
|
||||||
inspectionResults?: InspectorResult[] | undefined
|
inspectionResults?: InspectorResult[] | undefined
|
||||||
|
contextMenuEnabled?: boolean
|
||||||
}>(),
|
}>(),
|
||||||
{
|
{
|
||||||
modelValue: "",
|
modelValue: "",
|
||||||
@@ -91,6 +92,7 @@ const props = withDefaults(
|
|||||||
autoCompleteSource: undefined,
|
autoCompleteSource: undefined,
|
||||||
inspectionResult: undefined,
|
inspectionResult: undefined,
|
||||||
inspectionResults: undefined,
|
inspectionResults: undefined,
|
||||||
|
contextMenuEnabled: true,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -359,8 +361,11 @@ const initView = (el: any) => {
|
|||||||
handleTextSelection()
|
handleTextSelection()
|
||||||
}, 140)
|
}, 140)
|
||||||
|
|
||||||
el.addEventListener("mouseup", debounceFn)
|
// Only add event listeners if context menu is enabled in the component
|
||||||
el.addEventListener("keyup", debounceFn)
|
if (props.contextMenuEnabled) {
|
||||||
|
el.addEventListener("mouseup", debounceFn)
|
||||||
|
el.addEventListener("keyup", debounceFn)
|
||||||
|
}
|
||||||
|
|
||||||
const extensions: Extension = [
|
const extensions: Extension = [
|
||||||
EditorView.contentAttributes.of({ "aria-label": props.placeholder }),
|
EditorView.contentAttributes.of({ "aria-label": props.placeholder }),
|
||||||
@@ -396,7 +401,7 @@ const initView = (el: any) => {
|
|||||||
ev.preventDefault()
|
ev.preventDefault()
|
||||||
},
|
},
|
||||||
scroll(event) {
|
scroll(event) {
|
||||||
if (event.target) {
|
if (event.target && props.contextMenuEnabled) {
|
||||||
handleTextSelection()
|
handleTextSelection()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -405,7 +410,6 @@ const initView = (el: any) => {
|
|||||||
class {
|
class {
|
||||||
update(update: ViewUpdate) {
|
update(update: ViewUpdate) {
|
||||||
if (props.readonly) return
|
if (props.readonly) return
|
||||||
|
|
||||||
if (update.docChanged) {
|
if (update.docChanged) {
|
||||||
const prevValue = clone(cachedValue.value)
|
const prevValue = clone(cachedValue.value)
|
||||||
|
|
||||||
@@ -436,6 +440,17 @@ const initView = (el: any) => {
|
|||||||
clipboardEv = null
|
clipboardEv = null
|
||||||
pastedValue = null
|
pastedValue = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (props.contextMenuEnabled) {
|
||||||
|
// close the context menu if text is being updated in the editor
|
||||||
|
invokeAction("contextmenu.open", {
|
||||||
|
position: {
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
},
|
||||||
|
text: null,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,6 +63,8 @@ type CodeMirrorOptions = {
|
|||||||
|
|
||||||
additionalExts?: Extension[]
|
additionalExts?: Extension[]
|
||||||
|
|
||||||
|
contextMenuEnabled?: boolean
|
||||||
|
|
||||||
// callback on editor update
|
// callback on editor update
|
||||||
onUpdate?: (view: ViewUpdate) => void
|
onUpdate?: (view: ViewUpdate) => void
|
||||||
}
|
}
|
||||||
@@ -208,6 +210,9 @@ export function useCodemirror(
|
|||||||
): { cursor: Ref<{ line: number; ch: number }> } {
|
): { cursor: Ref<{ line: number; ch: number }> } {
|
||||||
const { subscribeToStream } = useStreamSubscriber()
|
const { subscribeToStream } = useStreamSubscriber()
|
||||||
|
|
||||||
|
// Set default value for contextMenuEnabled if not provided
|
||||||
|
options.contextMenuEnabled = options.contextMenuEnabled ?? true
|
||||||
|
|
||||||
const additionalExts = new Compartment()
|
const additionalExts = new Compartment()
|
||||||
const language = new Compartment()
|
const language = new Compartment()
|
||||||
const lineWrapping = new Compartment()
|
const lineWrapping = new Compartment()
|
||||||
@@ -272,8 +277,11 @@ export function useCodemirror(
|
|||||||
handleTextSelection()
|
handleTextSelection()
|
||||||
}, 140)
|
}, 140)
|
||||||
|
|
||||||
el.addEventListener("mouseup", debounceFn)
|
// Only add event listeners if context menu is enabled in the editor
|
||||||
el.addEventListener("keyup", debounceFn)
|
if (options.contextMenuEnabled) {
|
||||||
|
el.addEventListener("mouseup", debounceFn)
|
||||||
|
el.addEventListener("keyup", debounceFn)
|
||||||
|
}
|
||||||
|
|
||||||
if (options.onUpdate) {
|
if (options.onUpdate) {
|
||||||
options.onUpdate(update)
|
options.onUpdate(update)
|
||||||
@@ -312,7 +320,7 @@ export function useCodemirror(
|
|||||||
),
|
),
|
||||||
EditorView.domEventHandlers({
|
EditorView.domEventHandlers({
|
||||||
scroll(event) {
|
scroll(event) {
|
||||||
if (event.target) {
|
if (event.target && options.contextMenuEnabled) {
|
||||||
handleTextSelection()
|
handleTextSelection()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -549,13 +549,19 @@ const convertPathToHoppReqs = (
|
|||||||
),
|
),
|
||||||
|
|
||||||
// Construct request object
|
// Construct request object
|
||||||
RA.map(({ method, info }) =>
|
RA.map(({ method, info }) => {
|
||||||
makeRESTRequest({
|
const openAPIUrl = parseOpenAPIUrl(doc)
|
||||||
|
const openAPIPath = replaceOpenApiPathTemplating(pathName)
|
||||||
|
|
||||||
|
const endpoint =
|
||||||
|
openAPIUrl.endsWith("/") && openAPIPath.startsWith("/")
|
||||||
|
? openAPIUrl + openAPIPath.slice(1)
|
||||||
|
: openAPIUrl + openAPIPath
|
||||||
|
|
||||||
|
return makeRESTRequest({
|
||||||
name: info.operationId ?? info.summary ?? "Untitled Request",
|
name: info.operationId ?? info.summary ?? "Untitled Request",
|
||||||
method: method.toUpperCase(),
|
method: method.toUpperCase(),
|
||||||
endpoint: `${parseOpenAPIUrl(doc)}${replaceOpenApiPathTemplating(
|
endpoint,
|
||||||
pathName
|
|
||||||
)}`,
|
|
||||||
|
|
||||||
// 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(
|
||||||
@@ -572,7 +578,7 @@ const convertPathToHoppReqs = (
|
|||||||
preRequestScript: "",
|
preRequestScript: "",
|
||||||
testScript: "",
|
testScript: "",
|
||||||
})
|
})
|
||||||
),
|
}),
|
||||||
|
|
||||||
// Disable Readonly
|
// Disable Readonly
|
||||||
RA.toArray
|
RA.toArray
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ async function setInitialUser() {
|
|||||||
} else {
|
} else {
|
||||||
setUser(null)
|
setUser(null)
|
||||||
isGettingInitialUser.value = false
|
isGettingInitialUser.value = false
|
||||||
|
await logout()
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -146,22 +147,26 @@ async function setInitialUser() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function refreshToken() {
|
async function refreshToken() {
|
||||||
const res = await axios.get(
|
try {
|
||||||
`${import.meta.env.VITE_BACKEND_API_URL}/auth/refresh`,
|
const res = await axios.get(
|
||||||
{
|
`${import.meta.env.VITE_BACKEND_API_URL}/auth/refresh`,
|
||||||
withCredentials: true,
|
{
|
||||||
|
withCredentials: true,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const isSuccessful = res.status === 200
|
||||||
|
|
||||||
|
if (isSuccessful) {
|
||||||
|
authEvents$.next({
|
||||||
|
event: "token_refresh",
|
||||||
|
})
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
|
||||||
const isSuccessful = res.status === 200
|
return isSuccessful
|
||||||
|
} catch (error) {
|
||||||
if (isSuccessful) {
|
return false
|
||||||
authEvents$.next({
|
|
||||||
event: "token_refresh",
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return isSuccessful
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sendMagicLink(email: string) {
|
async function sendMagicLink(email: string) {
|
||||||
|
|||||||
59
packages/hoppscotch-sh-admin/src/components.d.ts
vendored
59
packages/hoppscotch-sh-admin/src/components.d.ts
vendored
@@ -1,9 +1,9 @@
|
|||||||
// 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 {
|
||||||
@@ -13,8 +13,6 @@ declare module '@vue/runtime-core' {
|
|||||||
AppModal: typeof import('./components/app/Modal.vue')['default']
|
AppModal: typeof import('./components/app/Modal.vue')['default']
|
||||||
AppSidebar: typeof import('./components/app/Sidebar.vue')['default']
|
AppSidebar: typeof import('./components/app/Sidebar.vue')['default']
|
||||||
AppToast: typeof import('./components/app/Toast.vue')['default']
|
AppToast: typeof import('./components/app/Toast.vue')['default']
|
||||||
ButtonPrimary: typeof import('./../../hoppscotch-ui/src/components/button/Primary.vue')['default']
|
|
||||||
ButtonSecondary: typeof import('./../../hoppscotch-ui/src/components/button/Secondary.vue')['default']
|
|
||||||
DashboardMetricsCard: typeof import('./components/dashboard/MetricsCard.vue')['default']
|
DashboardMetricsCard: typeof import('./components/dashboard/MetricsCard.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']
|
||||||
@@ -23,6 +21,7 @@ declare module '@vue/runtime-core' {
|
|||||||
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']
|
||||||
HoppSmartModal: typeof import('@hoppscotch/ui')['HoppSmartModal']
|
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']
|
||||||
@@ -30,42 +29,13 @@ declare module '@vue/runtime-core' {
|
|||||||
HoppSmartTable: typeof import('@hoppscotch/ui')['HoppSmartTable']
|
HoppSmartTable: typeof import('@hoppscotch/ui')['HoppSmartTable']
|
||||||
HoppSmartTabs: typeof import('@hoppscotch/ui')['HoppSmartTabs']
|
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']
|
IconLucideChevronDown: typeof import('~icons/lucide/chevron-down')['default']
|
||||||
IconLucideInbox: typeof import('~icons/lucide/inbox')['default']
|
IconLucideInbox: typeof import('~icons/lucide/inbox')['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']
|
||||||
SettingsReset: typeof import('./components/settings/Reset.vue')['default']
|
SettingsReset: typeof import('./components/settings/Reset.vue')['default']
|
||||||
SettingsServerRestart: typeof import('./components/settings/ServerRestart.vue')['default']
|
SettingsServerRestart: typeof import('./components/settings/ServerRestart.vue')['default']
|
||||||
SettingsSmtpConfiguration: typeof import('./components/settings/SmtpConfiguration.vue')['default']
|
SettingsSmtpConfiguration: typeof import('./components/settings/SmtpConfiguration.vue')['default']
|
||||||
SmartAnchor: typeof import('./../../hoppscotch-ui/src/components/smart/Anchor.vue')['default']
|
|
||||||
SmartAutoComplete: typeof import('./../../hoppscotch-ui/src/components/smart/AutoComplete.vue')['default']
|
|
||||||
SmartCheckbox: typeof import('./../../hoppscotch-ui/src/components/smart/Checkbox.vue')['default']
|
|
||||||
SmartConfirmModal: typeof import('./../../hoppscotch-ui/src/components/smart/ConfirmModal.vue')['default']
|
|
||||||
SmartExpand: typeof import('./../../hoppscotch-ui/src/components/smart/Expand.vue')['default']
|
|
||||||
SmartFileChip: typeof import('./../../hoppscotch-ui/src/components/smart/FileChip.vue')['default']
|
|
||||||
SmartInput: typeof import('./../../hoppscotch-ui/src/components/smart/Input.vue')['default']
|
|
||||||
SmartIntersection: typeof import('./../../hoppscotch-ui/src/components/smart/Intersection.vue')['default']
|
|
||||||
SmartItem: typeof import('./../../hoppscotch-ui/src/components/smart/Item.vue')['default']
|
|
||||||
SmartLink: typeof import('./../../hoppscotch-ui/src/components/smart/Link.vue')['default']
|
|
||||||
SmartModal: typeof import('./../../hoppscotch-ui/src/components/smart/Modal.vue')['default']
|
|
||||||
SmartPicture: typeof import('./../../hoppscotch-ui/src/components/smart/Picture.vue')['default']
|
|
||||||
SmartPlaceholder: typeof import('./../../hoppscotch-ui/src/components/smart/Placeholder.vue')['default']
|
|
||||||
SmartProgressRing: typeof import('./../../hoppscotch-ui/src/components/smart/ProgressRing.vue')['default']
|
|
||||||
SmartRadio: typeof import('./../../hoppscotch-ui/src/components/smart/Radio.vue')['default']
|
|
||||||
SmartRadioGroup: typeof import('./../../hoppscotch-ui/src/components/smart/RadioGroup.vue')['default']
|
|
||||||
SmartSelectWrapper: typeof import('./../../hoppscotch-ui/src/components/smart/SelectWrapper.vue')['default']
|
|
||||||
SmartSlideOver: typeof import('./../../hoppscotch-ui/src/components/smart/SlideOver.vue')['default']
|
|
||||||
SmartSpinner: typeof import('./../../hoppscotch-ui/src/components/smart/Spinner.vue')['default']
|
|
||||||
SmartTab: typeof import('./../../hoppscotch-ui/src/components/smart/Tab.vue')['default']
|
|
||||||
SmartTable: typeof import('./../../hoppscotch-ui/src/components/smart/Table.vue')['default']
|
|
||||||
SmartTabs: typeof import('./../../hoppscotch-ui/src/components/smart/Tabs.vue')['default']
|
|
||||||
SmartToggle: typeof import('./../../hoppscotch-ui/src/components/smart/Toggle.vue')['default']
|
|
||||||
SmartTree: typeof import('./../../hoppscotch-ui/src/components/smart/Tree.vue')['default']
|
|
||||||
SmartTreeBranch: typeof import('./../../hoppscotch-ui/src/components/smart/TreeBranch.vue')['default']
|
|
||||||
SmartWindow: typeof import('./../../hoppscotch-ui/src/components/smart/Window.vue')['default']
|
|
||||||
SmartWindows: typeof import('./../../hoppscotch-ui/src/components/smart/Windows.vue')['default']
|
|
||||||
TeamsAdd: typeof import('./components/teams/Add.vue')['default']
|
TeamsAdd: typeof import('./components/teams/Add.vue')['default']
|
||||||
TeamsDetails: typeof import('./components/teams/Details.vue')['default']
|
TeamsDetails: typeof import('./components/teams/Details.vue')['default']
|
||||||
TeamsInvite: typeof import('./components/teams/Invite.vue')['default']
|
TeamsInvite: typeof import('./components/teams/Invite.vue')['default']
|
||||||
@@ -76,27 +46,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']
|
||||||
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'];
|
|
||||||
HoppButtonSecondary: typeof import('@hoppscotch/ui')['HoppButtonSecondary'];
|
|
||||||
HoppSmartAnchor: typeof import('@hoppscotch/ui')['HoppSmartAnchor'];
|
|
||||||
HoppSmartConfirmModal: typeof import('@hoppscotch/ui')['HoppSmartConfirmModal'];
|
|
||||||
HoppSmartInput: typeof import('@hoppscotch/ui')['HoppSmartInput'];
|
|
||||||
HoppSmartItem: typeof import('@hoppscotch/ui')['HoppSmartItem'];
|
|
||||||
HoppSmartPicture: typeof import('@hoppscotch/ui')['HoppSmartPicture'];
|
|
||||||
HoppSmartSpinner: typeof import('@hoppscotch/ui')['HoppSmartSpinner'];
|
|
||||||
IconLucideInbox: typeof import('~icons/lucide/inbox')['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'];
|
|
||||||
UsersInviteModal: typeof import('./components/users/InviteModal.vue')['default'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
:class="isOpen ? '' : '-translate-x-full ease-in'"
|
:class="isOpen ? '' : '-translate-x-full ease-in'"
|
||||||
class="sidebar-container transform !md:translate-x-0 ease-out"
|
class="sidebar-container transform !md:translate-x-0 ease-out"
|
||||||
>
|
>
|
||||||
<div :class="isExpanded ? 'w-80' : 'w-full'">
|
<div :class="isExpanded ? 'w-56' : 'w-full'">
|
||||||
<div class="flex items-center justify-start px-4 my-4">
|
<div class="flex items-center justify-start px-4 my-4">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<HoppSmartLink class="flex items-center space-x-4" to="/dashboard">
|
<HoppSmartLink class="flex items-center space-x-4" to="/dashboard">
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
</HoppSmartLink>
|
</HoppSmartLink>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav class="my-5">
|
<nav class="my-5">
|
||||||
<HoppSmartLink
|
<HoppSmartLink
|
||||||
v-for="(navigation, index) in primaryNavigations"
|
v-for="(navigation, index) in primaryNavigations"
|
||||||
@@ -39,19 +38,32 @@
|
|||||||
:to="navigation.to"
|
:to="navigation.to"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
:exact="navigation.exact"
|
:exact="navigation.exact"
|
||||||
class="nav-link"
|
|
||||||
:class="
|
:class="
|
||||||
!isExpanded
|
!isExpanded
|
||||||
? 'flex items-center justify-center'
|
? 'flex items-center justify-center'
|
||||||
: 'flex items-center'
|
: 'flex items-center'
|
||||||
"
|
"
|
||||||
|
@click="setActiveTab(navigation.label)"
|
||||||
>
|
>
|
||||||
<div v-if="navigation.icon">
|
<div
|
||||||
<component :is="navigation.icon" class="svg-icons" />
|
class="flex p-5 w-full font-bold"
|
||||||
|
:class="
|
||||||
|
activeTab === navigation.label
|
||||||
|
? 'bg-primaryDark text-secondaryDark border-l-2 border-l-emerald-600'
|
||||||
|
: 'bg-primary hover:bg-primaryLight hover:text-secondaryDark focus-visible:text-secondaryDark focus-visible:bg-primaryLight focus-visible:outline-none'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="navigation.icon"
|
||||||
|
class="svg-icons"
|
||||||
|
:class="isExpanded ? 'mr-3' : 'mx-auto'"
|
||||||
|
>
|
||||||
|
<component :is="navigation.icon" />
|
||||||
|
</div>
|
||||||
|
<span v-if="isExpanded" class="nav-title">
|
||||||
|
{{ navigation.label }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span v-if="isExpanded" class="nav-title">
|
|
||||||
{{ navigation.label }}
|
|
||||||
</span>
|
|
||||||
</HoppSmartLink>
|
</HoppSmartLink>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
@@ -60,19 +72,27 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { HoppSmartLink } from '@hoppscotch/ui';
|
import { ref, type Component } from 'vue';
|
||||||
|
|
||||||
|
import { useI18n } from '~/composables/i18n';
|
||||||
import { useSidebar } from '~/composables/useSidebar';
|
import { useSidebar } from '~/composables/useSidebar';
|
||||||
import IconDashboard from '~icons/lucide/layout-dashboard';
|
import IconDashboard from '~icons/lucide/layout-dashboard';
|
||||||
|
import IconSettings from '~icons/lucide/settings';
|
||||||
import IconUser from '~icons/lucide/user';
|
import IconUser from '~icons/lucide/user';
|
||||||
import IconUsers from '~icons/lucide/users';
|
import IconUsers from '~icons/lucide/users';
|
||||||
import IconSettings from '~icons/lucide/settings';
|
|
||||||
import { useI18n } from '~/composables/i18n';
|
|
||||||
|
|
||||||
const t = useI18n();
|
const t = useI18n();
|
||||||
|
|
||||||
const { isOpen, isExpanded } = useSidebar();
|
const { isOpen, isExpanded } = useSidebar();
|
||||||
|
|
||||||
const primaryNavigations = [
|
type NavigationItem = {
|
||||||
|
label: string;
|
||||||
|
icon: Component;
|
||||||
|
to: string;
|
||||||
|
exact: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
const primaryNavigations: NavigationItem[] = [
|
||||||
{
|
{
|
||||||
label: t('metrics.dashboard'),
|
label: t('metrics.dashboard'),
|
||||||
icon: IconDashboard,
|
icon: IconDashboard,
|
||||||
@@ -98,6 +118,12 @@ const primaryNavigations = [
|
|||||||
exact: true,
|
exact: true,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const activeTab = ref('Dashboard');
|
||||||
|
|
||||||
|
const setActiveTab = (tab: string) => {
|
||||||
|
activeTab.value = tab;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@@ -106,54 +132,4 @@ const primaryNavigations = [
|
|||||||
@apply transition duration-300;
|
@apply transition duration-300;
|
||||||
@apply flex overflow-y-auto bg-primary border-r border-divider;
|
@apply flex overflow-y-auto bg-primary border-r border-divider;
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav-link {
|
|
||||||
@apply relative;
|
|
||||||
@apply p-4;
|
|
||||||
@apply flex flex-1;
|
|
||||||
@apply items-center;
|
|
||||||
@apply space-x-4;
|
|
||||||
@apply hover:bg-primaryDark hover:text-secondaryDark;
|
|
||||||
@apply focus-visible:text-secondaryDark;
|
|
||||||
@apply after:absolute;
|
|
||||||
@apply after:inset-x-0;
|
|
||||||
@apply after:md:inset-x-auto;
|
|
||||||
@apply after:md:inset-y-0;
|
|
||||||
@apply after:bottom-0;
|
|
||||||
@apply after:md:bottom-auto;
|
|
||||||
@apply after:md:left-0;
|
|
||||||
@apply after:z-10;
|
|
||||||
@apply after:h-0.5;
|
|
||||||
@apply after:md:h-full;
|
|
||||||
@apply after:w-full;
|
|
||||||
@apply after:md:w-0.5;
|
|
||||||
@apply after:content-[''];
|
|
||||||
@apply focus:after:bg-divider;
|
|
||||||
|
|
||||||
.svg-icons {
|
|
||||||
@apply opacity-75;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.router-link-active {
|
|
||||||
@apply text-secondaryDark;
|
|
||||||
@apply bg-primaryLight;
|
|
||||||
@apply hover:text-secondaryDark;
|
|
||||||
@apply after:bg-accent;
|
|
||||||
|
|
||||||
.svg-icons {
|
|
||||||
@apply opacity-100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.exact-active-link {
|
|
||||||
@apply text-secondaryDark;
|
|
||||||
@apply bg-primaryLight;
|
|
||||||
@apply hover:text-secondaryDark;
|
|
||||||
@apply after:bg-accent;
|
|
||||||
|
|
||||||
.svg-icons {
|
|
||||||
@apply opacity-100;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user