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

Emit an event in Nova whenever the order of a flexible content group changes #484

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
60bab43
Add support for TinyMCE editors by recreating them after their panels…
MaxKorlaar Jun 14, 2022
052784c
Update field.js from master and recompile with tinyMCE support
MaxKorlaar Aug 18, 2022
9b7cc82
Current TinyMCE logic was not compatible with TinyMCE 6 (we're using …
MaxKorlaar Aug 18, 2022
f925851
Build field for production and with compatibility for TinyMCE editors
MaxKorlaar Oct 13, 2022
24ff184
Replace the logic to remove and re-add tinyMCE editors by a Nova even…
MaxKorlaar Oct 18, 2022
148f348
Update Layout.php
Jon78 Dec 15, 2022
8eefdbd
Add support for TinyMCE editors by recreating them after their panels…
MaxKorlaar Jun 14, 2022
6971420
Update field.js from master and recompile with tinyMCE support
MaxKorlaar Aug 18, 2022
543d8e3
Current TinyMCE logic was not compatible with TinyMCE 6 (we're using …
MaxKorlaar Aug 18, 2022
3ff8f64
Build field for production and with compatibility for TinyMCE editors
MaxKorlaar Oct 13, 2022
33e90f6
Replace the logic to remove and re-add tinyMCE editors by a Nova even…
MaxKorlaar Oct 18, 2022
5b8a57b
Merge remote-tracking branch 'origin/master'
Oct 19, 2023
07a578d
- changed rtrim to str_replace during "media_collection_suffix" removal
Dec 20, 2023
b0a0648
Add missing method
mabdullahsari Jan 15, 2024
a2a7455
Update README.md
voidgraphics Feb 14, 2024
d9fd1e3
Fix delete button
nbolender Dec 1, 2023
20217eb
compile
nbolender Dec 1, 2023
852c213
get Underlying Media Model function
LTKort Feb 26, 2024
bcfa8bf
L11 Support
LTKort Mar 12, 2024
87bb411
Revert danger-button & fix indent
LTKort Mar 12, 2024
214c8fb
build JS
LTKort Mar 12, 2024
70d5628
Group Key loop fix
LTKort Mar 12, 2024
80838d6
Add support for TinyMCE editors by recreating them after their panels…
MaxKorlaar Jun 14, 2022
a07e543
Current TinyMCE logic was not compatible with TinyMCE 6 (we're using …
MaxKorlaar Aug 18, 2022
86597c8
Replace the logic to remove and re-add tinyMCE editors by a Nova even…
MaxKorlaar Oct 18, 2022
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ An easy & complete Flexible Field for Laravel Nova, perfect for repeated and fle

![Laravel Nova Flexible Content in action](https://user-images.githubusercontent.com/9298484/164532562-6e4e4179-8a53-470c-97c8-237e9a2c2ebb.gif)

## We are looking for someone to help us maintain this package!

We'd love to accept someone who uses this package a lot to help us review and merge incoming PRs. Shoot us a message at [email protected] if you're willing to help!

## Quick start

Here's a very condensed guide to get you started asap.
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
"require": {
"php": "^7.3|^8.0",
"ext-json": "*",
"laravel/framework": "^8.0|^9.0|^10.0",
"laravel/framework": "^8.0|^9.0|^10.0|^11.0",
"laravel/nova": "^4.0",
"nova-kit/nova-packages-tool": "^1.3.1"
},
Expand Down
2 changes: 1 addition & 1 deletion dist/css/field.css

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dist/js/field.js

Large diffs are not rendered by default.

100 changes: 50 additions & 50 deletions resources/js/components/DeleteGroupModal.vue
Original file line number Diff line number Diff line change
@@ -1,61 +1,61 @@
<template>
<Modal :show="true">
<form
@submit.prevent="$emit('confirm')"
class="mx-auto bg-white dark:bg-gray-800 rounded-lg shadow-lg overflow-hidden"
>
<slot>
<ModalHeader v-text="__('Delete Group')" />
<ModalContent>
<p class="leading-normal" v-if="message">
{{ message }}
</p>
<p class="leading-normal" v-else>
{{ __('Are you sure you want to delete this group?') }}
</p>
</ModalContent>
</slot>
<form
@submit.prevent="$emit('confirm')"
class="mx-auto bg-white dark:bg-gray-800 rounded-lg shadow-lg overflow-hidden"
>
<slot>
<ModalHeader v-text="__('Delete Group')" />
<ModalContent>
<p class="leading-normal" v-if="message">
{{ message }}
</p>
<p class="leading-normal" v-else>
{{ __("Are you sure you want to delete this group?") }}
</p>
</ModalContent>
</slot>

<ModalFooter>
<div class="ml-auto">
<link-button
type="button"
data-testid="cancel-button"
dusk="cancel-delete-button"
@click.prevent="this.$emit('close')"
class="mr-3"
>
{{ no }}
</link-button>
<ModalFooter>
<div class="ml-auto">
<link-button
type="button"
data-testid="cancel-button"
dusk="cancel-delete-button"
@click.prevent="this.$emit('close')"
class="mr-3"
>
{{ no }}
</link-button>

<danger-button
ref="confirmButton"
dusk="confirm-delete-button"
:processing="working"
:disabled="working"
type="submit"
>
{{ yes }}
</danger-button>
</div>
</ModalFooter>
</form>
<danger-button
ref="confirmButton"
dusk="confirm-delete-button"
:processing="working"
:disabled="working"
type="submit"
>
{{ yes }}
</danger-button>
</div>
</ModalFooter>
</form>
</Modal>
</template>

<script>
export default {
props: ['message', 'yes', 'no'],
export default {
props: ["message", "yes", "no"],

emits: ['close', 'confirm'],
emits: ["close", "confirm"],

/**
* Mount the component.
*/
mounted() {
this.$nextTick(() => {
// this.$refs.confirmButton.button.focus()
})
},
}
/**
* Mount the component.
*/
mounted() {
this.$nextTick(() => {
// this.$refs.confirmButton.button.focus()
});
},
};
</script>
82 changes: 59 additions & 23 deletions resources/js/components/DetailField.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
<template>
<PanelItem :field="field">
<PanelItem :index="index" :field="field">
<template #value>
<div v-for="(group, index) in groups">
<div v-for="(group, index) in orderedGroups">
<detail-nova-flexible-content-group
:index="index"
:last="(index === groups.length - 1)"
:group="group"
:key="group.key"
:resource="resource"
:resourceName="resourceName"
:resourceId="resourceId"
:attribute="field.attribute"
Expand All @@ -21,44 +23,78 @@ import Group from '../group';
export default {

props: ['resource', 'resourceName', 'resourceId', 'field'],
data: () => ({
order: [],
groups: {},
}),

computed: {
groups() {
let group;
return this.field.value.reduce((groups, item) => {
if(!(group = this.getGroup(item))) return groups;
groups.push(group);
layouts() {
return this.field.layouts || false;
},
orderedGroups() {
this.value = this.field.value || [];

this.populateGroups();

return this.order.reduce((groups, key) => {
groups.push(this.groups[key]);
return groups;
}, []);
}
},
},

methods: {
/*
* Set the displayed layouts from the field's current value
*/
populateGroups() {
this.order.splice(0, this.order.length);
this.groups = {};

for (var i = 0; i < this.value.length; i++) {
this.addGroup(
this.getLayout(this.value[i].layout),
this.value[i].attributes,
this.value[i].key,
this.field.collapsed,
this.value[i].title_data
);
}
},

/**
* Retrieve layout definition from its name
*/
getLayout(name) {
if(!this.field.layouts) return;
return this.field.layouts.find(layout => layout.name == name);
if (!this.layouts) return;
return this.layouts.find((layout) => layout.name == name);
},

/**
* create group instance from raw field value
* Append the given layout to flexible content's list
*/
getGroup(item) {
addGroup(layout, attributes, key, collapsed, resolved_title) {
if (!layout) return;

let layout = this.getLayout(item.layout);
collapsed = collapsed || false;

if(!layout) return;
let fields =
attributes || JSON.parse(JSON.stringify(layout.fields)),
group = new Group(
layout.name,
layout.title,
fields,
this.field,
key,
collapsed,
layout,
resolved_title
);

return new Group(
layout.name,
layout.title,
item.attributes,
this.field,
item.key
);
this.groups[group.key] = group;
this.order.push(group.key);
},
}
}
},
};
</script>
7 changes: 7 additions & 0 deletions resources/js/components/FormGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,13 @@ export default {
this.collapsed = true;
}
},

watch: {
// https://github.com/whitecube/nova-flexible-content/issues/156#issuecomment-932327771
index(index) {
Nova.$emit('flexible-content-order-changed', index);
}
},
}
</script>

Expand Down
10 changes: 5 additions & 5 deletions src/Concerns/HasMediaLibrary.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ trait HasMediaLibrary
*
* @return \Spatie\MediaLibrary\HasMedia
*/
public function getMediaModel(): HasMedia
protected function getUnderlyingMediaModel(): HasMedia
{
$model = Flexible::getOriginModel() ?? $this->model;

Expand All @@ -47,7 +47,7 @@ public function getMediaModel(): HasMedia
public function addMedia($file): \Spatie\MediaLibrary\MediaCollections\FileAdder
{
return app(FileAdderFactory::class)
->create($this->getMediaModel(), $file, $this->getSuffix())
->create($this->getUnderlyingMediaModel(), $file, $this->getSuffix())
->preservingOriginal();
}

Expand Down Expand Up @@ -85,7 +85,7 @@ public function addMediaFromUrl($url, ...$allowedMimeTypes): \Spatie\MediaLibrar
}

return app(FileAdderFactory::class)
->create($this->getMediaModel(), $temporaryFile, $this->getSuffix())
->create($this->getUnderlyingMediaModel(), $temporaryFile, $this->getSuffix())
->usingName(pathinfo($filename, PATHINFO_FILENAME))
->usingFileName($filename);
}
Expand All @@ -100,7 +100,7 @@ public function addMediaFromUrl($url, ...$allowedMimeTypes): \Spatie\MediaLibrar
public function getMedia(string $collectionName = 'default', $filters = []): Collection
{
return app(MediaRepository::class)
->getCollection($this->getMediaModel(), $collectionName.$this->getSuffix(), $filters);
->getCollection($this->getUnderlyingMediaModel(), $collectionName.$this->getSuffix(), $filters);
}

/**
Expand All @@ -123,7 +123,7 @@ public function resolveForDisplay(array $attributes = [])
{
$this->fields->each(function ($field) use ($attributes) {
if (is_a($field, Media::class)) {
$field->resolveForDisplay($this->getMediaModel(), $field->attribute.$this->getSuffix());
$field->resolveForDisplay($this->getUnderlyingMediaModel(), $field->attribute.$this->getSuffix());
} else {
$field->resolveForDisplay($attributes);
}
Expand Down
2 changes: 1 addition & 1 deletion src/FileAdder/FileAdder.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public function toMediaCollection(string $collectionName = 'default', string $di
public function determineDiskName(string $diskName, string $collectionName): string
{
if ($this->media_collection_suffix) {
$collectionName = rtrim($collectionName, $this->media_collection_suffix);
$collectionName = str_replace($this->media_collection_suffix, '', $collectionName);
}

return parent::determineDiskName($diskName, $collectionName);
Expand Down
10 changes: 10 additions & 0 deletions src/Layouts/Layout.php
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,16 @@ public function __construct($title = null, $name = null, $fields = null, $key =
$this->setRawAttributes($this->cleanAttributes($attributes));
}

/**
* Determine if accessing missing attributes is disabled.
*
* @return bool
*/
public static function preventsAccessingMissingAttributes()
{
return false;
}

/**
* Set the parent model instance
*
Expand Down
Loading