removed x from test + merge
gitea/salix/dev This commit looks good Details

This commit is contained in:
Carlos Jimenez Ruiz 2019-10-01 13:21:27 +02:00
commit eb80721ec4
26 changed files with 429 additions and 284 deletions

View File

@ -1,12 +0,0 @@
<div class="check">
<div class="focus"></div>
<div class="mark"></div>
</div>
<span translate>
{{::$ctrl.label}}
</span>
<i class="material-icons"
ng-if="::$ctrl.hasInfo"
vn-tooltip="{{::$ctrl.info}}">
info_outline
</i>

View File

@ -0,0 +1,12 @@
<div class="check">
<div class="focus-mark"></div>
<div class="mark"></div>
</div>
<span translate>
{{::$ctrl.label}}
</span>
<vn-icon
ng-if="::$ctrl.info != null"
vn-tooltip="{{::$ctrl.info}}"
icon="info_outline">
</vn-icon>

View File

@ -2,25 +2,32 @@ import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
/**
* Basic element for user input. You can use this to supply a way for the user
* to toggle an option.
*
* @property {String} label Label to display along the component
* @property {any} field The value with which the element is linked
* @property {Boolean} checked Whether the checkbox is checked
* @property {Boolean} disabled Put component in disabled mode
* @property {Boolean} tripleState Switch between three states when clicked
* @property {Boolean} indeterminate Sets the element into indeterminate state
* @property {String} info Shows a text information tooltip to the user
*/
export default class Controller extends Component {
constructor($element, $, $attrs) {
super($element, $);
this.hasInfo = Boolean($attrs.info);
this.info = $attrs.info || null;
let element = this.element;
element.addEventListener('click', e => this.onClick(e));
element.addEventListener('keydown', e => this.onClick(e));
element.addEventListener('keydown', e => this.onKeydown(e));
element.tabIndex = 0;
this.check = element.querySelector('.check');
}
set field(value) {
this._field = value;
let isIndeterminate = Boolean(value == null && this.tripleState);
this.check.classList.toggle('checked', Boolean(value));
this.check.classList.toggle('indeterminate', isIndeterminate);
this.element.classList.toggle('checked', Boolean(value));
this.indeterminate = Boolean(value == null && this.tripleState);
}
get field() {
@ -29,7 +36,7 @@ export default class Controller extends Component {
set disabled(value) {
this.element.tabIndex = !value ? 0 : -1;
this.check.classList.toggle('disabled', Boolean(value));
this.element.classList.toggle('disabled', Boolean(value));
this._disabled = value;
}
@ -37,6 +44,15 @@ export default class Controller extends Component {
return this._disabled;
}
set indeterminate(value) {
this._indeterminate = value;
this.element.classList.toggle('indeterminate', Boolean(value));
}
get indeterminate() {
return this._indeterminate;
}
set tripleState(value) {
this._tripleState = value;
this.field = this.field;
@ -53,9 +69,9 @@ export default class Controller extends Component {
if (this.tripleState) {
if (this.field == null)
this.field = false;
else if (!this.field)
this.field = true;
else if (this.field)
this.field = false;
else
this.field = null;
} else
@ -63,6 +79,7 @@ export default class Controller extends Component {
this.$.$applyAsync();
this.element.dispatchEvent(new Event('change'));
this.emit('change', {value: this.field});
}
onKeydown(event) {
@ -74,15 +91,16 @@ export default class Controller extends Component {
Controller.$inject = ['$element', '$scope', '$attrs'];
ngModule.component('vnCheck', {
template: require('./check.html'),
template: require('./index.html'),
controller: Controller,
bindings: {
field: '=?',
label: '@?',
disabled: '<?',
field: '=?',
checked: '<?',
disabled: '<?',
tripleState: '<?',
intermediate: '<?'
indeterminate: '<?',
info: '@?'
}
});

View File

@ -38,20 +38,20 @@ describe('Component vnCheck', () => {
expect($ctrl.field).toEqual(false);
});
it(`should check value and change to null when clicked`, () => {
it(`should check value and change to false when clicked`, () => {
$ctrl.field = true;
$ctrl.tripleState = true;
element.click();
expect($ctrl.field).toEqual(null);
expect($ctrl.field).toEqual(false);
});
it(`should set value to null and change to false when clicked`, () => {
it(`should set value to null and change to true when clicked`, () => {
$ctrl.field = null;
$ctrl.tripleState = true;
element.click();
expect($ctrl.field).toEqual(false);
expect($ctrl.field).toEqual(true);
});
it(`should cast value to boolean when clicked`, () => {

View File

@ -2,10 +2,13 @@
vn-check {
position: relative;
cursor: pointer;
display: inline-block;
outline: none;
cursor: pointer;
&.disabled {
cursor: initial;
}
& > .check {
position: relative;
box-sizing: border-box;
@ -16,7 +19,7 @@ vn-check {
height: 20px;
transition: background 250ms;
border: 2px solid #666;
margin: 3px;
margin: 6px 0;
margin-right: .4em;
& > .mark {
@ -25,15 +28,15 @@ vn-check {
display: block;
border-width: 0;
}
&.checked {
background-color: $color-main;
border-color: $color-main;
}
&.checked > .check {
background-color: $color-main;
border-color: $color-main;
& > .focus {
background-color: rgba($color-main, .15);
}
& > .focus-mark {
background-color: rgba($color-main, .15);
}
&.checked > .mark {
& > .mark {
top: 0;
left: 4px;
transform: rotate(45deg);
@ -43,16 +46,16 @@ vn-check {
border-top: 0;
border-left: 0;
}
&.indeterminate > .mark {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 12px;
height: 2px;
border-bottom: 2px solid #666;
}
}
& > .check > .focus {
&.indeterminate > .check > .mark {
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 12px;
height: 2px;
border-bottom: 2px solid #666;
}
& > .check > .focus-mark {
position: absolute;
top: 50%;
left: 50%;
@ -66,13 +69,12 @@ vn-check {
transition: transform 250ms;
background-color: rgba(0, 0, 0, .1);
}
&:focus > .check:not(.disabled) > .focus {
&:focus:not(.disabled) > .check > .focus-mark {
transform: scale3d(1, 1, 1);
}
& > i {
padding-left: 5px;
position: absolute;
& > vn-icon {
margin-left: 5px;
color: $color-font-secondary;
font-size: 20px;
vertical-align: middle;
}
}

View File

@ -19,8 +19,6 @@ import './menu/menu';
import './multi-check/multi-check';
import './date-picker/date-picker';
import './button/button';
import './check/check';
import './radio-group/radio-group';
import './textarea/textarea';
import './icon-button/icon-button';
import './submit/submit';
@ -31,16 +29,18 @@ import './label-value/label-value';
import './paging/paging';
import './pagination/pagination';
import './searchbar/searchbar';
import './scroll-up/scroll-up';
import './table';
import './td-editable';
import './th';
import './input-range';
import './calendar';
import './check';
import './chip';
import './color-legend';
import './input-number';
import './input-time';
import './input-file';
import './radio';
import './th';
import './treeview';
import './treeview/child';
import './calendar';
import './scroll-up/scroll-up';

View File

@ -2,13 +2,6 @@
ng-class="{selected: $ctrl.hasFocus}">
<div class="textField">
<div class="leftIcons">
<vn-icon-button
ng-if="$ctrl.displayControls"
icon="remove"
ng-click="$ctrl.stepDown()"
tabindex="-1"
translate-attr="{title: 'Remove'}">
</vn-icon-button>
</div>
<div class="infix">
<input
@ -30,6 +23,13 @@
<div class="underline"></div>
<div class="selected underline"></div>
<div class="suffix">
<vn-icon-button
ng-if="$ctrl.displayControls"
icon="remove"
ng-click="$ctrl.stepDown()"
tabindex="-1"
translate-attr="{title: 'Remove'}">
</vn-icon-button>
<vn-icon-button
ng-if="$ctrl.displayControls"
icon="add"

View File

@ -17,17 +17,9 @@ export default class InputNumber extends Input {
*/
registerEvents() {
this.input.addEventListener('change', event => {
if (!isNaN(this.value))
this.input.value = this.value;
this.validateValue();
this.emit('change', {event});
});
this.input.addEventListener('focus', event => {
this.emit('focus', {event});
});
}
/**
@ -49,12 +41,7 @@ export default class InputNumber extends Input {
this.input.value = value;
this._value = value;
if (this.hasValue)
this.element.classList.add('not-empty');
else
this.element.classList.remove('not-empty');
this.element.classList.toggle('not-empty', this.hasValue);
this.validateValue();
}
@ -111,6 +98,7 @@ export default class InputNumber extends Input {
*/
stepUp() {
this.input.stepUp();
this.input.dispatchEvent(new Event('change'));
}
/**
@ -118,6 +106,7 @@ export default class InputNumber extends Input {
*/
stepDown() {
this.input.stepDown();
this.input.dispatchEvent(new Event('change'));
}
}
InputNumber.$inject = ['$element', '$scope', '$attrs', 'vnTemplate'];

View File

@ -3,18 +3,13 @@
vn-input-number {
@extend vn-textfield;
input {
text-align: center !important;
}
vn-icon[icon=add],
vn-icon[icon=remove]{
vn-icon[icon=remove] {
&:not(:hover){
color: $color-font-secondary;
}
i {
-moz-user-select: none;
-webkit-user-select: none;
-ms-user-select: none;
user-select: none;
}
}

View File

@ -35,7 +35,7 @@ export default class InputTime extends Input {
*/
set value(value) {
this.updateValue(value);
this.input.value = this.$filter('date')(value, 'HH:mm');
this.input.value = this.$filter('dateTime')(value, 'HH:mm');
}
updateValue(value) {

View File

@ -1,5 +1,5 @@
<vn-check field="$ctrl.checked"
<vn-check
field="$ctrl.checked"
intermediate="$ctrl.isIntermediate"
vn-tooltip="Check all"
tooltip-position="up">
translate-attr="{title: 'Check all'}">
</vn-check>

View File

@ -1,5 +1,5 @@
vn-multi-check {
md-checkbox {
vn-check {
margin-bottom: 0.8em
}
}

View File

@ -1,8 +0,0 @@
<md-radio-group ng-model="$ctrl.model">
<md-radio-button aria-label="::option.label"
ng-repeat="option in $ctrl.options"
ng-value="option.value"
ng-disabled="$ctrl.disabled">
<span translate>{{::option.label}}</span>
</md-radio-button>
</md-radio-group>

View File

@ -1,41 +0,0 @@
import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
export default class Controller extends Component {
constructor($element, $scope, $attrs) {
super($element, $scope);
this.hasInfo = Boolean($attrs.info);
this.info = $attrs.info || null;
}
get model() {
return this._model;
}
set model(value) {
this._model = value;
}
get field() {
return this._model;
}
set field(value) {
this._model = value;
}
}
Controller.$inject = ['$element', '$scope', '$attrs'];
ngModule.component('vnRadioGroup', {
template: require('./radio-group.html'),
controller: Controller,
bindings: {
field: '=?',
options: '<?',
disabled: '<?',
checked: '<?'
}
});

View File

@ -1,11 +0,0 @@
@import "variables";
md-radio-group md-radio-button.md-checked .md-container {
.md-on {
background-color: $color-main
}
.md-off {
border-color: $color-main
}
}

View File

@ -0,0 +1,7 @@
<div class="radio">
<div class="focus-mark"></div>
<div class="mark"></div>
</div>
<span translate>
{{::$ctrl.label}}
</span>

View File

@ -0,0 +1,93 @@
import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
/**
* Basic element for user input. You can use this to supply a way for the user
* to pick an option from multiple choices.
*
* @property {String} label Label to display along the component
* @property {any} field The value with which the element is linked
* @property {Boolean} checked Whether the radio is checked
* @property {String} val The actual value of the option
* @property {Boolean} disabled Put component in disabled mode
*/
export default class Controller extends Component {
constructor($element, $, $attrs) {
super($element, $);
this.hasInfo = Boolean($attrs.info);
this.info = $attrs.info || null;
let element = this.element;
element.addEventListener('click', e => this.onClick(e));
element.addEventListener('keydown', e => this.onKeydown(e));
element.tabIndex = 0;
}
set field(value) {
this._field = value;
this.element.classList.toggle('checked',
Boolean(value) && value == this.val);
}
get field() {
return this._field;
}
set val(value) {
this._val = value;
this.field = this.field;
}
get val() {
return this._val;
}
set checked(value) {
this.field = value ? this.val : null;
this.$.$applyAsync();
}
get checked() {
return this.field == this.val;
}
set disabled(value) {
this.element.tabIndex = !value ? 0 : -1;
this.element.classList.toggle('disabled', Boolean(value));
this._disabled = value;
}
get disabled() {
return this._disabled;
}
onClick(event) {
if (this.disabled) return;
event.preventDefault();
this.field = this.val;
this.$.$applyAsync();
this.element.dispatchEvent(new Event('change'));
}
onKeydown(event) {
if (event.code == 'Space')
this.onClick(event);
}
}
Controller.$inject = ['$element', '$scope', '$attrs'];
ngModule.component('vnRadio', {
template: require('./index.html'),
controller: Controller,
bindings: {
label: '@?',
field: '=?',
checked: '<?',
val: '@?',
disabled: '<?'
}
});

View File

@ -0,0 +1,64 @@
describe('Component vnCheck', () => {
let $element;
let $ctrl;
let element;
beforeEach(angular.mock.module('vnCore', $translateProvider => {
$translateProvider.translations('en', {});
}));
beforeEach(inject(($compile, $rootScope) => {
$element = $compile(`<vn-check></vn-check`)($rootScope);
$ctrl = $element.controller('vnCheck');
element = $element[0];
}));
afterEach(() => {
$element.remove();
});
describe('field() setter', () => {
it(`should set model value`, () => {
$ctrl.field = true;
expect($ctrl.field).toEqual(true);
});
it(`should uncheck value and change to true when clicked`, () => {
$ctrl.field = false;
element.click();
expect($ctrl.field).toEqual(true);
});
it(`should check value and change to false when clicked`, () => {
$ctrl.field = true;
element.click();
expect($ctrl.field).toEqual(false);
});
it(`should uncheck value and change to null when clicked`, () => {
$ctrl.field = false;
$ctrl.tripleState = true;
element.click();
expect($ctrl.field).toEqual(null);
});
it(`should set value to null and change to true when clicked`, () => {
$ctrl.field = null;
$ctrl.tripleState = true;
element.click();
expect($ctrl.field).toEqual(true);
});
it(`should cast value to boolean when clicked`, () => {
$ctrl.field = 0;
element.click();
expect($ctrl.field).toEqual(true);
});
});
});

View File

@ -0,0 +1,62 @@
@import "variables";
vn-radio {
position: relative;
cursor: pointer;
display: inline-block;
outline: none;
&.disabled {
cursor: initial;
}
& > .radio {
position: relative;
box-sizing: border-box;
display: inline-block;
vertical-align: middle;
border-radius: 50%;
width: 20px;
height: 20px;
border: 2px solid #666;
margin: 6px 0;
margin-right: .4em;
& > .mark {
transition: background 250ms;
}
}
&.checked > .radio {
border-color: $color-main;
& > .mark {
position: absolute;
border-radius: 50%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 10px;
height: 10px;
background-color: $color-main;
}
& > .focus-mark {
background-color: rgba($color-main, .15);
}
}
& > .radio > .focus-mark {
position: absolute;
top: 50%;
left: 50%;
height: 38px;
width: 38px;
margin-top: -19px;
margin-left: -19px;
border-radius: 50%;
transform: scale3d(0, 0, 0);
transition: background 250ms;
transition: transform 250ms;
background-color: rgba(0, 0, 0, .1);
}
&:focus:not(.disabled) > .radio > .focus-mark {
transform: scale3d(1, 1, 1);
}
}

View File

@ -184,7 +184,7 @@ vn-table {
float: right;
margin: 0!important;
}
md-checkbox {
vn-check {
margin: 0;
}
}

View File

@ -1,55 +1,61 @@
<ul ng-if="::$ctrl.items">
<li ng-repeat="item in $ctrl.items"
ng-class="{
'expanded': item.active,
'collapsed': !item.active,
'included': item.selected == 1,
'excluded': item.selected == 0
}" vn-draggable="{{::$ctrl.draggable}}" vn-droppable="{{::$ctrl.droppable}}" on-drop="$ctrl.onDrop(item, dragged, dropped)">
<vn-horizontal>
<vn-auto class="actions">
<vn-icon icon="keyboard_arrow_down" title="{{'Toggle' | translate}}"
ng-click="$ctrl.toggle(item, $event)">
</vn-icon>
</vn-auto>
<vn-check vn-auto vn-acl="{{$ctrl.aclRole}}"
ng-if="$ctrl.selectable"
field="item.selected"
disabled="$ctrl.disabled"
on-change="$ctrl.select(item, value)"
triple-state="true">
</vn-check>
<vn-one class="description">{{::item.name}}</vn-one>
<vn-auto>
<vn-icon-button icon="{{icon.icon}}"
ng-repeat="icon in $ctrl.icons"
ng-click="$ctrl.onIconClick(icon, item, $ctrl.parent, $parent.$index)"
vn-acl="{{$ctrl.aclRole}}" vn-acl-action="remove">
</vn-icon-button>
</vn-auto>
</vn-horizontal>
<vn-treeview-child items="item.childs" parent="item"
selectable="$ctrl.selectable"
disabled="$ctrl.disabled"
editable="$ctrl.editable"
draggable="::$ctrl.draggable"
droppable="::$ctrl.droppable"
icons="::$ctrl.icons"
parent-scope="::$ctrl.parentScope"
acl-role="$ctrl.aclRole">
</vn-treeview-child>
</li>
<li ng-if="$ctrl.isInsertable && $ctrl.editable"
ng-click="$ctrl.onCreate($ctrl.parent)"
vn-acl="{{$ctrl.aclRole}}"
vn-acl-action="remove">
<vn-horizontal>
<vn-auto>
<vn-icon-button icon="add_circle"></vn-icon-button>
</vn-auto>
<div class="description" translate>
Create new one
</div>
</vn-horizontal>
</li>
</ul>
<li
ng-repeat="item in $ctrl.items"
on-drop="$ctrl.onDrop(item, dragged, dropped)"
vn-draggable="{{::$ctrl.draggable}}"
vn-droppable="{{::$ctrl.droppable}}"
ng-class="{expanded: item.active}">
<div
ng-click="$ctrl.toggle($event, item)"
class="node clickable">
<vn-icon
class="arrow"
ng-class="{invisible: item.sons == 0}"
icon="keyboard_arrow_down"
translate-attr="{title: 'Toggle'}">
</vn-icon>
<vn-check
vn-acl="{{$ctrl.aclRole}}"
ng-if="$ctrl.selectable"
field="item.selected"
disabled="$ctrl.disabled"
on-change="$ctrl.select(item, value)"
triple-state="true"
label="{{::item.name}}">
</vn-check>
<vn-icon-button
icon="{{icon.icon}}"
ng-repeat="icon in $ctrl.icons"
ng-click="$ctrl.onIconClick(icon, item, $ctrl.parent, $parent.$index)"
vn-acl="{{$ctrl.aclRole}}"
vn-acl-action="remove">
</vn-icon-button>
</div>
<vn-treeview-child
items="item.childs"
parent="item"
selectable="$ctrl.selectable"
disabled="$ctrl.disabled"
editable="$ctrl.editable"
draggable="::$ctrl.draggable"
droppable="::$ctrl.droppable"
icons="::$ctrl.icons"
parent-scope="::$ctrl.parentScope"
acl-role="$ctrl.aclRole">
</vn-treeview-child>
</li>
<li
ng-if="$ctrl.isInsertable && $ctrl.editable"
ng-click="$ctrl.onCreate($ctrl.parent)"
vn-acl="{{$ctrl.aclRole}}"
vn-acl-action="remove">
<div class="node">
<vn-icon-button
icon="add_circle">
</vn-icon-button>
<div class="description" translate>
Create new one
</div>
</div>
</li>
</ul>

View File

@ -7,7 +7,9 @@ class Controller extends Component {
this.$scope = $scope;
}
toggle(item) {
toggle(event, item) {
if (event.defaultPrevented || !item.sons) return;
event.preventDefault();
this.treeview.onToggle(item);
}

View File

@ -1,4 +1,5 @@
<vn-treeview-child acl-role="$ctrl.aclRole"
<vn-treeview-child
acl-role="$ctrl.aclRole"
items="$ctrl.data"
parent="$ctrl.data"
selectable="$ctrl.selectable"

View File

@ -1,80 +1,46 @@
@import "variables";
@import "effects";
vn-treeview {
vn-treeview-child {
display: block
}
ul {
line-height: 24px;
padding: 0;
margin: 0;
li {
list-style: none;
.actions {
& > div > .arrow {
min-width: 24px;
margin-right: 10px
margin-right: 10px;
transition: transform 200ms;
}
.description {
pointer-events: none;
padding-left: 5px
&.expanded > div > .arrow {
transform: rotate(180deg);
}
}
li vn-icon {
cursor: pointer;
}
li ul {
padding-left: 1.8em;
}
li > vn-horizontal {
padding: 5px
}
li > vn-horizontal:hover {
background-color: $color-hover-cd
}
li.expanded > vn-horizontal > .actions > vn-icon[icon="keyboard_arrow_down"] {
transition: all 0.2s;
transform: rotate(180deg);
}
li.collapsed > vn-horizontal > .actions > vn-icon[icon="keyboard_arrow_down"] {
transition: all 0.2s;
transform: rotate(0deg);
}
li.included {
& > vn-horizontal > .description {
color: $color-notice;
font-weight: bold;
& > .node {
@extend %clickable;
display: flex;
padding: 5px;
align-items: center;
& > vn-check:not(.indeterminate) {
color: $color-main;
& > .check {
border-color: $color-main;
}
}
& > vn-check.checked {
color: $color-main;
}
}
& > vn-horizontal > vn-check .md-icon {
background-color: $color-notice
}
}
li.excluded {
& > vn-horizontal > .description {
color: $color-alert;
font-weight: bold;
}
& > vn-horizontal > vn-check .md-icon {
background-color: $color-alert;
border-color: transparent
ul {
padding-left: 2.2em;
}
}
}
vn-icon-button {
padding: 0
}

View File

@ -80,10 +80,23 @@
on-response="$ctrl.onSave(response)">
<tpl-body>
<vn-vertical>
<vn-radio-group
field="$ctrl.eventType"
options="$ctrl.options">
</vn-radio-group>
<vn-vertical>
<vn-radio
field="$ctrl.eventType"
label="One day"
val="day">
</vn-radio>
<vn-radio
field="$ctrl.eventType"
label="Range of dates"
val="range">
</vn-radio>
<vn-radio
field="$ctrl.eventType"
label="Indefinitely"
val="indefinitely">
</vn-radio>
</vn-vertical>
<div
ng-if="$ctrl.eventType != 'day'"
class="week-days">

View File

@ -41,19 +41,6 @@ class Controller {
wday.abr = locale.substr(0, 1);
}
this.options = [
{
label: 'One day',
value: 'day'
}, {
label: 'Range of dates',
value: 'range'
}, {
label: 'Indefinitely',
value: 'indefinitely'
}
];
this.$http.get(`/api/Zones/${$stateParams.id}/exclusions`)
.then(res => this.$.exclusions = res.data);