3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-06-15 10:45:01 +00:00

Merge branch 'vue-3' of github.com:TheKodeToad/Zeppelin into TheKodeToad-vue-3

This commit is contained in:
Dragory 2025-06-01 15:26:14 +03:00
commit e313a91fbb
No known key found for this signature in database
17 changed files with 367 additions and 496 deletions

View file

@ -27,7 +27,7 @@
"source-map-loader": "^4.0.1",
"tailwindcss": "^1.9.6",
"ts-loader": "^9.4.3",
"vue-loader": "^15.10.1",
"vue-loader": "^17.4.2",
"vue-style-loader": "^4.1.3",
"vue-template-compiler": "^2.7.14",
"webpack": "^5.94.0",
@ -37,7 +37,6 @@
},
"dependencies": {
"@fastify/static": "^7.0.1",
"@highlightjs/vue-plugin": "^1.0.2",
"fastify": "^4.26.2",
"highlight.js": "^11.8.0",
"humanize-duration": "^3.27.0",
@ -45,11 +44,12 @@
"marked": "^5.1.0",
"modern-css-reset": "^1.4.0",
"moment": "^2.29.4",
"vue": "^2.7.14",
"vue-material-design-icons": "^4.1.0",
"vue-router": "^3.6.5",
"vue2-ace-editor": "^0.0.15",
"vuex": "^3.6.2"
"vue": "^3.5.13",
"vue-material-design-icons": "^5.3.1",
"vue-router": "^4.5.0",
"vue3-ace-editor": "^2.2.4",
"vue3-highlightjs": "^1.0.5",
"vuex": "^4.1.0"
},
"browserslist": [
"last 2 Chrome versions"

View file

@ -21,9 +21,11 @@ export const loginCallbackGuard: NavigationGuard = async (to, from, next) => {
} else {
window.location.href = `/?error=noAccess`;
}
return next();
};
export const authRedirectGuard: NavigationGuard = async (to, form, next) => {
if (await isAuthenticated()) return next("/dashboard");
window.location.href = `${process.env.API_URL}/auth/login`;
return next();
};

View file

@ -72,11 +72,11 @@
.inline-code,
code:not([class]),
>>> code:not([class]) {
:deep(code:not([class])) {
@apply bg-gray-900;
}
.codeblock {
:deep(.codeblock) {
box-shadow: none;
}
</style>

View file

@ -15,7 +15,7 @@
}
}
a {
:deep(a) {
@apply block;
@apply py-2;
@apply px-4;

View file

@ -175,7 +175,7 @@ export default {
expiresAt: null,
});
this.$set(perm, "permissions", new Set(perm.permissions));
perm.permissions = new Set(perm.permissions);
},
onTreeUpdate(targetPermissions) {

View file

@ -19,13 +19,20 @@
</div>
</div>
<AceEditor class="rounded shadow-lg border border-gray-700 mt-4"
v-model="editableConfig"
<v-ace-editor class="rounded shadow-lg border border-gray-700 mt-4"
v-model:value="editableConfig"
@init="editorInit"
lang="yaml"
theme="tomorrow_night"
:height="editorHeight"
ref="aceEditor" />
ref="aceEditor"
v-options="{
useSoftTabs: true,
tabSize: 2
}"
:style="{
width: editorWidth + 'px',
height: editorHeight + 'px',
}" />
</div>
</template>
@ -34,14 +41,19 @@
import {ApiError} from "../../api";
import { GuildState } from "../../store/types";
import AceEditor from "vue2-ace-editor";
import { VAceEditor } from "vue3-ace-editor";
import "ace-builds/src-noconflict/ext-language_tools";
import 'ace-builds/src-noconflict/ext-searchbox';
import "ace-builds/src-noconflict/mode-yaml";
import "ace-builds/src-noconflict/theme-tomorrow_night";
let editorKeybindListener;
let windowResizeListener;
export default {
components: {
AceEditor,
VAceEditor,
},
async mounted() {
try {
@ -101,16 +113,6 @@
},
methods: {
editorInit() {
require("brace/ext/language_tools");
require('brace/ext/searchbox');
require("brace/mode/yaml");
require("brace/theme/tomorrow_night");
this.$refs.aceEditor.editor.setOptions({
useSoftTabs: true,
tabSize: 2
});
// Add Ctrl+S/Cmd+S save shortcut
const isMac = /mac/i.test(navigator.platform);
const modKeyPressed = (ev: KeyboardEvent) => (isMac ? ev.metaKey : ev.ctrlKey);
@ -131,7 +133,7 @@
if (shortcutModifierPressed(ev) && ev.key === "f") {
ev.preventDefault();
this.$refs.aceEditor.editor.execCommand("find");
this.$refs.aceEditor.getAceInstance().execCommand("find");
return;
}
};
@ -171,7 +173,7 @@
this.editorHeight = newHeight;
this.$nextTick(() => {
this.$refs.aceEditor.editor.resize();
this.$refs.aceEditor.getAceInstance().resize();
});
},
async save() {

View file

@ -31,7 +31,7 @@
<!-- Sidebar -->
<nav class="docs-sidebar px-4 pt-2 pb-3 mr-8 mb-4 border border-gray-700 rounded bg-gray-800 shadow-md flex-full lg:flex-none lg:block" v-bind:class="{ closed: !mobileMenuOpen }">
<div role="none" v-for="(group, index) in menu">
<h1 class="font-bold" :aria-owns="'menu-group-' + index" :class="{'mt-4': index !== 0}">{{ group.label }}</h1>
<h1 class="font-bold" :aria-owns="'menu-group-' + index" :class="{'mt-4': typeof index === 'number' && index !== 0}">{{ group.label }}</h1>
<ul v-bind:id="'menu-group-' + index" role="group" class="list-none pl-2">
<li role="none" v-for="item in group.items">
<router-link role="menuitem" :to="item.to" class="text-gray-300 hover:text-gray-500" v-on:click.native="onChooseMenuItem()">{{ item.label }}</router-link>

View file

@ -81,6 +81,8 @@
<h3>Summary Example</h3>
<p>
Employing what we have learnt so far, we can write a configuration that:
</p>
<ul>
<li>Alerts members of their warns in a channel, instead of DMs.</li>
<li>Alerts members of kicks and bans in their DMs.</li>
@ -105,7 +107,6 @@
for {banTime}. We welcome you back provided you do not do this
again.
</CodeBlock>
</p>
<h2>Alerts</h2>
<p>

View file

@ -49,7 +49,7 @@
class="command mb-4"
v-bind:ref="getCommandSlug(command)" v-bind:class="{target: targetCommandId === getCommandSlug(command)}">
<h4 class="text-xl font-semibold mb-0">
<span v-for="(trigger, index) in getTriggers(command)"> <span class="text-gray-600" v-if="index > 0">/</span> !{{ trigger }} </span>
<span v-for="(trigger, index) in getTriggers(command)"> <span class="text-gray-600" v-if="typeof index === 'number' && index > 0">/</span> !{{ trigger }} </span>
</h4>
<MarkdownBlock v-if="command.description"
:content="command.description"
@ -88,7 +88,7 @@
<div v-if="command.signature">
<h5 class="font-semibold mb-2">Signatures:</h5>
<ul class="list-none">
<li v-for="(signature, index) in getCommandSignatures(command)" v-bind:class="{'mt-8': index !== 0}">
<li v-for="(signature, index) in getCommandSignatures(command)" v-bind:class="{'mt-8': typeof index === 'number' && index !== 0}">
<code class="inline-code bg-gray-900">
!{{ getTriggers(command)[0] }}
<span v-for="paramInfo in getSignatureParameters(signature)">{{ renderParameterOrOption(paramInfo.name, paramInfo.param) }} </span>

View file

@ -1,7 +1,7 @@
import Vue from "vue";
import { Directive } from "vue";
Vue.directive("trim-indents", {
bind(el, binding) {
export const trimIndents: Directive = {
beforeMount(el, binding) {
const withoutStartEndWhitespace = el.innerHTML.replace(/(^\n+|\n+$)/g, "");
const mode = binding.value != null ? binding.value : "start";
@ -22,4 +22,4 @@ Vue.directive("trim-indents", {
.map((line) => line.slice(spacesToTrim))
.join("\n");
},
});
};

View file

@ -1,10 +1,8 @@
import "./style/app.pcss";
import Vue from "vue";
import { createApp } from "vue";
import VueHighlightJS from "@highlightjs/vue-plugin";
import hljs from "highlight.js/lib/core";
import hljsYaml from "highlight.js/lib/languages/yaml.js";
import VueHighlightJS from "vue3-highlightjs";
import "highlight.js/styles/base16/ocean.css";
import { router } from "./routes";
@ -13,9 +11,15 @@ import { RootStore } from "./store";
import "./directives/trim-indents";
import App from "./components/App.vue";
import { trimIndents } from "./directives/trim-indents";
const app = createApp(App);
app.use(router);
app.use(RootStore);
// Set up a read-only global variable to access specific env vars
Vue.mixin({
app.mixin({
data() {
return {
get env() {
@ -27,14 +31,8 @@ Vue.mixin({
},
});
hljs.registerLanguage("yaml", hljsYaml);
Vue.use(VueHighlightJS, { hljs });
app.use(VueHighlightJS);
const app = new Vue({
router,
store: RootStore,
el: "#app",
render(h) {
return h(App);
},
});
app.directive("trim-indents", trimIndents);
app.mount("#app");

View file

@ -1,14 +1,11 @@
import Vue from "vue";
import VueRouter from "vue-router";
import { createRouter, createWebHistory } from "vue-router";
import { authGuard, authRedirectGuard, loginCallbackGuard } from "./auth";
Vue.use(VueRouter);
export const router = new VueRouter({
mode: "history",
export const router = createRouter({
history: createWebHistory(),
routes: [
{ path: "/login", beforeEnter: authRedirectGuard },
{ path: "/login-callback", beforeEnter: loginCallbackGuard },
{ path: "/login", components: {}, beforeEnter: authRedirectGuard },
{ path: "/login-callback", component: {}, beforeEnter: loginCallbackGuard },
// Privacy policy
{
@ -97,12 +94,12 @@ export const router = new VueRouter({
scrollBehavior(to, from, savedPosition) {
if (to.hash) {
return {
selector: to.hash,
el: to.hash,
};
} else if (savedPosition) {
return savedPosition;
} else {
return { x: 0, y: 0 };
return { left: 0, top: 0 };
}
},
});

View file

@ -1,4 +1,3 @@
import Vue from "vue";
import { Module } from "vuex";
import { get, post } from "../api";
import { GuildState, LoadStatus, RootState } from "./types";
@ -89,22 +88,18 @@ export const GuildStore: Module<GuildState, RootState> = {
},
setConfig(state: GuildState, { guildId, config }) {
Vue.set(state.configs, guildId, config);
state.configs[guildId] = config;
},
setGuildPermissionAssignments(state: GuildState, { guildId, permissionAssignments }) {
if (!state.guildPermissionAssignments) {
Vue.set(state, "guildPermissionAssignments", {});
state.guildPermissionAssignments = {};
}
Vue.set(
state.guildPermissionAssignments,
guildId,
permissionAssignments.map((p) => ({
state.guildPermissionAssignments[guildId] = permissionAssignments.map((p) => ({
...p,
permissions: new Set(p.permissions),
})),
);
}));
},
setTargetPermissions(state: GuildState, { guildId, targetId, type, permissions, expiresAt }) {

View file

@ -1,14 +1,11 @@
import Vue from "vue";
import Vuex, { Store } from "vuex";
Vue.use(Vuex);
import { createStore, Store } from "vuex";
import { AuthStore } from "./auth";
import { DocsStore } from "./docs";
import { GuildStore } from "./guilds";
import { RootState } from "./types";
export const RootStore = new Vuex.Store<RootState>({
export const RootStore = createStore({
modules: {
auth: AuthStore,
guilds: GuildStore,
@ -17,16 +14,8 @@ export const RootStore = new Vuex.Store<RootState>({
});
// Set up typings so Vue/our components know about the state's types
declare module "vue/types/options" {
interface ComponentOptions<V extends Vue> {
// @ts-ignore
store?: Store<RootState>;
}
}
declare module "vue/types/vue" {
interface Vue {
// @ts-ignore
declare module "vue" {
interface ComponentCustomProperties {
$store: Store<RootState>;
}
}

View file

@ -1,6 +1,7 @@
declare module "*.vue" {
import Vue from "vue";
export default Vue;
import { DefineComponent } from "vue";
const component: DefineComponent;
export default component;
}
declare module "*.png" {

View file

@ -65,7 +65,12 @@ let config = {
// Vue / Babel / Typescript
{
test: /\.vue$/,
use: ["vue-loader"],
loader: "vue-loader",
options: {
compilerOptions: {
whitespace: 'preserve', // not the default despite the docs saying so
},
}
},
{
test: /\.tsx?$/,
@ -158,6 +163,11 @@ let config = {
},
}),
new webpack.EnvironmentPlugin(["API_URL"]),
new webpack.DefinePlugin({
__VUE_OPTIONS_API__: true,
__VUE_PROD_DEVTOOLS__: false,
__VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
})
],
resolve: {
extensions: [".ts", ".tsx", ".js", ".mjs", ".vue"],

640
package-lock.json generated

File diff suppressed because it is too large Load diff