Skip to content

Commit

Permalink
[Data Objects] Add select mode to many-to-one relation field (pimcore…
Browse files Browse the repository at this point in the history
…#13676)

* add display mode to many-to-one relation field

* add display mode to many-to-one relation field

* fix PhpStan error

* better describing option labels for "display mode" configuration

* simplify type / subtype / class filtering

* simplify type / subtype / class filtering

* simplify code

* refactoring

* work with Data object instead of its settings as array

* work with Data object instead of its settings as array

* add fullpath to visible fields

* add fullpath to visible fields

* fix PhpStan errors

* fix PhpStan errors - use Relation trait already in AbstractRelations as all Relation field types use it anyway, either directly or via inheritance

* add getVisibleFields() to many-to-one-relation. currently hard-coded to "fullpath". soon we will implement configuration of visible fields also for many-to-one relation fields

* support path formatter for select display mode for many-to-one-relation fields

* fix path formatter usage

* fix set value from search popup

* respect path formatter for select field mode

* Remove interfaces which already get provided by parent class

Co-authored-by: mcop1 <[email protected]>

* fix PhpStan

* fix PhpStan

* fix PhpStan

* fix PhpStan

* change translations to YAML

* fix PhpStan

* fix PhpStan

* fix PhpStan

* fix PhpStan

* fix PhpStan

* fix PhpStan

Co-authored-by: mcop1 <[email protected]>
  • Loading branch information
BlackbitDevs and mcop1 authored Jan 11, 2023
1 parent af29ff9 commit 8bd2b8d
Show file tree
Hide file tree
Showing 14 changed files with 259 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,19 @@ pimcore.object.classes.data.manyToOneRelation = Class.create(pimcore.object.clas
width: 400
})
]
},
{
xtype: "combo",
fieldLabel: t("display_mode"),
name: "displayMode",
value: this.datax.displayMode ?? 'grid',
labelWidth: 140,
forceSelection: true,
width: 400,
store: [
['grid', t('display_mode_display')],
['combo', t('display_mode_inline_search')],
]
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,9 +100,9 @@ pimcore.object.tags.advancedManyToManyObjectRelation = Class.create(pimcore.obje
url: Routing.generate('pimcore_admin_dataobject_dataobject_relation_objects_list'),
extraParams: {
fieldConfig: JSON.stringify(this.fieldConfig),
data: this.data.map(function(element) {
return element.id;
}).join(','),
data: JSON.stringify(this.data.map(function(element) {
return {id: element.id, type: element.type};
})),
},
reader: {
type: 'json',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ pimcore.object.tags.manyToManyObjectRelation = Class.create(pimcore.object.tags.
url: Routing.generate('pimcore_admin_dataobject_dataobject_relation_objects_list'),
extraParams: {
fieldConfig: JSON.stringify(this.fieldConfig),
data: this.data.map(function(element) {
return element.id;
}).join(','),
data: JSON.stringify(this.data.map(function(element) {
return {id: element.id, type: element.type};
})),
},
reader: {
type: 'json',
Expand Down
128 changes: 117 additions & 11 deletions bundles/AdminBundle/public/js/pimcore/object/tags/manyToOneRelation.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,52 @@ pimcore.object.tags.manyToOneRelation = Class.create(pimcore.object.tags.abstrac
}
return true;
}.bind(this));

this.fieldConfig.visibleFields = "fullpath";

let storeConfig = {
data: this.data,
listeners: {
add: function () {
this.dataChanged = true;
}.bind(this),
remove: function () {
this.dataChanged = true;
}.bind(this),
clear: function () {
this.dataChanged = true;
}.bind(this)
},
};

if (this.fieldConfig.displayMode == 'combo') {
storeConfig.proxy = {
type: 'ajax',
url: Routing.generate('pimcore_admin_dataobject_dataobject_relation_objects_list'),
extraParams: {
fieldConfig: JSON.stringify(this.fieldConfig),
data: JSON.stringify(
(this.data.id && this.data.type) ? [{id: this.data.id, type: this.data.type}] : []
)
},
reader: {
type: 'json',
rootProperty: 'options',
successProperty: 'success',
messageProperty: 'message'
}
};
storeConfig.fields = ['id', 'label'];
storeConfig.autoLoad = true;
storeConfig.listeners = {
beforeload: function(store) {
store.getProxy().setExtraParam('unsavedChanges', this.object ? this.object.getSaveData().data : {});
store.getProxy().setExtraParam('context', JSON.stringify(this.getContext()));
}.bind(this)
};
}

this.store = new Ext.data.JsonStore(storeConfig);
},


Expand Down Expand Up @@ -77,9 +123,7 @@ pimcore.object.tags.manyToOneRelation = Class.create(pimcore.object.tags.abstrac

getLayoutEdit: function () {

var href = {
name: this.fieldConfig.name
};
var href = {};

var labelWidth = this.fieldConfig.labelWidth ? this.fieldConfig.labelWidth : 100;

Expand All @@ -95,10 +139,40 @@ pimcore.object.tags.manyToOneRelation = Class.create(pimcore.object.tags.abstrac
href.width = 300;
}

href.cls = 'pimcore_droptarget_display_edit';
if (this.fieldConfig.displayMode == 'combo') {
Object.assign(href, {
store: this.store,
autoLoadOnValue: true,
labelWidth: labelWidth,
forceSelection: true,
height: 'auto',
value: this.data.id,
typeAhead: true,
filterPickList: true,
triggerAction: "all",
displayField: "label",
valueField: "id",
listeners: {
change: function (comboBox, newValue) {
if (newValue) {
let record = this.store.getById(newValue);
if (record) {
this.dataChanged = true;
this.data.id = record.get('id');
this.data.type = record.get('type');
}
}
}.bind(this)
}
});

this.component = Ext.create('Ext.form.field.ComboBox', href);
} else {
href.cls = 'pimcore_droptarget_display_edit';
href.fieldBodyCls = 'pimcore_droptarget_display x-form-trigger-wrap';
this.component = new Ext.form.field.Display(href);
}

href.fieldBodyCls = 'pimcore_droptarget_display x-form-trigger-wrap';
this.component = new Ext.form.field.Display(href);
if (this.data.published === false) {
this.component.addCls("strikeThrough");
}
Expand All @@ -122,7 +196,7 @@ pimcore.object.tags.manyToOneRelation = Class.create(pimcore.object.tags.abstrac

el.getEl().on("contextmenu", this.onContextMenu.bind(this));

el.getEl().on('dblclick', function(){
el.getEl().on('dblclick', function () {
var subtype = this.data.subtype;
if (this.data.type === "object" && this.data.subtype !== "folder" && this.data.subtype !== null) {
subtype = "object";
Expand Down Expand Up @@ -270,7 +344,18 @@ pimcore.object.tags.manyToOneRelation = Class.create(pimcore.object.tags.abstrac
this.data.subtype = data["type"];
this.data.path = data["fullpath"];
this.dataChanged = true;
this.component.setValue(data["fullpath"]);
if (this.fieldConfig.displayMode == 'combo') {
if (!this.component.getStore().getById(data.id)) {
this.component.getStore().getProxy().setExtraParam('data', JSON.stringify([{id: this.data.id, type: this.data.type}]));
this.component.getStore().on('load', function(){
this.component.setValue(this.data.id);
}.bind(this), this, { single: true });
this.component.getStore().load();
}
this.component.setValue(this.data.id);
} else {
this.component.setValue(data["fullpath"]);
}
this.requestNicePathData();
}
} catch (e) {
Expand Down Expand Up @@ -308,7 +393,18 @@ pimcore.object.tags.manyToOneRelation = Class.create(pimcore.object.tags.abstrac
if (data.published === false) {
this.component.addCls("strikeThrough");
}
this.component.setValue(data.path);
if (this.fieldConfig.displayMode == 'combo') {
if (!this.component.getStore().getById(data.id)) {
this.component.getStore().getProxy().setExtraParam('data', JSON.stringify([{id: data.id, type: data.elementType}]));
this.component.getStore().on('load', function(){
this.component.setValue(data.id);
}.bind(this), this, { single: true });
this.component.getStore().load();
}
this.component.setValue(data.id);
} else {
this.component.setValue(data.path);
}
this.requestNicePathData();

return true;
Expand Down Expand Up @@ -429,7 +525,13 @@ pimcore.object.tags.manyToOneRelation = Class.create(pimcore.object.tags.abstrac
if (data.published === false) {
this.component.addCls("strikeThrough");
}
this.component.setValue(data.fullpath);

if (this.fieldConfig.displayMode == 'combo') {
this.component.setValue(data.id);
} else {
this.component.setValue(data.fullpath);
}

this.requestNicePathData();
},

Expand Down Expand Up @@ -554,7 +656,11 @@ pimcore.object.tags.manyToOneRelation = Class.create(pimcore.object.tags.abstrac
this.component.removeCls("grid_nicepath_requested");

if (typeof responseData[target["nicePathKey"]] !== "undefined") {
this.component.setValue(responseData[target["nicePathKey"]]);
if (this.fieldConfig.displayMode == 'combo') {
this.component.setValue(target["id"]);
} else {
this.component.setValue(responseData[target["nicePathKey"]]);
}
}

}.bind(this, target)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -557,64 +557,139 @@ static function (Task $task) {
*/
public function optionsAction(Request $request): JsonResponse
{
$fieldConfig = json_decode($request->get('fieldConfig'), true);

$options = [];
$classes = [];
if (count($fieldConfig['classes']) > 0) {
foreach ($fieldConfig['classes'] as $classData) {
$classes[] = $classData['classes'];
}
$fieldConfigData = json_decode($request->get('fieldConfig'), true);
$loader = \Pimcore::getContainer()->get('pimcore.implementation_loader.object.data');
if (!$loader->supports($fieldConfigData['fieldtype'])) {
return new JsonResponse([]);
}

$visibleFields = is_array($fieldConfig['visibleFields']) ? $fieldConfig['visibleFields'] : explode(',', $fieldConfig['visibleFields']);
/** @var AbstractRelations $fieldConfig */
$fieldConfig = $loader->build($fieldConfigData['fieldtype']);
$fieldConfig->setValues($fieldConfigData);

$visibleFields = null;
if(method_exists($fieldConfig, 'getVisibleFields')) {
$visibleFields = is_array($fieldConfig->getVisibleFields()) ? $fieldConfig->getVisibleFields() : explode(',', $fieldConfig->getVisibleFields());
}

if (!$visibleFields) {
$visibleFields = ['id', 'fullpath', 'classname'];
}

$searchRequest = $request;
$searchRequest->request->set('type', 'object');
$searchRequest->request->set('subtype', 'object,variant');

$allowedTypes = [];
$subTypes = [];
$classes = [];
$allowClasses = true;

if ($fieldConfig->getAssetsAllowed()) {
$allowedTypes[] = 'asset';
$allowClasses = false;

foreach ($fieldConfig->getAssetTypes() as $subType) {
$subTypes[] = $subType['assetTypes'];
}
}

if (method_exists($fieldConfig, 'getDocumentsAllowed') && $fieldConfig->getDocumentsAllowed()) {
$allowedTypes[] = 'document';
$allowClasses = false;

foreach ($fieldConfig->getDocumentTypes() as $subType) {
$subTypes[] = $subType['documentTypes'];
}
}

if (method_exists($fieldConfig, 'getObjectsAllowed') && $fieldConfig->getObjectsAllowed()) {
$allowedTypes[] = 'object';

if ( $allowClasses ) {
$subTypes = array_merge($subTypes, ['object', 'variant']);

foreach ($fieldConfig->getClasses() as $classData) {
$classes[] = $classData['classes'];
}
}
}

$searchRequest->request->set('type', implode(',', $allowedTypes));
$searchRequest->request->set('subtype', implode(',', $subTypes));
$searchRequest->request->set('class', implode(',', $classes));
$searchRequest->request->set('fields', $visibleFields);
$searchRequest->attributes->set('unsavedChanges', $request->get('unsavedChanges', ''));
$res = $this->forward(SearchController::class.'::findAction', ['request' => $searchRequest]);
$objects = json_decode($res->getContent(), true)['data'];

if ($request->get('data')) {
foreach (explode(',', $request->get('data')) as $preSelectedElementId) {
$objects[] = ['id' => $preSelectedElementId];
if($request->get('data')) {
foreach(json_decode($request->get('data'), true) as $preSelectedElement) {
if (isset($preSelectedElement['id'], $preSelectedElement['type'])) {
$objects[] = ['id' => $preSelectedElement['id'], 'type' => $preSelectedElement['type']];
}
}
}

$options = [];
foreach ($objects as $objectData) {
$option = [
'id' => $objectData['id'],
'type' => $objectData['type']
];

$visibleFieldValues = [];
foreach ($visibleFields as $visibleField) {
if ($visibleField === 'fullpath' && $fieldConfig instanceof DataObject\ClassDefinition\PathFormatterAwareInterface) {
$object = Element\Service::getElementById($objectData['type'], $objectData['id']);
if (!$object instanceof Element\ElementInterface) {
continue;
}

$formatter = $fieldConfig->getPathFormatterClass();

if (null !== $formatter) {
$pathFormatter = DataObject\ClassDefinition\Helper\PathFormatterResolver::resolvePathFormatter(
$fieldConfig->getPathFormatterClass()
);

if ($pathFormatter instanceof DataObject\ClassDefinition\PathFormatterInterface) {
$formattedPath = $pathFormatter->formatPath(
[],
$object,
[$objectData],
[
'fd' => $fieldConfig,
'context' => []
]
)[0] ?? null;
if($formattedPath) {
$objectData['fullpath'] = $formattedPath;
}
}
}
}

if (isset($objectData[$visibleField])) {
$visibleFieldValues[] = $objectData[$visibleField];
} else {
$object = Element\Service::getElementById($objectData['type'], $objectData['id']);
if (!$object instanceof Element\ElementInterface) {
continue;
}

$inheritValues = DataObject\Concrete::getGetInheritedValues();
$fallbackValues = DataObject\Localizedfield::getGetFallbackValues();

DataObject\Concrete::setGetInheritedValues(true);
DataObject\Localizedfield::setGetFallbackValues(true);

$object = DataObject\Concrete::getById($objectData['id']);
if (!$object instanceof DataObject\Concrete) {
continue;
}

$getter = 'get'.ucfirst($visibleField);
$visibleFieldValue = $object->$getter();
if (count($classes) > 1 && $visibleField == 'key') {
$visibleFieldValue .= ' ('.$object->getClassName().')';
if(method_exists($object, $getter)) {
$visibleFieldValue = $object->$getter();
if ($visibleField === 'key' && $object instanceof DataObject\Concrete && count($classes) > 1) {
$visibleFieldValue .= ' ('.$object->getClassName().')';
}
$visibleFieldValues[] = $visibleFieldValue;
}
$visibleFieldValues[] = $visibleFieldValue;

DataObject\Concrete::setGetInheritedValues($inheritValues);
DataObject\Localizedfield::setGetFallbackValues($fallbackValues);
Expand Down
Loading

0 comments on commit 8bd2b8d

Please sign in to comment.