@chat21/chat21-web-widget 5.0.59-rc.2 → 5.0.59-rc.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/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # chat21-web-widget ver 5.0
2
2
 
3
+ ### 5.0.59-rc.3
4
+ - bug-fixed: if mobileMarginX or MobileMarginY is set, widget do not fit on fullscreen once is opened
5
+
3
6
  ### 5.0.59-rc.2
4
7
  - added: handler for buttons in last-message component
5
8
  - changed: tooltip custom directive
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chat21/chat21-web-widget",
3
3
  "author": "Tiledesk SRL",
4
- "version": "5.0.59-rc.2",
4
+ "version": "5.0.59-rc.3",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.tiledesk.com",
7
7
  "repository": {
@@ -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
- ngOnInit(): void {
130
- this.logger.info('[APP-CONF]---------------- ngOnInit: APP.COMPONENT ---------------- ')
131
- this.initWidgetParamiters();
132
- }
131
+ ngOnInit(): void {
132
+ this.logger.info('[APP-CONF]---------------- ngOnInit: APP.COMPONENT ---------------- ')
133
+ this.initWidgetParamiters();
134
+ }
133
135
 
134
- ngAfterViewInit(): void {
135
- this.logger.info('[APP-CONF]---------------- ngAfterViewInit: APP.COMPONENT ---------------- ')
136
- this.ngZone.run(() => {
137
- const that = this;
138
- const subChangedConversation = this.conversationsHandlerService.conversationChanged.subscribe((conversation) => {
139
- // that.ngZone.run(() => {
140
- if (conversation) {
141
- this.onImageLoaded(conversation)
142
- this.onConversationLoaded(conversation)
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
- if(conversation.recipient === this.g.senderId && isUserBanned(conversation)){
145
- that.disposeWidget();
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
- if(conversation.is_new && conversation.sender !== this.g.senderId && !isInfo(conversation)){
150
- that.manageTabNotification();
151
- }
183
+
184
+ // });
185
+ });
186
+ this.subscriptions.push(subChangedConversation);
152
187
 
153
- if (that.g.isOpen === true) {
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
- this.logger.debug('[APP-COMP] obsChangeConversation ::: ', conversation);
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
- } else {
162
- // if(conversation.is_new && isJustRecived(this.g.startedAt.getTime(), conversation.timestamp)){
163
- //widget closed
164
- if(conversation.is_new && conversation.sender !== this.g.senderId && !isInfo(conversation)){
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
- that.triggerOnConversationUpdated(conversation);
177
- } else {
178
- this.logger.debug('[APP-COMP] oBSconversationChanged null: errorrr')
179
- return;
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
- if (conversation.is_new) {
196
- that.manageTabNotification()
197
- // this.soundMessage();
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
- if(this.g.isOpen === false){
200
- that.lastConversation = conversation;
201
- that.g.isOpenNewMessage = true;
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
- } else {
204
- //widget closed
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.subscriptions.push(subAddedConversation);
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
- const subAddedArchivedConversations = this.archivedConversationsService.archivedConversationAdded.subscribe((conversation) => {
220
- // that.ngZone.run(() => {
221
- if (conversation) {
222
- that.triggerOnConversationUpdated(conversation);
223
- this.onImageLoaded(conversation)
224
- this.onConversationLoaded(conversation)
225
- }
226
- // });
227
- });
228
- this.subscriptions.push(subAddedArchivedConversations);
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
- const subRemovedArchivedConversations = this.archivedConversationsService.archivedConversationRemoved.subscribe((conversation) => {
231
- // that.ngZone.run(() => {
232
- if (conversation) {
233
- this.isConversationArchived = false;
234
- that.triggerOnConversationUpdated(conversation);
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(subRemovedArchivedConversations);
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
- // SET AUDIO
293
- this.audio = new Audio();
294
- this.audio.src = this.g.baseLocation + URL_SOUND_LIST_CONVERSATION;
295
- this.audio.load();
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
- private initAll() {
299
- this.addComponentToWindow(this.ngZone);
302
+ private initAll() {
303
+ this.addComponentToWindow(this.ngZone);
300
304
 
301
- //INIT TRIGGER-HANDLER
302
- this.triggerHandler.setElement(this.el)
303
- this.triggerHandler.setWindowContext(this.g.windowContext)
305
+ //INIT TRIGGER-HANDLER
306
+ this.triggerHandler.setElement(this.el)
307
+ this.triggerHandler.setWindowContext(this.g.windowContext)
304
308
 
305
- // /** TRANSLATION LOADER: */
306
- // // this.translatorService.translate(this.g);
307
- // this.translatorService.initI18n().then((result) => {
308
- // this.g.wdLog(['»»»» APP-COMPONENT.TS initI18n result', result]);
309
- // this.translatorService.translate(this.g);
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
- /** SET ATTRIBUTES */
313
- const attributes = this.setAttributesFromStorageService();
314
- if (attributes) {
315
- this.g.attributes = attributes;
316
- }
317
- this.setStyleMap()
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
- * INIZIALIZE GLOBALS :
324
- * create settings object used in trigger
325
- * set isMobile
326
- * set attributes
327
- */
328
- this.g.initialize();
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
- this.removeFirebasewebsocketFromLocalStorage();
332
- // this.triggerLoadParamsEvent();
333
- // this.addComponentToWindow(this.ngZone); // forse dovrebbe stare prima di tutti i triggers
335
+ this.removeFirebasewebsocketFromLocalStorage();
336
+ // this.triggerLoadParamsEvent();
337
+ // this.addComponentToWindow(this.ngZone); // forse dovrebbe stare prima di tutti i triggers
334
338
 
335
- this.initLauncherButton();
336
- this.triggerLoadParamsEvent(); // first trigger
337
- //this.setAvailableAgentsStatus();
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() {
@@ -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 { TooltipDirective } from 'src/app/directives/tooltip.directive';
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
  })
@@ -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-->
@@ -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 {
@@ -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){
@@ -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
+ }