ui/lib/shared/addon/components/form-key-value/component.js

233 lines
5.1 KiB
JavaScript

import { on } from '@ember/object/evented';
import { next, debounce } from '@ember/runloop';
import Component from '@ember/component';
import { get, set, observer } from '@ember/object'
import Upload from 'shared/mixins/upload';
import layout from './template';
function applyLinesIntoArray(lines, ary) {
lines.forEach((line) => {
line = line.trim();
if ( !line ) {
return;
}
let idx = line.indexOf('=');
if ( idx === -1 ) {
idx = line.indexOf(': ');
}
let key = '';
let val = '';
if ( idx > 0 ) {
key = line.substr(0, idx).trim();
val = line.substr(idx + 1).trim();
} else {
key = line.trim();
val = '';
}
var existing = ary.filterBy('key', key)[0];
if ( existing ) {
set(existing, 'value', val);
} else {
ary.pushObject({
key,
value: val
});
}
});
}
function removeEmptyEntries(ary, allowEmptyValue = false) {
// Clean up empty user entries
let toRemove = [];
ary.forEach((item) => {
if ( !get(item, 'key') && (!get(item, 'value') || !allowEmptyValue) ) {
toRemove.push(item);
}
});
ary.removeObjects(toRemove);
}
export default Component.extend(Upload, {
layout,
// Inputs
initialStr: null,
initialMap: null,
initialArray: null,
requiredIfAny: null,
ary: null,
allowEmptyValue: false,
allowAdd: true,
allowUpload: false,
allowRemove: true,
allowEditKey: true,
addInitialEmptyRow: false,
allowMultilineValue: true,
base64Value: false,
showNoneLabel: true,
concealValue: false,
editing: true,
kvSeparator: '=',
separators: ['=', ': '],
addActionLabel: 'formKeyValue.addAction',
keyLabel: 'formKeyValue.key.label',
valueLabel: 'formKeyValue.value.label',
keyPlaceholder: 'formKeyValue.key.placeholder',
valuePlaceholder: 'formKeyValue.value.placeholder',
uploadAction: 'pastedValues',
init() {
this._super(...arguments);
var ary = [];
var map = get(this, 'initialMap');
if ( map ) {
Object.keys(map).forEach((key) => {
ary.push({
key,
value: map[key]
});
});
} else if ( get(this, 'initialStr') ) {
let lines = get(this, 'initialStr').split(',');
let required = get(this, 'requiredIfAny');
applyLinesIntoArray(lines, ary, get(this, 'kvSeparator'));
removeEmptyEntries(ary, get(this, 'allowEmptyValue'));
if (required) {
Object.keys(required).forEach((key) => {
let line = ary.findBy('key', key);
line.editable = false;
});
}
} else if ( get(this, 'initialArray') ) {
get(this, 'initialArray').forEach((line) => {
ary.push({
key: line.key,
value: line.value
});
});
}
if ( get(this, 'base64Value') ) {
ary.forEach((entry) => {
entry.value = AWS.util.base64.decode(entry.value).toString();
});
}
set(this, 'ary', ary);
if ( !ary.length && get(this, 'addInitialEmptyRow') ) {
this.send('add');
}
},
// groupMap: null,
actions: {
add() {
let ary = get(this, 'ary');
let required = get(this, 'requiredIfAny');
if ( required && !get(ary, 'length') ) {
Object.keys(required).forEach((k) => {
ary.pushObject({
key: k,
value: required[k],
editable: false
});
});
}
ary.pushObject({
key: '',
value: ''
});
next(() => {
if ( this.isDestroyed || this.isDestroying ) {
return;
}
let elem = this.$('INPUT.key').last()[0];
if ( elem ) {
elem.focus();
}
});
},
remove(obj) {
get(this, 'ary').removeObject(obj);
},
pastedValues(str) {
let ary = get(this, 'ary');
str = str.trim();
let lines = str.split(/\r?\n/);
applyLinesIntoArray(lines, ary);
removeEmptyEntries(ary, get(this, 'allowEmptyValue'));
},
},
aryObserver: on('init', observer('ary.@each.{key,value}', function() {
debounce(this, 'fireChanged', 100);
})),
fireChanged() {
if ( this.isDestroyed || this.isDestroying ) {
return;
}
let map = {};
let str = '';
let arr = [];
get(this, 'ary').forEach((row) => {
var k = get(row, 'key').trim();
var v;
if ( get(row, 'value') !== undefined && get(row, 'value') !== null ) {
v = (`${ get(row, 'value') }`).trim();
}
if ( get(this, 'base64Value') ) {
v = AWS.util.base64.encode(v);
}
if ( k && (v || get(this, 'allowEmptyValue')) ) {
map[k] = v;
str += (str ? ', ' : '') + k + (v ? get(this, 'kvSeparator') + v : '');
arr.push({
key: k,
value: v,
});
}
});
next(() => {
this.sendAction('changed', map);
this.sendAction('changedStr', str);
this.sendAction('changedArray', arr);
});
},
});