@magmamath/students-features 0.3.0-rc.7 → 0.3.0-rc.9

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.
Files changed (40) hide show
  1. package/dist/commonjs/features/chatbot/components/Alternatives/Alternatives.js.map +1 -1
  2. package/dist/commonjs/features/chatbot/model/ChatBotModel.js +33 -23
  3. package/dist/commonjs/features/chatbot/model/ChatBotModel.js.map +1 -1
  4. package/dist/commonjs/features/chatbot/model/t2s.js +1 -2
  5. package/dist/commonjs/features/chatbot/model/t2s.js.map +1 -1
  6. package/dist/commonjs/features/chatbot/model/translation.js +25 -15
  7. package/dist/commonjs/features/chatbot/model/translation.js.map +1 -1
  8. package/dist/commonjs/lib/effector/createEntityFieldStore.js +14 -13
  9. package/dist/commonjs/lib/effector/createEntityFieldStore.js.map +1 -1
  10. package/dist/module/features/chatbot/components/Alternatives/Alternatives.js.map +1 -1
  11. package/dist/module/features/chatbot/model/ChatBotModel.js +33 -23
  12. package/dist/module/features/chatbot/model/ChatBotModel.js.map +1 -1
  13. package/dist/module/features/chatbot/model/t2s.js +1 -2
  14. package/dist/module/features/chatbot/model/t2s.js.map +1 -1
  15. package/dist/module/features/chatbot/model/translation.js +25 -15
  16. package/dist/module/features/chatbot/model/translation.js.map +1 -1
  17. package/dist/module/lib/effector/createEntityFieldStore.js +12 -13
  18. package/dist/module/lib/effector/createEntityFieldStore.js.map +1 -1
  19. package/dist/typescript/commonjs/features/chatbot/model/ChatBotModel.d.ts +4 -40
  20. package/dist/typescript/commonjs/features/chatbot/model/ChatBotModel.d.ts.map +1 -1
  21. package/dist/typescript/commonjs/features/chatbot/model/t2s.d.ts +1 -1
  22. package/dist/typescript/commonjs/features/chatbot/model/t2s.d.ts.map +1 -1
  23. package/dist/typescript/commonjs/features/chatbot/model/translation.d.ts +22 -6
  24. package/dist/typescript/commonjs/features/chatbot/model/translation.d.ts.map +1 -1
  25. package/dist/typescript/commonjs/lib/effector/createEntityFieldStore.d.ts +6 -5
  26. package/dist/typescript/commonjs/lib/effector/createEntityFieldStore.d.ts.map +1 -1
  27. package/dist/typescript/module/features/chatbot/model/ChatBotModel.d.ts +4 -40
  28. package/dist/typescript/module/features/chatbot/model/ChatBotModel.d.ts.map +1 -1
  29. package/dist/typescript/module/features/chatbot/model/t2s.d.ts +1 -1
  30. package/dist/typescript/module/features/chatbot/model/t2s.d.ts.map +1 -1
  31. package/dist/typescript/module/features/chatbot/model/translation.d.ts +22 -6
  32. package/dist/typescript/module/features/chatbot/model/translation.d.ts.map +1 -1
  33. package/dist/typescript/module/lib/effector/createEntityFieldStore.d.ts +6 -5
  34. package/dist/typescript/module/lib/effector/createEntityFieldStore.d.ts.map +1 -1
  35. package/package.json +1 -1
  36. package/src/features/chatbot/components/Alternatives/Alternatives.tsx +1 -1
  37. package/src/features/chatbot/model/ChatBotModel.ts +34 -26
  38. package/src/features/chatbot/model/t2s.ts +1 -2
  39. package/src/features/chatbot/model/translation.ts +54 -20
  40. package/src/lib/effector/createEntityFieldStore.ts +11 -9
@@ -5,7 +5,6 @@ import {
5
5
  sample,
6
6
  type Store,
7
7
  type Effect,
8
- combine,
9
8
  createStore,
10
9
  createEffect,
11
10
  } from 'effector'
@@ -18,7 +17,7 @@ import {
18
17
  SetHintMessageProps,
19
18
  StartConversationFxData,
20
19
  } from '../types/model.types'
21
- import { ChatAnswer, GetAlternativesResponse, PostMessageResponse } from '../types/api.types'
20
+ import { GetAlternativesResponse, PostMessageResponse } from '../types/api.types'
22
21
  import { generateRandomId } from '../../../lib/helpers/helpers'
23
22
  import { ChatbotAPI } from './api'
24
23
  import { ChatbotTranslation } from './translation'
@@ -42,7 +41,7 @@ export class ChatbotModel {
42
41
 
43
42
  readonly setIsOpen = createEvent<boolean>()
44
43
  readonly toggleOpen = createEvent()
45
- readonly $isOpen = restore(this.setIsOpen, false).on(this.toggleOpen, isOpen => !isOpen)
44
+ readonly $isOpen = restore(this.setIsOpen, false).on(this.toggleOpen, (isOpen) => !isOpen)
46
45
 
47
46
  // separate messages and alternatives class?
48
47
  public readonly removeLastMessage = createEvent()
@@ -56,6 +55,10 @@ export class ChatbotModel {
56
55
 
57
56
  readonly defaultMessages: ChatbotModelProps['messages']
58
57
 
58
+ readonly messages = createEntityFieldStore<ConversationMessage[]>()
59
+ readonly threadIds = createEntityFieldStore<string>()
60
+ readonly availableChats = createEntityFieldStore<boolean>()
61
+
59
62
  constructor({ api, messages, $key }: ChatbotModelProps) {
60
63
  this.api = new ChatbotAPI(api)
61
64
 
@@ -71,34 +74,23 @@ export class ChatbotModel {
71
74
  .on(this.setAlternatives, (_, payload) => payload)
72
75
  .reset(this.resetAlternatives)
73
76
 
74
- // TODO: do not pass this, just what you need
75
- this.translation = new ChatbotTranslation(this)
77
+ this.translation = new ChatbotTranslation({
78
+ defaultMessages: messages,
79
+ $key: this.$currentKey,
80
+ api: this.api,
81
+ messagesModel: this.messages,
82
+ alternativesModel: {
83
+ $store: this.$alternatives,
84
+ set: this.setAlternatives,
85
+ },
86
+ })
87
+
76
88
  this.t2s = new ChatTextToSpeechModel({ $isOpen: this.$isOpen, api: this.api })
77
89
 
78
90
  this.sendHelpRequestFx = this.createSendHelpRequestFx()
79
91
  this.initChatReplyWatcher()
80
92
  }
81
93
 
82
- public readonly reinitConversation = createEffect(({ key }: ReinitConversationProps) => {
83
- this.messages.setField({
84
- key,
85
- fn: messages => {
86
- if (!messages?.length) return
87
- const lastMessage = messages[messages.length - 1]
88
- const copy = [...messages]
89
- copy.splice(messages.length - 1, 1, {
90
- ...lastMessage,
91
- options: this.defaultMessages.start.options,
92
- })
93
- return copy
94
- },
95
- })
96
- })
97
-
98
- readonly messages = createEntityFieldStore<ConversationMessage[]>()
99
- readonly threadIds = createEntityFieldStore<string>()
100
- readonly availableChats = createEntityFieldStore<boolean>()
101
-
102
94
  private createSendHelpRequestFx() {
103
95
  return attach({
104
96
  source: [this.$currentKey, this.messages.$state, this.translation.$isTranslated],
@@ -225,13 +217,29 @@ export class ChatbotModel {
225
217
  const options = this.$alternatives.getState()?.options.hints ?? message.options
226
218
  this.messages.setField({
227
219
  key: `${entityId}-${fieldId}`,
228
- fn: messages => {
220
+ fn: (messages) => {
229
221
  if (!messages || messages.length > 1) return
230
222
  return [{ ...message, options }]
231
223
  },
232
224
  })
233
225
  }
234
226
 
227
+ public readonly reinitConversation = createEffect(({ key }: ReinitConversationProps) => {
228
+ this.messages.setField({
229
+ key,
230
+ fn: (messages) => {
231
+ if (!messages?.length || messages.length > 1) return
232
+ const lastMessage = messages[messages.length - 1]
233
+ const copy = [...messages]
234
+ copy.splice(messages.length - 1, 1, {
235
+ ...lastMessage,
236
+ options: [{ text: 'Give me another hint', promptKey: '' }],
237
+ })
238
+ return copy
239
+ },
240
+ })
241
+ })
242
+
235
243
  public bindKey($store: Store<string>) {
236
244
  sample({
237
245
  source: $store,
@@ -1,8 +1,7 @@
1
- import { restore, createEvent, Store, sample } from 'effector'
1
+ import { restore, createEvent, Store, sample, createEffect } from 'effector'
2
2
  import { AUDIO_CONFIG, DEFAULT_VOICE } from '../constants'
3
3
  import { AudioProvider, AudioStatus, PlayTextToSpeechProps } from '../types/t2s.types'
4
4
  import { ChatbotAPI } from './api'
5
- import { createEffect } from 'effector/effector.umd'
6
5
 
7
6
  type ChatTextToSpeechModelProps = {
8
7
  $isOpen: Store<boolean>
@@ -1,17 +1,41 @@
1
- import { createEvent, restore, attach, createEffect, type Effect, sample } from 'effector'
2
- import { ChatbotModel } from './ChatBotModel'
3
-
1
+ import {
2
+ createEvent,
3
+ restore,
4
+ attach,
5
+ createEffect,
6
+ type Effect,
7
+ sample,
8
+ Store,
9
+ EventCallable,
10
+ } from 'effector'
4
11
  import {
5
12
  TranslateAlternativesFxProps,
6
13
  TranslateBatchFxProps,
7
14
  TranslateMessageFxProps,
8
15
  } from '../types/translation.types'
9
- import { ConversationMessage } from '../types/model.types'
16
+ import { ChatbotModelProps, ConversationMessage } from '../types/model.types'
10
17
  import { GetAlternativesResponse } from '../types/api.types'
11
18
  import { decodeHTMLEntities } from '../helpers'
19
+ import { ChatbotAPI } from './api'
20
+ import { EntityFieldStore } from '../../../lib/effector/createEntityFieldStore'
21
+
22
+ type ChatbotTranslationProps = {
23
+ api: ChatbotAPI
24
+ $key: Store<string>
25
+ defaultMessages: ChatbotModelProps['messages']
26
+ messagesModel: EntityFieldStore<ConversationMessage[]>
27
+ alternativesModel: {
28
+ set: EventCallable<GetAlternativesResponse | null>
29
+ $store: Store<GetAlternativesResponse | null>
30
+ }
31
+ }
12
32
 
13
33
  export class ChatbotTranslation {
14
- private readonly model: ChatbotModel
34
+ private readonly api
35
+ private readonly $key
36
+ private readonly defaultMessages
37
+ private readonly messagesModel
38
+ private readonly alternativesModel
15
39
 
16
40
  readonly setIsTranslated = createEvent<boolean>()
17
41
  readonly $isTranslated = restore(this.setIsTranslated, false)
@@ -23,8 +47,18 @@ export class ChatbotTranslation {
23
47
  GetAlternativesResponse | null
24
48
  >
25
49
 
26
- constructor(chatbotModel: ChatbotModel) {
27
- this.model = chatbotModel
50
+ constructor({
51
+ api,
52
+ $key,
53
+ defaultMessages,
54
+ messagesModel,
55
+ alternativesModel,
56
+ }: ChatbotTranslationProps) {
57
+ this.api = api
58
+ this.$key = $key
59
+ this.defaultMessages = defaultMessages
60
+ this.messagesModel = messagesModel
61
+ this.alternativesModel = alternativesModel
28
62
 
29
63
  this.translateAlternativesFx = this.createTranslateAlternativesEffect()
30
64
  this.translateMessageFx = this.createTranslateMessageEffect()
@@ -51,15 +85,15 @@ export class ChatbotTranslation {
51
85
  private initTranslationSamples() {
52
86
  sample({
53
87
  clock: this.translateBatchFx.doneData,
54
- source: [this.model.$currentKey] as const,
88
+ source: [this.$key] as const,
55
89
  fn: ([key], translatedMessages) => ({ key, data: translatedMessages }),
56
- target: this.model.messages.setField,
90
+ target: this.messagesModel.setField,
57
91
  })
58
92
  }
59
93
 
60
94
  private createTranslateAlternativesEffect() {
61
95
  return attach({
62
- source: [this.model.$alternatives],
96
+ source: [this.alternativesModel.$store],
63
97
  mapParams: (params: TranslateAlternativesFxProps['params'], [alternatives]) => ({
64
98
  params,
65
99
  alternatives,
@@ -72,7 +106,7 @@ export class ChatbotTranslation {
72
106
 
73
107
  if (hintAlternatives.length) {
74
108
  const hintText = hintAlternatives.map(({ text }) => text)
75
- const response = await this.model.api.translateTextFx({
109
+ const response = await this.api.translateTextFx({
76
110
  text: hintText,
77
111
  targetLanguage: params.targetLanguage,
78
112
  })
@@ -89,7 +123,7 @@ export class ChatbotTranslation {
89
123
 
90
124
  if (defaultAlternatives.length) {
91
125
  const defaultText = defaultAlternatives.map(({ text }) => text)
92
- const response = await this.model.api.translateTextFx({
126
+ const response = await this.api.translateTextFx({
93
127
  text: defaultText,
94
128
  targetLanguage: params.targetLanguage,
95
129
  })
@@ -114,7 +148,7 @@ export class ChatbotTranslation {
114
148
  private createTranslateMessageEffect() {
115
149
  return createEffect(async ({ message, targetLanguage }: TranslateMessageFxProps) => {
116
150
  const optionsText = message.options.map(({ text }) => text)
117
- const response = await this.model.api.translateTextFx({
151
+ const response = await this.api.translateTextFx({
118
152
  text: [message.message, ...optionsText],
119
153
  targetLanguage,
120
154
  })
@@ -136,7 +170,7 @@ export class ChatbotTranslation {
136
170
 
137
171
  private createTranslateBatchEffect() {
138
172
  return attach({
139
- source: [this.model.$currentKey, this.model.messages.$state],
173
+ source: [this.$key, this.messagesModel.$state],
140
174
  mapParams: (params: TranslateBatchFxProps['params'], [key, messages]) => ({
141
175
  params,
142
176
  messages: messages[key] ?? [],
@@ -147,7 +181,7 @@ export class ChatbotTranslation {
147
181
  }
148
182
 
149
183
  const messagesText = messages.map(({ message }) => message)
150
- const response = await this.model.api.translateTextFx({
184
+ const response = await this.api.translateTextFx({
151
185
  text: messagesText,
152
186
  targetLanguage: params.targetLanguage,
153
187
  })
@@ -157,12 +191,12 @@ export class ChatbotTranslation {
157
191
  ? await this.translateMessageOptions(lastMessage, params.targetLanguage)
158
192
  : undefined
159
193
 
160
- const errorMessageTranslationResponse = await this.model.api.translateTextFx({
161
- text: [this.model.defaultMessages.error.message],
194
+ const errorMessageTranslationResponse = await this.api.translateTextFx({
195
+ text: [this.defaultMessages.error.message],
162
196
  targetLanguage: params.targetLanguage,
163
197
  })
164
198
 
165
- this.model.defaultMessages.error.translatedMessage = decodeHTMLEntities(
199
+ this.defaultMessages.error.translatedMessage = decodeHTMLEntities(
166
200
  errorMessageTranslationResponse.data.translations[0].translatedText,
167
201
  )
168
202
 
@@ -189,12 +223,12 @@ export class ChatbotTranslation {
189
223
  private async translateMessageOptions(message: ConversationMessage, targetLanguage: string) {
190
224
  if (!message?.options?.length) {
191
225
  const translatedAlternatives = await this.translateAlternativesFx({ targetLanguage })
192
- this.model.setAlternatives(translatedAlternatives)
226
+ this.alternativesModel.set(translatedAlternatives)
193
227
  return
194
228
  }
195
229
 
196
230
  const optionsText = message.options.map(({ text }) => text)
197
- const response = await this.model.api.translateTextFx({
231
+ const response = await this.api.translateTextFx({
198
232
  text: optionsText,
199
233
  targetLanguage,
200
234
  })
@@ -4,21 +4,23 @@ type UpdateField<T> = {
4
4
  key: string
5
5
  } & ({ data: T; fn?: never } | { data?: never; fn: (props: T | void) => T | void })
6
6
 
7
- export function createEntityFieldStore<T>() {
8
- const setField = createEvent<UpdateField<T>>()
9
- const reset = createEvent()
7
+ export class EntityFieldStore<T> {
8
+ public readonly setField = createEvent<UpdateField<T>>()
9
+ public readonly reset = createEvent()
10
10
 
11
- const $state = createStore<Record<string, T>>({})
12
- .on(setField, (state, { key, data }) => {
13
- if (typeof data === 'function') {
11
+ public readonly $state = createStore<Record<string, T>>({})
12
+ .on(this.setField, (state, { key, data, fn }) => {
13
+ if (fn) {
14
14
  const currentData = state[key]
15
- const newData = data(currentData)
15
+ const newData = fn(currentData)
16
16
  if (newData === undefined) return state
17
17
  return { ...state, [key]: newData }
18
18
  }
19
19
  return { ...state, [key]: data }
20
20
  })
21
- .reset(reset)
21
+ .reset(this.reset)
22
+ }
22
23
 
23
- return { $state, setField, reset }
24
+ export function createEntityFieldStore<T>() {
25
+ return new EntityFieldStore<T>()
24
26
  }