Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add minimum fields option #266

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dist/js/field.js

Large diffs are not rendered by default.

15 changes: 13 additions & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ Flexible::make('Content')->limit(2);

You can specify any integer, or no integer at all; in that case it will default to 1.

#### Minimum number of layouts

You can set the minimum of how many layouts can appear using the following:

```php
Flexible::make('Content')->minimum(2);
```

You can specify any integer. If the number of layouts is at or below this integer,
the delete icon will not be visible.

#### Layout removal confirmation

You can choose to display a confirmation prompt before a layout is deleted by doing:
Expand Down Expand Up @@ -183,9 +194,9 @@ class MyFlexibleCast extends FlexibleCast
protected function getLayoutMappings()
{
$mappings = [];

// Conditionally add mappings however you want

return $mappings;
}
}
Expand Down
37 changes: 24 additions & 13 deletions resources/js/components/FormField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
:errors="errors"
full-width-content>
<template slot="field">

<div
v-if="order.length > 0">
<form-nova-flexible-content-group
Expand All @@ -20,6 +19,8 @@
:resource-id="resourceId"
:resource="resource"
:errors="errors"
:is-above-minimum="isAboveMinimum"
:is-orderable="isOrderable"
@move-up="moveUp(group.key)"
@move-down="moveDown(group.key)"
@remove="remove(group.key)"
Expand All @@ -30,7 +31,7 @@
:layouts="layouts"
:is="field.menu.component"
:field="field"
:limit-counter="limitCounter"
:is-below-limit="isBelowLimit"
:errors="errors"
:resource-name="resourceName"
:resource-id="resourceId"
Expand Down Expand Up @@ -64,15 +65,26 @@ export default {
groups.push(this.groups[key]);
return groups;
}, []);
}
},
isBelowLimit() {
return this.groupCounter < (this.field.limit || Infinity);
},
isAboveMinimum() {
return this.groupCounter > (this.field.minimum || 0);
},
groupCounter() {
return Object.keys(this.groups).length;
},
isOrderable() {
return this.groupCounter > 1;
},
},

data() {
return {
order: [],
groups: {},
files: {},
limitCounter: this.field.limit
};
},

Expand Down Expand Up @@ -181,12 +193,11 @@ export default {
let fields = attributes || JSON.parse(JSON.stringify(layout.fields)),
group = new Group(layout.name, layout.title, fields, this.field, key, collapsed);

this.groups[group.key] = group;
this.groups = {
...this.groups,
[group.key]: group,
};
this.order.push(group.key);

if (this.limitCounter > 0) {
this.limitCounter--;
}
},

/**
Expand Down Expand Up @@ -220,11 +231,11 @@ export default {
if(index < 0) return;

this.order.splice(index, 1);
delete this.groups[key];

if (this.limitCounter >= 0) {
this.limitCounter++;
}
const groups = { ...this.groups };
delete groups[key];

this.groups = groups;
}
}
}
Expand Down
39 changes: 22 additions & 17 deletions resources/js/components/FormGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,29 @@
@click.prevent="collapse">
<icon class="align-top" type="minus-square" width="16" height="16" view-box="0 0 24 24" />
</button>

<div v-if="!readonly">
<template v-if="isOrderable">
<button
dusk="move-up-group"
type="button"
class="group-control btn border-t border-r border-40 w-8 h-8 block"
:title="__('Move up')"
@click.prevent="moveUp">
<icon type="arrow-up" view-box="0 0 8 4.8" width="10" height="10" />
</button>
<button
dusk="move-down-group"
type="button"
class="group-control btn border-t border-r border-40 w-8 h-8 block"
:title="__('Move down')"
@click.prevent="moveDown">
<icon type="arrow-down" view-box="0 0 8 4.8" width="10" height="10" />
</button>
</template>

<button
dusk="move-up-group"
type="button"
class="group-control btn border-t border-r border-40 w-8 h-8 block"
:title="__('Move up')"
@click.prevent="moveUp">
<icon type="arrow-up" view-box="0 0 8 4.8" width="10" height="10" />
</button>
<button
dusk="move-down-group"
type="button"
class="group-control btn border-t border-r border-40 w-8 h-8 block"
:title="__('Move down')"
@click.prevent="moveDown">
<icon type="arrow-down" view-box="0 0 8 4.8" width="10" height="10" />
</button>
<button
v-if="isAboveMinimum"
dusk="delete-group"
type="button"
class="group-control btn border-t border-r border-40 w-8 h-8 block"
Expand Down Expand Up @@ -91,7 +96,7 @@ import { BehavesAsPanel } from 'laravel-nova';
export default {
mixins: [BehavesAsPanel],

props: ['errors', 'group', 'index', 'field'],
props: ['errors', 'group', 'index', 'field', 'isAboveMinimum', 'isOrderable'],

data() {
return {
Expand Down
4 changes: 2 additions & 2 deletions resources/js/components/OriginalDropMenu.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
tabindex="0"
class="btn btn-default btn-primary inline-flex items-center relative"
@click="toggleLayoutsDropdownOrAddDefault"
v-if="this.limitCounter != 0"
v-if="isBelowLimit"
>
<span>{{ field.button }}</span>
</button>
Expand All @@ -34,7 +34,7 @@
<script>

export default {
props: ['layouts', 'field', 'resourceName', 'resourceId', 'resource', 'errors', 'limitCounter'],
props: ['layouts', 'field', 'resourceName', 'resourceId', 'resource', 'errors', 'isBelowLimit'],

data() {
return {
Expand Down
4 changes: 2 additions & 2 deletions resources/js/components/SearchMenu.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<div class="w-3/5" v-if="layouts">

<div v-if="this.limitCounter != 0">
<div v-if="isBelowLimit">
<div v-if="layouts.length === 1">
<button
dusk="toggle-layouts-dropdown-or-add-default"
Expand Down Expand Up @@ -38,7 +38,7 @@
export default {
components: {Multiselect},

props: ['layouts', 'field', 'resourceName', 'resourceId', 'resource', 'errors', 'limitCounter'],
props: ['layouts', 'field', 'resourceName', 'resourceId', 'resource', 'errors', 'isBelowLimit'],

data() {
return {
Expand Down
15 changes: 13 additions & 2 deletions src/Flexible.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ public function fullWidth()
}

/**
* Prevent the 'Add Layout' button from appearing more than once
* Prevent the 'Add Layout' button from appearing more than once
*
* @return $this
*/
Expand All @@ -121,6 +121,17 @@ public function limit($limit = 1)
return $this->withMeta(['limit' => $limit]);
}

/**
* Prevent the 'Delete' button from appearing when reaching a minimum
* number of resources.
*
* @return $this
*/
public function minimum($minimum = 0)
{
return $this->withMeta(['minimum' => $minimum]);
}

/**
* Confirm remove
*
Expand Down Expand Up @@ -182,7 +193,7 @@ public function addLayout(...$arguments)
}

$layout = $arguments[0];

if(is_string($layout) && is_a($layout, LayoutInterface::class, true)) {
$layout = new $layout();
}
Expand Down