@miso.ai/client-sdk-ui 1.9.0-beta.8 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/combo/ask/index.js +6 -0
- package/dist/cjs/combo/ask/options.js +39 -6
- package/dist/cjs/combo/ask/phrases.js +10 -0
- package/dist/cjs/combo/ask/templates.js +21 -20
- package/dist/cjs/combo/base.js +4 -1
- package/dist/cjs/element/combo/miso-combo.js +1 -1
- package/dist/cjs/plugin.js +6 -6
- package/dist/cjs/styles.js +77 -0
- package/dist/cjs/version.js +1 -1
- package/package.json +2 -2
- package/src/combo/ask/index.js +7 -0
- package/src/combo/ask/options.js +37 -3
- package/src/combo/ask/phrases.js +7 -0
- package/src/combo/ask/templates.js +17 -10
- package/src/combo/base.js +4 -1
- package/src/element/combo/miso-combo.js +1 -1
- package/src/plugin.js +8 -3
- package/src/styles.js +74 -0
- package/src/version.js +1 -1
|
@@ -18,6 +18,7 @@ class AskCombo extends _base.default {
|
|
|
18
18
|
plugin,
|
|
19
19
|
MisoClient
|
|
20
20
|
});
|
|
21
|
+
// TODO: extract options to super class
|
|
21
22
|
this._options = new _options.default();
|
|
22
23
|
this._localOptions = {};
|
|
23
24
|
}
|
|
@@ -41,6 +42,9 @@ class AskCombo extends _base.default {
|
|
|
41
42
|
get elements() {
|
|
42
43
|
return this._elements;
|
|
43
44
|
}
|
|
45
|
+
autoStart() {
|
|
46
|
+
this.resolvedOptions.autostart && this.start();
|
|
47
|
+
}
|
|
44
48
|
async _start() {
|
|
45
49
|
await (0, _commons.waitForDomContentLoaded)();
|
|
46
50
|
await this.MisoClient.cmdDone;
|
|
@@ -111,6 +115,8 @@ class AskCombo extends _base.default {
|
|
|
111
115
|
const context = client.ui.asks;
|
|
112
116
|
const rootWorkflow = client.ui.ask;
|
|
113
117
|
|
|
118
|
+
// TODO: set placeholder is present in options
|
|
119
|
+
|
|
114
120
|
// when a answer is fully populated, insert a new section for the follow-up question
|
|
115
121
|
context.on('done', _ref => {
|
|
116
122
|
let {
|
|
@@ -6,7 +6,8 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.default = void 0;
|
|
7
7
|
var _commons = require("@miso.ai/commons");
|
|
8
8
|
var templates = _interopRequireWildcard(require("./templates.js"));
|
|
9
|
-
|
|
9
|
+
var phrases = _interopRequireWildcard(require("./phrases.js"));
|
|
10
|
+
const _excluded = ["api_key", "api_host", "templates", "phrases"];
|
|
10
11
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
11
12
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
|
|
12
13
|
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
@@ -16,7 +17,9 @@ const {
|
|
|
16
17
|
currentScript
|
|
17
18
|
} = document;
|
|
18
19
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
19
|
-
templates
|
|
20
|
+
templates,
|
|
21
|
+
phrases,
|
|
22
|
+
autostart: true
|
|
20
23
|
});
|
|
21
24
|
class AskComboOptions {
|
|
22
25
|
constructor() {
|
|
@@ -50,12 +53,16 @@ function normalizeOptions() {
|
|
|
50
53
|
let _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
51
54
|
let {
|
|
52
55
|
api_key: apiKey,
|
|
53
|
-
api_host: apiHost
|
|
56
|
+
api_host: apiHost,
|
|
57
|
+
templates,
|
|
58
|
+
phrases
|
|
54
59
|
} = _ref,
|
|
55
60
|
options = _objectWithoutPropertiesLoose(_ref, _excluded);
|
|
56
61
|
return (0, _commons.trimObj)(Object.assign({
|
|
57
62
|
apiKey,
|
|
58
|
-
apiHost
|
|
63
|
+
apiHost,
|
|
64
|
+
templates: templateAsFunction(templates),
|
|
65
|
+
phrases: templateAsFunction(phrases)
|
|
59
66
|
}, options));
|
|
60
67
|
}
|
|
61
68
|
|
|
@@ -74,7 +81,7 @@ function readFromScriptSrc() {
|
|
|
74
81
|
if (key === 'q') {
|
|
75
82
|
continue;
|
|
76
83
|
}
|
|
77
|
-
params[key] = value
|
|
84
|
+
params[key] = coerceValue(value);
|
|
78
85
|
}
|
|
79
86
|
return params;
|
|
80
87
|
}
|
|
@@ -88,10 +95,36 @@ function readFromPageUrl() {
|
|
|
88
95
|
const params = {};
|
|
89
96
|
for (const [key, value] of new URLSearchParams(window.location.search)) {
|
|
90
97
|
if (key.startsWith('miso_') && key.length > 5 && key !== 'miso_api_key') {
|
|
91
|
-
params[key.substring(5)] = value
|
|
98
|
+
params[key.substring(5)] = coerceValue(value);
|
|
92
99
|
} else if (key === 'q') {
|
|
93
100
|
params.q = value;
|
|
94
101
|
}
|
|
95
102
|
}
|
|
96
103
|
return params;
|
|
104
|
+
}
|
|
105
|
+
function coerceValue(value) {
|
|
106
|
+
return value === '' ? true : value === 'false' ? false : value;
|
|
107
|
+
}
|
|
108
|
+
function templateAsFunction(value) {
|
|
109
|
+
if (value === undefined || value === null) {
|
|
110
|
+
return value;
|
|
111
|
+
}
|
|
112
|
+
switch (typeof value) {
|
|
113
|
+
case 'function':
|
|
114
|
+
return value;
|
|
115
|
+
case 'string':
|
|
116
|
+
case 'number':
|
|
117
|
+
return () => value;
|
|
118
|
+
case 'object':
|
|
119
|
+
return Array.isArray(value) ? value.map(templateAsFunction) : mappingObjectValues(value, templateAsFunction);
|
|
120
|
+
default:
|
|
121
|
+
throw new Error(`Unsupported template type: ${value}`);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function mappingObjectValues(obj, fn) {
|
|
125
|
+
const mapped = {};
|
|
126
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
127
|
+
mapped[key] = fn(value);
|
|
128
|
+
}
|
|
129
|
+
return mapped;
|
|
97
130
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.sources = exports.relatedResources = exports.relatedQuestions = exports.question = void 0;
|
|
7
|
+
const question = exports.question = 'You asked...';
|
|
8
|
+
const sources = exports.sources = 'My reply is based on the following';
|
|
9
|
+
const relatedQuestions = exports.relatedQuestions = 'Related questions you can explore';
|
|
10
|
+
const relatedResources = exports.relatedResources = 'Go beyond, and learn more about this topic';
|
|
@@ -17,50 +17,50 @@ const root = options => `
|
|
|
17
17
|
<section class="${_constants.PREFIX}__section ${_constants.PREFIX}__answer">
|
|
18
18
|
${options.templates.answer(options)}
|
|
19
19
|
${options.templates.sources(options)}
|
|
20
|
+
<miso-ask class="${_constants.PREFIX}__bottom-spacing-container" visible-when="ongoing"></miso-ask>
|
|
20
21
|
</section>
|
|
21
22
|
<div id="${_constants.PREFIX}__follow-ups" class="${_constants.PREFIX}__follow-ups"></div>
|
|
22
23
|
<section id="${_constants.PREFIX}__related-resources" class="${_constants.PREFIX}__section ${_constants.PREFIX}__related-resources">
|
|
23
24
|
<miso-ask visible-when="nonempty" logo="true">
|
|
24
|
-
<h2 class="${_constants.PREFIX}__phrase ${_constants.PREFIX}__related-resources-phrase"
|
|
25
|
+
<h2 class="${_constants.PREFIX}__phrase ${_constants.PREFIX}__related-resources-phrase">${options.phrases.relatedResources(options)}</h2>
|
|
25
26
|
<miso-related-resources></miso-related-resources>
|
|
26
27
|
</miso-ask>
|
|
27
28
|
</section>
|
|
28
29
|
`.trim();
|
|
29
30
|
exports.root = root;
|
|
30
|
-
const followUp = (options
|
|
31
|
-
let {
|
|
31
|
+
const followUp = function (options) {
|
|
32
|
+
let session = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
33
|
+
const {
|
|
32
34
|
parentQuestionId
|
|
33
|
-
} =
|
|
35
|
+
} = session;
|
|
34
36
|
return `
|
|
35
37
|
<section class="${_constants.PREFIX}__section ${_constants.PREFIX}__follow-up">
|
|
36
|
-
<miso-ask class="${_constants.PREFIX}__query-suggestions-container" visible-when="initial" parent-question-id="${parentQuestionId}">
|
|
37
|
-
<h3 class="${_constants.PREFIX}__phrase ${_constants.PREFIX}__related-questions-phrase"
|
|
38
|
+
<miso-ask class="${_constants.PREFIX}__query-suggestions-container" visible-when="initial+nonempty" parent-question-id="${parentQuestionId}">
|
|
39
|
+
<h3 class="${_constants.PREFIX}__phrase ${_constants.PREFIX}__related-questions-phrase">${options.phrases.relatedQuestions(options, session)}</h3>
|
|
38
40
|
<miso-query-suggestions></miso-query-suggestions>
|
|
39
41
|
</miso-ask>
|
|
40
42
|
<miso-ask class="${_constants.PREFIX}__query-container" visible-when="initial loading" parent-question-id="${parentQuestionId}">
|
|
41
43
|
<miso-query></miso-query>
|
|
42
44
|
</miso-ask>
|
|
43
|
-
${options.templates.answer(options,
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
${options.templates.sources(options, {
|
|
47
|
-
parentQuestionId
|
|
48
|
-
})}
|
|
45
|
+
${options.templates.answer(options, session)}
|
|
46
|
+
${options.templates.sources(options, session)}
|
|
47
|
+
<miso-ask class="${_constants.PREFIX}__bottom-spacing-container" visible-when="ongoing" parent-question-id="${parentQuestionId}"></miso-ask>
|
|
49
48
|
</section>
|
|
50
49
|
`.trim();
|
|
51
50
|
};
|
|
52
51
|
exports.followUp = followUp;
|
|
53
52
|
const answer = function (options) {
|
|
54
|
-
let {
|
|
55
|
-
parentQuestionId
|
|
56
|
-
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
53
|
+
let session = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
57
54
|
// TODO: include/omit miso-circled-citation-index by options
|
|
55
|
+
const {
|
|
56
|
+
parentQuestionId
|
|
57
|
+
} = session;
|
|
58
58
|
const openTag = `<miso-ask class="${_constants.PREFIX}__answer-container miso-circled-citation-index" visible-when="ready" logo="false"${parentQuestionId ? ` parent-question-id="${parentQuestionId}"` : ''}>`;
|
|
59
59
|
const closeTag = '</miso-ask>';
|
|
60
60
|
return `
|
|
61
61
|
${openTag}
|
|
62
62
|
${parentQuestionId ? '<hr>' : ''}
|
|
63
|
-
<div class="${_constants.PREFIX}__phrase ${_constants.PREFIX}__question-phrase"
|
|
63
|
+
<div class="${_constants.PREFIX}__phrase ${_constants.PREFIX}__question-phrase">${options.phrases.question(options, session)}</div>
|
|
64
64
|
<miso-question></miso-question>
|
|
65
65
|
<miso-answer></miso-answer>
|
|
66
66
|
<miso-feedback></miso-feedback>
|
|
@@ -69,16 +69,17 @@ ${closeTag}
|
|
|
69
69
|
};
|
|
70
70
|
exports.answer = answer;
|
|
71
71
|
const sources = function (options) {
|
|
72
|
-
let {
|
|
73
|
-
parentQuestionId
|
|
74
|
-
} = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
72
|
+
let session = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
75
73
|
// TODO: include/omit miso-circled-citation-index by options
|
|
74
|
+
const {
|
|
75
|
+
parentQuestionId
|
|
76
|
+
} = session;
|
|
76
77
|
const openTag = `<miso-ask class="${_constants.PREFIX}__sources-container miso-circled-citation-index" visible-when="nonempty" logo="false"${parentQuestionId ? ` parent-question-id="${parentQuestionId}"` : ''}>`;
|
|
77
78
|
const closeTag = '</miso-ask>';
|
|
78
79
|
return `
|
|
79
80
|
${openTag}
|
|
80
81
|
<hr>
|
|
81
|
-
<h3 class="${_constants.PREFIX}__phrase ${_constants.PREFIX}__sources-phrase"
|
|
82
|
+
<h3 class="${_constants.PREFIX}__phrase ${_constants.PREFIX}__sources-phrase">${options.phrases.sources(options, session)}</h3>
|
|
82
83
|
<miso-sources></miso-sources>
|
|
83
84
|
${closeTag}
|
|
84
85
|
`.trim();
|
package/dist/cjs/combo/base.js
CHANGED
|
@@ -30,11 +30,14 @@ class Combo extends _commons.Component {
|
|
|
30
30
|
set element(element) {
|
|
31
31
|
this._element = element;
|
|
32
32
|
}
|
|
33
|
-
start() {
|
|
33
|
+
start(options) {
|
|
34
34
|
if (this._started) {
|
|
35
35
|
return;
|
|
36
36
|
}
|
|
37
37
|
this._started = true;
|
|
38
|
+
if (options) {
|
|
39
|
+
this.config(options);
|
|
40
|
+
}
|
|
38
41
|
this._start();
|
|
39
42
|
}
|
|
40
43
|
_start() {
|
package/dist/cjs/plugin.js
CHANGED
|
@@ -11,6 +11,7 @@ var _layouts = _interopRequireDefault(require("./layouts.js"));
|
|
|
11
11
|
var elements = _interopRequireWildcard(require("./element/index.js"));
|
|
12
12
|
var layouts = _interopRequireWildcard(require("./layout/index.js"));
|
|
13
13
|
var sources = _interopRequireWildcard(require("./source/index.js"));
|
|
14
|
+
var _styles = require("./styles.js");
|
|
14
15
|
var _misoContainer = _interopRequireDefault(require("./element/container/miso-container.js"));
|
|
15
16
|
var _misoCombo = _interopRequireDefault(require("./element/combo/miso-combo.js"));
|
|
16
17
|
const _excluded = ["containers", "roles", "combos"];
|
|
@@ -24,18 +25,13 @@ class UiPlugin extends _commons.Component {
|
|
|
24
25
|
return PLUGIN_ID;
|
|
25
26
|
}
|
|
26
27
|
constructor() {
|
|
27
|
-
let {
|
|
28
|
-
loadStyles = true
|
|
29
|
-
} = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
30
28
|
super('ui');
|
|
31
29
|
this.layouts = new _layouts.default(this);
|
|
32
30
|
this._recommendations = new WeakMap();
|
|
33
31
|
this._asks = new WeakMap();
|
|
34
32
|
this._extensions = new WeakMap();
|
|
35
|
-
// TODO: load CSS
|
|
36
33
|
}
|
|
37
|
-
|
|
38
|
-
install(MisoClient, context) {
|
|
34
|
+
async install(MisoClient, context) {
|
|
39
35
|
context.addSubtree(this);
|
|
40
36
|
MisoClient.on('create', this._injectClient.bind(this));
|
|
41
37
|
const ui = {};
|
|
@@ -75,6 +71,10 @@ class UiPlugin extends _commons.Component {
|
|
|
75
71
|
ElementClass.MisoClient = MisoClient; // TODO: find better way
|
|
76
72
|
}
|
|
77
73
|
|
|
74
|
+
// load styles
|
|
75
|
+
await (0, _styles.loadStylesIfNecessary)();
|
|
76
|
+
|
|
77
|
+
// define custom elements
|
|
78
78
|
for (const ElementClass of ElementClasses) {
|
|
79
79
|
(0, _commons.defineAndUpgrade)(ElementClass);
|
|
80
80
|
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.loadStyles = loadStyles;
|
|
7
|
+
exports.loadStylesIfNecessary = loadStylesIfNecessary;
|
|
8
|
+
var _version = _interopRequireDefault(require("./version.js"));
|
|
9
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
10
|
+
const {
|
|
11
|
+
currentScript
|
|
12
|
+
} = document;
|
|
13
|
+
let cssUrl;
|
|
14
|
+
let stylesLoaded;
|
|
15
|
+
async function loadStylesIfNecessary() {
|
|
16
|
+
return stylesLoaded || (stylesLoaded = loadStyles());
|
|
17
|
+
}
|
|
18
|
+
async function loadStyles() {
|
|
19
|
+
try {
|
|
20
|
+
let link = getExistedLinkElement();
|
|
21
|
+
if (link) {
|
|
22
|
+
return waitForLinkLoaded(link);
|
|
23
|
+
}
|
|
24
|
+
link = document.createElement('link');
|
|
25
|
+
link.rel = 'stylesheet';
|
|
26
|
+
link.href = getCssUrl();
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
link.onload = resolve;
|
|
29
|
+
link.onerror = reject;
|
|
30
|
+
document.head.appendChild(link);
|
|
31
|
+
});
|
|
32
|
+
} catch (e) {
|
|
33
|
+
console.error(e);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// helpers //
|
|
38
|
+
function getCssUrl() {
|
|
39
|
+
return cssUrl || (cssUrl = resolveCssUrl());
|
|
40
|
+
}
|
|
41
|
+
function resolveCssUrl() {
|
|
42
|
+
// TODO: refactor with getPluginScriptUrl() in core
|
|
43
|
+
if (_version.default === 'dev') {
|
|
44
|
+
const src = currentScript.src;
|
|
45
|
+
const searchIndex = src.indexOf('?');
|
|
46
|
+
const k = searchIndex < 0 ? src.length : searchIndex;
|
|
47
|
+
const i = src.lastIndexOf('/', k); // .../dist/umd/*.min.js
|
|
48
|
+
return `${src.slice(0, i - 4)}/css/ui.css`;
|
|
49
|
+
} else {
|
|
50
|
+
return `https://cdn.jsdelivr.net/npm/@miso.ai/client-sdk@${_version.default}/dist/css/ui.css`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function getExistedLinkElement() {
|
|
54
|
+
return document.head.querySelector(`link[href="${getCssUrl()}"]`);
|
|
55
|
+
}
|
|
56
|
+
async function waitForLinkLoaded(element) {
|
|
57
|
+
if (element.sheet) {
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
return new Promise((resolve, reject) => {
|
|
61
|
+
let intervalId;
|
|
62
|
+
element.onload = () => {
|
|
63
|
+
intervalId && clearInterval(intervalId);
|
|
64
|
+
resolve();
|
|
65
|
+
};
|
|
66
|
+
element.onerror = () => {
|
|
67
|
+
intervalId && clearInterval(intervalId);
|
|
68
|
+
reject();
|
|
69
|
+
};
|
|
70
|
+
intervalId = setInterval(() => {
|
|
71
|
+
if (element.sheet) {
|
|
72
|
+
intervalId && clearInterval(intervalId);
|
|
73
|
+
resolve();
|
|
74
|
+
}
|
|
75
|
+
}, 100);
|
|
76
|
+
});
|
|
77
|
+
}
|
package/dist/cjs/version.js
CHANGED
package/package.json
CHANGED
package/src/combo/ask/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export default class AskCombo extends Combo {
|
|
|
13
13
|
plugin,
|
|
14
14
|
MisoClient,
|
|
15
15
|
});
|
|
16
|
+
// TODO: extract options to super class
|
|
16
17
|
this._options = new AskComboOptions();
|
|
17
18
|
this._localOptions = {};
|
|
18
19
|
}
|
|
@@ -40,6 +41,10 @@ export default class AskCombo extends Combo {
|
|
|
40
41
|
return this._elements;
|
|
41
42
|
}
|
|
42
43
|
|
|
44
|
+
autoStart() {
|
|
45
|
+
this.resolvedOptions.autostart && this.start();
|
|
46
|
+
}
|
|
47
|
+
|
|
43
48
|
async _start() {
|
|
44
49
|
await waitForDomContentLoaded();
|
|
45
50
|
await this.MisoClient.cmdDone;
|
|
@@ -100,6 +105,8 @@ export default class AskCombo extends Combo {
|
|
|
100
105
|
const context = client.ui.asks;
|
|
101
106
|
const rootWorkflow = client.ui.ask;
|
|
102
107
|
|
|
108
|
+
// TODO: set placeholder is present in options
|
|
109
|
+
|
|
103
110
|
// when a answer is fully populated, insert a new section for the follow-up question
|
|
104
111
|
context.on('done', ({ workflow }) => {
|
|
105
112
|
elements.followUpsSection.insertAdjacentHTML('beforeend', templates.followUp(options, { parentQuestionId: workflow.questionId }));
|
package/src/combo/ask/options.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { trimObj } from '@miso.ai/commons';
|
|
2
2
|
import * as templates from './templates.js';
|
|
3
|
+
import * as phrases from './phrases.js';
|
|
3
4
|
|
|
4
5
|
// TODO: generalize
|
|
5
6
|
|
|
@@ -7,6 +8,8 @@ const { currentScript } = document;
|
|
|
7
8
|
|
|
8
9
|
const DEFAULT_OPTIONS = Object.freeze({
|
|
9
10
|
templates,
|
|
11
|
+
phrases,
|
|
12
|
+
autostart: true,
|
|
10
13
|
});
|
|
11
14
|
|
|
12
15
|
export default class AskComboOptions {
|
|
@@ -40,10 +43,12 @@ function mergeTwoOptions(merged, overrides) {
|
|
|
40
43
|
});
|
|
41
44
|
}
|
|
42
45
|
|
|
43
|
-
function normalizeOptions({ api_key: apiKey, api_host: apiHost, ...options } = {}) {
|
|
46
|
+
function normalizeOptions({ api_key: apiKey, api_host: apiHost, templates, phrases, ...options } = {}) {
|
|
44
47
|
return trimObj({
|
|
45
48
|
apiKey,
|
|
46
49
|
apiHost,
|
|
50
|
+
templates: templateAsFunction(templates),
|
|
51
|
+
phrases: templateAsFunction(phrases),
|
|
47
52
|
...options,
|
|
48
53
|
});
|
|
49
54
|
}
|
|
@@ -64,7 +69,7 @@ function readFromScriptSrc() {
|
|
|
64
69
|
if (key === 'q') {
|
|
65
70
|
continue;
|
|
66
71
|
}
|
|
67
|
-
params[key] = value
|
|
72
|
+
params[key] = coerceValue(value);
|
|
68
73
|
}
|
|
69
74
|
return params;
|
|
70
75
|
}
|
|
@@ -78,10 +83,39 @@ function readFromPageUrl() {
|
|
|
78
83
|
const params = {};
|
|
79
84
|
for (const [key, value] of new URLSearchParams(window.location.search)) {
|
|
80
85
|
if (key.startsWith('miso_') && key.length > 5 && key !== 'miso_api_key') {
|
|
81
|
-
params[key.substring(5)] = value
|
|
86
|
+
params[key.substring(5)] = coerceValue(value);
|
|
82
87
|
} else if (key === 'q') {
|
|
83
88
|
params.q = value;
|
|
84
89
|
}
|
|
85
90
|
}
|
|
86
91
|
return params;
|
|
87
92
|
}
|
|
93
|
+
|
|
94
|
+
function coerceValue(value) {
|
|
95
|
+
return value === '' ? true : value === 'false' ? false : value;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function templateAsFunction(value) {
|
|
99
|
+
if (value === undefined || value === null) {
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
switch (typeof value) {
|
|
103
|
+
case 'function':
|
|
104
|
+
return value;
|
|
105
|
+
case 'string':
|
|
106
|
+
case 'number':
|
|
107
|
+
return () => value;
|
|
108
|
+
case 'object':
|
|
109
|
+
return Array.isArray(value) ? value.map(templateAsFunction) : mappingObjectValues(value, templateAsFunction);
|
|
110
|
+
default:
|
|
111
|
+
throw new Error(`Unsupported template type: ${value}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function mappingObjectValues(obj, fn) {
|
|
116
|
+
const mapped = {};
|
|
117
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
118
|
+
mapped[key] = fn(value);
|
|
119
|
+
}
|
|
120
|
+
return mapped;
|
|
121
|
+
}
|
|
@@ -12,38 +12,44 @@ export const root = (options) => `
|
|
|
12
12
|
<section class="${PREFIX}__section ${PREFIX}__answer">
|
|
13
13
|
${options.templates.answer(options)}
|
|
14
14
|
${options.templates.sources(options)}
|
|
15
|
+
<miso-ask class="${PREFIX}__bottom-spacing-container" visible-when="ongoing"></miso-ask>
|
|
15
16
|
</section>
|
|
16
17
|
<div id="${PREFIX}__follow-ups" class="${PREFIX}__follow-ups"></div>
|
|
17
18
|
<section id="${PREFIX}__related-resources" class="${PREFIX}__section ${PREFIX}__related-resources">
|
|
18
19
|
<miso-ask visible-when="nonempty" logo="true">
|
|
19
|
-
<h2 class="${PREFIX}__phrase ${PREFIX}__related-resources-phrase"
|
|
20
|
+
<h2 class="${PREFIX}__phrase ${PREFIX}__related-resources-phrase">${options.phrases.relatedResources(options)}</h2>
|
|
20
21
|
<miso-related-resources></miso-related-resources>
|
|
21
22
|
</miso-ask>
|
|
22
23
|
</section>
|
|
23
24
|
`.trim();
|
|
24
25
|
|
|
25
|
-
export const followUp = (options,
|
|
26
|
+
export const followUp = (options, session = {}) => {
|
|
27
|
+
const { parentQuestionId } = session;
|
|
28
|
+
return `
|
|
26
29
|
<section class="${PREFIX}__section ${PREFIX}__follow-up">
|
|
27
|
-
<miso-ask class="${PREFIX}__query-suggestions-container" visible-when="initial" parent-question-id="${parentQuestionId}">
|
|
28
|
-
<h3 class="${PREFIX}__phrase ${PREFIX}__related-questions-phrase"
|
|
30
|
+
<miso-ask class="${PREFIX}__query-suggestions-container" visible-when="initial+nonempty" parent-question-id="${parentQuestionId}">
|
|
31
|
+
<h3 class="${PREFIX}__phrase ${PREFIX}__related-questions-phrase">${options.phrases.relatedQuestions(options, session)}</h3>
|
|
29
32
|
<miso-query-suggestions></miso-query-suggestions>
|
|
30
33
|
</miso-ask>
|
|
31
34
|
<miso-ask class="${PREFIX}__query-container" visible-when="initial loading" parent-question-id="${parentQuestionId}">
|
|
32
35
|
<miso-query></miso-query>
|
|
33
36
|
</miso-ask>
|
|
34
|
-
${options.templates.answer(options,
|
|
35
|
-
${options.templates.sources(options,
|
|
37
|
+
${options.templates.answer(options, session)}
|
|
38
|
+
${options.templates.sources(options, session)}
|
|
39
|
+
<miso-ask class="${PREFIX}__bottom-spacing-container" visible-when="ongoing" parent-question-id="${parentQuestionId}"></miso-ask>
|
|
36
40
|
</section>
|
|
37
41
|
`.trim();
|
|
42
|
+
};
|
|
38
43
|
|
|
39
|
-
export const answer = (options,
|
|
44
|
+
export const answer = (options, session = {}) => {
|
|
40
45
|
// TODO: include/omit miso-circled-citation-index by options
|
|
46
|
+
const { parentQuestionId } = session;
|
|
41
47
|
const openTag = `<miso-ask class="${PREFIX}__answer-container miso-circled-citation-index" visible-when="ready" logo="false"${parentQuestionId ? ` parent-question-id="${parentQuestionId}"` : ''}>`;
|
|
42
48
|
const closeTag = '</miso-ask>';
|
|
43
49
|
return `
|
|
44
50
|
${openTag}
|
|
45
51
|
${ parentQuestionId ? '<hr>' : '' }
|
|
46
|
-
<div class="${PREFIX}__phrase ${PREFIX}__question-phrase"
|
|
52
|
+
<div class="${PREFIX}__phrase ${PREFIX}__question-phrase">${options.phrases.question(options, session)}</div>
|
|
47
53
|
<miso-question></miso-question>
|
|
48
54
|
<miso-answer></miso-answer>
|
|
49
55
|
<miso-feedback></miso-feedback>
|
|
@@ -51,14 +57,15 @@ ${closeTag}
|
|
|
51
57
|
`.trim();
|
|
52
58
|
};
|
|
53
59
|
|
|
54
|
-
export const sources = (options,
|
|
60
|
+
export const sources = (options, session = {}) => {
|
|
55
61
|
// TODO: include/omit miso-circled-citation-index by options
|
|
62
|
+
const { parentQuestionId } = session;
|
|
56
63
|
const openTag = `<miso-ask class="${PREFIX}__sources-container miso-circled-citation-index" visible-when="nonempty" logo="false"${parentQuestionId ? ` parent-question-id="${parentQuestionId}"` : ''}>`;
|
|
57
64
|
const closeTag = '</miso-ask>';
|
|
58
65
|
return `
|
|
59
66
|
${openTag}
|
|
60
67
|
<hr>
|
|
61
|
-
<h3 class="${PREFIX}__phrase ${PREFIX}__sources-phrase"
|
|
68
|
+
<h3 class="${PREFIX}__phrase ${PREFIX}__sources-phrase">${options.phrases.sources(options, session)}</h3>
|
|
62
69
|
<miso-sources></miso-sources>
|
|
63
70
|
${closeTag}
|
|
64
71
|
`.trim();
|
package/src/combo/base.js
CHANGED
|
@@ -27,11 +27,14 @@ export default class Combo extends Component {
|
|
|
27
27
|
this._element = element;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
start() {
|
|
30
|
+
start(options) {
|
|
31
31
|
if (this._started) {
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
34
|
this._started = true;
|
|
35
|
+
if (options) {
|
|
36
|
+
this.config(options);
|
|
37
|
+
}
|
|
35
38
|
this._start();
|
|
36
39
|
}
|
|
37
40
|
|
package/src/plugin.js
CHANGED
|
@@ -5,6 +5,7 @@ import Layouts from './layouts.js';
|
|
|
5
5
|
import * as elements from './element/index.js';
|
|
6
6
|
import * as layouts from './layout/index.js';
|
|
7
7
|
import * as sources from './source/index.js';
|
|
8
|
+
import { loadStylesIfNecessary } from './styles.js';
|
|
8
9
|
|
|
9
10
|
import MisoContainerElement from './element/container/miso-container.js';
|
|
10
11
|
import MisoComboElement from './element/combo/miso-combo.js';
|
|
@@ -17,16 +18,15 @@ export default class UiPlugin extends Component {
|
|
|
17
18
|
return PLUGIN_ID;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
constructor(
|
|
21
|
+
constructor() {
|
|
21
22
|
super('ui');
|
|
22
23
|
this.layouts = new Layouts(this);
|
|
23
24
|
this._recommendations = new WeakMap();
|
|
24
25
|
this._asks = new WeakMap();
|
|
25
26
|
this._extensions = new WeakMap();
|
|
26
|
-
// TODO: load CSS
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
install(MisoClient, context) {
|
|
29
|
+
async install(MisoClient, context) {
|
|
30
30
|
context.addSubtree(this);
|
|
31
31
|
MisoClient.on('create', this._injectClient.bind(this));
|
|
32
32
|
|
|
@@ -61,6 +61,11 @@ export default class UiPlugin extends Component {
|
|
|
61
61
|
for (const ElementClass of ElementClasses) {
|
|
62
62
|
ElementClass.MisoClient = MisoClient; // TODO: find better way
|
|
63
63
|
}
|
|
64
|
+
|
|
65
|
+
// load styles
|
|
66
|
+
await loadStylesIfNecessary();
|
|
67
|
+
|
|
68
|
+
// define custom elements
|
|
64
69
|
for (const ElementClass of ElementClasses) {
|
|
65
70
|
defineAndUpgrade(ElementClass);
|
|
66
71
|
}
|
package/src/styles.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import version from './version.js';
|
|
2
|
+
|
|
3
|
+
const { currentScript } = document;
|
|
4
|
+
|
|
5
|
+
let cssUrl;
|
|
6
|
+
let stylesLoaded;
|
|
7
|
+
|
|
8
|
+
export async function loadStylesIfNecessary() {
|
|
9
|
+
return stylesLoaded || (stylesLoaded = loadStyles());
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function loadStyles() {
|
|
13
|
+
try {
|
|
14
|
+
let link = getExistedLinkElement();
|
|
15
|
+
if (link) {
|
|
16
|
+
return waitForLinkLoaded(link)
|
|
17
|
+
}
|
|
18
|
+
link = document.createElement('link');
|
|
19
|
+
link.rel = 'stylesheet';
|
|
20
|
+
link.href = getCssUrl();
|
|
21
|
+
return new Promise((resolve, reject) => {
|
|
22
|
+
link.onload = resolve;
|
|
23
|
+
link.onerror = reject;
|
|
24
|
+
document.head.appendChild(link);
|
|
25
|
+
});
|
|
26
|
+
} catch(e) {
|
|
27
|
+
console.error(e);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// helpers //
|
|
32
|
+
function getCssUrl() {
|
|
33
|
+
return cssUrl || (cssUrl = resolveCssUrl());
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function resolveCssUrl() {
|
|
37
|
+
// TODO: refactor with getPluginScriptUrl() in core
|
|
38
|
+
if (version === 'dev') {
|
|
39
|
+
const src = currentScript.src;
|
|
40
|
+
const searchIndex = src.indexOf('?');
|
|
41
|
+
const k = searchIndex < 0 ? src.length : searchIndex;
|
|
42
|
+
const i = src.lastIndexOf('/', k); // .../dist/umd/*.min.js
|
|
43
|
+
return `${src.slice(0, i - 4)}/css/ui.css`;
|
|
44
|
+
} else {
|
|
45
|
+
return `https://cdn.jsdelivr.net/npm/@miso.ai/client-sdk@${version}/dist/css/ui.css`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function getExistedLinkElement() {
|
|
50
|
+
return document.head.querySelector(`link[href="${getCssUrl()}"]`);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function waitForLinkLoaded(element) {
|
|
54
|
+
if (element.sheet) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
let intervalId;
|
|
59
|
+
element.onload = () => {
|
|
60
|
+
intervalId && clearInterval(intervalId);
|
|
61
|
+
resolve();
|
|
62
|
+
};
|
|
63
|
+
element.onerror = () => {
|
|
64
|
+
intervalId && clearInterval(intervalId);
|
|
65
|
+
reject();
|
|
66
|
+
};
|
|
67
|
+
intervalId = setInterval(() => {
|
|
68
|
+
if (element.sheet) {
|
|
69
|
+
intervalId && clearInterval(intervalId);
|
|
70
|
+
resolve();
|
|
71
|
+
}
|
|
72
|
+
}, 100);
|
|
73
|
+
});
|
|
74
|
+
}
|
package/src/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '1.9.0
|
|
1
|
+
export default '1.9.0';
|