Commit 2e9fd5db authored by jeromecambon's avatar jeromecambon Committed by benjaminParisel

feat(view edit widget): view a Bonita widget or edit a Custom widget (#2680)

Covers [UID-63](https://bonitasoft.atlassian.net/browse/UID-63)
parent df8bc20b
......@@ -6,7 +6,7 @@
</th>
<th class="col-xs-4 Property-actions" colspan="2">
<button class="btn btn-default btn-data--help" ng-click="vm.openHelp('widget')" title="{{'Open help' | translate}}"><i class="fa fa-question-circle"></i></button>
<button id="addasset" title="Add a new asset" class="btn btn-bonita-primary" ng-click="vm.openAssetPopup()">
<button id="addasset" title="Add a new asset" class="btn btn-bonita-primary" ng-disabled="!widget.custom" ng-click="vm.openAssetPopup()">
<i class="fa fa-plus"></i>
<span translate>Add</span>
</button>
......@@ -23,8 +23,8 @@
<tbody>
<tr ng-repeat="asset in vm.component.assets | orderBy:'order' as results">
<td>
<a ng-click="vm.decrementOrderAsset(asset)" ng-if="!$first" title="{{ 'Move asset up' | translate }}"><i class="fa fa-arrow-up asset-ordering-action clickable"></i></a>
<a ng-click="vm.incrementOrderAsset(asset)" ng-if="!$last" title="{{ 'Move asset down' | translate }}"><i class="fa fa-arrow-down asset-ordering-action clickable"></i></a>
<a ng-click="vm.decrementOrderAsset(asset)" ng-if="!$first && widget.custom" title="{{ 'Move asset up' | translate }}"><i class="fa fa-arrow-up asset-ordering-action clickable"></i></a>
<a ng-click="vm.incrementOrderAsset(asset)" ng-if="!$last && widget.custom" title="{{ 'Move asset down' | translate }}"><i class="fa fa-arrow-down asset-ordering-action clickable"></i></a>
</td>
<td>{{asset.name}}</td>
<td>{{asset.type | assetType}}</td>
......@@ -36,11 +36,11 @@
ng-if="vm.isViewable(asset)" ng-click="vm.openAssetPreviewPopup(asset)">
<i class="fa fa-search"></i>
</button>
<button class="btn btn-bonita-default" ng-click="vm.openAssetEditPopup(asset)"
<button id="editAsset" class="btn btn-bonita-default" ng-disabled="!widget.custom" ng-click="vm.openAssetEditPopup(asset)"
title="{{ 'Update asset' | translate }}" ng-if="vm.isEditable(asset)">
<i class="fa fa-pencil"></i>
</button>
<button class="btn btn-bonita-default" ng-click="vm.delete(asset)" title="{{ 'Delete asset' | translate }}">
<button id="deleteAsset" class="btn btn-bonita-default" ng-disabled="!widget.custom" ng-click="vm.delete(asset)" title="{{ 'Delete asset' | translate }}">
<i class="fa fa-trash"></i>
</button>
</td>
......
......@@ -8,14 +8,15 @@
<i class="ui-icon ui-designer"></i>
</a>
<span class="EditorHeader-brand" translate>
Custom widget editor
widget editor
</span>
<h3 class="EditorHeader-name EditorHeader-name--custom">
<identicon name="{{widget.id}}" size="30" foreground-color="[203, 213, 225, 255]" background-color="[0,0,0,0]"></identicon>
{{widget.name}}
</h3>
<div class="EditorHeader-actions">
<div class="btn-group" uib-dropdown>
<button ng-if="!widget.custom" id="saveas-bonita" type="button" class="btn btn-bonita-primary" ng-click="saveAs(widget)" translate>Save as...</button>
<div ng-if="widget.custom" class="btn-group" uib-dropdown>
<button id="save" type="button" class="btn btn-bonita-primary" ng-click="save()" ng-disabled="!isPageDirty(widget)" translate>Save</button>
<button type="button" class="btn btn-bonita-primary uib-dropdown-toggle" uib-dropdown-toggle>
<span class="fa fa-caret-down"></span>
......@@ -27,6 +28,7 @@
</div>
<button type="button"
id="export"
ng-disabled="!widget.custom"
class="btn btn-bonita-primary"
ng-click="saveAndExport()"
title="{{'Export'|translate}}">
......@@ -51,15 +53,15 @@
<translate>Description</translate>
<i class="fa fa-info-circle CustomEditor-helper" tooltip-placement="bottom" uib-tooltip="{{'This description will be displayed as a tooltip in the palette' | translate }}" tooltip-append-to-body="true"></i>
</h4>
<textarea class="form-control textarea--widget" ng-attr-placeholder="{{ 'Widget description' | translate }}" ng-model="widget.description"></textarea>
<textarea class="form-control textarea--widget" ng-disabled="!widget.custom" ng-attr-placeholder="{{ 'Widget description' | translate }}" ng-model="widget.description"></textarea>
</div>
<div>
<h4 class="CustomEditor-section" translate>Template</h4>
<ace-editor class="ace-editor--widget" mode="html" ng-model="widget.template" id="template"></ace-editor>
<ace-editor id="template" class="ace-editor--widget" ng-class="{'ace_editor-readonly': !widget.custom}" mode="html" readonly="{{!widget.custom}}" ng-model="widget.template"></ace-editor>
</div>
<div>
<h4 class="CustomEditor-section" translate>Controller</h4>
<ace-editor class="ace-editor--widget" mode="javascript" ng-model="widget.controller" id="controller"></ace-editor>
<ace-editor id="controller" class="ace-editor--widget" ng-class="{'ace_editor-readonly': !widget.custom}" mode="javascript" readonly="{{!widget.custom}}" ng-model="widget.controller"></ace-editor>
</div>
</form>
</div>
......@@ -72,7 +74,7 @@
<translate>Required angular modules</translate>
<i class="fa fa-info-circle CustomEditor-helper" uib-tooltip="{{'Extra angular modules needed by this custom widget (comma separated)' | translate }}" tooltip-append-to-body="true"></i>
</h4>
<input type="text" class="form-control" id="requiredModules" ng-model="widget.requiredModules" ng-list>
<input type="text" class="form-control" id="requiredModules" ng-disabled="!widget.custom" ng-model="widget.requiredModules" ng-list>
</div>
<table class="table table-striped">
......@@ -81,7 +83,7 @@
<h4 class="CustomEditor-section" translate>Properties</h4>
</th>
<th class="col-xs-2 Property-actions">
<button id="create" title="Create a new property" class="btn btn-bonita-primary" ng-click="createOrUpdate()">
<button id="create" title="Create a new property" class="btn btn-bonita-primary" ng-disabled="!widget.custom" ng-click="createOrUpdate()">
<i class="fa fa-plus"></i>
<span translate>Create</span>
</button>
......@@ -98,8 +100,8 @@
<div ng-if="property.bond !== 'variable'"><small translate>Default value</small>: {{ property.defaultValue }}</div>
</td>
<td class="col-xs-2 Property-actions">
<button class="btn btn-bonita-default" title="Update property" ng-click="createOrUpdate(property)"><i class="fa fa-pencil"></i></button>
<button class="btn btn-bonita-default" title="Delete property" ng-click="deleteParam(property)"><i class="fa fa-trash"></i></button>
<button id="editProperty" class="btn btn-bonita-default" title="Update property" ng-disabled="!widget.custom" ng-click="createOrUpdate(property)"><i class="fa fa-pencil"></i></button>
<button id="deleteProperty" class="btn btn-bonita-default" title="Delete property" ng-disabled="!widget.custom" ng-click="deleteParam(property)"><i class="fa fa-trash"></i></button>
</td>
</tr>
</tbody>
......
......@@ -5,8 +5,11 @@
<div class="modal-body">
<uib-tabset class="tabs-left" active="tabContainer.activeTab">
<uib-tab id="help-general" heading="{{ 'General' | translate }}" index="'general'">
<p translate>If the standard widgets do not meet your needs, you can create a custom widget to match exactly what you want to. After creation, a custom widget is available in the palette for designing pages, forms or fragments.</p>
<p translate>Custom widget implementation is based on the AngularJS framework.</p>
<p translate>This page allows you to view a standard widget, or edit a custom widget.</p>
<p translate>If the standard widget does not meet your needs, you can create a custom widget to match exactly what you want to.
To do this, clone the standard widget by saving it with a different name, and modify it.
After creation, the custom widget is available in the palette for designing pages, forms or fragments.</p>
<p translate>Widget implementation is based on the AngularJS framework.</p>
<p translate>For more information, see the AngularJS guide on
<a href="https://docs.angularjs.org/guide/templates">templates</a> and
<a href="https://docs.angularjs.org/guide/controller">controllers</a>.</p>
......@@ -15,24 +18,25 @@
</uib-tab>
<uib-tab id="help-template" heading="{{ 'Template' | translate }}" index="'template'">
<p translate>The custom widget HTML template is defined here.</p>
<p translate>The widget HTML template is defined here.</p>
<p translate>You can use standard HTML tags and AngularJS built-in directives, scope and interpolation system.</p>
<p translate>Custom widget properties defined on the right can be used as variables in a templates with properties.newProperty.</p>
<p translate>Widget properties defined on the right can be used as variables in a template with properties.newProperty.</p>
<p translate>Functions exposed in the controller can be used with ctrl.newFunction().</p>
<p translate>You can use the <i>environment</i> property injected in the scope when inside the whiteboard editor. It allows to create a mockup display for the whiteboard as the real use data will not be available.</p>
<p translate>You can use the <i>environment</i> property injected in the scope when inside the whiteboard editor.
It allows to create a mockup display for the whiteboard as the real use data will not be available.</p>
</uib-tab>
<uib-tab id="help-controller" heading="{{ 'Controller' | translate }}" index="'controller'">
<p translate>The controller is a JavaScript function that augments the AngularJS scope and exposes functions that can be used in the custom widget template.</p>
<p translate>The controller is a JavaScript function that augments the AngularJS scope and exposes functions that can be used in the widget template.</p>
<p translate>Custom widget properties defined on the right can be used as variables in a controller with $scope.properties.</p>
<p translate>Widget properties defined on the right can be used as variables in a controller with $scope.properties.</p>
<p translate>To use AngularJS standard services, you must declare them in the main function arguments.</p>
<p translate>You can leave the controller empty if you do not need it.</p>
<p translate>Controller can be left empty if not needed.</p>
</uib-tab>
<uid-l10n-help-tab></uid-l10n-help-tab>
<uib-tab id="help-migration" heading="{{ 'Migration' | translate }}" index="'migration'">
......
......@@ -6,13 +6,21 @@
popover-trigger="none" popover-is-open="widgetHelpPopover.isOpen" popover-placement="left-top" popover-class="PropertyPanel-help-popover">
<i class="fa fa-question-circle"></i>
</button>
<button ng-if="currentComponent.$$widget.type !== 'container'"
ng-click="saveAndEditCustomWidget(currentComponent.$$widget.id)" class="btn btn-xs btn-bonita-edit-widget PropertyPanel-edit-btn"
id="edit-widget"
tooltip-placement="top-right" uib-tooltip="{{ 'Edit widget' | translate }}"
tooltip-append-to-body="true">
<i class="fa fa-pencil"></i>
</button>
<div id="action" class="btn-group PropertyPanel-widget-action-btn" uib-dropdown>
<button ng-if="currentComponent.$$widget.type !== 'container' && currentComponent.type !== 'fragment'" id="widgetActionButton" type="button" class="btn btn-xs btn-bonita-action-widget" uib-dropdown-toggle
tooltip-placement="top-right" uib-tooltip="{{ 'Widget actions' | translate }}"
tooltip-append-to-body="true">
<span class="fa fa-ellipsis-v"/>
</button>
<ul class="dropdown-menu dropdown-menu-right PropertyPanel-widget-action-menu" role="menu" aria-labelledby="typeButton">
<li><a ng-if="!currentComponent.$$widget.custom" id="viewAction" class="clickable PropertyPanel-widget-action-item"
ng-click="saveAndEditCustomWidget(currentComponent.$$widget.id)" translate>View...</a></li>
<li><a ng-if="currentComponent.$$widget.custom" id="editAction" class="clickable PropertyPanel-widget-action-item"
ng-click="saveAndEditCustomWidget(currentComponent.$$widget.id)" translate>Edit...</a></li>
<li><a id="switchAction" class="clickable PropertyPanel-widget-action-item" ng-click="" translate>Switch...</a></li>
</ul>
</div>
<h3 class="PropertyPanel-title">
{{ currentComponent.$$widget.name }}
</h3>
......
......@@ -123,6 +123,16 @@ PropertyPanel-help-popover-body {
margin-right:7px;
}
.PropertyPanel-widget-action-btn {
margin-top: 17px;
margin-bottom: 15px;
font-size: 14px;
float: right;
}
.PropertyPanel-widget-action-menu {
min-width: 120px;
}
.PropertyPanel-content {
flex: 1;
overflow-x: hidden;
......
......@@ -116,7 +116,7 @@
}
}
.btn-bonita-edit-widget {
.btn-bonita-action-widget {
.button-variant(@btn-bonita-edit-widget-color, @btn-bonita-edit-widget-bg, @btn-bonita-edit-widget-border);
&:hover {
......@@ -170,6 +170,7 @@
@color-custom-editor-section: #E21938;
@color-custom-editor-helper: #0B4361;
@color-custom-editor-widget-name: #CBD5E1;
@color-custom-editor-disable-background: #EEEEEE;
/**
......
.ace_editor.ace-editor--widget {
height: 300px;
}
.ace_editor-readonly .ace_content{
cursor: not-allowed;
background-color: @color-custom-editor-disable-background;
}
.textarea--widget {
resize:vertical;
......
......@@ -234,7 +234,117 @@
}
],
assets: []
}, {
},
{
id : 'pbDatePicker',
name : 'Date Picker',
lastUpdate : 1554292993458,
template : '<div ng-class=\"{\n \"form-horizontal\": properties.labelPosition === \"left\" && !properties.labelHidden,\n \"row\": properties.labelPosition === \"top\" && !properties.labelHidden || properties.labelHidden\n }\">\n <div class=\"form-group\">\n <label\n ng-if=\"!properties.labelHidden\"\n ng-class=\"{ \"control-label--required\": properties.required }\"\n class=\"control-label col-xs-{{ !properties.labelHidden && properties.labelPosition === \"left\" ? properties.labelWidth : 12 }}\">\n {{ properties.label | uiTranslate }}\n </label>\n\n <div\n class=\"col-xs-{{ 12 - (!properties.labelHidden && properties.labelPosition === \"left\" ? properties.labelWidth : 0) }}\">\n <p class=\"input-group\">\n <input class=\"form-control\"\n name=\"{{ctrl.name}}\"\n type=\"text\"\n placeholder=\"{{properties.placeholder | uiTranslate}}\"\n ng-model=\"properties.value\"\n ng-readonly=\"properties.readOnly\"\n ng-required=\"properties.required\"\n bs-datepicker\n data-container=\"body\"\n data-autoclose=\"1\"\n data-timezone=\"UTC\"\n date-format=\"{{properties.dateFormat | uiTranslate}}\"\n data-trigger=\"focus\"\n data-start-week=\"{{ctrl.firstDayOfWeek}}\">\n\n <span class=\"input-group-btn\">\n <button ng-if=\"properties.showToday\"\n type=\"button\"\n class=\"btn btn-default today\n {{$form[ctrl.name].$dirty && ($form[ctrl.name].$error.date || $form[ctrl.name].$error.parse ||\n (properties.required && $form[ctrl.name].$error.required)) ? \"btn-invalid\":\"\"}}\"\n ng-click=\"ctrl.setDateToToday()\"\n ng-disabled=\"properties.readOnly\" ui-translate>\n {{properties.todayLabel || \"Today\" | uiTranslate}}\n </button>\n <button type=\"button\"\n class=\"btn btn-default calendar\n {{$form[ctrl.name].$dirty && ($form[ctrl.name].$error.date || $form[ctrl.name].$error.parse ||\n (properties.required && $form[ctrl.name].$error.required)) ? \"btn-invalid\":\"\"}}\"\n ng-click=\"ctrl.openDatePicker()\"\n ng-disabled=\"properties.readOnly\">\n <i class=\"glyphicon glyphicon-calendar\"></i>\n </button>\n </span>\n </p>\n <div ng-messages=\"$form[ctrl.name].$dirty && $form[ctrl.name].$error \"\n ng-messages-include=\"forms-generic-errors.html\" role=\"alert\">\n <div ng-message=\"parse\" ng-if=\"!environment || !environment.editor\" class=\"text-danger\">\n {{ \"This is not a valid date\" | uiTranslate }}\n </div>\n </div>\n </div>\n </div>\n</div>\n\"',
icon : '<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0.000000 0.061756 50.000000 20.000000\"><path fill=\"none\" d=\"M0 .062h50v20H0z\"/><path d=\"M0 .062v20h50v-20zm49 19H1v-18h48z\" fill=\"#fff\"/><g fill=\"#fff\"><path d=\"M20.152 1.864c-.246.143-.308.28-.328.69l-.016.354-.672.02c-.67.018-.67.018-.87.126-.35.193-.538.482-.604.94-.023.164-.032 2.29-.026 6.804l.01 6.564.075.202c.152.395.522.688.964.762.13.02 2.545.03 6.446.024l6.24-.01.19-.08c.23-.102.477-.308.608-.51.21-.322.2-.08.197-5.346 0-2.63-.014-5.638-.026-6.686l-.02-1.902-.095-.206c-.122-.262-.285-.437-.53-.566-.188-.098-.207-.098-.866-.12l-.672-.016-.016-.37c-.017-.335-.024-.38-.11-.496-.283-.402-.91-.346-1.13.098-.027.063-.057.237-.067.436l-.02.332h-7.663l-.017-.367c-.01-.2-.035-.397-.056-.435-.164-.31-.616-.43-.927-.24zm10.955 10.313v4.975l-6.12.01c-4.47.004-6.132-.002-6.15-.03-.022-.046-.032-9.79-.008-9.888.015-.056.33-.06 6.146-.052l6.13.01z\"/><path d=\"M21.842 7.557l-.317.014.01.74.01.74.716.012c.48.003.732-.004.754-.028.024-.025.036-.293.036-.754v-.713h-.252c-.138 0-.337-.007-.442-.01-.105-.007-.338-.007-.514 0zM24.06 7.557l-.203.014-.017.182c-.016.137-.01 1.083.01 1.292 0 .014.337.02.75.018l.743-.01.01-.744.01-.74h-.354c-.198 0-.447-.008-.55-.015-.106-.007-.286-.003-.394.004zM26.247 7.56l-.104.01.01.74.01.74.742.012.744.007.01-.35c.008-.19 0-.53-.01-.758l-.018-.408-.638-.004c-.35 0-.688.004-.747.01zM28.48 7.585c-.01.02-.01.36-.01.75l.01.716.51.012c.277.007.615 0 .746-.01l.235-.025v-1.46l-.136-.003c-.672-.02-1.346-.01-1.356.02zM19.226 10.22c-.01.21-.01.56 0 .77l.016.383.74-.007.74-.01V9.853l-.74-.01-.74-.007zM21.538 9.882c-.01.025-.01.367-.01.758l.01.715.74.01.74.008.023-.314c.015-.176.015-.52 0-.77l-.022-.453h-.734c-.563 0-.736.01-.75.045zM23.876 10.22c-.01.21-.01.56 0 .77l.017.383.74-.007.74-.01V9.853l-.74-.01-.74-.007zM26.19 9.882c-.01.025-.01.367-.01.758l.01.715.74.01.74.008.022-.314c.014-.176.014-.52 0-.77l-.023-.453h-.735c-.563 0-.737.01-.75.045zM28.46 10.22c-.008.21-.008.56 0 .77l.018.383.74-.007.74-.01V9.853l-.74-.01-.74-.007zM19.226 12.34v.726c0 .286.01.545.01.566 0 .035.163.045.713.045.39 0 .73-.014.752-.028.03-.025.04-.2.033-.762l-.01-.73-.743-.01-.747-.007zM21.548 12.165c-.014.01-.024.35-.024.748 0 .726 0 .73.076.747.04.01.38.014.753.01l.684-.01.01-.454c.01-.252.01-.59-.01-.76l-.02-.305h-.726c-.4 0-.736.012-.746.025zM23.876 12.34v.726c0 .286.01.545.01.566 0 .035.164.045.714.045.39 0 .73-.014.753-.028.03-.025.04-.2.033-.762l-.01-.73-.743-.01-.747-.007zM26.198 12.165c-.013.01-.023.35-.023.748 0 .726 0 .73.075.747.04.01.38.014.754.01l.684-.01.01-.454c.01-.252.01-.59-.01-.76l-.02-.305h-.726c-.4 0-.737.012-.747.025zM28.46 12.34v.726c0 .286.01.545.01.566 0 .035.165.045.715.045.39 0 .73-.014.753-.028.03-.025.04-.2.033-.762l-.008-.73-.744-.01-.747-.007zM19.23 14.522c0 .045-.01.384-.01.754v.67h1.522l-.01-.743-.01-.74-.743-.01-.747-.008zM21.525 15.196v.75H23.048l.01-.656c0-.36 0-.695-.01-.75l-.02-.095h-1.5zM23.88 14.522c0 .045-.01.384-.01.754v.67H25.393l-.01-.743-.01-.74-.743-.01-.747-.008zM26.175 15.196v.75H27.698l.01-.656c0-.36 0-.695-.01-.75l-.02-.095h-1.5zM28.465 14.522c0 .045-.01.384-.01.754v.67H29.978l-.01-.743-.01-.74-.743-.01-.747-.008z\"/></g></svg>',
controller : 'function PbDatePickerCtrl($scope, $log, widgetNameFactory, $element, $locale, $bsDatepicker) {\n\n \"rause strict\";\n\n this.name = widgetNameFactory.getName(\"pbDatepicker\");\n this.firstDayOfWeek = ($locale && $locale.DATETIME_FORMATS && $locale.DATETIME_FORMATS.FIRSTDAYOFWEEK) || 0;\n\n $bsDatepicker.defaults.keyboard = false;\n\n this.setDateToToday = function() {\n var today = new Date();\n if(today.getDay() !== today.getUTCDay()) {\n //we need to add this offset for the displayed date to be correct\n if(today.getTimezoneOffset() > 0) {\n today.setTime(today.getTime() - 1440 * 60 * 1000);\n } else if(today.getTimezoneOffset() < 0) {\n today.setTime(today.getTime() + 1440 * 60 * 1000);\n }\n }\n today.setUTCHours(0);\n today.setUTCMinutes(0);\n today.setUTCSeconds(0);\n today.setUTCMilliseconds(0);\n $scope.properties.value = today;\n };\n\n this.openDatePicker = function () {\n $element.find(\"input\")[0].focus();\n };\n\n\n if (!$scope.properties.isBound(\"value\")) {\n $log.error(\"the pbDatepicker property named \"value\" need to be bound to a variable\");\n }\n\n\n}\n',
description : 'Calendar for selecting a date (only)',
custom : false,
order : 10,
properties : [ {
label : 'Read-only',
name : 'readOnly',
type : 'boolean',
defaultValue : false,
bond : 'expression'
}, {
label : 'Required',
name : 'required',
help : 'In the context of a form container, use $form.$invalid as a Boolean to check form validity in a widget property',
type : 'boolean',
defaultValue : false,
bond : 'expression'
}, {
label : 'Label hidden',
name : 'labelHidden',
type : 'boolean',
defaultValue : false,
bond : 'constant'
}, {
label : 'Label',
name : 'label',
showFor : 'properties.labelHidden.value === false',
type : 'text',
defaultValue : 'Date',
bond : 'interpolation'
}, {
label : 'Label position',
name : 'labelPosition',
showFor : 'properties.labelHidden.value === false',
type : 'choice',
defaultValue : 'top',
choiceValues : [ 'left', 'top' ],
bond : 'constant'
}, {
label : 'Label width',
name : 'labelWidth',
showFor : 'properties.labelHidden.value === false',
type : 'integer',
defaultValue : 4,
bond : 'constant',
constraints : {
min : '1',
max : '12'
}
}, {
label : 'Value',
name : 'value',
caption : 'Input: <a href=\"https://en.wikipedia.org/wiki/ISO_8601\" target=\"_blank\">ISO 8601</a> formatted String (yyyy-MM-dd), Date object or Long number <br>Output: Date object (see widget help)',
type : 'text',
bond : 'variable'
}, {
label : 'Technical date format',
name : 'dateFormat',
caption : 'Use the characters: M (month), d (day), y (year)',
type : 'text',
defaultValue : 'MM/dd/yyyy',
bond : 'expression'
}, {
label : 'Date Placeholder',
name : 'placeholder',
caption : 'Includes the localized version of the Technical date format property, to guide the user',
help : 'Short hint that describes the expected input format for the date',
type : 'text',
defaultValue : 'Enter a date (mm/dd/yyyy)',
bond : 'interpolation'
}, {
label : 'Show Today button',
name : 'showToday',
help : 'Display or hide the shortcut button to current day',
type : 'boolean',
defaultValue : true,
bond : 'constant'
}, {
label : 'Today button label',
name : 'todayLabel',
help : 'Can be translated in subscription editions using the asset localization.json',
showFor : 'properties.showToday.value === true',
type : 'text',
defaultValue : 'Today',
bond : 'interpolation'
} ],
assets : [ {
name : 'angular-strap-2.3.9-patched-dateTimePicker-setValidity.compat.min.js',
type : 'js',
order : 1,
external : false
}, {
name : 'angular-strap-2.3.9-patched-dateTimePicker-setValidity.tpl.min.js',
type : 'js',
order : 2,
external : false
} ],
requiredModules : [ 'mgcrea.ngStrap.datepicker' ],
type : 'widget',
hasHelp : true
},
{
'designerVersion': '1.5-SNAPSHOT',
'favorite': false,
'id': 'pbTitle',
......
......@@ -71,7 +71,7 @@ describe('custom widget editor', function() {
expect(properties).toEqual(['qualifier', 'verb']);
});
it('should allow to add a property', function() {
it('if custom only, should allow to add a property', function() {
$('#create').click();
$('#name').sendKeys('newProperty');
......@@ -94,6 +94,10 @@ describe('custom widget editor', function() {
expect($('.modal-body #help').getAttribute('value')).toBe('Tooltip for new property');
expect($('.modal-body #caption').getAttribute('value')).toBe('Caption for new property');
expect($('.modal-body #default').getAttribute('value')).toBe('Default value');
// Standard widget: create button should be disabled
widgetEditor = WidgetEditor.get('pbInput');
expect(element(by.css('#create:disabled')).isPresent()).toBeTruthy();
});
it('should allow to update a property', function() {
......@@ -123,6 +127,11 @@ describe('custom widget editor', function() {
expect(updated.all(by.tagName('div')).get(3).getText()).toBe('Type: choice');
expect(updated.all(by.tagName('div')).get(4).getText()).toBe('Choices: red, green, blue');
expect(updated.all(by.tagName('div')).get(5).getText()).toBe('Default value: red');
// Standard widget: update property should be disabled
widgetEditor = WidgetEditor.get('pbInput');
property = element.all(by.repeater('property in widget.properties')).first();
expect(property.element(by.css('#editProperty:disabled')).isPresent()).toBeTruthy();
});
it('should allow to choose property type only with some bond type while creating/updating a property', function() {
......@@ -171,6 +180,11 @@ describe('custom widget editor', function() {
var properties = getPropertyNamesInList();
expect(properties).not.toContain(firstParamName);
// Standard widget: delete property should be disabled
widgetEditor = WidgetEditor.get('pbInput');
var property = element.all(by.repeater('property in widget.properties')).first();
expect(property.element(by.css('#deleteProperty:disabled')).isPresent()).toBeTruthy();
});
it('should allow to edit a widget template and controller', function() {
......@@ -187,6 +201,11 @@ describe('custom widget editor', function() {
// should go back to root when saved
expect(browser.getCurrentUrl()).toMatch(/.*#\//);
// Standard widget: edit template and controller should be disabled
widgetEditor = WidgetEditor.get('pbInput');
expect(element(by.css('#template:read-only')).isPresent()).toBeTruthy();
expect(element(by.css('#controller:read-only')).isPresent()).toBeTruthy();
});
it('should save a widget as', function() {
......@@ -243,6 +262,13 @@ describe('custom widget editor', function() {
expect(localEditableAsset.element(by.css('button i.fa-search')).isPresent()).toBeFalsy();
expect(localEditableAsset.element(by.css('button i.fa-pencil')).isPresent()).toBeTruthy();
expect(localEditableAsset.element(by.css('button i.fa-trash')).isPresent()).toBeTruthy();
// Standard widget: edit/delete should be disabled
widgetEditor = WidgetEditor.get('pbDatePicker');
assets = widgetEditor.assets().list();
let firstAsset = assets.first();
expect(firstAsset.element(by.css('#editAsset')).isEnabled()).toBeFalsy();
expect(firstAsset.element(by.css('#deleteAsset')).isEnabled()).toBeFalsy();
});
it('should allow to edit a local asset', function () {
......
......@@ -11,10 +11,11 @@ describe('custom widget test', function() {
editor.addCustomWidget('customAwesomeWidget');
// then we should be able to edit it
$('#edit-widget').click();
$('#widgetActionButton').click();
$('#editAction').click();
// then we should go the custom widget edition
expect($('.EditorHeader-brand').getText()).toBe('CUSTOM WIDGET EDITOR');
expect($('.EditorHeader-brand').getText()).toBe('WIDGET EDITOR');
});
});
......@@ -33,7 +33,7 @@ describe('home page', function() {
it('should navigate to a widget', function() {
$$('.ArtifactList-widget a').first().click();
expect($('.EditorHeader-brand').getText()).toBe('CUSTOM WIDGET EDITOR');
expect($('.EditorHeader-brand').getText()).toBe('WIDGET EDITOR');
});
it('should create a layout', function() {
......@@ -74,7 +74,7 @@ describe('home page', function() {
it('should create a widget with widget tab selected', function() {
home.openTab('widget');
home.createDefault('testWidget');
expect($('.EditorHeader-brand').getText()).toBe('CUSTOM WIDGET EDITOR');
expect($('.EditorHeader-brand').getText()).toBe('WIDGET EDITOR');
});
it('should not create a page with space or special characters in name', function() {
......@@ -115,7 +115,7 @@ describe('home page', function() {
it('should create a widget', function() {
home.createWidget('test');
expect($('.EditorHeader-brand').getText()).toBe('CUSTOM WIDGET EDITOR');
expect($('.EditorHeader-brand').getText()).toBe('WIDGET EDITOR');
});
it('should change sort order to alphabetical or chronological', () => {
......
......@@ -10,14 +10,20 @@ describe('properties panel test', function() {
});
it('should display edit button', function() {
expect(element(by.css('#edit-widget')).isDisplayed()).toBe(true);
it('should display action button, then editAction if custom widget, or viewAction if standard widget', function() {
expect(element(by.css('#editAction')).isPresent()).toBe(false);
expect(element(by.css('#widgetActionButton')).isDisplayed()).toBe(true);
element(by.css('#widgetActionButton')).click();
expect(element(by.css('#viewAction')).isDisplayed()).toBe(true);
editor = PageEditor.get('empty');
expect(element(by.css('#edit-widget')).isDisplayed()).toBe(false);
expect(element(by.css('#widgetActionButton')).isDisplayed()).toBe(false);
editor.addWidget('container');
expect(element(by.css('#edit-widget')).isDisplayed()).toBe(false);
expect(element(by.css('#widgetActionButton')).isDisplayed()).toBe(false);
editor.addCustomWidget('customAwesomeWidget');
expect(element(by.css('#edit-widget')).isDisplayed()).toBe(true);
expect(element(by.css('#widgetActionButton')).isDisplayed()).toBe(true);
element(by.css('#widgetActionButton')).click();
expect(element(by.css('#viewAction')).isPresent()).toBe(false);
expect(element(by.css('#editAction')).isDisplayed()).toBe(true);
});
it('should display default properties on container', function() {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment