- mail_settings_controller for setting smtp settings - added view ror rjecting dataset for editor - added new model AppConfig for stroing appwide config values - better validate_chesum.ts command with process chunking - added vue3 apps 'BasicSettings' like email, profile settings - started with 2 multilingual capabilities - npm updates
This commit is contained in:
parent
010bead723
commit
b06ccae603
67 changed files with 7820 additions and 1463 deletions
|
@ -1,8 +1,6 @@
|
|||
<!--
|
||||
- @copyright Copyright (c) 2023 Arno Kaimbacher <arno.kaimbacher@outlook.at>
|
||||
-
|
||||
- @author Marco Ambrosini <arno.kaimbacher@outlook.at>
|
||||
-
|
||||
- -
|
||||
- @license GNU AGPL version 3 or any later version
|
||||
-
|
||||
- This program is free software: you can redistribute it and/or modify
|
||||
|
@ -46,7 +44,8 @@ import Card from './Card.vue';
|
|||
// import { generateUrl } from '@nextcloud/router';
|
||||
import { loadState } from '@/utils/initialState';
|
||||
|
||||
const desktop = loadState('firstrunwizard', 'desktop');
|
||||
const desktop = loadState('firstrunwizard', 'desktop'); //'https://gitea.geologie.ac.at/geolba/tethys.backend'
|
||||
// const profileEnabledByDefault = loadState('settings', 'profileEnabledByDefault'); //true
|
||||
|
||||
export default {
|
||||
name: 'Page2',
|
||||
|
|
|
@ -51,6 +51,10 @@ const props = defineProps({
|
|||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
extraHigh: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
required: Boolean,
|
||||
borderless: Boolean,
|
||||
transparent: Boolean,
|
||||
|
@ -67,7 +71,7 @@ const inputElClass = computed(() => {
|
|||
const base = [
|
||||
'px-3 py-2 max-w-full focus:ring focus:outline-none border-gray-700 rounded w-full',
|
||||
'dark:placeholder-gray-400',
|
||||
computedType.value === 'textarea' ? 'h-44' : 'h-12',
|
||||
props.extraHigh ? 'h-80' : (computedType.value === 'textarea' ? 'h-44' : 'h-12'),
|
||||
props.borderless ? 'border-0' : 'border',
|
||||
// props.transparent && !props.isReadOnly ? 'bg-transparent' : 'bg-white dark:bg-slate-800',
|
||||
props.isReadOnly ? 'bg-gray-50 dark:bg-slate-600' : 'bg-white dark:bg-slate-800',
|
||||
|
|
30
resources/js/Components/Icons/Alert.vue
Normal file
30
resources/js/Components/Icons/Alert.vue
Normal file
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<span v-bind="$attrs" :aria-hidden="title ? null : true" :aria-label="title" class="material-design-icon alert-icon"
|
||||
role="img" @click="$emit('click', $event)">
|
||||
<svg :fill="fillColor" class="material-design-icon__svg" :width="size" :height="size" viewBox="0 0 24 24">
|
||||
<path d="M13 14H11V9H13M13 18H11V16H13M1 21H23L12 2L1 21Z">
|
||||
<title v-if="title">{{ title }}</title>
|
||||
</path>
|
||||
</svg>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AlertIcon",
|
||||
emits: ['click'],
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
fillColor: {
|
||||
type: String,
|
||||
default: "currentColor"
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 24
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
31
resources/js/Components/Icons/AlertDecagram.vue
Normal file
31
resources/js/Components/Icons/AlertDecagram.vue
Normal file
|
@ -0,0 +1,31 @@
|
|||
<template>
|
||||
<span v-bind="$attrs" :aria-hidden="title ? null : true" :aria-label="title"
|
||||
class="material-design-icon alert-decagram-icon" role="img" @click="$emit('click', $event)">
|
||||
<svg :fill="fillColor" class="material-design-icon__svg" :width="size" :height="size" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M23,12L20.56,9.22L20.9,5.54L17.29,4.72L15.4,1.54L12,3L8.6,1.54L6.71,4.72L3.1,5.53L3.44,9.21L1,12L3.44,14.78L3.1,18.47L6.71,19.29L8.6,22.47L12,21L15.4,22.46L17.29,19.28L20.9,18.46L20.56,14.78L23,12M13,17H11V15H13V17M13,13H11V7H13V13Z">
|
||||
<title v-if="title">{{ title }}</title>
|
||||
</path>
|
||||
</svg>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "AlertDecagramIcon",
|
||||
emits: ['click'],
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
fillColor: {
|
||||
type: String,
|
||||
default: "currentColor"
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 24
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
38
resources/js/Components/Icons/CheckboxMarkedCircle.vue
Normal file
38
resources/js/Components/Icons/CheckboxMarkedCircle.vue
Normal file
|
@ -0,0 +1,38 @@
|
|||
<template>
|
||||
<span v-bind="$attrs"
|
||||
:aria-hidden="title ? null : true"
|
||||
:aria-label="title"
|
||||
class="material-design-icon checkbox-marked-circle-icon"
|
||||
role="img"
|
||||
@click="$emit('click', $event)">
|
||||
<svg :fill="fillColor"
|
||||
class="material-design-icon__svg"
|
||||
:width="size"
|
||||
:height="size"
|
||||
viewBox="0 0 24 24">
|
||||
<path d="M10,17L5,12L6.41,10.58L10,14.17L17.59,6.58L19,8M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z">
|
||||
<title v-if="title">{{ title }}</title>
|
||||
</path>
|
||||
</svg>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "CheckboxMarkedCircleIcon",
|
||||
emits: ['click'],
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
fillColor: {
|
||||
type: String,
|
||||
default: "currentColor"
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 24
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
38
resources/js/Components/Icons/HelpCircle.vue
Normal file
38
resources/js/Components/Icons/HelpCircle.vue
Normal file
|
@ -0,0 +1,38 @@
|
|||
<template>
|
||||
<span v-bind="$attrs"
|
||||
:aria-hidden="title ? null : true"
|
||||
:aria-label="title"
|
||||
class="material-design-icon help-circle-icon"
|
||||
role="img"
|
||||
@click="$emit('click', $event)">
|
||||
<svg :fill="fillColor"
|
||||
class="material-design-icon__svg"
|
||||
:width="size"
|
||||
:height="size"
|
||||
viewBox="0 0 24 24">
|
||||
<path d="M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z">
|
||||
<title v-if="title">{{ title }}</title>
|
||||
</path>
|
||||
</svg>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "HelpCircleIcon",
|
||||
emits: ['click'],
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
fillColor: {
|
||||
type: String,
|
||||
default: "currentColor"
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 24
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
31
resources/js/Components/Icons/Information.vue
Normal file
31
resources/js/Components/Icons/Information.vue
Normal file
|
@ -0,0 +1,31 @@
|
|||
<template>
|
||||
<span v-bind="$attrs" :aria-hidden="title ? null : true" :aria-label="title"
|
||||
class="material-design-icon information-icon" role="img" @click="$emit('click', $event)">
|
||||
<svg :fill="fillColor" class="material-design-icon__svg" :width="size" :height="size" viewBox="0 0 24 24">
|
||||
<path
|
||||
d="M13,9H11V7H13M13,17H11V11H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2Z">
|
||||
<title v-if="title">{{ title }}</title>
|
||||
</path>
|
||||
</svg>
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "InformationIcon",
|
||||
emits: ['click'],
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
},
|
||||
fillColor: {
|
||||
type: String,
|
||||
default: "currentColor"
|
||||
},
|
||||
size: {
|
||||
type: Number,
|
||||
default: 24
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
|
@ -8,7 +8,7 @@ import { svg } from 'leaflet/src/layer/vector/SVG';
|
|||
import axios from 'axios';
|
||||
import { LatLngBoundsExpression } from 'leaflet/src/geo/LatLngBounds';
|
||||
import { tileLayerWMS } from 'leaflet/src/layer/tile/TileLayer.WMS';
|
||||
import { TileLayer } from 'leaflet/src/layer/tile/TileLayer';
|
||||
// import { TileLayer } from 'leaflet/src/layer/tile/TileLayer';
|
||||
import { Attribution } from 'leaflet/src/control/Control.Attribution';
|
||||
import DrawControlComponent from '@/Components/Map/draw.component.vue';
|
||||
import ZoomControlComponent from '@/Components/Map/zoom.component.vue';
|
||||
|
@ -59,8 +59,8 @@ Map.include({
|
|||
});
|
||||
const DEFAULT_BASE_LAYER_NAME = 'BaseLayer';
|
||||
const DEFAULT_BASE_LAYER_ATTRIBUTION = '© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors';
|
||||
// const OPENSEARCH_HOST = 'http://localhost:9200';
|
||||
const OPENSEARCH_HOST = `${process.env.OPENSEARCH_HOST}`;
|
||||
const OPENSEARCH_HOST = 'https://catalog.geosphere.at';
|
||||
// const OPENSEARCH_HOST = `${process.env.OPENSEARCH_HOST}`;
|
||||
// const OPENSEARCH_HOST = `http://${process.env.OPENSEARCH_PUBLIC_HOST}`;
|
||||
let map: Map;
|
||||
|
||||
|
|
163
resources/js/Components/NCNoteCard.vue
Normal file
163
resources/js/Components/NCNoteCard.vue
Normal file
|
@ -0,0 +1,163 @@
|
|||
<template>
|
||||
<!-- <div class="notecard" :class="`notecard--${color}`" :role="shouldShowAlert ? 'alert' : 'note'"> -->
|
||||
<div class="notecard" :class="colorsBgLight[type]" :role="shouldShowAlert ? 'alert' : 'note'">
|
||||
<!-- @slot Manually provide icon -->
|
||||
<slot name="icon">
|
||||
<component :is="icon" class="notecard__icon" :class="{ 'notecard__icon--heading': heading }" :fill-color="color"
|
||||
:size="20" />
|
||||
</slot>
|
||||
<div>
|
||||
<p v-if="heading" class="font-bold">
|
||||
{{ heading }}
|
||||
</p>
|
||||
<!-- @slot The main content (overwrites the `text` prop) -->
|
||||
<slot>
|
||||
<p class="notecard__text">
|
||||
{{ text }}
|
||||
</p>
|
||||
</slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- <div v-if="flash && flash.message" class="flex flex-col mt-6 animate-fade-in">
|
||||
<div class="bg-yellow-500 border-l-4 border-orange-400 text-white p-4" role="alert">
|
||||
<p class="font-bold">Be Warned</p>
|
||||
<p>{{ flash.message }}</p>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
<script lang="ts">
|
||||
import CheckboxMarkedCircle from './Icons/CheckboxMarkedCircle.vue';
|
||||
import AlertDecagram from './Icons/AlertDecagram.vue';
|
||||
import Alert from './Icons/Alert.vue';
|
||||
import Information from './Icons/Information.vue';
|
||||
import { colorsBgLight } from '@/colors';
|
||||
|
||||
export default {
|
||||
name: 'NcNoteCard',
|
||||
|
||||
data() {
|
||||
return {
|
||||
colorsBgLight: colorsBgLight,
|
||||
};
|
||||
},
|
||||
|
||||
props: {
|
||||
/**
|
||||
* Type or severity of the message
|
||||
*/
|
||||
type: {
|
||||
type: String,
|
||||
default: 'warning',
|
||||
validator: (type: string) => ['success', 'info', 'warning', 'danger'].includes(type),
|
||||
},
|
||||
/**
|
||||
* Enforce the `alert` role on the note card.
|
||||
*
|
||||
* The [`alert` role](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/alert_role)
|
||||
* should only be used for information that requires the user's immediate attention.
|
||||
*/
|
||||
showAlert: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
/**
|
||||
* Optional text to show as a heading of the note card
|
||||
*/
|
||||
heading: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**
|
||||
* The message text of the note card
|
||||
*/
|
||||
text: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
|
||||
computed: {
|
||||
shouldShowAlert() {
|
||||
return this.showAlert || this.type === 'error';
|
||||
},
|
||||
icon() {
|
||||
switch (this.type) {
|
||||
case 'error':
|
||||
return AlertDecagram;
|
||||
case 'success':
|
||||
return CheckboxMarkedCircle;
|
||||
case 'info':
|
||||
return Information;
|
||||
case 'warning':
|
||||
return Alert;
|
||||
default:
|
||||
return Alert;
|
||||
}
|
||||
},
|
||||
color() {
|
||||
switch (this.type) {
|
||||
case 'error':
|
||||
return 'var(--color-error)';
|
||||
case 'success':
|
||||
return 'var(--color-success)';
|
||||
case 'info':
|
||||
return 'var(--color-info)';
|
||||
case 'warning':
|
||||
return 'var(--color-warning)';
|
||||
default:
|
||||
return 'var(--color-warning)';
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.notecard {
|
||||
--note-card-icon-size: 20px;
|
||||
--note-card-padding: calc(2 * var(--default-grid-baseline));
|
||||
/* color: var(--color-main-text) !important; */
|
||||
/* background-color: var(--note-background) !important;
|
||||
border-inline-start: var(--default-grid-baseline) solid var(--note-theme);
|
||||
border-radius: var(--border-radius); */
|
||||
margin: 1rem 0;
|
||||
padding: var(--note-card-padding);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
gap: var(--note-card-padding);
|
||||
|
||||
&__heading {
|
||||
font-size: var(--note-card-icon-size);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
&--heading {
|
||||
font-size: 20px;
|
||||
margin-block: calc((1lh - 1em) / 2) auto;
|
||||
}
|
||||
}
|
||||
|
||||
/* &--success {
|
||||
--note-background: rgba(var(--color-success-rgb), 0.1);
|
||||
--note-theme: var(--color-success);
|
||||
}
|
||||
|
||||
&--info {
|
||||
--note-background: rgba(var(--color-info-rgb), 0.1);
|
||||
--note-theme: var(--color-info);
|
||||
}
|
||||
|
||||
&--error {
|
||||
--note-background: rgba(var(--color-error-rgb), 0.1);
|
||||
--note-theme: var(--color-error);
|
||||
}
|
||||
|
||||
&--warning {
|
||||
--note-background: rgba(var(--color-warning-rgb), 0.1);
|
||||
--note-theme: var(--color-warning);
|
||||
} */
|
||||
}
|
||||
</style>
|
147
resources/js/Components/NcSettingsSection.vue
Normal file
147
resources/js/Components/NcSettingsSection.vue
Normal file
|
@ -0,0 +1,147 @@
|
|||
|
||||
<template>
|
||||
<!-- <div class="settings-section" :class="{'settings-section--limit-width': forceLimitWidth}"> -->
|
||||
<div class="settings-section" v-bind:class="containerMaxW">
|
||||
<h2 class="settings-section__name">
|
||||
{{ name }}
|
||||
<a v-if="hasDocUrl"
|
||||
:href="docUrl"
|
||||
class="settings-section__info"
|
||||
:title="docNameTranslated"
|
||||
:aria-label="docNameTranslated"
|
||||
target="_blank"
|
||||
rel="noreferrer nofollow">
|
||||
<HelpCircle :size="20" />
|
||||
</a>
|
||||
</h2>
|
||||
<p v-if="hasDescription"
|
||||
class="settings-section__desc">
|
||||
{{ description }}
|
||||
</p>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
// import { t } from '../../l10n.js'
|
||||
// import { translate as t } from '@nextcloud/l10n'
|
||||
import { translate as t } from '@/utils/tethyscloud-l10n';
|
||||
|
||||
import HelpCircle from './Icons/HelpCircle.vue';
|
||||
import { containerMaxW } from '@/config';
|
||||
|
||||
export default {
|
||||
name: 'NcSettingsSection',
|
||||
|
||||
components: {
|
||||
HelpCircle,
|
||||
},
|
||||
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
docUrl: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
/**
|
||||
* Limit the width of the setting's content
|
||||
*
|
||||
* Setting this to false allows unrestricted (width) settings content.
|
||||
* Note that the name and description have always a width limit.
|
||||
* @deprecated Will be removed with next version and will not be used on Nextcloud 30+ (always forced to true)
|
||||
*/
|
||||
limitWidth: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
docNameTranslated: t('External documentation for {name}', {
|
||||
name: this.name,
|
||||
}),
|
||||
containerMaxW: containerMaxW,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
forceLimitWidth() {
|
||||
// if (this.limitWidth) {
|
||||
// return true
|
||||
// }
|
||||
// // Overwrite this on Nextcloud 30+ to always limit the width
|
||||
// const [major] = window._oc_config?.version.split('.', 2) ?? []
|
||||
// return major && Number.parseInt(major) >= 30
|
||||
return true;
|
||||
},
|
||||
|
||||
hasDescription() {
|
||||
return this.description.length > 0
|
||||
},
|
||||
hasDocUrl() {
|
||||
return this.docUrl.length > 0
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
/* $maxWidth: 900px; */
|
||||
|
||||
.settings-section {
|
||||
display: block;
|
||||
margin-bottom: auto;
|
||||
padding: 30px;
|
||||
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid var(--color-border);
|
||||
}
|
||||
|
||||
&--limit-width > * {
|
||||
max-width: 900px;
|
||||
}
|
||||
|
||||
&__name {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
max-width: 900px;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
&__info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: var(--default-clickable-area);
|
||||
height: var(--default-clickable-area);
|
||||
|
||||
/* margin: calc($icon-margin * -1); */
|
||||
margin-left: 0;
|
||||
color: var(--color-text-maxcontrast);
|
||||
|
||||
&:hover, &:focus, &:active {
|
||||
color: var(--color-main-text);
|
||||
}
|
||||
}
|
||||
|
||||
&__desc {
|
||||
margin-top: -.2em;
|
||||
margin-bottom: 1em;
|
||||
color: var(--color-text-maxcontrast);
|
||||
max-width: 900px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
159
resources/js/Components/Pagination.vue
Normal file
159
resources/js/Components/Pagination.vue
Normal file
|
@ -0,0 +1,159 @@
|
|||
<script lang="ts" setup>
|
||||
import { Link } from '@inertiajs/vue3';
|
||||
import { computed } from 'vue';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
});
|
||||
// meta:
|
||||
// {total: 19, perPage: 5, currentPage: 1, lastPage: 4, firstPage: 1, …}
|
||||
// currentPage:
|
||||
// 1
|
||||
// firstPage:
|
||||
// 1
|
||||
// firstPageUrl:
|
||||
// '/?page=1'
|
||||
// lastPage:
|
||||
// 4
|
||||
// lastPageUrl:
|
||||
// '/?page=4'
|
||||
// nextPageUrl:
|
||||
// '/?page=2'
|
||||
// perPage:
|
||||
// 5
|
||||
// previousPageUrl:
|
||||
// null
|
||||
// total:
|
||||
// 19
|
||||
const calculateNextPageLink = computed(() => {
|
||||
let url = new URL(document.location.href);
|
||||
url.searchParams.set('page', String(props.data.current_page + 1));
|
||||
return url.href;
|
||||
});
|
||||
const calculatePrevPageLink = computed(() => {
|
||||
let url = new URL(document.location.href);
|
||||
url.searchParams.set('page', String(props.data.current_page - 1));
|
||||
return url.href;
|
||||
});
|
||||
const toPage = computed(() => {
|
||||
let currentPage = props.data.current_page;
|
||||
let perPage = props.data.per_page;
|
||||
|
||||
if (props.data.current_page == props.data.last_page) {
|
||||
return props.data.total;
|
||||
} else {
|
||||
return currentPage * perPage;
|
||||
}
|
||||
});
|
||||
const fromPage = computed(() => {
|
||||
let currentPage = props.data.current_page;
|
||||
let perPage = props.data.per_page;
|
||||
return currentPage * perPage - (perPage - 1);
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- <nav v-if="data.links.length > 3" -->
|
||||
<nav v-if="data.total > 3" role="navigation" aria-label="Pagination Navigation"
|
||||
class="flex items-center justify-between">
|
||||
<div class="flex justify-between flex-1 sm:hidden">
|
||||
<span v-if="data.current_page <= 1"
|
||||
class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md">
|
||||
Previous
|
||||
</span>
|
||||
<Link v-else :href="data.previous_page_url"
|
||||
class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
|
||||
Previous
|
||||
</Link>
|
||||
|
||||
<Link v-if="data.current_page < data.last_page" :href="data.next_page_url"
|
||||
class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 rounded-md hover:text-gray-500 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150">
|
||||
Next
|
||||
</Link>
|
||||
<span v-else
|
||||
class="relative inline-flex items-center px-4 py-2 ml-3 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5 rounded-md">
|
||||
Next
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="hidden sm:flex-1 sm:flex sm:items-center sm:justify-between">
|
||||
<div>
|
||||
<p class="text-sm text-gray-700 leading-5">
|
||||
Showing
|
||||
<span class="font-medium">{{ fromPage }}</span>
|
||||
to
|
||||
<span class="font-medium">{{ toPage }}</span>
|
||||
of
|
||||
<span class="font-medium">{{ data.total }}</span>
|
||||
results
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span class="relative z-0 inline-flex shadow-sm rounded-md">
|
||||
<span v-if="props.data.current_page <= 1" aria-disabled="true" aria-label="Previous">
|
||||
<span
|
||||
class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-l-md leading-5 opacity-50"
|
||||
aria-hidden="true">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd"
|
||||
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
|
||||
<!-- <Link v-else :href="data.previousPageUrl" rel="prev" -->
|
||||
<Link v-else :href="calculatePrevPageLink" rel="prev"
|
||||
class="relative inline-flex items-center px-2 py-2 text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-l-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150"
|
||||
aria-label="Previous">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd"
|
||||
d="M12.707 5.293a1 1 0 010 1.414L9.414 10l3.293 3.293a1 1 0 01-1.414 1.414l-4-4a1 1 0 010-1.414l4-4a1 1 0 011.414 0z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</Link>
|
||||
|
||||
<!-- <template v-for="(link, key) in data.links">
|
||||
<template v-if="key > 0 && key < data.last_page + 1">
|
||||
<span v-if="!link.active && link.url === null" :key="key" aria-disabled="true">
|
||||
<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 cursor-default leading-5">{{ link.label }}</span>
|
||||
</span>
|
||||
|
||||
<span v-else-if="link.active" :key="`current-${key}`" aria-current="page">
|
||||
<span class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default leading-5">{{ link.label }}</span>
|
||||
</span>
|
||||
|
||||
<Link v-else :key="`link-${key}`" :href="link.url" v-html="link.label" class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 leading-5 hover:text-gray-500 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-700 transition ease-in-out duration-150" aria-label="`Go to page ${link.label}`" />
|
||||
</template>
|
||||
</template> -->
|
||||
|
||||
<Link v-if="props.data.current_page < props.data.last_page" :href="calculateNextPageLink" rel="next"
|
||||
class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 rounded-r-md leading-5 hover:text-gray-400 focus:z-10 focus:outline-none focus:ring ring-gray-300 focus:border-blue-300 active:bg-gray-100 active:text-gray-500 transition ease-in-out duration-150"
|
||||
aria-label="Next">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd"
|
||||
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</Link>
|
||||
<!-- else disabled link -->
|
||||
<span v-else aria-disabled="true" aria-label="Next">
|
||||
<span
|
||||
class="relative inline-flex items-center px-2 py-2 -ml-px text-sm font-medium text-gray-500 bg-white border border-gray-300 cursor-default rounded-r-md leading-5 opacity-50"
|
||||
aria-hidden="true">
|
||||
<svg class="w-5 h-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fill-rule="evenodd"
|
||||
d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z"
|
||||
clip-rule="evenodd" />
|
||||
</svg>
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
</template>
|
|
@ -1,7 +1,7 @@
|
|||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue';
|
||||
// import { MainService } from '@/Stores/main';
|
||||
import { StyleService } from '@/Stores/style.service';
|
||||
// import { StyleService } from '@/Stores/style.service';
|
||||
import { mdiTrashCan } from '@mdi/js';
|
||||
import { mdiDragVariant } from '@mdi/js';
|
||||
import BaseIcon from '@/Components/BaseIcon.vue';
|
||||
|
@ -10,9 +10,9 @@ import BaseIcon from '@/Components/BaseIcon.vue';
|
|||
// import BaseLevel from '@/Components/BaseLevel.vue';
|
||||
import BaseButtons from '@/Components/BaseButtons.vue';
|
||||
import BaseButton from '@/Components/BaseButton.vue';
|
||||
import UserAvatar from '@/Components/UserAvatar.vue';
|
||||
// import UserAvatar from '@/Components/UserAvatar.vue';
|
||||
// import Person from 'App/Models/Person';
|
||||
import { Person } from '@/Stores/main';
|
||||
import { Person } from '@/Dataset';
|
||||
import Draggable from 'vuedraggable';
|
||||
import FormControl from '@/Components/FormControl.vue';
|
||||
|
||||
|
@ -36,7 +36,7 @@ const props = defineProps({
|
|||
},
|
||||
});
|
||||
|
||||
const styleService = StyleService();
|
||||
// const styleService = StyleService();
|
||||
// const mainService = MainService();
|
||||
// const items = computed(() => props.persons);
|
||||
|
||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue