From 65c9e7ae141453396b7cfe177f0a93c5041f5fab Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Fri, 1 Nov 2019 15:15:59 -0400 Subject: [PATCH] Fields drag n drop --- ext/afform/core/afform.php | 1 + ext/afform/gui/afform_gui.php | 3 +- ext/afform/gui/ang/afGuiEditor.css | 46 +++++++--- ext/afform/gui/ang/afGuiEditor.js | 84 +++++++++++++++---- ext/afform/gui/ang/afGuiEditor/block.html | 4 +- .../gui/ang/afGuiEditor/config-entity.html | 11 ++- ext/afform/gui/ang/afGuiEditor/main.html | 2 +- 7 files changed, 113 insertions(+), 38 deletions(-) diff --git a/ext/afform/core/afform.php b/ext/afform/core/afform.php index e9decfee32..a54dd7fa7f 100644 --- a/ext/afform/core/afform.php +++ b/ext/afform/core/afform.php @@ -316,6 +316,7 @@ function afform_civicrm_alterAngular($angular) { } $entityType = $entities[$entityName]['type']; $getFields = civicrm_api4($entityType, 'getFields', [ + 'action' => 'create', 'where' => [['name', '=', $fieldName]], 'select' => ['title', 'input_type', 'input_attrs', 'options'], 'loadOptions' => TRUE, diff --git a/ext/afform/gui/afform_gui.php b/ext/afform/gui/afform_gui.php index f72cb7f014..5aef321d40 100644 --- a/ext/afform/gui/afform_gui.php +++ b/ext/afform/gui/afform_gui.php @@ -186,7 +186,8 @@ function afform_gui_civicrm_buildAsset($asset, $params, &$mimeType, &$content) { ->setCheckPermissions(FALSE) ->setIncludeCustom(TRUE) ->setLoadOptions(TRUE) - ->setAction('Create') + ->setAction('create') + ->setSelect(['name', 'title', 'input_type', 'input_attrs', 'options']) ->execute(); $contactSettings = [ diff --git a/ext/afform/gui/ang/afGuiEditor.css b/ext/afform/gui/ang/afGuiEditor.css index 424e5aad54..95df8383fd 100644 --- a/ext/afform/gui/ang/afGuiEditor.css +++ b/ext/afform/gui/ang/afGuiEditor.css @@ -64,18 +64,6 @@ width: 100%; padding-left:15px; } -/* grip handle */ -#afGuiEditor .af-gui-bar:before { - background-size: cover; - background: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1IiBoZWlnaHQ9IjUiPgo8cmVjdCB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjODg4Ij48L3JlY3Q+Cjwvc3ZnPg=="); - width: 10px; - height: 15px; - content: ' '; - display: block; - position: absolute; - left: 4px; - top: 5px; -} #afGuiEditor-canvas:hover .af-gui-bar { visibility: visible; @@ -106,3 +94,37 @@ #afGuiEditor .af-gui-block:hover { border: 2px dashed #757575; } + +#afGuiEditor [ui-sortable] { + min-height: 25px; +} + +#afGuiEditor .af-gui-field-select-list { + max-height: 280px; + overflow-y: auto; +} + +#afGuiEditor .af-gui-field-select-list > div { + cursor: move; + padding-left:15px; + position: relative; +} +#afGuiEditor .af-gui-field-select-list > div.disabled { + cursor: auto; +} +#afGuiEditor .af-gui-field-select-list > div:not(.disabled):hover { + background-color: #efefef; +} +/* grip handle */ +#afGuiEditor .af-gui-bar:before, +#afGuiEditor .af-gui-field-select-list > div:not(.disabled):hover:before { + background-size: cover; + background: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI1IiBoZWlnaHQ9IjUiPgo8cmVjdCB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBmaWxsPSIjODg4Ij48L3JlY3Q+Cjwvc3ZnPg=="); + width: 10px; + height: 15px; + content: ' '; + display: block; + position: absolute; + left: 4px; + top: 5px; +} diff --git a/ext/afform/gui/ang/afGuiEditor.js b/ext/afform/gui/ang/afGuiEditor.js index 45ef072bf6..9569255426 100644 --- a/ext/afform/gui/ang/afGuiEditor.js +++ b/ext/afform/gui/ang/afGuiEditor.js @@ -1,7 +1,7 @@ (function(angular, $, _) { angular.module('afGuiEditor', CRM.angRequires('afGuiEditor')); - angular.module('afGuiEditor').directive('afGuiEditor', function(crmApi4, $parse) { + angular.module('afGuiEditor').directive('afGuiEditor', function(crmApi4, $parse, $timeout) { return { restrict: 'A', templateUrl: '~/afGuiEditor/main.html', @@ -14,6 +14,7 @@ $scope.selectedEntity = null; $scope.meta = CRM.afformAdminData; $scope.controls = {}; + $scope.fieldList = {}; $scope.editor = this; var newForm = { title: ts('Untitled Form'), @@ -49,7 +50,8 @@ $scope.layout = getTags($scope.afform.layout, 'af-form')[0]; evaluate($scope.layout['#children']); $scope.entities = getTags($scope.layout['#children'], 'af-entity', 'name'); - $scope.fields = getAllFields($scope.layout['#children']); + expandFields($scope.layout['#children']); + _.each(_.keys($scope.entities), buildFieldList); } this.addEntity = function(entityType) { @@ -91,10 +93,29 @@ return $scope.selectedEntity; }; + $scope.rebuildFieldList = function() { + $timeout(function() { + $scope.$apply(function() { + buildFieldList($scope.selectedEntity); + }); + }); + }; + + function buildFieldList(entityName) { + $scope.fieldList[entityName] = $scope.fieldList[entityName] || []; + $scope.fieldList[entityName].length = 0; + _.each($scope.meta.fields[$scope.entities[entityName].type], function(field) { + $scope.fieldList[entityName].push({ + "#tag": "af-field", + name: field.name, + defn: _.cloneDeep(_.pick(field, ['title', 'input_type', 'input_attrs'])) + }); + }); + } + $scope.valuesFields = function() { var fields = _.transform($scope.meta.fields[$scope.entities[$scope.selectedEntity].type], function(fields, field) { - var data = $scope.entities[$scope.selectedEntity].data || {}; - fields.push({id: field.name, text: field.title, disabled: field.name in data}); + fields.push({id: field.name, text: field.title, disabled: $scope.fieldInUse($scope.selectedEntity, field.name)}); }, []); return {results: fields}; }; @@ -113,6 +134,33 @@ } }); + // Checks if a field is on the form or set as a value + $scope.fieldInUse = function(entityName, fieldName) { + var data = $scope.entities[entityName].data || {}, + found = false; + if (fieldName in data) { + return true; + } + return check($scope.layout['#children']); + function check(group) { + _.each(group, function(item) { + if (found) { + return false; + } + if (_.isPlainObject(item)) { + if ((!item['af-fieldset'] || (item['af-fieldset'] === entityName)) && item['#children']) { + check(item['#children']); + } + if (item['#tag'] === 'af-field' && item.name === fieldName) { + found = true; + } + } + }); + return found; + } + }; + + // Parse strings of javascript that php couldn't interpret function evaluate(collection) { _.each(collection, function(item) { if (_.isPlainObject(item)) { @@ -129,6 +177,22 @@ }); } + function expandFields(collection, entityType) { + _.each(collection, function (item) { + if (_.isPlainObject(item)) { + if (item['af-fieldset']) { + expandFields(item['#children'], $scope.editor.getEntity(item['af-fieldset']).type); + } + else if (item['#tag'] === 'af-field') { + item.defn = item.defn || {}; + _.defaults(item.defn, _.cloneDeep(_.pick($scope.editor.getField(entityType, item.name), ['title', 'input_type', 'input_attrs']))); + } else { + expandFields(item['#children'], entityType); + } + } + }); + } + } }; }); @@ -149,18 +213,6 @@ return indexBy ? _.indexBy(items, indexBy) : items; } - // Lists fields by entity. Note that fields for an entity can be spread across several fieldsets. - function getAllFields(layout) { - var allFields = {}; - _.each(getTags(layout, 'af-fieldset'), function(fieldset) { - if (!allFields[fieldset.model]) { - allFields[fieldset.model] = {}; - } - _.assign(allFields[fieldset.model], getTags(fieldset['#children'], 'af-field', 'name')); - }); - return allFields; - } - // Turns a space-separated list (e.g. css classes) into an array function splitClass(str) { if (_.isArray(str)) { diff --git a/ext/afform/gui/ang/afGuiEditor/block.html b/ext/afform/gui/ang/afGuiEditor/block.html index 6aca722e1d..e45853423d 100644 --- a/ext/afform/gui/ang/afGuiEditor/block.html +++ b/ext/afform/gui/ang/afGuiEditor/block.html @@ -5,10 +5,10 @@ -
+
-
+
diff --git a/ext/afform/gui/ang/afGuiEditor/config-entity.html b/ext/afform/gui/ang/afGuiEditor/config-entity.html index 495319c907..cf32fadf03 100644 --- a/ext/afform/gui/ang/afGuiEditor/config-entity.html +++ b/ext/afform/gui/ang/afGuiEditor/config-entity.html @@ -19,12 +19,11 @@
{{ ts('Fields') }} -
    -
  • - - -
  • -
+
+
+ {{ field.defn.title }} +
+
diff --git a/ext/afform/gui/ang/afGuiEditor/main.html b/ext/afform/gui/ang/afGuiEditor/main.html index bf677ca448..bd8b471e1b 100644 --- a/ext/afform/gui/ang/afGuiEditor/main.html +++ b/ext/afform/gui/ang/afGuiEditor/main.html @@ -1,7 +1,7 @@
-
+
-- 2.25.1