@miso.ai/client-sdk-ui 1.13.2-beta.1 → 1.14.0-beta.3
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/asset/svgs.js +17 -4
- package/dist/cjs/combo/ask/index.js +2 -2
- package/dist/cjs/constants.js +120 -98
- package/dist/cjs/defaults/ask/controls.js +1 -1
- package/dist/cjs/defaults/hybrid-search/answer-box.js +4 -4
- package/dist/cjs/defaults.js +259 -0
- package/dist/cjs/element/container/index.js +28 -0
- package/dist/cjs/element/container/miso-ask.js +3 -3
- package/dist/cjs/element/container/miso-conversation.js +21 -0
- package/dist/cjs/element/container/miso-explore.js +1 -1
- package/dist/cjs/element/container/miso-history.js +21 -0
- package/dist/cjs/element/container/miso-hybrid-search.js +1 -1
- package/dist/cjs/element/container/miso-message-item.js +91 -0
- package/dist/cjs/element/container/miso-recommendation.js +1 -1
- package/dist/cjs/element/container/miso-search.js +1 -1
- package/dist/cjs/element/container/miso-thread-item.js +91 -0
- package/dist/cjs/element/context/miso-follow-ups.js +1 -1
- package/dist/cjs/element/role/index.js +49 -0
- package/dist/cjs/element/role/miso-delete.js +20 -0
- package/dist/cjs/element/role/miso-messages.js +20 -0
- package/dist/cjs/element/role/miso-new-thread.js +20 -0
- package/dist/cjs/element/role/miso-rename.js +20 -0
- package/dist/cjs/element/role/miso-subscription.js +20 -0
- package/dist/cjs/element/role/miso-threads.js +20 -0
- package/dist/cjs/element/role/miso-title.js +20 -0
- package/dist/cjs/layout/affiliation/affiliation.js +1 -1
- package/dist/cjs/layout/banner/banner.js +2 -1
- package/dist/cjs/layout/button/button.js +170 -0
- package/dist/cjs/layout/button/checkbox.js +116 -0
- package/dist/cjs/layout/button/more-button.js +3 -3
- package/dist/cjs/layout/container/container.js +1 -1
- package/dist/cjs/layout/container/item-container.js +99 -0
- package/dist/cjs/layout/error/error.js +2 -1
- package/dist/cjs/layout/index.js +42 -0
- package/dist/cjs/layout/input/facets.js +4 -3
- package/dist/cjs/layout/input/option-list.js +3 -2
- package/dist/cjs/layout/input/search-box.js +50 -12
- package/dist/cjs/layout/input/select.js +2 -1
- package/dist/cjs/layout/list/cards.js +2 -1
- package/dist/cjs/layout/list/carousel.js +2 -1
- package/dist/cjs/layout/list/collection.js +13 -1
- package/dist/cjs/layout/list/gallery.js +2 -1
- package/dist/cjs/layout/list/horizontal.js +2 -1
- package/dist/cjs/layout/list/list.js +2 -1
- package/dist/cjs/layout/list/messages.js +359 -0
- package/dist/cjs/layout/list/threads.js +199 -0
- package/dist/cjs/layout/mixin/trackable.js +4 -5
- package/dist/cjs/layout/mixin/triggerable.js +2 -2
- package/dist/cjs/layout/radio/feedback.js +4 -3
- package/dist/cjs/layout/templates.js +97 -0
- package/dist/cjs/layout/text/question.js +71 -0
- package/dist/cjs/layout/text/text.js +2 -1
- package/dist/cjs/layout/text/typewriter/index.js +18 -23
- package/dist/cjs/plugin.js +43 -104
- package/dist/cjs/util/confirm.js +33 -0
- package/dist/cjs/util/dom.js +21 -0
- package/dist/cjs/util/modal.js +48 -0
- package/dist/cjs/util/prompt.js +47 -0
- package/dist/cjs/version.js +1 -1
- package/package.json +5 -4
- package/src/CLAUDE.md +51 -104
- package/src/asset/svgs.js +16 -3
- package/src/combo/ask/index.js +2 -2
- package/src/constants.js +39 -147
- package/src/defaults/ask/controls.js +1 -1
- package/src/defaults/hybrid-search/answer-box.js +2 -2
- package/src/defaults.js +174 -0
- package/src/element/container/index.js +4 -0
- package/src/element/container/miso-ask.js +3 -3
- package/src/element/container/miso-conversation.js +19 -0
- package/src/element/container/miso-explore.js +1 -1
- package/src/element/container/miso-history.js +19 -0
- package/src/element/container/miso-hybrid-search.js +1 -1
- package/src/element/container/miso-message-item.js +94 -0
- package/src/element/container/miso-recommendation.js +1 -1
- package/src/element/container/miso-search.js +1 -1
- package/src/element/container/miso-thread-item.js +94 -0
- package/src/element/context/miso-follow-ups.js +1 -1
- package/src/element/role/index.js +7 -0
- package/src/element/role/miso-delete.js +16 -0
- package/src/element/role/miso-messages.js +16 -0
- package/src/element/role/miso-new-thread.js +16 -0
- package/src/element/role/miso-rename.js +16 -0
- package/src/element/role/miso-subscription.js +16 -0
- package/src/element/role/miso-threads.js +16 -0
- package/src/element/role/miso-title.js +16 -0
- package/src/layout/affiliation/affiliation.js +2 -2
- package/src/layout/banner/banner.js +2 -1
- package/src/layout/button/button.js +152 -0
- package/src/layout/button/checkbox.js +92 -0
- package/src/layout/button/more-button.js +3 -3
- package/src/layout/container/container.js +2 -2
- package/src/layout/container/item-container.js +99 -0
- package/src/layout/error/error.js +2 -1
- package/src/layout/index.js +6 -0
- package/src/layout/input/facets.js +3 -2
- package/src/layout/input/option-list.js +3 -2
- package/src/layout/input/search-box.js +45 -8
- package/src/layout/input/select.js +2 -1
- package/src/layout/list/cards.js +2 -1
- package/src/layout/list/carousel.js +2 -1
- package/src/layout/list/collection.js +15 -2
- package/src/layout/list/gallery.js +2 -1
- package/src/layout/list/horizontal.js +2 -1
- package/src/layout/list/list.js +2 -1
- package/src/layout/list/messages.js +316 -0
- package/src/layout/list/threads.js +166 -0
- package/src/layout/mixin/trackable.js +2 -3
- package/src/layout/mixin/triggerable.js +1 -1
- package/src/layout/radio/feedback.js +3 -2
- package/src/layout/templates.js +97 -0
- package/src/layout/text/question.js +58 -0
- package/src/layout/text/text.js +2 -1
- package/src/layout/text/typewriter/index.js +15 -18
- package/src/plugin.js +31 -117
- package/src/util/confirm.js +28 -0
- package/src/util/dom.js +16 -0
- package/src/util/modal.js +49 -0
- package/src/util/prompt.js +42 -0
- package/src/version.js +1 -1
- package/dist/cjs/actor/data.js +0 -132
- package/dist/cjs/actor/feedback.js +0 -29
- package/dist/cjs/actor/fields.js +0 -57
- package/dist/cjs/actor/filters.js +0 -161
- package/dist/cjs/actor/hub.js +0 -57
- package/dist/cjs/actor/index.js +0 -73
- package/dist/cjs/actor/interactions.js +0 -36
- package/dist/cjs/actor/sessions.js +0 -25
- package/dist/cjs/actor/tracker-states.js +0 -61
- package/dist/cjs/actor/tracker.js +0 -109
- package/dist/cjs/actor/trackers.js +0 -52
- package/dist/cjs/actor/utils.js +0 -15
- package/dist/cjs/actor/view.js +0 -294
- package/dist/cjs/actor/views.js +0 -209
- package/dist/cjs/source.js +0 -27
- package/dist/cjs/util/proxy.js +0 -88
- package/dist/cjs/util/trackers.js +0 -88
- package/dist/cjs/workflow/affiliations.js +0 -140
- package/dist/cjs/workflow/answer-based.js +0 -337
- package/dist/cjs/workflow/ask.js +0 -319
- package/dist/cjs/workflow/asks.js +0 -150
- package/dist/cjs/workflow/autocompletable.js +0 -63
- package/dist/cjs/workflow/autocomplete.js +0 -120
- package/dist/cjs/workflow/base.js +0 -418
- package/dist/cjs/workflow/context.js +0 -19
- package/dist/cjs/workflow/explore.js +0 -210
- package/dist/cjs/workflow/explores.js +0 -21
- package/dist/cjs/workflow/hybrid-search-answer.js +0 -88
- package/dist/cjs/workflow/hybrid-search-views.js +0 -109
- package/dist/cjs/workflow/hybrid-search.js +0 -213
- package/dist/cjs/workflow/index.js +0 -41
- package/dist/cjs/workflow/options/api.js +0 -41
- package/dist/cjs/workflow/options/auto-query.js +0 -97
- package/dist/cjs/workflow/options/configurable.js +0 -45
- package/dist/cjs/workflow/options/data-processor.js +0 -20
- package/dist/cjs/workflow/options/filters.js +0 -15
- package/dist/cjs/workflow/options/index.js +0 -126
- package/dist/cjs/workflow/options/interactions.js +0 -41
- package/dist/cjs/workflow/options/layouts.js +0 -79
- package/dist/cjs/workflow/options/options.js +0 -156
- package/dist/cjs/workflow/options/pagination.js +0 -25
- package/dist/cjs/workflow/options/roles.js +0 -15
- package/dist/cjs/workflow/options/templates.js +0 -30
- package/dist/cjs/workflow/options/trackers.js +0 -83
- package/dist/cjs/workflow/options/utils.js +0 -33
- package/dist/cjs/workflow/processors.js +0 -607
- package/dist/cjs/workflow/recommendation.js +0 -57
- package/dist/cjs/workflow/recommendations.js +0 -18
- package/dist/cjs/workflow/search-based.js +0 -337
- package/dist/cjs/workflow/search.js +0 -64
- package/dist/cjs/workflow/unit.js +0 -57
- package/dist/cjs/workflow/units.js +0 -42
- package/dist/cjs/workflow/use-link.js +0 -49
- package/src/actor/data.js +0 -106
- package/src/actor/feedback.js +0 -28
- package/src/actor/fields.js +0 -51
- package/src/actor/filters.js +0 -149
- package/src/actor/hub.js +0 -47
- package/src/actor/index.js +0 -10
- package/src/actor/interactions.js +0 -32
- package/src/actor/sessions.js +0 -21
- package/src/actor/tracker-states.js +0 -57
- package/src/actor/tracker.js +0 -104
- package/src/actor/trackers.js +0 -45
- package/src/actor/utils.js +0 -7
- package/src/actor/view.js +0 -272
- package/src/actor/views.js +0 -224
- package/src/source.js +0 -17
- package/src/util/proxy.js +0 -81
- package/src/util/trackers.js +0 -84
- package/src/workflow/affiliations.js +0 -121
- package/src/workflow/answer-based.js +0 -312
- package/src/workflow/ask.js +0 -284
- package/src/workflow/asks.js +0 -143
- package/src/workflow/autocompletable.js +0 -67
- package/src/workflow/autocomplete.js +0 -114
- package/src/workflow/base.js +0 -396
- package/src/workflow/context.js +0 -16
- package/src/workflow/explore.js +0 -194
- package/src/workflow/explores.js +0 -18
- package/src/workflow/hybrid-search-answer.js +0 -73
- package/src/workflow/hybrid-search-views.js +0 -116
- package/src/workflow/hybrid-search.js +0 -230
- package/src/workflow/index.js +0 -5
- package/src/workflow/options/api.js +0 -31
- package/src/workflow/options/auto-query.js +0 -70
- package/src/workflow/options/configurable.js +0 -48
- package/src/workflow/options/data-processor.js +0 -15
- package/src/workflow/options/filters.js +0 -10
- package/src/workflow/options/index.js +0 -11
- package/src/workflow/options/interactions.js +0 -36
- package/src/workflow/options/layouts.js +0 -73
- package/src/workflow/options/options.js +0 -175
- package/src/workflow/options/pagination.js +0 -18
- package/src/workflow/options/roles.js +0 -12
- package/src/workflow/options/templates.js +0 -27
- package/src/workflow/options/trackers.js +0 -80
- package/src/workflow/options/utils.js +0 -26
- package/src/workflow/processors.js +0 -490
- package/src/workflow/recommendation.js +0 -63
- package/src/workflow/recommendations.js +0 -14
- package/src/workflow/search-based.js +0 -329
- package/src/workflow/search.js +0 -73
- package/src/workflow/unit.js +0 -51
- package/src/workflow/units.js +0 -43
- package/src/workflow/use-link.js +0 -41
package/src/actor/view.js
DELETED
|
@@ -1,272 +0,0 @@
|
|
|
1
|
-
import { trimObj, defineValues, delegateGetters, EventEmitter } from '@miso.ai/commons';
|
|
2
|
-
import { STATUS, ROLE, isDataRole } from '../constants.js';
|
|
3
|
-
import * as fields from './fields.js';
|
|
4
|
-
import ProxyElement from '../util/proxy.js';
|
|
5
|
-
|
|
6
|
-
// TODO: browser dependency on syncSize
|
|
7
|
-
|
|
8
|
-
function statesEqual(a, b) {
|
|
9
|
-
return a === b || (a && b &&
|
|
10
|
-
a.status === b.status &&
|
|
11
|
-
a.error === b.error &&
|
|
12
|
-
a.value === b.value && // skip deep equals
|
|
13
|
-
a.ongoing === b.ongoing &&
|
|
14
|
-
stateEmptyness(a) === stateEmptyness(b) && // TODO: ad-hoc
|
|
15
|
-
sessionEquals(a.session, b.session));
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
function sessionEquals(a, b) {
|
|
19
|
-
return a === b || (a && b && a.uuid === b.uuid);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function stateEmptyness(data) {
|
|
23
|
-
return data && data.meta && data.meta.empty;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export default class ViewActor {
|
|
27
|
-
|
|
28
|
-
constructor(views, role) {
|
|
29
|
-
this._events = new EventEmitter({ target: this });
|
|
30
|
-
this._views = views;
|
|
31
|
-
// TODO: we should pull this up to views, for the results are also used in judging container emptyness
|
|
32
|
-
this._mapping = asMappingFunction((views._roles.mappings || {})[role] || role);
|
|
33
|
-
|
|
34
|
-
defineValues(this, {
|
|
35
|
-
role,
|
|
36
|
-
interface: new View(this),
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
get hub() {
|
|
41
|
-
return this._views._hub;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
get element() {
|
|
45
|
-
return this._element;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
set element(element) {
|
|
49
|
-
if (element === this._element) {
|
|
50
|
-
return;
|
|
51
|
-
}
|
|
52
|
-
if (this._element) {
|
|
53
|
-
this._safeApplyOnLayout('unrender', this._element);
|
|
54
|
-
}
|
|
55
|
-
this._element = element;
|
|
56
|
-
this._proxyElement && this._proxyElement.sync();
|
|
57
|
-
this._events.emit('element', element);
|
|
58
|
-
this.refresh({ force: true });
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
get proxyElement() {
|
|
62
|
-
if (!this._proxyElement) {
|
|
63
|
-
this._proxyElement = new ProxyElement(() => this.element);
|
|
64
|
-
}
|
|
65
|
-
return this._proxyElement;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
get layout() {
|
|
69
|
-
return this._layout;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
set layout(layout) {
|
|
73
|
-
if (layout === this._layout) {
|
|
74
|
-
return;
|
|
75
|
-
}
|
|
76
|
-
if (layout && typeof layout.render !== 'function') {
|
|
77
|
-
throw new Error(`Render function is mandatory in a layout.`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// clean up old layout
|
|
81
|
-
const { element } = this;
|
|
82
|
-
element && this._safeApplyOnLayout('unrender', element);
|
|
83
|
-
this._safeApplyOnLayout('destroy');
|
|
84
|
-
|
|
85
|
-
this._layout = layout;
|
|
86
|
-
|
|
87
|
-
// initialize new layout
|
|
88
|
-
if (layout) {
|
|
89
|
-
layout._view = this;
|
|
90
|
-
// don't use _safeApplyOnLayout, for any error should be thrown
|
|
91
|
-
if (typeof layout.initialize === 'function') {
|
|
92
|
-
layout.initialize(this);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// in case the data is already there
|
|
97
|
-
this.refresh({ force: true });
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
get tracker() {
|
|
101
|
-
return this._views.trackers[this.role];
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
get workflow() {
|
|
105
|
-
return this._views._workflow;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
get workflowOptions() {
|
|
109
|
-
return this._views._options.resolved;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
get trackerOptions() {
|
|
113
|
-
return this._views._getTrackerOptions(this.role);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
get filters() {
|
|
117
|
-
return this._views.filters;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
async refresh({ force = false, data } = {}) {
|
|
121
|
-
// protocol: no reaction when layout is absent
|
|
122
|
-
if (!this._layout) {
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// nothing to do when element is absent
|
|
127
|
-
const { element } = this;
|
|
128
|
-
if (!element) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// sync data
|
|
133
|
-
const previousData = this._data;
|
|
134
|
-
this._data = data = this._sliceData(data || this._views._getData());
|
|
135
|
-
|
|
136
|
-
// if data is unchanged, skip unless forced
|
|
137
|
-
if (!force && statesEqual(data, previousData)) {
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const { session, status, ongoing, request, meta, value } = data;
|
|
142
|
-
const baseState = { session, status, ongoing, request, meta, data: value, ...getDataEmptyness(this.role, data) };
|
|
143
|
-
|
|
144
|
-
// render
|
|
145
|
-
const notifyUpdate = (state = {}, options) => {
|
|
146
|
-
state !== false && this.updateState({ ...baseState, ...state }, options);
|
|
147
|
-
};
|
|
148
|
-
try {
|
|
149
|
-
await this._layout.render(element, data, { notifyUpdate });
|
|
150
|
-
} catch (error) {
|
|
151
|
-
this._error(error);
|
|
152
|
-
notifyUpdate({ error });
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
updateState(state, { silent = false } = {}) {
|
|
157
|
-
// there might be error from notifyUpdate() call
|
|
158
|
-
const status = state.error ? STATUS.ERRONEOUS : state.status;
|
|
159
|
-
state = this._state = Object.freeze(trimObj({ ...state, status }));
|
|
160
|
-
const { role } = this;
|
|
161
|
-
this.hub.update(fields.view(role), state, { silent });
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
_sliceData(data) {
|
|
165
|
-
const { value, error, status, meta, ...rest } = data;
|
|
166
|
-
const sliced = {
|
|
167
|
-
value: this._mapping(data, this),
|
|
168
|
-
status,
|
|
169
|
-
data: value,
|
|
170
|
-
meta,
|
|
171
|
-
...rest,
|
|
172
|
-
};
|
|
173
|
-
if (this.role === ROLE.CONTAINER) {
|
|
174
|
-
// pass empty/nonempty information
|
|
175
|
-
sliced.meta = {
|
|
176
|
-
...meta,
|
|
177
|
-
empty: this._isContainerEmpty(data),
|
|
178
|
-
};
|
|
179
|
-
}
|
|
180
|
-
return trimObj(sliced);
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
// TODO: move this to workflow
|
|
184
|
-
_isContainerEmpty(data) {
|
|
185
|
-
const { element } = this;
|
|
186
|
-
if (!element) {
|
|
187
|
-
return false;
|
|
188
|
-
}
|
|
189
|
-
// iterate over all member components' roles
|
|
190
|
-
for (const { role } of element.components) {
|
|
191
|
-
// not a data role -> irrelevant
|
|
192
|
-
if (!isDataRole(role)) {
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
// respect data mapping
|
|
196
|
-
const mapping = asMappingFunction((this._views._roles.mappings || {})[role] || role);
|
|
197
|
-
const sliced = mapping(data, this); // TODO: the view passed in should be the view of the role, not container role
|
|
198
|
-
if (!isDateValueEmpty(role, sliced)) {
|
|
199
|
-
return false;
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return true;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
_syncSize() {
|
|
206
|
-
this._element && this._safeApplyOnLayout('syncSize', this._element);
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
_safeApplyOnLayout(method, ...args) {
|
|
210
|
-
if (!this._layout || typeof this._layout[method] !== 'function') {
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
try {
|
|
214
|
-
this._layout[method](...args);
|
|
215
|
-
} catch (e) {
|
|
216
|
-
this._error(e);
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
_emit(name, data) {
|
|
221
|
-
this._events.emit(name, data);
|
|
222
|
-
this._views._events.emit(`${this.role}:${name}`, data);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
_error(e) {
|
|
226
|
-
this._views._error(e);
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
_destroy() {
|
|
230
|
-
this._safeApplyOnLayout('destroy');
|
|
231
|
-
this._proxyElement && this._proxyElement.destroy();
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
class View {
|
|
237
|
-
|
|
238
|
-
constructor(actor) {
|
|
239
|
-
delegateGetters(this, actor, ['role', 'layout', 'element', 'proxyElement', 'refresh', 'on', 'tracker']);
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
function asMappingFunction(fn) {
|
|
245
|
-
switch (typeof fn) {
|
|
246
|
-
case 'function':
|
|
247
|
-
return fn;
|
|
248
|
-
case 'string':
|
|
249
|
-
return data => data.value && data.value[fn];
|
|
250
|
-
default:
|
|
251
|
-
throw new Error(`Invalid mapping function: ${fn}`);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
function getDataEmptyness(role, data) {
|
|
256
|
-
return isDataStatusRelevantToEmptyness(data) ? { empty: !!isDateValueEmpty(role, data && data.value) } : {};
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
function isDataStatusRelevantToEmptyness(data) {
|
|
260
|
-
return data.status === STATUS.READY && !data.ongoing;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
function isDateValueEmpty(role, value) {
|
|
264
|
-
// TODO: ad-hoc
|
|
265
|
-
switch (role) {
|
|
266
|
-
case ROLE.ANSWER:
|
|
267
|
-
case ROLE.REASONING:
|
|
268
|
-
return !value || !value.value;
|
|
269
|
-
default:
|
|
270
|
-
return value === undefined || ((Array.isArray(value) || typeof value === 'string') && !value.length);
|
|
271
|
-
}
|
|
272
|
-
}
|
package/src/actor/views.js
DELETED
|
@@ -1,224 +0,0 @@
|
|
|
1
|
-
import { defineValues, delegateGetters, EventEmitter } from '@miso.ai/commons';
|
|
2
|
-
import { ROLE } from '../constants.js';
|
|
3
|
-
import * as fields from './fields.js';
|
|
4
|
-
import ViewActor from './view.js';
|
|
5
|
-
import Filters from './filters.js';
|
|
6
|
-
|
|
7
|
-
export default class ViewsActor {
|
|
8
|
-
|
|
9
|
-
constructor(hub, {
|
|
10
|
-
workflow,
|
|
11
|
-
extensions,
|
|
12
|
-
layouts,
|
|
13
|
-
roles,
|
|
14
|
-
options,
|
|
15
|
-
}) {
|
|
16
|
-
this._hub = hub;
|
|
17
|
-
this._workflow = workflow;
|
|
18
|
-
this._workflowName = workflow._name;
|
|
19
|
-
this._extensions = extensions;
|
|
20
|
-
this._layoutFactory = layouts;
|
|
21
|
-
this._options = options;
|
|
22
|
-
this._roles = roles;
|
|
23
|
-
this._containers = new Map();
|
|
24
|
-
this._components = new Map();
|
|
25
|
-
this._filters = new Filters(this);
|
|
26
|
-
this._events = new EventEmitter();
|
|
27
|
-
|
|
28
|
-
defineValues(this, {
|
|
29
|
-
interface: new Views(this),
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
this._unsubscribes = [
|
|
33
|
-
onResize(this.syncSize.bind(this)),
|
|
34
|
-
hub.on(fields.data(), data => this.refresh({ data })),
|
|
35
|
-
options.on('layouts', () => this._syncLayouts()),
|
|
36
|
-
];
|
|
37
|
-
|
|
38
|
-
this._syncLayouts();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
get filters() {
|
|
42
|
-
return this._filters;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
get trackers() {
|
|
46
|
-
return this._workflow.trackers;
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
on(role, name, fn) {
|
|
50
|
-
return this._events.on(`${role}:${name}`, fn);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
// elements //
|
|
54
|
-
addContainer(element) {
|
|
55
|
-
if (this._containers.has(element)) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const view = this._createView(element);
|
|
59
|
-
this._containers.set(element, view);
|
|
60
|
-
|
|
61
|
-
const { components } = element;
|
|
62
|
-
for (const component of components) {
|
|
63
|
-
this.addComponent(component);
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
removeContainer(element) {
|
|
68
|
-
const view = this._containers.get(element);
|
|
69
|
-
if (!view) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
const { components } = element;
|
|
73
|
-
for (const component of components) {
|
|
74
|
-
this.removeComponent(component);
|
|
75
|
-
}
|
|
76
|
-
view._destroy();
|
|
77
|
-
this._containers.delete(element);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
addComponent(element) {
|
|
81
|
-
if (this._components.has(element)) {
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
const view = this._createView(element);
|
|
85
|
-
this._components.set(element, view);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
removeComponent(element) {
|
|
89
|
-
const view = this._components.get(element);
|
|
90
|
-
if (!view) {
|
|
91
|
-
return;
|
|
92
|
-
}
|
|
93
|
-
view._destroy();
|
|
94
|
-
this._components.delete(element);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
updateComponentRole(element, oldRole, newRole) {
|
|
98
|
-
// TODO
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
containsElement(element) {
|
|
102
|
-
return this._containers.has(element) || this._components.has(element);
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
refreshElement(element) {
|
|
106
|
-
const view = element.isContainer ? this._containers.get(element) : this._components.get(element);
|
|
107
|
-
view && view.refresh({ force: true });
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
_createView(element) {
|
|
111
|
-
const view = new ViewActor(this, element.role);
|
|
112
|
-
view.layout = this._createLayout(element.role);
|
|
113
|
-
view.element = element;
|
|
114
|
-
return view;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
_syncLayouts() {
|
|
118
|
-
// TODO: put a debug event here
|
|
119
|
-
const { layouts } = this._options.resolved;
|
|
120
|
-
if (layouts === false) {
|
|
121
|
-
for (const view of [...this._containers.values(), ...this._components.values()]) {
|
|
122
|
-
view.layout = undefined;
|
|
123
|
-
}
|
|
124
|
-
} else {
|
|
125
|
-
for (const view of [...this._containers.values(), ...this._components.values()]) {
|
|
126
|
-
view.layout = this._createLayout(view.role);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
_createLayout(role) {
|
|
132
|
-
const args = this._options.resolved.layouts[role];
|
|
133
|
-
if (!args) {
|
|
134
|
-
return undefined;
|
|
135
|
-
}
|
|
136
|
-
const [name, options] = args;
|
|
137
|
-
return this._layoutFactory.create(name, { ...options, role, workflow: this._workflowName });
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
get(role) {
|
|
141
|
-
return this.getAll(role)[0];
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
getAll(role) {
|
|
145
|
-
return role === ROLE.CONTAINER ? this._containers.values() : this._components.values().filter(view => view.role === role);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
get views() {
|
|
149
|
-
return this._getViews(true);
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
_getViews(containerFirst = true) {
|
|
153
|
-
return containerFirst ? [
|
|
154
|
-
...this._containers.values(),
|
|
155
|
-
...this._components.values(),
|
|
156
|
-
] : [
|
|
157
|
-
...this._components.values(),
|
|
158
|
-
...this._containers.values(),
|
|
159
|
-
];
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
syncSize() {
|
|
163
|
-
// TODO: containers?
|
|
164
|
-
for (const view of this._components.values()) {
|
|
165
|
-
view._syncSize();
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
async refresh({ force, data } = {}) {
|
|
170
|
-
data = this._getData(data);
|
|
171
|
-
// container first
|
|
172
|
-
let views = this._getViews(true);
|
|
173
|
-
|
|
174
|
-
await Promise.all(views.map(view => view.refresh({ force, data })));
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
_getData(data) {
|
|
178
|
-
return data || this._hub.states[fields.data()];
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
_error(e) {
|
|
182
|
-
// TODO: hub trigger error event
|
|
183
|
-
console.error(e);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
_destroy({ dom } = {}) {
|
|
187
|
-
// destroy components, and then containers
|
|
188
|
-
for (const view of this._getViews(false)) {
|
|
189
|
-
// TODO: handle dom option
|
|
190
|
-
view._destroy();
|
|
191
|
-
}
|
|
192
|
-
for (const unsubscribe of this._unsubscribes) {
|
|
193
|
-
unsubscribe();
|
|
194
|
-
}
|
|
195
|
-
this._unsubscribes = [];
|
|
196
|
-
this._filters._destroy();
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
class Views {
|
|
202
|
-
|
|
203
|
-
constructor(actor) {
|
|
204
|
-
this._actor = actor;
|
|
205
|
-
delegateGetters(this, actor, ['syncSize', 'refresh', 'trackers', 'filters']);
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
get(role) {
|
|
209
|
-
return this._actor.get(role).interface;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
get all() {
|
|
213
|
-
return this._actor.views.map(view => view.interface);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
function onResize(callback) {
|
|
219
|
-
if (typeof window === 'undefined') {
|
|
220
|
-
return () => {};
|
|
221
|
-
}
|
|
222
|
-
window.addEventListener('resize', callback);
|
|
223
|
-
return () => window.removeEventListener('resize', callback);
|
|
224
|
-
}
|
package/src/source.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { API } from '@miso.ai/commons';
|
|
2
|
-
|
|
3
|
-
export function api(client) {
|
|
4
|
-
// TODO: send uuid & unit id
|
|
5
|
-
return async ({ group, name, payload, options }) => {
|
|
6
|
-
if (group === API.GROUP.ASK) {
|
|
7
|
-
switch (name) {
|
|
8
|
-
case API.NAME.QUESTIONS:
|
|
9
|
-
return client.api.ask.questions(payload, options);
|
|
10
|
-
case API.NAME.SEARCH:
|
|
11
|
-
return client.api.ask.search(payload, options);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
// because name is in snake case
|
|
15
|
-
return client.api[group]._run(name, payload, options);
|
|
16
|
-
};
|
|
17
|
-
}
|
package/src/util/proxy.js
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { removeItem, findAndRemoveItem } from '@miso.ai/commons';
|
|
2
|
-
|
|
3
|
-
export default class ProxyElement {
|
|
4
|
-
|
|
5
|
-
constructor(element) {
|
|
6
|
-
this._get = typeof element === 'function' ? element : () => element;
|
|
7
|
-
this._handlers = [];
|
|
8
|
-
this._elementUpdatedHandlers = [];
|
|
9
|
-
this.sync();
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
get current() {
|
|
13
|
-
return this._element;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
on(event, handler) {
|
|
17
|
-
if (event === 'element') {
|
|
18
|
-
return this._onElementUpdated(handler);
|
|
19
|
-
}
|
|
20
|
-
const element = this._get();
|
|
21
|
-
if (element) {
|
|
22
|
-
element.addEventListener(event, handler);
|
|
23
|
-
}
|
|
24
|
-
this._handlers.push({ event, handler });
|
|
25
|
-
return () => this._off(event, handler);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
_off(event, handler) {
|
|
29
|
-
const element = this._get();
|
|
30
|
-
if (element) {
|
|
31
|
-
element.removeEventListener(event, handler);
|
|
32
|
-
}
|
|
33
|
-
findAndRemoveItem(this._handlers, en => en.handler === handler);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
_onElementUpdated(handler) {
|
|
37
|
-
this._elementUpdatedHandlers.push(handler);
|
|
38
|
-
return () => {
|
|
39
|
-
removeItem(this._elementUpdatedHandlers, handler);
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
sync({ silent = false } = {}) {
|
|
44
|
-
const element = this._get();
|
|
45
|
-
if (this._element === element) {
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
this._offAllFromCurrentElement();
|
|
49
|
-
if (element) {
|
|
50
|
-
for (const { event, handler } of this._handlers) {
|
|
51
|
-
element.addEventListener(event, handler);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
const oldElement = this._element;
|
|
55
|
-
this._element = element;
|
|
56
|
-
|
|
57
|
-
if (silent) {
|
|
58
|
-
return;
|
|
59
|
-
}
|
|
60
|
-
for (const handler of this._elementUpdatedHandlers) {
|
|
61
|
-
try {
|
|
62
|
-
handler(element, oldElement);
|
|
63
|
-
} catch (e) {
|
|
64
|
-
console.error(e); // TODO
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
_offAllFromCurrentElement() {
|
|
70
|
-
if (this._element) {
|
|
71
|
-
for (const { event, handler } of this._handlers) {
|
|
72
|
-
this._element.removeEventListener(event, handler);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
destroy() {
|
|
78
|
-
this._offAllFromCurrentElement();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
}
|
package/src/util/trackers.js
DELETED
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { findInAncestors, trimObj } from '@miso.ai/commons';
|
|
2
|
-
|
|
3
|
-
const TRACKED = Symbol.for('miso:tracked');
|
|
4
|
-
|
|
5
|
-
export function isTracked(event) {
|
|
6
|
-
return !!event[TRACKED];
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export function markAsTracked(event) {
|
|
10
|
-
event[TRACKED] = true;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const DEFAULT_TRACKER_OPTIONS = Object.freeze({
|
|
14
|
-
impression: Object.freeze({
|
|
15
|
-
}),
|
|
16
|
-
viewable: Object.freeze({
|
|
17
|
-
area: 0.5,
|
|
18
|
-
duration: 1000,
|
|
19
|
-
}),
|
|
20
|
-
click: Object.freeze({
|
|
21
|
-
lenient: false,
|
|
22
|
-
}),
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
function mergeOptions(def, opt) {
|
|
26
|
-
// if opt is falsy then return false, merge otherwise
|
|
27
|
-
return !!opt && { ...def, ...opt };
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// TODO: don't need this anymore
|
|
31
|
-
export function normalizeTrackerOptions(options) {
|
|
32
|
-
// TODO: make this { active: false } to keep it an object
|
|
33
|
-
if (options === false) {
|
|
34
|
-
return false; // turn off all tracking
|
|
35
|
-
}
|
|
36
|
-
if (options === true) {
|
|
37
|
-
options = {};
|
|
38
|
-
}
|
|
39
|
-
if (typeof options !== 'object') {
|
|
40
|
-
throw new Error(`Invalid options: ${options}`);
|
|
41
|
-
}
|
|
42
|
-
const { impression = {}, viewable = {}, click = {}, ...rest } = options;
|
|
43
|
-
return trimObj({
|
|
44
|
-
...DEFAULT_TRACKER_OPTIONS,
|
|
45
|
-
...rest,
|
|
46
|
-
impression: mergeOptions(DEFAULT_TRACKER_OPTIONS.impression, impression),
|
|
47
|
-
viewable: mergeOptions(DEFAULT_TRACKER_OPTIONS.viewable, viewable),
|
|
48
|
-
click: mergeOptions(DEFAULT_TRACKER_OPTIONS.click, click),
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function validateClick(options = {}, event) {
|
|
53
|
-
if (!options) {
|
|
54
|
-
return false;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (typeof options.validate === 'function') {
|
|
58
|
-
return options.validate(event);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
if (options.lenient) {
|
|
62
|
-
return true;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// standard criteria
|
|
66
|
-
// 1. each event can only be tracked once
|
|
67
|
-
if (isTracked(event)) {
|
|
68
|
-
return false;
|
|
69
|
-
}
|
|
70
|
-
// 2. it must be a left click
|
|
71
|
-
if (event.button !== 0) {
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
// 3. event default must not be prevented
|
|
75
|
-
if (event.defaultPrevented) {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
// 4. must go through a real link
|
|
79
|
-
if (!findInAncestors(event.target, element => (element.tagName === 'A' && element.href) || undefined)) {
|
|
80
|
-
return false;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
return true;
|
|
84
|
-
}
|