| <!-- |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| --> |
| <!-- ENTITY TYPE --> |
| <section class="spec-type container-fluid panel-group"> |
| <div class="panel"> |
| <div class="spec-type-header"> |
| <h2 class="spec-title"><input class="form-control editable" ng-model="model.name" placeholder="{{model.miscData.get('typeName') || 'Unnamed ' + (!model.hasParent() ? 'application' : model.family.displayName)}}" blur-on-enter /></h2> |
| |
| <div class="btn-group pull-right spec-actions" ng-if="model.hasType()" uib-dropdown> |
| <button id="spec-actions" type="button" class="btn btn-link" uib-dropdown-toggle> |
| <span class="fa fa-bars"></span> |
| </button> |
| <ul class="dropdown-menu" uib-dropdown-menu role="menu" aria-labelledby="spec-actions"> |
| <li role="menuitem"><a ng-href="/brooklyn-ui-catalog/#!/bundles/{{model.miscData.get('bundle').symbolicName}}/{{model.miscData.get('bundle').version}}/types/{{model.type}}/{{model.version || 'latest'}}" target="_blank">Open in Catalog</a></li> |
| <li role="separator" class="divider"></li> |
| <li role="menuitem"><a href ng-click="removeModel()"><span class="text-danger">Delete</span></a></li> |
| </ul> |
| </div> |
| </div> |
| |
| <p ng-if="!model.hasParent()"><input class="form-control editable spec-id" ng-model="model.id" placeholder="No reference ID" blur-on-enter /></p> |
| |
| <div class="media" ng-if="model.hasParent()"> |
| <div class="media-left"> |
| <img ng-src="{{model.icon}}" alt="{{model | entityName}} logo" class="media-object" /> |
| </div> |
| <div class="media-body panel-header-body"> |
| <div title="{{ model.miscData.get('typeName') }}"><i class="fa fa-bookmark panel-header-icon"></i><samp class="entity-type-header">{{model.type}}</samp> <span class="label label-primary version">{{model | entityVersion}}</span></div> |
| <div ng-if="['POLICY', 'ENRICHER'].indexOf(model.family.id) === -1" class="identifier"> |
| <i class="fa fa-id-card-o panel-header-icon"></i> |
| <input class="form-control editable" ng-model="model.id" placeholder="(no reference ID)" blur-on-enter /> |
| </div> |
| </div> |
| </div> |
| </div> |
| </section> |
| |
| <!-- ENTITY CONFIGURATION --> |
| <br-collapsible ng-if="true" state="state.config.open"> <!-- the ng-if is needed to make state update?! --> |
| <heading> |
| Configuration |
| <span ng-if="getConfigIssues().length> 0" class="badge" ng-class="getBadgeClass(getConfigIssues())">{{getConfigIssues().length}}</span> |
| <span class="pull-right" ng-show="$parent.stateWrapped.state"> |
| <span class="spec-toolbar-action" ng-class="{'active': state.config.filter.open}"><i class="fa fa-filter collapsible-action" title="Filter configuration" ng-click="$event.stopPropagation(); $event.preventDefault(); state.config.filter.open = !state.config.filter.open" ng-class="{'text-info': state.config.search.length > 0}"></i></span> |
| <span class="spec-toolbar-action"><i class="fa fa-plus collapsible-action" title="Add configuration" ng-click="$event.stopPropagation(); $event.preventDefault(); state.config.add.open = !state.config.add.open"></i></span> |
| </span> |
| </heading> |
| |
| <fieldset uib-collapse="!state.config.filter.open" class="spec-configuration-filters"> |
| <div class="form-group"> |
| <input ng-model="state.config.search" type="text" class="form-control" placeholder="Search for config key by name" auto-focus="state.config.filter.open" blur-on-enter /> |
| </div> |
| <div class="form-group"> |
| <ul class="spec-configuration-filters-categories"> |
| <li ng-repeat="filter in filters.config track by filter.id" |
| ng-class="{ 'disabled': isFilterDisabled(filter) }" |
| ng-click="onFilterClicked(filter)" |
| class="pull-left"> |
| <i class="filter-checkbox fa" ng-class="{'fa-check-square-o': state.config.filter.values[ filter.id ], 'fa-square-o': !state.config.filter.values[ filter.id ]}"></i> {{filter.label}} |
| </li> |
| </ul> |
| </div> |
| </fieldset> |
| |
| <fieldset uib-collapse="!state.config.add.open" class="spec-configuration-add"> |
| <input auto-focus="state.config.add.open" |
| type="text" |
| autocomplete="off" |
| ng-model="state.config.add.value" |
| placeholder="Add a new configuration key or open existing" |
| class="form-control" |
| uib-typeahead="config.name for config in state.config.add.list | filter:{name:$viewValue}" |
| typeahead-template-url="blueprint-composer/component/spec-editor/config-item.html" |
| typeahead-editable="true" |
| typeahead-show-hint="true" |
| typeahead-min-length="0" |
| typeahead-select-on-blur="true" |
| typeahead-on-select="onFocusOnConfig($item, $model, $label, $event)" |
| typeahead-no-results="noResults" |
| blur-on-enter /> |
| |
| <div ng-if="state.config.add.value.length > 0 && noResults" uib-dropdown uib-dropdown-toggle auto-close="disabled" is-open="true"> |
| <ul class="dropdown-menu"> |
| <!-- mimic real dropdown if nothing found --> |
| <li class="uib-typeahead-match"><a ng-click="addConfigKey()"> |
| <div class="dropdown-item" ng-init="item = match.model"> |
| <div class="dropdown-row"> |
| <span ng-bind-html="state.config.add.value | uibTypeaheadHighlight:query" class="config-name"></span> |
| <i class="fa fa-fw fa-plus-square-o"></i> |
| </div> |
| </a></li> |
| </ul> |
| </div> |
| </fieldset> |
| |
| <div class="spec-configuration"> |
| <div class="spec-empty-state" ng-if="filteredItems.length === 0"> |
| <div ng-if="model.miscData.get('config').length === 0"> |
| <h4>No configuration</h4> |
| </div> |
| <div ng-if="model.miscData.get('config').length > 0"> |
| <h4>No matching configuration</h4> |
| <p class="buttons"> |
| <button class="btn btn-sm btn-default" ng-if="state.config.search.length > 0" ng-click="state.config.search = ''">Clear search</button> |
| <button class="btn btn-sm btn-success" ng-if="!state.config.filter.values.all" ng-click="state.config.filter.values.all = true"> |
| <i class="fa fa-filter"></i> Display all config options |
| </button> |
| </p> |
| </div> |
| </div> |
| |
| <form name="formSpecConfig" novalidate class="lightweight"> |
| <div ng-repeat="item in (filteredItems = (model.miscData.get('config') | specEditorConfig:state.config.filter.values:model | filter:{name:state.config.search} | orderBy:+priority)) track by item.name "> |
| <div class="form-group" ng-class="{'has-error': (model.issues | filter:{ref: item.name}:true).length > 0, 'used': config[item.name] !== undefined}" |
| ng-switch="getConfigWidgetMode(item)" |
| tabindex="1" |
| auto-focus="state.config.focus === item.name" |
| auto-focus-listen-to-window="true" |
| auto-focus-not-if-within="true" |
| ng-focus="specEditor.recordFocus(item)" |
| on-enter="specEditor.advanceControlInFormGroup"> |
| <div ng-if="specEditor.getCustomConfigWidgetMode(item) === 'enabled'" class="custom-config-widget"> |
| <ng-include src="specEditor.getCustomConfigWidgetTemplate(item)" class="custom-config-widget"/> |
| </div> |
| |
| <!-- have to hide it; excluding it conditionally via if doesn't play nice with switch --> |
| <div ng-show="specEditor.getCustomConfigWidgetMode(item) !== 'enabled'" class="config-flex-row"> |
| <label class="control-label" for="{{item.name}}"> |
| <span class="label-spec-configuration">{{item.label || item.name}}</span> |
| <span class="info-spec-configuration"> |
| <i class="fa fa-fw fa-info-circle" popover-trigger="'mouseenter'" |
| popover-title="{{item.label || item.name}}" |
| uib-popover-template="'blueprint-composer/component/spec-editor/config-info.html'" |
| popover-class="spec-editor-popover" popover-placement="top-left" popover-append-to-body="true"></i> |
| </span> |
| </label> |
| |
| <span class="label-rhs-buttons"> |
| <span class="spacer"> </span> |
| <span class="custom-widget-enable-button" ng-if="specEditor.getCustomConfigWidgetMode(item) !== null"> |
| <i class="fa fa-fw fa-sun-o" ng-click="specEditor.toggleCustomConfigWidgetMode(item)" aria-hidden="true" title="{{specEditor.getCustomConfigWidgetModeTitle(item)}} [{{item.name}}]"></i> |
| <span class="sr-only">{{specEditor.getCustomConfigWidgetModeTitle(item)}} [{{item.name}}]</span> |
| </span> |
| <span class="json-config" ng-class="{'code-mode-active': state.config.codeModeActive[item.name], 'code-mode-forced': state.config.codeModeForced[item.name]}" ng-if="isCodeModeAvailable(item)"> |
| <i class="fa fa-fw fa-code" ng-click="codeModeClick(item)" aria-hidden="true" title="{{getJsonModeTitle(item.name)}} [{{item.name}}]"></i> |
| <span class="sr-only">{{getJsonModeTitle(item.name)}} [{{item.name}}]</span> |
| </span> |
| <span ng-if="specEditor.isDsl(item.name)" class="rhs-buttons-subspan"> |
| <span class="dsl-open-wizard-from-toolbar" ng-if="!state.config.dslViewerManualOverride[item.name]"> |
| <i class="fa fa-fw fa-bolt" ui-sref="main.graphical.edit.dsl({entityId: model._id, for: item.name})" aria-hidden="true" title="Open in DSL editor [{{item.name}}]"></i> |
| <span class="sr-only">Open in DSL editor [{{item.name}}]</span> |
| </span> |
| <span class="dsl-manual-override-editor" ng-class="{ 'dsl-viewer-manual-override': state.config.dslViewerManualOverride[item.name] }"> |
| <i class="fa fa-fw fa-pencil" ng-click="state.config.dslViewerManualOverride[item.name] = !state.config.dslViewerManualOverride[item.name]" aria-hidden="true" title="Edit DSL code [{{item.name}}]"></i> |
| <span class="sr-only">Edit DSL code [{{item.name}}]</span> |
| </span> |
| </span> |
| <span class="remove-spec-configuration" ng-if="config[item.name] !== undefined"> |
| <i class="fa fa-fw fa-eraser" ng-click="model.removeConfig(item.name)" aria-hidden="true" title="Clear configuration [{{item.name}}]"></i> |
| <span class="sr-only">Clear configuration [{{item.name}}]</span> |
| </span> |
| </span> |
| |
| <div class="control-value" ng-class="{ 'inline-control': item.widgetMode==='boolean', 'unset': !defined(config[item.name]), 'has-default': defined(item.defaultValue) && item.defaultValue!=null, 'code-mode-active': state.config.codeModeActive[item.name] }"> |
| <div ng-switch-when="boolean" class="boolean"> |
| <div class="btn-group btn-block" role="group"> |
| <button type="button" class="btn btn-xs btn-default" ng-class="{'btn-success active': config[item.name] === false, 'active': config[item.name] === undefined && item.defaultValue === false}" ng-click="config[item.name] = false" ng-focus="specEditor.recordFocus(item)">false</button> |
| <button type="button" class="btn btn-xs btn-default" ng-class="{'btn-success active': config[item.name] === true, 'active': config[item.name] === undefined && item.defaultValue === true}" ng-click="config[item.name] = true" ng-focus="specEditor.recordFocus(item)">true</button> |
| <span class="input-group-btn dsl-wizard-button" ng-if="specEditor.isDslWizardButtonAllowed(item.name)"> |
| <a ui-sref="main.graphical.edit.dsl({entityId: model._id, for: item.name})" class="btn btn-xs btn-default" ng-class="{'btn-success active': config[item.name].length > 0}" title="Open in DSL editor" ng-focus="specEditor.recordFocus(item)"><i class="fa fa-bolt"></i></a> |
| </span> |
| </div> |
| </div> |
| |
| <span class="main-control span-for-rounded-edge"> |
| <select ng-switch-when="java.lang.Enum" |
| ng-model="config[item.name]" |
| ng-options="s.value as (s.description + (item.defaultValue === s.value ? ' --- default' : '')) for s in item.possibleValues" |
| ng-focus="specEditor.recordFocus(item)" |
| class="form-control rounded-edge" |
| name="{{item.name}}" |
| id="{{item.name}}"></select> |
| </span> |
| |
| <div ng-switch-when="map" |
| ng-init="expandMode = 'default'" class="collection" |
| ng-class="{ 'open-when-unfocused': expandMode=='open' }"> |
| <p class="collection-toggle" ng-click="expandMode = cycleExpandMode(expandMode, 'map', item, state)" ng-focus="specEditor.recordFocus(item)" |
| ng-class="{ 'has-default': item.defaultValue && getObjectSize(item.defaultValue) }"> |
| <i class="fa collection-caret" ng-class="{'fa-caret-square-o-down': expandMode=='closed', 'fa-caret-square-o-up': expandMode=='open', 'caret-default': expandMode=='default' }" aria-hidden="true" title="{{expandMode=='closed' ? 'Unpin' : expandMode=='open' ? 'Close (pin)' : 'Open (pin)'}} map"></i> |
| <span class="sr-only">{{expandMode=='closed' ? 'Unpin' : expandMode=='open' ? 'Close (pin)' : 'Open (pin)'}} map</span> |
| <ng-pluralize count="getObjectSize(config[item.name])" |
| when="{'0': 'No entries', |
| 'one': '{} entry', |
| 'other': '{} entries'}"></ng-pluralize> |
| <span ng-if="!defined(config[item.name]) && getObjectSize(item.defaultValue)"> |
| (default <ng-pluralize count="getObjectSize(item.defaultValue)" |
| when="{'0': 'no entries', |
| 'one': '{} entry', |
| 'other': '{} entries'}"></ng-pluralize>) |
| </span> |
| </p> |
| <ul class="collection-map" |
| ng-class="{'default-collapse': expandMode=='default', 'collapse': expandMode=='closed'}"> |
| <li ng-repeat="(mapKey, mapValue) in config[item.name] track by mapKey" class="collection-item"> |
| <span class="collection-item-shrink collection-map-key"> |
| <i ng-click="onDeleteMapProperty(config[item.name], mapKey)" class="fa fa-fw fa-times remove-spec-configuration" aria-hidden="true" title="Remove property [{{mapKey}}]"></i> |
| <span class="sr-only">Remove property [{{mapKey}}]</span> |
| {{mapKey}} |
| </span> |
| <div class="collection-item-grow"> |
| <span class="input-group"> |
| <span class="main-control span-for-rounded-edge"> |
| <input type="text" ng-model="config[item.name][mapKey]" class="form-control rounded-edge" placeholder="(empty)" |
| ng-focus="specEditor.recordFocus(item)" |
| on-enter="specEditor.advanceControlInFormGroup" /> |
| </span> |
| <span class="input-group-btn dsl-wizard-button rounded-edge" ng-if="specEditor.isDslWizardButtonAllowed(item.name, mapKey)"> |
| <a ui-sref="main.graphical.edit.dsl({entityId: model._id, for: item.name, index: mapKey})" class="btn btn-default" title="Open in DSL editor"><i class="fa fa-bolt"></i></a> |
| </span> |
| </span> |
| </div> |
| </li> |
| <li class="collection-item collection-add input-group" ng-class="{'nonempty': nonempty(config[item.name])}"> |
| <span class="main-control span-for-rounded-edge"> |
| <input ng-model="newKey" type="text" placeholder="Add property key" class="form-control rounded-edge" |
| ng-focus="specEditor.recordFocus(item)" |
| on-enter="specEditor.advanceOutToFormGroupInPanel" ng-blur="onAddMapProperty(item.name, newKey, $event); newKey = '';" required /> |
| </span> |
| <span class="input-group-btn dsl-wizard-button rounded-edge" ng-if="specEditor.isDslWizardButtonAllowed(item.name, null, newKey)"> |
| <a ui-sref="main.graphical.edit.dsl({entityId: model._id, for: item.name})" class="btn btn-default" title="Open in DSL editor"><i class="fa fa-bolt"></i></a> |
| </span> |
| </li> |
| </ul> |
| </div> |
| |
| <div ng-switch-when="array" ng-switch-when-separator="|" |
| ng-init="expandMode = 'default'" class="collection" |
| ng-class="{ 'open-when-unfocused': expandMode=='open' }"> |
| <p class="collection-toggle" ng-click="expandMode = cycleExpandMode(expandMode, 'map', item, state)" ng-focus="specEditor.recordFocus(item)" |
| ng-class="{ 'has-default': item.defaultValue && item.defaultValue.length }"> |
| <i class="fa collection-caret" ng-class="{'fa-caret-square-o-down': expandMode=='closed', 'fa-caret-square-o-up': expandMode=='open', 'caret-default': expandMode=='default' }" aria-hidden="true" title="{{expandMode=='closed' ? 'Unpin' : expandMode=='open' ? 'Close (pin)' : 'Open (pin)'}} list"></i> |
| <span class="sr-only">{{expandMode=='closed' ? 'Unpin' : expandMode=='open' ? 'Close (pin)' : 'Open (pin)'}} list</span> |
| <ng-pluralize count="config[item.name] ? config[item.name].length : 0" |
| when="{'0': 'No entries', |
| 'one': '{} entry', |
| 'other': '{} entries'}"></ng-pluralize> |
| <span ng-if="!defined(config[item.name]) && item.defaultValue && item.defaultValue.length"> |
| (default <ng-pluralize count="item.defaultValue.length" |
| when="{'0': 'no entries', |
| 'one': '{} entry', |
| 'other': '{} entries'}"></ng-pluralize>) |
| </span> |
| </p> |
| <ul class="collection-list" |
| ng-class="{'default-collapse': expandMode=='default', 'collapse': expandMode=='closed'}"> |
| <li ng-repeat="value in config[item.name] track by $index" class="collection-item"> |
| <span class="collection-item-shrink"> |
| <i ng-click="onDeleteListItem(config[item.name], $index)" class="fa fa-fw fa-times remove-spec-configuration" aria-hidden="true" title="Remove item [{{value}}]"></i> |
| <span class="sr-only">Remove item [{{value}}]</span> |
| </span> |
| <div class="collection-item-grow"> |
| <span class="input-group"> |
| <span class="main-control span-for-rounded-edge"> |
| <input type="text" ng-model="config[item.name][$index]" class="form-control rounded-edge" placeholder="(empty)" |
| ng-focus="specEditor.recordFocus(item)" |
| on-enter="specEditor.advanceControlInFormGroup" /> |
| </span> |
| <span class="input-group-btn dsl-wizard-button rounded-edge" ng-if="specEditor.isDslWizardButtonAllowed(item.name, $index)" ng-focus="specEditor.recordFocus(item)"> |
| <a ui-sref="main.graphical.edit.dsl({entityId: model._id, for: item.name, index: $index})" class="btn btn-default" title="Open in DSL editor"><i class="fa fa-bolt"></i></a> |
| </span> |
| </span> |
| </div> |
| </li> |
| <li class="collection-item collection-add input-group" ng-class="{'nonempty': config[item.name].length>0}"> |
| <span class="input-group"> |
| <span class="main-control span-for-rounded-edge"> |
| <input ng-model="newItem" type="text" placeholder="Add item" class="form-control rounded-edge" auto-focus="expandMode != 'closed'" |
| ng-focus="specEditor.recordFocus(item)" |
| on-enter="specEditor.advanceOutToFormGroupInPanel" ng-blur="onAddListItem(item.name, newItem, $event, $element); newItem = '';" required /> |
| </span> |
| <span class="input-group-btn dsl-wizard-button rounded-edge" ng-if="specEditor.isDslWizardButtonAllowed(item.name, -1, newItem)"> |
| <a ui-sref="main.graphical.edit.dsl({entityId: model._id, for: item.name, index: config[item.name].length})" class="btn btn-default" title="Open in DSL editor"><i class="fa fa-bolt"></i></a> |
| </span> |
| </span> |
| </li> |
| </ul> |
| </div> |
| |
| <div ng-switch-when="org.apache.brooklyn.api.entity.EntitySpec" ng-init="adjunct = config[item.name][REPLACED_DSL_ENTITYSPEC]"> |
| <div class="spec-adjunct" ng-if="config[item.name][REPLACED_DSL_ENTITYSPEC]"> |
| <a ui-sref="main.graphical.edit.spec({entityId: model._id, specId: adjunct._id})" |
| class="open-entity-spec" |
| title="Open in spec editor" |
| ng-focus="specEditor.recordFocus(item)"></a> |
| <ng-include src="'blueprint-composer/component/spec-editor/adjunct.html'"></ng-include> |
| </div> |
| <a ng-if="!config[item.name][REPLACED_DSL_ENTITYSPEC]" ui-sref="main.graphical.edit.add({entityId: model._id, family: 'spec', configKey: item.name})" class="no-spec"> |
| (no spec set) |
| </a> |
| </div> |
| |
| <div class="input-group" ng-switch-default> |
| <span class="main-control span-for-rounded-edge"> |
| <textarea ng-model="config[item.name]" class="form-control rounded-edge" name="{{item.name}}" id="{{item.name}}" auto-grow |
| placeholder="{{defined(config[item.name]) ? null : item.defaultValue=='' || item.defaultValue==null ? '(empty)' : item.defaultValue}}" |
| ng-focus="specEditor.recordFocus(item)" on-enter="specEditor.advanceOutToFormGroupInPanel"></textarea> |
| </span> |
| <span class="input-group-btn dsl-wizard-button rounded-edge" ng-if="specEditor.isDslWizardButtonAllowed(item.name)"> |
| <a ui-sref="main.graphical.edit.dsl({entityId: model._id, for: item.name})" class="btn btn-default" title="Open in DSL editor"><i class="fa fa-bolt"></i></a> |
| </span> |
| </div> |
| |
| <dsl-viewer dsl="model.config.get(item.name)" ng-switch-when="dsl-viewer"></dsl-viewer> |
| |
| </div> |
| |
| <small ng-repeat="issue in model.issues | filter:{ref: item.name}:true" class="help-block issue" ng-bind-html="issue.message"></small> |
| </div> |
| |
| </div> |
| </div> |
| </form> |
| </div> |
| </br-collapsible> |
| |
| <!-- ENTITY LOCATION --> |
| <ng-include src="'blueprint-composer/component/spec-editor/section-locations.html'"></ng-include> |
| <script type="text/ng-template" id="blueprint-composer/component/spec-editor/section-locations.html" defer-to-preexisting-id="true"> |
| <br-collapsible ng-if="[FAMILIES.ENTITY, FAMILIES.SPEC].indexOf(model.family) > -1" state="state.location.open"> |
| <heading> |
| Location |
| <span ng-if="(model.issues | filter:{group:'location'}).length> 0" class="badge" ng-class="getBadgeClass((model.issues | filter:{group:'location'}))">{{(model.issues | filter:{group:'location'}).length}}</span> |
| </heading> |
| |
| <div class="spec-location"> |
| <div ng-repeat="issue in model.issues | filter:{group:'location'}" class="alert" ng-class="{'alert-warning': issue.level.id === 'warn', 'alert-danger': issue.level.id === 'error'}" role="alert"> |
| <span ng-bind-html="issue.message"></span> |
| </div> |
| <div class="spec-empty-state" ng-if="!model.hasLocation()"> |
| <h4>No location attached</h4> |
| <p ng-if="!model.hasLocation() && model.hasInheritedLocation()">However, location <strong class="text-primary">{{model.getInheritedLocation()}}</strong> has been attached on an ancestor.</p> |
| <p><a ui-sref="main.graphical.edit.add({entityId: model._id, family: 'location'})" class="btn btn-sm btn-success"><i class="fa fa-plus"></i> Attach a location</a></p> |
| </div> |
| <div ng-if="model.hasLocation()"> |
| <p ng-repeat="issue in state.issues | filter:{group:'location'}" class="alert alert-{{issue.severity}}"> |
| <em ng-bind-html="issue.message"></em> |
| </p> |
| <p>Will be deployed to: <strong>{{model.miscData.get('locationName')}}</strong></p> |
| <a class="btn btn-default" ui-sref="main.graphical.edit.add({entityId: model._id, family: 'location'})">Change location</a> |
| <button class="btn btn-danger btn-link" ng-click="model.clearIssues({group: 'location'}).removeLocation()">Remove</button> |
| </div> |
| </div> |
| </br-collapsible> |
| </script> |
| |
| <!-- ENTITY POLICIES --> |
| <ng-include src="'blueprint-composer/component/spec-editor/section-policies.html'"></ng-include> |
| <script type="text/ng-template" id="blueprint-composer/component/spec-editor/section-policies.html" defer-to-preexisting-id="true"> |
| <br-collapsible ng-if="[FAMILIES.ENTITY, FAMILIES.SPEC].indexOf(model.family) > -1" state="state.policy.open"> |
| <heading> |
| Policies |
| <span ng-if="getPoliciesIssues().length> 0" class="badge" ng-class="getBadgeClass(getPoliciesIssues())">{{getPoliciesIssues().length}}</span> |
| |
| <span class="pull-right" ng-show="$parent.stateWrapped.state"> |
| <i class="fa fa-search collapsible-action" title="Filter policies" ng-click="$event.stopPropagation(); $event.preventDefault();" ng-class="{'text-success': state.policy.search.length > 0}" uib-popover-template="'blueprint-composer/component/spec-editor/search-policy.html'" popover-placement="bottom-right" popover-trigger="'outsideClick'"></i> |
| <a class="fa fa-plus collapsible-action" title="Add policy" ui-sref="main.graphical.edit.add({entityId: model._id, family: 'policy'})" ng-click="$event.stopPropagation()" ></a> |
| </span> |
| </heading> |
| |
| <div class="spec-policies"> |
| <div class="spec-empty-state" ng-if="!model.hasPolicies() || filteredPolicies.length === 0 "> |
| <h4 ng-if="!model.hasPolicies()">No policies attached</h4> |
| <h4 ng-if="model.hasPolicies() && filteredPolicies.length === 0">No policies matching the current search</h4> |
| <p> |
| <button class="btn btn-sm btn-default" ng-if="state.policy.search.length > 0" ng-click="state.policy.search = ''">Clear search</button> |
| <a ui-sref="main.graphical.edit.add({entityId: model._id, family: 'policy'})" class="btn btn-sm btn-success"> |
| <i class="fa fa-plus"></i> |
| <span ng-if="!model.hasPolicies()">Attach a policy</span> |
| <span ng-if="model.hasPolicies() && filteredPolicies.length === 0">Attach another policy</span> |
| </a> |
| </p> |
| </div> |
| |
| <div ng-repeat="adjunct in filteredPolicies = (model.getPoliciesAsArray() | specEditorType:state.policy.search) track by adjunct._id" class="spec-policy spec-adjunct"> |
| <a ui-sref="main.graphical.edit.policy({entityId: model._id, policyId: adjunct._id})"></a> |
| <ng-include src="'blueprint-composer/component/spec-editor/adjunct.html'"></ng-include> |
| </div> |
| </div> |
| </br-collapsible> |
| </script> |
| |
| <!-- ENTITY ENRICHERS --> |
| <ng-include src="'blueprint-composer/component/spec-editor/section-enrichers.html'"></ng-include> |
| <script type="text/ng-template" id="blueprint-composer/component/spec-editor/section-enrichers.html" defer-to-preexisting-id="true"> |
| <br-collapsible ng-if="[FAMILIES.ENTITY, FAMILIES.SPEC].indexOf(model.family) > -1" state="state.enricher.open"> |
| <heading> |
| Enrichers |
| <span ng-if="getEnrichersIssues().length> 0" class="badge" ng-class="getBadgeClass(getEnrichersIssues())">{{getEnrichersIssues().length}}</span> |
| |
| <span class="pull-right" ng-show="$parent.stateWrapped.state"> |
| <i class="fa fa-search collapsible-action" title="Search enrichers" ng-click="$event.stopPropagation(); $event.preventDefault();" ng-class="{'text-success': state.enricher.search.length > 0}" uib-popover-template="'blueprint-composer/component/spec-editor/search-enricher.html'" popover-placement="bottom-right" popover-trigger="'outsideClick'"></i> |
| <a class="fa fa-plus collapsible-action" title="Add enricher" ui-sref="main.graphical.edit.add({entityId: model._id, family: 'enricher'})" ng-click="$event.stopPropagation()" ></a> |
| </span> |
| </heading> |
| |
| <div class="spec-enrichers"> |
| <div class="spec-empty-state" ng-if="!model.hasEnrichers() || filteredEnrichers.length === 0"> |
| <h4 ng-if="!model.hasEnrichers()">No Enrichers attached</h4> |
| <h4 ng-if="model.hasEnrichers() && filteredEnrichers.length === 0">No enrichers matching the current search</h4> |
| <p> |
| <button class="btn btn-sm btn-default" ng-if="state.enricher.search.length > 0" ng-click="state.enricher.search = ''">Clear search</button> |
| <a ui-sref="main.graphical.edit.add({entityId: model._id, family: 'enricher'})" class="btn btn-sm btn-success"> |
| <i class="fa fa-plus"></i> |
| <span ng-if="!model.hasEnrichers()">Attach an enricher</span> |
| <span ng-if="model.hasEnrichers() && filteredEnrichers.length === 0">Attach another enricher</span> |
| </a> |
| </p> |
| </div> |
| |
| <div ng-repeat="adjunct in filteredEnrichers = (model.getEnrichersAsArray() | specEditorType:state.enricher.search) track by adjunct._id" class="spec-enricher spec-adjunct"> |
| <a ui-sref="main.graphical.edit.enricher({entityId: model._id, enricherId: adjunct._id})"></a> |
| <ng-include src="'blueprint-composer/component/spec-editor/adjunct.html'"></ng-include> |
| </div> |
| </div> |
| </br-collapsible> |
| </script> |
| |
| <ng-include src="'blueprint-composer/component/spec-editor/section-others.html'"></ng-include> |
| <script type="text/ng-template" id="blueprint-composer/component/spec-editor/section-others.html" defer-to-preexisting-id="true"> |
| </script> |
| |
| |
| <!-- CONFIG INFO TEMPLATE :: START --> |
| <script type="text/ng-template" id="blueprint-composer/component/spec-editor/config-info.html" defer-to-preexisting-id="true"> |
| <div class="config-item-quick-info"> |
| <div class="quick-info-metadata"> |
| <p><i class="mini-icon fa fa-fw fa-cog"></i> <samp class="type-symbolic-name">{{item.name}}</samp> |
| <span class="config-type label-color column-for-type oneline label label-success">{{item.type}}</span></p> |
| </div> |
| <p class="quick-info-description" ng-if="item.description" ng-bind-html="specEditor.descriptionHtml(item.description)"></p> |
| <div class="quick-info-metadata config-default" ng-if="item.defaultValue"></i>Default value: <samp>{{item.defaultValue}}</samp></div> |
| <div class="quick-info-metadata config-required" ng-if="item.constraints.required"><i>This field is required.</div> |
| </div> |
| |
| </script> |
| <!-- CONFIG INFO TEMPLATE :: START--> |
| |
| <!-- SEARCH POLICY TEMPLATE :: START --> |
| <script type="text/ng-template" id="blueprint-composer/component/spec-editor/search-policy.html" defer-to-preexisting-id="true"> |
| <div ng-click="$event.stopPropagation(); $event.preventDefault();"> |
| <input ng-model="state.policy.search" type="text" class="form-control" placeholder="Search for a policy" auto-focus blur-on-enter /> |
| </div> |
| </script> |
| <!--SEARCH POLICY TEMPLATE :: START--> |
| |
| <!-- SEARCH ENRICHER TEMPLATE :: START --> |
| <script type="text/ng-template" id="blueprint-composer/component/spec-editor/search-enricher.html" defer-to-preexisting-id="true"> |
| <div ng-click="$event.stopPropagation(); $event.preventDefault();"> |
| <input ng-model="state.enricher.search" type="text" class="form-control" placeholder="Search for an enricher" auto-focus blur-on-enter /> |
| </div> |
| </script> |
| <!--SEARCH ENRICHER TEMPLATE :: START--> |
| |
| <!--TYPEAHEAD TEMPLATE :: START--> |
| <script type="text/ng-template" id="blueprint-composer/component/spec-editor/config-item.html" defer-to-preexisting-id="true"> |
| <div class="dropdown-item" ng-init="item = match.model"> |
| <div class="dropdown-row"> |
| <span ng-bind-html="match.model.name | uibTypeaheadHighlight:query" class="config-name"></span> |
| <i class="fa fa-fw fa-asterisk" ng-if="match.model.constraints.required"></i> |
| <i class="fa fa-fw fa-eye-slash" ng-if="match.model.isHidden"></i> |
| <!-- previously showed just the label; now show just the name as that's what is inserted. |
| ideally would show label and description as popover (reusing ConfigInfoTemplate), but due to bugs in popover |
| we can't easily get that to work. --> |
| </div> |
| </div> |
| </script> |
| <!--TYPEAHEAD TEMPLATE :: END--> |
| |
| <!--ADJUNCT TEMPLATE :: START--> |
| <script type="text/ng-template" id="blueprint-composer/component/spec-editor/adjunct.html" defer-to-preexisting-id="true"> |
| <div class="media" ng-class="{'has-issues': adjunct.hasIssues()}"> |
| <div class="media-left media-middle"> |
| <img ng-src="{{adjunct.icon}}" alt="{{adjunct | entityName}} logo" class="media-object" /> |
| </div> |
| <div class="media-body"> |
| <div> |
| {{adjunct.miscData.get('typeName')}} |
| <span ng-if="adjunct.issues.length > 0" > • <small class="text-danger"> |
| <em> |
| <i class="fa fa-ban"></i> |
| <ng-pluralize count="adjunct.issues.length" when="{ |
| 'one': '{} issue', |
| 'other': '{} issues'}"> |
| </ng-pluralize> |
| </em> |
| </small></span> |
| </div> |
| <i ng-if="['POLICY', 'ENRICHER'].indexOf(adjunct.family.id) > -1" class="fa fa-trash remove-spec-adjunct" ng-click="removeAdjunct($event, adjunct)" title="Remove"></i> |
| <a ng-if="adjunct.family.id === 'SPEC'" ui-sref="main.graphical.edit.add({entityId: model._id, family: 'spec', configKey: item.name})" class="update-spec-adjunct" title="Change type"> |
| <i class="fa fa-exchange"></i> |
| </a> |
| </div> |
| </div> |
| </script> |
| <!--ADJUNCT TEMPLATE :: END--> |