mirror of
https://github.com/MarcZierle/photo-log-frontend.git
synced 2025-04-07 13:04:37 +00:00
add subgroups
This commit is contained in:
parent
3db2070ef3
commit
f5148dd017
43
package-lock.json
generated
43
package-lock.json
generated
@ -1,15 +1,16 @@
|
||||
{
|
||||
"name": "zierle-training-online-tools",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "zierle-training-online-tools",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"dependencies": {
|
||||
"autoprefixer": "^9.8.8",
|
||||
"axios": "^0.24.0",
|
||||
"lorem-ipsum": "^2.0.8",
|
||||
"postcss": "^7.0.39",
|
||||
"tailwind-children": "^0.5.0",
|
||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.17",
|
||||
@ -2542,6 +2543,29 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz",
|
||||
"integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg=="
|
||||
},
|
||||
"node_modules/lorem-ipsum": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.8.tgz",
|
||||
"integrity": "sha512-5RIwHuCb979RASgCJH0VKERn9cQo/+NcAi2BMe9ddj+gp7hujl6BI+qdOG4nVsLDpwWEJwTVYXNKP6BGgbcoGA==",
|
||||
"dependencies": {
|
||||
"commander": "^9.3.0"
|
||||
},
|
||||
"bin": {
|
||||
"lorem-ipsum": "dist/bin/lorem-ipsum.bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 8.x",
|
||||
"npm": ">= 5.x"
|
||||
}
|
||||
},
|
||||
"node_modules/lorem-ipsum/node_modules/commander": {
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz",
|
||||
"integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw==",
|
||||
"engines": {
|
||||
"node": "^12.20.0 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
@ -5890,6 +5914,21 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz",
|
||||
"integrity": "sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg=="
|
||||
},
|
||||
"lorem-ipsum": {
|
||||
"version": "2.0.8",
|
||||
"resolved": "https://registry.npmjs.org/lorem-ipsum/-/lorem-ipsum-2.0.8.tgz",
|
||||
"integrity": "sha512-5RIwHuCb979RASgCJH0VKERn9cQo/+NcAi2BMe9ddj+gp7hujl6BI+qdOG4nVsLDpwWEJwTVYXNKP6BGgbcoGA==",
|
||||
"requires": {
|
||||
"commander": "^9.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"commander": {
|
||||
"version": "9.4.0",
|
||||
"resolved": "https://registry.npmjs.org/commander/-/commander-9.4.0.tgz",
|
||||
"integrity": "sha512-sRPT+umqkz90UA8M1yqYfnHlZA7fF6nSphDtxeywPZ49ysjxDQybzk13CL+mXekDRG92skbcqCLVovuCusNmFw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"lru-cache": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||
|
@ -3,14 +3,15 @@
|
||||
"version": "0.2.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src"
|
||||
"dev": "vite",
|
||||
"build": "vite build",
|
||||
"serve": "vite preview",
|
||||
"lint": "eslint --ext .js,.vue --ignore-path .gitignore --fix src"
|
||||
},
|
||||
"dependencies": {
|
||||
"autoprefixer": "^9.8.8",
|
||||
"axios": "^0.24.0",
|
||||
"lorem-ipsum": "^2.0.8",
|
||||
"postcss": "^7.0.39",
|
||||
"tailwind-children": "^0.5.0",
|
||||
"tailwindcss": "npm:@tailwindcss/postcss7-compat@^2.2.17",
|
||||
|
@ -1,7 +1,7 @@
|
||||
import axios from 'axios'
|
||||
|
||||
const apiClient = axios.create({
|
||||
baseURL: 'https://zierle-training-staging.riezel.com/api/v1',
|
||||
baseURL: 'https://zierle-training.riezel.com/api/v1',
|
||||
withCredentials: false,
|
||||
timeout: 10000,
|
||||
headers: {
|
||||
|
@ -1,5 +1,11 @@
|
||||
<template>
|
||||
<nav class="flex flex-row static">
|
||||
<nav
|
||||
class="flex flex-row fixed top-0 z-50 w-full transition-all bg-white"
|
||||
:class="{
|
||||
'bg-opacity-100' : showNavBg,
|
||||
'bg-opacity-0' : !showNavBg,
|
||||
}"
|
||||
>
|
||||
<router-link :to="{name: 'Home'}">Home</router-link>
|
||||
<router-link :to="{name: 'ManagePhotos'}">Photos</router-link>
|
||||
<router-link :to="{name: 'LogsList'}">All Logs</router-link>
|
||||
@ -13,24 +19,37 @@
|
||||
export default {
|
||||
name: 'NavBar',
|
||||
data() {
|
||||
return {}
|
||||
}
|
||||
return {
|
||||
scrollThreshold: 120,
|
||||
scrollPosition: 0,
|
||||
showNavBg: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('scroll', this.updateScrollPosition)
|
||||
},
|
||||
methods: {
|
||||
updateScrollPosition() {
|
||||
this.scrollPosition = window.scrollY
|
||||
|
||||
if (!this.showNavBg && this.scrollPosition >= this.scrollThreshold) {
|
||||
this.showNavBg = true
|
||||
} else if (this.showNavBg && this.scrollPosition <= 10) {
|
||||
this.showNavBg = false
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
nav {
|
||||
width: 100%;
|
||||
box-shadow: 0px 0px 10px rgba(0,0,0,0.2);
|
||||
margin-bottom: 1em;
|
||||
background: rgba(255,255,255,0.2);
|
||||
backdrop-filter: blur(10px);
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 0.75em;
|
||||
transition: all 0.15s ease-in-out;
|
||||
border-right: 1px solid #eee;
|
||||
}
|
||||
|
||||
.router-link-exact-active,
|
||||
|
48
src/components/ui/PrimaryButton.vue
Normal file
48
src/components/ui/PrimaryButton.vue
Normal file
@ -0,0 +1,48 @@
|
||||
<template>
|
||||
<button
|
||||
@click="emit('click')"
|
||||
>
|
||||
<slot></slot>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
emits: ['click'],
|
||||
setup () {
|
||||
|
||||
|
||||
return {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
button {
|
||||
transition: all .3s ease-in-out;
|
||||
height: 3.5rem;
|
||||
padding: 0 26px;
|
||||
line-height: 2;
|
||||
color: rgb(250, 251, 252);
|
||||
overflow: hidden;
|
||||
background: linear-gradient(180deg,rgba(66,76,222,.2),transparent 100%,rgba(66,76,222,0) 0),linear-gradient(90deg,rgba(37,6,228,.8),rgba(54,126,255,.8) 80%,rgba(54,126,255,.8)),rgba(66,76,222,.8);
|
||||
box-shadow: 0 4px 4px rgb(0 0 0 / 8%), 0 -1px 1px rgb(0 0 0 / 8%), 0 2px 2px rgb(0 0 0 / 16%), inset 0 1px 0 hsl(0deg 0% 100% / 16%);
|
||||
background-size: 200% 100%;
|
||||
background-position-x: 50%;
|
||||
cursor: pointer;
|
||||
font-family: Eina,system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji;
|
||||
font-size: .9375rem;
|
||||
text-transform: none;
|
||||
justify-content: center;
|
||||
border-radius: .625rem;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background-position-x: 98%;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background-position-x: 0%;
|
||||
}
|
||||
</style>
|
@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="banner-bg">
|
||||
<div class="banner-bg opacity-50">
|
||||
<div>
|
||||
<n-gradient-text :size="40" type="success">
|
||||
Zierle-Training
|
||||
@ -17,7 +17,9 @@
|
||||
<n-space vertical>
|
||||
<h2 class="font-bold text-xl mb-4">Documents</h2>
|
||||
<a target="_blank" href='https://dev.marczierle.com/zierle-training/generate_document/modify_document.php?selection=0'>
|
||||
<n-button type="primary">All Documents</n-button>
|
||||
<PrimaryButton>
|
||||
All Documents
|
||||
</PrimaryButton>
|
||||
</a>
|
||||
</n-space>
|
||||
<n-space vertical>
|
||||
@ -46,6 +48,8 @@
|
||||
<n-button @click='set_lang("en")'>EN</n-button>
|
||||
<n-button @click='set_lang("de")'>DE</n-button>
|
||||
-->
|
||||
|
||||
{{ lorem.generateParagraphs(20) }}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -54,10 +58,29 @@
|
||||
import CameraAdd20Filled from '@vicons/fluent/CameraAdd20Filled'
|
||||
import { loadAndSetLocale } from '@/i18n.js'
|
||||
|
||||
import PrimaryButton from '../components/ui/PrimaryButton.vue'
|
||||
|
||||
import { LoremIpsum } from "lorem-ipsum"
|
||||
|
||||
export default {
|
||||
name: 'HomeView',
|
||||
components: {
|
||||
CameraAdd20Filled
|
||||
CameraAdd20Filled,
|
||||
PrimaryButton,
|
||||
},
|
||||
setup() {
|
||||
const lorem = new LoremIpsum({
|
||||
sentencesPerParagraph: {
|
||||
max: 8,
|
||||
min: 4
|
||||
},
|
||||
wordsPerSentence: {
|
||||
max: 16,
|
||||
min: 4
|
||||
}
|
||||
})
|
||||
|
||||
return { lorem }
|
||||
},
|
||||
methods: {
|
||||
set_lang(locale) {
|
||||
|
@ -2,15 +2,50 @@
|
||||
<div>
|
||||
<h1 class="font-bold text-2xl m-4 my-6">Manage Photos</h1>
|
||||
<n-collapse
|
||||
v-if="photoGroups && photoGroups.length > 0"
|
||||
v-if="parentPhotoGroups && parentPhotoGroups.length > 0"
|
||||
@item-header-click="loadPhotosInGroup"
|
||||
>
|
||||
<n-collapse-item
|
||||
v-for="group in photoGroups" :key="group.id"
|
||||
v-for="group in parentPhotoGroups" :key="group.id"
|
||||
:title="group.name"
|
||||
:name="group.id">
|
||||
<template #header-extra>{{ group.date }}</template>
|
||||
|
||||
<n-space
|
||||
v-if="groupsInPhotogroup(group.id).length > 0"
|
||||
>
|
||||
<n-collapse-item
|
||||
v-for="group in groupsInPhotogroup(group.id)" :key="group.id"
|
||||
:title="group.name"
|
||||
:name="group.id"
|
||||
>
|
||||
<template #header-extra>{{ group.date }}</template>
|
||||
|
||||
<div style="text-align: center">
|
||||
<p v-if="is_group_loading.get(group.id)">loading...</p>
|
||||
<p v-else-if="!photos[group.id]">no photos in group found</p>
|
||||
</div>
|
||||
|
||||
<n-space>
|
||||
<PhotoItem
|
||||
v-for="(photo, idx) in photos[group.id]" :key="idx"
|
||||
:src="getPhotoSrcById(photo.id)"
|
||||
:can_change_group="true"
|
||||
:can_crop="true"
|
||||
:can_change_ocr="true"
|
||||
:can_change_tag="true"
|
||||
:can_delete="true"
|
||||
:loading="photosStatus[photo.id] === 'cropping'"
|
||||
@update:group="change_group_modal(photo.id)"
|
||||
@update:crop="change_crop_modal(photo.id)"
|
||||
@update:ocr="change_ocr_modal(photo.id)"
|
||||
@update:tag="change_tag_modal(photo.id)"
|
||||
@update:delete="change_delete_modal(photo.id)"
|
||||
/>
|
||||
</n-space>
|
||||
</n-collapse-item>
|
||||
</n-space>
|
||||
|
||||
<div style="text-align: center">
|
||||
<p v-if="is_group_loading.get(group.id)">loading...</p>
|
||||
<p v-else-if="!photos[group.id]">no photos in group found</p>
|
||||
@ -192,7 +227,7 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
photoGroups() {
|
||||
allPhotoGroups() {
|
||||
let groups = this.$store.state.photoGroups
|
||||
if (groups !== null && groups.length > 0) {
|
||||
groups = [...groups].sort((a,b) => {
|
||||
@ -207,6 +242,11 @@ export default {
|
||||
}
|
||||
return []
|
||||
},
|
||||
parentPhotoGroups() {
|
||||
let groups = this.allPhotoGroups
|
||||
groups = groups.filter(group => group.parent === undefined || group.parent === null)
|
||||
return groups
|
||||
},
|
||||
photoTags() {
|
||||
let tags = this.$store.state.photoTags
|
||||
if (tags !== null && tags.length > 0) {
|
||||
@ -221,12 +261,12 @@ export default {
|
||||
return this.$store.state.photosStatus
|
||||
},
|
||||
groups_select_options() {
|
||||
if (this.photoGroups.length > 0) {
|
||||
if (this.allPhotoGroups.length > 0) {
|
||||
let options = []
|
||||
for (const idx in this.photoGroups) {
|
||||
for (const idx in this.allPhotoGroups) {
|
||||
options.push({
|
||||
value: this.photoGroups[idx].id,
|
||||
label: this.photoGroups[idx].name,
|
||||
value: this.allPhotoGroups[idx].id,
|
||||
label: this.allPhotoGroups[idx].name,
|
||||
})
|
||||
}
|
||||
return options
|
||||
@ -256,6 +296,11 @@ export default {
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
groupsInPhotogroup(groupId) {
|
||||
let groups = this.allPhotoGroups
|
||||
groups = groups.filter(group => group.parent === groupId)
|
||||
return groups
|
||||
},
|
||||
loadPhotosInGroup(group_data) {
|
||||
this.is_group_loading.set(group_data.name, true)
|
||||
if (group_data.expanded)
|
||||
|
Loading…
Reference in New Issue
Block a user