Skip to content

Commit

Permalink
Add support for collapse navigator and global config (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
崔庆才丨静觅 authored Jan 7, 2024
1 parent 8b53968 commit 576e0a7
Show file tree
Hide file tree
Showing 20 changed files with 305 additions and 50 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "minor",
"comment": "add config support global",
"packageName": "@zhishuyun/hub",
"email": "[email protected]",
"dependentChangeType": "patch"
}
20 changes: 20 additions & 0 deletions hub.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
module.exports = {
site: {
logo: {
url: 'https://hub.zhishuyun.com/assets/logo.da8de841.svg',
width: 'auto',
height: 'auto'
}
},
apps: {
chat: {
enabled: true
},
midjourney: {
enabled: true
}
},
distribution: {
inviterId: '123'
}
};
10 changes: 9 additions & 1 deletion src/components/common/AuthPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,15 @@ export default defineComponent({
return `${getBaseUrlAuth()}/auth/login?inviter_id=${this.inviterId}`;
},
inviterId() {
const result = this.$route.query.inviter_id?.toString() || getCookie('INVITER_ID');
// if forceInviterId is set, then use forceInviterId
if (this.$config?.distribution?.forceInviterId) {
return this.$config?.distribution?.defaultInviterId;
}
// Otherwise, use the inviter_id in the url, then use the inviter_id in the cookie, and finally use the default inviter_id
const result =
this.$route.query.inviter_id?.toString() ||
getCookie('INVITER_ID') ||
this.$config?.distribution?.defaultInviterId;
return result;
},
authenticated() {
Expand Down
38 changes: 38 additions & 0 deletions src/components/common/Chevron.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<template>
<font-awesome-icon :icon="icon" class="icon" />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
export default defineComponent({
name: 'Chevron',
components: {
FontAwesomeIcon
},
props: {
direction: {
type: String,
default: 'right'
}
},
computed: {
icon(): string {
return `fa-solid fa-chevron-${this.direction}`;
}
}
});
</script>

<style lang="scss" scoped>
.icon {
font-size: 12px;
border: 1px solid var(--el-border-color);
border-radius: 50%;
padding: 5px 6px;
cursor: pointer;
color: var(--el-color-black);
background: var(--el-color-white);
}
</style>
146 changes: 114 additions & 32 deletions src/components/common/Navigator.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
<template>
<div class="navigator">
<chevron v-if="collapsed" class="chevron" direction="right" @click="onOpenMenu"></chevron>
<chevron v-else class="chevron" direction="left" @click="onCollapseMenu"></chevron>
<div class="top">
<div v-for="(link, linkIndex) in links" :key="linkIndex" class="link">
<el-tooltip effect="dark" :content="link.displayName" placement="right">
<div v-if="!collapsed">
<img src="@/assets/images/logo.svg" class="logo" @click="onHome" />
</div>
<el-menu v-if="!collapsed" :default-active="activeIndex">
<el-menu-item
v-for="(link, linkIndex) in links"
:key="linkIndex"
:index="link.route.name"
@click="$router.push(link.route)"
>
<font-awesome-icon :icon="link.icon" class="mr-2" />
<template #title>{{ link.displayName }}</template>
</el-menu-item>
</el-menu>
<div v-for="(link, linkIndex) in links" v-else :key="linkIndex" class="link">
<el-tooltip v-if="collapsed" effect="dark" :content="link.displayName" placement="right">
<el-button
:class="{
button: true,
active: link.routes.includes($route.name as string)
}"
:class="{button: true, active: link.routes.includes($route.name as string)}"
@click="$router.push(link.route)"
>
<font-awesome-icon :icon="link.icon" />
Expand All @@ -16,15 +29,27 @@
</div>
</div>
<div class="middle" />
<div class="bottom">
<div class="link">
<div v-if="!collapsed" class="bottom">
<el-menu :default-active="activeIndex">
<el-menu-item @click="onConsole">
<font-awesome-icon icon="fa-solid fa-compass" class="mr-2" />
<template #title>{{ $t('common.nav.console') }}</template>
</el-menu-item>
<el-menu-item @click="onLogout">
<font-awesome-icon icon="fa-solid fa-arrow-right-from-bracket" class="mr-2" />
<template #title>{{ $t('common.nav.logOut') }}</template>
</el-menu-item>
</el-menu>
</div>
<div v-else class="bottom">
<div v-if="$config.navigation?.console" class="link">
<el-tooltip effect="dark" :content="$t('common.nav.console')" placement="right">
<el-button class="button" @click="onConsole">
<font-awesome-icon icon="fa-solid fa-compass" />
</el-button>
</el-tooltip>
</div>
<div class="link">
<div v-if="$config.navigation?.help" class="link">
<help-entry />
</div>
<div v-if="authenticated" class="link">
Expand All @@ -40,55 +65,87 @@

<script lang="ts">
import { defineComponent } from 'vue';
import { ElButton, ElTooltip } from 'element-plus';
import { ElButton, ElTooltip, ElMenu, ElMenuItem } from 'element-plus';
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome';
import {
ROUTE_CHAT_CONVERSATION,
ROUTE_CHAT_CONVERSATION_NEW,
ROUTE_CONSOLE_ROOT,
ROUTE_INDEX,
ROUTE_MIDJOURNEY_HISTORY,
ROUTE_MIDJOURNEY_INDEX
} from '@/router/constants';
import HelpEntry from './HelpEntry2.vue';
import Chevron from './Chevron.vue';
export default defineComponent({
name: 'Navigator',
components: {
ElButton,
HelpEntry,
ElTooltip,
FontAwesomeIcon
FontAwesomeIcon,
ElMenu,
ElMenuItem,
Chevron
},
data() {
return {
links: [
{
route: {
name: ROUTE_CHAT_CONVERSATION_NEW
},
displayName: this.$t('common.nav.chat'),
icon: 'fa-regular fa-comment',
image: 'https://cdn.zhishuyun.com/9ad12c99b2.png/thumb_100x100',
routes: [ROUTE_CHAT_CONVERSATION, ROUTE_CHAT_CONVERSATION_NEW]
const links = [];
if (this.$config?.navigation?.chat) {
links.push({
route: {
name: ROUTE_CHAT_CONVERSATION_NEW
},
{
route: {
name: ROUTE_MIDJOURNEY_INDEX
},
displayName: this.$t('common.nav.midjourney'),
icon: 'fa-solid fa-palette',
image: 'https://cdn.zhishuyun.com/83ee211091.png/thumb_100x100',
routes: [ROUTE_MIDJOURNEY_INDEX, ROUTE_MIDJOURNEY_HISTORY]
}
]
displayName: this.$t('common.nav.chat'),
icon: 'fa-regular fa-comment',
image: 'https://cdn.zhishuyun.com/9ad12c99b2.png/thumb_100x100',
routes: [ROUTE_CHAT_CONVERSATION, ROUTE_CHAT_CONVERSATION_NEW]
});
}
if (this.$config.navigation?.midjourney) {
links.push({
route: {
name: ROUTE_MIDJOURNEY_INDEX
},
displayName: this.$t('common.nav.midjourney'),
icon: 'fa-solid fa-palette',
image: 'https://cdn.zhishuyun.com/83ee211091.png/thumb_100x100',
routes: [ROUTE_MIDJOURNEY_INDEX, ROUTE_MIDJOURNEY_HISTORY]
});
}
return {
links,
activeIndex: this.$route.name as string
};
},
computed: {
authenticated() {
return !!this.$store.state.token.access;
},
collapsed: {
get() {
return this.$store.state.setting?.navigationCollapsed;
},
set(val: boolean) {
this.$store.commit('setSetting', {
navigationCollapsed: val
});
}
}
},
methods: {
onHome() {
this.$router.push({
name: ROUTE_INDEX
});
},
async onOpenMenu() {
this.collapsed = false;
},
async onCollapseMenu() {
this.collapsed = true;
},
async onLogout() {
await this.$store.dispatch('resetAll');
await this.$store.dispatch('chat/resetAll');
Expand All @@ -106,6 +163,31 @@ export default defineComponent({
display: flex;
flex-direction: column;
align-items: center;
position: relative;
.el-menu {
width: 150px;
border-right: none;
.el-menu-item {
height: 50px;
}
}
.chevron {
position: absolute;
right: -12px;
top: 50%;
transform: translateY(-50%) scale(0.8);
z-index: 10;
}
.logo {
width: 80%;
max-height: 40px;
cursor: pointer;
margin: 10px auto 20px auto;
display: block;
}
.top,
.bottom {
Expand All @@ -115,7 +197,7 @@ export default defineComponent({
.link {
width: 40px;
height: 40px;
margin-bottom: 10px;
margin: 0 10px 10px 10px;
.button {
width: 40px;
height: 40px;
Expand Down
16 changes: 11 additions & 5 deletions src/components/console/SidePanel.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="side-panel">
<div>
<img v-if="isOfficial" src="@/assets/images/logo.svg" class="logo" @click="onHome" />
<img src="@/assets/images/logo.svg" class="logo" @click="onHome" />
</div>
<div class="links">
<a
Expand Down Expand Up @@ -75,14 +75,20 @@ export default defineComponent({
text: this.$t('console.menu.orderList'),
name: ROUTE_CONSOLE_ORDER_LIST,
icon: 'fa-solid fa-store'
},
{
}
];
// if forcedInviterId is set, only the forced inviter can see the distribution menu
// if forcedInviterId is not set, everyone can see the distribution menu
if (!this.$config.distribution?.forceInviterId || this.user?.id === this.$config.distribution?.forceInviterId) {
links.push({
key: 'distribution-index',
text: this.$t('console.menu.distributionIndex'),
name: ROUTE_CONSOLE_DISTRIBUTION_INDEX,
icon: 'fa-solid fa-coins'
}
];
});
}
return links;
}
},
Expand Down
62 changes: 62 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
export default {
/**
* The global configuration.
*/
global: {},

/**
* The left navigation configuration.
*/
navigation: {
/**
* Show chat entry in left navigation.
*/
chat: true,

/**
* Show midjourney entry in left navigation.
*/
midjourney: true,

/**
* Show console entry in left navigation.
*/
console: true,

/**
* Show help entry in left navigation.
*/
help: true
},

/**
* The features configuration.
*/
features: {
/**
* The chat feature config.
*/
chat: {},

/**
* The midjourney feature config.
*/
midjourney: {}
},

/**
* The distribution configuration.
*/
distribution: {
/**
* The default inviter id to use when no inviter id (in url) is provided,
*/
defaultInviterId: undefined,

/**
* Force the inviter id to be used, even if an inviter id is provided.
* Note: if the forceInviterId is set, there will be no distribution page in console except for the forced inviter.
*/
forceInviterId: undefined
}
};
Loading

0 comments on commit 576e0a7

Please sign in to comment.