tas-uell-sdk 0.1.3 → 0.3.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.
- package/README.md +3 -0
- package/esm2020/lib/components/tas-btn/tas-btn.component.mjs +17 -15
- package/esm2020/lib/components/tas-feedback-modal/tas-feedback-modal.component.mjs +229 -0
- package/esm2020/lib/components/tas-floating-call/tas-floating-call.component.mjs +38 -3
- package/esm2020/lib/components/tas-incoming-appointment/tas-incoming-appointment.component.mjs +46 -8
- package/esm2020/lib/components/tas-videocall/tas-videocall.component.mjs +163 -43
- package/esm2020/lib/components/tas-waiting-room/tas-waiting-room.component.mjs +150 -34
- package/esm2020/lib/icons/tas-icons.mjs +17 -0
- package/esm2020/lib/interfaces/tas.interfaces.mjs +13 -1
- package/esm2020/lib/services/tas.service.mjs +127 -26
- package/esm2020/lib/tas-uell-sdk.module.mjs +8 -3
- package/esm2020/public-api.mjs +2 -1
- package/fesm2015/tas-uell-sdk.mjs +794 -124
- package/fesm2015/tas-uell-sdk.mjs.map +1 -1
- package/fesm2020/tas-uell-sdk.mjs +787 -123
- package/fesm2020/tas-uell-sdk.mjs.map +1 -1
- package/lib/components/tas-btn/tas-btn.component.d.ts +1 -0
- package/lib/components/tas-feedback-modal/tas-feedback-modal.component.d.ts +101 -0
- package/lib/components/tas-floating-call/tas-floating-call.component.d.ts +5 -0
- package/lib/components/tas-incoming-appointment/tas-incoming-appointment.component.d.ts +12 -1
- package/lib/components/tas-videocall/tas-videocall.component.d.ts +49 -6
- package/lib/components/tas-waiting-room/tas-waiting-room.component.d.ts +40 -12
- package/lib/icons/tas-icons.d.ts +8 -0
- package/lib/interfaces/tas.interfaces.d.ts +36 -3
- package/lib/services/tas.service.d.ts +27 -2
- package/lib/tas-uell-sdk.module.d.ts +5 -4
- package/package.json +1 -1
- package/public-api.d.ts +1 -0
- package/src/lib/styles/tas-global.scss +17 -0
|
@@ -47,6 +47,7 @@ export declare class TasButtonComponent implements OnInit, OnDestroy {
|
|
|
47
47
|
* Check status endpoint to determine if button should be enabled
|
|
48
48
|
*/
|
|
49
49
|
private checkStatus;
|
|
50
|
+
private handleStatusError;
|
|
50
51
|
onClick(): void;
|
|
51
52
|
private openWaitingRoomModal;
|
|
52
53
|
private openVideoCallModal;
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { OnInit, OnDestroy } from '@angular/core';
|
|
2
|
+
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
|
3
|
+
import { TasService } from '../../services/tas.service';
|
|
4
|
+
import { TasBusinessRole, FeedbackMotive } from '../../interfaces/tas.interfaces';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
export declare class TasFeedbackModalComponent implements OnInit, OnDestroy {
|
|
7
|
+
activeModal: NgbActiveModal;
|
|
8
|
+
private tasService;
|
|
9
|
+
videoCallId: number;
|
|
10
|
+
tenant: string;
|
|
11
|
+
businessRole: TasBusinessRole;
|
|
12
|
+
motives: FeedbackMotive[];
|
|
13
|
+
filteredMotives: FeedbackMotive[];
|
|
14
|
+
selectedMotive: FeedbackMotive | null;
|
|
15
|
+
rating: number;
|
|
16
|
+
hoverRating: number;
|
|
17
|
+
observation: string;
|
|
18
|
+
isSubmitting: boolean;
|
|
19
|
+
showToast: boolean;
|
|
20
|
+
isDropdownOpen: boolean;
|
|
21
|
+
private subscriptions;
|
|
22
|
+
private toastTimeout;
|
|
23
|
+
constructor(activeModal: NgbActiveModal, tasService: TasService);
|
|
24
|
+
ngOnInit(): void;
|
|
25
|
+
ngOnDestroy(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Check if current user can see all motives (BUSINESS + TECHNICAL)
|
|
28
|
+
* Only BACKOFFICE, ADMIN_MANAGER, MANAGER roles see BUSINESS motives
|
|
29
|
+
*/
|
|
30
|
+
get canSeeBusinessMotives(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Observation is required when "Otro problema tecnico" is selected
|
|
33
|
+
*/
|
|
34
|
+
get isObservationRequired(): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Can submit if rating > 0 OR motive is selected
|
|
37
|
+
* If observation is required, it must not be empty
|
|
38
|
+
*/
|
|
39
|
+
get canSubmit(): boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Progress percentage for the divider line
|
|
42
|
+
* 0 = nothing selected, 50 = one selected, 100 = both selected
|
|
43
|
+
*/
|
|
44
|
+
get feedbackProgress(): number;
|
|
45
|
+
/**
|
|
46
|
+
* Set star rating
|
|
47
|
+
*/
|
|
48
|
+
setRating(value: number): void;
|
|
49
|
+
/**
|
|
50
|
+
* Set hover preview rating
|
|
51
|
+
*/
|
|
52
|
+
setHoverRating(value: number): void;
|
|
53
|
+
/**
|
|
54
|
+
* Clear hover preview
|
|
55
|
+
*/
|
|
56
|
+
clearHoverRating(): void;
|
|
57
|
+
/**
|
|
58
|
+
* Get the display rating (hover preview or actual)
|
|
59
|
+
*/
|
|
60
|
+
getDisplayRating(): number;
|
|
61
|
+
/**
|
|
62
|
+
* Toggle dropdown open/close
|
|
63
|
+
*/
|
|
64
|
+
toggleDropdown(): void;
|
|
65
|
+
/**
|
|
66
|
+
* Close dropdown
|
|
67
|
+
*/
|
|
68
|
+
closeDropdown(): void;
|
|
69
|
+
/**
|
|
70
|
+
* Select a motive from dropdown
|
|
71
|
+
*/
|
|
72
|
+
selectMotive(motive: FeedbackMotive): void;
|
|
73
|
+
/**
|
|
74
|
+
* Clear selected motive
|
|
75
|
+
*/
|
|
76
|
+
clearMotive(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Submit feedback
|
|
79
|
+
*/
|
|
80
|
+
submit(): void;
|
|
81
|
+
/**
|
|
82
|
+
* Close modal without saving
|
|
83
|
+
*/
|
|
84
|
+
dismiss(): void;
|
|
85
|
+
/**
|
|
86
|
+
* Load motives from API
|
|
87
|
+
*/
|
|
88
|
+
private loadMotives;
|
|
89
|
+
/**
|
|
90
|
+
* Filter motives based on user role
|
|
91
|
+
* USERs see only TECHNICAL motives
|
|
92
|
+
* Owners (BACKOFFICE, ADMIN_MANAGER, MANAGER) see all motives
|
|
93
|
+
*/
|
|
94
|
+
private filterMotives;
|
|
95
|
+
/**
|
|
96
|
+
* Show toast notification and auto-dismiss after 3s
|
|
97
|
+
*/
|
|
98
|
+
private showToastNotification;
|
|
99
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<TasFeedbackModalComponent, never>;
|
|
100
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<TasFeedbackModalComponent, "tas-feedback-modal", never, { "videoCallId": "videoCallId"; "tenant": "tenant"; "businessRole": "businessRole"; }, {}, never, never>;
|
|
101
|
+
}
|
|
@@ -9,12 +9,17 @@ export declare class TasFloatingCallComponent implements OnInit, OnDestroy {
|
|
|
9
9
|
isMuted: boolean;
|
|
10
10
|
private subscriptions;
|
|
11
11
|
private videoCallModalRef;
|
|
12
|
+
private feedbackShown;
|
|
12
13
|
constructor(tasService: TasService, modalService: NgbModal);
|
|
13
14
|
ngOnInit(): void;
|
|
14
15
|
ngOnDestroy(): void;
|
|
15
16
|
onExpand(): void;
|
|
16
17
|
onHangUp(): void;
|
|
17
18
|
toggleMute(): void;
|
|
19
|
+
/**
|
|
20
|
+
* Open feedback modal when call ends from PiP mode
|
|
21
|
+
*/
|
|
22
|
+
private openFeedbackModal;
|
|
18
23
|
private setupSubscriptions;
|
|
19
24
|
private openVideoCallModal;
|
|
20
25
|
private readonly PIP_MARGIN;
|
|
@@ -15,16 +15,27 @@ export declare class TasIncomingAppointmentComponent implements OnInit, OnDestro
|
|
|
15
15
|
appointments: TasAppointment[];
|
|
16
16
|
isLoading: boolean;
|
|
17
17
|
hasError: boolean;
|
|
18
|
+
activeAppointmentId: number | null;
|
|
18
19
|
private subscriptions;
|
|
19
20
|
constructor(tasService: TasService);
|
|
20
21
|
ngOnInit(): void;
|
|
21
22
|
ngOnDestroy(): void;
|
|
22
23
|
private loadAppointments;
|
|
24
|
+
/**
|
|
25
|
+
* Check status endpoint to get the active appointmentId
|
|
26
|
+
*/
|
|
27
|
+
private checkStatus;
|
|
23
28
|
onEnterCall(appointment: TasAppointment): void;
|
|
24
29
|
/**
|
|
25
|
-
* Check if tas-btn should be shown for an appointment
|
|
30
|
+
* Check if tas-btn should be shown for an appointment.
|
|
31
|
+
* Only shows when appointment.id matches the activeAppointmentId from status API.
|
|
32
|
+
* tas-btn handles its own polling for joinable state.
|
|
26
33
|
*/
|
|
27
34
|
shouldShowTasBtn(appointment: TasAppointment): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* TrackBy function for ngFor
|
|
37
|
+
*/
|
|
38
|
+
trackByAppointmentId(index: number, appointment: TasAppointment): number;
|
|
28
39
|
/**
|
|
29
40
|
* Format date to Spanish format: "Lunes 8 de diciembre"
|
|
30
41
|
*/
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import { OnInit, OnDestroy, ElementRef, AfterViewInit } from '@angular/core';
|
|
2
|
-
import {
|
|
2
|
+
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
|
|
3
|
+
import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
|
3
4
|
import { TasService } from '../../services/tas.service';
|
|
4
5
|
import { GeolocationService } from '../../services/geolocation.service';
|
|
5
|
-
import { CallState, TasBusinessRole, WaitingRoomUser } from '../../interfaces/tas.interfaces';
|
|
6
|
+
import { CallState, TasBusinessRole, WaitingRoomUser, UserGeoInfo } from '../../interfaces/tas.interfaces';
|
|
6
7
|
import * as i0 from "@angular/core";
|
|
8
|
+
/** User geolocation panel view states */
|
|
9
|
+
export declare enum UserGeoViewState {
|
|
10
|
+
HIDDEN = "HIDDEN",
|
|
11
|
+
INITIAL = "INITIAL",
|
|
12
|
+
VERIFYING = "VERIFYING",
|
|
13
|
+
VERIFIED = "VERIFIED",
|
|
14
|
+
DENIED = "DENIED"
|
|
15
|
+
}
|
|
7
16
|
export declare class TasVideocallComponent implements OnInit, OnDestroy, AfterViewInit {
|
|
8
17
|
activeModal: NgbActiveModal;
|
|
9
18
|
private tasService;
|
|
10
19
|
private geolocationService;
|
|
20
|
+
private sanitizer;
|
|
21
|
+
private modalService;
|
|
11
22
|
sessionId: string;
|
|
12
23
|
token: string;
|
|
13
24
|
appointmentId?: number;
|
|
@@ -31,12 +42,23 @@ export declare class TasVideocallComponent implements OnInit, OnDestroy, AfterVi
|
|
|
31
42
|
geoLocationStatus: 'unknown' | 'active' | 'denied';
|
|
32
43
|
geoRequestActive: boolean;
|
|
33
44
|
allGeoGranted: boolean;
|
|
45
|
+
userGeoInfo: UserGeoInfo[];
|
|
46
|
+
userGeoViewState: UserGeoViewState;
|
|
47
|
+
UserGeoViewState: typeof UserGeoViewState;
|
|
48
|
+
homeIcon: SafeHtml;
|
|
49
|
+
devModeEnabled: boolean;
|
|
50
|
+
private geoPanelDismissed;
|
|
51
|
+
private feedbackShown;
|
|
34
52
|
private subscriptions;
|
|
35
|
-
constructor(activeModal: NgbActiveModal, tasService: TasService, geolocationService: GeolocationService);
|
|
53
|
+
constructor(activeModal: NgbActiveModal, tasService: TasService, geolocationService: GeolocationService, sanitizer: DomSanitizer, modalService: NgbModal);
|
|
36
54
|
ngOnInit(): void;
|
|
37
55
|
ngAfterViewInit(): void;
|
|
38
56
|
ngOnDestroy(): void;
|
|
39
57
|
hangUp(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Open feedback modal when call ends
|
|
60
|
+
*/
|
|
61
|
+
private openFeedbackModal;
|
|
40
62
|
toggleMute(): void;
|
|
41
63
|
minimize(): void;
|
|
42
64
|
toggleSwap(): void;
|
|
@@ -45,6 +67,20 @@ export declare class TasVideocallComponent implements OnInit, OnDestroy, AfterVi
|
|
|
45
67
|
* Check if current user can admit others (OWNER, BACKOFFICE, or MODERATOR)
|
|
46
68
|
*/
|
|
47
69
|
get canAdmitUsers(): boolean;
|
|
70
|
+
/** Users with pending geo status */
|
|
71
|
+
get pendingUsers(): UserGeoInfo[];
|
|
72
|
+
/** Users who granted geo */
|
|
73
|
+
get grantedUsers(): UserGeoInfo[];
|
|
74
|
+
/** Users who denied geo */
|
|
75
|
+
get deniedUsers(): UserGeoInfo[];
|
|
76
|
+
/** Show location panel only if owner and there are users who haven't granted */
|
|
77
|
+
get shouldShowLocationPanel(): boolean;
|
|
78
|
+
/** Check if any user has denied geo */
|
|
79
|
+
get hasAnyDenied(): boolean;
|
|
80
|
+
/** Show user geo panel for owners when not hidden */
|
|
81
|
+
get shouldShowUserGeoPanel(): boolean;
|
|
82
|
+
/** Set user geo view state (for dev controls or close button) */
|
|
83
|
+
setUserGeoViewState(state: UserGeoViewState): void;
|
|
48
84
|
/**
|
|
49
85
|
* Admit a user from the waiting room
|
|
50
86
|
*/
|
|
@@ -58,19 +94,26 @@ export declare class TasVideocallComponent implements OnInit, OnDestroy, AfterVi
|
|
|
58
94
|
*/
|
|
59
95
|
closeLocationPanel(): void;
|
|
60
96
|
/**
|
|
61
|
-
* Request the user to share their location
|
|
97
|
+
* Request the user to share their location (called by owner)
|
|
62
98
|
*/
|
|
63
99
|
requestUserLocation(): void;
|
|
64
100
|
private setupSubscriptions;
|
|
65
101
|
/**
|
|
66
102
|
* Handle activateGeo request from backend (for non-owner users).
|
|
67
|
-
*
|
|
103
|
+
* Directly prompts browser for geolocation - no panel for users.
|
|
68
104
|
*/
|
|
69
105
|
private handleActivateGeo;
|
|
106
|
+
/** Start geolocation verification (called from template button) */
|
|
107
|
+
startGeoVerification(): Promise<void>;
|
|
70
108
|
/**
|
|
71
|
-
* Report geolocation
|
|
109
|
+
* Report granted geolocation to backend.
|
|
110
|
+
* IMPORTANT: Only call with valid coordinates.
|
|
72
111
|
*/
|
|
73
112
|
private reportGeoStatus;
|
|
113
|
+
/**
|
|
114
|
+
* Report denied geolocation to backend.
|
|
115
|
+
*/
|
|
116
|
+
private denyGeoLocation;
|
|
74
117
|
private initializeCall;
|
|
75
118
|
private resetVideoPositions;
|
|
76
119
|
private initInteract;
|
|
@@ -26,6 +26,7 @@ export declare class TasWaitingRoomComponent implements OnInit, OnDestroy {
|
|
|
26
26
|
state: WaitingRoomState;
|
|
27
27
|
WaitingRoomState: typeof WaitingRoomState;
|
|
28
28
|
errorMessage: string;
|
|
29
|
+
showErrorDetails: boolean;
|
|
29
30
|
isJoinable: boolean;
|
|
30
31
|
private resolvedSessionId;
|
|
31
32
|
private resolvedAppointmentId;
|
|
@@ -34,39 +35,61 @@ export declare class TasWaitingRoomComponent implements OnInit, OnDestroy {
|
|
|
34
35
|
private subscriptions;
|
|
35
36
|
private videoCallModalRef;
|
|
36
37
|
private geoPosition;
|
|
38
|
+
private geoWasDenied;
|
|
39
|
+
private geoResultSent;
|
|
40
|
+
private mediaPermissionsGranted;
|
|
41
|
+
private geoPermissionsResolved;
|
|
42
|
+
private retryCount;
|
|
43
|
+
private readonly MAX_RETRIES;
|
|
37
44
|
/** Whether current user is an owner */
|
|
38
45
|
get isOwner(): boolean;
|
|
46
|
+
/** Whether we're still requesting permissions (for template) */
|
|
47
|
+
get isRequestingPermissions(): boolean;
|
|
48
|
+
/** Whether we're waiting for admission after permissions granted (for template) */
|
|
49
|
+
get isWaitingForAdmission(): boolean;
|
|
39
50
|
constructor(activeModal: NgbActiveModal, tasService: TasService, geolocationService: GeolocationService, modalService: NgbModal, cdr: ChangeDetectorRef);
|
|
40
51
|
ngOnInit(): void;
|
|
41
52
|
/**
|
|
42
53
|
* Request camera and microphone permissions.
|
|
54
|
+
* Triggers auto-join when permissions are resolved.
|
|
43
55
|
*/
|
|
44
56
|
private requestMediaPermissions;
|
|
45
57
|
/**
|
|
46
|
-
* Request geolocation
|
|
58
|
+
* Request geolocation permission and cache result.
|
|
47
59
|
* Only for regular users (not owners/backoffice).
|
|
48
|
-
*
|
|
60
|
+
* Actual send to backend happens after we have videoCallId.
|
|
61
|
+
* Triggers auto-join when geolocation is resolved.
|
|
49
62
|
*/
|
|
50
63
|
private requestGeolocation;
|
|
51
64
|
/**
|
|
52
|
-
* Send
|
|
53
|
-
*
|
|
65
|
+
* Send geo result to backend (granted or denied).
|
|
66
|
+
* Only sends if videoCallId is available and not already sent.
|
|
67
|
+
*/
|
|
68
|
+
private sendGeoResultToBackend;
|
|
69
|
+
/**
|
|
70
|
+
* Send granted geolocation to backend via modify user endpoint.
|
|
54
71
|
*/
|
|
55
72
|
private sendGeolocationToBackend;
|
|
73
|
+
/**
|
|
74
|
+
* Send geolocation denial to backend via modify user endpoint.
|
|
75
|
+
*/
|
|
76
|
+
private sendGeoDenialToBackend;
|
|
56
77
|
ngOnDestroy(): void;
|
|
57
78
|
/**
|
|
58
79
|
* Check status to get session info
|
|
59
80
|
*/
|
|
60
81
|
private checkStatus;
|
|
61
82
|
/**
|
|
62
|
-
* Handle changes to joinable status
|
|
83
|
+
* Handle changes to joinable status.
|
|
84
|
+
* Triggers auto-join when joinable becomes true.
|
|
63
85
|
*/
|
|
64
86
|
private handleJoinableChange;
|
|
65
87
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
88
|
+
* Attempt to auto-join the session when all conditions are met.
|
|
89
|
+
* - For owners: just need joinable + sessionId
|
|
90
|
+
* - For users: need media permissions + geo resolved + joinable + sessionId
|
|
68
91
|
*/
|
|
69
|
-
|
|
92
|
+
private tryAutoJoin;
|
|
70
93
|
/**
|
|
71
94
|
* Check if user has owner/backoffice role
|
|
72
95
|
*/
|
|
@@ -76,13 +99,18 @@ export declare class TasWaitingRoomComponent implements OnInit, OnDestroy {
|
|
|
76
99
|
*/
|
|
77
100
|
private startSessionAndJoin;
|
|
78
101
|
/**
|
|
79
|
-
*
|
|
102
|
+
* Retry after an error.
|
|
103
|
+
* Resets retry count and restarts the flow.
|
|
80
104
|
*/
|
|
81
|
-
|
|
105
|
+
retry(): void;
|
|
82
106
|
/**
|
|
83
|
-
*
|
|
107
|
+
* Toggle the error details dropdown visibility.
|
|
84
108
|
*/
|
|
85
|
-
|
|
109
|
+
toggleErrorDetails(): void;
|
|
110
|
+
/**
|
|
111
|
+
* Close the waiting room modal.
|
|
112
|
+
*/
|
|
113
|
+
close(): void;
|
|
86
114
|
private openVideoCallModal;
|
|
87
115
|
static ɵfac: i0.ɵɵFactoryDeclaration<TasWaitingRoomComponent, never>;
|
|
88
116
|
static ɵcmp: i0.ɵɵComponentDeclaration<TasWaitingRoomComponent, "tas-waiting-room", never, { "roomType": "roomType"; "entityId": "entityId"; "tenant": "tenant"; "businessRole": "businessRole"; "currentUser": "currentUser"; }, {}, never, never>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SVG icons used internally by TAS SDK components.
|
|
3
|
+
* Icons are stored as strings to avoid asset bundling complexity.
|
|
4
|
+
*/
|
|
5
|
+
export declare const TAS_ICONS: {
|
|
6
|
+
readonly home: "<svg width=\"120\" height=\"100\" viewBox=\"0 0 120 100\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<rect x=\"10\" width=\"100\" height=\"100\" rx=\"50\" fill=\"#44D8E8\" fill-opacity=\"0.2\"/>\n<path d=\"M45 70C43.625 70 42.4479 69.5104 41.4688 68.5313C40.4896 67.5521 40 66.375 40 65V46.5625L37.5 48.5C36.9583 48.9167 36.3438 49.0833 35.6562 49C34.9688 48.9167 34.4167 48.5833 34 48C33.5833 47.4583 33.4271 46.8542 33.5312 46.1875C33.6354 45.5208 33.9583 44.9792 34.5 44.5625L56.9375 27.3125C57.3958 26.9792 57.8854 26.7292 58.4062 26.5625C58.9271 26.3958 59.4583 26.3125 60 26.3125C60.5417 26.3125 61.0729 26.3958 61.5938 26.5625C62.1146 26.7292 62.6042 26.9792 63.0625 27.3125L85.5 44.5C86.0417 44.9167 86.3646 45.4583 86.4688 46.125C86.5729 46.7917 86.4167 47.4167 86 48C85.5833 48.5833 85.0417 48.9063 84.375 48.9688C83.7083 49.0313 83.0833 48.8542 82.5 48.4375L60 31.25L45 42.75V65H50.0625C50.7708 65 51.3542 65.2396 51.8125 65.7188C52.2708 66.1979 52.5 66.7917 52.5 67.5C52.5 68.2083 52.2604 68.8021 51.7812 69.2813C51.3021 69.7604 50.7083 70 50 70H45ZM67.3125 73.9375C66.9792 73.9375 66.6667 73.875 66.375 73.75C66.0833 73.625 65.8125 73.4375 65.5625 73.1875L58.5 66.125C58 65.625 57.75 65.0417 57.75 64.375C57.75 63.7083 58 63.125 58.5 62.625C59 62.125 59.5833 61.875 60.25 61.875C60.9167 61.875 61.5 62.125 62 62.625L67.3125 67.875L79.6875 55.5C80.1875 55 80.7812 54.7604 81.4688 54.7813C82.1562 54.8021 82.75 55.0625 83.25 55.5625C83.75 56.0625 84 56.6458 84 57.3125C84 57.9792 83.75 58.5625 83.25 59.0625L69.0625 73.1875C68.8125 73.4375 68.5417 73.625 68.25 73.75C67.9583 73.875 67.6458 73.9375 67.3125 73.9375Z\" fill=\"white\"/>\n<path d=\"M110 5L106.575 3.425L105 0L103.425 3.425L100 5L103.425 6.575L105 10L106.575 6.575L110 5Z\" fill=\"#44D8E8\"/>\n<path d=\"M10 51L6.575 49.425L5 46L3.425 49.425L0 51L3.425 52.575L5 56L6.575 52.575L10 51Z\" fill=\"#44D8E8\"/>\n<path d=\"M95 43.5L93.2875 42.7125L92.5 41L91.7125 42.7125L90 43.5L91.7125 44.2875L92.5 46L93.2875 44.2875L95 43.5Z\" fill=\"#44D8E8\"/>\n<path d=\"M42 4.5L40.2875 3.7125L39.5 2L38.7125 3.7125L37 4.5L38.7125 5.2875L39.5 7L40.2875 5.2875L42 4.5Z\" fill=\"#44D8E8\"/>\n<path d=\"M88 83.5L86.2875 82.7125L85.5 81L84.7125 82.7125L83 83.5L84.7125 84.2875L85.5 86L86.2875 84.2875L88 83.5Z\" fill=\"#44D8E8\"/>\n<path d=\"M120 97.5L118.287 96.7125L117.5 95L116.713 96.7125L115 97.5L116.713 98.2875L117.5 100L118.287 98.2875L120 97.5Z\" fill=\"#44D8E8\"/>\n</svg>";
|
|
7
|
+
};
|
|
8
|
+
export declare type TasIconName = keyof typeof TAS_ICONS;
|
|
@@ -36,7 +36,13 @@ export declare enum UserCallAction {
|
|
|
36
36
|
BAN = "BAN",
|
|
37
37
|
CHANGE_STATUS = "CHANGE_STATUS",
|
|
38
38
|
REQUEST_GEOLOCALIZATION = "REQUEST_GEOLOCALIZATION",
|
|
39
|
-
ACTIVATE_GEOLOCATION = "ACTIVATE_GEOLOCATION"
|
|
39
|
+
ACTIVATE_GEOLOCATION = "ACTIVATE_GEOLOCATION",
|
|
40
|
+
DENY_GEOLOCATION = "DENY_GEOLOCATION"
|
|
41
|
+
}
|
|
42
|
+
export declare enum GeoStatus {
|
|
43
|
+
PENDING = "PENDING",
|
|
44
|
+
GRANTED = "GRANTED",
|
|
45
|
+
DENIED = "DENIED"
|
|
40
46
|
}
|
|
41
47
|
export declare enum RoomUserStatus {
|
|
42
48
|
ASSIGNED = "ASSIGNED",
|
|
@@ -55,6 +61,10 @@ export declare enum ViewMode {
|
|
|
55
61
|
FULLSCREEN = "FULLSCREEN",
|
|
56
62
|
PIP = "PIP"
|
|
57
63
|
}
|
|
64
|
+
export declare enum FeedbackMotiveType {
|
|
65
|
+
TECHNICAL = "TECHNICAL",
|
|
66
|
+
BUSINESS = "BUSINESS"
|
|
67
|
+
}
|
|
58
68
|
export interface TasCurrentUser {
|
|
59
69
|
id: number;
|
|
60
70
|
name: string;
|
|
@@ -99,6 +109,9 @@ export interface ProxyVideoStatusUser {
|
|
|
99
109
|
userId: number;
|
|
100
110
|
rol: TasUserRole;
|
|
101
111
|
status: UserStatus;
|
|
112
|
+
geoStatus: GeoStatus;
|
|
113
|
+
latitude: number | null;
|
|
114
|
+
longitude: number | null;
|
|
102
115
|
}
|
|
103
116
|
export interface ProxyVideoStatusResponse {
|
|
104
117
|
content: {
|
|
@@ -109,8 +122,8 @@ export interface ProxyVideoStatusResponse {
|
|
|
109
122
|
waitingRoomAvailable: boolean;
|
|
110
123
|
appointmentId: number;
|
|
111
124
|
activateGeo: boolean;
|
|
112
|
-
geoRequestActive
|
|
113
|
-
allGeoGranted
|
|
125
|
+
geoRequestActive: boolean | null;
|
|
126
|
+
allGeoGranted: boolean;
|
|
114
127
|
users: ProxyVideoStatusUser[];
|
|
115
128
|
};
|
|
116
129
|
}
|
|
@@ -137,6 +150,13 @@ export interface WaitingRoomUser {
|
|
|
137
150
|
name: string;
|
|
138
151
|
status: RoomUserStatus;
|
|
139
152
|
}
|
|
153
|
+
/** User geolocation info for owner panel */
|
|
154
|
+
export interface UserGeoInfo {
|
|
155
|
+
userId: number;
|
|
156
|
+
geoStatus: GeoStatus;
|
|
157
|
+
latitude: number | null;
|
|
158
|
+
longitude: number | null;
|
|
159
|
+
}
|
|
140
160
|
export declare enum AppointmentStatus {
|
|
141
161
|
CONFIRMED = "CONFIRMED",
|
|
142
162
|
CANCELLED = "CANCELLED",
|
|
@@ -166,3 +186,16 @@ export interface GetAppointmentsRequest {
|
|
|
166
186
|
toDate: string;
|
|
167
187
|
entityId?: number;
|
|
168
188
|
}
|
|
189
|
+
export interface SaveFeedbackRequest {
|
|
190
|
+
videoCallId: number;
|
|
191
|
+
motiveId: number;
|
|
192
|
+
motiveType?: FeedbackMotiveType;
|
|
193
|
+
observation: string;
|
|
194
|
+
rating: number;
|
|
195
|
+
tenant: string;
|
|
196
|
+
}
|
|
197
|
+
export interface FeedbackMotive {
|
|
198
|
+
id: number;
|
|
199
|
+
description: string;
|
|
200
|
+
motiveType: FeedbackMotiveType;
|
|
201
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { TasUtilityService } from './tas-utility.service';
|
|
2
2
|
import { Observable } from 'rxjs';
|
|
3
3
|
import * as OT from '@opentok/client';
|
|
4
|
-
import { GenerateTokenResponse, StartSessionRequest, FinishSessionResponse, ProxyVideoStatusRequest, ProxyVideoStatusResponse, ProxyVideoFinishRequest, ProxyVideoUserModifyRequest, UserCallAction, RoomUserStatus, TasBusinessRole, CallState, ViewMode, WaitingRoomUser, TasAppointment, GetAppointmentsRequest } from '../interfaces/tas.interfaces';
|
|
4
|
+
import { GenerateTokenResponse, StartSessionRequest, FinishSessionResponse, ProxyVideoStatusRequest, ProxyVideoStatusResponse, ProxyVideoFinishRequest, ProxyVideoUserModifyRequest, UserCallAction, RoomUserStatus, GeoStatus, TasBusinessRole, CallState, ViewMode, WaitingRoomUser, UserGeoInfo, TasAppointment, GetAppointmentsRequest, SaveFeedbackRequest, FeedbackMotive } from '../interfaces/tas.interfaces';
|
|
5
5
|
import { TasConfig, TasHttpClient } from '../config/tas.config';
|
|
6
6
|
import * as i0 from "@angular/core";
|
|
7
|
-
export { CallState, ViewMode, TasBusinessRole, UserCallAction, RoomUserStatus };
|
|
7
|
+
export { CallState, ViewMode, TasBusinessRole, UserCallAction, RoomUserStatus, GeoStatus };
|
|
8
8
|
export declare class TasService {
|
|
9
9
|
private httpClient;
|
|
10
10
|
private config;
|
|
@@ -40,12 +40,16 @@ export declare class TasService {
|
|
|
40
40
|
geoRequestActive$: Observable<boolean>;
|
|
41
41
|
private allGeoGrantedSubject;
|
|
42
42
|
allGeoGranted$: Observable<boolean>;
|
|
43
|
+
private userGeoInfoSubject;
|
|
44
|
+
userGeoInfo$: Observable<UserGeoInfo[]>;
|
|
43
45
|
private statusPollingInterval;
|
|
44
46
|
private readonly DEFAULT_POLL_INTERVAL_MS;
|
|
45
47
|
private wasOwnerPresent;
|
|
46
48
|
private currentAppointmentId;
|
|
47
49
|
private currentVideoCallId;
|
|
48
50
|
private currentTenant;
|
|
51
|
+
private readonly STATUS_CACHE_TTL_MS;
|
|
52
|
+
private statusCache;
|
|
49
53
|
constructor(httpClient: TasHttpClient, config: TasConfig, tasUtilityService: TasUtilityService);
|
|
50
54
|
/**
|
|
51
55
|
* Start automatic status polling for the current session.
|
|
@@ -86,8 +90,15 @@ export declare class TasService {
|
|
|
86
90
|
* PROXY circuit token: /v2/proxy/video/start
|
|
87
91
|
*/
|
|
88
92
|
startProxyVideoSession(payload: StartSessionRequest): Observable<GenerateTokenResponse>;
|
|
93
|
+
/**
|
|
94
|
+
* Generate cache key from request payload
|
|
95
|
+
*/
|
|
96
|
+
private getStatusCacheKey;
|
|
97
|
+
private inflightStatusRequests;
|
|
89
98
|
/**
|
|
90
99
|
* PROXY circuit status: /v2/proxy/video/status
|
|
100
|
+
* Uses a 1-second cache to avoid redundant API calls from multiple components
|
|
101
|
+
* Implements request deduplication for simultaneous calls
|
|
91
102
|
*/
|
|
92
103
|
getProxyVideoStatus(payload: ProxyVideoStatusRequest): Observable<ProxyVideoStatusResponse>;
|
|
93
104
|
/**
|
|
@@ -101,6 +112,19 @@ export declare class TasService {
|
|
|
101
112
|
* @returns Observable of appointment array
|
|
102
113
|
*/
|
|
103
114
|
getAppointments(params: GetAppointmentsRequest): Observable<TasAppointment[]>;
|
|
115
|
+
/**
|
|
116
|
+
* Save video call feedback.
|
|
117
|
+
* POST /v2/proxy/video/save/feedback
|
|
118
|
+
* @param payload Feedback data including videoCallId, motiveId, motiveType, observation, rating (1-5), and tenant
|
|
119
|
+
* @returns Observable that completes on success (HTTP 200 OK, no response body)
|
|
120
|
+
*/
|
|
121
|
+
saveFeedback(payload: SaveFeedbackRequest): Observable<void>;
|
|
122
|
+
/**
|
|
123
|
+
* Get available feedback motives.
|
|
124
|
+
* GET /v2/proxy/video/motives
|
|
125
|
+
* @returns Observable of feedback motives array
|
|
126
|
+
*/
|
|
127
|
+
getMotives(): Observable<FeedbackMotive[]>;
|
|
104
128
|
/**
|
|
105
129
|
* Start automatic status polling for the current session.
|
|
106
130
|
* Status is polled every STATUS_POLL_INTERVAL_MS milliseconds.
|
|
@@ -122,6 +146,7 @@ export declare class TasService {
|
|
|
122
146
|
admitUserFromWaitingRoom(userId: number, videoCallId: number): Observable<any>;
|
|
123
147
|
get appointmentId(): number | null;
|
|
124
148
|
get videoCallId(): number | null;
|
|
149
|
+
get tenant(): string | null;
|
|
125
150
|
/**
|
|
126
151
|
* Connects to a TokBox video session
|
|
127
152
|
*/
|
|
@@ -7,9 +7,10 @@ import * as i3 from "./components/tas-floating-call/tas-floating-call.component"
|
|
|
7
7
|
import * as i4 from "./components/tas-waiting-room/tas-waiting-room.component";
|
|
8
8
|
import * as i5 from "./components/tas-avatar/tas-avatar.component";
|
|
9
9
|
import * as i6 from "./components/tas-incoming-appointment/tas-incoming-appointment.component";
|
|
10
|
-
import * as i7 from "
|
|
11
|
-
import * as i8 from "@angular/
|
|
12
|
-
import * as i9 from "@
|
|
10
|
+
import * as i7 from "./components/tas-feedback-modal/tas-feedback-modal.component";
|
|
11
|
+
import * as i8 from "@angular/common";
|
|
12
|
+
import * as i9 from "@angular/forms";
|
|
13
|
+
import * as i10 from "@ng-bootstrap/ng-bootstrap";
|
|
13
14
|
export declare class TasUellSdkModule {
|
|
14
15
|
/**
|
|
15
16
|
* Use forRoot() to configure the TAS SDK module with required dependencies.
|
|
@@ -45,6 +46,6 @@ export declare class TasUellSdkModule {
|
|
|
45
46
|
httpClient: new (...args: any[]) => TasHttpClient;
|
|
46
47
|
}): ModuleWithProviders<TasUellSdkModule>;
|
|
47
48
|
static ɵfac: i0.ɵɵFactoryDeclaration<TasUellSdkModule, never>;
|
|
48
|
-
static ɵmod: i0.ɵɵNgModuleDeclaration<TasUellSdkModule, [typeof i1.TasButtonComponent, typeof i2.TasVideocallComponent, typeof i3.TasFloatingCallComponent, typeof i4.TasWaitingRoomComponent, typeof i5.TasAvatarComponent, typeof i6.TasIncomingAppointmentComponent], [typeof
|
|
49
|
+
static ɵmod: i0.ɵɵNgModuleDeclaration<TasUellSdkModule, [typeof i1.TasButtonComponent, typeof i2.TasVideocallComponent, typeof i3.TasFloatingCallComponent, typeof i4.TasWaitingRoomComponent, typeof i5.TasAvatarComponent, typeof i6.TasIncomingAppointmentComponent, typeof i7.TasFeedbackModalComponent], [typeof i8.CommonModule, typeof i9.FormsModule, typeof i10.NgbTooltipModule], [typeof i1.TasButtonComponent, typeof i2.TasVideocallComponent, typeof i3.TasFloatingCallComponent, typeof i4.TasWaitingRoomComponent, typeof i5.TasAvatarComponent, typeof i6.TasIncomingAppointmentComponent, typeof i7.TasFeedbackModalComponent]>;
|
|
49
50
|
static ɵinj: i0.ɵɵInjectorDeclaration<TasUellSdkModule>;
|
|
50
51
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tas-uell-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "TAS (Telemedicine Assistance Service) SDK for Angular applications - Video call functionality using TokBox/Vonage",
|
|
5
5
|
"peerDependencies": {
|
|
6
6
|
"@angular/common": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
|
package/public-api.d.ts
CHANGED
|
@@ -9,4 +9,5 @@ export * from './lib/components/tas-videocall/tas-videocall.component';
|
|
|
9
9
|
export * from './lib/components/tas-floating-call/tas-floating-call.component';
|
|
10
10
|
export * from './lib/components/tas-avatar/tas-avatar.component';
|
|
11
11
|
export * from './lib/components/tas-incoming-appointment/tas-incoming-appointment.component';
|
|
12
|
+
export * from './lib/components/tas-feedback-modal/tas-feedback-modal.component';
|
|
12
13
|
export * from './lib/tas-uell-sdk.module';
|
|
@@ -34,3 +34,20 @@
|
|
|
34
34
|
padding: 0;
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
/* TAS Feedback Modal - global styles for NgbModal wrapper */
|
|
39
|
+
.tas-feedback-modal-wrapper {
|
|
40
|
+
.modal-dialog {
|
|
41
|
+
max-width: 480px;
|
|
42
|
+
}
|
|
43
|
+
.modal-content {
|
|
44
|
+
border: none;
|
|
45
|
+
border-radius: 20px;
|
|
46
|
+
background: #ffffff;
|
|
47
|
+
overflow: hidden;
|
|
48
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15);
|
|
49
|
+
}
|
|
50
|
+
.modal-body {
|
|
51
|
+
padding: 0;
|
|
52
|
+
}
|
|
53
|
+
}
|