surveysparrow-ionic-plugin 1.0.7-beta.4 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/dist/angular-ui/esm2022/angular-ui.mjs +5 -0
  2. package/dist/angular-ui/esm2022/public-api.mjs +3 -0
  3. package/dist/angular-ui/esm2022/spotcheck.component.mjs +17 -0
  4. package/dist/angular-ui/esm2022/spotchecks/SpotCheck.mjs +51 -0
  5. package/dist/angular-ui/esm2022/spotchecks/SpotCheckComponent.mjs +323 -0
  6. package/dist/angular-ui/esm2022/spotchecks/SpotcheckStateService.mjs +65 -0
  7. package/dist/angular-ui/esm2022/spotchecks/api.mjs +230 -0
  8. package/dist/angular-ui/esm2022/spotchecks/helpers.mjs +328 -0
  9. package/dist/angular-ui/esm2022/spotchecks/index.mjs +2 -0
  10. package/dist/angular-ui/esm2022/spotchecks/storage.mjs +7 -0
  11. package/dist/angular-ui/esm2022/spotchecks/types.mjs +2 -0
  12. package/dist/angular-ui/fesm2022/angular-ui.mjs +1013 -0
  13. package/dist/angular-ui/fesm2022/angular-ui.mjs.map +1 -0
  14. package/dist/angular-ui/index.d.ts +5 -0
  15. package/dist/angular-ui/public-api.d.ts +2 -0
  16. package/dist/angular-ui/spotcheck.component.d.ts +5 -0
  17. package/dist/angular-ui/spotchecks/SpotCheckComponent.d.ts +56 -0
  18. package/dist/angular-ui/spotchecks/SpotcheckStateService.d.ts +12 -0
  19. package/dist/{esm → angular-ui}/spotchecks/helpers.d.ts +1 -4
  20. package/dist/angular-ui/spotchecks/index.d.ts +2 -0
  21. package/dist/angular-ui/spotchecks/storage.d.ts +2 -0
  22. package/dist/{esm → angular-ui}/spotchecks/types.d.ts +5 -4
  23. package/dist/esm/angular-ui/lib/public-api.d.ts +2 -0
  24. package/dist/esm/angular-ui/lib/public-api.js +3 -0
  25. package/dist/esm/angular-ui/lib/public-api.js.map +1 -0
  26. package/dist/esm/angular-ui/lib/spotcheck.component.d.ts +2 -0
  27. package/dist/esm/angular-ui/lib/spotcheck.component.js +20 -0
  28. package/dist/esm/angular-ui/lib/spotcheck.component.js.map +1 -0
  29. package/dist/esm/angular-ui/lib/spotchecks/SpotCheck.d.ts +4 -0
  30. package/dist/esm/{spotchecks → angular-ui/lib/spotchecks}/SpotCheck.js +1 -3
  31. package/dist/esm/angular-ui/lib/spotchecks/SpotCheck.js.map +1 -0
  32. package/dist/esm/{spotchecks → angular-ui/lib/spotchecks}/SpotCheckComponent.d.ts +1 -0
  33. package/dist/esm/{spotchecks → angular-ui/lib/spotchecks}/SpotCheckComponent.js +13 -7
  34. package/dist/esm/angular-ui/lib/spotchecks/SpotCheckComponent.js.map +1 -0
  35. package/dist/esm/{spotchecks → angular-ui/lib/spotchecks}/SpotcheckStateService.js +1 -0
  36. package/dist/esm/angular-ui/lib/spotchecks/SpotcheckStateService.js.map +1 -0
  37. package/dist/esm/angular-ui/lib/spotchecks/api.d.ts +15 -0
  38. package/dist/esm/{spotchecks → angular-ui/lib/spotchecks}/api.js +20 -29
  39. package/dist/esm/angular-ui/lib/spotchecks/api.js.map +1 -0
  40. package/dist/esm/angular-ui/lib/spotchecks/helpers.d.ts +29 -0
  41. package/dist/esm/{spotchecks → angular-ui/lib/spotchecks}/helpers.js +6 -19
  42. package/dist/esm/angular-ui/lib/spotchecks/helpers.js.map +1 -0
  43. package/dist/esm/angular-ui/lib/spotchecks/index.d.ts +2 -0
  44. package/dist/esm/angular-ui/lib/spotchecks/index.js +2 -0
  45. package/dist/esm/angular-ui/lib/spotchecks/index.js.map +1 -0
  46. package/dist/esm/angular-ui/lib/spotchecks/storage.js.map +1 -0
  47. package/dist/esm/angular-ui/lib/spotchecks/types.d.ts +78 -0
  48. package/dist/esm/angular-ui/lib/spotchecks/types.js.map +1 -0
  49. package/dist/esm/index.d.ts +1 -1
  50. package/dist/esm/index.js +1 -1
  51. package/dist/esm/index.js.map +1 -1
  52. package/dist/plugin.cjs.js +51510 -527
  53. package/dist/plugin.cjs.js.map +1 -1
  54. package/dist/plugin.js +51511 -524
  55. package/dist/plugin.js.map +1 -1
  56. package/package.json +31 -4
  57. package/src/angular-ui/lib/public-api.ts +2 -0
  58. package/src/angular-ui/lib/spotcheck.component.ts +10 -0
  59. package/src/angular-ui/lib/spotchecks/SpotCheck.ts +54 -0
  60. package/src/angular-ui/lib/spotchecks/SpotCheckComponent.css +7 -0
  61. package/src/angular-ui/lib/spotchecks/SpotCheckComponent.html +27 -0
  62. package/src/angular-ui/lib/spotchecks/SpotCheckComponent.ts +295 -0
  63. package/src/angular-ui/lib/spotchecks/SpotcheckStateService.ts +64 -0
  64. package/src/angular-ui/lib/spotchecks/api.ts +286 -0
  65. package/src/angular-ui/lib/spotchecks/helpers.ts +401 -0
  66. package/src/angular-ui/lib/spotchecks/index.ts +9 -0
  67. package/src/angular-ui/lib/spotchecks/storage.ts +7 -0
  68. package/src/angular-ui/lib/spotchecks/types.ts +84 -0
  69. package/src/angular-ui/ng-package.json +13 -0
  70. package/src/angular-ui/package.json +10 -0
  71. package/src/definitions.ts +17 -0
  72. package/src/index.ts +10 -0
  73. package/dist/esm/spotchecks/SpotCheck.js.map +0 -1
  74. package/dist/esm/spotchecks/SpotCheckComponent.js.map +0 -1
  75. package/dist/esm/spotchecks/SpotCheckService.d.ts +0 -8
  76. package/dist/esm/spotchecks/SpotCheckService.js +0 -45
  77. package/dist/esm/spotchecks/SpotCheckService.js.map +0 -1
  78. package/dist/esm/spotchecks/SpotcheckStateService.js.map +0 -1
  79. package/dist/esm/spotchecks/SpotchecksListener.d.ts +0 -9
  80. package/dist/esm/spotchecks/SpotchecksListener.js +0 -37
  81. package/dist/esm/spotchecks/SpotchecksListener.js.map +0 -1
  82. package/dist/esm/spotchecks/api.js.map +0 -1
  83. package/dist/esm/spotchecks/helpers.js.map +0 -1
  84. package/dist/esm/spotchecks/index.d.ts +0 -5
  85. package/dist/esm/spotchecks/index.js +0 -6
  86. package/dist/esm/spotchecks/index.js.map +0 -1
  87. package/dist/esm/spotchecks/storage.js.map +0 -1
  88. package/dist/esm/spotchecks/types.js.map +0 -1
  89. /package/dist/{esm → angular-ui}/spotchecks/SpotCheck.d.ts +0 -0
  90. /package/dist/{esm → angular-ui}/spotchecks/api.d.ts +0 -0
  91. /package/dist/esm/{spotchecks → angular-ui/lib/spotchecks}/SpotcheckStateService.d.ts +0 -0
  92. /package/dist/esm/{spotchecks → angular-ui/lib/spotchecks}/storage.d.ts +0 -0
  93. /package/dist/esm/{spotchecks → angular-ui/lib/spotchecks}/storage.js +0 -0
  94. /package/dist/esm/{spotchecks → angular-ui/lib/spotchecks}/types.js +0 -0
package/package.json CHANGED
@@ -1,7 +1,8 @@
1
1
  {
2
2
  "name": "surveysparrow-ionic-plugin",
3
- "version": "1.0.7-beta.4",
3
+ "version": "2.0.0",
4
4
  "description": "SurveySparrow SDK enables you to collect feedback from your mobile app. Embed the Classic, Chat & NPS surveys in your ionic application seamlessly with few lines of code.",
5
+ "type": "module",
5
6
  "main": "dist/plugin.cjs.js",
6
7
  "module": "dist/esm/index.js",
7
8
  "types": "dist/esm/index.d.ts",
@@ -13,8 +14,25 @@
13
14
  "ios/Sources",
14
15
  "ios/Tests",
15
16
  "Package.swift",
16
- "SurveysparrowIonicPlugin.podspec"
17
+ "SurveysparrowIonicPlugin.podspec",
18
+ "dist/capacitor",
19
+ "dist/angular-ui",
20
+ "capacitor",
21
+ "src"
17
22
  ],
23
+ "exports": {
24
+ ".": {
25
+ "import": "./dist/esm/index.js",
26
+ "types": "./dist/esm/index.d.ts"
27
+ },
28
+ "./angular-ui": {
29
+ "import": "./dist/angular-ui/fesm2022/angular-ui.mjs",
30
+ "types": "./dist/angular-ui/index.d.ts",
31
+ "esm2022": "./dist/angular-ui/esm2022/angular-ui.mjs",
32
+ "esm": "./dist/angular-ui/esm2022/angular-ui.mjs",
33
+ "default": "./dist/angular-ui/fesm2022/angular-ui.mjs"
34
+ }
35
+ },
18
36
  "author": "Gokulkrishna-Raju",
19
37
  "license": "MIT",
20
38
  "repository": {
@@ -27,7 +45,9 @@
27
45
  "keywords": [
28
46
  "capacitor",
29
47
  "plugin",
30
- "native"
48
+ "native",
49
+ "ionic",
50
+ "angular"
31
51
  ],
32
52
  "scripts": {
33
53
  "verify": "npm run verify:ios && npm run verify:android && npm run verify:web",
@@ -40,13 +60,15 @@
40
60
  "prettier": "prettier \"**/*.{css,html,ts,js,java}\" --plugin=prettier-plugin-java",
41
61
  "swiftlint": "node-swiftlint",
42
62
  "docgen": "docgen --api SurveySparrowIonicPluginPlugin --output-readme README.md --output-json dist/docs.json",
43
- "build": "npm run clean && npm run docgen && tsc && rollup -c rollup.config.mjs",
63
+ "build": "npm run clean && npm run docgen && npx ng-packagr -p src/angular-ui/ng-package.json && tsc && rollup -c rollup.config.mjs",
44
64
  "clean": "rimraf ./dist",
45
65
  "watch": "tsc --watch",
46
66
  "prepublishOnly": "npm run build"
47
67
  },
48
68
  "devDependencies": {
49
69
  "@angular/common": "^20.3.2",
70
+ "@angular/compiler": "^20.3.2",
71
+ "@angular/compiler-cli": "^20.3.2",
50
72
  "@angular/core": "^20.3.2",
51
73
  "@angular/platform-browser": "^20.3.2",
52
74
  "@capacitor/android": "^7.0.0",
@@ -61,6 +83,7 @@
61
83
  "@rollup/plugin-node-resolve": "^16.0.1",
62
84
  "axios": "^1.12.2",
63
85
  "eslint": "^8.57.0",
86
+ "ng-packagr": "^18.2.1",
64
87
  "prettier": "^3.4.2",
65
88
  "prettier-plugin-java": "^2.6.6",
66
89
  "rimraf": "^6.0.1",
@@ -87,6 +110,10 @@
87
110
  }
88
111
  },
89
112
  "dependencies": {
113
+ "@capacitor/device": "^7.0.2",
114
+ "axios": "^1.12.2",
115
+ "tslib": "^2.3.0",
116
+ "uuid": "^13.0.0",
90
117
  "@types/node": "^24.5.2"
91
118
  }
92
119
  }
@@ -0,0 +1,2 @@
1
+ export * from './spotcheck.component';
2
+ export * from './spotchecks';
@@ -0,0 +1,10 @@
1
+ import { Component } from '@angular/core';
2
+ import { SpotCheckComponent } from './spotchecks/SpotCheckComponent';
3
+
4
+ @Component({
5
+ selector: 'SpotCheck',
6
+ template: `<SpotCheckComponent />`,
7
+ standalone: true,
8
+ imports: [SpotCheckComponent],
9
+ })
10
+ export class SpotCheck {}
@@ -0,0 +1,54 @@
1
+ import { InitializeSpotChecksProps, TrackEventProps, TrackScreenProps } from './types';
2
+ import { sendTrackScreenRequest, sendTrackEventRequest } from './api';
3
+ import { getSpotcheckStateService } from './helpers';
4
+
5
+ export const initializeSpotChecks = ({
6
+ domainName,
7
+ targetToken,
8
+ userDetails = {},
9
+ variables = {},
10
+ customProperties = {},
11
+ }: InitializeSpotChecksProps) => {
12
+ const spotcheckStateService = getSpotcheckStateService();
13
+ spotcheckStateService.setState({
14
+ domainName,
15
+ targetToken,
16
+ userDetails,
17
+ variables,
18
+ customProperties,
19
+ });
20
+ };
21
+
22
+ export const trackScreen = async ({ screen, options }: TrackScreenProps) => {
23
+ try {
24
+ const response = await sendTrackScreenRequest({ screen, options });
25
+ if (response.valid) {
26
+ console.log('Screen Tracking succeeded.');
27
+ } else {
28
+ if ('error' in response) {
29
+ throw new Error(response.error.toString());
30
+ } else {
31
+ throw new Error('Tracking failed without an explicit error.');
32
+ }
33
+ }
34
+ } catch (error: any) {
35
+ console.log(`Screen Tracking Failed. ${error.message}`);
36
+ }
37
+ };
38
+
39
+ export const trackEvent = async ({ screen, event }: TrackEventProps) => {
40
+ try {
41
+ const response = await sendTrackEventRequest({ screen, event });
42
+ if (response.valid) {
43
+ console.log('TrackEvent succeeded.');
44
+ } else {
45
+ if ('error' in response) {
46
+ throw new Error(response.error.toString());
47
+ } else {
48
+ throw new Error('Tracking failed without an explicit error.');
49
+ }
50
+ }
51
+ } catch (error: any) {
52
+ console.log(`Event Tracking Failed. ${error.message}`);
53
+ }
54
+ };
@@ -0,0 +1,7 @@
1
+ .safe-area {
2
+ padding-top: env(safe-area-inset-top);
3
+ padding-bottom: env(safe-area-inset-bottom);
4
+ padding-left: env(safe-area-inset-left);
5
+ padding-right: env(safe-area-inset-right);
6
+ box-sizing: border-box;
7
+ }
@@ -0,0 +1,27 @@
1
+ <div [ngStyle]="componentStyles.wrapperStyles" class="safe-area">
2
+ <div [ngStyle]="componentStyles.styles">
3
+ <div style="position: relative; height: 100%;">
4
+ <spotcheck-close-button />
5
+
6
+ <WebViewComponent
7
+ *ngIf="state.classicUrl && state.classicUrl.length > 0 && state.spotcheckURL.length > 0 && state.spotCheckType === 'classic'"
8
+ [url]="state.classicUrl"
9
+ [webviewType]="'classic'"
10
+ [isMiniCard]="state.spotChecksMode === 'miniCard'"
11
+ />
12
+
13
+ <WebViewComponent
14
+ *ngIf="state.chatUrl && state.chatUrl.length > 0 && state.spotcheckURL.length > 0 && state.spotCheckType === 'chat'"
15
+ [url]="state.chatUrl"
16
+ [webviewType]="'chat'"
17
+ [isMiniCard]="state.spotChecksMode === 'miniCard'"
18
+ />
19
+
20
+ <div *ngIf="state.spotChecksMode === 'miniCard' && state.avatarEnabled">
21
+ <div style="position: absolute; bottom: -66px; left: 16px; z-index: 100001;">
22
+ <img [src]="avatarUrl" style="width: 56px; height: 56px; border-radius: 50px; background-color: white;"/>
23
+ </div>
24
+ </div>
25
+ </div>
26
+ </div>
27
+ </div>
@@ -0,0 +1,295 @@
1
+ import {
2
+ OnInit,
3
+ Component,
4
+ Input,
5
+ OnDestroy,
6
+ ViewChild,
7
+ ElementRef,
8
+ AfterViewInit,
9
+ HostListener,
10
+ } from '@angular/core';
11
+ import { CommonModule } from '@angular/common';
12
+ import { Subscription } from 'rxjs';
13
+ import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
14
+ import { closeSpotCheck, closeSpotCheckAndHandleSurveyEnd, getSpotcheckComponentCssStyles, handleSurveyEnd, ischatSurvey } from './helpers';
15
+ import { SpotcheckState } from './types';
16
+ import { getSpotcheckStateService } from './helpers';
17
+ import { SpotcheckStateService } from './SpotcheckStateService';
18
+ import axios from 'axios';
19
+
20
+ @Component({
21
+ selector: 'WebViewComponent',
22
+ template: `
23
+ <div style="overflow: hidden; height: 100%; border-radius: {{isMiniCard ? 12 : 0}}px; padding-left: {{isMiniCard ? 12 : 0}}px; padding-right: {{isMiniCard ? 12 : 0}}px; box-sizing: border-box;">
24
+ <iframe
25
+ allow="camera; microphone; geolocation; display-capture; autoplay; clipboard-read; clipboard-write;"
26
+ #iframeRef
27
+ [src]="safeUrl"
28
+ style="width: 100%; height: 100%; display: block; border-radius: {{isMiniCard ? 12 : 0}}px;"
29
+ frameborder="0"
30
+ >
31
+ </iframe>
32
+ </div>
33
+ `,
34
+ standalone: true,
35
+ imports: [CommonModule],
36
+ })
37
+ export class WebViewComponent implements OnInit, AfterViewInit {
38
+ @Input() url: string = '';
39
+ @Input() webviewType: 'classic' | 'chat' = 'classic';
40
+ @Input() isMiniCard: boolean = false;
41
+
42
+ safeUrl: SafeResourceUrl | null = null;
43
+ @ViewChild('iframeRef') iframe!: ElementRef<HTMLIFrameElement>;
44
+
45
+ constructor(private sanitizer: DomSanitizer) {}
46
+ ngOnInit() {
47
+ if (this.url) {
48
+ this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
49
+ }
50
+ }
51
+
52
+ ngAfterViewInit() {
53
+ const stateService = getSpotcheckStateService();
54
+ const webViewRef = this.iframe.nativeElement;
55
+
56
+ if (this.webviewType === 'classic') {
57
+ stateService.setState({
58
+ classicWebViewRef: webViewRef,
59
+ isClassicLoading: false,
60
+ });
61
+ } else {
62
+ stateService.setState({
63
+ chatWebViewRef: webViewRef,
64
+ isChatLoading: false,
65
+ });
66
+ }
67
+ this.setupIframeLoadListener();
68
+ }
69
+
70
+ private setupIframeLoadListener() {
71
+ const iframe = this.iframe.nativeElement;
72
+ iframe.addEventListener('load', () => {
73
+ const stateService = getSpotcheckStateService();
74
+ if (this.webviewType === 'classic') {
75
+ stateService.setState({ isClassicLoading: false });
76
+ } else {
77
+ stateService.setState({ isChatLoading: false });
78
+ }
79
+ });
80
+ }
81
+
82
+ @HostListener('window:message', ['$event'])
83
+ onMessage(event: MessageEvent) {
84
+ const stateService = getSpotcheckStateService();
85
+ const { data } = event;
86
+ switch (data.type) {
87
+ case 'slideInFrame':
88
+ if (data.mounted) {
89
+ stateService.setState({ isMounted: true });
90
+ }
91
+ break;
92
+
93
+ case 'resizeWindow':
94
+ if (data.size) {
95
+ stateService.setState({
96
+ currentQuestionHeight: data.size.height,
97
+ });
98
+ } else if (data.isCloseButtonEnabled) {
99
+ stateService.setState({
100
+ isCloseButtonEnabled: data.isCloseButtonEnabled,
101
+ });
102
+ }
103
+ break;
104
+
105
+ case 'surveyCompleted':
106
+ closeSpotCheckAndHandleSurveyEnd();
107
+ // spotchecksListener.emitSurveyCompleted(data.response);
108
+ break;
109
+
110
+ case 'surveyLoadStarted':
111
+ // spotchecksListener.emitSurveyLoadStarted(data.surveyDetails);
112
+ break;
113
+
114
+ default:
115
+ break;
116
+ }
117
+ }
118
+ }
119
+
120
+ @Component({
121
+ selector: 'close-svg',
122
+ template: `
123
+ <svg
124
+ [attr.width]="size"
125
+ [attr.height]="size"
126
+ viewBox="0 0 32 32"
127
+ fill="none"
128
+ xmlns="https://www.w3.org/2000/svg"
129
+ >
130
+ <path
131
+ d="M10.6665 10.667L21.3332 21.3337M21.3332 10.667L10.6665 21.3337"
132
+ [attr.stroke]="stroke"
133
+ [attr.stroke-width]="strokeWidth"
134
+ stroke-linecap="round"
135
+ stroke-linejoin="round"
136
+ />
137
+ </svg>
138
+ `,
139
+ standalone: true,
140
+ imports: [CommonModule],
141
+ })
142
+ export class CloseSVGComponent {
143
+ @Input() size: number = 32;
144
+ @Input() stroke: string = '#919191';
145
+ @Input() strokeWidth: number = 1.5;
146
+ }
147
+
148
+ @Component({
149
+ selector: 'spotcheck-close-button',
150
+ template: `
151
+ <div style="position: absolute; top: -36px; right: 16px; z-index: 100001; cursor: pointer; background-color: white; border-radius: 50px;" (click)="onClick()" *ngIf="isVisible && isMiniCard">
152
+ <close-svg [size]="size" [stroke]="stroke" [strokeWidth]="strokeWidth" style="display: flex; align-items: center; justify-content: center;"/>
153
+ </div>
154
+ <div style="position: absolute; top: 16px; right: 16px; z-index: 100001; cursor: pointer;" (click)="onClick()" *ngIf="isVisible && !isMiniCard">
155
+ <close-svg [size]="size" [stroke]="stroke" [strokeWidth]="strokeWidth"/>
156
+ </div>
157
+ `,
158
+ standalone: true,
159
+ imports: [CommonModule, CloseSVGComponent],
160
+ })
161
+ export class CloseButtonComponent implements OnDestroy {
162
+ @Input() size: number = 30;
163
+ @Input() strokeWidth: number = 1.2;
164
+
165
+ state: SpotcheckState;
166
+ private stateService: SpotcheckStateService;
167
+ private stateSubscription!: Subscription;
168
+
169
+ isVisible: boolean = false;
170
+ isMiniCard: boolean = false;
171
+ stroke: string = 'black';
172
+
173
+ constructor() {
174
+ this.stateService = getSpotcheckStateService();
175
+ this.state = this.stateService.getState();
176
+ this.updateComponentState();
177
+
178
+ this.stateSubscription = this.stateService.state$.subscribe(
179
+ (newState: SpotcheckState) => {
180
+ this.state = newState;
181
+ this.updateComponentState();
182
+ }
183
+ );
184
+ }
185
+
186
+ ngOnDestroy(): void {
187
+ if (this.stateSubscription) {
188
+ this.stateSubscription.unsubscribe();
189
+ }
190
+ }
191
+
192
+ private updateComponentState(): void {
193
+ this.isVisible =
194
+ this.state.isCloseButtonEnabled &&
195
+ ((this.state.currentQuestionHeight > 0 && !this.state.isFullScreenMode) ||
196
+ (this.state.isFullScreenMode &&
197
+ ((!this.state.isClassicLoading &&
198
+ this.state.spotCheckType === 'classic') ||
199
+ (!this.state.isChatLoading &&
200
+ this.state.spotCheckType === 'chat'))));
201
+ this.isMiniCard = this.state.spotChecksMode === 'miniCard';
202
+ this.stroke = this.isMiniCard ? 'black' : this.state.closeButtonStyle?.['ctaButton'] || 'black';
203
+ }
204
+
205
+ onClick = async () => {
206
+ await closeSpotCheck();
207
+ handleSurveyEnd();
208
+ };
209
+ }
210
+
211
+
212
+ @Component({
213
+ selector: 'SpotCheckComponent',
214
+ templateUrl: './SpotCheckComponent.html',
215
+ styleUrls: ['./SpotCheckComponent.css'],
216
+ standalone: true,
217
+ imports: [CommonModule, WebViewComponent, CloseButtonComponent],
218
+ })
219
+ export class SpotCheckComponent implements OnInit, OnDestroy {
220
+ state: SpotcheckState;
221
+ private spotcheckStateService: SpotcheckStateService;
222
+ private stateSubscription: Subscription;
223
+ componentStyles: any = {};
224
+ avatarUrl: string = '';
225
+
226
+ constructor() {
227
+ this.spotcheckStateService = getSpotcheckStateService();
228
+ this.state = this.spotcheckStateService.getState();
229
+ this.updateComponentStyles();
230
+
231
+ this.stateSubscription = this.spotcheckStateService.state$.subscribe(
232
+ (newState: SpotcheckState) => {
233
+ this.state = newState;
234
+ this.updateComponentStyles();
235
+ this.avatarUrl = this.state.avatarUrl || "https://static.surveysparrow.com/application/images/profile.png";
236
+ }
237
+ );
238
+ }
239
+
240
+ ngOnInit(): void {
241
+ this.initializeComponent();
242
+ }
243
+
244
+ ngOnDestroy(): void {
245
+ if (this.stateSubscription) {
246
+ this.stateSubscription.unsubscribe();
247
+ }
248
+ }
249
+
250
+ private updateComponentStyles(): void {
251
+ this.componentStyles = getSpotcheckComponentCssStyles(this.state);
252
+ }
253
+
254
+ initializeComponent = async () => {
255
+ try {
256
+ const domainName = this.state.domainName;
257
+ const targetToken = this.state.targetToken;
258
+ const response = await axios.get(
259
+ `https://${domainName}/api/internal/spotcheck/widget/${targetToken}/init`
260
+ );
261
+ const data = response.data;
262
+
263
+ if (data.filteredSpotChecks && data.filteredSpotChecks.length > 0) {
264
+ let classicIframe = false;
265
+ let chatIframe = false;
266
+
267
+ data.filteredSpotChecks.forEach((spotcheck: any) => {
268
+ if (
269
+ spotcheck.appearance.mode === 'fullScreen' &&
270
+ ischatSurvey(spotcheck?.survey?.surveyType)
271
+ ) {
272
+ chatIframe = true;
273
+ } else {
274
+ classicIframe = true;
275
+ }
276
+ });
277
+
278
+ const newClassicUrl = classicIframe
279
+ ? `https://${domainName}/eui-template/classic`
280
+ : '';
281
+ const newChatUrl = chatIframe
282
+ ? `https://${domainName}/eui-template/chat`
283
+ : '';
284
+
285
+ this.spotcheckStateService.setState({
286
+ filteredSpotChecks: data.filteredSpotChecks,
287
+ classicUrl: newClassicUrl,
288
+ chatUrl: newChatUrl,
289
+ });
290
+ }
291
+ } catch (error) {
292
+ console.log('Error initializing widget:', JSON.stringify(error));
293
+ }
294
+ };
295
+ }
@@ -0,0 +1,64 @@
1
+ import { Injectable } from '@angular/core';
2
+ import { BehaviorSubject } from 'rxjs';
3
+ import { SpotcheckState } from './types';
4
+
5
+ @Injectable({
6
+ providedIn: 'root',
7
+ })
8
+ export class SpotcheckStateService {
9
+ private initialState: SpotcheckState = {
10
+ isVisible: false,
11
+ spotcheckPosition: 'bottom',
12
+ spotcheckURL: '',
13
+ spotcheckID: 0,
14
+ spotcheckContactID: 0,
15
+ afterDelay: 0.0,
16
+ maxHeight: 0.5,
17
+ currentQuestionHeight: 0,
18
+ isFullScreenMode: false,
19
+ isBannerImageOn: false,
20
+ triggerToken: '',
21
+ closeButtonStyle: {},
22
+ isCloseButtonEnabled: false,
23
+ isSpotPassed: false,
24
+ isChecksPassed: false,
25
+ customEventsSpotChecks: [],
26
+ targetToken: '',
27
+ domainName: '',
28
+ userDetails: {},
29
+ variables: {},
30
+ customProperties: {},
31
+ traceId: '',
32
+ isClassicLoading: true,
33
+ isChatLoading: true,
34
+ classicUrl: '',
35
+ chatUrl: '',
36
+ classicWebViewRef: null,
37
+ chatWebViewRef: null,
38
+ filteredSpotChecks: [],
39
+ spotCheckType: '',
40
+ isMounted: false,
41
+ textPosition: 0,
42
+ screenHeight: 0,
43
+ keyBoardHeight: 0,
44
+ spotChecksMode: '',
45
+ avatarEnabled: false,
46
+ avatarUrl: '',
47
+ screenwiseUserDetails: {}
48
+ };
49
+
50
+ private spotcheckState = new BehaviorSubject<SpotcheckState>(this.initialState);
51
+ state$ = this.spotcheckState.asObservable();
52
+
53
+ setState(state: Partial<SpotcheckState>) {
54
+ this.spotcheckState.next({ ...this.spotcheckState.value, ...state });
55
+ }
56
+
57
+ clearState() {
58
+ this.spotcheckState.next(this.initialState);
59
+ }
60
+
61
+ getState() {
62
+ return this.spotcheckState.getValue();
63
+ }
64
+ }