import {OOElement} from '../oo-element' import {html, render} from '../../lib/html' import weakMap from '../../lib/weak-map' import {Scope} from '../../type/scope' import {ChangeAskDetail, ChangeAsk} from '../../type/event' import session from '../../lib/session-storage' import customEvent from '../../lib/custom-event' import autosize from 'autosize' import taboverride from 'taboverride' import {asTags, asScope} from '../../lib/as' import tagsInput from 'tags-input' import {currencyToSign} from '../../lib/get-price-per-hour' import getInitPrice from '../../lib/get-init-price' import {Currency} from '../../type/currency' import getCurrency from '../../lib/get-currency' interface HTMLElementEvent extends Event { target: T } const ATTR = { DATA_IAM: 'data-iam', DATA_TITLE: 'data-title', DATA_TAGS: 'data-tags', DATA_SCOPE: 'data-scope' } const EVENT = { CHANGED: (detail: ChangeAskDetail): ChangeAsk => customEvent('changed', detail) } const iam = weakMap() const message = weakMap() const stateTitle = weakMap() const stateScope = weakMap() const stateTags = weakMap>() const stateCurrency = weakMap() const stateTextareaElement = weakMap() const stateInitialData = weakMap<{ iam?: string, title?: string, body?: string, tags?: Array, scope?: Scope }>() const initialization = (el: OOElement) => { if (el.textContent || el.hasAttribute(ATTR.DATA_TITLE)) { message.set(el, el.textContent || '') stateTitle.set(el, el.getAttribute(ATTR.DATA_TITLE) || '') stateInitialData.set(el, { title: stateTitle.get(el), body: message.get(el) }) } } const removeTagsInput = (el: OOElement) => { const tagsEl = el.shadowRoot && el.shadowRoot.querySelector('.tags-input') if (tagsEl) { tagsEl.parentElement.removeChild(tagsEl) } } const removeVendorElements = (el: OOElement): boolean => { try { removeTagsInput(el) return true } catch(err) { return false } } const cleanUp = (el: OOElement): boolean => { try { removeVendorElements(el) render(html``, el) return true } catch(err) { return false } } export default class extends OOElement { static get observedAttributes() { return [ATTR.DATA_IAM, ATTR.DATA_TAGS, ATTR.DATA_SCOPE] } constructor() { super() message.set(this, '') stateScope.set(this, 'public') stateCurrency.set(this, getCurrency()) } get message() { return message.get(this) || '' } get tags() { return stateTags.get(this) || [] } get scope() { return asScope(stateScope.get(this)) } get dontAssign() { return !Boolean(iam.get(this)) } attributeChangedCallback(attr, prev, next) { if (prev === next) { return } switch (attr) { case ATTR.DATA_IAM: iam.set(this, next) const prevAsk = session.previousAsk if (prevAsk) { if (prevAsk.iam === iam.get(this)) { stateInitialData.set(this, prevAsk) stateTitle.set(this, prevAsk.title) message.set(this, prevAsk.body) } } break case ATTR.DATA_TAGS: stateTags.set(this, asTags(next)) break case ATTR.DATA_SCOPE: stateScope.set(this, asScope(next)) break default: break } if (this.connected) { cleanUp(this) this.update() } } connectedCallback() { initialization(this) super.connectedCallback() this.dispatchChanged() } disconnectedCallback() { super.disconnectedCallback() const textarea = stateTextareaElement.get(this) if (textarea) { autosize.destroy(textarea) taboverride.utils.removeListeners(textarea) stateTextareaElement.delete(this) } } render() { const init = stateInitialData.get(this) const { title = '', body = '' } = init || {} const {tags, scope} = this const currency = stateCurrency.get(this) const price = getInitPrice(currency) const {amount} = price const sign = currencyToSign(currency) const cost = `${currency.toUpperCase()} ${sign}${amount}` const showCost = (s: Scope) => { if (s === 'private') { return html`Pay ${cost} later` } return html`` } return html` ${showCost(scope)}
` } renderedCallback() { if (!stateTextareaElement.get(this)) { const textarea = this.shadowRoot.querySelector('textarea') if (textarea) { stateTextareaElement.set(this, textarea) autosize(textarea) taboverride.set(textarea) } } const input = this.shadowRoot.querySelector('input[name=tags]') if (input) { tagsInput(input) } } updateSession() { session.previousAsk = { iam: iam.get(this), title: stateTitle.get(this) || '', body: this.message } } removeSession() { session.remove('oo:previous-ask') } onTitleChange(e: HTMLElementEvent) { const {target} = e const {value} = target stateTitle.set(this, value || '') this.dispatchChanged() } onMessageChange(e: HTMLElementEvent) { const {target} = e const {value} = target message.set(this, value || '') this.dispatchChanged() } onTagsChange(e: HTMLElementEvent) { const {target} = e const {value} = target stateTags.set(this, asTags(value)) this.dispatchChanged() } dispatchChanged() { const detail = { title: stateTitle.get(this) || '', message: this.message, tags: this.tags, scope: this.scope, currency: stateCurrency.get(this) } this.updateSession() this.dispatchEvent(EVENT.CHANGED(detail)) } }