Revamp saveTrigger

This commit is contained in:
djmaze 2021-02-11 10:08:27 +01:00
parent 325f3c8eea
commit ce4ee3ba3f
15 changed files with 72 additions and 179 deletions

View file

@ -14,7 +14,6 @@ import { i18nToNodes, initOnStartOrLangChange } from 'Common/Translator';
import { LanguageStore } from 'Stores/Language';
import { ThemeStore } from 'Stores/Theme';
import { SaveTriggerComponent } from 'Component/SaveTrigger';
import { InputComponent } from 'Component/Input';
import { SelectComponent } from 'Component/Select';
import { TextAreaComponent } from 'Component/TextArea';
@ -107,7 +106,6 @@ export class AbstractApp {
}
});
register('SaveTrigger', SaveTriggerComponent);
register('Input', InputComponent);
register('Select', SelectComponent);
register('TextArea', TextAreaComponent);

View file

@ -1,38 +0,0 @@
import { SaveSettingsStep } from 'Common/Enums';
import { AbstractComponent } from 'Component/Abstract';
export class SaveTriggerComponent extends AbstractComponent {
/**
* @param {Object} params
*/
constructor(params) {
super();
const el = params.element;
this.element = el || null;
this.value = params.value && params.value.subscribe ? params.value : null;
if (el) {
if (this.value) {
el.style.display = 'inline-block';
if (params.verticalAlign) {
el.style.verticalAlign = params.verticalAlign;
}
this.setState(this.value());
this.disposable.push(this.value.subscribe(this.setState, this));
} else {
el.style.display = 'none';
}
}
}
setState(value) {
value = parseInt(value,10);
this.element.querySelector('.icon-spinner').hidden = value !== SaveSettingsStep.Animate;
this.element.querySelector('.success').hidden = value !== SaveSettingsStep.TrueResult;
this.element.querySelector('.error').hidden = value !== SaveSettingsStep.FalseResult;
}
}

View file

@ -2,43 +2,9 @@ import 'External/ko';
import ko from 'ko';
import { SaveSettingsStep } from 'Common/Enums';
ko.bindingHandlers.saveTrigger = {
init: (element) => {
element.saveTriggerType = element.matches('input[type=text],input[type=email],input[type=password],select,textarea')
? 'input' : 'custom';
if ('custom' === element.saveTriggerType) {
element.append(
'  ',
Element.fromHTML('<i class="icon-spinner"></i>'),
Element.fromHTML('<i class="fontastic error">✖</i>'),
Element.fromHTML('<i class="icon-ok success"></i>')
);
element.classList.add('settings-saved-trigger');
} else {
element.classList.add('settings-saved-trigger-input');
}
},
update: (element, fValueAccessor) => {
const value = parseInt(ko.unwrap(fValueAccessor()),10);
if ('custom' === element.saveTriggerType) {
element.querySelector('.icon-spinner').hidden = value !== SaveSettingsStep.Animate;
element.querySelector('.success').hidden = value !== SaveSettingsStep.TrueResult;
element.querySelector('.error').hidden = value !== SaveSettingsStep.FalseResult;
} else if (value !== SaveSettingsStep.Animate) {
element.classList.toggle('success', value === SaveSettingsStep.TrueResult);
element.classList.toggle('error', value === SaveSettingsStep.FalseResult);
}
}
};
ko.extenders.idleTrigger = (target) => {
target.trigger = ko.observable(SaveSettingsStep.Idle);
return target;
};
// functions
ko.observable.fn.idleTrigger = function() {
return this.extend({ 'idleTrigger': true });
this.trigger = ko.observable(SaveSettingsStep.Idle);
return this;
};

44
dev/External/ko.js vendored
View file

@ -1,5 +1,6 @@
import { i18n, i18nToNodes, trigger } from 'Common/Translator';
import { doc, dropdownVisibility } from 'Common/Globals';
import { doc, createElement, dropdownVisibility } from 'Common/Globals';
import { SaveSettingsStep } from 'Common/Enums';
const
isFunction = v => typeof v === 'function',
@ -170,6 +171,29 @@ ko.bindingHandlers.command = {
}
};
ko.bindingHandlers.saveTrigger = {
init: (element) => {
let icon = element;
if (element.matches('input,select,textarea')) {
element.classList.add('settings-saved-trigger-input');
element.after(element.saveTriggerIcon = icon = createElement('span'));
}
icon.classList.add('settings-save-trigger');
},
update: (element, fValueAccessor) => {
const value = parseInt(ko.unwrap(fValueAccessor()),10);
let cl = (element.saveTriggerIcon || element).classList;
if (element.saveTriggerIcon) {
cl.toggle('saving', value === SaveSettingsStep.Animate);
cl.toggle('success', value === SaveSettingsStep.TrueResult);
cl.toggle('error', value === SaveSettingsStep.FalseResult);
}
cl = element.classList;
cl.toggle('success', value === SaveSettingsStep.TrueResult);
cl.toggle('error', value === SaveSettingsStep.FalseResult);
}
};
// extenders
ko.extenders.limitedList = (target, limitedList) => {
@ -233,17 +257,7 @@ ko.extenders.toggleSubscribeProperty = (target, options) => {
};
ko.extenders.falseTimeout = (target, option) => {
target.iFalseTimeoutTimeout = 0;
target.subscribe(value => {
if (value) {
clearTimeout(target.iFalseTimeoutTimeout);
target.iFalseTimeoutTimeout = setTimeout(() => {
target(false);
target.iFalseTimeoutTimeout = 0;
}, parseInt(option, 10) || 0);
}
});
target.subscribe((() => target(false)).debounce(parseInt(option, 10) || 0));
return target;
};
@ -254,12 +268,8 @@ ko.observable.fn.deleteAccessHelper = function() {
};
ko.addObservablesTo = (target, observables) => {
Object.entries(observables).forEach(([key, value]) => target[key] = ko.observable(value) );
/*
Object.entries(observables).forEach(([key, value]) =>
target[key] = Array.isArray(value) ? ko.observableArray(value) : ko.observable(value)
);
*/
target[key] = /*Array.isArray(value) ? ko.observableArray(value) :*/ ko.observable(value) );
};
ko.addComputablesTo = (target, computables) =>

View file

@ -250,17 +250,11 @@
}
.btn {
.btn-text-wrp {
padding-left: 7px;
white-space: normal;
}
&.buttonCompose {
width: calc(~'100% - 85px');
max-width: -moz-fit-content;
max-width: -webkit-fit-content;
max-width: fit-content;
white-space: nowrap;
overflow: hidden;
height: 19px;
margin-top: 1px;

View file

@ -37,7 +37,7 @@
}
.e-item.selected > .e-link {
background-color: var(--dropdown-menu-selected-bg-color, #eee) !important;
background-color: var(--dropdown-menu-selected-bg-color, #eee);
}
.e-item:not(.disabled) > .e-link:focus,
@ -92,48 +92,54 @@
}
}
.settings-saved-trigger {
.settings-save-trigger {
display: inline-block;
height: 17px;
line-height: 17px;
font-size: 16px;
position: relative;
height: 1em;
line-height: 1em;
.animated {
color: #888;
&::after {
font-family: "snappymail";
content: " ";
display: block;
margin-left: 1em;
opacity: 0;
transition: opacity 1s linear;
}
.success {
&.saving::after {
animation: rotation .8s infinite ease-in-out;
border: 3px solid transparent;
border-radius: 100%;
border-top-color: #999;
height: 11px;
opacity: 1;
width: 11px;
}
&.success::after {
color: #080;
}
.error {
color: #F00;
}
i {
transition: opacity 2s linear;
position: absolute;
}
i:not([hidden]) {
content: "✔";
opacity: 1;
}
i[hidden] {
opacity: 0;
&.error::after {
color: #F00;
content: "✖";
opacity: 1;
}
}
textarea + .settings-save-trigger {
vertical-align: top;
}
.settings-saved-trigger-input {
transition: border-color 0.5s linear;
&.success {
border-color: green !important;
border-color: green;
}
&.error {
border-color: red !important;
border-color: red;
}
}