Skip to content

Commit

Permalink
Merge branch 'Visifo-feature/81-depend-on-several-fields'
Browse files Browse the repository at this point in the history
  • Loading branch information
Florian Strauß committed May 12, 2021
2 parents 4190df3 + ed984ba commit d9750d0
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 46 deletions.
15 changes: 15 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

[*.{yml,yaml}]
indent_size = 2
59 changes: 56 additions & 3 deletions resources/js/components/FormField.vue
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,30 @@ export default {
}).authorizedToCreate;
},
},
beforeDestroy() {
Nova.$off("nova-belongsto-depend-" + this.field.dependsOn);
if (this.field.dependsOn) {
let $busEvents = [];
for (let i = 0; i < this.field.dependsOn.length; i++) {
$busEvents.push("nova-belongsto-depend-" + this.field.dependsOn[i]);
}
Nova.$off($busEvents);
}
},
created() {
if (this.field.dependsOn) {
Nova.$on("nova-belongsto-depend-" + this.field.dependsOn, async (dependsOnValue) => {
let $busEvents = [];
for (let i = 0; i < this.field.dependsOn.length; i++) {
$busEvents.push("nova-belongsto-depend-" + this.field.dependsOn[i]);
}
Nova.$on($busEvents, async (dependsOnValue) => {
this.value = "";
Nova.$emit("nova-belongsto-depend-" + this.field.attribute.toLowerCase(), {
Expand All @@ -120,12 +138,14 @@ export default {
});
if (dependsOnValue && dependsOnValue.value) {
this.updateDependsMap(dependsOnValue);
this.options = (
await Nova.request().post("/nova-vendor/nova-belongsto-depend", {
resourceClass: this.field.resourceParentClass,
modelClass: dependsOnValue.field.modelClass,
attribute: this.field.attribute,
dependKey: dependsOnValue.value[dependsOnValue.field.modelPrimaryKey],
dependsMap: this.field.dependsMap
})
).data;
Expand All @@ -136,12 +156,45 @@ export default {
field: this.field,
});
}
} else {
this.cleanupDependsMap(dependsOnValue);
}
});
}
},
methods: {
updateDependsMap(dependsOnValue) {
let exists = false;
let index = -1;
for (let i = 0; i < this.field.dependsMap.length; i++) {
if (this.field.dependsMap[i].key === dependsOnValue.field.modelClass) {
exists = true;
index = i;
break;
}
}
if (exists) {
this.field.dependsMap[index].value = dependsOnValue.value[dependsOnValue.field.modelPrimaryKey];
} else {
this.field.dependsMap.push({
key: dependsOnValue.field.modelClass,
value: dependsOnValue.value[dependsOnValue.field.modelPrimaryKey]
});
}
},
cleanupDependsMap(dependsOnValue) {
for (let i = 0; i < this.field.dependsMap.length; i++) {
if (this.field.dependsMap[i].key === dependsOnValue.field.modelClass) {
this.field.dependsMap.splice(i, 1);
}
}
},
customLabel(item) {
return item[this.field.titleKey];
},
Expand Down
102 changes: 79 additions & 23 deletions src/Http/Controllers/FieldController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use \Illuminate\Http\Resources\MergeValue;
use Illuminate\Routing\Controller;
use Illuminate\Support\Collection;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Panel;
use Orlyapps\NovaBelongsToDepend\NovaBelongsToDepend;
Expand All @@ -12,7 +13,7 @@ class FieldController extends Controller
{
public function index(NovaRequest $request)
{
if (is_null($request->dependKey)) {
if (is_null($request->dependsMap)) {
abort(500, 'Depend On Relationship not found on the Resource specified for the Field "' . $request->attribute . '" Please check you have set correct /App/Nova/Resource');
}

Expand All @@ -22,33 +23,21 @@ public function index(NovaRequest $request)
$resource = new $request->resourceClass;
}

// Create Nested Array Fields from Panels, Flatten and find
$fields = $this->returnFields($resource->fields($request));
$attributedField = $this->getAttributedField($request, $resource);

$fields = $fields->filter(function ($value) use ($request) {
return ($value instanceof NovaBelongsToDepend);
});
$modelMap = $this->getModelMap($request, $attributedField);

$field = $fields->first(function ($value, $key) use ($request) {
return ($value instanceof NovaBelongsToDepend && $value->attribute == $request->attribute);
});

if (is_null($field)) {
abort(500, 'Can not find the Field "' . $request->attribute . '" in the Model "' . $request->resourceClass . '"');
if (empty($modelMap)) {
return [];
}

$model = $request->modelClass::find($request->dependKey);
$options = $this->getOptions($attributedField, $modelMap);

if (is_null($model)) {
abort(500, 'Can not find the Model "' . $request->modelClass . '::find(' . $request->dependKey . ')');
}

$result = ($field->optionResolveCallback)($model);

return $result;
return $options instanceof Collection ? $options : [$options];
}

public function returnFields($fields) {

public function returnFields($fields)
{
return collect($fields)->map(function ($field) {
if (isset($field->data)) {
return $this->returnFields($field->data);
Expand All @@ -57,8 +46,75 @@ public function returnFields($fields) {
} elseif (isset($field->fields)) {
return $this->returnFields($field->fields);
}

return $field;
})->flatten();
}

private function getAttributedField($request, $resource)
{
// Create Nested Array Fields from Panels, filter out irrelevant fields
$fields = $this->returnFields($resource->fields($request));

$fields = $fields->filter(
function ($value) use ($request) {
return ($value instanceof NovaBelongsToDepend);
}
);

//get the attributed field
$attributedField = $fields->first(function ($value, $key) use ($request) {
return ($value instanceof NovaBelongsToDepend && $value->attribute == $request->attribute);
});

if (is_null($attributedField)) {
abort(500, 'Can not find the Field "' . $request->attribute . '" in the Model "' . $request->resourceClass . '"');
}

return $attributedField;
}

private function getModelMap($request, $attributedField)
{
$models = [];

foreach ($request->dependsMap as $value) {

if (is_null($request->modelClass::find($value['value']))) {
abort(500, 'Can not find the Model "' . $request->modelClass . '::find(' . $value['value'] . ')');
}

array_push($models, $request->modelClass::find($value['value']));
}

$modelMap = [];

if (count($attributedField->dependsOn) == count($models)) {
for ($i = 0; $i < count($models); $i++) {
$modelMap[$attributedField->dependsOn[$i]] = $models[$i];
}
}

return $modelMap;
}

private function getOptions($attributedField, $modelMap)
{
$options = null;

if (count($modelMap) == 1 && count($attributedField->dependsOn) == 1) {

$model = $modelMap[$attributedField->dependsOn[0]];
$options = ($attributedField->optionResolveCallback)($model);

} else {
$options = ($attributedField->optionResolveCallback)((object)$modelMap);
}

if (is_null($options)) {
abort(500, 'Failed to create Result from ' . $attributedField->optionResolveCallback . ' with given Model');
}

return $options;
}
}
40 changes: 20 additions & 20 deletions src/NovaBelongsToDepend.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,9 @@ class NovaBelongsToDepend extends BelongsTo

public $titleKey;

public $dependKey;
public $dependsOn;
public $dependsOn = [];

public $dependsMap = [];

public $optionResolveCallback = null;
public $options = [];
Expand Down Expand Up @@ -79,9 +80,12 @@ public function optionsResolve($callback)
return $this;
}

public function dependsOn($relationship)
public function dependsOn(string ...$classNames): NovaBelongsToDepend
{
$this->dependsOn = Str::lower($relationship);
foreach ($classNames as &$value) {
$value = Str::lower($value);
}
$this->dependsOn = $classNames;
return $this;
}

Expand All @@ -91,17 +95,17 @@ public function fallback($fallback)
return $this;
}

/**
* @param $parentResourceClass
* @return self
*/
public function setResourceParentClass($parentResourceClass)
{
$this->resourceParentClass = $parentResourceClass;
return $this;
}
/**
* @param $parentResourceClass
* @return self
*/
public function setResourceParentClass($parentResourceClass)
{
$this->resourceParentClass = $parentResourceClass;
return $this;
}

public function hideLinkToResourceFromDetail()
public function hideLinkToResourceFromDetail()
{
$this->showLinkToResourceFromDetail = false;
return $this;
Expand Down Expand Up @@ -131,10 +135,6 @@ public function resolve($resource, $attribute = null)
$foreign = $resource->{$this->attribute}();
$this->foreignKeyName = $foreign->getForeignKeyName();

if ($this->dependsOn) {
$this->dependKey = $resource->{$this->dependsOn}()->getForeignKeyName();
}

if ($resource->relationLoaded($this->attribute)) {
$value = $resource->getRelation($this->attribute);
}
Expand Down Expand Up @@ -220,7 +220,7 @@ public function meta()
return array_merge([
'options' => $this->options,
'valueKey' => $this->valueKey,
'dependKey' => $this->dependKey,
'dependsMap' => $this->dependsMap,
'dependsOn' => $this->dependsOn,
'titleKey' => $this->titleKey,
'resourceParentClass' => $this->resourceParentClass,
Expand All @@ -229,7 +229,7 @@ public function meta()
'foreignKeyName' => $this->foreignKeyName,
'fallback' => $this->fallback,
'showLinkToResourceFromDetail' => $this->showLinkToResourceFromDetail,
'showLinkToResourceFromIndex' => $this->showLinkToResourceFromIndex
'showLinkToResourceFromIndex' => $this->showLinkToResourceFromIndex,
], $this->meta);
}
}

0 comments on commit d9750d0

Please sign in to comment.