@chat21/chat21-web-widget 5.0.59-rc.2 → 5.0.59-rc.4
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/CHANGELOG.md +6 -0
- package/package.json +1 -1
- package/src/app/app.component.ts +188 -177
- package/src/app/app.module.ts +5 -3
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html +1 -1
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +43 -0
- package/src/app/component/home/home.component.html +1 -1
- package/src/app/component/home/home.component.ts +45 -0
- package/src/app/providers/global-settings.service.ts +1 -0
- package/src/app/utils/globals.ts +12 -0
- package/src/chat21-core/providers/abstract/notifications.service.ts +1 -1
- package/src/chat21-core/providers/chat-manager.ts +1 -1
- package/src/chat21-core/providers/firebase/firebase-notifications.ts +162 -69
- package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +1 -0
- package/src/chat21-core/providers/mqtt/mqtt-notifications.ts +40 -19
- package/src/chat21-core/providers/scripts/script.service.spec.ts +12 -0
- package/src/chat21-core/providers/scripts/script.service.ts +71 -0
- package/src/chat21-core/utils/constants.ts +8 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# chat21-web-widget ver 5.0
|
|
2
2
|
|
|
3
|
+
### 5.0.59-rc.4
|
|
4
|
+
- bug-fixed: texarea remains disabled if messages array has the last (non ordered) timestamp message set with 'disabledTextArea' set to true
|
|
5
|
+
|
|
6
|
+
### 5.0.59-rc.3
|
|
7
|
+
- bug-fixed: if mobileMarginX or MobileMarginY is set, widget do not fit on fullscreen once is opened
|
|
8
|
+
|
|
3
9
|
### 5.0.59-rc.2
|
|
4
10
|
- added: handler for buttons in last-message component
|
|
5
11
|
- changed: tooltip custom directive
|
package/package.json
CHANGED
package/src/app/app.component.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ScriptService } from './../chat21-core/providers/scripts/script.service';
|
|
1
2
|
import { TYPE_DIRECT } from './../chat21-core/utils/constants';
|
|
2
3
|
/** ANGULAR MODULES */
|
|
3
4
|
import { AfterViewInit, Component, ElementRef, HostListener, NgZone, OnDestroy, OnInit, ViewChild, ViewEncapsulation } from '@angular/core';
|
|
@@ -113,6 +114,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
113
114
|
private appStorageService: AppStorageService,
|
|
114
115
|
private translatorService: TranslatorService,
|
|
115
116
|
private translateService: CustomTranslateService,
|
|
117
|
+
private scriptService: ScriptService,
|
|
116
118
|
public chatManager: ChatManager,
|
|
117
119
|
private tiledeskRequestsService: TiledeskRequestsService,
|
|
118
120
|
public tiledeskAuthService: TiledeskAuthService,
|
|
@@ -123,220 +125,222 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
123
125
|
public imageRepoService: ImageRepoService,
|
|
124
126
|
public typingService: TypingService,
|
|
125
127
|
public presenceService: PresenceService,
|
|
126
|
-
public uploadService: UploadService
|
|
128
|
+
public uploadService: UploadService
|
|
127
129
|
){}
|
|
128
130
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
ngOnInit(): void {
|
|
132
|
+
this.logger.info('[APP-CONF]---------------- ngOnInit: APP.COMPONENT ---------------- ')
|
|
133
|
+
this.initWidgetParamiters();
|
|
134
|
+
}
|
|
133
135
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
136
|
+
ngAfterViewInit(): void {
|
|
137
|
+
this.logger.info('[APP-CONF]---------------- ngAfterViewInit: APP.COMPONENT ---------------- ')
|
|
138
|
+
this.ngZone.run(() => {
|
|
139
|
+
const that = this;
|
|
140
|
+
const subChangedConversation = this.conversationsHandlerService.conversationChanged.subscribe((conversation) => {
|
|
141
|
+
// that.ngZone.run(() => {
|
|
142
|
+
if (conversation) {
|
|
143
|
+
this.onImageLoaded(conversation)
|
|
144
|
+
this.onConversationLoaded(conversation)
|
|
143
145
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
if(conversation.recipient === this.g.senderId && isUserBanned(conversation)){
|
|
147
|
+
that.disposeWidget();
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if(conversation.is_new && conversation.sender !== this.g.senderId && !isInfo(conversation)){
|
|
152
|
+
that.manageTabNotification();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (that.g.isOpen === true) {
|
|
156
|
+
that.g.setParameter('displayEyeCatcherCard', 'none');
|
|
157
|
+
|
|
158
|
+
this.logger.debug('[APP-COMP] obsChangeConversation ::: ', conversation);
|
|
159
|
+
if (conversation.attributes && conversation.attributes['subtype'] === 'info') {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
} else {
|
|
164
|
+
// if(conversation.is_new && isJustRecived(this.g.startedAt.getTime(), conversation.timestamp)){
|
|
165
|
+
//widget closed
|
|
166
|
+
if(conversation.is_new && conversation.sender !== this.g.senderId && !isInfo(conversation)){
|
|
167
|
+
that.lastConversation = conversation;
|
|
168
|
+
that.g.isOpenNewMessage = true;
|
|
169
|
+
that.logger.debug('[APP-COMP] lastconversationnn', that.lastConversation)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
let badgeNewConverstionNumber = that.conversationsHandlerService.countIsNew()
|
|
174
|
+
that.g.setParameter('conversationsBadge', badgeNewConverstionNumber);
|
|
175
|
+
// }
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
that.triggerOnConversationUpdated(conversation);
|
|
179
|
+
} else {
|
|
180
|
+
this.logger.debug('[APP-COMP] oBSconversationChanged null: errorrr')
|
|
146
181
|
return;
|
|
147
182
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
183
|
+
|
|
184
|
+
// });
|
|
185
|
+
});
|
|
186
|
+
this.subscriptions.push(subChangedConversation);
|
|
152
187
|
|
|
153
|
-
|
|
188
|
+
const subAddedConversation = this.conversationsHandlerService.conversationAdded.subscribe((conversation) => {
|
|
189
|
+
// that.ngZone.run(() => {
|
|
190
|
+
if (that.g.isOpen === true && conversation) {
|
|
154
191
|
that.g.setParameter('displayEyeCatcherCard', 'none');
|
|
155
|
-
|
|
156
|
-
|
|
192
|
+
that.triggerOnConversationUpdated(conversation);
|
|
193
|
+
that.logger.debug('[APP-COMP] obsAddedConversation ::: ', conversation);
|
|
157
194
|
if (conversation.attributes && conversation.attributes['subtype'] === 'info') {
|
|
158
195
|
return;
|
|
159
196
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if(
|
|
197
|
+
if (conversation.is_new) {
|
|
198
|
+
that.manageTabNotification()
|
|
199
|
+
// this.soundMessage();
|
|
200
|
+
}
|
|
201
|
+
if(this.g.isOpen === false){
|
|
165
202
|
that.lastConversation = conversation;
|
|
166
203
|
that.g.isOpenNewMessage = true;
|
|
167
|
-
that.logger.debug('[APP-COMP] lastconversationnn', that.lastConversation)
|
|
168
204
|
}
|
|
169
|
-
|
|
205
|
+
} else {
|
|
206
|
+
//widget closed
|
|
170
207
|
|
|
171
208
|
let badgeNewConverstionNumber = that.conversationsHandlerService.countIsNew()
|
|
172
209
|
that.g.setParameter('conversationsBadge', badgeNewConverstionNumber);
|
|
173
|
-
// }
|
|
174
210
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
// });
|
|
183
|
-
});
|
|
184
|
-
this.subscriptions.push(subChangedConversation);
|
|
185
|
-
|
|
186
|
-
const subAddedConversation = this.conversationsHandlerService.conversationAdded.subscribe((conversation) => {
|
|
187
|
-
// that.ngZone.run(() => {
|
|
188
|
-
if (that.g.isOpen === true && conversation) {
|
|
189
|
-
that.g.setParameter('displayEyeCatcherCard', 'none');
|
|
190
|
-
that.triggerOnConversationUpdated(conversation);
|
|
191
|
-
that.logger.debug('[APP-COMP] obsAddedConversation ::: ', conversation);
|
|
192
|
-
if (conversation.attributes && conversation.attributes['subtype'] === 'info') {
|
|
193
|
-
return;
|
|
211
|
+
// that.manageTabNotification()
|
|
212
|
+
// });
|
|
213
|
+
if(conversation){
|
|
214
|
+
this.onImageLoaded(conversation)
|
|
215
|
+
this.onConversationLoaded(conversation)
|
|
194
216
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
217
|
+
|
|
218
|
+
});
|
|
219
|
+
this.subscriptions.push(subAddedConversation);
|
|
220
|
+
|
|
221
|
+
const subAddedArchivedConversations = this.archivedConversationsService.archivedConversationAdded.subscribe((conversation) => {
|
|
222
|
+
// that.ngZone.run(() => {
|
|
223
|
+
if (conversation) {
|
|
224
|
+
that.triggerOnConversationUpdated(conversation);
|
|
225
|
+
this.onImageLoaded(conversation)
|
|
226
|
+
this.onConversationLoaded(conversation)
|
|
198
227
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
228
|
+
// });
|
|
229
|
+
});
|
|
230
|
+
this.subscriptions.push(subAddedArchivedConversations);
|
|
231
|
+
|
|
232
|
+
const subRemovedArchivedConversations = this.archivedConversationsService.archivedConversationRemoved.subscribe((conversation) => {
|
|
233
|
+
// that.ngZone.run(() => {
|
|
234
|
+
if (conversation) {
|
|
235
|
+
this.isConversationArchived = false;
|
|
236
|
+
that.triggerOnConversationUpdated(conversation);
|
|
202
237
|
}
|
|
203
|
-
|
|
204
|
-
|
|
238
|
+
// });
|
|
239
|
+
});
|
|
240
|
+
this.subscriptions.push(subRemovedArchivedConversations);
|
|
205
241
|
|
|
206
|
-
let badgeNewConverstionNumber = that.conversationsHandlerService.countIsNew()
|
|
207
|
-
that.g.setParameter('conversationsBadge', badgeNewConverstionNumber);
|
|
208
|
-
}
|
|
209
|
-
// that.manageTabNotification()
|
|
210
|
-
// });
|
|
211
|
-
if(conversation){
|
|
212
|
-
this.onImageLoaded(conversation)
|
|
213
|
-
this.onConversationLoaded(conversation)
|
|
214
|
-
}
|
|
215
|
-
|
|
216
242
|
});
|
|
217
|
-
this.
|
|
243
|
+
this.appStorageService.initialize(environment.storage_prefix, this.g.persistence, this.g.projectid)
|
|
244
|
+
this.tiledeskAuthService.initialize(this.appConfigService.getConfig().apiUrl)
|
|
245
|
+
this.tiledeskRequestsService.initialize(this.appConfigService.getConfig().apiUrl, this.g.projectid)
|
|
246
|
+
this.messagingAuthService.initialize();
|
|
247
|
+
this.chatManager.initialize();
|
|
248
|
+
this.uploadService.initialize();
|
|
249
|
+
}
|
|
218
250
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
251
|
+
private initWidgetParamiters(){
|
|
252
|
+
const that = this;
|
|
253
|
+
const obsSettingsService = this.globalSettingsService.obsSettingsService.subscribe((resp) => {
|
|
254
|
+
if(resp){
|
|
255
|
+
|
|
256
|
+
// /** INIT */
|
|
257
|
+
this.logger.setLoggerConfig(this.g.isLogEnabled, this.g.logLevel)
|
|
258
|
+
this.tabTitle = this.g.windowContext.window.document.title
|
|
259
|
+
this.appStorageService.initialize(environment.storage_prefix, this.g.persistence, this.g.projectid)
|
|
260
|
+
this.logger.debug('[APP-COMP] check if token is passed throw url: ', this.g.jwt);
|
|
261
|
+
/**CHECK IF JWT IS IN URL PARAMETERS */
|
|
262
|
+
if (this.g.jwt) {
|
|
263
|
+
// logging in with custom token from url
|
|
264
|
+
// add JWY token to localstorage and authenticate with it this.logger.debug('[APP-COMP] token from url. isShown:', this.g.isShown, 'autostart:', this.g.autoStart)
|
|
265
|
+
this.logger.debug('[APP-COMP] ---------------- logging in with custom token from url ---------------- ');
|
|
266
|
+
// this.g.autoStart = false;
|
|
267
|
+
const storedTiledeskToken = this.appStorageService.getItem('tiledeskToken')
|
|
268
|
+
storedTiledeskToken === this.g.jwt? null: this.appStorageService.setItem('tiledeskToken', this.g.jwt);
|
|
269
|
+
this.g.tiledeskToken = this.g.jwt;
|
|
270
|
+
// this.signInWithCustomToken(this.g.jwt) // moved to authenticate() in else(tiledeskToken)
|
|
271
|
+
}
|
|
229
272
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
273
|
+
/** INIT LABELS TRANSLATIONS */
|
|
274
|
+
this.translatorService.initI18n().then((result) => {
|
|
275
|
+
this.logger.debug('[APP-COMP] »»»» APP-COMPONENT.TS initI18n result', result);
|
|
276
|
+
const browserLang = this.translatorService.getLanguage();
|
|
277
|
+
// moment.locale(browserLang)
|
|
278
|
+
dayjs.locale(browserLang)
|
|
279
|
+
this.translatorService.translate(this.g);
|
|
280
|
+
}).then(() => {
|
|
281
|
+
/** INIT */
|
|
282
|
+
that.initAll();
|
|
283
|
+
/** TRIGGER ONBEFORE INIT */
|
|
284
|
+
that.triggerOnBeforeInit();
|
|
285
|
+
/** AUTH */
|
|
286
|
+
that.setAuthSubscription();
|
|
287
|
+
/** SCRIPT LOAD */
|
|
288
|
+
that.loadCustomScript(this.appConfigService.getConfig())
|
|
289
|
+
})
|
|
290
|
+
|
|
235
291
|
}
|
|
236
|
-
// });
|
|
237
292
|
});
|
|
238
|
-
this.subscriptions.push(
|
|
239
|
-
|
|
240
|
-
});
|
|
241
|
-
this.appStorageService.initialize(environment.storage_prefix, this.g.persistence, this.g.projectid)
|
|
242
|
-
this.tiledeskAuthService.initialize(this.appConfigService.getConfig().apiUrl)
|
|
243
|
-
this.tiledeskRequestsService.initialize(this.appConfigService.getConfig().apiUrl, this.g.projectid)
|
|
244
|
-
this.messagingAuthService.initialize();
|
|
245
|
-
this.chatManager.initialize();
|
|
246
|
-
this.uploadService.initialize();
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
private initWidgetParamiters(){
|
|
250
|
-
const that = this;
|
|
251
|
-
const obsSettingsService = this.globalSettingsService.obsSettingsService.subscribe((resp) => {
|
|
252
|
-
if(resp){
|
|
253
|
-
|
|
254
|
-
// /** INIT */
|
|
255
|
-
this.logger.setLoggerConfig(this.g.isLogEnabled, this.g.logLevel)
|
|
256
|
-
this.tabTitle = this.g.windowContext.window.document.title
|
|
257
|
-
this.appStorageService.initialize(environment.storage_prefix, this.g.persistence, this.g.projectid)
|
|
258
|
-
this.logger.debug('[APP-COMP] check if token is passed throw url: ', this.g.jwt);
|
|
259
|
-
/**CHECK IF JWT IS IN URL PARAMETERS */
|
|
260
|
-
if (this.g.jwt) {
|
|
261
|
-
// logging in with custom token from url
|
|
262
|
-
// add JWY token to localstorage and authenticate with it this.logger.debug('[APP-COMP] token from url. isShown:', this.g.isShown, 'autostart:', this.g.autoStart)
|
|
263
|
-
this.logger.debug('[APP-COMP] ---------------- logging in with custom token from url ---------------- ');
|
|
264
|
-
// this.g.autoStart = false;
|
|
265
|
-
const storedTiledeskToken = this.appStorageService.getItem('tiledeskToken')
|
|
266
|
-
storedTiledeskToken === this.g.jwt? null: this.appStorageService.setItem('tiledeskToken', this.g.jwt);
|
|
267
|
-
this.g.tiledeskToken = this.g.jwt;
|
|
268
|
-
// this.signInWithCustomToken(this.g.jwt) // moved to authenticate() in else(tiledeskToken)
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
/** INIT LABELS TRANSLATIONS */
|
|
272
|
-
this.translatorService.initI18n().then((result) => {
|
|
273
|
-
this.logger.debug('[APP-COMP] »»»» APP-COMPONENT.TS initI18n result', result);
|
|
274
|
-
const browserLang = this.translatorService.getLanguage();
|
|
275
|
-
// moment.locale(browserLang)
|
|
276
|
-
dayjs.locale(browserLang)
|
|
277
|
-
this.translatorService.translate(this.g);
|
|
278
|
-
}).then(() => {
|
|
279
|
-
/** INIT */
|
|
280
|
-
that.initAll();
|
|
281
|
-
/** TRIGGER ONBEFORE INIT */
|
|
282
|
-
that.triggerOnBeforeInit();
|
|
283
|
-
/** AUTH */
|
|
284
|
-
that.setAuthSubscription();
|
|
285
|
-
})
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
});
|
|
289
|
-
this.subscriptions.push(obsSettingsService);
|
|
290
|
-
this.globalSettingsService.initWidgetParamiters(this.g, this.el);
|
|
293
|
+
this.subscriptions.push(obsSettingsService);
|
|
294
|
+
this.globalSettingsService.initWidgetParamiters(this.g, this.el);
|
|
291
295
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
296
|
+
// SET AUDIO
|
|
297
|
+
this.audio = new Audio();
|
|
298
|
+
this.audio.src = this.g.baseLocation + URL_SOUND_LIST_CONVERSATION;
|
|
299
|
+
this.audio.load();
|
|
300
|
+
}
|
|
297
301
|
|
|
298
|
-
|
|
299
|
-
|
|
302
|
+
private initAll() {
|
|
303
|
+
this.addComponentToWindow(this.ngZone);
|
|
300
304
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
305
|
+
//INIT TRIGGER-HANDLER
|
|
306
|
+
this.triggerHandler.setElement(this.el)
|
|
307
|
+
this.triggerHandler.setWindowContext(this.g.windowContext)
|
|
304
308
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
309
|
+
// /** TRANSLATION LOADER: */
|
|
310
|
+
// // this.translatorService.translate(this.g);
|
|
311
|
+
// this.translatorService.initI18n().then((result) => {
|
|
312
|
+
// this.g.wdLog(['»»»» APP-COMPONENT.TS initI18n result', result]);
|
|
313
|
+
// this.translatorService.translate(this.g);
|
|
314
|
+
// });
|
|
311
315
|
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
316
|
+
/** SET ATTRIBUTES */
|
|
317
|
+
const attributes = this.setAttributesFromStorageService();
|
|
318
|
+
if (attributes) {
|
|
319
|
+
this.g.attributes = attributes;
|
|
320
|
+
}
|
|
321
|
+
this.setStyleMap()
|
|
318
322
|
|
|
319
|
-
|
|
323
|
+
// ------------------------------- //
|
|
320
324
|
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
325
|
+
// ------------------------------- //
|
|
326
|
+
/**
|
|
327
|
+
* INIZIALIZE GLOBALS :
|
|
328
|
+
* create settings object used in trigger
|
|
329
|
+
* set isMobile
|
|
330
|
+
* set attributes
|
|
331
|
+
*/
|
|
332
|
+
this.g.initialize();
|
|
333
|
+
// ------------------------------- //
|
|
330
334
|
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
335
|
+
this.removeFirebasewebsocketFromLocalStorage();
|
|
336
|
+
// this.triggerLoadParamsEvent();
|
|
337
|
+
// this.addComponentToWindow(this.ngZone); // forse dovrebbe stare prima di tutti i triggers
|
|
334
338
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
339
|
+
this.initLauncherButton();
|
|
340
|
+
this.triggerLoadParamsEvent(); // first trigger
|
|
341
|
+
//this.setAvailableAgentsStatus();
|
|
338
342
|
|
|
339
|
-
|
|
343
|
+
}
|
|
340
344
|
|
|
341
345
|
// ========= begin:: SUBSCRIPTIONS ============//
|
|
342
346
|
private async setAuthSubscription(){
|
|
@@ -2064,6 +2068,13 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
2064
2068
|
this.el.nativeElement.style.setProperty('--button-in-msg-font-size', this.g.buttonFontSize)
|
|
2065
2069
|
}
|
|
2066
2070
|
|
|
2071
|
+
|
|
2072
|
+
private loadCustomScript(config){
|
|
2073
|
+
if(config.hasOwnProperty("globalRemoteJSSrc")){
|
|
2074
|
+
this.scriptService.buildScriptArray(config['globalRemoteJSSrc'])
|
|
2075
|
+
}
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2067
2078
|
// ========= begin:: DESTROY ALL SUBSCRIPTIONS ============//
|
|
2068
2079
|
/** elimino tutte le sottoscrizioni */
|
|
2069
2080
|
ngOnDestroy() {
|
package/src/app/app.module.ts
CHANGED
|
@@ -62,10 +62,11 @@ import { TranslateModule } from '@ngx-translate/core';
|
|
|
62
62
|
import { PickerModule } from '@ctrl/ngx-emoji-mart';
|
|
63
63
|
import { LoggerModule, NGXLogger, NgxLoggerLevel } from "ngx-logger";
|
|
64
64
|
|
|
65
|
-
//DIRECTIVES
|
|
65
|
+
//DIRECTIVES-PIPES
|
|
66
66
|
import { HtmlEntitiesEncodePipe } from './pipe/html-entities-encode.pipe';
|
|
67
67
|
import { MarkedPipe } from './pipe/marked.pipe';
|
|
68
68
|
import { SafeHtmlPipe } from './pipe/safe-html.pipe';
|
|
69
|
+
import { TooltipDirective } from 'src/app/directives/tooltip.directive';
|
|
69
70
|
|
|
70
71
|
//LOGGER SERVICES
|
|
71
72
|
import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
|
|
@@ -128,7 +129,7 @@ import { WaitingService } from './providers/waiting.service';
|
|
|
128
129
|
import { StarRatingWidgetService } from './providers/star-rating-widget.service';
|
|
129
130
|
import { LikeUnlikeComponent } from './component/message/like-unlike/like-unlike.component';
|
|
130
131
|
import { Rules } from './utils/rules';
|
|
131
|
-
import {
|
|
132
|
+
import { ScriptService } from 'src/chat21-core/providers/scripts/script.service';
|
|
132
133
|
|
|
133
134
|
|
|
134
135
|
const appInitializerFn = (appConfig: AppConfigService, logger: NGXLogger) => {
|
|
@@ -381,7 +382,8 @@ export function uploadFactory(http: HttpClient, appConfig: AppConfigService, app
|
|
|
381
382
|
TranslatorService,
|
|
382
383
|
CustomTranslateService,
|
|
383
384
|
Triggerhandler,
|
|
384
|
-
WaitingService
|
|
385
|
+
WaitingService,
|
|
386
|
+
ScriptService
|
|
385
387
|
],
|
|
386
388
|
bootstrap: [AppComponent]
|
|
387
389
|
})
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<!-- LOGO-->
|
|
2
2
|
<div id="hiddenFooter" *ngIf="!hideTextAreaContent && poweredBy" class="fade-in-bottom"
|
|
3
3
|
[class.hideTextReply]="hideTextReply">
|
|
4
|
-
<div tabindex="-1" class="c21-powered-by" [innerHTML]="poweredBy"></div>
|
|
4
|
+
<div tabindex="-1" class="c21-powered-by" [innerHTML]="poweredBy" (click)="managePoweredBy($event)"></div>
|
|
5
5
|
</div>
|
|
6
6
|
|
|
7
7
|
<!-- TEXTAREA + ICONS: conv active-->
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts
CHANGED
|
@@ -596,4 +596,47 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
596
596
|
}
|
|
597
597
|
}
|
|
598
598
|
|
|
599
|
+
|
|
600
|
+
|
|
601
|
+
managePoweredBy(event: Event){
|
|
602
|
+
event.stopPropagation();
|
|
603
|
+
this.segmentLogoClick()
|
|
604
|
+
let target = (event.target as Element) || (event.srcElement as Element) || (event.currentTarget as Element)
|
|
605
|
+
if(target.parentElement.tagName === 'A' && target.parentElement.hasAttribute('href')){
|
|
606
|
+
window.open(target.parentElement.getAttribute('href'), '_blank')
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
|
|
611
|
+
private segmentLogoClick(){
|
|
612
|
+
let that = this
|
|
613
|
+
if(window['analytics']){
|
|
614
|
+
try {
|
|
615
|
+
window['analytics'].page("Widget Conversation Page, LogoClick", {});
|
|
616
|
+
} catch (err) {
|
|
617
|
+
this.logger.error('Event:Signed In [page] error', err);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
try {
|
|
621
|
+
window['analytics'].identify(that.senderId, {
|
|
622
|
+
name: that.userFullname,
|
|
623
|
+
email: that.userEmail,
|
|
624
|
+
logins: 5,
|
|
625
|
+
});
|
|
626
|
+
} catch (err) {
|
|
627
|
+
this.logger.error('Event:LogoClick [identify] error', err);
|
|
628
|
+
}
|
|
629
|
+
// Segments
|
|
630
|
+
try {
|
|
631
|
+
window['analytics'].track('LogoClick', {
|
|
632
|
+
"username": that.userFullname,
|
|
633
|
+
"userId": that.userEmail,
|
|
634
|
+
"attributes": that.attributes
|
|
635
|
+
});
|
|
636
|
+
} catch (err) {
|
|
637
|
+
this.logger.error('Event:LogoClick [track] error', err);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
|
|
599
642
|
}
|
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
<!-- FOOTER -->
|
|
145
145
|
<div class="c21-footer fade-in-bottom-footer">
|
|
146
146
|
<div id="c21-powered-by" (mouseover)="hover=true" (mouseleave)="hover=false">
|
|
147
|
-
<div tabindex="-1" class="c21-powered-by" [innerHTML]="g.poweredBy"></div>
|
|
147
|
+
<div tabindex="-1" class="c21-powered-by" [innerHTML]="g.poweredBy" (click)="managePoweredBy($event)"></div>
|
|
148
148
|
<!-- <div class="build_version">{{g.BUILD_VERSION}}</div> -->
|
|
149
149
|
</div>
|
|
150
150
|
<chat-menu-options *ngIf="!hideSettings"
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { TiledeskAuthService } from './../../../chat21-core/providers/tiledesk/tiledesk-auth.service';
|
|
1
2
|
import { AfterViewInit, Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild, ViewEncapsulation } from '@angular/core';
|
|
2
3
|
import { CustomTranslateService } from 'src/chat21-core/providers/custom-translate.service';
|
|
3
4
|
import { ConversationModel } from '../../../chat21-core/models/conversation';
|
|
@@ -47,6 +48,7 @@ export class HomeComponent implements OnInit, AfterViewInit {
|
|
|
47
48
|
|
|
48
49
|
constructor(
|
|
49
50
|
public g: Globals,
|
|
51
|
+
private tiledeskAuthService : TiledeskAuthService,
|
|
50
52
|
private customTranslateService: CustomTranslateService,
|
|
51
53
|
) {
|
|
52
54
|
|
|
@@ -85,6 +87,49 @@ export class HomeComponent implements OnInit, AfterViewInit {
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
|
|
90
|
+
managePoweredBy(event: Event){
|
|
91
|
+
event.stopPropagation();
|
|
92
|
+
this.segmentLogoClick()
|
|
93
|
+
let target = (event.target as Element) || (event.srcElement as Element) || (event.currentTarget as Element)
|
|
94
|
+
if(target.parentElement.tagName === 'A' && target.parentElement.hasAttribute('href')){
|
|
95
|
+
window.open(target.parentElement.getAttribute('href'), '_blank')
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
private segmentLogoClick(){
|
|
101
|
+
let that = this
|
|
102
|
+
let user = this.tiledeskAuthService.getCurrentUser()
|
|
103
|
+
if(window['analytics']){
|
|
104
|
+
try {
|
|
105
|
+
window['analytics'].page("Widget Home Page, LogoClick", {});
|
|
106
|
+
} catch (err) {
|
|
107
|
+
this.logger.error('Event:Signed In [page] error', err);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
try {
|
|
111
|
+
window['analytics'].identify(user.uid, {
|
|
112
|
+
name: user.firstname + ' ' + user.lastname,
|
|
113
|
+
email: user.email,
|
|
114
|
+
logins: 5,
|
|
115
|
+
});
|
|
116
|
+
} catch (err) {
|
|
117
|
+
this.logger.error('Event:LogoClick [identify] error', err);
|
|
118
|
+
}
|
|
119
|
+
// Segments
|
|
120
|
+
try {
|
|
121
|
+
window['analytics'].track('LogoClick', {
|
|
122
|
+
"username": user.firstname + ' ' + user.lastname,
|
|
123
|
+
"userId": user.uid,
|
|
124
|
+
"attributes": that.g.attributes
|
|
125
|
+
});
|
|
126
|
+
} catch (err) {
|
|
127
|
+
this.logger.error('Event:LogoClick [track] error', err);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
88
133
|
|
|
89
134
|
|
|
90
135
|
|
|
@@ -369,6 +369,7 @@ export class GlobalSettingsService {
|
|
|
369
369
|
this.globals.isMobile? marginX= this.globals.mobileMarginX: marginX = this.globals.marginX
|
|
370
370
|
divTiledeskiframe.style.right = marginX;
|
|
371
371
|
}
|
|
372
|
+
|
|
372
373
|
if (this.globals.isMobile) {
|
|
373
374
|
divTiledeskiframe.style.bottom = this.globals.mobileMarginY
|
|
374
375
|
} else {
|
package/src/app/utils/globals.ts
CHANGED
|
@@ -587,6 +587,18 @@ export class Globals {
|
|
|
587
587
|
} else if(!isOpen && chat21conversationsEL){
|
|
588
588
|
chat21conversationsEL.classList.remove('isMobile')
|
|
589
589
|
}
|
|
590
|
+
|
|
591
|
+
|
|
592
|
+
//customize position for 'tiledeskdiv' for mobile
|
|
593
|
+
if(isOpen && this.isMobile && divTiledeskWidget){
|
|
594
|
+
divTiledeskWidget.style.right = '0px'
|
|
595
|
+
divTiledeskWidget.style.bottom = '0px'
|
|
596
|
+
} else if(!isOpen && this.isMobile && divTiledeskWidget){
|
|
597
|
+
divTiledeskWidget.style.bottom = this.marginY
|
|
598
|
+
this.align === 'left'? divTiledeskWidget.style.left = this.mobileMarginX : divTiledeskWidget.style.right = this.mobileMarginX;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
|
|
590
602
|
}
|
|
591
603
|
|
|
592
604
|
setWidgetPreviewContainerSize(width: number, height: number){
|
|
@@ -17,7 +17,7 @@ export abstract class NotificationsService {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
abstract initialize(tenant: string, vapidKey: string): void;
|
|
20
|
+
abstract initialize(tenant: string, vapidKey: string, platform: string): void;
|
|
21
21
|
abstract getNotificationPermissionAndSaveToken(currentUserUid: string): void;
|
|
22
22
|
abstract removeNotificationsInstance(callback: (string) => void): void;
|
|
23
23
|
|
|
@@ -184,7 +184,7 @@ export class ChatManager {
|
|
|
184
184
|
getConversationHandlerByConversationId(conversationId): any {
|
|
185
185
|
let handler = null;
|
|
186
186
|
this.handlers.forEach(conv => {
|
|
187
|
-
|
|
187
|
+
this.logger.log('[CHAT MANAGER]forEach ***', conversationId, this.handlers, conv);
|
|
188
188
|
if (conv.conversationWith === conversationId) {
|
|
189
189
|
handler = conv;
|
|
190
190
|
return;
|
|
@@ -1,79 +1,82 @@
|
|
|
1
|
-
import { LoggerInstance } from './../logger/loggerInstance';
|
|
2
1
|
import { Injectable } from '@angular/core';
|
|
3
2
|
// services
|
|
4
3
|
import { NotificationsService } from '../abstract/notifications.service';
|
|
5
|
-
|
|
4
|
+
import { LoggerInstance } from '../logger/loggerInstance';
|
|
5
|
+
import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
|
|
6
6
|
// firebase
|
|
7
|
-
// import firebase from 'firebase/app';
|
|
7
|
+
// import * as firebase from 'firebase/app';
|
|
8
|
+
import firebase from "firebase/app";
|
|
9
|
+
import 'firebase/messaging';
|
|
10
|
+
import 'firebase/auth';
|
|
8
11
|
|
|
9
|
-
|
|
12
|
+
@Injectable({ providedIn: 'root' })
|
|
10
13
|
|
|
11
|
-
// @Injectable({ providedIn: 'root' })
|
|
12
|
-
@Injectable()
|
|
13
14
|
export class FirebaseNotifications extends NotificationsService {
|
|
14
|
-
|
|
15
|
-
// public BUILD_VERSION: string;
|
|
15
|
+
|
|
16
16
|
private FCMcurrentToken: string;
|
|
17
17
|
private userId: string;
|
|
18
18
|
private tenant: string;
|
|
19
19
|
private vapidkey: string;
|
|
20
|
-
private
|
|
21
|
-
|
|
20
|
+
private platform: string;
|
|
22
21
|
private logger: LoggerService = LoggerInstance.getInstance();
|
|
23
22
|
constructor() {
|
|
24
23
|
super();
|
|
25
24
|
}
|
|
26
25
|
|
|
27
|
-
|
|
26
|
+
initialize(tenant: string, vapId: string, platform: string): void {
|
|
28
27
|
this.tenant = tenant
|
|
29
28
|
this.vapidkey = vapId
|
|
30
|
-
this.
|
|
31
|
-
|
|
32
|
-
const { default: firebase} = await import("firebase/app");
|
|
33
|
-
this.firebase = firebase
|
|
29
|
+
platform === 'desktop'? this.platform = 'ionic' : this.platform = platform
|
|
30
|
+
this.logger.log('[FIREBASE-NOTIFICATIONS] initialize - tenant ', this.tenant, this.platform)
|
|
34
31
|
|
|
35
32
|
if (!('serviceWorker' in navigator)) {
|
|
36
33
|
// , disable or hide UI.
|
|
37
34
|
this.logger.error("[FIREBASE-NOTIFICATIONS] initialize - Service Worker isn't supported on this browser", navigator)
|
|
38
35
|
return;
|
|
39
36
|
}
|
|
40
|
-
if (('serviceWorker' in navigator)) {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
if (serviceWorkerRegistrations.length > 0) {
|
|
45
|
-
serviceWorkerRegistrations.forEach(registration => {
|
|
46
|
-
this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registration ", registration)
|
|
47
|
-
// this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registrations scriptURL", registrations.active.scriptURL)
|
|
48
|
-
// this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registrations state", registrations.active.state)
|
|
49
|
-
|
|
50
|
-
});
|
|
51
|
-
} else {
|
|
52
|
-
this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser - !not registered",)
|
|
37
|
+
// if (('serviceWorker' in navigator)) {
|
|
38
|
+
// navigator.serviceWorker.register('firebase-messaging-sw.js')
|
|
39
|
+
// .then(function (registration) {
|
|
40
|
+
// console.log('[FIREBASE-NOTIFICATIONS] initialize serviceWorker Registration successful, scope is:', registration.scope);
|
|
53
41
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
42
|
+
|
|
43
|
+
// // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser ", navigator)
|
|
44
|
+
// // navigator.serviceWorker.getRegistrations().then((serviceWorkerRegistrations) => {
|
|
45
|
+
// // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser serviceWorkerRegistrations", serviceWorkerRegistrations)
|
|
46
|
+
// // if (serviceWorkerRegistrations.length > 0) {
|
|
47
|
+
// // serviceWorkerRegistrations.forEach(registration => {
|
|
48
|
+
// // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registration ", registration)
|
|
49
|
+
// // // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registrations scriptURL", registrations.active.scriptURL)
|
|
50
|
+
// // // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser registrations state", registrations.active.state)
|
|
51
|
+
|
|
52
|
+
// // });
|
|
53
|
+
// // } else {
|
|
54
|
+
// // this.logger.log("[FIREBASE-NOTIFICATIONS] initialize - Service Worker is supported on this browser - !not registered",)
|
|
55
|
+
// // // navigator.serviceWorker.register('http://localhost:8101/firebase-messaging-sw.js')
|
|
56
|
+
// // // .then(function (registration) {
|
|
57
|
+
// // // console.log('Service worker successfully registered.');
|
|
58
|
+
// // // return registration;
|
|
59
|
+
// // // }).catch(function (err) {
|
|
60
|
+
// // // console.error('Unable to register service worker.', err);
|
|
61
|
+
// // // });
|
|
62
|
+
// // }
|
|
63
|
+
// // });
|
|
64
|
+
// }).catch(function (err) {
|
|
65
|
+
// console.log('Service worker registration failed, error:', err);
|
|
66
|
+
// });
|
|
67
|
+
// }
|
|
57
68
|
}
|
|
58
69
|
|
|
70
|
+
|
|
71
|
+
|
|
59
72
|
getNotificationPermissionAndSaveToken(currentUserUid) {
|
|
60
73
|
// this.tenant = this.getTenant();
|
|
61
|
-
this.logger.log('[FIREBASE-NOTIFICATIONS] calling requestPermission - tenant ', this.tenant)
|
|
62
|
-
this.logger.log('[FIREBASE-NOTIFICATIONS] calling requestPermission - currentUserUid ', currentUserUid)
|
|
74
|
+
this.logger.log('initialize FROM [APP-COMP] - [FIREBASE-NOTIFICATIONS] calling requestPermission - tenant ', this.tenant, ' currentUserUid ', currentUserUid)
|
|
75
|
+
// this.logger.log('[FIREBASE-NOTIFICATIONS] calling requestPermission - currentUserUid ', currentUserUid)
|
|
63
76
|
this.userId = currentUserUid;
|
|
64
|
-
// Service Worker explicit registration to explicitly define sw location at a path
|
|
65
|
-
// const swRegistration = async () => {
|
|
66
|
-
// try {
|
|
67
|
-
// await navigator.serviceWorker.register('http://localhost:8101/firebase-messaging-sw.js');
|
|
68
|
-
// } catch (error) {
|
|
69
|
-
// console.error(error);
|
|
70
|
-
// }
|
|
71
|
-
// }
|
|
72
|
-
|
|
73
77
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const messaging = this.firebase.messaging();
|
|
78
|
+
if (firebase.messaging.isSupported()) {
|
|
79
|
+
const messaging = firebase.messaging();
|
|
77
80
|
// messaging.requestPermission()
|
|
78
81
|
Notification.requestPermission().then((permission) => {
|
|
79
82
|
if (permission === 'granted') {
|
|
@@ -91,46 +94,136 @@ export class FirebaseNotifications extends NotificationsService {
|
|
|
91
94
|
});
|
|
92
95
|
} else {
|
|
93
96
|
this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> FIREBASE MESSAGING IS NOT SUPPORTED')
|
|
97
|
+
|
|
98
|
+
// if(this.platform == 'android' || this.platform === 'ios'){
|
|
99
|
+
// this.logger.log('[MQTTNotificationService] >>>> FIREBASE MESSAGING: use FCM plugin')
|
|
100
|
+
// this.fcm.onTokenRefresh().subscribe(FCMtoken => {
|
|
101
|
+
// // Register your new token in your back-end if you want
|
|
102
|
+
// // backend.registerToken(token);
|
|
103
|
+
// this.FCMcurrentToken = FCMtoken;
|
|
104
|
+
// console.log("[MQTTNotificationService] FCM: onTokenRefresh --->", FCMtoken);
|
|
105
|
+
// this.updateToken(FCMtoken, currentUserUid)
|
|
106
|
+
// });
|
|
107
|
+
// this.fcm.requestPushPermission().then((permission) => {
|
|
108
|
+
// console.log("[MQTTNotificationService] FCM: requestPushPermission --->", permission);
|
|
109
|
+
// if(permission === true){
|
|
110
|
+
// this.fcm.getToken().then(FCMtoken => {
|
|
111
|
+
// console.log("[MQTTNotificationService] FCM: getToken --->", FCMtoken);
|
|
112
|
+
// this.FCMcurrentToken = FCMtoken;
|
|
113
|
+
// this.updateToken(FCMtoken, currentUserUid)
|
|
114
|
+
// });
|
|
115
|
+
// }
|
|
116
|
+
// });
|
|
117
|
+
|
|
118
|
+
// }
|
|
94
119
|
}
|
|
95
120
|
}
|
|
96
121
|
|
|
122
|
+
|
|
123
|
+
// getNotificationPermissionAndSaveToken(currentUserUid) {
|
|
124
|
+
// // this.tenant = this.getTenant();
|
|
125
|
+
// this.logger.log('[FIREBASE-NOTIFICATIONS] calling requestPermission - tenant ', this.tenant)
|
|
126
|
+
// this.logger.log('[FIREBASE-NOTIFICATIONS] calling requestPermission - currentUserUid ', currentUserUid)
|
|
127
|
+
// this.userId = currentUserUid;
|
|
128
|
+
// const messaging = firebase.messaging();
|
|
129
|
+
// if (firebase.messaging.isSupported()) {
|
|
130
|
+
// // messaging.requestPermission()
|
|
131
|
+
// Notification.requestPermission().then((permission) => {
|
|
132
|
+
// if (permission === 'granted') {
|
|
133
|
+
// this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> requestPermission Notification permission granted.');
|
|
134
|
+
// messaging.getToken({ vapidKey: 'BOsgS2ADwspKdWAmiFDZXEYqY1HSYADVfJT3j67wsySh3NxaViJqoabPJH8WM02wb5r8cQIm5TgM0UK047Z1D1c'}).then((currentToken) => {
|
|
135
|
+
// if (currentToken) {
|
|
136
|
+
// this.sendTokenToServer(currentToken);
|
|
137
|
+
// // updateUIForPushEnabled(currentToken);
|
|
138
|
+
|
|
139
|
+
// } else {
|
|
140
|
+
// // Show permission request UI
|
|
141
|
+
// console.log('No registration token available. Request permission to generate one.');
|
|
142
|
+
// // ...
|
|
143
|
+
// }
|
|
144
|
+
// }).catch((err) => {
|
|
145
|
+
// console.log('An error occurred while retrieving token. ', err);
|
|
146
|
+
// // ...
|
|
147
|
+
// });
|
|
148
|
+
|
|
149
|
+
// resetUI()
|
|
150
|
+
|
|
151
|
+
// } else {
|
|
152
|
+
// this.logger.error('Unable to get permission to notify.');
|
|
153
|
+
// }
|
|
154
|
+
// })
|
|
155
|
+
|
|
156
|
+
// }
|
|
157
|
+
// }
|
|
158
|
+
|
|
159
|
+
// sendTokenToServer(currentToken) {
|
|
160
|
+
// if (!this.isTokenSentToServer()) {
|
|
161
|
+
// console.log('Sending token to server...');
|
|
162
|
+
// // TODO(developer): Send the current token to your server.
|
|
163
|
+
// this.setTokenSentToServer(true);
|
|
164
|
+
// } else {
|
|
165
|
+
// console.log('Token already sent to server so won\'t send it again ' +
|
|
166
|
+
// 'unless it changes');
|
|
167
|
+
// }
|
|
168
|
+
// }
|
|
169
|
+
|
|
170
|
+
// isTokenSentToServer() {
|
|
171
|
+
// return window.localStorage.getItem('sentToServer') === '1';
|
|
172
|
+
// }
|
|
173
|
+
|
|
174
|
+
// setTokenSentToServer(sent) {
|
|
175
|
+
// window.localStorage.setItem('sentToServer', sent ? '1' : '0');
|
|
176
|
+
// }
|
|
177
|
+
|
|
97
178
|
removeNotificationsInstance(callback: (string) => void) {
|
|
98
179
|
var self = this;
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
const connectionsRefinstancesId = urlNodeFirebase + '/users/' + this.userId + '/instances/'
|
|
113
|
-
this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> connectionsRefinstancesId ', connectionsRefinstancesId);
|
|
180
|
+
// firebase.auth().onAuthStateChanged(function (user) {
|
|
181
|
+
// if (user) {
|
|
182
|
+
// self.logger.debug('[FIREBASE-NOTIFICATIONS] - FB User is signed in. ', user)
|
|
183
|
+
// self.logger.log('[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > this.userId', self.userId);
|
|
184
|
+
// self.logger.log('[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > FCMcurrentToken', self.FCMcurrentToken);
|
|
185
|
+
// // this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > this.tenant', this.tenant);
|
|
186
|
+
// } else {
|
|
187
|
+
// self.logger.debug('[FIREBASE-NOTIFICATIONS] - No FB user is signed in. ', user)
|
|
188
|
+
// }
|
|
189
|
+
// });
|
|
190
|
+
const urlNodeFirebase = '/apps/' + self.tenant
|
|
191
|
+
const connectionsRefinstancesId = urlNodeFirebase + '/users/' + self.userId + '/instances/'
|
|
192
|
+
self.logger.log('[FIREBASE-NOTIFICATIONS] >>>> connectionsRefinstancesId ', connectionsRefinstancesId);
|
|
114
193
|
let connectionsRefURL = '';
|
|
115
194
|
if (connectionsRefinstancesId) {
|
|
116
|
-
connectionsRefURL = connectionsRefinstancesId +
|
|
117
|
-
const connectionsRef =
|
|
118
|
-
|
|
119
|
-
|
|
195
|
+
connectionsRefURL = connectionsRefinstancesId + self.FCMcurrentToken;
|
|
196
|
+
const connectionsRef = firebase.database().ref().child(connectionsRefURL);
|
|
197
|
+
self.logger.log('[FIREBASE-NOTIFICATIONS] >>>> connectionsRef ', connectionsRef);
|
|
198
|
+
self.logger.log('[FIREBASE-NOTIFICATIONS] >>>> connectionsRef url ', connectionsRefURL);
|
|
120
199
|
connectionsRef.off()
|
|
121
200
|
connectionsRef.remove()
|
|
122
201
|
.then(() => {
|
|
123
|
-
|
|
202
|
+
self.logger.log("[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance > Remove succeeded.")
|
|
124
203
|
callback('success')
|
|
125
204
|
}).catch((error) => {
|
|
126
|
-
|
|
205
|
+
self.logger.error("[FIREBASE-NOTIFICATIONS] >>>> removeNotificationsInstance Remove failed: " + error.message)
|
|
127
206
|
callback('error')
|
|
128
207
|
}).finally(() => {
|
|
129
|
-
|
|
208
|
+
self.logger.log('[FIREBASE-NOTIFICATIONS] COMPLETED');
|
|
130
209
|
})
|
|
131
210
|
}
|
|
211
|
+
|
|
132
212
|
}
|
|
133
213
|
|
|
214
|
+
// removeNotificationsInstance() {
|
|
215
|
+
// let promise = new Promise((resolve, reject) => {
|
|
216
|
+
// this.appStoreService.getInstallation(this.projectId).then((res) => {
|
|
217
|
+
// console.log("Get Installation Response: ", res);
|
|
218
|
+
// resolve(res);
|
|
219
|
+
// }).catch((err) => {
|
|
220
|
+
// console.error("Error getting installation: ", err);
|
|
221
|
+
// reject(err);
|
|
222
|
+
// })
|
|
223
|
+
// })
|
|
224
|
+
// return promise;
|
|
225
|
+
// }
|
|
226
|
+
|
|
134
227
|
|
|
135
228
|
// ********** PRIVATE METHOD - START ****************//
|
|
136
229
|
private updateToken(FCMcurrentToken, currentUserUid) {
|
|
@@ -149,14 +242,14 @@ export class FirebaseNotifications extends NotificationsService {
|
|
|
149
242
|
const device_model = {
|
|
150
243
|
device_model: navigator.userAgent,
|
|
151
244
|
language: navigator.language,
|
|
152
|
-
platform:
|
|
245
|
+
platform: this.platform,
|
|
153
246
|
platform_version: this.BUILD_VERSION
|
|
154
247
|
}
|
|
155
248
|
|
|
156
249
|
updates[connectionsRefinstancesId + connection] = device_model;
|
|
157
250
|
|
|
158
251
|
this.logger.log('[FIREBASE-NOTIFICATIONS] >>>> getPermission > updateToken in DB', updates);
|
|
159
|
-
|
|
252
|
+
firebase.database().ref().update(updates)
|
|
160
253
|
}
|
|
161
254
|
// ********** PRIVATE METHOD - END ****************//
|
|
162
255
|
|
|
@@ -102,6 +102,7 @@ export class MQTTConversationHandler extends ConversationHandlerService {
|
|
|
102
102
|
this.chat21Service.chatClient.lastMessages(this.conversationWith, (err, messages) => {
|
|
103
103
|
if (!err) {
|
|
104
104
|
this.logger.log('[MQTTConversationHandlerSERVICE] message lastMessages:', messages);
|
|
105
|
+
messages.sort(compareValues('timestamp', 'asc'));
|
|
105
106
|
messages.forEach(message => {
|
|
106
107
|
// this.addedMessage(msg);
|
|
107
108
|
const msg: MessageModel = message;
|
|
@@ -1,49 +1,48 @@
|
|
|
1
|
-
|
|
2
1
|
import { Injectable } from '@angular/core';
|
|
3
2
|
// services
|
|
4
3
|
import { NotificationsService } from '../abstract/notifications.service';
|
|
5
4
|
import { LoggerInstance } from '../logger/loggerInstance';
|
|
6
5
|
import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
|
|
7
|
-
|
|
8
6
|
// firebase
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
import firebase from "firebase/app";
|
|
8
|
+
import 'firebase/messaging';
|
|
9
|
+
import 'firebase/auth';
|
|
11
10
|
// chat21
|
|
12
11
|
import { Chat21Service } from './chat-service';
|
|
13
12
|
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
@Injectable({
|
|
14
|
+
providedIn: 'root'
|
|
15
|
+
})
|
|
16
16
|
export class MQTTNotifications extends NotificationsService {
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
// public BUILD_VERSION: string;
|
|
19
19
|
private FCMcurrentToken: string;
|
|
20
20
|
private userId: string;
|
|
21
21
|
private tenant: string;
|
|
22
22
|
private vapidkey: string;
|
|
23
|
-
private
|
|
24
|
-
|
|
23
|
+
private platform: string;
|
|
25
24
|
private logger: LoggerService = LoggerInstance.getInstance();
|
|
26
25
|
|
|
27
26
|
constructor(
|
|
28
|
-
public chat21Service: Chat21Service
|
|
27
|
+
public chat21Service: Chat21Service,
|
|
29
28
|
) {
|
|
30
29
|
super();
|
|
31
30
|
}
|
|
32
31
|
|
|
33
|
-
|
|
32
|
+
initialize(tenant: string, vapId: string, platform: string): void {
|
|
34
33
|
this.tenant = tenant;
|
|
35
34
|
this.vapidkey = vapId;
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
this.firebase = firebase
|
|
39
|
-
|
|
35
|
+
platform === 'desktop'? this.platform = 'ionic' : this.platform = platform
|
|
36
|
+
this.logger.log('[MQTTNotificationService] initialize - tenant ', this.tenant, this.platform)
|
|
40
37
|
return;
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
getNotificationPermissionAndSaveToken(currentUserUid) {
|
|
41
|
+
console.log("[MQTTNotificationService] getNotificationPermissionAndSaveToken()",currentUserUid);
|
|
44
42
|
this.userId = currentUserUid;
|
|
45
|
-
if (
|
|
46
|
-
|
|
43
|
+
if (firebase.messaging.isSupported()) {
|
|
44
|
+
console.log("[MQTTNotificationService] firebase.messaging.isSupported -> YES");
|
|
45
|
+
const messaging = firebase.messaging();
|
|
47
46
|
// messaging.requestPermission()
|
|
48
47
|
Notification.requestPermission().then((permission) => {
|
|
49
48
|
if (permission === 'granted') {
|
|
@@ -61,6 +60,28 @@ export class MQTTNotifications extends NotificationsService {
|
|
|
61
60
|
});
|
|
62
61
|
} else {
|
|
63
62
|
this.logger.log('[MQTTNotificationService] >>>> FIREBASE MESSAGING IS NOT SUPPORTED')
|
|
63
|
+
|
|
64
|
+
// if(this.platform == 'android' || this.platform === 'ios'){
|
|
65
|
+
// this.logger.log('[MQTTNotificationService] >>>> FIREBASE MESSAGING: use FCM plugin')
|
|
66
|
+
// this.fcm.onTokenRefresh().subscribe(FCMtoken => {
|
|
67
|
+
// // Register your new token in your back-end if you want
|
|
68
|
+
// // backend.registerToken(token);
|
|
69
|
+
// this.FCMcurrentToken = FCMtoken;
|
|
70
|
+
// console.log("[MQTTNotificationService] FCM: onTokenRefresh --->", FCMtoken);
|
|
71
|
+
// this.saveToken(FCMtoken, currentUserUid)
|
|
72
|
+
// });
|
|
73
|
+
// this.fcm.requestPushPermission().then((permission) => {
|
|
74
|
+
// console.log("[MQTTNotificationService] FCM: requestPushPermission --->", permission);
|
|
75
|
+
// if(permission === true){
|
|
76
|
+
// this.fcm.getToken().then(FCMtoken => {
|
|
77
|
+
// console.log("[MQTTNotificationService] FCM: getToken --->", FCMtoken);
|
|
78
|
+
// this.FCMcurrentToken = FCMtoken;
|
|
79
|
+
// this.saveToken(FCMtoken, currentUserUid)
|
|
80
|
+
// });
|
|
81
|
+
// }
|
|
82
|
+
// });
|
|
83
|
+
|
|
84
|
+
// }
|
|
64
85
|
}
|
|
65
86
|
}
|
|
66
87
|
|
|
@@ -83,7 +104,7 @@ export class MQTTNotifications extends NotificationsService {
|
|
|
83
104
|
let connectionsRefURL = '';
|
|
84
105
|
if (connectionsRefinstancesId) {
|
|
85
106
|
connectionsRefURL = connectionsRefinstancesId + self.FCMcurrentToken;
|
|
86
|
-
const connectionsRef =
|
|
107
|
+
const connectionsRef = firebase.database().ref().child(connectionsRefURL);
|
|
87
108
|
self.logger.log('[MQTTNotificationService] >>>> connectionsRef ', connectionsRef);
|
|
88
109
|
self.logger.log('[MQTTNotificationService] >>>> connectionsRef url ', connectionsRefURL);
|
|
89
110
|
connectionsRef.off()
|
|
@@ -107,7 +128,7 @@ export class MQTTNotifications extends NotificationsService {
|
|
|
107
128
|
const device_model = {
|
|
108
129
|
device_model: navigator.userAgent,
|
|
109
130
|
language: navigator.language,
|
|
110
|
-
platform:
|
|
131
|
+
platform: this.platform,
|
|
111
132
|
platform_version: this.BUILD_VERSION
|
|
112
133
|
}
|
|
113
134
|
this.chat21Service.chatClient.saveInstance(FCMcurrentToken,device_model,(err, response) => {
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { TestBed } from '@angular/core/testing';
|
|
2
|
+
|
|
3
|
+
import { ScriptService } from './script.service';
|
|
4
|
+
|
|
5
|
+
describe('ScriptService', () => {
|
|
6
|
+
beforeEach(() => TestBed.configureTestingModule({}));
|
|
7
|
+
|
|
8
|
+
it('should be created', () => {
|
|
9
|
+
const service: ScriptService = TestBed.get(ScriptService);
|
|
10
|
+
expect(service).toBeTruthy();
|
|
11
|
+
});
|
|
12
|
+
});
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { HttpClient } from '@angular/common/http';
|
|
2
|
+
import { Injectable } from '@angular/core';
|
|
3
|
+
import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
|
|
4
|
+
import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
|
|
5
|
+
|
|
6
|
+
@Injectable({
|
|
7
|
+
providedIn: 'root'
|
|
8
|
+
})
|
|
9
|
+
export class ScriptService {
|
|
10
|
+
|
|
11
|
+
private scriptList: Array<{name: string, loaded: boolean, src: string}> = []
|
|
12
|
+
private logger: LoggerService = LoggerInstance.getInstance();
|
|
13
|
+
|
|
14
|
+
constructor(
|
|
15
|
+
public http: HttpClient,
|
|
16
|
+
) { }
|
|
17
|
+
|
|
18
|
+
buildScriptArray(globalRemoteJSSrc: string){
|
|
19
|
+
this.logger.log('[SCRIPT-SERVICE] buildScriptArray globalRemoteJSSrc ', globalRemoteJSSrc);
|
|
20
|
+
if(!this.isEmpty(globalRemoteJSSrc)){
|
|
21
|
+
var scriptArray = globalRemoteJSSrc.split(",")
|
|
22
|
+
|
|
23
|
+
let count = 0;
|
|
24
|
+
scriptArray.forEach(element => {
|
|
25
|
+
count = count + 1;
|
|
26
|
+
this.scriptList.push({name: element.split('/').pop(), loaded: false, src: element})
|
|
27
|
+
});
|
|
28
|
+
this.logger.log('[SCRIPT-SERVICE] buildScriptArray ', this.scriptList);
|
|
29
|
+
this.load()
|
|
30
|
+
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
load() {
|
|
35
|
+
this.logger.log('[SCRIPT-SERV] load ...scripts ', this.scriptList)
|
|
36
|
+
var promises: any[] = [];
|
|
37
|
+
this.scriptList.forEach((script) => promises.push(this.loadScript(script)));
|
|
38
|
+
return Promise.all(promises).catch((err) => {
|
|
39
|
+
// log that I have an error, return the entire array;
|
|
40
|
+
this.logger.error('A promise failed to resolve', err);
|
|
41
|
+
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
loadScript(currentScript){
|
|
47
|
+
this.logger.log('[SCRIPT-SERVICE] load script:', currentScript);
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
//resolve if already loaded
|
|
50
|
+
if (currentScript.loaded) {
|
|
51
|
+
resolve({ script: currentScript.name, loaded: true, status: 'Already Loaded' });
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
//load script
|
|
55
|
+
let script = document.createElement('script')
|
|
56
|
+
script.type = 'text/javascript';
|
|
57
|
+
script.src = currentScript.src;
|
|
58
|
+
script.onload = () => {
|
|
59
|
+
currentScript.loaded = true;
|
|
60
|
+
resolve({ script: name, loaded: true, status: 'Loaded' });
|
|
61
|
+
}
|
|
62
|
+
script.onerror = (error: any) => resolve({ script: currentScript.name, loaded: false, status: 'Loaded' });
|
|
63
|
+
document.getElementsByTagName('head')[0].appendChild(script);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
isEmpty(url: string) {
|
|
69
|
+
return (url === undefined || url == null || url.length <= 0) ? true : false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -38,12 +38,20 @@ export const BCK_COLOR_CONVERSATION_UNSELECTED = '#FFFFFF ';
|
|
|
38
38
|
|
|
39
39
|
export const TYPE_SUPPORT_GROUP = 'support-group';
|
|
40
40
|
export const CHANNEL_TYPE_GROUP = 'group';
|
|
41
|
+
export const CHANNEL_TYPE_CHAT21 = 'chat21';
|
|
42
|
+
export const CHANNEL_TYPE_EMAIL = 'email';
|
|
43
|
+
export const CHANNEL_TYPE_FORM = 'form';
|
|
44
|
+
export const CHANNEL_TYPE_MESSANGER = 'messanger';
|
|
45
|
+
export const CHANNEL_TYPE_WHATSAPP = 'whatsapp';
|
|
46
|
+
export const CHANNEL_TYPE_TELEGRAM = 'telegram';
|
|
41
47
|
|
|
42
48
|
// TYPES MESSAGES
|
|
43
49
|
export const TYPE_MSG_TEXT = 'text';
|
|
44
50
|
export const TYPE_MSG_IMAGE = 'image';
|
|
45
51
|
export const TYPE_MSG_FILE = 'file';
|
|
46
52
|
export const TYPE_MSG_BUTTON = 'button';
|
|
53
|
+
export const TYPE_MSG_EMAIL = 'email';
|
|
54
|
+
export const TYPE_MSG_FORM = 'form';
|
|
47
55
|
|
|
48
56
|
export const MAX_WIDTH_IMAGES = 230;
|
|
49
57
|
export const MIN_WIDTH_IMAGES = 130;
|