Skip to content

Commit

Permalink
fixed: many relationship heading
Browse files Browse the repository at this point in the history
  • Loading branch information
Yasser Lahbibi committed Jan 14, 2019
1 parent e553f05 commit facc9b7
Show file tree
Hide file tree
Showing 7 changed files with 166 additions and 136 deletions.
2 changes: 1 addition & 1 deletion dist/js/field.js

Large diffs are not rendered by default.

205 changes: 113 additions & 92 deletions resources/js/components/FormField.vue
Original file line number Diff line number Diff line change
@@ -1,107 +1,128 @@
<template>
<div class="nested-form-container">
<!-- HEADING -->
<div class="p-4 border-b border-40 bg-30 flex justify-between items-center">
<h1 class="text-90 font-normal text-xl">{{field.name}}</h1>
<button v-if="displayAddButton"
type="button"
class="btn btn-default btn-primary btn-sm leading-none"
@click="add">{{ __('Add a new :resourceSingularName', { resourceSingularName: field.singularLabel }) }}</button>
</div>
<!-- HEADING -->

<template v-if="field.children.length > 0">
<!-- ACTUAL FIELDS -->
<nested-form-field v-for="(child, index) in field.children"
:key="`${field.attribute}-${index}`"
:index="index"
:field="field"
:child="child"
:errors="errors" />
<!-- ACTUAL FIELDS -->
</template>

<template v-else>
<p class="m-8">{{__('No :resourcePluralName', { resourcePluralName: field.pluralLabel })}}.</p>
</template>

<div class="nested-form-container">
<!-- HEADING -->
<div class="p-4 border-b border-40 bg-30 flex justify-between items-center">
<h1 class="text-90 font-normal text-xl">{{field.name}}</h1>
<button v-if="displayAddButton"
type="button"
class="btn btn-default btn-primary btn-sm leading-none"
@click="add">{{ __('Add a new :resourceSingularName', { resourceSingularName: field.singularLabel }) }}</button>
</div>
<!-- HEADING -->
<template v-if="field.children.length > 0">
<!-- ACTUAL FIELDS -->
<nested-form-field v-for="(child, index) in field.children"
:key="`${field.attribute}-${index}`"
:index="index"
:field="field"
:child="child"
:errors="errors" />
<!-- ACTUAL FIELDS -->
</template>

<template v-else>
<p class="m-8">{{__('No :resourcePluralName', { resourcePluralName: field.pluralLabel })}}.</p>
</template>
</div>
</template>

<script>
import { FormField, HandlesValidationErrors } from 'laravel-nova'
import NestedFormField from './NestedFormField'
import { FormField, HandlesValidationErrors } from "laravel-nova"
import NestedFormField from "./NestedFormField"
export default {
mixins: [FormField, HandlesValidationErrors],
mixins: [FormField, HandlesValidationErrors],
props: ["resourceName", "resourceId", "field"],
components: { NestedFormField },
computed: {
/**
* Whether or not to display the add button
*/
displayAddButton() {
return (
(this.field.has_many ||
this.field.morph_many ||
this.field.children.length === 0) &&
(this.field.max > 0
? this.field.max > this.field.children.length
: true)
)
props: ['resourceName', 'resourceId', 'field'],
}
},
components: { NestedFormField },
methods: {
/**
* This toggles the visibility of the
* content of the related resource
*/
toggleVisibility() {
this.field.opened = !this.field.opened
},
/**
* This adds a resource to the children
*/
add() {
this.field.children.push(this.replaceIndexesInSchema(this.field))
computed: {
/**
* Whether or not to display the add button
*/
displayAddButton() {
return (this.field.has_many || this.field.children.length === 0) && (this.field.max > 0 ? this.field.max > this.field.children.length : true)
}
},
methods: {
/**
* This toggles the visibility of the
* content of the related resource
*/
toggleVisibility() {
this.field.opened = !this.field.opened
},
/**
* This adds a resource to the children
*/
add() {
this.field.children.push(this.replaceIndexesInSchema(this.field))
},
/**
* Overrides the fill method.
*/
fill(formData) {
this.field.children.forEach(child => child.fill(formData))
if (this.field.singularLabel === 'Post') {
const obj = {}
formData.forEach((v, k) => {
obj[k] = v
})
console.log(obj)
}
},
/**
* This replaces the "{{index}}" values of the schema to
* their actual index.
*
*/
replaceIndexesInSchema(field) {
const schema = JSON.parse(JSON.stringify(field.schema))
schema.fields.forEach(field => {
if (field.schema) {
field.schema.opened = false
field.schema = this.replaceIndexesInSchema(field)
}
if (field.attribute) {
field.attribute = field.attribute.replace(this.field.INDEX, this.field.children.length)
}
})
schema.heading = schema.heading.replace(this.field.INDEX, this.field.children.length + 1)
schema.attribute = schema.attribute.replace(this.field.INDEX, this.field.children.length)
return schema
},
/**
* Overrides the fill method.
*/
fill(formData) {
this.field.children.forEach(child => child.fill(formData))
},
/**
* This replaces the "{{index}}" values of the schema to
* their actual index.
*
*/
replaceIndexesInSchema(field) {
const schema = JSON.parse(JSON.stringify(field.schema))
schema.fields.forEach(field => {
if (field.schema) {
field.schema.opened = false
field.schema = this.replaceIndexesInSchema(field)
}
if (field.attribute) {
field.attribute = field.attribute.replace(
this.field.INDEX,
this.field.children.length
)
}
})
schema.heading = schema.heading.replace(
this.field.INDEX,
this.field.children.length + 1
)
schema.attribute = schema.attribute.replace(
this.field.INDEX,
this.field.children.length
)
return schema
}
}
}
</script>
79 changes: 39 additions & 40 deletions resources/js/components/Modals/Delete.vue
Original file line number Diff line number Diff line change
@@ -1,50 +1,49 @@
<template>
<modal @modal-close="handleClose">
<form @submit.prevent="handleConfirm"
slot-scope="props"
class="bg-white rounded-lg shadow-lg overflow-hidden"
style="width: 460px">
<slot>
<div class="p-8">
<heading :level="2"
class="mb-6">{{ __('Remove a :resourceSingularName', { resourceSingularName}) }}</heading>
<p class="text-80 leading-normal">{{__('Are you sure you want to remove this :resourceSingularName?', { resourceSingularName })}}</p>
</div>
</slot>
<div class="bg-30 px-6 py-3 flex">
<div class="ml-auto">
<button type="button"
@click.prevent="handleClose"
class="btn text-80 font-normal h-9 px-3 mr-3 btn-link">{{__('Cancel')}}</button>
<button type="submit"
ref="confirmButton"
class="btn btn-default btn-danger">{{__('Remove')}}</button>
</div>
</div>
</form>
</modal>
<modal @modal-close="handleClose">
<form @submit.prevent="handleConfirm"
class="bg-white rounded-lg shadow-lg overflow-hidden"
style="width: 460px">
<slot>
<div class="p-8">
<heading :level="2"
class="mb-6">{{ __('Remove a :resourceSingularName', { resourceSingularName}) }}</heading>
<p class="text-80 leading-normal">{{__('Are you sure you want to remove this :resourceSingularName?', { resourceSingularName })}}</p>
</div>
</slot>
<div class="bg-30 px-6 py-3 flex">
<div class="ml-auto">
<button type="button"
@click.prevent="handleClose"
class="btn text-80 font-normal h-9 px-3 mr-3 btn-link">{{__('Cancel')}}</button>
<button type="submit"
ref="confirmButton"
class="btn btn-default btn-danger">{{__('Remove')}}</button>
</div>
</div>
</form>
</modal>
</template>

<script>
export default {
props: {
resourceSingularName: {
type: String,
required: true
}
props: {
resourceSingularName: {
type: String,
required: true
}
},
methods: {
handleClose() {
this.$emit('close')
},
methods: {
handleClose() {
this.$emit('close')
},
handleConfirm() {
this.$emit('submit')
this.$emit('close')
},
},
mounted() {
this.$refs.confirmButton.focus()
handleConfirm() {
this.$emit('submit')
this.$emit('close')
}
},
mounted() {
this.$refs.confirmButton.focus()
}
}
</script>
10 changes: 10 additions & 0 deletions src/NestedForm.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,4 +254,14 @@ protected function setRequest(Request $request = null)

return $this;
}

/**
* Checks whether the current relationship has many children.
*
* @return bool
*/
protected function isManyRelationship()
{
return isset($this->meta['has_many']) || isset($this->meta['morph_many']);
}
}
2 changes: 1 addition & 1 deletion src/Traits/FillsSubAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ protected function attribute(string $attribute, int $index = null)
}
}

return $attribute . ((isset($this->meta['has_many']) || isset($this->meta['morph_many'])) ? '[' . $index . ']' : '');
return $attribute . ($this->isManyRelationship() ? '[' . $index . ']' : '');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Traits/HasHeading.php
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public function separator(string $separator)
*/
protected function defaultHeading()
{
return (isset($this->meta['has_many']) ? self::INDEX . $this->separator . ' ' : ' ') . Str::singular($this->name);
return ($this->isManyRelationship() ? self::INDEX . $this->separator . ' ' : ' ') . Str::singular($this->name);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion webpack.mix.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ mix.setPublicPath('dist')
'@': path.resolve(__dirname, './vendor/laravel/nova/resources/js/'),
},
},
})
})

0 comments on commit facc9b7

Please sign in to comment.