ui/lib/shared/addon/components/input-answers/component.js

216 lines
5.2 KiB
JavaScript

import { alias } from '@ember/object/computed';
import Component from '@ember/component';
import {
get, set, computed, observer, setProperties
} from '@ember/object';
import { on } from '@ember/object/evented';
import { isSafari } from 'ui/utils/platform';
import { evaluate } from 'shared/utils/evaluate';
import { inject as service } from '@ember/service';
import layout from './template';
import jsyaml from 'js-yaml';
import convertDotAnswersToYaml from 'shared/utils/convert-yaml';
import InputAnswers from 'shared/mixins/input-answers';
import { next } from '@ember/runloop';
const HIDDEN = 'Hidden';
export default Component.extend(InputAnswers, {
growl: service(),
modalService: service('modal'),
layout,
pasteOrUpload: false,
isMultiClusterApp: false,
accept: '.yml, .yaml',
showHeader: true,
answerSections: null,
questions: alias('selectedTemplate.allQuestions'),
valuesYaml: alias('selectedTemplate.valuesYaml'),
didInsertElement() {
this._super(...arguments);
// don't show yaml editor before the component is finished rendering or we get an empty yaml editor until user clicks in yaml form.
// reason being code-mirror doesn't have an element to initialize on
next(() => {
const { isMultiClusterApp } = this;
let pasteOrUpload = isMultiClusterApp ? !!get(this, 'app.answers.firstObject.valuesYaml') : !!get(this, 'app.valuesYaml');
set(this, 'pasteOrUpload', pasteOrUpload);
})
},
// shared actions exist in mixin
// actions: {},
pastedAnswers: computed('app.answers.firstObject.valuesYaml', 'app.valuesYaml', 'pasteOrUpload', 'questions', {
get( /* key */ ) {
let valuesYaml;
const { isMultiClusterApp } = this;
if ( isMultiClusterApp ) {
valuesYaml = get(this, 'app.answers.firstObject.valuesYaml') || '';
} else {
valuesYaml = get(this, 'app.valuesYaml') || '';
}
let yaml;
if ( valuesYaml ) {
yaml = valuesYaml;
} else {
const questions = get(this, 'questions');
const input = {};
questions.forEach((q) => {
if ( q.answer !== undefined && q.answer !== null ) {
input[q.variable] = q.answer;
} else if ( q.default !== undefined && q.default !== null ) {
input[q.variable] = q.default;
} else {
input[q.variable] = '';
}
});
yaml = convertDotAnswersToYaml(input);
}
set(this, 'valuesYaml', yaml);
return yaml;
},
set(key, value) {
try {
jsyaml.safeLoad(value);
} catch ( err ) {
set(this, 'yamlErrors', [`YAML Parse Error: ${ err.snippet } - ${ err.message }`]);
return value;
}
setProperties(this, {
yamlErrors: [],
valuesYaml: value,
});
return value;
}
}),
actualAccept: computed('accept', function() {
if ( isSafari ) {
return '';
} else {
return get(this, 'accept');
}
}),
answerDidChange: on('init', observer('questions.@each.answer', function() {
const questions = (get(this, 'questions') || []);
let oldQuestions = [];
let newQuestions = [];
(get(this, 'answerSections') || []).forEach((section) => {
section.data.forEach((group) => {
group.forEach((q) => {
oldQuestions.push(q.variable);
});
});
});
oldQuestions = oldQuestions.sort();
const filteredQuestions = questions.filter((q) => evaluate(q, questions));
newQuestions = filteredQuestions.map((q) => q.variable).sort();
const sections = {};
const notInAnySection = [];
filteredQuestions.forEach((item) => {
if ( item.group ) {
if ( item.group === HIDDEN ) {
return;
}
if ( !sections[item.group] ) {
sections[item.group] = [];
}
sections[item.group].push(item);
} else {
notInAnySection.push(item);
}
});
const allSections = [];
Object.keys(sections).forEach((key) => {
allSections.push({
title: key,
data: sections[key],
});
});
if ( notInAnySection.length ) {
allSections.push({ data: notInAnySection, });
}
const out = [];
allSections.forEach((section) => {
const data = [];
let dataIndex = 0;
out.push({
title: section.title,
data,
});
section.data.forEach((item, index) => {
if (index % 2 === 0) {
data.push([item])
dataIndex++
} else {
data[dataIndex - 1].push(item)
}
});
});
if (newQuestions.toString() !== oldQuestions.toString()) {
set(this, 'answerSections', out);
}
})),
change(event) {
if ( get(this, 'pasteOrUpload') ) {
return;
}
var input = event.target;
if ( input.files && input.files[0] ) {
let file = input.files[0];
var reader = new FileReader();
reader.onload = (event2) => {
var out = event2.target.result;
set(this, 'pastedAnswers', out);
input.value = '';
};
reader.onerror = (err) => {
get(this, 'growl').fromError(get(err, 'srcElement.error.message'));
};
reader.readAsText(file);
}
},
});