1717
1818
1919qx . Class . define ( "osparc.study.Conversation" , {
20- extend : qx . ui . tabview . Page ,
20+ extend : osparc . conversation . Conversation ,
2121
2222 /**
23- * @param conversationData {Object} Conversation Data
2423 * @param studyData {String} Study Data
24+ * @param conversation {osparc.data.model.Conversation} Conversation
2525 */
26- construct : function ( conversationData , studyData ) {
27- this . base ( arguments ) ;
28-
26+ construct : function ( studyData , conversation ) {
2927 this . __studyData = studyData ;
30- this . __messages = [ ] ;
31-
32- this . _setLayout ( new qx . ui . layout . VBox ( 5 ) ) ;
33-
34- this . set ( {
35- padding : 10 ,
36- showCloseButton : false ,
37- } ) ;
38-
39- this . getChildControl ( "button" ) . set ( {
40- font : "text-13" ,
41- } ) ;
42- this . __addConversationButtons ( ) ;
43-
44- this . __buildLayout ( ) ;
45-
46- if ( conversationData ) {
47- const conversation = new osparc . data . model . Conversation ( conversationData , this . __studyData ) ;
48- this . setConversation ( conversation ) ;
49- this . setLabel ( conversationData [ "name" ] ) ;
50- } else {
51- this . setLabel ( this . tr ( "new" ) ) ;
52- }
53- } ,
54-
55- properties : {
56- conversation : {
57- check : "osparc.data.model.Conversation" ,
58- init : null ,
59- nullable : false ,
60- event : "changeConversation" ,
61- apply : "__applyConversation" ,
62- } ,
28+ this . base ( arguments , conversation ) ;
6329 } ,
6430
6531 members : {
6632 __studyData : null ,
67- __messages : null ,
68- __nextRequestParams : null ,
69- __messagesTitle : null ,
70- __messageScroll : null ,
71- __messagesList : null ,
72- __loadMoreMessages : null ,
73-
74- __applyConversation : function ( conversation ) {
75- this . __reloadMessages ( true ) ;
76-
77- if ( conversation ) {
78- conversation . addListener ( "messageAdded" , e => {
79- const message = e . getData ( ) ;
80- this . addMessage ( message ) ;
81- } , this ) ;
82- conversation . addListener ( "messageUpdated" , e => {
83- const message = e . getData ( ) ;
84- this . updateMessage ( message ) ;
85- } , this ) ;
86- conversation . addListener ( "messageDeleted" , e => {
87- const message = e . getData ( ) ;
88- this . deleteMessage ( message ) ;
89- } , this ) ;
90- }
91- } ,
92-
93- getConversationId : function ( ) {
94- if ( this . getConversation ( ) ) {
95- return this . getConversation ( ) . getConversationId ( ) ;
96- }
97- return null ;
98- } ,
99-
100- __addConversationButtons : function ( ) {
101- const tabButton = this . getChildControl ( "button" ) ;
102-
103- const buttonsAesthetics = {
104- focusable : false ,
105- keepActive : true ,
106- padding : 0 ,
107- backgroundColor : "transparent" ,
108- } ;
109- const renameButton = new qx . ui . form . Button ( null , "@FontAwesome5Solid/pencil-alt/10" ) . set ( {
110- ...buttonsAesthetics ,
111- visibility : osparc . data . model . Study . canIWrite ( this . __studyData [ "accessRights" ] ) ? "visible" : "excluded" ,
112- } ) ;
113- renameButton . addListener ( "execute" , ( ) => {
114- const titleEditor = new osparc . widget . Renamer ( tabButton . getLabel ( ) ) ;
115- titleEditor . addListener ( "labelChanged" , e => {
116- titleEditor . close ( ) ;
117- const newLabel = e . getData ( ) [ "newLabel" ] ;
118- if ( this . getConversationId ( ) ) {
119- osparc . store . ConversationsProject . getInstance ( ) . renameConversation ( this . __studyData [ "uuid" ] , this . getConversationId ( ) , newLabel )
120- . then ( ( ) => this . renameConversation ( newLabel ) ) ;
121- } else {
122- // create new conversation first
123- osparc . store . ConversationsProject . getInstance ( ) . postConversation ( this . __studyData [ "uuid" ] , newLabel )
124- . then ( data => {
125- const conversation = new osparc . data . model . Conversation ( data , this . __studyData ) ;
126- this . setConversation ( conversation ) ;
127- this . getChildControl ( "button" ) . setLabel ( newLabel ) ;
128- } ) ;
129- }
130- } , this ) ;
131- titleEditor . center ( ) ;
132- titleEditor . open ( ) ;
133- } ) ;
134- // eslint-disable-next-line no-underscore-dangle
135- tabButton . _add ( renameButton , {
136- row : 0 ,
137- column : 3
138- } ) ;
139-
140- const closeButton = new qx . ui . form . Button ( null , "@FontAwesome5Solid/times/12" ) . set ( {
141- ...buttonsAesthetics ,
142- paddingLeft : 4 , // adds spacing between buttons
143- visibility : osparc . data . model . Study . canIWrite ( this . __studyData [ "accessRights" ] ) ? "visible" : "excluded" ,
144- } ) ;
145- closeButton . addListener ( "execute" , ( ) => {
146- if ( this . __messagesList . getChildren ( ) . length === 0 ) {
147- osparc . store . ConversationsProject . getInstance ( ) . deleteConversation ( this . __studyData [ "uuid" ] , this . getConversationId ( ) ) ;
148- } else {
149- const msg = this . tr ( "Are you sure you want to delete the conversation?" ) ;
150- const confirmationWin = new osparc . ui . window . Confirmation ( msg ) . set ( {
151- caption : this . tr ( "Delete Conversation" ) ,
152- confirmText : this . tr ( "Delete" ) ,
153- confirmAction : "delete"
154- } ) ;
155- confirmationWin . open ( ) ;
156- confirmationWin . addListener ( "close" , ( ) => {
157- if ( confirmationWin . getConfirmed ( ) ) {
158- osparc . store . ConversationsProject . getInstance ( ) . deleteConversation ( this . __studyData [ "uuid" ] , this . getConversationId ( ) ) ;
159- }
160- } , this ) ;
161- }
162- } ) ;
163- // eslint-disable-next-line no-underscore-dangle
164- tabButton . _add ( closeButton , {
165- row : 0 ,
166- column : 4
167- } ) ;
168- this . bind ( "conversation" , closeButton , "visibility" , {
169- converter : value => value ? "visible" : "excluded"
170- } ) ;
171- } ,
172-
173- renameConversation : function ( newName ) {
174- this . getChildControl ( "button" ) . setLabel ( newName ) ;
175- } ,
176-
177- __buildLayout : function ( ) {
178- this . __messagesTitle = new qx . ui . basic . Label ( ) ;
179- this . _add ( this . __messagesTitle ) ;
180-
181- // add spacer to keep the messages list at the bottom
182- this . _add ( new qx . ui . core . Spacer ( ) , {
183- flex : 100 // high number to keep even a one message list at the bottom
184- } ) ;
18533
186- this . __messagesList = new qx . ui . container . Composite ( new qx . ui . layout . VBox ( 5 ) ) . set ( {
187- alignY : "middle"
188- } ) ;
189- const scrollView = this . __messageScroll = new qx . ui . container . Scroll ( ) ;
190- scrollView . add ( this . __messagesList ) ;
191- this . _add ( scrollView , {
192- flex : 1
193- } ) ;
194-
195- this . __loadMoreMessages = new osparc . ui . form . FetchButton ( this . tr ( "Load more messages..." ) ) ;
196- this . __loadMoreMessages . addListener ( "execute" , ( ) => this . __reloadMessages ( false ) ) ;
197- this . _add ( this . __loadMoreMessages ) ;
34+ _buildLayout : function ( ) {
35+ this . base ( arguments ) ;
19836
199- const addMessage = new osparc . conversation . AddMessage ( ) . set ( {
37+ const addMessage = this . getChildControl ( "add-message" ) . set ( {
20038 studyData : this . __studyData ,
20139 enabled : osparc . data . model . Study . canIWrite ( this . __studyData [ "accessRights" ] ) ,
202- paddingLeft : 10 ,
203- } ) ;
204- this . bind ( "conversation" , addMessage , "conversationId" , {
205- converter : conversation => conversation ? conversation . getConversationId ( ) : null
20640 } ) ;
20741 addMessage . addListener ( "addMessage" , e => {
20842 const content = e . getData ( ) ;
@@ -234,7 +68,14 @@ qx.Class.define("osparc.study.Conversation", {
23468 } ) ;
23569 }
23670 } ) ;
237- this . _add ( addMessage ) ;
71+ } ,
72+
73+ _createMessageUI : function ( message ) {
74+ const messageUI = new osparc . conversation . MessageUI ( message , this . __studyData ) ;
75+ messageUI . getChildControl ( "message-content" ) . set ( {
76+ measurerMaxWidth : 400 ,
77+ } ) ;
78+ return messageUI ;
23879 } ,
23980
24081 __postMessage : function ( content ) {
@@ -258,142 +99,5 @@ qx.Class.define("osparc.study.Conversation", {
25899 }
259100 } ) ;
260101 } ,
261-
262- __reloadMessages : function ( removeMessages = true ) {
263- if ( this . getConversationId ( ) === null ) {
264- // temporary conversation page
265- this . __messagesTitle . setValue ( this . tr ( "No Messages yet" ) ) ;
266- this . __messagesList . hide ( ) ;
267- this . __loadMoreMessages . hide ( ) ;
268- return ;
269- }
270-
271- if ( removeMessages ) {
272- this . clearAllMessages ( ) ;
273- }
274- this . __messagesList . show ( ) ;
275-
276- this . __loadMoreMessages . show ( ) ;
277- this . __loadMoreMessages . setFetching ( true ) ;
278- this . getConversation ( ) . getNextMessages ( )
279- . then ( resp => {
280- const messages = resp [ "data" ] ;
281- messages . forEach ( message => this . addMessage ( message ) ) ;
282- this . __nextRequestParams = resp [ "_links" ] [ "next" ] ;
283- if ( this . __nextRequestParams === null && this . __loadMoreMessages ) {
284- this . __loadMoreMessages . exclude ( ) ;
285- }
286- } )
287- . finally ( ( ) => this . __loadMoreMessages . setFetching ( false ) ) ;
288- } ,
289-
290- clearAllMessages : function ( ) {
291- this . __messages = [ ] ;
292- this . __messagesList . removeAll ( ) ;
293- } ,
294-
295- __updateMessagesNumber : function ( ) {
296- if ( ! this . __messagesTitle ) {
297- return ;
298- }
299- const nMessages = this . __messages . filter ( msg => msg [ "type" ] === "MESSAGE" ) . length ;
300- if ( nMessages === 0 ) {
301- this . __messagesTitle . setValue ( this . tr ( "No Messages yet" ) ) ;
302- } else if ( nMessages === 1 ) {
303- this . __messagesTitle . setValue ( this . tr ( "1 Message" ) ) ;
304- } else if ( nMessages > 1 ) {
305- this . __messagesTitle . setValue ( nMessages + this . tr ( " Messages" ) ) ;
306- }
307- } ,
308-
309- addMessage : function ( message ) {
310- // backend doesn't provide the projectId
311- message [ "projectId" ] = this . __studyData [ "uuid" ] ;
312-
313- // ignore it if it was already there
314- const messageIndex = this . __messages . findIndex ( msg => msg [ "messageId" ] === message [ "messageId" ] ) ;
315- if ( messageIndex !== - 1 ) {
316- return ;
317- }
318-
319- // determine insertion index for latest‐first order
320- const newTime = new Date ( message [ "created" ] ) ;
321- let insertAt = this . __messages . findIndex ( m => new Date ( m [ "created" ] ) > newTime ) ;
322- if ( insertAt === - 1 ) {
323- insertAt = this . __messages . length ;
324- }
325-
326- // Insert the message in the messages array
327- this . __messages . splice ( insertAt , 0 , message ) ;
328-
329- // Add the UI element to the messages list
330- let control = null ;
331- switch ( message [ "type" ] ) {
332- case "MESSAGE" :
333- control = new osparc . conversation . MessageUI ( message , this . __studyData ) ;
334- control . getChildControl ( "message-content" ) . set ( {
335- measurerMaxWidth : 400 ,
336- } ) ;
337- control . addListener ( "messageUpdated" , e => this . updateMessage ( e . getData ( ) ) ) ;
338- control . addListener ( "messageDeleted" , e => this . deleteMessage ( e . getData ( ) ) ) ;
339- break ;
340- case "NOTIFICATION" :
341- control = new osparc . conversation . NotificationUI ( message ) ;
342- break ;
343- }
344- if ( control ) {
345- // insert into the UI at the same position
346- this . __messagesList . addAt ( control , insertAt ) ;
347- }
348-
349- // scroll to bottom
350- // add timeout to ensure the scroll happens after the UI is updated
351- setTimeout ( ( ) => {
352- this . __messageScroll . scrollToY ( this . __messageScroll . getChildControl ( "pane" ) . getScrollMaxY ( ) ) ;
353- } , 50 ) ;
354-
355- this . __updateMessagesNumber ( ) ;
356- } ,
357-
358- deleteMessage : function ( message ) {
359- // remove it from the messages array
360- const messageIndex = this . __messages . findIndex ( msg => msg [ "messageId" ] === message [ "messageId" ] ) ;
361- if ( messageIndex === - 1 ) {
362- return ;
363- }
364- this . __messages . splice ( messageIndex , 1 ) ;
365-
366- // Remove the UI element from the messages list
367- const children = this . __messagesList . getChildren ( ) ;
368- const controlIndex = children . findIndex (
369- ctrl => ( "getMessage" in ctrl && ctrl . getMessage ( ) [ "messageId" ] === message [ "messageId" ] )
370- ) ;
371- if ( controlIndex > - 1 ) {
372- this . __messagesList . remove ( children [ controlIndex ] ) ;
373- }
374-
375- this . __updateMessagesNumber ( ) ;
376- } ,
377-
378- updateMessage : function ( message ) {
379- // backend doesn't provide the projectId
380- message [ "projectId" ] = this . __studyData [ "uuid" ] ;
381-
382- // Replace the message in the messages array
383- const messageIndex = this . __messages . findIndex ( msg => msg [ "messageId" ] === message [ "messageId" ] ) ;
384- if ( messageIndex === - 1 ) {
385- return ;
386- }
387- this . __messages [ messageIndex ] = message ;
388-
389- // Update the UI element from the messages list
390- this . __messagesList . getChildren ( ) . forEach ( control => {
391- if ( "getMessage" in control && control . getMessage ( ) [ "messageId" ] === message [ "messageId" ] ) {
392- // Force a new reference
393- control . setMessage ( Object . assign ( { } , message ) ) ;
394- return ;
395- }
396- } ) ;
397- } ,
398102 }
399103} ) ;
0 commit comments