$scope.crmUrl = CRM.url;
this.tabs = CRM.afAdmin.afform_type;
+ $scope.tabs = _.indexBy(ctrl.tabs, 'name');
+ _.each(['form', 'block', 'search'], function(type) {
+ if ($scope.tabs[type]) {
+ $scope.tabs[type].options = [];
+ if (type === 'form') {
+ $scope.tabs.form.default = '#create/form/Individual';
+ }
+ }
+ });
this.afforms = _.transform(afforms, function(afforms, afform) {
- var type = afform.type || 'system';
- afforms[type] = afforms[type] || [];
- afforms[type].push(afform);
+ afform.type = afform.type || 'system';
+ afforms[afform.type] = afforms[afform.type] || [];
+ afforms[afform.type].push(afform);
}, {});
$scope.$bindToRoute({
default: ctrl.tabs[0].name
});
+ this.createLinks = function() {
+ ctrl.searchCreateLinks = '';
+ if ($scope.tabs[ctrl.tab].options.length) {
+ return;
+ }
+ var links = [];
+
+ if (ctrl.tab === 'form') {
+ _.each(CRM.afGuiEditor.entities, function(entity, name) {
+ if (entity.defaults) {
+ links.push({
+ url: '#create/form/' + name,
+ label: entity.label,
+ icon: entity.icon
+ });
+ }
+ });
+ $scope.tabs.form.options = _.sortBy(links, 'Label');
+ }
+
+ if (ctrl.tab === 'block') {
+ _.each(CRM.afGuiEditor.entities, function(entity, name) {
+ if (entity.defaults) {
+ links.push({
+ url: '#create/block/' + name,
+ label: entity.label,
+ icon: entity.icon
+ });
+ }
+ });
+ $scope.tabs.block.options = _.sortBy(links, 'Label');
+ }
+ };
+
this.revert = function(afform) {
var index = _.findIndex(ctrl.afforms[ctrl.tab], {name: afform.name});
if (index > -1) {
<div id="bootstrap-theme" class="afadmin-list">
<h1 crm-page-title>{{:: ts('Configurable Forms') }}</h1>
- <div class="form-inline text-right">
- <a class="btn btn-primary" href="#/create/form">
- <i class="crm-i fa-plus"></i>
- {{:: ts('New Form') }}
- </a>
- </div>
-
<ul class="nav nav-tabs">
<li role="presentation" ng-repeat="tab in $ctrl.tabs" ng-class="{active: tab.name === $ctrl.tab}">
- <a href ng-click="$ctrl.tab = tab.name"><i class="crm-i {{ tab.icon }}"></i> {{:: tab.label }}</a>
+ <a href ng-click="$ctrl.tab = tab.name; $ctrl.searchAfformList = ''"><i class="crm-i {{ tab.icon }}"></i> {{:: tab.label }}</a>
</li>
</ul>
<div class="form-inline">
- <input class="form-control" type="search" ng-model="$ctrl.search" placeholder="{{:: ts('Filter') }}">
+ <label for="afform-list-filter">{{:: ts('Filter:') }}</label>
+ <input class="form-control" type="search" id="afform-list-filter" ng-model="$ctrl.searchAfformList" placeholder="">
+ <div class="btn-group pull-right" ng-if="tabs[$ctrl.tab].options">
+ <a ng-if="tabs[$ctrl.tab].default" href="{{ tabs[$ctrl.tab].default }}" class="btn btn-primary">
+ {{ ts('New %1', {1: tabs[$ctrl.tab].label }) }}
+ </a>
+ <button ng-click="$ctrl.createLinks()" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+ <span ng-class="{'sr-only': tabs[$ctrl.tab].default}">{{ ts('New %1', {1: tabs[$ctrl.tab].label }) }}</span>
+ <span class="caret"></span>
+ </button>
+ <ul class="dropdown-menu">
+ <li>
+ <input ng-if="tabs[$ctrl.tab].options.length" type="search" class="form-control" placeholder="" ng-model="$ctrl.searchCreateLinks">
+ <a href ng-if="!tabs[$ctrl.tab].options.length"><i class="crm-i fa-spinner fa-spin"></i></a>
+ </li>
+ <li ng-repeat="link in tabs[$ctrl.tab].options | filter:$ctrl.searchCreateLinks">
+ <a href="{{ link.url }}">
+ <i class="crm-i {{ link.icon }}"></i>
+ {{ link.label }}
+ </a>
+ </li>
+ </ul>
+ </div>
</div>
<table>
</tr>
</thead>
<tbody>
- <tr ng-repeat="afform in $ctrl.afforms[$ctrl.tab] | filter:$ctrl.search">
+ <tr ng-repeat="afform in $ctrl.afforms[$ctrl.tab] | filter:$ctrl.searchAfformList">
<td>{{afform.title}}</td>
<td>
<code>{{afform.name}}</code>
</td>
<td>{{afform.is_public ? ts('Frontend') : ts('Backend')}}</td>
<td>
- <a href="#/edit/{{ afform.name }}" class="btn btn-xs btn-primary">{{ ts('Edit') }}</a>
+ <a ng-if="afform.type !== 'system'" href="#/edit/{{ afform.name }}" class="btn btn-xs btn-primary">{{ ts('Edit') }}</a>
<a href ng-if="afform.has_local" class="btn btn-xs btn-danger" crm-confirm="{type: afform.has_base ? 'revert' : 'delete', obj: afform}" on-yes="$ctrl.revert(afform)">
{{ afform.has_base ? ts('Revert') : ts('Delete') }}
</a>
font-size: 12px;
}
-#afGuiEditor input[type=search]::placeholder {
+#bootstrap-theme input[type=search]::placeholder {
font-family: FontAwesome;
text-align: right;
}
-#afGuiEditor input[type=search]:-ms-input-placeholder {
+#bootstrap-theme input[type=search]:-ms-input-placeholder {
font-family: FontAwesome;
text-align: right;
}
-#afGuiEditor input[type=search]::-ms-input-placeholder {
+#bootstrap-theme input[type=search]::-ms-input-placeholder {
font-family: FontAwesome;
text-align: right;
}
meta: CRM.afGuiEditor,
- getField: function(entityType, fieldName) {
- return CRM.afGuiEditor.entities[entityType].fields[fieldName];
+ getEntity: function(entityName) {
+ return CRM.afGuiEditor.entities[entityName];
+ },
+
+ getField: function(entityName, fieldName) {
+ return CRM.afGuiEditor.entities[entityName].fields[fieldName];
},
// Recursively searches a collection and its children using _.filter
}
$scope.canvasTab = 'layout';
$scope.layoutHtml = '';
- editor.layout = afGui.findRecursive($scope.afform.layout, {'#tag': 'af-form'})[0];
- $scope.entities = afGui.findRecursive(editor.layout['#children'], {'#tag': 'af-entity'}, 'name');
+ editor.layout = {'#children': []};
+ $scope.entities = {};
- if (editor.mode === 'create') {
- editor.addEntity(editor.entity);
- editor.layout['#children'].push(afGui.meta.elements.submit.element);
+ if ($scope.afform.type === 'form') {
+ editor.allowEntityConfig = true;
+ editor.layout['#children'] = afGui.findRecursive($scope.afform.layout, {'#tag': 'af-form'})[0]['#children'];
+ $scope.entities = afGui.findRecursive(editor.layout['#children'], {'#tag': 'af-entity'}, 'name');
+
+ if (editor.mode === 'create') {
+ editor.addEntity(editor.entity);
+ editor.layout['#children'].push(afGui.meta.elements.submit.element);
+ }
+ }
+
+ else if ($scope.afform.type === 'block') {
+ editor.layout['#children'] = $scope.afform.layout;
+ editor.blockEntity = $scope.afform.join || $scope.afform.block;
+ $scope.entities[editor.blockEntity] = {
+ type: editor.blockEntity,
+ name: editor.blockEntity,
+ label: afGui.getEntity(editor.blockEntity).label
+ };
}
// Set changesSaved to true on initial load, false thereafter whenever changes are made to the model
</div>
<div id="afGuiEditor-canvas-body" class="panel-body" ng-if="canvasTab === 'layout'">
- <af-gui-container ng-if="editor.layout" node="editor.layout" entity-name="" ></af-gui-container>
+ <af-gui-container ng-if="editor.layout" node="editor.layout" entity-name="editor.blockEntity" data-entity="{{ editor.blockEntity }}" ></af-gui-container>
</div>
<div class="panel-body" ng-if="canvasTab === 'markup'">
<p class="help-block">{{:: ts('This is a read-only preview of the auto-generated markup.') }}</p>
</li>
<li role="presentation" ng-repeat="entity in entities" ng-class="{active: selectedEntityName === entity.name}">
<a href ng-click="editor.selectEntity(entity.name)">
- <span ng-if="!entity.loading" af-gui-editable ng-model="entity.label">{{ entity.label }}</span>
+ <span ng-if="!entity.loading && editor.allowEntityConfig" af-gui-editable ng-model="entity.label">{{ entity.label }}</span>
+ <span ng-if="!entity.loading && !editor.allowEntityConfig">{{ entity.label }}</span>
<i ng-if="entity.loading" class="crm-i fa-spin fa-spinner"></i>
</a>
</li>
- <li role="presentation" class="dropdown">
- <a href class="dropdown-toggle" data-toggle="dropdown">
+ <li role="presentation" class="dropdown" ng-if="editor.allowEntityConfig">
+ <a href class="dropdown-toggle" data-toggle="dropdown" title="{{ ts('Add Entity') }}">
<span><i class="crm-i fa-plus"></i></span>
</a>
<ul class="dropdown-menu">
if (!search || _.contains(name, search) || _.contains(element.title.toLowerCase(), search)) {
var node = _.cloneDeep(element.element);
if (name === 'fieldset') {
+ if (!ctrl.editor.allowEntityConfig) {
+ return;
+ }
node['af-fieldset'] = ctrl.entity.name;
}
$scope.elementList.push(node);
</fieldset>
</div>
-<a href ng-click="$ctrl.editor.removeEntity($ctrl.entity.name)" class="btn btn-sm btn-danger-outline af-gui-remove-entity" title="{{ ts('Remove %1', {1: getMeta().label}) }}">
+<a ng-if="!$ctrl.entity.loading && $ctrl.editor.allowEntityConfig" href ng-click="$ctrl.editor.removeEntity($ctrl.entity.name)" class="btn btn-sm btn-danger-outline af-gui-remove-entity" title="{{ ts('Remove %1', {1: getMeta().label}) }}">
<i class="crm-i fa-trash"></i>
</a>
-<fieldset ng-if="!$ctrl.entity.loading">
+<fieldset ng-if="!$ctrl.entity.loading && $ctrl.editor.allowEntityConfig">
<legend>{{:: ts('Options') }}</legend>
<div ng-include="'~/afGuiEditor/entityConfig/' + $ctrl.entity.type + '.html'"></div>
</fieldset>
ctrl = this;
this.$onInit = function() {
- if ((ctrl.node['#tag'] in afGui.meta.blocks) || ctrl.join) {
+ if (ctrl.node['#tag'] && ((ctrl.node['#tag'] in afGui.meta.blocks) || ctrl.join)) {
var blockNode = getBlockNode(),
blockTag = blockNode ? blockNode['#tag'] : null;
if (blockTag && (blockTag in afGui.meta.blocks) && !afGui.meta.blocks[blockTag].layout) {
this.node = ctrl.node;
this.getNodeType = function(node) {
- if (!node) {
+ if (!node || !node['#tag']) {
return null;
}
if (node['#tag'] === 'af-field') {
-<div class="af-gui-bar" ng-if="$ctrl.node['#tag'] !== 'af-form'" ng-click="selectEntity()" >
+<div class="af-gui-bar" ng-if="$ctrl.node['#tag']" ng-click="selectEntity()" >
<div ng-if="!$ctrl.loading" class="form-inline" af-gui-menu>
<span ng-if="$ctrl.getNodeType($ctrl.node) == 'fieldset'">{{ $ctrl.editor.getEntity($ctrl.entityName).label }}</span>
<span ng-if="block">{{ $ctrl.join ? ts($ctrl.join) + ':' : ts('Block:') }}</span>