Compose common form components.

This commit is contained in:
Buster Neece 2022-12-23 08:53:11 -06:00
parent f75dfd2fcb
commit 4065c7dbd9
No known key found for this signature in database
GPG Key ID: F1D2E64A0005E80E
16 changed files with 412 additions and 401 deletions

View File

@ -107,7 +107,7 @@
</div>
</template>
<script>
<script setup>
import Icon from "~/components/Common/Icon";
import DataTable from "~/components/Common/DataTable";
import AdminBackupsLastOutputModal from "./Backups/LastOutputModal";
@ -117,108 +117,121 @@ import AdminBackupsConfigureModal from "~/components/Admin/Backups/ConfigureModa
import AdminBackupsRunBackupModal from "~/components/Admin/Backups/RunBackupModal";
import EnabledBadge from "~/components/Common/Badges/EnabledBadge.vue";
import {useAzuraCast} from "~/vendor/azuracast";
import {onMounted, ref} from "vue";
import {useTranslate} from "~/vendor/gettext";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
import {useSweetAlert} from "~/vendor/sweetalert";
export default {
name: 'AdminBackups',
components: {
EnabledBadge,
AdminBackupsRunBackupModal,
AdminBackupsConfigureModal,
AdminBackupsLastOutputModal,
DataTable,
Icon
},
props: {
listUrl: String,
settingsUrl: String,
runBackupUrl: String,
storageLocations: Object,
isDocker: Boolean,
},
data() {
return {
fields: [
{
key: 'basename',
isRowHeader: true,
label: this.$gettext('File Name'),
sortable: false
},
{
key: 'timestamp',
label: this.$gettext('Last Modified'),
sortable: false
},
{
key: 'size',
label: this.$gettext('Size'),
sortable: false
},
{key: 'actions', label: this.$gettext('Actions'), sortable: false, class: 'shrink'}
],
settingsLoading: false,
settings: {
backupEnabled: false,
backupLastRun: null,
backupLastOutput: '',
}
}
},
mounted() {
this.relist();
},
methods: {
relist() {
this.settingsLoading = true;
this.$wrapWithLoading(
this.axios.get(this.settingsUrl)
).then((resp) => {
this.settings = {
backupEnabled: resp.data.backup_enabled,
backupLastRun: resp.data.backup_last_run,
backupLastOutput: resp.data.backup_last_output
};
this.settingsLoading = false;
});
const props = defineProps({
listUrl: String,
settingsUrl: String,
runBackupUrl: String,
storageLocations: Object,
isDocker: Boolean,
});
this.$refs.datatable.relist();
},
toRelativeTime(timestamp) {
return DateTime.fromSeconds(timestamp).toRelative();
},
toLocaleTime(timestamp) {
const {timeConfig} = useAzuraCast();
const settingsLoading = ref(false);
return DateTime.fromSeconds(timestamp).toLocaleString(
{...DateTime.DATETIME_SHORT, timeConfig}
);
},
formatFileSize(size) {
return formatFileSize(size);
},
showLastOutput() {
this.$refs.lastOutputModal.show();
},
doConfigure() {
this.$refs.configureModal.open();
},
doRunBackup() {
this.$refs.runBackupModal.open();
},
doDelete(url) {
this.$confirmDelete({
title: this.$gettext('Delete Backup?')
}).then((result) => {
if (result.value) {
this.$wrapWithLoading(
this.axios.delete(url)
).then((resp) => {
this.$notifySuccess(resp.data.message);
this.relist();
});
}
});
}
const blankSettings = {
backupEnabled: false,
backupLastRun: null,
backupLastOutput: '',
};
const settings = ref({...blankSettings});
const {$gettext} = useTranslate();
const fields = [
{
key: 'basename',
isRowHeader: true,
label: $gettext('File Name'),
sortable: false
},
{
key: 'timestamp',
label: $gettext('Last Modified'),
sortable: false
},
{
key: 'size',
label: $gettext('Size'),
sortable: false
},
{
key: 'actions',
label: $gettext('Actions'),
sortable: false,
class: 'shrink'
}
}
];
const datatable = ref(); // Template Ref
const {wrapWithLoading, notifySuccess} = useNotify();
const {axios} = useAxios();
const relist = () => {
settingsLoading.value = true;
wrapWithLoading(
axios.get(props.settingsUrl)
).then((resp) => {
settings.value = {
backupEnabled: resp.data.backup_enabled,
backupLastRun: resp.data.backup_last_run,
backupLastOutput: resp.data.backup_last_output
};
settingsLoading.value = false;
});
datatable.value.relist();
};
onMounted(relist);
const toRelativeTime = (timestamp) => {
return DateTime.fromSeconds(timestamp).toRelative();
};
const toLocaleTime = (timestamp) => {
const {timeConfig} = useAzuraCast();
return DateTime.fromSeconds(timestamp).toLocaleString(
{...DateTime.DATETIME_SHORT, timeConfig}
);
};
const lastOutputModal = ref(); // Template Ref
const showLastOutput = () => {
lastOutputModal.value.show();
};
const configureModal = ref(); // Template Ref
const doConfigure = () => {
configureModal.value.open();
};
const runBackupModal = ref(); // Template Ref
const doRunBackup = () => {
runBackupModal.value.open();
};
const {confirmDelete} = useSweetAlert();
const doDelete = (url) => {
confirmDelete({
title: $gettext('Delete Backup?')
}).then((result) => {
if (result.value) {
wrapWithLoading(
axios.delete(url)
).then((resp) => {
notifySuccess(resp.data.message);
relist();
});
}
});
};
</script>

View File

@ -80,7 +80,6 @@
</template>
<script setup>
import useVuelidate from "@vuelidate/core";
import BFormFieldset from "~/components/Form/BFormFieldset";
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import InvisibleSubmitButton from "~/components/Common/InvisibleSubmitButton";
@ -90,6 +89,7 @@ import StreamingLogView from "~/components/Common/StreamingLogView";
import {computed, ref} from "vue";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
import {useVuelidateOnForm} from "~/components/Form/UseVuelidateOnForm";
const props = defineProps({
runBackupUrl: String,
@ -106,21 +106,18 @@ const logUrl = ref(null);
const error = ref(null);
const modal = ref(); // BModal
const blankForm = {
storage_location: null,
path: '',
exclude_media: false,
};
const form = ref({...blankForm});
const validations = {
'storage_location': {},
'path': {},
'exclude_media': {}
};
const v$ = useVuelidate(validations, form);
const {form, resetForm, v$} = useVuelidateOnForm(
{
'storage_location': {},
'path': {},
'exclude_media': {}
},
{
storage_location: null,
path: '',
exclude_media: false,
}
);
const open = () => {
modal.value.show();
@ -158,7 +155,7 @@ const clearContents = () => {
logUrl.value = null;
error.value = null;
form.value = {...blankForm};
resetForm();
}
defineExpose({

View File

@ -13,11 +13,11 @@
<div class="card-body">
<ul class="list-unstyled">
<custom-asset-form id="asset_background" class="mb-3" :api-url="backgroundApiUrl"
:caption="langBackground"></custom-asset-form>
:caption="$gettext('Public Page Background')"></custom-asset-form>
<custom-asset-form id="asset_album_art" class="mb-3" :api-url="albumArtApiUrl"
:caption="langAlbumArt"></custom-asset-form>
:caption="$gettext('Default Album Art')"></custom-asset-form>
<custom-asset-form id="asset_browser_icon" :api-url="browserIconApiUrl"
:caption="langBrowserIcon"></custom-asset-form>
:caption="$gettext('Browser Icon')"></custom-asset-form>
</ul>
</div>
</section>
@ -26,29 +26,15 @@
</div>
</template>
<script>
<script setup>
import CustomAssetForm from "./Branding/CustomAssetForm";
import BrandingForm from "./Branding/BrandingForm";
export default {
name: 'Branding',
components: {BrandingForm, CustomAssetForm},
props: {
settingsApiUrl: String,
browserIconApiUrl: String,
backgroundApiUrl: String,
albumArtApiUrl: String
},
computed: {
langBrowserIcon() {
return this.$gettext('Browser Icon');
},
langBackground() {
return this.$gettext('Public Page Background');
},
langAlbumArt() {
return this.$gettext('Default Album Art');
}
}
};
const props = defineProps({
settingsApiUrl: String,
browserIconApiUrl: String,
backgroundApiUrl: String,
albumArtApiUrl: String
});
</script>

View File

@ -140,7 +140,6 @@
</template>
<script setup>
import useVuelidate from "@vuelidate/core";
import CodemirrorTextarea from "~/components/Common/CodemirrorTextarea";
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import BWrappedFormCheckbox from "~/components/Form/BWrappedFormCheckbox";
@ -149,6 +148,7 @@ import {useAxios} from "~/vendor/axios";
import mergeExisting from "~/functions/mergeExisting";
import {useNotify} from "~/vendor/bootstrapVue";
import {useTranslate} from "~/vendor/gettext";
import {useVuelidateOnForm} from "~/components/Form/UseVuelidateOnForm";
const props = defineProps({
apiUrl: String,
@ -157,31 +157,28 @@ const props = defineProps({
const loading = ref(true);
const error = ref(null);
const blankForm = {
'public_theme': '',
'hide_album_art': false,
'homepage_redirect_url': '',
'default_album_art_url': '',
'hide_product_name': false,
'public_custom_css': '',
'public_custom_js': '',
'internal_custom_css': ''
};
const form = ref({...blankForm});
const validations = {
'public_theme': {},
'hide_album_art': {},
'homepage_redirect_url': {},
'default_album_art_url': {},
'hide_product_name': {},
'public_custom_css': {},
'public_custom_js': {},
'internal_custom_css': {}
};
const v$ = useVuelidate(validations, form);
const {form, resetForm, v$} = useVuelidateOnForm(
{
'public_theme': {},
'hide_album_art': {},
'homepage_redirect_url': {},
'default_album_art_url': {},
'hide_product_name': {},
'public_custom_css': {},
'public_custom_js': {},
'internal_custom_css': {}
},
{
'public_theme': '',
'hide_album_art': false,
'homepage_redirect_url': '',
'default_album_art_url': '',
'hide_product_name': false,
'public_custom_css': '',
'public_custom_js': '',
'internal_custom_css': ''
}
);
const {$gettext} = useTranslate();
@ -209,8 +206,8 @@ const populateForm = (data) => {
};
const relist = () => {
v$.value.$reset();
form.value = {...blankForm};
resetForm();
loading.value = true;
axios.get(props.apiUrl).then((resp) => {

View File

@ -39,60 +39,71 @@
</data-table>
</b-card>
<edit-modal ref="editModal" :create-url="listUrl" :auto-assign-types="autoAssignTypes"
<edit-modal ref="editmodal" :create-url="listUrl" :auto-assign-types="autoAssignTypes"
@relist="relist"></edit-modal>
</template>
<script>
<script setup>
import DataTable from '~/components/Common/DataTable';
import EditModal from './CustomFields/EditModal';
import Icon from '~/components/Common/Icon';
import InfoCard from '~/components/Common/InfoCard';
import _ from 'lodash';
import {useTranslate} from "~/vendor/gettext";
import {ref} from "vue";
import {useSweetAlert} from "~/vendor/sweetalert";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
export default {
name: 'AdminCustomFields',
components: {InfoCard, Icon, EditModal, DataTable},
props: {
listUrl: String,
autoAssignTypes: Object
},
data() {
return {
fields: [
{key: 'name', isRowHeader: true, label: this.$gettext('Field Name'), sortable: false},
{key: 'auto_assign', label: this.$gettext('Auto-Assign Value'), sortable: false},
{key: 'actions', label: this.$gettext('Actions'), sortable: false, class: 'shrink'}
]
};
},
methods: {
getAutoAssignName(autoAssign) {
return _.get(this.autoAssignTypes, autoAssign, this.$gettext('None'));
},
relist() {
this.$refs.datatable.refresh();
},
doCreate() {
this.$refs.editModal.create();
},
doEdit(url) {
this.$refs.editModal.edit(url);
},
doDelete(url) {
this.$confirmDelete({
title: this.$gettext('Delete Custom Field?')
}).then((result) => {
if (result.value) {
this.$wrapWithLoading(
this.axios.delete(url)
).then((resp) => {
this.$notifySuccess(resp.data.message);
this.relist();
});
}
const props = defineProps({
listUrl: String,
autoAssignTypes: Object
});
const {$gettext} = useTranslate();
const fields = [
{key: 'name', isRowHeader: true, label: $gettext('Field Name'), sortable: false},
{key: 'auto_assign', label: $gettext('Auto-Assign Value'), sortable: false},
{key: 'actions', label: $gettext('Actions'), sortable: false, class: 'shrink'}
];
const getAutoAssignName = (autoAssign) => {
return _.get(props.autoAssignTypes, autoAssign, $gettext('None'));
};
const datatable = ref(); // Template Ref
const relist = () => {
datatable.value.refresh();
};
const editmodal = ref(); // Template Ref
const doCreate = () => {
editmodal.value.create();
}
const doEdit = (url) => {
editmodal.value.edit(url);
}
const {confirmDelete} = useSweetAlert();
const {wrapWithLoading, notifySuccess} = useNotify();
const {axios} = useAxios();
const doDelete = (url) => {
confirmDelete({
title: $gettext('Delete Custom Field?')
}).then((result) => {
if (result.value) {
wrapWithLoading(
axios.delete(url)
).then((resp) => {
notifySuccess(resp.data.message);
relist();
});
}
}
});
};
</script>

View File

@ -9,38 +9,28 @@
</template>
<script>
import useVuelidate from "@vuelidate/core";
import {required} from '@vuelidate/validators';
import BaseEditModal from '~/components/Common/BaseEditModal';
import AdminCustomFieldsForm from "~/components/Admin/CustomFields/Form";
import {ref} from "vue";
import {useVuelidateOnForm} from "~/components/Form/UseVuelidateOnForm";
export default {
name: 'AdminCustomFieldsEditModal',
mixins: [BaseEditModal],
components: {AdminCustomFieldsForm},
setup() {
const blankForm = {
'name': '',
'short_name': '',
'auto_assign': ''
};
const form = ref({
...blankForm
});
const resetForm = () => {
form.value = {...blankForm};
}
const validations = {
'name': {required},
'short_name': {},
'auto_assign': {}
};
const v$ = useVuelidate(validations, form);
const {form, resetForm, v$} = useVuelidateOnForm(
{
'name': {required},
'short_name': {},
'auto_assign': {}
},
{
'name': '',
'short_name': '',
'auto_assign': ''
}
);
return {
form,

View File

@ -44,21 +44,24 @@
<script setup>
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import {computed} from "vue";
import {useTranslate} from "~/vendor/gettext";
const props = defineProps({
form: Object,
autoAssignTypes: Object
});
const {$gettext} = useTranslate();
const autoAssignOptions = computed(() => {
let autoAssignOptions = [
{
text: this.$gettext('Disable'),
text: $gettext('Disable'),
value: '',
}
];
_.forEach(this.autoAssignTypes, (typeName, typeKey) => {
_.forEach(props.autoAssignTypes, (typeName, typeKey) => {
autoAssignOptions.push({
text: typeName,
value: typeKey

View File

@ -86,22 +86,40 @@
</div>
</template>
<script>
import useVuelidate from "@vuelidate/core";
import BFormFieldset from "~/components/Form/BFormFieldset";
<script setup>
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import '~/vendor/sweetalert.js';
import InfoCard from "~/components/Common/InfoCard";
import {ref} from "vue";
import {useVuelidateOnForm} from "~/components/Form/UseVuelidateOnForm";
const props = defineProps({
apiUrl: String
});
const loading = ref(true);
const version = ref(null);
const {form, resetForm, v$} = useVuelidateOnForm(
{
key: {}
},
{
key: null
}
);
</script>
<script>
export default {
name: 'GeoLite',
components: {InfoCard, BWrappedFormGroup, BFormFieldset},
setup() {
return {v$: useVuelidate()}
},
props: {
apiUrl: String
},
props: {},
data() {
return {
loading: true,
@ -109,9 +127,7 @@ export default {
version: null
};
},
validations: {
key: {}
},
validations: {},
computed: {
langInstalledVersion() {
const text = this.$gettext('GeoLite version "%{ version }" is currently installed.');

View File

@ -15,13 +15,11 @@
</template>
<script>
import useVuelidate from "@vuelidate/core";
import {required} from '@vuelidate/validators';
import BaseEditModal from '~/components/Common/BaseEditModal';
import AdminPermissionsGlobalForm from "./Form/GlobalForm";
import AdminPermissionsStationForm from "./Form/StationForm";
import _ from 'lodash';
import {ref} from "vue";
export default {
name: 'AdminPermissionsEditModal',
@ -33,29 +31,22 @@ export default {
stationPermissions: Object
},
setup() {
const blankForm = {
'name': '',
'permissions': {
'global': [],
'station': [],
const {form, resetForm, v$} = useVuelidateOnForm(
{
'name': {required},
'permissions': {
'global': {},
'station': {},
}
},
{
'name': '',
'permissions': {
'global': [],
'station': [],
}
}
};
const form = ref({...blankForm});
const validations = {
'name': {required},
'permissions': {
'global': {},
'station': {},
}
};
const resetForm = () => {
form.value = {...blankForm};
}
const v$ = useVuelidate(validations, form);
);
return {
form,

View File

@ -63,11 +63,11 @@ import SettingsGeneralTab from "./Settings/GeneralTab";
import SettingsServicesTab from "./Settings/ServicesTab";
import SettingsSecurityPrivacyTab from "~/components/Admin/Settings/SecurityPrivacyTab";
import {onMounted, ref} from "vue";
import useVuelidate from "@vuelidate/core";
import {useAxios} from "~/vendor/axios";
import mergeExisting from "~/functions/mergeExisting";
import {useNotify} from "~/vendor/bootstrapVue";
import {useTranslate} from "~/vendor/gettext";
import {useVuelidateOnForm} from "~/components/Form/UseVuelidateOnForm";
const props = defineProps({
apiUrl: String,
@ -82,88 +82,85 @@ const props = defineProps({
const emits = defineEmits(['saved']);
const blankForm = {
base_url: '',
instance_name: '',
prefer_browser_url: true,
use_radio_proxy: true,
history_keep_days: 7,
enable_static_nowplaying: true,
enable_advanced_features: true,
analytics: null,
always_use_ssl: false,
api_access_control: '*',
check_for_updates: 1,
acme_email: '',
acme_domains: '',
mail_enabled: false,
mail_sender_name: '',
mail_sender_email: '',
mail_smtp_host: '',
mail_smtp_port: '',
mail_smtp_secure: '',
mail_smtp_username: '',
mail_smtp_password: '',
avatar_service: 'gravatar',
avatar_default_url: '',
use_external_album_art_in_apis: false,
use_external_album_art_when_processing_media: false,
last_fm_api_key: ''
};
const {form, resetForm, v$} = useVuelidateOnForm(
{
base_url: {required},
instance_name: {},
prefer_browser_url: {},
use_radio_proxy: {},
history_keep_days: {required},
enable_static_nowplaying: {},
enable_advanced_features: {},
const form = ref({...blankForm});
analytics: {required},
const validations = {
base_url: {required},
instance_name: {},
prefer_browser_url: {},
use_radio_proxy: {},
history_keep_days: {required},
enable_static_nowplaying: {},
enable_advanced_features: {},
always_use_ssl: {},
api_access_control: {},
analytics: {required},
always_use_ssl: {},
api_access_control: {},
check_for_updates: {},
acme_email: {},
acme_domains: {},
mail_enabled: {},
mail_sender_name: {},
mail_sender_email: {},
mail_smtp_host: {},
mail_smtp_port: {},
mail_smtp_secure: {},
mail_smtp_username: {},
mail_smtp_password: {},
avatar_service: {},
avatar_default_url: {},
use_external_album_art_in_apis: {},
use_external_album_art_when_processing_media: {},
last_fm_api_key: {},
$validationGroups: {
generalTab: [
'base_url', 'instance_name', 'prefer_browser_url', 'use_radio_proxy',
'history_keep_days', 'enable_static_nowplaying', 'enable_advanced_features'
],
securityPrivacyTab: [
'analytics', 'always_use_ssl', 'api_access_control'
],
servicesTab: [
'check_for_updates',
'acme_email', 'acme_domains',
'mail_enabled', 'mail_sender_name', 'mail_sender_email',
'mail_smtp_host', 'mail_smtp_port', 'mail_smtp_secure', 'mail_smtp_username',
'mail_smtp_password', 'avatar_service', 'avatar_default_url',
'use_external_album_art_in_apis', 'use_external_album_art_when_processing_media',
'last_fm_api_key',
]
check_for_updates: {},
acme_email: {},
acme_domains: {},
mail_enabled: {},
mail_sender_name: {},
mail_sender_email: {},
mail_smtp_host: {},
mail_smtp_port: {},
mail_smtp_secure: {},
mail_smtp_username: {},
mail_smtp_password: {},
avatar_service: {},
avatar_default_url: {},
use_external_album_art_in_apis: {},
use_external_album_art_when_processing_media: {},
last_fm_api_key: {},
$validationGroups: {
generalTab: [
'base_url', 'instance_name', 'prefer_browser_url', 'use_radio_proxy',
'history_keep_days', 'enable_static_nowplaying', 'enable_advanced_features'
],
securityPrivacyTab: [
'analytics', 'always_use_ssl', 'api_access_control'
],
servicesTab: [
'check_for_updates',
'acme_email', 'acme_domains',
'mail_enabled', 'mail_sender_name', 'mail_sender_email',
'mail_smtp_host', 'mail_smtp_port', 'mail_smtp_secure', 'mail_smtp_username',
'mail_smtp_password', 'avatar_service', 'avatar_default_url',
'use_external_album_art_in_apis', 'use_external_album_art_when_processing_media',
'last_fm_api_key',
]
}
},
{
base_url: '',
instance_name: '',
prefer_browser_url: true,
use_radio_proxy: true,
history_keep_days: 7,
enable_static_nowplaying: true,
enable_advanced_features: true,
analytics: null,
always_use_ssl: false,
api_access_control: '*',
check_for_updates: 1,
acme_email: '',
acme_domains: '',
mail_enabled: false,
mail_sender_name: '',
mail_sender_email: '',
mail_smtp_host: '',
mail_smtp_port: '',
mail_smtp_secure: '',
mail_smtp_username: '',
mail_smtp_password: '',
avatar_service: 'gravatar',
avatar_default_url: '',
use_external_album_art_in_apis: false,
use_external_album_art_when_processing_media: false,
last_fm_api_key: ''
}
};
const v$ = useVuelidate(validations, form);
);
const loading = ref(true);
const error = ref(null);

View File

@ -19,33 +19,26 @@
</template>
<script setup>
import useVuelidate from "@vuelidate/core";
import {email, required} from '@vuelidate/validators';
import BWrappedFormGroup from "~/components/Form/BWrappedFormGroup";
import {ref} from "vue";
import {useNotify} from "~/vendor/bootstrapVue";
import {useTranslate} from "~/vendor/gettext";
import {useAxios} from "~/vendor/axios";
import {useVuelidateOnForm} from "~/components/Form/UseVuelidateOnForm";
const props = defineProps({
testMessageUrl: String
});
const blankForm = {
emailAddress: null
};
const form = ref({...blankForm});
const validations = {
emailAddress: {required, email}
};
const v$ = useVuelidate(validations, form, {$stopPropagation: true});
const resetForm = () => {
form.value = {...blankForm};
};
const {form, resetForm, v$} = useVuelidateOnForm(
{
emailAddress: {required, email}
},
{
emailAddress: null
}
);
const modal = ref(); // BModal

View File

@ -9,7 +9,6 @@
</template>
<script setup>
import useVuelidate from "@vuelidate/core";
import {required} from '@vuelidate/validators';
import ModalForm from "~/components/Common/ModalForm";
import AdminStationsCloneModalForm from "~/components/Admin/Stations/CloneModalForm";
@ -17,6 +16,7 @@ import {ref} from "vue";
import {useTranslate} from "~/vendor/gettext";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
import {useVuelidateOnForm} from "~/components/Form/UseVuelidateOnForm";
const emit = defineEmits(['relist']);
@ -24,25 +24,18 @@ const loading = ref(true);
const cloneUrl = ref(null);
const error = ref(null);
const blankForm = {
name: '',
description: '',
clone: [],
};
const form = ref({...blankForm});
const validations = {
name: {required},
description: {},
clone: {}
};
const v$ = useVuelidate(validations, form);
const resetForm = () => {
form.value = {...blankForm};
};
const {form, resetForm, v$} = useVuelidateOnForm(
{
name: {required},
description: {},
clone: {}
},
{
name: '',
description: '',
clone: [],
}
);
const modal = ref(); // BVModal
const {$gettext} = useTranslate();

View File

@ -98,10 +98,10 @@ import AdminStationsStreamersForm from "./Form/StreamersForm.vue";
import {decimal, numeric, required, url} from '@vuelidate/validators';
import {AUDIO_PROCESSING_NONE, BACKEND_LIQUIDSOAP, FRONTEND_ICECAST} from "~/components/Entity/RadioAdapters";
import {computed, ref, watch} from "vue";
import useVuelidate from "@vuelidate/core";
import {useNotify} from "~/vendor/bootstrapVue";
import {useAxios} from "~/vendor/axios";
import mergeExisting from "~/functions/mergeExisting";
import {useVuelidateOnForm} from "~/components/Form/UseVuelidateOnForm";
const props = defineProps({
...StationFormProps.props,
@ -335,10 +335,7 @@ const buildForm = () => {
};
const {blankForm, validations} = buildForm();
const form = ref({...blankForm});
const v$ = useVuelidate(validations, form);
const {form, resetForm, v$} = useVuelidateOnForm(validations, blankForm);
const isValid = computed(() => {
return !v$.value?.$invalid ?? true;
@ -379,10 +376,10 @@ const getTabClass = (validationGroup) => {
}
const clear = () => {
resetForm();
loading.value = false;
error.value = null;
station.value = {...blankStation};
form.value = {...blankForm};
};
const populateForm = (data) => {

View File

@ -13,6 +13,7 @@ import BaseEditModal from '~/components/Common/BaseEditModal';
import StorageLocationForm from './Form';
import useVuelidate from "@vuelidate/core";
import {computed} from "vue";
import {useResettableForm} from "~/components/Form/UseResettableForm";
export default {
name: 'AdminStorageLocationsEditModal',
@ -41,11 +42,7 @@ export default {
'storageQuota': ''
}
const form = {...blankForm};
const resetForm = () => {
form.value = {...blankForm};
};
const {form, resetForm} = useResettableForm(blankForm);
const validations = computed(() => {
let validationRules = {

View File

@ -0,0 +1,11 @@
import {ref} from "vue";
export function useResettableForm(blankForm) {
const form = ref({...blankForm});
const resetForm = () => {
form.value = {...blankForm};
}
return {form, resetForm};
}

View File

@ -0,0 +1,19 @@
import useVuelidate from "@vuelidate/core";
import {useResettableForm} from "~/components/Form/UseResettableForm";
export function useVuelidateOnForm(validations, blankForm) {
const {form, resetForm: parentResetForm} = useResettableForm(blankForm);
const v$ = useVuelidate(validations, form);
const resetForm = () => {
v$.value.$reset();
parentResetForm();
}
return {
form,
resetForm,
v$
};
}