Skip to content

Commit

Permalink
Add File field support
Browse files Browse the repository at this point in the history
  • Loading branch information
Tarpsvo committed Jun 13, 2022
1 parent f8e2007 commit 4fa98f7
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 21 deletions.
32 changes: 28 additions & 4 deletions resources/js/components/PageManagerField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PageManagerPanelsContent
v-if="seoPanelsWithFields"
:view="field.view"
:type="'seo'"
:resourceId="resourceId"
:resourceName="resourceName"
@field-changed="onUpdateFormStatus"
Expand All @@ -13,6 +14,7 @@

<PageManagerPanelsContent
:view="field.view"
:type="'data'"
:resourceId="resourceId"
:resourceName="resourceName"
@field-changed="onUpdateFormStatus"
Expand Down Expand Up @@ -67,20 +69,42 @@ export default {
fill(formData) {
try {
const data = this.getDataFromFill(this.panelsWithFields);
formData.set('data', JSON.stringify(data));
this.addFieldValuesToFormData(this.panelsWithFields, 'data', formData);
} catch (e) {
console.error(e);
}
try {
const seoData = this.getDataFromFill(this.seoPanelsWithFields);
formData.set('seo', JSON.stringify(seoData));
this.addFieldValuesToFormData(this.seoPanelsWithFields, 'seo', formData);
} catch (e) {
console.error(e);
}
},
addFieldValuesToFormData(fields, keyPrefix, formData) {
const localizedData = this.getDataFromFill(fields);
const localeKeys = Object.keys(localizedData);
for (const locale of localeKeys) {
const data = localizedData[locale];
const dataKeys = Object.keys(data);
for (const key of dataKeys) {
const val = data[key];
const isFile = val instanceof File || val instanceof Blob;
if (typeof val === 'object' && !isFile) {
const objKeys = Object.keys(val);
for (const objKey of objKeys) {
formData.set(`${keyPrefix}[${locale}][${key}][${objKey}]`, val[objKey]);
}
} else {
formData.set(`${keyPrefix}[${locale}][${key}]`, val);
}
}
}
},
getDataFromFill(panelsWithFields) {
const localeKeys = Object.keys(this.field.locales);
Expand Down
4 changes: 2 additions & 2 deletions resources/js/components/PageManagerFieldHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
v-for="locale of Object.keys(locales)"
:key="locale"
@click.prevent="$emit('changeLocale', locale)"
class="npm-cursor-pointer npm-font-bold npm-px-2 npm-h-full npm-flex npm-items-center npm-box-border npm-border-b-2"
class="npm-cursor-pointer npm-font-bold npm-px-2 npm-h-full npm-flex npm-items-center npm-box-border npm-border-b-2 npm-select-none"
:class="{
'text-primary-500 border-primary-500': activeLocale === locale,
'npm-text-80 npm-border-transparent': activeLocale !== locale,
Expand All @@ -30,7 +30,7 @@ export default {
#page-manager-field-header {
position: absolute;
right: 0;
top: 20px;
top: 14px;
display: flex;
}
</style>
3 changes: 2 additions & 1 deletion resources/js/components/PageManagerPanelsContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
:panel="panel"
:name="panel.name"
:resource-id="resourceId"
:resource-name="resourceName"
:resource-name="`page-manager/${type}/${resourceName}/${key}`"
:form-unique-id="formUniqueId"
mode="form"
:validation-errors="validationErrors"
Expand All @@ -34,6 +34,7 @@ export default {
'locales',
'panelsWithFields',
'view',
'type',
'formUniqueId',
'validationErrors',
],
Expand Down
6 changes: 5 additions & 1 deletion routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,8 @@
use Illuminate\Support\Facades\Route;
use Outl1ne\PageManager\Http\Controllers\PageManagerController;

Route::get('/{type}/{slug}/fields', [PageManagerController::class, 'getFields']);
Route::prefix('nova-vendor/page-manager')->group(function () {
Route::get('/{type}/{slug}/fields', [PageManagerController::class, 'getFields']);
});

Route::delete('/nova-api/page-manager/{panelType}/{resourceType}/{locale}/{resourceId}/field/{fieldAttribute}', [PageManagerController::class, 'deleteFile']);
24 changes: 24 additions & 0 deletions src/Http/Controllers/PageManagerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,28 @@ public function getFields(Request $request, $type, $resourceId)
'seoPanelsWithFields' => $seoPanelsData,
];
}

public function deleteFile(Request $request)
{
$panelType = $request->route('panelType');
$resourceType = $request->route('resourceType');
$locale = $request->route('locale');
$resourceId = $request->route('resourceId');
$fieldAttribute = $request->route('fieldAttribute');

if (!in_array($panelType, ['seo', 'data'])) return response()->json(['error' => 'Invalid panel type.'], 400);
if (!in_array($resourceType, ['pages', 'regions'])) return response()->json(['error' => 'Invalid resource type.'], 400);

$modelClass = $resourceType === 'pages'
? NPM::getPageModel()
: NPM::getRegionModel();

$model = $modelClass::findOrFail($resourceId);
$data = $model->{$panelType};
$data[$locale][$fieldAttribute] = null;
$model->{$panelType} = $data;
$model->save();

return response('', 204);
}
}
1 change: 0 additions & 1 deletion src/NPMServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ protected function registerRoutes()
if ($this->app->routesAreCached()) return;

Route::middleware(['nova', \Outl1ne\PageManager\Http\Middleware\AuthorizeMiddleware::class])
->prefix('nova-vendor/page-manager')
->group(__DIR__ . '/../routes/api.php');
}
}
40 changes: 28 additions & 12 deletions src/Nova/Fields/PageManagerField.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@

use Outl1ne\PageManager\NPM;
use Laravel\Nova\Fields\Field;
use Illuminate\Http\UploadedFile;
use Outl1ne\PageManager\Template;
use Laravel\Nova\Fields\FieldCollection;
use Laravel\Nova\Http\Requests\NovaRequest;
use Outl1ne\PageManager\Template;
use Symfony\Component\HttpFoundation\HeaderBag;
use Symfony\Component\HttpFoundation\ParameterBag;

class PageManagerField extends Field
{
Expand Down Expand Up @@ -41,32 +41,48 @@ public function withSeoFields($seoFields)
public function fill(NovaRequest $request, $model)
{
$fields = new FieldCollection($this->template->fields($request));
$model->data = $this->fillFieldsAndGetData($request, 'data', $fields);

$model->data = $this->fillFieldsAndGetData($request, 'data', $fields, $model->data);

if ($this->meta['type'] === Template::TYPE_PAGE) {
$seoFields = new FieldCollection($this->seoFields);
$model->seo = $this->fillFieldsAndGetData($request, 'seo', $seoFields);

$model->seo = $this->fillFieldsAndGetData($request, 'seo', $seoFields, $model->seo);
}
}

protected function fillFieldsAndGetData($request, $attributeKey, $fields)
protected function fillFieldsAndGetData($request, $attributeKey, $fields, $existingData)
{
$locales = NPM::getLocales();

$data = $request->get($attributeKey, '');
$data = json_decode($data, true);
$all = $request->all();
$data = $all[$attributeKey] ?? [];

$newData = [];
foreach ($locales as $key => $localeName) {
$fakeRequest = new NovaRequest();
$fakeRequest->headers = new HeaderBag(['Content-Type' => 'application/json']);
$dataAttributes = [];
$fileAttributes = [];

foreach ($data[$key] as $k => $v) {
if ($v instanceof UploadedFile) {
$fileAttributes[$k] = $v;
} else {
$dataAttributes[$k] = $v;
}
}

$fakeRequest = new NovaRequest([], $dataAttributes, [], [], $fileAttributes);
$fakeRequest->headers = new HeaderBag(['Content-Type' => 'multipart/form-data']);
$fakeRequest->setMethod(NovaRequest::METHOD_POST);
$fakeRequest->setJson(new ParameterBag($data[$key]));

$fakeModel = (object) [];
$fields->resolve((object) $fakeRequest->all());
$fields->resolve((object) $data[$key]);
$fields->map->fill($fakeRequest, $fakeModel);
$newData[$key] = (array) $fakeModel;

$newData[$key] = array_merge(
$existingData[$key] ?? [],
(array) $fakeModel,
);
}

return $newData;
Expand Down

0 comments on commit 4fa98f7

Please sign in to comment.