Spaces:
Runtime error
Runtime error
; | |
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; | |