tethys.backend/resources/js/Pages/Submitter/Dataset/Create.vue
Arno Kaimbacher c4f4eff0d9
All checks were successful
CI Pipeline / japa-tests (push) Successful in 59s
- daraggable crators and contributors inside Pages/Submitter/Dataset/Create.Vue
- typescript and prettier updates
- FileUpload component with dark mode and dragable uploads
- comment FontFamily in tailwind.config.js
2023-06-16 16:44:28 +02:00

1201 lines
60 KiB
Vue

<script setup lang="ts">
import { Head, useForm, usePage } from '@inertiajs/vue3';
import { ref, watch, computed, ComputedRef } from 'vue';
import { Dataset, Description, Title, Subject } from '@/Dataset';
import {
mdiDatabasePlus,
mdiMinusCircle,
mdiPlusCircle,
mdiFinance,
mdiInformationOutline,
mdiBookOpenPageVariant,
mdiImageText,
mdiEarthPlus,
mdiAlertBoxOutline
} from '@mdi/js';
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
import SectionMain from '@/Components/SectionMain.vue';
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
import CardBox from '@/Components/CardBox.vue';
import FormField from '@/Components/FormField.vue';
import FormControl from '@/Components/FormControl.vue';
import FormCheckRadioGroup from '@/Components/FormCheckRadioGroup.vue';
// import BaseDivider from '@/Components/BaseDivider.vue';
import BaseButton from '@/Components/BaseButton.vue';
// import BaseButtons from '@/Components/BaseButtons.vue';
import { stardust } from '@eidellev/adonis-stardust/client';
// import { Inertia } from '@inertiajs/inertia';
import CardBoxModal from '@/Components/CardBoxModal.vue';
import BaseIcon from '@/Components/BaseIcon.vue';
import IconWizard from '@/Components/Icons/Wizard.vue';
import IconMandatory from '@/Components/Icons/Mandatory.vue';
import IconLanguage from '@/Components/Icons/Language.vue';
import IconRecommendet from '@/Components/Icons/Recommendet.vue';
import IconConfirm from '@/Components/Icons/Confirm.vue';
import SearchAutocomplete from '@/Components/SearchAutocomplete.vue';
import TablePersons from '@/Components/TablePersons.vue';
import { MainService } from '@/Stores/main';
import { notify } from '@/notiwind';
import MapComponent from '@/Components/Map/map.component.vue';
import { MapOptions } from '@/Components/Map/MapOptions';
import { LatLngBoundsExpression } from 'leaflet/src/geo/LatLngBounds';
import { LayerOptions } from '@/Components/Map/LayerOptions';
import TableKeywords from '@/Components/TableKeywords.vue';
import NotificationBar from '@/Components/NotificationBar.vue';
import FileUploadComponent from '@/Components/FileUpload.vue';
const props = defineProps({
licenses: {
type: Object,
default: () => ({}),
},
doctypes: {
type: Object,
default: () => ({}),
},
titletypes: {
type: Object,
default: () => ({}),
},
descriptiontypes: {
type: Object,
default: () => ({}),
},
projects: {
type: Object,
default: () => ({}),
},
errors: {
type: Object,
default: () => ({}),
},
});
const flash: ComputedRef<any> = computed(() => {
// let test = usePage();
// console.log(test);
return usePage().props.flash;
});
const mainService = MainService();
// let serrors = reactive([]);
// const form = useForm({
// language: '',
// licenses: [],
// type: '',
// titles: [{ value: '', type: 'Main', language: Dataset.language }],
// });
// let language: (string | Ref<string>) = ref('');
let language = ref('');
let dataset: Dataset;
if (Object.keys(mainService.dataset).length == 0) {
// language = ref('');
dataset = {
language: language,
licenses: [],
rights: false,
type: '',
creating_corporation: 'Tethys RDR',
titles: [{ value: '', type: 'Main', language: language }],
descriptions: [{ value: '', type: 'Abstract', language: language }],
authors: [],
contributors: [],
project_id: undefined,
embargo_date: '',
coverage: {
x_min: undefined,
y_min: undefined,
x_max: undefined,
y_max: undefined,
elevation_min: undefined,
elevation_max: undefined,
elevation_absolut: undefined,
depth_min: undefined,
depth_max: undefined,
depth_absolut: undefined,
time_min: undefined,
time_max: undefined,
time_absolut: undefined,
},
// errors: undefined,
subjects: [
{ value: '', type: 'uncontrolled', language: language.value },
{ value: '', type: 'uncontrolled', language: language.value },
{ value: '', type: 'uncontrolled', language: language.value },
],
files: [],
// upload: { label: 'test', sorting: 0 },
};
// Set the form's current values as the new defaults...
// mainService.setDataset(dataset, language);
} else {
// console.log(mainService.dataset);
language = ref(mainService.dataset.language);
// dataset = mainService.dataset;
dataset = {
language: language,
licenses: mainService.dataset.licenses,
rights: mainService.dataset.rights,
type: mainService.dataset.type,
creating_corporation: mainService.dataset.creating_corporation,
titles: mainService.dataset.titles,
descriptions: mainService.dataset.descriptions,
authors: mainService.dataset.authors,
contributors: mainService.dataset.contributors,
project_id: mainService.dataset.project_id,
embargo_date: mainService.dataset.embargo_date,
coverage: mainService.dataset.coverage,
subjects: mainService.dataset.subjects,
files: mainService.dataset.files,
// upload: mainService.dataset.upload,
};
for (let index in mainService.dataset.titles) {
let title: Title = mainService.dataset.titles[index];
if (title.type == 'Main') {
title.language = language;
}
}
for (let index in mainService.dataset.descriptions) {
let description: Description = mainService.dataset.descriptions[index];
if (description.type == 'Abstract') {
description.language = language;
}
}
}
// const form = useForm<Dataset>({
// language: language,
// licenses: [],
// rights: false,
// type: '',
// creating_corporation: 'Tethys RDR',
// titles: [{ value: '', type: 'Main', language: language }],
// descriptions: [{ value: '', type: 'Abstract', language: language }],
// });
let form = useForm<Dataset>(dataset);
// form.defaults();
// const emit = defineEmits(['update:modelValue', 'setRef']);
// computed({
// get: () => form.rights,
// set: (value) => {
// emit('update:modelValue', value);
// },
// });
let elevation = ref('no_elevation');
watch(elevation, (currentValue) => {
if (currentValue == 'absolut') {
form.coverage.elevation_min = undefined;
form.coverage.elevation_max = undefined;
} else if (currentValue == 'range') {
form.coverage.elevation_absolut = undefined;
} else {
form.coverage.elevation_absolut = undefined;
form.coverage.elevation_min = undefined;
form.coverage.elevation_max = undefined;
}
});
let depth = ref('no_depth');
watch(depth, (currentValue) => {
if (currentValue == 'absolut') {
form.coverage.depth_min = undefined;
form.coverage.depth_max = undefined;
} else if (currentValue == 'range') {
form.coverage.depth_absolut = undefined;
} else {
form.coverage.depth_absolut = undefined;
form.coverage.depth_min = undefined;
form.coverage.depth_max = undefined;
}
});
// let time= "no_time";
const isModalActive = ref(false);
const formStep = ref(1);
const mapOptions: MapOptions = {
center: [48.208174, 16.373819],
zoom: 3,
zoomControl: false,
attributionControl: false,
};
const baseMaps: Map<string, LayerOptions> = new Map<string, LayerOptions>();
const fitBounds: LatLngBoundsExpression = [
[46.4318173285, 9.47996951665],
[49.0390742051, 16.9796667823],
];
const mapId = 'test';
// const submit = async () => {
// await router.post(stardust.route('user.store'), form, {
// onSuccess: () => {
// form.reset(), (formStep.value = 1);
// },
// });
// };
const nextStep = async () => {
let route;
if (formStep.value == 1) {
route = stardust.route('dataset.first.step');
} else if (formStep.value == 2) {
route = stardust.route('dataset.second.step');
} else if (formStep.value == 3) {
route = stardust.route('dataset.third.step');
}
// formStep.value++;
await form
.transform((data) => ({
...data,
rights: form.rights && form.rights == true ? 'true' : 'false',
}))
.post(route, {
onSuccess: () => {
// console.log(form.data());
mainService.setDataset(form.data());
formStep.value++;
},
});
};
const prevStep = () => {
formStep.value--;
};
const submit = async () => {
let route = stardust.route('dataset.submit');
// this.currentStatus = STATUS_SAVING;
// serrors = [];
// formStep.value++;
await form
.transform((data) => ({
...data,
rights: form.rights && form.rights == true ? 'true' : 'false',
}))
.post(route, {
// forceFormData: true,
onSuccess: () => {
// console.log(form.data());
// mainService.clearDataset();
// mainService.setDataset(form.data());
// formStep.value++;
// form.reset();
language.value = '';
formStep.value = 1;
let dataset = {
language: language,
licenses: [],
rights: false,
type: '',
creating_corporation: 'Tethys RDR',
titles: [{ value: '', type: 'Main', language: language }],
descriptions: [{ value: '', type: 'Abstract', language: language }],
authors: [],
contributors: [],
project_id: undefined,
embargo_date: '',
coverage: {
x_min: undefined,
y_min: undefined,
x_max: undefined,
y_max: undefined,
elevation_min: undefined,
elevation_max: undefined,
elevation_absolut: undefined,
depth_min: undefined,
depth_max: undefined,
depth_absolut: undefined,
time_min: undefined,
time_max: undefined,
time_absolut: undefined,
},
// errors: undefined,
subjects: [
{ value: '', type: 'uncontrolled', language: language.value },
{ value: '', type: 'uncontrolled', language: language.value },
{ value: '', type: 'uncontrolled', language: language.value },
],
files: [] as Array<File>,
upload: { label: 'test', sorting: 0 },
};
form = useForm<Dataset>(dataset);
mainService.setDataset(form.data());
},
});
};
const addTitle = () => {
let newTitle: Title = { value: '', language: '', type: '' };
//this.dataset.files.push(uploadedFiles[i]);
form.titles.push(newTitle);
};
const removeTitle = (key) => {
form.titles.splice(key, 1);
};
const addDescription = () => {
let newDescription = { value: '', language: '', type: '' };
//this.dataset.files.push(uploadedFiles[i]);
form.descriptions.push(newDescription);
};
const removeDescription = (key) => {
form.descriptions.splice(key, 1);
};
const onAddAuthor = (person) => {
if (form.authors.filter((e) => e.id === person.id).length > 0) {
notify({ type: 'warning', title: 'Warning', text: 'person is already defined as author' }, 4000);
} else if (form.contributors.filter((e) => e.id === person.id).length > 0) {
notify({ type: 'warning', title: 'Warning', text: 'person is already defined as contributor' });
} else {
form.authors.push(person);
notify({ type: 'info', text: 'person has been successfully added as author' });
}
};
const onAddContributor = (person) => {
if (form.contributors.filter((e) => e.id === person.id).length > 0) {
notify({ type: 'warning', title: 'Warning', text: 'person is already defined as contributor' }, 4000);
} else if (form.authors.filter((e) => e.id === person.id).length > 0) {
notify({ type: 'warning', title: 'Warning', text: 'person is already defined as author' }, 4000);
} else {
// person.pivot = { contributor_type: '' };
// // person.pivot = { name_type: '', contributor_type: '' };
form.contributors.push(person);
notify({ type: 'info', text: 'person has been successfully added as contributor' }, 4000);
}
};
// const onMapInitializedEvent = "onMapInitializedEvent";
const onMapInitialized = (newItem) => {
// notify({ type: 'info', text: message });
console.log(newItem);
};
/*
adds a new Keyword
*/
const addKeyword = () => {
let newSubject: Subject = { value: 'test', language: '', type: 'uncontrolled' };
//this.dataset.files.push(uploadedFiles[i]);
form.subjects.push(newSubject);
};
// const onChangeFile = (event) => {
// // let uploadedFile = event.target.files[0];
// let fileName = String(event.target.files[0].name.replace(/\.[^/.]+$/, ''));
// form.file = event.target.files[0];
// form.upload.label = fileName;
// // form.upload = file;
// // console.log(file.file);
// };
/*
Removes a selected keyword
*/
// const removeKeyword = (key) => {
// form.subjects.splice(key, 1);
// };
</script>
<template>
<CardBoxModal v-model="isModalActive" title="Einverständniserklärung *">
Mit dem Setzen des Hakens bestätige ich hiermit
<ul class="list-decimal">
<li>
die Data Policy von Tethys RDR sowie die Terms & Conditions von Tethys gelesen und verstanden zu haben (<a
href="/docs/HandbuchTethys.pdf"
target="_blank"
>siehe hier</a
>)
</li>
<li>das Einverständnis aller Co-Autoren über die bevorstehende Datenpublikation schriftlich eingeholt zu haben</li>
<li>sowohl mit der Data Policy als auch mit den Terms & Conditions einverstanden zu sein</li>
</ul>
</CardBoxModal>
<LayoutAuthenticated>
<Head title="Submit Dataset" />
<SectionMain>
<SectionTitleLineWithButton :icon="mdiDatabasePlus" title="Submit dataset" main>
<!-- <BaseButton :route-name="stardust.route('user.index')" :icon="mdiArrowLeftBoldOutline" label="Back"
color="white" rounded-full small /> -->
{{ formStep }}
</SectionTitleLineWithButton>
<NotificationBar v-if="flash.message" color="success" :icon="mdiAlertBoxOutline">
{{ flash.message }}
</NotificationBar>
<CardBox>
<div class="mx-4 p-4">
<div class="flex items-center">
<!-- <label>{{ form.titles[0].language }}</label>
<label>{{ form.language }}</label> -->
<icon-wizard :is-current="formStep == 1" :is-checked="formStep > 1" :label="'Language'">
<icon-language></icon-language>
</icon-wizard>
<icon-wizard :is-current="formStep == 2" :is-checked="formStep > 2" :label="'Mandatory'">
<icon-mandatory></icon-mandatory>
</icon-wizard>
<icon-wizard :is-current="formStep == 3" :is-checked="formStep > 3" :label="'Recommendet'">
<icon-recommendet></icon-recommendet>
</icon-wizard>
<icon-wizard :is-current="formStep == 4" :is-checked="false" :label="'Confirm'" :is-last-step="true">
<icon-confirm></icon-confirm>
</icon-wizard>
</div>
</div>
<!-- mt-8: margin-top: 2rem; /* 32px */ 4 p-4: spacing 1rem 16px-->
<div class="mt-8 p-4">
<div v-if="formStep == 1">
<div class="flex flex-col md:flex-row">
<FormField
label="Language *"
help="required: select dataset main language"
:class="{ 'text-red-400': errors.language }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.language"
:type="'select'"
placeholder="[Enter Language]"
:errors="form.errors.language"
:options="{ de: 'de', en: 'en' }"
>
<div class="text-red-400 text-sm" v-if="form.errors.language">
{{ form.errors.language.join(', ') }}
</div>
</FormControl>
</FormField>
</div>
<FormField
label="Licenses"
wrap-body
:class="{ 'text-red-400': form.errors.licenses }"
class="mt-8 w-full mx-2 flex-1"
>
<FormCheckRadioGroup v-model="form.licenses" name="roles" is-column :options="props.licenses" />
</FormField>
<!-- <label for="rights">
<input class="form-checkbox" name="rights" id="rights" type="checkbox" v-model="dataset.rights" />
terms and conditions
</label> -->
<FormField
label="Rights"
help="You must agree to continue"
wrap-body
:class="{ 'text-red-400': form.errors.rights }"
class="mt-8 w-full mx-2 flex-1 flex-col"
>
<label for="rights" class="checkbox mr-6 mb-3 last:mr-0">
<input type="checkbox" id="rights" required v-model="form.rights" />
<span class="check" />
<a class="pl-2" target="_blank">terms and conditions </a>
<!-- <BaseButton color="modern" :icon="mdiInformationOutline" small @click="isModalActive = true" /> -->
<BaseIcon
v-if="mdiInformationOutline"
:path="mdiInformationOutline"
@click.prevent="isModalActive = true"
/>
</label>
</FormField>
<div class="text-red-400 text-sm" v-if="errors.rights && Array.isArray(errors.rights)">
<!-- {{ errors.password_confirmation }} -->
{{ errors.rights.join(', ') }}
</div>
</div>
<div v-if="formStep == 2">
<!-- <CardBox title="Performance" :icon="mdiFinance" :header-icon="mdiReload" class="mb-6"> -->
<div class="flex flex-col md:flex-row">
<FormField
label="Dataset Type *"
help="required: dataset type"
:class="{ 'text-red-400': form.errors.type }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.type"
:type="'select'"
placeholder="-- select type --"
:errors="errors.type"
:options="doctypes"
>
<div class="text-red-400 text-sm" v-if="form.errors.type && Array.isArray(form.errors.type)">
{{ form.errors.type.join(', ') }}
</div>
</FormControl>
</FormField>
<!-- <div class="w-full mx-2 flex-1 svelte-1l8159u"></div> -->
<!-- Creating Corporation -->
<FormField
label="Creating Corporation *"
:class="{ 'text-red-400': form.errors.creating_corporation }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.creating_corporation"
type="text"
placeholder="[enter creating corporation]"
:is-read-only="true"
>
<div
class="text-red-400 text-sm"
v-if="form.errors.creating_corporation && Array.isArray(form.errors.creating_corporation)"
>
{{ form.errors.creating_corporation.join(', ') }}
</div>
</FormControl>
</FormField>
</div>
<!-- <BaseDivider /> -->
<!-- titles -->
<CardBox
class="mb-6 shadow"
:has-form-data="true"
title="Titles"
:icon="mdiFinance"
:header-icon="mdiPlusCircle"
v-on:header-icon-click="addTitle()"
>
<!-- <div class="py-6 border-t border-gray-100 dark:border-slate-800"> -->
<div class="flex flex-col md:flex-row">
<FormField
label="Main Title *"
help="required: main title"
:class="{ 'text-red-400': form.errors['titles.0.value'] }"
class="w-full mx-2 flex-1"
>
<FormControl required v-model="form.titles[0].value" type="text" placeholder="[enter main title]">
<div
class="text-red-400 text-sm"
v-if="form.errors['titles.0.value'] && Array.isArray(form.errors['titles.0.value'])"
>
{{ form.errors['titles.0.value'].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
label="Main Title Language*"
help="required: main title language"
:class="{ 'text-red-400': form.errors['titles.0.language'] }"
class="w-full mx-2 flex-1"
>
<FormControl required v-model="form.titles[0].language" type="text" :is-read-only="true">
<div
class="text-red-400 text-sm"
v-if="form.errors['titles.0.language'] && Array.isArray(form.errors['titles.0.language'])"
>
{{ form.errors['titles.0.language'].join(', ') }}
</div>
</FormControl>
</FormField>
</div>
<label v-if="form.titles.length > 1">additional titles </label>
<!-- <BaseButton :icon="mdiPlusCircle" @click.prevent="addTitle()" color="modern" rounded-full small /> -->
<div v-if="form.titles.length > 1">
<div v-for="(item, index) in form.titles">
<div class="flex flex-col md:flex-row" v-if="item.type != 'Main'">
<FormField v-if="item.type != 'Main'" label="Remove">
<BaseButton
:icon="mdiMinusCircle"
class="mt-1"
@click.prevent="removeTitle(index)"
color="modern"
small
/>
</FormField>
<FormField
label="Title Value *"
:class="{ 'text-red-400': form.errors[`titles.${index}.value`] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.titles[index].value"
type="text"
placeholder="[enter main title]"
>
<div class="text-red-400 text-sm" v-if="form.errors[`titles.${index}.value`]">
{{ form.errors[`titles.${index}.value`].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
label="Title Type*"
:class="{ 'text-red-400': form.errors[`titles.${index}.type`] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.titles[index].type"
type="select"
:options="titletypes"
placeholder="[select title type]"
>
<div class="text-red-400 text-sm" v-if="Array.isArray(form.errors[`titles.${index}.type`])">
{{ form.errors[`titles.${index}.type`].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
label="Title Language*"
:class="{ 'text-red-400': form.errors[`titles.${index}.language`] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.titles[index].language"
type="select"
:options="{ de: 'de', en: 'en' }"
placeholder="[select title language]"
>
<div class="text-red-400 text-sm" v-if="form.errors[`titles.${index}.language`]">
{{ form.errors[`titles.${index}.language`].join(', ') }}
</div>
</FormControl>
</FormField>
</div>
</div>
</div>
<!-- </div> -->
</CardBox>
<!-- Descriptions -->
<CardBox
:icon="mdiImageText"
class="mb-6 shadow"
:has-form-data="true"
title="Descriptions"
:header-icon="mdiPlusCircle"
v-on:header-icon-click="addDescription()"
>
<div class="flex flex-col md:flex-row">
<FormField
label="Main Abstract *"
help="required: main abstract"
:class="{ 'text-red-400': form.errors['descriptions.0.value'] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.descriptions[0].value"
type="textarea"
placeholder="[enter main abstract]"
>
<div
class="text-red-400 text-sm"
v-if="form.errors['descriptions.0.value'] && Array.isArray(form.errors['descriptions.0.value'])"
>
{{ form.errors['descriptions.0.value'].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
label="Main Title Language*"
help="required: main abstract language"
:class="{ 'text-red-400': form.errors['descriptions.0.language'] }"
class="w-full mx-2 flex-1"
>
<FormControl required v-model="form.descriptions[0].language" type="text" :is-read-only="true">
<div
class="text-red-400 text-sm"
v-if="
form.errors['descriptions.0.value'] && Array.isArray(form.errors['descriptions.0.language'])
"
>
{{ form.errors['descriptions.0.language'].join(', ') }}
</div>
</FormControl>
</FormField>
</div>
<label v-if="form.descriptions.length > 1">additional descriptions: </label>
<!-- <BaseButton :icon="mdiPlusCircle" @click.prevent="addTitle()" color="modern" rounded-full small /> -->
<div v-if="form.descriptions.length > 1">
<div v-for="(item, index) in form.descriptions">
<div class="flex flex-col md:flex-row" v-if="item.type != 'Abstract'">
<FormField v-if="item.type != 'Abstract'" label="Remove">
<BaseButton
:icon="mdiMinusCircle"
class="mt-1"
@click.prevent="removeDescription(index)"
color="modern"
small
/>
</FormField>
<FormField
label="Description Value *"
:class="{ 'text-red-400': form.errors[`descriptions.${index}.value`] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.descriptions[index].value"
type="text"
placeholder="[enter additional description]"
>
<div
class="text-red-400 text-sm"
v-if="
form.errors[`descriptions.${index}.value`] &&
Array.isArray(form.errors[`descriptions.${index}.value`])
"
>
{{ form.errors[`descriptions.${index}.value`].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
label="Description Type *"
:class="{ 'text-red-400': form.errors[`descriptions.${index}.type`] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.descriptions[index].type"
type="select"
:options="descriptiontypes"
placeholder="[select description type]"
>
<div
class="text-red-400 text-sm"
v-if="
form.errors[`descriptions.${index}.type`] &&
Array.isArray(form.errors[`descriptions.${index}.type`])
"
>
{{ form.errors[`descriptions.${index}.type`].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
label="Description Language*"
:class="{ 'text-red-400': form.errors[`titdescriptionsles.${index}.language`] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.descriptions[index].language"
type="select"
:options="{ de: 'de', en: 'en' }"
placeholder="[select title language]"
>
<div
class="text-red-400 text-sm"
v-if="form.errors && Array.isArray(form.errors[`descriptions.${index}.language`])"
>
{{ form.errors[`descriptions.${index}.language`].join(', ') }}
</div>
</FormControl>
</FormField>
</div>
</div>
</div>
</CardBox>
<!-- authors -->
<CardBox class="mb-6 shadow" has-table title="Authors" :icon="mdiBookOpenPageVariant">
<SearchAutocomplete
source="/api/persons"
:response-property="'first_name'"
placeholder="search in person table...."
v-on:person="onAddAuthor"
></SearchAutocomplete>
<TablePersons :persons="form.authors" v-if="form.authors.length > 0" />
<div class="text-red-400 text-sm" v-if="errors.authors && Array.isArray(errors.authors)">
{{ errors.authors.join(', ') }}
</div>
</CardBox>
<!-- contributors -->
<CardBox class="mb-6 shadow" has-table title="Contributors" :icon="mdiBookOpenPageVariant">
<SearchAutocomplete
source="/api/persons"
:response-property="'first_name'"
placeholder="search in person table...."
v-on:person="onAddContributor"
></SearchAutocomplete>
<TablePersons :persons="form.contributors" v-if="form.contributors.length > 0" />
</CardBox>
</div>
<!-- <label>To Do: Recommendet</label> -->
<div v-if="formStep == 3">
<div class="flex flex-col md:flex-row">
<FormField
label="Project.."
help="project is optional"
:class="{ 'text-red-400': errors.project_id }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.project_id"
:type="'select'"
placeholder="[Select Project]"
:errors="form.errors.project_id"
:options="projects"
>
<div class="text-red-400 text-sm" v-if="form.errors.project_id">
{{ form.errors.project_id.join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
label="Embargo Date.."
help="embargo date is optional"
:class="{ 'text-red-400': errors.embargo_date }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.embargo_date"
:type="'date'"
placeholder="date('y-m-d')"
:errors="form.errors.embargo_date"
>
<div class="text-red-400 text-sm" v-if="form.errors.embargo_date">
{{ form.errors.embargo_date.join(', ') }}
</div>
</FormControl>
</FormField>
</div>
<CardBox class="mb-6 shadow" has-table title="Geo Location" :icon="mdiEarthPlus">
<!-- @onMapInitialized="onMapInitialized" -->
<!-- v-bind-event="{ mapId, name: mapId }" -->
<MapComponent
:mapOptions="mapOptions"
:baseMaps="baseMaps"
:fitBounds="fitBounds"
:coverage="form.coverage"
:mapId="mapId"
v-bind-event:onMapInitializedEvent="onMapInitialized"
></MapComponent>
<!-- <label v-bind-event="{ for: mapId }" /> -->
<div class="flex flex-col md:flex-row">
<!-- x min and max -->
<FormField
label="Coverage X Min"
:class="{ 'text-red-400': form.errors['coverage.x_min'] }"
class="w-full mx-2 flex-1"
>
<FormControl required v-model="form.coverage.x_min" type="text" placeholder="[enter x_min]">
<div
class="text-red-400 text-sm"
v-if="form.errors['coverage.x_min'] && Array.isArray(form.errors['coverage.x_min'])"
>
{{ form.errors['coverage.x_min'].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
label="Coverage X Max"
:class="{ 'text-red-400': form.errors['coverage.x_max'] }"
class="w-full mx-2 flex-1"
>
<FormControl required v-model="form.coverage.x_max" type="text" placeholder="[enter x_max]">
<div
class="text-red-400 text-sm"
v-if="form.errors['coverage.x_max'] && Array.isArray(form.errors['coverage.x_max'])"
>
{{ form.errors['coverage.x_max'].join(', ') }}
</div>
</FormControl>
</FormField>
<!-- y min and max -->
<FormField
label="Coverage Y Min"
:class="{ 'text-red-400': form.errors['coverage.y_min'] }"
class="w-full mx-2 flex-1"
>
<FormControl required v-model="form.coverage.y_min" type="text" placeholder="[enter y_min]">
<div
class="text-red-400 text-sm"
v-if="form.errors['coverage.y_min'] && Array.isArray(form.errors['coverage.y_min'])"
>
{{ form.errors['coverage.y_min'].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
label="Coverage Y Max"
:class="{ 'text-red-400': form.errors['coverage.y_max'] }"
class="w-full mx-2 flex-1"
>
<FormControl required v-model="form.coverage.y_max" type="text" placeholder="[enter y_max]">
<div
class="text-red-400 text-sm"
v-if="form.errors['coverage.y_max'] && Array.isArray(form.errors['coverage.y_max'])"
>
{{ form.errors['coverage.y_max'].join(', ') }}
</div>
</FormControl>
</FormField>
</div>
</CardBox>
<CardBox class="mb-6 shadow" has-table title="Coverage Information" :icon="mdiEarthPlus">
<!-- elevation menu -->
<div class="lex flex-col md:flex-row mb-3">
<label for="elevation-option-one" class="pure-radio">
<input id="elevation-option-one" type="radio" v-model="elevation" value="absolut" />
absolut elevation (m)
</label>
<label for="elevation-option-two" class="pure-radio">
<input id="elevation-option-two" type="radio" v-model="elevation" value="range" />
elevation range (m)
</label>
<label for="elevation-option-three" class="pure-radio">
<input id="elevation-option-three" type="radio" v-model="elevation" value="no_elevation" />
no elevation
</label>
</div>
<div class="flex flex-col md:flex-row">
<FormField
v-if="elevation === 'absolut'"
label="elevation absolut"
:class="{ 'text-red-400': form.errors['coverage.elevation_absolut'] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.coverage.elevation_absolut"
type="text"
placeholder="[enter elevation_absolut]"
>
<div class="text-red-400 text-sm" v-if="Array.isArray(form.errors['coverage.elevation_absolut'])">
{{ form.errors['coverage.elevation_absolut'].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
v-if="elevation === 'range'"
label="elevation min"
:class="{ 'text-red-400': form.errors['coverage.elevation_min'] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.coverage.elevation_min"
type="text"
placeholder="[enter elevation_min]"
>
<div class="text-red-400 text-sm" v-if="Array.isArray(form.errors['coverage.elevation_min'])">
{{ form.errors['coverage.elevation_min'].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
v-if="elevation === 'range'"
label="elevation max"
:class="{ 'text-red-400': form.errors['coverage.elevation_max'] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.coverage.elevation_max"
type="text"
placeholder="[enter elevation_max]"
>
<div class="text-red-400 text-sm" v-if="Array.isArray(form.errors['coverage.elevation_max'])">
{{ form.errors['coverage.elevation_max'].join(', ') }}
</div>
</FormControl>
</FormField>
</div>
<!-- depth menu -->
<div class="lex flex-col md:flex-row mb-3">
<label for="depth-option-one" class="pure-radio">
<input id="depth-option-one" type="radio" v-model="depth" value="absolut" />
absolut depth (m)
</label>
<label for="depth-option-two" class="pure-radio">
<input id="depth-option-two" type="radio" v-model="depth" value="range" />
depth range (m)
</label>
<label for="depth-option-three" class="pure-radio">
<input id="depth-option-three" type="radio" v-model="depth" value="no_depth" />
no depth
</label>
</div>
<div class="flex flex-col md:flex-row">
<FormField
v-if="depth === 'absolut'"
label="depth absolut"
:class="{ 'text-red-400': form.errors['coverage.depth_absolut'] }"
class="w-full mx-2 flex-1"
>
<FormControl
required
v-model="form.coverage.depth_absolut"
type="text"
placeholder="[enter depth_absolut]"
>
<div class="text-red-400 text-sm" v-if="Array.isArray(form.errors['coverage.depth_absolut'])">
{{ form.errors['coverage.depth_absolut'].join(', ') }}
</div>
</FormControl></FormField
>
<FormField
v-if="depth === 'range'"
label="depth min"
:class="{ 'text-red-400': form.errors['coverage.depth_min'] }"
class="w-full mx-2 flex-1"
>
<FormControl required v-model="form.coverage.depth_min" type="text" placeholder="[enter depth_min]">
<div class="text-red-400 text-sm" v-if="Array.isArray(form.errors['coverage.depth_min'])">
{{ form.errors['coverage.depth_min'].join(', ') }}
</div>
</FormControl>
</FormField>
<FormField
v-if="depth === 'range'"
label="depth max"
:class="{ 'text-red-400': form.errors['coverage.depth_max'] }"
class="w-full mx-2 flex-1"
>
<FormControl required v-model="form.coverage.depth_max" type="text" placeholder="[enter depth_max]">
<div class="text-red-400 text-sm" v-if="Array.isArray(form.errors['coverage.depth_max'])">
{{ form.errors['coverage.depth_max'].join(', ') }}
</div>
</FormControl>
</FormField>
</div>
</CardBox>
<CardBox
class="mb-6 shadow"
has-table
title="Dataset Keywords"
:icon="mdiEarthPlus"
:header-icon="mdiPlusCircle"
v-on:header-icon-click="addKeyword"
>
<!-- <ul>
<li v-for="(subject, index) in form.subjects" :key="index">
{{ subject.value }} <BaseButton color="danger" :icon="mdiTrashCan" small @click.prevent="removeKeyword(index)" />
</li>
</ul> -->
<TableKeywords :keywords="form.subjects" :errors="form.errors" v-if="form.subjects.length > 0" />
</CardBox>
</div>
<div v-if="formStep == 4">
<!-- <progress v-if="form.progress" :value="form.progress.percentage" max="100">
{{ form.progress.percentage }}%
</progress> -->
<!-- <p v-if="isSaving">Uploading @{{ fileCount }} files...</p> -->
<!-- <div class="dropbox">
<input type="file" multiple name="files" @change="onChangeFile" class="input-file" />
<p>
Drag your file(s) here to begin<br />
or click to browse
</p>
</div> -->
<FileUploadComponent v-model="form.files"></FileUploadComponent>
<div class="text-red-400 text-sm" v-if="form.errors['file'] && Array.isArray(form.errors['file'])">
{{ form.errors['file'].join(', ') }}
</div>
<div class="text-red-400 text-sm" v-if="form.errors['upload.label'] && Array.isArray(form.errors['upload.label'])">
{{ form.errors['upload.label'].join(', ') }}
</div>
<!-- <label v-if="form.upload">{{ form.upload?.label }}</label> -->
</div>
</div>
<template #footer>
<div class="flex p-2 mt-4">
<button
v-if="formStep > 1"
@click="prevStep"
class="text-base hover:scale-110 focus:outline-none flex justify-center px-4 py-2 rounded font-bold cursor-pointer hover:bg-gray-200 bg-gray-100 text-gray-700 border duration-200 ease-in-out border-gray-600 transition"
>
Previous
</button>
<div class="flex-auto flex flex-row-reverse">
<button
v-if="formStep < 4"
@click="nextStep"
class="text-base ml-2 hover:scale-110 focus:outline-none flex justify-center px-4 py-2 rounded font-bold cursor-pointer hover:bg-teal-600 bg-teal-600 text-teal-100 border duration-200 ease-in-out border-teal-600 transition"
>
Next
</button>
<button
v-if="formStep == 4"
:disabled="form.processing"
class="text-base hover:scale-110 focus:outline-none flex justify-center px-4 py-2 rounded font-bold cursor-pointer hover:bg-teal-200 bg-teal-100 text-teal-700 border duration-200 ease-in-out border-teal-600 transition"
@click.stop="submit"
>
Save
</button>
</div>
</div>
<progress v-if="form.progress" :value="form.progress.percentage" max="100">{{ form.progress.percentage }}%</progress>
</template>
</CardBox>
</SectionMain>
</LayoutAuthenticated>
</template>
<style>
.dropbox {
outline: 2px dashed grey; /* the dash box */
outline-offset: -10px;
background: lightcyan;
color: dimgray;
padding: 10px 0;
min-height: 200px; /* minimum height */
position: relative;
cursor: pointer;
}
.input-file {
opacity: 0; /* invisible but it's there! */
width: 100%;
height: 200px;
position: absolute;
cursor: pointer;
}
.dropbox:hover {
background: lightblue; /* when mouse over to the drop zone, change color */
}
.dropbox p {
font-size: 1.2em;
text-align: center;
padding: 50px 0;
}
span.remove-file {
color: red;
cursor: pointer;
/* float: right; */
}
</style>