mirror of
https://github.com/HangarMC/Hangar.git
synced 2025-01-24 14:24:47 +08:00
add tooltips and user admin buttons
This commit is contained in:
parent
6cc4458044
commit
f5c31cd042
@ -1,2 +1,3 @@
|
||||
HANGAR_PUBLIC_HOST=http://localhost:3333
|
||||
HANGAR_PROXY_HOST=http://localhost:8080
|
||||
HANGAR_AUTH_HOST=http://localhost:3001
|
||||
|
@ -1,2 +1,3 @@
|
||||
HANGAR_PUBLIC_HOST=https://hangar.benndorf.dev
|
||||
HANGAR_PROXY_HOST=http://hangar_new_backend:8080
|
||||
HANGAR_AUTH_HOST=Https://hangar-auth.benndorf.dev
|
||||
|
@ -41,7 +41,8 @@
|
||||
"vite-ssr": "^0.15.0",
|
||||
"vue": "^3.2.31",
|
||||
"vue-i18n": "^9.1.9",
|
||||
"vue-router": "^4.0.14"
|
||||
"vue-router": "^4.0.14",
|
||||
"vue3-popper": "link:@types\\vue3-popper"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify/json": "^2.1.20",
|
||||
|
@ -63,6 +63,7 @@ specifiers:
|
||||
vue: ^3.2.31
|
||||
vue-i18n: ^9.1.9
|
||||
vue-router: ^4.0.14
|
||||
vue3-popper: link:@types\vue3-popper
|
||||
|
||||
dependencies:
|
||||
'@headlessui/vue': 1.5.0_vue@3.2.31
|
||||
@ -88,6 +89,7 @@ dependencies:
|
||||
vue: 3.2.31
|
||||
vue-i18n: 9.1.9_vue@3.2.31
|
||||
vue-router: 4.0.14_vue@3.2.31
|
||||
vue3-popper: 1.4.2_vue@3.2.31
|
||||
|
||||
devDependencies:
|
||||
'@iconify/json': 2.1.20
|
||||
@ -1540,6 +1542,10 @@ packages:
|
||||
resolution: {integrity: sha512-YBI/6o2EBz02tdEJRBK8xkt3zvOFOWlLBf7WKYGBsSYSRtjjgrqPe2skp6VLLmKx5WbHHDNcW+6oACaurxGzeA==}
|
||||
dev: false
|
||||
|
||||
/@popperjs/core/2.11.4:
|
||||
resolution: {integrity: sha512-q/ytXxO5NKvyT37pmisQAItCFqA7FD/vNb8dgaJy3/630Fsc+Mz9/9f2SziBoIZ30TJooXyTwZmhi1zjXmObYg==}
|
||||
dev: false
|
||||
|
||||
/@rollup/plugin-babel/5.3.1_@babel+core@7.17.8+rollup@2.70.1:
|
||||
resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
@ -2523,6 +2529,10 @@ packages:
|
||||
engines: {node: '>= 12'}
|
||||
dev: true
|
||||
|
||||
/debounce/1.2.1:
|
||||
resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==}
|
||||
dev: false
|
||||
|
||||
/debug/2.6.9:
|
||||
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
|
||||
dependencies:
|
||||
@ -5451,6 +5461,17 @@ packages:
|
||||
'@vue/shared': 3.2.31
|
||||
dev: false
|
||||
|
||||
/vue3-popper/1.4.2_vue@3.2.31:
|
||||
resolution: {integrity: sha512-nc5vM//AJ8/DyNetjrrgkkLv7aKVdSsljvqlQ1tWhAV2lgA8tkn8xE6icDd0/kBt0Yo5Li8Pftf0H0C/hNmu1Q==}
|
||||
engines: {node: '>=12'}
|
||||
peerDependencies:
|
||||
vue: ^3.2.20
|
||||
dependencies:
|
||||
'@popperjs/core': 2.11.4
|
||||
debounce: 1.2.1
|
||||
vue: 3.2.31
|
||||
dev: false
|
||||
|
||||
/web-streams-polyfill/3.2.0:
|
||||
resolution: {integrity: sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==}
|
||||
engines: {node: '>= 8'}
|
||||
|
@ -6,10 +6,17 @@ import { avatarUrl, forumUserUrl } from "~/composables/useUrlHelper";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import Card from "~/components/design/Card.vue";
|
||||
import TaglineModal from "~/components/modals/TaglineModal.vue";
|
||||
import { computed } from "vue";
|
||||
import { computed, FunctionalComponent } from "vue";
|
||||
import { NamedPermission } from "~/types/enums";
|
||||
import { hasPerms } from "~/composables/usePerm";
|
||||
import { useAuthStore } from "~/store/auth";
|
||||
import Button from "~/components/design/Button.vue";
|
||||
import Tooltip from "~/components/design/Tooltip.vue";
|
||||
import IconMdiWrench from "~icons/mdi/wrench";
|
||||
import IconMdiCog from "~icons/mdi/cog";
|
||||
import IconMdiKey from "~icons/mdi/key";
|
||||
import IconMdiCalendar from "~icons/mdi/calendar";
|
||||
import Link from "~/components/design/Link.vue";
|
||||
|
||||
const props = defineProps<{
|
||||
user: User;
|
||||
@ -26,6 +33,36 @@ const isCurrentUser = computed(() => {
|
||||
const canEditCurrentUser = computed(() => {
|
||||
return hasPerms(NamedPermission.EDIT_ALL_USER_SETTINGS) || isCurrentUser || hasPerms(NamedPermission.EDIT_SUBJECT_SETTINGS);
|
||||
});
|
||||
|
||||
interface UserButton {
|
||||
icon: FunctionalComponent;
|
||||
action?: () => void;
|
||||
attr: {
|
||||
to?: string;
|
||||
href?: string;
|
||||
};
|
||||
name: string;
|
||||
}
|
||||
|
||||
const buttons = computed<UserButton[]>(() => {
|
||||
const list = [] as UserButton[];
|
||||
if (!props.user.isOrganization) {
|
||||
if (isCurrentUser.value) {
|
||||
list.push({ icon: IconMdiCog, attr: { href: `${import.meta.env.HANGAR_AUTH_HOST}/account/settings` }, name: "settings" });
|
||||
}
|
||||
if (isCurrentUser.value || hasPerms(NamedPermission.EDIT_ALL_USER_SETTINGS)) {
|
||||
list.push({ icon: IconMdiKey, attr: { to: "/" + props.user.name + "/settings/api-keys" }, name: "apiKeys" });
|
||||
}
|
||||
}
|
||||
if ((hasPerms(NamedPermission.MOD_NOTES_AND_FLAGS) || hasPerms(NamedPermission.REVIEWER)) && !props.user.isOrganization) {
|
||||
list.push({ icon: IconMdiCalendar, attr: { to: `/admin/activities/${props.user.name}` }, name: "activity" });
|
||||
}
|
||||
if (hasPerms(NamedPermission.EDIT_ALL_USER_SETTINGS)) {
|
||||
list.push({ icon: IconMdiWrench, attr: { to: "/admin/user/" + props.user.name }, name: "admin" });
|
||||
}
|
||||
|
||||
return list;
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@ -48,8 +85,15 @@ const canEditCurrentUser = computed(() => {
|
||||
<span v-if="user.tagline">{{ user.tagline }}</span>
|
||||
<span v-else-if="canEditCurrentUser">{{ i18n.t("author.addTagline") }}</span>
|
||||
<TaglineModal :tagline="user.tagline" :action="`${user.isOrganization ? 'organizations/org' : 'users'}/${user.name}/settings/tagline`" />
|
||||
<!-- todo user log modal -->
|
||||
</div>
|
||||
|
||||
<Tooltip v-for="btn in buttons" :key="btn.name" :content="i18n.t(`author.tooltips.${btn.name}`)">
|
||||
<Link v-bind="btn.attr">
|
||||
<Button size="small"><component :is="btn.icon" /></Button>
|
||||
</Link>
|
||||
</Tooltip>
|
||||
|
||||
<!-- todo lock user modal -->
|
||||
</div>
|
||||
|
||||
<div class="flex-grow" />
|
||||
|
38
frontend-new/src/components/design/Tooltip.vue
Normal file
38
frontend-new/src/components/design/Tooltip.vue
Normal file
@ -0,0 +1,38 @@
|
||||
<script lang="ts" setup>
|
||||
import Popper from "vue3-popper";
|
||||
import { defineComponent, onMounted, ref } from "vue";
|
||||
|
||||
const ServerOnly = defineComponent({
|
||||
name: "ServerOnly",
|
||||
setup(_, { slots }) {
|
||||
const show = ref(true);
|
||||
onMounted(() => {
|
||||
show.value = false;
|
||||
});
|
||||
return () => (show.value && slots.default ? slots.default() : null);
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ClientOnly>
|
||||
<Popper v-bind="$attrs" hover open-delay="200" close-delay="100">
|
||||
<slot />
|
||||
<template #content="props">
|
||||
<slot name="content" v-bind="props" />
|
||||
</template>
|
||||
</Popper>
|
||||
</ClientOnly>
|
||||
<ServerOnly>
|
||||
<slot />
|
||||
</ServerOnly>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
:deep(.popper) {
|
||||
background: #464646;
|
||||
padding: 0.5rem;
|
||||
border-radius: 0.375rem;
|
||||
color: #fff;
|
||||
}
|
||||
</style>
|
1
frontend-new/src/env.d.ts
vendored
1
frontend-new/src/env.d.ts
vendored
@ -3,6 +3,7 @@
|
||||
interface ImportMetaEnv {
|
||||
readonly HANGAR_PUBLIC_HOST: string;
|
||||
readonly HANGAR_PROXY_HOST: string;
|
||||
readonly HANGAR_AUTH_HOST: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
|
Loading…
Reference in New Issue
Block a user