feat: introducing self hosted admin dashboard package (#12)

Co-authored-by: Andrew Bastin <andrewbastin.k@gmail.com>
Co-authored-by: Anwarul Islam <anwaarulislaam@gmail.com>
This commit is contained in:
Joel Jacob Stephen
2023-02-28 13:13:27 +05:30
committed by GitHub
parent 2ba05a46ee
commit 3f59597864
219 changed files with 6737 additions and 1967 deletions

View File

@@ -0,0 +1,92 @@
<template>
<header
class="flex items-center justify-between border-b border-gray-400 dark:border-gray-600 px-6 py-4 bg-neutral-50 dark:bg-neutral-900 shadow-lg"
>
<div class="flex items-center">
<button
@click="isOpen = true"
class="text-gray-200 focus:outline-none lg:hidden mr-2"
>
<icon-lucide-menu class="text-gray-300 w-6" />
</button>
<div class="mr-3 mt-2">
<button @click="expandSidebar">
<icon-lucide-sidebar-open
v-if="isExpanded"
class="text-gray-300 w-6"
/>
<icon-lucide-sidebar-close v-else class="text-gray-300 w-6" />
</button>
</div>
</div>
<div class="flex items-center">
<button class="flex mx-4 text-gray-400 focus:outline-none toggle-dark">
<icon-lucide-bell class="text-gray-300 w-6" />
</button>
<div class="relative">
<button
@click="dropdownOpen = !dropdownOpen"
class="relative z-10 block w-8 h-8 overflow-hidden rounded-full shadow focus:outline-none"
>
<img
class="object-cover w-full h-full"
src="https://media.licdn.com/dms/image/C5603AQHMCx72bNN1MA/profile-displayphoto-shrink_800_800/0/1630736416611?e=2147483647&v=beta&t=McWCdK_7t_NLeU4ze3JPB8xvwg5w50Okuj2JDBekqjw"
alt="Your avatar"
/>
</button>
<div
v-show="dropdownOpen"
@click="dropdownOpen = false"
class="fixed inset-0 z-10 w-full h-full"
></div>
<transition
enter-active-class="transition duration-150 ease-out transform"
enter-from-class="scale-95 opacity-0"
enter-to-class="scale-100 opacity-100"
leave-active-class="transition duration-150 ease-in transform"
leave-from-class="scale-100 opacity-100"
leave-to-class="scale-95 opacity-0"
>
<div
v-show="dropdownOpen"
class="absolute right-0 z-20 w-48 py-2 mt-2 bg-zinc-200 dark:bg-zinc-800 rounded-md shadow-xl"
>
<a
href="#"
class="block px-4 py-2 text-sm text-gray-800 dark:text-gray-200 hover:bg-emerald-700 hover:text-white"
>Profile</a
>
<a
href="#"
class="block px-4 py-2 text-sm text-gray-800 dark:text-gray-200 hover:bg-emerald-700 hover:text-white"
>Settings</a
>
<router-link
to="/"
class="block px-4 py-2 text-sm text-gray-800 dark:text-gray-200 hover:bg-emerald-700 hover:text-white"
>Log out</router-link
>
</div>
</transition>
</div>
</div>
</header>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { useSidebar } from '../../composables/useSidebar';
const { isOpen, isExpanded } = useSidebar();
const expandSidebar = () => {
isExpanded.value = !isExpanded.value;
};
const dropdownOpen = ref(false);
</script>

View File

@@ -0,0 +1,89 @@
<template>
<div>
<button
@click="open = true"
class="inline-flex items-center bg-emerald-700 h-8 ml-3 pl-2.5 pr-2 rounded-md shadow text-gray-200 dark:border-gray-800 border border-gray-200 leading-none py-0 hover:bg-emerald-700 focus:outline-none focus:bg-emerald-800"
>
Invite User
</button>
<div
:class="`modal ${
!open && 'opacity-0 pointer-events-none'
} z-50 fixed w-full h-full top-0 left-0 flex items-center justify-center`"
>
<div
@click="open = false"
class="absolute w-full h-full bg-neutral-800 opacity-50 modal-overlay"
></div>
<div
class="z-50 w-11/12 mx-auto overflow-y-auto bg-neutral-900 rounded shadow-lg modal-container md:max-w-md"
>
<div
class="absolute top-0 right-0 z-50 flex flex-col items-center mt-4 mr-4 text-sm text-white cursor-pointer modal-close"
>
<svg
class="text-white fill-current"
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 18 18"
>
<path
d="M14.53 4.53l-1.06-1.06L9 7.94 4.53 3.47 3.47 4.53 7.94 9l-4.47 4.47 1.06 1.06L9 10.06l4.47 4.47 1.06-1.06L10.06 9z"
/>
</svg>
<span class="text-sm">(Esc)</span>
</div>
<!-- Add margin if you want to see some of the overlay behind the modal-->
<div class="px-6 py-4 text-left modal-content">
<!--Title-->
<div class="flex items-center justify-between pb-3">
<p class="text-2xl ml-3 font-bold">{{ title }}</p>
<div class="z-50 cursor-pointer modal-close" @click="open = false">
<svg
class="text-white fill-current"
xmlns="http://www.w3.org/2000/svg"
width="18"
height="18"
viewBox="0 0 18 18"
>
<path
d="M14.53 4.53l-1.06-1.06L9 7.94 4.53 3.47 3.47 4.53 7.94 9l-4.47 4.47 1.06 1.06L9 10.06l4.47 4.47 1.06-1.06L10.06 9z"
/>
</svg>
</div>
</div>
<!--Body-->
<slot name="content"> </slot>
<!--Footer-->
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const open = ref(false);
defineProps({
title: {
type: String,
},
button: {
type: String,
},
});
</script>
<style>
.modal {
transition: opacity 0.25s ease;
}
</style>

View File

@@ -0,0 +1,100 @@
<template>
<div class="flex">
<!-- Backdrop -->
<div
:class="isOpen ? 'block' : 'hidden'"
@click="isOpen = false"
class="fixed inset-0 z-20 transition-opacity bg-black opacity-50 lg:hidden"
></div>
<!-- End Backdrop -->
<div
:class="isOpen ? 'translate-x-0 ease-out' : '-translate-x-full ease-in'"
class="flex fixed inset-y-0 left-0 z-30 overflow-y-auto transition duration-300 transform bg-neutral-200 dark:bg-neutral-900 lg:translate-x-0 lg:static lg:inset-0 border-r border-gray-300 dark:border-gray-600"
>
<div :class="isExpanded ? 'w-64' : 'w-full'">
<div class="flex items-center justify-start mt-6 ml-6">
<div class="flex items-center">
<router-link class="flex" to="/dashboard">
<img src="/public/cover.jpg" alt="" class="h-7" />
<span
v-if="isExpanded"
class="mx-2 text-xl font-semibold text-gray-600 dark:text-gray-200"
>Hoppscotch</span
>
</router-link>
</div>
</div>
<nav class="mt-10">
<router-link
class="flex items-center px-6 py-4 duration-200 border-l-4"
:class="[route.name === '/dashboard' ? activeClass : inactiveClass]"
to="/dashboard"
>
<icon-lucide-layout-dashboard
class="text-xl"
:class="route.name === '/dashboard' ? 'white' : 'gray'"
/>
<span v-if="isExpanded" class="mx-4">Dashboard</span>
</router-link>
<router-link
class="flex items-center px-6 py-4 duration-200 border-l-4 rounded-sm"
:class="[route.name === 'User' ? activeClass : inactiveClass]"
to="/users"
>
<icon-lucide-user
class="text-xl"
:class="route.path === '/users' ? 'white' : 'gray'"
/>
<span v-if="isExpanded" class="mx-4">Users</span>
</router-link>
<router-link
class="flex items-center px-6 py-4 duration-200 border-l-4 rounded-sm"
:class="[route.name === '/teams' ? activeClass : inactiveClass]"
to="/teams"
>
<icon-lucide-users
class="text-xl"
:class="route.name === '/teams' ? 'white' : 'gray'"
/>
<span v-if="isExpanded" class="mx-4">Teams</span>
</router-link>
<router-link
class="flex items-center px-6 py-4 duration-200 border-l-4 rounded-sm"
:class="[route.name === '/settings' ? activeClass : inactiveClass]"
to="/settings"
>
<icon-lucide-settings
class="text-xl"
:class="route.name === '/settings' ? 'white' : 'gray'"
/>
<span v-if="isExpanded" class="mx-4">Settings</span>
</router-link>
</nav>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { useSidebar } from '../../composables/useSidebar';
import { useRoute } from 'vue-router';
const { isOpen, isExpanded } = useSidebar();
const route = useRoute();
const activeClass =
'bg-gray-600 bg-opacity-25 text-gray-100 border-gray-100 border-emerald-600';
const inactiveClass =
'border-gray-900 text-gray-500 hover:bg-gray-600 hover:bg-opacity-25 hover:text-gray-100';
</script>