/** @odoo-module */
import {
Component,
onWillRender,
onWillUpdateProps,
xml as owlXml,
toRaw,
useState,
} from "@odoo/owl";
import { isNode, toSelector } from "@web/../lib/hoot-dom/helpers/dom";
import { isIterable } from "@web/../lib/hoot-dom/hoot_dom_utils";
import { logger } from "../core/logger";
import { getTypeOf, Markup, stringify, toExplicitString } from "../hoot_utils";
/**
* @typedef {{
* value?: any;
* }} TechnicalValueProps
*/
//-----------------------------------------------------------------------------
// Global
//-----------------------------------------------------------------------------
const {
Object: { keys: $keys },
} = globalThis;
//-----------------------------------------------------------------------------
// Internal
//-----------------------------------------------------------------------------
/**
* Compacted version of {@link owlXml} removing all whitespace between tags.
*
* @type {typeof String.raw}
*/
const xml = (template, ...substitutions) =>
owlXml({
raw: String.raw(template, ...substitutions)
.replace(/>\s+/g, ">")
.replace(/\s+} */
export class HootTechnicalValue extends Component {
static components = { HootTechnicalValue };
static props = {
value: { optional: true },
};
static template = xml`
[
]
{
}
`;
getTypeOf = getTypeOf;
isIterable = isIterable;
isNode = isNode;
stringify = stringify;
toSelector = toSelector;
get explicitValue() {
return toExplicitString(this.value);
}
setup() {
this.logged = false;
this.state = useState({
open: false,
promiseState: null,
});
this.wrapPromiseValue(this.props.value);
onWillRender(() => {
this.isMarkup = Markup.isMarkup(this.props.value);
this.value = toRaw(this.props.value);
});
onWillUpdateProps((nextProps) => {
this.state.open = false;
this.wrapPromiseValue(nextProps.value);
});
}
onClick() {
this.log(this.value);
this.state.open = !this.state.open;
}
getLabelAndSize() {
if (this.value instanceof Date) {
return [this.value.toISOString(), null];
}
if (this.value instanceof RegExp) {
return [String(this.value), null];
}
return [this.value.constructor.name, this.getSize()];
}
getSize() {
for (const Class of INVARIABLE_OBJECTS) {
if (this.value instanceof Class) {
return null;
}
}
const values = isIterable(this.value) ? [...this.value] : $keys(this.value);
return values.length;
}
displayComma(value) {
return value && typeof value === "object" ? "" : ",";
}
log() {
if (this.logged) {
return;
}
this.logged = true;
logger.debug(this.value);
}
wrapPromiseValue(promise) {
if (!(promise instanceof Promise)) {
return;
}
this.state.promiseState = ["pending", null];
Promise.resolve(promise).then(
(value) => {
this.state.promiseState = ["fulfilled", value];
return value;
},
(reason) => {
this.state.promiseState = ["rejected", reason];
throw reason;
}
);
}
}