375 lines
9.5 KiB
Vue
Executable File
375 lines
9.5 KiB
Vue
Executable File
<template>
|
|
<loading-view :loading="loading">
|
|
<custom-create-header class="mb-3" :resource-name="resourceName" />
|
|
|
|
<form
|
|
v-if="panels"
|
|
@submit="submitViaCreateResource"
|
|
@change="onUpdateFormStatus"
|
|
autocomplete="off"
|
|
ref="form"
|
|
>
|
|
<form-panel
|
|
class="mb-8"
|
|
v-for="panel in panelsWithFields"
|
|
@field-changed="onUpdateFormStatus"
|
|
@file-upload-started="handleFileUploadStarted"
|
|
@file-upload-finished="handleFileUploadFinished"
|
|
:shown-via-new-relation-modal="shownViaNewRelationModal"
|
|
:panel="panel"
|
|
:name="panel.name"
|
|
:key="panel.name"
|
|
:resource-name="resourceName"
|
|
:fields="panel.fields"
|
|
mode="form"
|
|
:validation-errors="validationErrors"
|
|
:via-resource="viaResource"
|
|
:via-resource-id="viaResourceId"
|
|
:via-relationship="viaRelationship"
|
|
/>
|
|
|
|
<!-- Create Button -->
|
|
<div class="flex items-center">
|
|
<cancel-button @click="$emit('cancelled-create')" />
|
|
|
|
<progress-button
|
|
v-if="shouldShowAddAnotherButton"
|
|
dusk="create-and-add-another-button"
|
|
class="mr-3"
|
|
@click.native="submitViaCreateResourceAndAddAnother"
|
|
:disabled="isWorking"
|
|
:processing="wasSubmittedViaCreateResourceAndAddAnother"
|
|
>
|
|
{{ __('Create & Add Another') }}
|
|
</progress-button>
|
|
|
|
<progress-button
|
|
dusk="create-button"
|
|
type="submit"
|
|
:disabled="isWorking"
|
|
:processing="wasSubmittedViaCreateResource"
|
|
>
|
|
{{ createButtonLabel }}
|
|
</progress-button>
|
|
</div>
|
|
</form>
|
|
</loading-view>
|
|
</template>
|
|
|
|
<script>
|
|
import {
|
|
mapProps,
|
|
Errors,
|
|
Minimum,
|
|
InteractsWithResourceInformation,
|
|
} from 'laravel-nova'
|
|
import HandlesUploads from '@/mixins/HandlesUploads'
|
|
|
|
export default {
|
|
mixins: [InteractsWithResourceInformation, HandlesUploads],
|
|
|
|
metaInfo() {
|
|
if (this.shouldOverrideMeta && this.resourceInformation) {
|
|
return {
|
|
title: this.__('Create :resource', {
|
|
resource: this.resourceInformation.singularLabel,
|
|
}),
|
|
}
|
|
}
|
|
},
|
|
|
|
props: {
|
|
mode: {
|
|
type: String,
|
|
default: 'form',
|
|
validator: val => ['modal', 'form'].includes(val),
|
|
},
|
|
|
|
updateFormStatus: {
|
|
type: Function,
|
|
default: () => {},
|
|
},
|
|
|
|
...mapProps([
|
|
'resourceName',
|
|
'viaResource',
|
|
'viaResourceId',
|
|
'viaRelationship',
|
|
'shouldOverrideMeta',
|
|
]),
|
|
},
|
|
|
|
data: () => ({
|
|
relationResponse: null,
|
|
loading: true,
|
|
submittedViaCreateResourceAndAddAnother: false,
|
|
submittedViaCreateResource: false,
|
|
fields: [],
|
|
panels: [],
|
|
validationErrors: new Errors(),
|
|
}),
|
|
|
|
async created() {
|
|
if (Nova.missingResource(this.resourceName))
|
|
return this.$router.push({ name: '404' })
|
|
|
|
// If this create is via a relation index, then let's grab the field
|
|
// and use the label for that as the one we use for the title and buttons
|
|
if (this.isRelation) {
|
|
const { data } = await Nova.request().get(
|
|
'/nova-api/' + this.viaResource + '/field/' + this.viaRelationship,
|
|
{
|
|
params: {
|
|
resourceName: this.resourceName,
|
|
viaResource: this.viaResource,
|
|
viaResourceId: this.viaResourceId,
|
|
viaRelationship: this.viaRelationship,
|
|
},
|
|
}
|
|
)
|
|
this.relationResponse = data
|
|
|
|
if (this.isHasOneRelationship && this.alreadyFilled) {
|
|
Nova.error(this.__('The HasOne relationship has already been filled.'))
|
|
|
|
this.$router.push({
|
|
name: 'detail',
|
|
params: {
|
|
resourceId: this.viaResourceId,
|
|
resourceName: this.viaResource,
|
|
},
|
|
})
|
|
}
|
|
|
|
if (this.isHasOneThroughRelationship && this.alreadyFilled) {
|
|
Nova.error(
|
|
this.__('The HasOneThrough relationship has already been filled.')
|
|
)
|
|
|
|
this.$router.push({
|
|
name: 'detail',
|
|
params: {
|
|
resourceId: this.viaResourceId,
|
|
resourceName: this.viaResource,
|
|
},
|
|
})
|
|
}
|
|
}
|
|
|
|
this.getFields()
|
|
},
|
|
|
|
methods: {
|
|
/**
|
|
* Get the available fields for the resource.
|
|
*/
|
|
async getFields() {
|
|
this.panels = []
|
|
this.fields = []
|
|
|
|
const {
|
|
data: { panels, fields },
|
|
} = await Nova.request().get(
|
|
`/nova-api/${this.resourceName}/creation-fields`,
|
|
{
|
|
params: {
|
|
editing: true,
|
|
editMode: 'create',
|
|
viaResource: this.viaResource,
|
|
viaResourceId: this.viaResourceId,
|
|
viaRelationship: this.viaRelationship,
|
|
},
|
|
}
|
|
)
|
|
|
|
this.panels = panels
|
|
this.fields = fields
|
|
this.loading = false
|
|
},
|
|
|
|
async submitViaCreateResource(e) {
|
|
e.preventDefault()
|
|
this.submittedViaCreateResource = true
|
|
this.submittedViaCreateResourceAndAddAnother = false
|
|
await this.createResource()
|
|
},
|
|
|
|
async submitViaCreateResourceAndAddAnother() {
|
|
this.submittedViaCreateResourceAndAddAnother = true
|
|
this.submittedViaCreateResource = false
|
|
await this.createResource()
|
|
},
|
|
|
|
/**
|
|
* Create a new resource instance using the provided data.
|
|
*/
|
|
async createResource() {
|
|
this.isWorking = true
|
|
|
|
if (this.$refs.form.reportValidity()) {
|
|
try {
|
|
const {
|
|
data: { redirect, id },
|
|
} = await this.createRequest()
|
|
|
|
this.canLeave = true
|
|
|
|
Nova.success(
|
|
this.__('The :resource was created!', {
|
|
resource: this.resourceInformation.singularLabel.toLowerCase(),
|
|
})
|
|
)
|
|
|
|
if (this.submittedViaCreateResource) {
|
|
this.$emit('resource-created', { id, redirect })
|
|
} else {
|
|
// Reset the form by refetching the fields
|
|
this.getFields()
|
|
this.validationErrors = new Errors()
|
|
this.submittedViaCreateAndAddAnother = false
|
|
this.submittedViaCreateResource = false
|
|
this.isWorking = false
|
|
|
|
return
|
|
}
|
|
} catch (error) {
|
|
window.scrollTo(0, 0)
|
|
|
|
this.submittedViaCreateAndAddAnother = false
|
|
this.submittedViaCreateResource = true
|
|
this.isWorking = false
|
|
|
|
if (this.resourceInformation.preventFormAbandonment) {
|
|
this.canLeave = false
|
|
}
|
|
|
|
if (error.response.status == 422) {
|
|
this.validationErrors = new Errors(error.response.data.errors)
|
|
Nova.error(this.__('There was a problem submitting the form.'))
|
|
} else {
|
|
Nova.error(
|
|
this.__('There was a problem submitting the form.') +
|
|
' "' +
|
|
error.response.statusText +
|
|
'"'
|
|
)
|
|
}
|
|
}
|
|
}
|
|
|
|
this.submittedViaCreateAndAddAnother = false
|
|
this.submittedViaCreateResource = true
|
|
this.isWorking = false
|
|
},
|
|
|
|
/**
|
|
* Send a create request for this resource
|
|
*/
|
|
createRequest() {
|
|
return Nova.request().post(
|
|
`/nova-api/${this.resourceName}`,
|
|
this.createResourceFormData(),
|
|
{
|
|
params: {
|
|
editing: true,
|
|
editMode: 'create',
|
|
},
|
|
}
|
|
)
|
|
},
|
|
|
|
/**
|
|
* Create the form data for creating the resource.
|
|
*/
|
|
createResourceFormData() {
|
|
return _.tap(new FormData(), formData => {
|
|
_.each(this.fields, field => {
|
|
field.fill(formData)
|
|
})
|
|
|
|
formData.append('viaResource', this.viaResource)
|
|
formData.append('viaResourceId', this.viaResourceId)
|
|
formData.append('viaRelationship', this.viaRelationship)
|
|
})
|
|
},
|
|
|
|
/**
|
|
* Prevent accidental abandonment only if form was changed.
|
|
*/
|
|
onUpdateFormStatus() {
|
|
if (this.resourceInformation.preventFormAbandonment) {
|
|
this.updateFormStatus()
|
|
}
|
|
},
|
|
},
|
|
|
|
computed: {
|
|
wasSubmittedViaCreateResource() {
|
|
return this.isWorking && this.submittedViaCreateResource
|
|
},
|
|
|
|
wasSubmittedViaCreateResourceAndAddAnother() {
|
|
return this.isWorking && this.submittedViaCreateResourceAndAddAnother
|
|
},
|
|
|
|
panelsWithFields() {
|
|
return _.map(this.panels, panel => {
|
|
return {
|
|
...panel,
|
|
fields: _.filter(this.fields, field => field.panel == panel.name),
|
|
}
|
|
})
|
|
},
|
|
|
|
singularName() {
|
|
if (this.relationResponse) {
|
|
return this.relationResponse.singularLabel
|
|
}
|
|
|
|
return this.resourceInformation.singularLabel
|
|
},
|
|
|
|
createButtonLabel() {
|
|
return this.resourceInformation.createButtonLabel
|
|
},
|
|
|
|
isRelation() {
|
|
return Boolean(this.viaResourceId && this.viaRelationship)
|
|
},
|
|
|
|
shownViaNewRelationModal() {
|
|
return this.mode == 'modal'
|
|
},
|
|
|
|
inFormMode() {
|
|
return this.mode == 'form'
|
|
},
|
|
|
|
canAddMoreResources() {
|
|
return this.authorizedToCreate
|
|
},
|
|
|
|
alreadyFilled() {
|
|
return this.relationResponse && this.relationResponse.alreadyFilled
|
|
},
|
|
|
|
isHasOneRelationship() {
|
|
return this.relationResponse && this.relationResponse.hasOneRelationship
|
|
},
|
|
|
|
isHasOneThroughRelationship() {
|
|
return (
|
|
this.relationResponse && this.relationResponse.hasOneThroughRelationship
|
|
)
|
|
},
|
|
|
|
shouldShowAddAnotherButton() {
|
|
return (
|
|
Boolean(this.inFormMode && !this.alreadyFilled) &&
|
|
!Boolean(this.isHasOneRelationship || this.isHasOneThroughRelationship)
|
|
)
|
|
},
|
|
},
|
|
}
|
|
</script>
|