feat: enhanced dataset management and UI improvements
Some checks failed
CI Pipeline / japa-tests (push) Failing after 1m10s
Some checks failed
CI Pipeline / japa-tests (push) Failing after 1m10s
- Submitter/DatasetController.ts: improved validations for time_absolute, time_min, and time_max. - validators/dataset.ts: enhanced validations for time_absolute, time_min, and time_max. - Added new favicon.ico for better branding. - Improved password-meter.vue component with clearer hint messages. - Updated checkStrength.ts: enhanced checkStrength() method for password strength validation. - submitter/Dataset/Create.vue: added form controls for time_min, time_max, and/or time_absolute fields. - submitter/Dataset/Edit.vue: introduced a loading spinner during file upload for better UX.
This commit is contained in:
parent
f67b736a88
commit
d1480b1240
17 changed files with 2682 additions and 1446 deletions
|
@ -365,7 +365,7 @@ function onEnter() {
|
|||
</li>
|
||||
</ul>
|
||||
</div> -->
|
||||
<FormField label="Permissions" wrap-body>
|
||||
<FormField label="Extensions" wrap-body>
|
||||
<FormCheckRadioGroup v-model="form.file_extension" :options="file_extensions" name="file_extensions"
|
||||
is-column />
|
||||
</FormField>
|
||||
|
|
|
@ -14,11 +14,11 @@ 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 passwordMeter from '@/Components/SimplePasswordMeter/password-meter.vue';
|
||||
import PasswordMeter from '@/Components/SimplePasswordMeter/password-meter.vue';
|
||||
|
||||
const enabled = ref(false);
|
||||
const handleScore = (score: number) => {
|
||||
if (score == 4){
|
||||
if (score >= 4){
|
||||
enabled.value = true;
|
||||
} else {
|
||||
enabled.value = false;
|
||||
|
@ -101,15 +101,15 @@ const submit = async () => {
|
|||
</FormControl>
|
||||
</FormField>
|
||||
|
||||
<FormField label="Password" :class="{ 'text-red-400': errors.password }">
|
||||
<!-- <FormField label="Password" :class="{ 'text-red-400': errors.password }">
|
||||
<FormControl v-model="form.password" type="password" placeholder="Enter Password" :errors="errors.password">
|
||||
<div class="text-red-400 text-sm" v-if="errors.password && Array.isArray(errors.password)">
|
||||
<!-- {{ errors.password }} -->
|
||||
<div class="text-red-400 text-sm" v-if="errors.password && Array.isArray(errors.password)">
|
||||
{{ errors.password.join(', ') }}
|
||||
</div>
|
||||
</FormControl>
|
||||
</FormField>
|
||||
<password-meter :password="form.password" @score="handleScore" />
|
||||
<password-meter :password="form.password" @score="handleScore" /> -->
|
||||
<PasswordMeter v-model:password="form.password" :errors="form.errors" @score="handleScore" />
|
||||
|
||||
<FormField label="Password Confirmation" :class="{ 'text-red-400': errors.password_confirmation }">
|
||||
<FormControl
|
||||
|
|
|
@ -14,7 +14,7 @@ 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 passwordMeter from '@/Components/SimplePasswordMeter/password-meter.vue';
|
||||
import PasswordMeter from '@/Components/SimplePasswordMeter/password-meter.vue';
|
||||
|
||||
const enabled = ref(false);
|
||||
const props = defineProps({
|
||||
|
@ -52,7 +52,7 @@ const submit = async () => {
|
|||
await router.put(stardust.route('settings.user.update', [props.user.id]), form);
|
||||
};
|
||||
const handleScore = (score: number) => {
|
||||
if (score == 4){
|
||||
if (score >= 4){
|
||||
enabled.value = true;
|
||||
} else {
|
||||
enabled.value = false;
|
||||
|
@ -116,7 +116,7 @@ const handleScore = (score: number) => {
|
|||
</FormControl>
|
||||
</FormField>
|
||||
|
||||
<password-meter :password="form.password" @score="handleScore" />
|
||||
<PasswordMeter v-model:password="form.password" :errors="form.errors" @score="handleScore" />
|
||||
|
||||
<FormField label="Password Confirmation" :class="{ 'text-red-400': errors.password_confirmation }">
|
||||
<FormControl
|
||||
|
|
|
@ -25,11 +25,11 @@ import NotificationBar from '@/Components/NotificationBar.vue';
|
|||
import LayoutAuthenticated from '@/Layouts/LayoutAuthenticated.vue';
|
||||
import SectionTitleLineWithButton from '@/Components/SectionTitleLineWithButton.vue';
|
||||
import { stardust } from '@eidellev/adonis-stardust/client';
|
||||
import passwordMeter from '@/Components/SimplePasswordMeter/password-meter.vue';
|
||||
import { computed, Ref } from 'vue';
|
||||
import { usePage } from '@inertiajs/vue3';
|
||||
import FormValidationErrors from '@/Components/FormValidationErrors.vue';
|
||||
import PersonalTotpSettings from '@/Components/PersonalTotpSettings.vue';
|
||||
import PasswordMeter from '@/Components/SimplePasswordMeter/password-meter.vue';
|
||||
// import PersonalSettings from '@/Components/PersonalSettings.vue';
|
||||
// import { MainService } from '@/Stores/main';
|
||||
// const mainService = MainService();
|
||||
|
@ -38,7 +38,7 @@ const emit = defineEmits(['confirm', 'update:confirmation'])
|
|||
|
||||
const enabled = ref(false);
|
||||
const handleScore = (score: number) => {
|
||||
if (score == 4){
|
||||
if (score >= 4){
|
||||
enabled.value = true;
|
||||
} else {
|
||||
enabled.value = false;
|
||||
|
@ -186,7 +186,7 @@ const flash: Ref<any> = computed(() => {
|
|||
</FormField>
|
||||
<BaseDivider />
|
||||
|
||||
<FormField label="New password" help="Required. New password"
|
||||
<!-- <FormField label="New password" help="Required. New password"
|
||||
:class="{ 'text-red-400': passwordForm.errors.new_password }">
|
||||
<FormControl v-model="passwordForm.new_password" :icon="mdiFormTextboxPassword" name="new_password"
|
||||
type="password" required :error="passwordForm.errors.new_password">
|
||||
|
@ -194,8 +194,8 @@ const flash: Ref<any> = computed(() => {
|
|||
{{ passwordForm.errors.new_password }}
|
||||
</div>
|
||||
</FormControl>
|
||||
</FormField>
|
||||
<password-meter :password="passwordForm.new_password" @score="handleScore" />
|
||||
</FormField> -->
|
||||
<PasswordMeter v-model:password="passwordForm.new_password" :errors="passwordForm.errors" @score="handleScore" />
|
||||
|
||||
|
||||
<FormField label="Confirm password" help="Required. New password one more time"
|
||||
|
|
|
@ -252,6 +252,19 @@ watch(depth, (currentValue) => {
|
|||
}
|
||||
});
|
||||
// let time= "no_time";
|
||||
let time = ref('no_time');
|
||||
watch(time, (currentValue) => {
|
||||
if (currentValue == 'absolut') {
|
||||
form.coverage.time_min = undefined;
|
||||
form.coverage.time_max = undefined;
|
||||
} else if (currentValue == 'range') {
|
||||
form.coverage.time_absolut = undefined;
|
||||
} else {
|
||||
form.coverage.time_absolut = undefined;
|
||||
form.coverage.time_min = undefined;
|
||||
form.coverage.time_max = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
const isModalActive = ref(false);
|
||||
const formStep = ref(1);
|
||||
|
@ -860,16 +873,16 @@ Removes a selected keyword
|
|||
|
||||
<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">
|
||||
<div class="flex flex-col md:flex-row mb-3 space-y-2 md:space-y-0 md:space-x-4">
|
||||
<label for="elevation-option-one" class="pure-radio mb-2 md:mb-0">
|
||||
<input id="elevation-option-one" type="radio" v-model="elevation" value="absolut" />
|
||||
absolut elevation (m)
|
||||
</label>
|
||||
<label for="elevation-option-two" class="pure-radio">
|
||||
<label for="elevation-option-two" class="pure-radio mb-2 md:mb-0">
|
||||
<input id="elevation-option-two" type="radio" v-model="elevation" value="range" />
|
||||
elevation range (m)
|
||||
</label>
|
||||
<label for="elevation-option-three" class="pure-radio">
|
||||
<label for="elevation-option-three" class="pure-radio mb-2 md:mb-0">
|
||||
<input id="elevation-option-three" type="radio" v-model="elevation"
|
||||
value="no_elevation" />
|
||||
no elevation
|
||||
|
@ -912,16 +925,16 @@ Removes a selected keyword
|
|||
</div>
|
||||
|
||||
<!-- depth menu -->
|
||||
<div class="lex flex-col md:flex-row mb-3">
|
||||
<label for="depth-option-one" class="pure-radio">
|
||||
<div class="flex flex-col md:flex-row mb-3 space-y-2 md:space-y-0 md:space-x-4">
|
||||
<label for="depth-option-one" class="pure-radio mb-2 md:mb-0">
|
||||
<input id="depth-option-one" type="radio" v-model="depth" value="absolut" />
|
||||
absolut depth (m)
|
||||
</label>
|
||||
<label for="depth-option-two" class="pure-radio">
|
||||
<label for="depth-option-two" class="pure-radio mb-2 md:mb-0">
|
||||
<input id="depth-option-two" type="radio" v-model="depth" value="range" />
|
||||
depth range (m)
|
||||
</label>
|
||||
<label for="depth-option-three" class="pure-radio">
|
||||
<label for="depth-option-three" class="pure-radio mb-2 md:mb-0">
|
||||
<input id="depth-option-three" type="radio" v-model="depth" value="no_depth" />
|
||||
no depth
|
||||
</label>
|
||||
|
@ -961,11 +974,62 @@ Removes a selected keyword
|
|||
</FormControl>
|
||||
</FormField>
|
||||
</div>
|
||||
|
||||
<!-- time menu -->
|
||||
<div class="flex flex-col md:flex-row mb-3 space-y-2 md:space-y-0 md:space-x-4">
|
||||
<label for="time-option-one" class="pure-radio mb-2 md:mb-0">
|
||||
<input id="time-option-one" type="radio" v-model="time" value="absolut" />
|
||||
absolut time (yyyy-MM-dd HH:mm:ss)
|
||||
</label>
|
||||
<label for="time-option-two" class="pure-radio mb-2 md:mb-0">
|
||||
<input id="time-option-two" type="radio" v-model="time" value="range" />
|
||||
time range (yyyy-MM-dd HH:mm:ss)
|
||||
</label>
|
||||
<label for="time-option-three" class="pure-radio mb-2 md:mb-0">
|
||||
<input id="time-option-three" type="radio" v-model="time" value="no_time" />
|
||||
no time
|
||||
</label>
|
||||
</div>
|
||||
<div class="flex flex-col md:flex-row">
|
||||
<FormField v-if="time === 'absolut'" label="time absolut"
|
||||
:class="{ 'text-red-400': form.errors['coverage.time_absolut'] }"
|
||||
class="w-full mx-2 flex-1">
|
||||
<FormControl required v-model="form.coverage.time_absolut" type="datetime-local"
|
||||
placeholder="[enter time_absolut]">
|
||||
<div class="text-red-400 text-sm"
|
||||
v-if="Array.isArray(form.errors['coverage.time_absolut'])">
|
||||
{{ form.errors['coverage.time_absolut'].join(', ') }}
|
||||
</div>
|
||||
</FormControl>
|
||||
</FormField>
|
||||
<FormField v-if="time === 'range'" label="time min"
|
||||
:class="{ 'text-red-400': form.errors['coverage.time_min'] }"
|
||||
class="w-full mx-2 flex-1">
|
||||
<FormControl required v-model="form.coverage.time_min" type="datetime-local"
|
||||
placeholder="[enter time_min]">
|
||||
<div class="text-red-400 text-sm"
|
||||
v-if="Array.isArray(form.errors['coverage.time_min'])">
|
||||
{{ form.errors['coverage.time_min'].join(', ') }}
|
||||
</div>
|
||||
</FormControl>
|
||||
</FormField>
|
||||
<FormField v-if="time === 'range'" label="time max"
|
||||
:class="{ 'text-red-400': form.errors['coverage.time_max'] }"
|
||||
class="w-full mx-2 flex-1">
|
||||
<FormControl required v-model="form.coverage.time_max" type="datetime-local"
|
||||
placeholder="[enter time_max]">
|
||||
<div class="text-red-400 text-sm"
|
||||
v-if="Array.isArray(form.errors['coverage.time_max'])">
|
||||
{{ form.errors['coverage.time_max'].join(', ') }}
|
||||
</div>
|
||||
</FormControl>
|
||||
</FormField>
|
||||
</div>
|
||||
</CardBox>
|
||||
|
||||
<CardBox class="mb-6 shadow" has-table title="Dataset References" :header-icon="mdiPlusCircle"
|
||||
v-on:header-icon-click="addReference">
|
||||
<!-- Message when no references exist -->
|
||||
<CardBox class="mb-6 shadow" has-table title="Dataset References" :icon="mdiEarthPlus"
|
||||
:header-icon="mdiPlusCircle" v-on:header-icon-click="addReference">
|
||||
<!-- Message when no references exist -->
|
||||
<div v-if="form.references.length === 0" class="text-center py-4">
|
||||
<p class="text-gray-600">No references added yet.</p>
|
||||
<p class="text-gray-400">Click the plus icon above to add a new reference.</p>
|
||||
|
|
|
@ -334,8 +334,14 @@
|
|||
</FormField>
|
||||
</div>
|
||||
|
||||
<CardBox class="mb-6 shadow" has-table title="Dataset References" :header-icon="mdiPlusCircle"
|
||||
<CardBox class="mb-6 shadow" has-table title="Dataset References" :icon="mdiEarthPlus" :header-icon="mdiPlusCircle"
|
||||
v-on:header-icon-click="addReference">
|
||||
<!-- Message when no references exist -->
|
||||
<div v-if="form.references.length === 0" class="text-center py-4">
|
||||
<p class="text-gray-600">No references added yet.</p>
|
||||
<p class="text-gray-400">Click the plus icon above to add a new reference.</p>
|
||||
</div>
|
||||
<!-- Reference form -->
|
||||
<table class="table-fixed border-green-900" v-if="form.references.length">
|
||||
<thead>
|
||||
<tr>
|
||||
|
@ -388,8 +394,9 @@
|
|||
<FormControl required v-model="form.references[index].label" type="text"
|
||||
placeholder="[reference label]">
|
||||
<div class="text-red-400 text-sm"
|
||||
v-if="form.errors[`references.${index}.label`] && Array.isArray(form.errors[`references.${index}.label`])">
|
||||
v-if="form.errors[`references.${index}.label`]">
|
||||
{{ form.errors[`references.${index}.label`].join(', ') }}
|
||||
|
||||
</div>
|
||||
</FormControl>
|
||||
</td>
|
||||
|
@ -468,7 +475,15 @@
|
|||
</BaseButtons>
|
||||
</template>
|
||||
</CardBox>
|
||||
<!-- </div> -->
|
||||
<!-- Loading Spinner -->
|
||||
<div v-if="form.processing"
|
||||
class="fixed inset-0 flex items-center justify-center bg-gray-500 bg-opacity-50 z-50">
|
||||
<svg class="animate-spin h-12 w-12 text-white" xmlns="http://www.w3.org/2000/svg" fill="none"
|
||||
viewBox="0 0 24 24">
|
||||
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
|
||||
<path class="opacity-75" fill="currentColor" d="M12 2a10 10 0 0110 10h-4a6 6 0 00-6-6V2z"></path>
|
||||
</svg>
|
||||
</div>
|
||||
</SectionMain>
|
||||
</LayoutAuthenticated>
|
||||
</template>
|
||||
|
|
Loading…
Add table
editor.link_modal.header
Reference in a new issue