New elements and updates

This commit is contained in:
René Preuß
2023-02-20 18:42:21 +01:00
parent 40d02e52ec
commit d9041f471e
11 changed files with 334 additions and 14 deletions

View File

@@ -4,6 +4,10 @@
:class="computedClass"
@click="click"
>
<i
v-if="icon"
:class="['fal mr-1', icon]"
/>
<slot v-if="!loading" />
<template v-else>
<i class="fas fa-spinner fa-spin" />
@@ -16,6 +20,10 @@ export default {
name: "BitinflowButton",
props: {
icon: {
type: String,
default: null
},
size: {
type: String,
default: 'md'
@@ -59,9 +67,11 @@ export default {
.disabled {
@apply opacity-50 cursor-not-allowed;
}
.loading {
@apply opacity-50 cursor-not-allowed;
}
.button-text-sm {
@apply text-sm;
}
@@ -97,6 +107,7 @@ export default {
.primary-solid {
@apply bg-primary-500 hover:bg-primary-600 dark:bg-primary-500 dark:hover:bg-primary-400 text-white;
}
.primary-outline {
@apply border-primary-500 hover:bg-primary-500 dark:hover:bg-primary-500 dark:border-primary-500 dark:hover:border-primary-500 text-primary-500 hover:text-white;
}
@@ -104,6 +115,7 @@ export default {
.danger-solid {
@apply bg-rose-500 hover:bg-rose-600 dark:bg-rose-500 dark:hover:bg-rose-400 text-white;
}
.danger-outline {
@apply border-rose-500 hover:bg-rose-500 dark:hover:bg-rose-500 dark:border-rose-500 dark:hover:border-rose-500 text-rose-500 hover:text-white;
}
@@ -111,6 +123,7 @@ export default {
.warning-solid {
@apply bg-amber-500 hover:bg-amber-600 dark:bg-amber-500 dark:hover:bg-amber-400 text-white;
}
.warning-outline {
@apply border-amber-500 hover:bg-amber-500 dark:hover:bg-amber-500 dark:border-amber-500 dark:hover:border-amber-500 text-amber-500 hover:text-white;
}
@@ -118,6 +131,7 @@ export default {
.base-solid {
@apply bg-white hover:bg-zinc-100 dark:bg-base-700 dark:hover:bg-base-600 text-black dark:text-white;
}
.base-outline {
@apply border-zinc-100 hover:bg-zinc-100 dark:hover:bg-base-700 dark:border-base-600 dark:hover:border-base-600 text-black dark:text-white;
}
@@ -125,6 +139,7 @@ export default {
.light-solid {
@apply bg-zinc-200 hover:bg-zinc-300 dark:bg-base-600 dark:hover:bg-base-500 text-black dark:text-white;
}
.light-outline {
@apply border-zinc-200 hover:bg-zinc-200 hover:border-zinc-200 dark:hover:bg-base-500 dark:border-base-500 dark:hover:border-base-500 text-black dark:text-white;
}

View File

@@ -1,7 +1,8 @@
<template>
<nuxt-link
class="hover:bg-primary-500 rounded-lg text-center text-xs py-4 flex flex-col space-y-2"
href="#"
:class="calculateClasses"
:to="to"
>
<i :class="['fal text-xl', icon]" />
<span>
@@ -17,7 +18,29 @@ export default {
icon: {
type: String,
default: 'fa-arrow-up-right-from-square'
},
to: {
type: String,
default: '/'
}
},
computed: {
calculateClasses: function () {
return {
'router-link-active': this.$route.path.includes(this.to) && this.to !== '/',
}
}
}
}
</script>
<style scoped>
.router-link-active {
@apply bg-primary-500 dark:bg-primary-500;
}
/*
.router-link-active:hover {
@apply bg-primary-600 dark:bg-primary-400;
}
*/
</style>

View File

@@ -139,6 +139,12 @@ export default {
],
};
},
mounted() {
// restore dark mode from local storage
if (localStorage.getItem('darkMode') === 'true') {
document.body.classList.add('dark');
}
},
methods: {
toggleMenu() {
this.$refs.overlay.classList.toggle('hidden');
@@ -166,7 +172,8 @@ export default {
}, 500);
});
}
document.body.classList.toggle('dark')
const result = document.body.classList.toggle('dark')
localStorage.setItem('darkMode', result ? 'true' : 'false');
}
},
};

View File

@@ -0,0 +1,15 @@
<template>
<div class="flex-1">
<slot />
</div>
</template>
<script>
export default {
name: "BitinflowFlex1"
}
</script>
<style scoped>
</style>

View File

@@ -6,7 +6,7 @@
<script>
export default {
name: "BitinflowFlex"
name: "BitinflowFlexAuto"
}
</script>

View File

@@ -1,9 +1,9 @@
<template>
<bitinflow-button
class="flex items-center gap-2 w-full"
icon="fa-plus"
@click="$emit('click')"
>
<i :class="['fal', icon]" />
<slot />
</bitinflow-button>
</template>

View File

@@ -1,6 +1,7 @@
<template>
<bitinflow-button-link
class="flex items-center gap-2"
:class="calculateClasses"
:to="to"
>
<i :class="['fal', icon]" />
@@ -23,6 +24,25 @@ export default {
type: String,
required: true
}
},
computed: {
calculateClasses: function () {
return {
'router-link-active': this.$route.path.includes(this.to),
}
}
}
}
</script>
<style scoped>
.router-link-active, .router-link-exact-active {
@apply bg-primary-500 dark:bg-primary-500;
}
/*
.router-link-active:hover, .router-link-exact-active:hover {
@apply bg-primary-600 dark:bg-primary-400;
}
*/
</style>

View File

@@ -1,7 +1,7 @@
<!-- eslint-disable vue/require-explicit-emits -->
<template>
<nav
class="w-64 bg-white text-black shadow dark:bg-base-700 dark:text-white dark:border-base-900 dark:border-l flex flex-col overflow-y-auto h-screen absolute sm:relative transform -translate-x-full sm:translate-x-0 pt-10 pb-4 px-4 space-y-2"
class="w bg-white text-black shadow dark:bg-base-700 dark:text-white dark:border-base-900 dark:border-l flex flex-col overflow-y-auto h-screen absolute sm:relative transform -translate-x-full sm:translate-x-0 pt-10 pb-4 px-4 space-y-2"
>
<span class="font-semibold px-4">
<slot name="title" />
@@ -14,11 +14,23 @@
<div
v-for="i in 3"
:key="i"
class="bg-zinc-100 dark:bg-base-600 rounded-lg px-4 py-2"
>
&nbsp;
</div>
class="bg-zinc-100 dark:bg-base-600 rounded-lg px-4 py-2 h-10 animate-pulse"
/>
</template>
<div v-else-if="empty" class="bg-zinc-100 dark:bg-base-600 rounded-lg px-4 py-16 text-xl opacity-50 text-center">
<i class="fas fa-ghost mr-2 text-5xl opacity-70" />
<div>
No resources found
</div>
<div class="text-xs mt-2 opacity-70">
<template v-if="hasCreateListener">
Click on the <span class="font-bold"><i class="far fa-plus" /> Create Resource</span> button below to create your first resource.
</template>
<template v-else>
You don't have any resources yet.
</template>
</div>
</div>
</div>
<div v-if="hasCreateListener">
<bitinflow-second-level-button
@@ -51,6 +63,10 @@ export default {
loading: {
type: Boolean,
default: false
},
empty: {
type: Boolean,
default: false
}
},

View File

@@ -0,0 +1,135 @@
<template>
<template v-if="loading">
<div
v-for="i in 3"
:key="i"
class="bg-white text-black dark:bg-base-700 rounded-lg h-16 animate-pulse"
/>
</template>
<div
v-else-if="items.length === 0"
class="bg-white dark:bg-base-700 rounded-lg px-4 py-16 text-xl text-center text-black dark:text-white"
>
<i class="fas fa-ghost mr-2 text-5xl opacity-70" />
<div>
No resources found
</div>
<div class="text-xs mt-2 opacity-70">
<template v-if="hasCreateListener">
Click on the
<span class="font-bold"><i class="far fa-plus" /> Create Resource</span>
button below to create your first resource.
</template>
<template v-else>
You don't have any resources yet.
</template>
</div>
<div v-if="hasCreateListener">
<bitinflow-button
color="light"
variant="outline"
class="mt-8"
size="sm"
icon="fa-plus"
@click="$emit('create')"
>
Create Resource
</bitinflow-button>
</div>
</div>
<div
v-else
class="text-black dark:text-white"
>
<div class="flex gap-4 py-2">
<div>
<bitinflow-table-checkbox
v-model="checkedAll"
@update:model-value="toggleAll"
/>
</div>
<div
class="flex-auto px-6"
:class="gridClass"
>
<template
v-for="key in keys"
:key="key"
>
<div class="opacity-80">{{ columns[key].label }}</div>
</template>
</div>
</div>
<div class="grid gap-4">
<bitinflow-table-row
v-for="item in items"
:key="item.id"
:grid-class="gridClass"
@click="click(item)"
>
<slot
name="row"
:item="item"
:keys="keys"
/>
</bitinflow-table-row>
</div>
</div>
</template>
<script>
import BitinflowTableRow from "../../../dist/runtime/components/BitinflowTableRow.vue";
import BitinflowTableCheckbox from "./BitinflowTableCheckbox.vue";
export default {
name: "BitinflowTable",
components: {BitinflowTableCheckbox, BitinflowTableRow},
props: {
columns: {
type: Array,
required: true
},
items: {
type: Array,
required: true
},
loading: {
type: Boolean,
default: false
}
},
data() {
return {
keys: Object.keys(this.columns),
checkedAll: false,
}
},
computed: {
gridClass() {
return `grid grid-cols-${this.keys.length} gap-4`;
},
hasCreateListener() {
return this.$attrs && this.$attrs.onCreate;
}
},
methods: {
title(value) {
// "humanized" by converting kebab-case, snake_case, and camelCase to individual words and capitalizes each word.
return value.replace(/([A-Z])/g, ' $1').replace(/[-_]/g, ' ').toLowerCase().replace(/(?:^|\s)\S/g, function(a) { return a.toUpperCase(); });
},
toggleAll(checked) {
console.log('toggleAll', checked)
},
click(item) {
this.$emit('click', item);
}
}
}
</script>

View File

@@ -0,0 +1,37 @@
<template>
<a
class="w-4 h-4 flex justify-center rounded p-2 text-black dark:text-white border-2 border-zinc-200 dark:border-base-600 dark:bg-base-700 dark:text-white"
href="#"
@click.prevent="toggle"
>
<i
v-if="modelValue"
class="fas fa-check text-xs text-primary-500 self-center"
/>
</a>
</template>
<script>
export default {
name: "BitinflowTableCheckbox",
props: {
modelValue: {
type: Boolean,
default: false
}
},
emits: ['update:modelValue'],
methods: {
toggle() {
this.$emit('update:modelValue', !this.modelValue);
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,52 @@
<template>
<div class="flex gap-4">
<div class="self-center">
<bitinflow-table-checkbox v-model="checked" />
</div>
<div class="flex-auto relative">
<a
class="after:absolute after:inset-0"
href="#"
@click.prevent="click"
/>
<div
class="bg-white border-2 text-black dark:bg-base-700 dark:text-white rounded shadow py-4 px-6"
:class="checked ? 'border-primary-500' : 'border-transparent'"
>
<div :class="gridClass" class="items-center">
<slot />
</div>
</div>
</div>
</div>
</template>
<script>
import BitinflowTableCheckbox from "./BitinflowTableCheckbox.vue";
export default {
name: "BitinflowTableRow",
components: {BitinflowTableCheckbox},
props: {
gridClass: {
type: String,
required: true
}
},
emits: ['click'],
data() {
return {
checked: false
}
},
methods: {
click() {
this.$emit('click');
}
}
}
</script>