123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- 'use strict';
- const ArrayPrompt = require('../types/array');
- class Survey extends ArrayPrompt {
- constructor(options = {}) {
- super(options);
- this.emptyError = options.emptyError || 'No items were selected';
- this.term = process.env.TERM_PROGRAM;
- if (!this.options.header) {
- let header = ['', '4 - Strongly Agree', '3 - Agree', '2 - Neutral', '1 - Disagree', '0 - Strongly Disagree', ''];
- header = header.map(ele => this.styles.muted(ele));
- this.state.header = header.join('\n ');
- }
- }
- async toChoices(...args) {
- if (this.createdScales) return false;
- this.createdScales = true;
- let choices = await super.toChoices(...args);
- for (let choice of choices) {
- choice.scale = createScale(5, this.options);
- choice.scaleIdx = 2;
- }
- return choices;
- }
- dispatch() {
- this.alert();
- }
- space() {
- let choice = this.focused;
- let ele = choice.scale[choice.scaleIdx];
- let selected = ele.selected;
- choice.scale.forEach(e => (e.selected = false));
- ele.selected = !selected;
- return this.render();
- }
- indicator() {
- return '';
- }
- pointer() {
- return '';
- }
- separator() {
- return this.styles.muted(this.symbols.ellipsis);
- }
- right() {
- let choice = this.focused;
- if (choice.scaleIdx >= choice.scale.length - 1) return this.alert();
- choice.scaleIdx++;
- return this.render();
- }
- left() {
- let choice = this.focused;
- if (choice.scaleIdx <= 0) return this.alert();
- choice.scaleIdx--;
- return this.render();
- }
- indent() {
- return ' ';
- }
- async renderChoice(item, i) {
- await this.onChoice(item, i);
- let focused = this.index === i;
- let isHyper = this.term === 'Hyper';
- let n = !isHyper ? 8 : 9;
- let s = !isHyper ? ' ' : '';
- let ln = this.symbols.line.repeat(n);
- let sp = ' '.repeat(n + (isHyper ? 0 : 1));
- let dot = enabled => (enabled ? this.styles.success('◉') : '◯') + s;
- let num = i + 1 + '.';
- let color = focused ? this.styles.heading : this.styles.noop;
- let msg = await this.resolve(item.message, this.state, item, i);
- let indent = this.indent(item);
- let scale = indent + item.scale.map((e, i) => dot(i === item.scaleIdx)).join(ln);
- let val = i => i === item.scaleIdx ? color(i) : i;
- let next = indent + item.scale.map((e, i) => val(i)).join(sp);
- let line = () => [num, msg].filter(Boolean).join(' ');
- let lines = () => [line(), scale, next, ' '].filter(Boolean).join('\n');
- if (focused) {
- scale = this.styles.cyan(scale);
- next = this.styles.cyan(next);
- }
- return lines();
- }
- async renderChoices() {
- if (this.state.submitted) return '';
- let choices = this.visible.map(async(ch, i) => await this.renderChoice(ch, i));
- let visible = await Promise.all(choices);
- if (!visible.length) visible.push(this.styles.danger('No matching choices'));
- return visible.join('\n');
- }
- format() {
- if (this.state.submitted) {
- let values = this.choices.map(ch => this.styles.info(ch.scaleIdx));
- return values.join(', ');
- }
- return '';
- }
- async render() {
- let { submitted, size } = this.state;
- let prefix = await this.prefix();
- let separator = await this.separator();
- let message = await this.message();
- let prompt = [prefix, message, separator].filter(Boolean).join(' ');
- this.state.prompt = prompt;
- let header = await this.header();
- let output = await this.format();
- let help = await this.error() || await this.hint();
- let body = await this.renderChoices();
- let footer = await this.footer();
- if (output || !help) prompt += ' ' + output;
- if (help && !prompt.includes(help)) prompt += ' ' + help;
- if (submitted && !output && !body && this.multiple && this.type !== 'form') {
- prompt += this.styles.danger(this.emptyError);
- }
- this.clear(size);
- this.write([prompt, header, body, footer].filter(Boolean).join('\n'));
- this.restore();
- }
- submit() {
- this.value = {};
- for (let choice of this.choices) {
- this.value[choice.name] = choice.scaleIdx;
- }
- return this.base.submit.call(this);
- }
- }
- function createScale(n, options = {}) {
- if (Array.isArray(options.scale)) {
- return options.scale.map(ele => ({ ...ele }));
- }
- let scale = [];
- for (let i = 1; i < n + 1; i++) scale.push({ i, selected: false });
- return scale;
- }
- module.exports = Survey;
|