@chat21/chat21-ionic 3.0.61-rc8 → 3.0.61
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 +71 -0
- package/README.md +6 -0
- package/angular.json +2 -0
- package/config.xml +0 -1
- package/deploy_pre.sh +1 -1
- package/deploy_prod.sh +1 -1
- package/env.sample +1 -1
- package/package.json +4 -4
- package/src/app/app-routing.module.ts +15 -0
- package/src/app/app.component.ts +12 -9
- package/src/app/app.module.ts +11 -3
- package/src/app/chatlib/conversation-detail/ion-conversation-detail/ion-conversation-detail.component.html +36 -25
- package/src/app/chatlib/conversation-detail/ion-conversation-detail/ion-conversation-detail.component.scss +160 -50
- package/src/app/chatlib/conversation-detail/ion-conversation-detail/ion-conversation-detail.component.ts +108 -18
- package/src/app/chatlib/conversation-detail/message/bubble-message/bubble-message.component.html +21 -36
- package/src/app/chatlib/conversation-detail/message/bubble-message/bubble-message.component.scss +19 -7
- package/src/app/chatlib/conversation-detail/message/bubble-message/bubble-message.component.ts +35 -40
- package/src/app/chatlib/conversation-detail/message/message-attachment/message-attachment.component.scss +1 -1
- package/src/app/chatlib/list-conversations-component/list-conversations/list-conversations.component.ts +13 -10
- package/src/app/components/conversation-detail/header-conversation-detail/header-conversation-detail.component.html +3 -2
- package/src/app/components/conversation-detail/header-conversation-detail/header-conversation-detail.component.scss +2 -0
- package/src/app/components/conversation-detail/header-conversation-detail/header-conversation-detail.component.ts +142 -71
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.html +57 -20
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.scss +32 -9
- package/src/app/components/conversation-detail/message-text-area/message-text-area.component.ts +98 -24
- package/src/app/components/ddp-header/ddp-header.component.html +9 -2
- package/src/app/components/ddp-header/ddp-header.component.ts +93 -18
- package/src/app/components/project-item/project-item.component.html +1 -1
- package/src/app/components/project-item/project-item.component.scss +1 -1
- package/src/app/components/project-item/project-item.component.ts +3 -3
- package/src/app/components/sidebar/sidebar.component.html +65 -52
- package/src/app/components/sidebar/sidebar.component.scss +23 -0
- package/src/app/components/sidebar/sidebar.component.ts +74 -26
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.html +20 -9
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.scss +20 -3
- package/src/app/components/sidebar-user-details/sidebar-user-details.component.ts +24 -8
- package/src/app/pages/conversation-detail/conversation-detail.module.ts +5 -1
- package/src/app/pages/conversation-detail/conversation-detail.page.html +19 -10
- package/src/app/pages/conversation-detail/conversation-detail.page.scss +28 -0
- package/src/app/pages/conversation-detail/conversation-detail.page.ts +229 -389
- package/src/app/pages/conversations-list/conversations-list.page.ts +646 -454
- package/src/app/pages/create-canned-response/create-canned-response-routing.module.ts +17 -0
- package/src/app/pages/create-canned-response/create-canned-response.module.ts +30 -0
- package/src/app/pages/create-canned-response/create-canned-response.page.html +150 -0
- package/src/app/pages/create-canned-response/create-canned-response.page.scss +55 -0
- package/src/app/pages/create-canned-response/create-canned-response.page.spec.ts +24 -0
- package/src/app/pages/create-canned-response/create-canned-response.page.ts +319 -0
- package/src/app/pages/create-requester/create-requester-routing.module.ts +17 -0
- package/src/app/pages/create-requester/create-requester.module.ts +28 -0
- package/src/app/pages/create-requester/create-requester.page.html +67 -0
- package/src/app/pages/create-requester/create-requester.page.scss +30 -0
- package/src/app/pages/create-requester/create-requester.page.spec.ts +24 -0
- package/src/app/pages/create-requester/create-requester.page.ts +138 -0
- package/src/app/pages/create-ticket/create-ticket-routing.module.ts +17 -0
- package/src/app/pages/create-ticket/create-ticket.module.ts +28 -0
- package/src/app/pages/create-ticket/create-ticket.page.html +171 -0
- package/src/app/pages/create-ticket/create-ticket.page.scss +52 -0
- package/src/app/pages/create-ticket/create-ticket.page.spec.ts +24 -0
- package/src/app/pages/create-ticket/create-ticket.page.ts +432 -0
- package/src/app/pages/loader-preview/loader-preview.page.ts +2 -11
- package/src/app/pages/profile-info/profile-info.page.html +2 -2
- package/src/app/pages/profile-info/profile-info.page.scss +12 -1
- package/src/app/services/tiledesk/tiledesk.service.ts +190 -0
- package/src/app/shared/shared.module.ts +1 -1
- package/src/assets/i18n/de.json +37 -1
- package/src/assets/i18n/en.json +37 -1
- package/src/assets/i18n/es.json +38 -2
- package/src/assets/i18n/fr.json +38 -2
- package/src/assets/i18n/it.json +38 -2
- package/src/assets/i18n/pt.json +38 -2
- package/src/assets/i18n/ru.json +38 -2
- package/src/assets/i18n/sr.json +38 -2
- package/src/assets/i18n/tr.json +37 -1
- package/src/assets/images/default-avatar-x-select.png +0 -0
- package/src/assets/images/priority_icons/high.svg +3 -0
- package/src/assets/images/priority_icons/high_v2.svg +14 -0
- package/src/assets/images/priority_icons/low.svg +10 -0
- package/src/assets/images/priority_icons/low_v2.svg +14 -0
- package/src/assets/images/priority_icons/medium.svg +16 -0
- package/src/assets/images/priority_icons/medium_v2.svg +11 -0
- package/src/assets/images/priority_icons/urgent.svg +4 -0
- package/src/assets/images/priority_icons/urgent_v2.svg +16 -0
- package/src/chat-config-mqtt.json +25 -16
- package/src/chat-config-template.json +5 -4
- package/src/chat-config.json +1 -0
- package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +8 -3
- package/src/chat21-core/utils/constants.ts +2 -0
- package/src/chat21-core/utils/utils-message.ts +19 -0
- package/src/global.scss +33 -9
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<ion-header>
|
|
2
|
+
<ion-toolbar>
|
|
3
|
+
<ion-title> {{'CreateNewRequester' | translate}} </ion-title>
|
|
4
|
+
<ion-buttons slot="end">
|
|
5
|
+
<ion-button ion-button fill="clear" (click)="closeModalAddNewRequester()">
|
|
6
|
+
<ion-icon slot="icon-only" name="close"></ion-icon>
|
|
7
|
+
</ion-button>
|
|
8
|
+
</ion-buttons>
|
|
9
|
+
</ion-toolbar>
|
|
10
|
+
</ion-header>
|
|
11
|
+
|
|
12
|
+
<ion-content class="ion-padding">
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
<form [formGroup]="validations_form" (ngSubmit)="onSubmit(validations_form.value)">
|
|
17
|
+
<ion-grid>
|
|
18
|
+
<ion-row>
|
|
19
|
+
<ion-col size="12">
|
|
20
|
+
|
|
21
|
+
<ion-item>
|
|
22
|
+
<ion-label position="floating" color="primary">{{'Name' | translate}} *</ion-label>
|
|
23
|
+
<ion-input type="text" formControlName="name"></ion-input>
|
|
24
|
+
</ion-item>
|
|
25
|
+
<div class="validation-errors">
|
|
26
|
+
<ng-container *ngFor="let validation of validation_messages.name">
|
|
27
|
+
<div class="error-message"
|
|
28
|
+
*ngIf="validations_form.get('name').hasError(validation.type) && (validations_form.get('name').dirty || validations_form.get('name').touched)">
|
|
29
|
+
<ion-icon name="information-circle-outline"></ion-icon>
|
|
30
|
+
<span class="validation-message"> {{ validation.message }} </span>
|
|
31
|
+
</div>
|
|
32
|
+
</ng-container>
|
|
33
|
+
</div>
|
|
34
|
+
</ion-col>
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
<ion-col size="12">
|
|
38
|
+
<ion-item>
|
|
39
|
+
<ion-label position="floating" color="primary">Email</ion-label>
|
|
40
|
+
<ion-input type="text" formControlName="email"></ion-input>
|
|
41
|
+
</ion-item>
|
|
42
|
+
<div class="validation-errors">
|
|
43
|
+
<ng-container *ngFor="let validation of validation_messages.email">
|
|
44
|
+
<div class="error-message"
|
|
45
|
+
*ngIf="validations_form.get('email').hasError(validation.type) && (validations_form.get('email').dirty || validations_form.get('email').touched)">
|
|
46
|
+
<ion-icon name="information-circle-outline"></ion-icon>
|
|
47
|
+
<span class="validation-message"> {{ validation.message }} </span>
|
|
48
|
+
|
|
49
|
+
</div>
|
|
50
|
+
</ng-container>
|
|
51
|
+
</div>
|
|
52
|
+
</ion-col>
|
|
53
|
+
<!-- expand="block" -->
|
|
54
|
+
<ion-col size="12" style="text-align: center;">
|
|
55
|
+
<ion-button color="primary" class="submit-btn" type="submit" [disabled]="!validations_form.valid" style="min-width:253px">
|
|
56
|
+
<ion-icon *ngIf="showSpinnerCreateRequester === false" style="font-size: 1.9em;" slot="start" name="add-circle-outline"></ion-icon>
|
|
57
|
+
<ion-spinner *ngIf="showSpinnerCreateRequester === true" style="color: #fff; margin: 0px 0.3em 0px -0.3em;" name="bubbles" duration="2" ></ion-spinner>
|
|
58
|
+
{{'CreateNewRequester' | translate}}</ion-button>
|
|
59
|
+
</ion-col>
|
|
60
|
+
</ion-row>
|
|
61
|
+
</ion-grid>
|
|
62
|
+
</form>
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
</ion-content>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
ion-content {
|
|
2
|
+
.validation-errors {
|
|
3
|
+
height: 20px;
|
|
4
|
+
margin-bottom: 16px;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.error-message {
|
|
8
|
+
// color: red;
|
|
9
|
+
// font-size: 14px;
|
|
10
|
+
// margin-left: 10px;
|
|
11
|
+
// margin-top: 10px;
|
|
12
|
+
ion-icon {
|
|
13
|
+
color: red;
|
|
14
|
+
font-size: 16px;
|
|
15
|
+
margin-left: 15px;
|
|
16
|
+
margin-right: 3px;
|
|
17
|
+
position: relative;
|
|
18
|
+
top: 3px;
|
|
19
|
+
}
|
|
20
|
+
.validation-message {
|
|
21
|
+
color: red;
|
|
22
|
+
font-size: 14px;
|
|
23
|
+
margin-top: 1px;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.submit-btn {
|
|
28
|
+
margin: 48px 12px 12px;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { IonicModule } from '@ionic/angular';
|
|
3
|
+
|
|
4
|
+
import { CreateRequesterPage } from './create-requester.page';
|
|
5
|
+
|
|
6
|
+
describe('CreateRequesterPage', () => {
|
|
7
|
+
let component: CreateRequesterPage;
|
|
8
|
+
let fixture: ComponentFixture<CreateRequesterPage>;
|
|
9
|
+
|
|
10
|
+
beforeEach(async(() => {
|
|
11
|
+
TestBed.configureTestingModule({
|
|
12
|
+
declarations: [ CreateRequesterPage ],
|
|
13
|
+
imports: [IonicModule.forRoot()]
|
|
14
|
+
}).compileComponents();
|
|
15
|
+
|
|
16
|
+
fixture = TestBed.createComponent(CreateRequesterPage);
|
|
17
|
+
component = fixture.componentInstance;
|
|
18
|
+
fixture.detectChanges();
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
it('should create', () => {
|
|
22
|
+
expect(component).toBeTruthy();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import { Component, Input, OnInit } from '@angular/core';
|
|
2
|
+
import { Validators, FormBuilder, FormGroup, FormControl} from '@angular/forms';
|
|
3
|
+
import { ModalController } from '@ionic/angular'
|
|
4
|
+
import { TranslateService } from '@ngx-translate/core';
|
|
5
|
+
import { TiledeskService } from 'src/app/services/tiledesk/tiledesk.service';
|
|
6
|
+
import { TiledeskAuthService } from 'src/chat21-core/providers/tiledesk/tiledesk-auth.service';
|
|
7
|
+
import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
|
|
8
|
+
import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
|
|
9
|
+
@Component({
|
|
10
|
+
selector: 'app-create-requester',
|
|
11
|
+
templateUrl: './create-requester.page.html',
|
|
12
|
+
styleUrls: ['./create-requester.page.scss'],
|
|
13
|
+
})
|
|
14
|
+
export class CreateRequesterPage implements OnInit {
|
|
15
|
+
public new_user_name: string;
|
|
16
|
+
public new_user_email : string;
|
|
17
|
+
|
|
18
|
+
validations_form: FormGroup;
|
|
19
|
+
@Input() projectUserAndLeadsArray: any
|
|
20
|
+
|
|
21
|
+
prjctID: string;
|
|
22
|
+
tiledeskToken: string;
|
|
23
|
+
showSpinnerCreateRequester: boolean = false;
|
|
24
|
+
requester_id: string;
|
|
25
|
+
logger: LoggerService = LoggerInstance.getInstance();
|
|
26
|
+
|
|
27
|
+
constructor(
|
|
28
|
+
public modalController: ModalController,
|
|
29
|
+
private formBuilder: FormBuilder,
|
|
30
|
+
public tiledeskService: TiledeskService,
|
|
31
|
+
public tiledeskAuthService: TiledeskAuthService,
|
|
32
|
+
private translate: TranslateService,
|
|
33
|
+
) { }
|
|
34
|
+
|
|
35
|
+
ngOnInit() {
|
|
36
|
+
this.logger.log('[CREATE-REQUESTER] projectUserAndLeadsArray ', this.projectUserAndLeadsArray)
|
|
37
|
+
const stored_project = localStorage.getItem('last_project')
|
|
38
|
+
const storedPrjctObjct = JSON.parse(stored_project)
|
|
39
|
+
this.logger.log('[CREATE-REQUESTER] storedPrjctObjct ', storedPrjctObjct)
|
|
40
|
+
if (storedPrjctObjct) {
|
|
41
|
+
this.prjctID = storedPrjctObjct.id_project.id
|
|
42
|
+
this.logger.log('[CREATE-REQUESTER] this.prjctID ', this.prjctID)
|
|
43
|
+
}
|
|
44
|
+
this.tiledeskToken = this.tiledeskAuthService.getTiledeskToken()
|
|
45
|
+
this.logger.log('[CREATE-REQUESTER] tiledeskToken ', this.tiledeskToken)
|
|
46
|
+
|
|
47
|
+
this.buildForm()
|
|
48
|
+
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
buildForm() {
|
|
52
|
+
this.validations_form = this.formBuilder.group({
|
|
53
|
+
|
|
54
|
+
name: new FormControl('', Validators.required),
|
|
55
|
+
|
|
56
|
+
email: new FormControl('', Validators.compose([
|
|
57
|
+
Validators.pattern('^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+.[a-zA-Z0-9-.]+$')
|
|
58
|
+
])),
|
|
59
|
+
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
validation_messages = {
|
|
64
|
+
'name': [
|
|
65
|
+
{ type: 'required', message: this.translate.instant('NameIsRequired') }
|
|
66
|
+
],
|
|
67
|
+
|
|
68
|
+
'email': [
|
|
69
|
+
{ type: 'pattern', message: this.translate.instant('EnterValidEmail') }
|
|
70
|
+
],
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
onSubmit(values){
|
|
74
|
+
this.logger.log('[CREATE-REQUESTER] ON SUBMIT VALUSES' , values);
|
|
75
|
+
this.new_user_name = values.name
|
|
76
|
+
this.new_user_email = values.email
|
|
77
|
+
this.createProjectUserAndThenNewLead(this.new_user_name, this.new_user_email)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
createProjectUserAndThenNewLead(new_user_name, new_user_email) {
|
|
81
|
+
this.showSpinnerCreateRequester = true;
|
|
82
|
+
this.logger.log('[CREATE-REQUESTER] - CREATE-NEW-USER name ', new_user_name);
|
|
83
|
+
this.logger.log('[CREATE-REQUESTER] - CREATE-NEW-USER email ', new_user_email);
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
this.tiledeskService.createNewProjectUserToGetNewLeadID(this.prjctID, this.tiledeskToken).subscribe(res => {
|
|
87
|
+
this.logger.log('[CREATE-REQUESTER] - CREATE-NEW-USER - CREATE-PROJECT-USER ', res);
|
|
88
|
+
this.logger.log('[CREATE-REQUESTER] - CREATE-NEW-USER - CREATE-PROJECT-USER UUID ', res.uuid_user);
|
|
89
|
+
if (res) {
|
|
90
|
+
if (res.uuid_user) {
|
|
91
|
+
let new_lead_id = res.uuid_user
|
|
92
|
+
this.createNewContact(new_lead_id, new_user_name, new_user_email, this.prjctID, this.tiledeskToken)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}, error => {
|
|
96
|
+
this.showSpinnerCreateRequester = false;
|
|
97
|
+
this.logger.error('[CREATE-REQUESTER] - CREATE-NEW-USER - CREATE-PROJECT-USER - ERROR: ', error);
|
|
98
|
+
}, () => {
|
|
99
|
+
|
|
100
|
+
this.logger.log('[CREATE-REQUESTER] - CREATE-NEW-USER - CREATE-PROJECT-USER - COMPLETE');
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
createNewContact(lead_id: string, lead_name: string, lead_email: string, projecId: string, tiledeskToken: string) {
|
|
106
|
+
this.tiledeskService.createNewLead(lead_id, lead_name, lead_email, projecId, tiledeskToken ).subscribe(lead => {
|
|
107
|
+
this.logger.log('[CREATE-REQUESTER] - CREATE-NEW-USER - CREATE-NEW-LEAD - RES ', lead);
|
|
108
|
+
this.projectUserAndLeadsArray.push({ id: lead.lead_id, name: lead.fullname, role: 'lead', email: lead_email, requestertype: 'lead', requester_id: lead._id});
|
|
109
|
+
this.requester_id = lead._id
|
|
110
|
+
// this.projectUserAndLeadsArray.push({ id: lead.lead_id, name: lead.fullname + ' (lead)' });
|
|
111
|
+
// this.projectUserAndLeadsArray = this.projectUserAndLeadsArray.slice(0);
|
|
112
|
+
this.logger.log('[CREATE-REQUESTER]- CREATE-NEW-USER - projectUserAndLeadsArray AFTERT NEW LEAD CREATION : ', this.projectUserAndLeadsArray);
|
|
113
|
+
}, error => {
|
|
114
|
+
this.showSpinnerCreateRequester = false;
|
|
115
|
+
this.logger.error('[CREATE-REQUESTER]- CREATE-NEW-USER - CREATE-NEW-LEAD - ERROR: ', error);
|
|
116
|
+
}, () => {
|
|
117
|
+
|
|
118
|
+
this.closeModalAddNewRequester( this.projectUserAndLeadsArray, lead_id, this.requester_id)
|
|
119
|
+
// -------------------------------------------------
|
|
120
|
+
// When is cmpleted the creation of the new reqester
|
|
121
|
+
// -------------------------------------------------
|
|
122
|
+
// this.displayCreateNewUserModal = 'none'
|
|
123
|
+
// this.displayInternalRequestModal = 'block'
|
|
124
|
+
|
|
125
|
+
// Auto select the new lead crerated in the select Requester
|
|
126
|
+
// this.selectedRequester = lead_id
|
|
127
|
+
this.logger.log('[WS-REQUESTS-LIST] - CREATE-NEW-USER - CREATE-NEW-LEAD * COMPLETE *');
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async closeModalAddNewRequester( projectUserAndLeadsArray?: any, lead_id?: string, requester_id?: string) {
|
|
132
|
+
this.logger.log('[CREATE-REQUESTER]', this.modalController)
|
|
133
|
+
this.logger.log( '[CREATE-REQUESTER] .getTop()',this.modalController.getTop())
|
|
134
|
+
await this.modalController.getTop()
|
|
135
|
+
this.modalController.dismiss({updatedProjectUserAndLeadsArray: projectUserAndLeadsArray, selectedRequester: lead_id, requester_type: 'lead', requester_id: requester_id })
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { Routes, RouterModule } from '@angular/router';
|
|
3
|
+
|
|
4
|
+
import { CreateTicketPage } from './create-ticket.page';
|
|
5
|
+
|
|
6
|
+
const routes: Routes = [
|
|
7
|
+
{
|
|
8
|
+
path: '',
|
|
9
|
+
component: CreateTicketPage
|
|
10
|
+
}
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
@NgModule({
|
|
14
|
+
imports: [RouterModule.forChild(routes)],
|
|
15
|
+
exports: [RouterModule],
|
|
16
|
+
})
|
|
17
|
+
export class CreateTicketPageRoutingModule {}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { NgModule } from '@angular/core';
|
|
2
|
+
import { CommonModule } from '@angular/common';
|
|
3
|
+
import { FormsModule } from '@angular/forms';
|
|
4
|
+
import { IonicModule } from '@ionic/angular';
|
|
5
|
+
import { CreateTicketPageRoutingModule } from './create-ticket-routing.module';
|
|
6
|
+
import { CreateTicketPage } from './create-ticket.page';
|
|
7
|
+
import { NgSelectModule } from '@ng-select/ng-select';
|
|
8
|
+
import { TranslateLoader, TranslateModule} from '@ngx-translate/core';
|
|
9
|
+
import { createTranslateLoader } from '../../../chat21-core/utils/utils';
|
|
10
|
+
import { HttpClient } from '@angular/common/http';
|
|
11
|
+
@NgModule({
|
|
12
|
+
imports: [
|
|
13
|
+
CommonModule,
|
|
14
|
+
FormsModule,
|
|
15
|
+
IonicModule,
|
|
16
|
+
CreateTicketPageRoutingModule,
|
|
17
|
+
NgSelectModule,
|
|
18
|
+
TranslateModule.forChild({
|
|
19
|
+
loader: {
|
|
20
|
+
provide: TranslateLoader,
|
|
21
|
+
useFactory: (createTranslateLoader),
|
|
22
|
+
deps: [HttpClient]
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
],
|
|
26
|
+
declarations: [CreateTicketPage]
|
|
27
|
+
})
|
|
28
|
+
export class CreateTicketPageModule {}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
<ion-header>
|
|
2
|
+
<ion-toolbar>
|
|
3
|
+
<ion-title>{{'CreateTicket' | translate}}</ion-title>
|
|
4
|
+
<ion-buttons slot="end">
|
|
5
|
+
<ion-button ion-button fill="clear" (click)="closeModalCreateTicketModal()">
|
|
6
|
+
<ion-icon slot="icon-only" name="close"></ion-icon>
|
|
7
|
+
</ion-button>
|
|
8
|
+
</ion-buttons>
|
|
9
|
+
</ion-toolbar>
|
|
10
|
+
</ion-header>
|
|
11
|
+
|
|
12
|
+
<ion-content >
|
|
13
|
+
|
|
14
|
+
<ion-grid class="ion-grid-custom-padding" [ngClass]="{'center-content': ticketCreationCompleted === true }">
|
|
15
|
+
<ion-row *ngIf="ticketCreationCompleted === false">
|
|
16
|
+
<ion-col size="12">
|
|
17
|
+
<!-- // with custom search {{'SelectRequester' | translate}}-->
|
|
18
|
+
<!-- {{ projectUserAndLeadsArray | json}} -->
|
|
19
|
+
<ion-label class="custom-create-ticket-label">{{'Requester' | translate }}</ion-label>
|
|
20
|
+
<ion-label [ngClass]="{'open-requester-details-disable': !selectedRequester}" class="custom-create-ticket-label-to-left"
|
|
21
|
+
(click)="openRequesterDetails()">
|
|
22
|
+
{{'ViewRequesterDetails' | translate }}
|
|
23
|
+
<span class="material-icons" style="color: #0f62ff; vertical-align: middle;font-size: 16px;">
|
|
24
|
+
open_in_new
|
|
25
|
+
</span>
|
|
26
|
+
</ion-label>
|
|
27
|
+
<ng-select class="create-ticket-custom-select" name="users_and_leads" [items]="projectUserAndLeadsArray"
|
|
28
|
+
bindLabel="name" bindValue="id" [(ngModel)]="selectedRequester" [virtualScroll]="true"
|
|
29
|
+
[searchFn]="customSearchFn" (change)="selectRequester($event)" placeholder="{{'SelectRequester' | translate}}"
|
|
30
|
+
[loading]=loadingRequesters loadingText='Loading...'>
|
|
31
|
+
|
|
32
|
+
<ng-template ng-label-tmp let-item="item">
|
|
33
|
+
<!-- ---------------------------------------- -->
|
|
34
|
+
<!-- Usecase Firebase -->
|
|
35
|
+
<!-- ---------------------------------------- -->
|
|
36
|
+
<img *ngIf="item.requestertype === 'agent' && UPLOAD_ENGINE_IS_FIREBASE" height="24" width="24"
|
|
37
|
+
style="border-radius:50%; object-fit: cover; vertical-align: middle;"
|
|
38
|
+
src="https://firebasestorage.googleapis.com/v0/b/{{storageBucket}}/o/profiles%2F{{item.id}}%2Fphoto.jpg?alt=media"
|
|
39
|
+
alt="" onerror="this.src='assets/images/default-avatar-x-select.png'">
|
|
40
|
+
|
|
41
|
+
<!-- ---------------------------------------- -->
|
|
42
|
+
<!-- Usecase Native -->
|
|
43
|
+
<!-- ---------------------------------------- -->
|
|
44
|
+
<img *ngIf="item.requestertype === 'agent' && !UPLOAD_ENGINE_IS_FIREBASE" height="24" width="24"
|
|
45
|
+
style="border-radius:50%;object-fit: cover;vertical-align: middle;"
|
|
46
|
+
src="{{baseUrl}}images?path=uploads%2Fusers%2F{{item.id}}%2Fimages%2Fthumbnails_200_200-photo.jpg" alt=""
|
|
47
|
+
onerror="this.src='assets/images/default-avatar-x-select.png'">
|
|
48
|
+
|
|
49
|
+
<img *ngIf="item.requestertype === 'lead'" height="24" width="24"
|
|
50
|
+
style="border-radius:50%;object-fit: cover;vertical-align: middle;"
|
|
51
|
+
src="assets/images/default-avatar-x-select.png" alt="">
|
|
52
|
+
<span style="font-weight: 400;">
|
|
53
|
+
{{ item.name }}
|
|
54
|
+
</span>
|
|
55
|
+
<span class="requester-role-or-type">
|
|
56
|
+
({{item.role}})
|
|
57
|
+
</span>
|
|
58
|
+
|
|
59
|
+
</ng-template>
|
|
60
|
+
<ng-template ng-option-tmp let-item="item" let-search="searchTerm" let-index="index">
|
|
61
|
+
<!-- ---------------------------------------- -->
|
|
62
|
+
<!-- Usecase Firebase -->
|
|
63
|
+
<!-- ---------------------------------------- -->
|
|
64
|
+
<img *ngIf="item.requestertype === 'agent' && UPLOAD_ENGINE_IS_FIREBASE" height="24" width="24"
|
|
65
|
+
style="border-radius:50%;object-fit: cover;vertical-align: middle;"
|
|
66
|
+
src="https://firebasestorage.googleapis.com/v0/b/{{storageBucket}}/o/profiles%2F{{item.id}}%2Fphoto.jpg?alt=media"
|
|
67
|
+
alt="" onerror="this.src='assets/images/default-avatar-x-select.png'">
|
|
68
|
+
|
|
69
|
+
<!-- ---------------------------------------- -->
|
|
70
|
+
<!-- Usecase Native -->
|
|
71
|
+
<!-- ---------------------------------------- -->
|
|
72
|
+
<img *ngIf="item.requestertype === 'agent' && !UPLOAD_ENGINE_IS_FIREBASE" height="24" width="24"
|
|
73
|
+
style="border-radius:50%;object-fit: cover;vertical-align: middle;"
|
|
74
|
+
src="{{baseUrl}}images?path=uploads%2Fusers%2F{{item.id}}%2Fimages%2Fthumbnails_200_200-photo.jpg" alt=""
|
|
75
|
+
onerror="this.src='assets/images/default-avatar-x-select.png'">
|
|
76
|
+
|
|
77
|
+
<img *ngIf="item.requestertype === 'lead'" height="24" width="24"
|
|
78
|
+
style="border-radius:50%; object-fit: cover;vertical-align: middle;"
|
|
79
|
+
src="assets/images/default-avatar-x-select.png" alt="">
|
|
80
|
+
<span style="font-weight: 400;">
|
|
81
|
+
{{ item.name }}
|
|
82
|
+
</span>
|
|
83
|
+
<span class="requester-role-or-type">
|
|
84
|
+
({{item.role}})
|
|
85
|
+
</span>
|
|
86
|
+
<br />
|
|
87
|
+
<small style="font-weight:400;font-size: 13px; margin-left: 28px; position: relative;top: -3px;">
|
|
88
|
+
{{ item.email }}
|
|
89
|
+
</small>
|
|
90
|
+
</ng-template>
|
|
91
|
+
|
|
92
|
+
<ng-template ng-footer-tmp>
|
|
93
|
+
<div style="cursor:pointer" (click)="presentModalAddNewRequester()">
|
|
94
|
+
<span class="material-icons" style="vertical-align: middle; color:#0f62ff"> add </span>
|
|
95
|
+
<span style="color:#0f62ff">
|
|
96
|
+
{{'AddRequester' | translate}}
|
|
97
|
+
</span>
|
|
98
|
+
</div>
|
|
99
|
+
</ng-template>
|
|
100
|
+
|
|
101
|
+
</ng-select>
|
|
102
|
+
</ion-col>
|
|
103
|
+
|
|
104
|
+
<ion-col size="12">
|
|
105
|
+
<ion-label class="custom-create-ticket-label" position="stacked">{{ 'Subject' | translate }} *</ion-label>
|
|
106
|
+
<ion-input [(ngModel)]="ticket_subject" type="text" class="custom-ion-input"></ion-input>
|
|
107
|
+
</ion-col>
|
|
108
|
+
|
|
109
|
+
<ion-col size="12">
|
|
110
|
+
<ion-label class="custom-create-ticket-label">{{ 'SelectAssignee' | translate }}</ion-label>
|
|
111
|
+
<ng-select class="create-ticket-custom-select" name="assignee" [(ngModel)]="assignee_id" [searchable]="true" [clearable]="false"
|
|
112
|
+
placeholder="{{ 'SelectAssignee' | translate }}" (change)="selectedAssignee()" [loading]=loadingAssignee
|
|
113
|
+
loadingText='Loading...'>
|
|
114
|
+
<ng-option *ngFor="let assignee of projectUserBotsAndDeptsArray" [value]="assignee.id">
|
|
115
|
+
{{assignee.name}}
|
|
116
|
+
</ng-option>
|
|
117
|
+
</ng-select>
|
|
118
|
+
</ion-col>
|
|
119
|
+
|
|
120
|
+
<ion-col size="12">
|
|
121
|
+
<ion-label class="custom-create-ticket-label">{{ 'Priority' | translate }}</ion-label>
|
|
122
|
+
<ng-select class="create-ticket-custom-select" [items]="priority" bindLabel="name" bindValue="name" [clearable]="false" [hideSelected]="true"
|
|
123
|
+
[(ngModel)]="selectedPriority" (change)="onChangeSelectedPriority(selectedPriority)">
|
|
124
|
+
<ng-template ng-label-tmp let-item="item">
|
|
125
|
+
<img style="width: 15px;height: 15px; vertical-align: middle;" height="15" width="15" [src]="item.avatar" />
|
|
126
|
+
{{item.name | translate}}
|
|
127
|
+
</ng-template>
|
|
128
|
+
<ng-template ng-option-tmp let-item="item" let-index="index">
|
|
129
|
+
<img style="width: 15px;height: 15px;vertical-align: middle;" height="15" width="15" [src]="item.avatar" />
|
|
130
|
+
{{item.name | translate }}
|
|
131
|
+
</ng-template>
|
|
132
|
+
</ng-select>
|
|
133
|
+
|
|
134
|
+
</ion-col>
|
|
135
|
+
|
|
136
|
+
<ion-col size="12">
|
|
137
|
+
<ion-label class="custom-create-ticket-label">{{ 'Message' | translate }} *</ion-label>
|
|
138
|
+
<ion-textarea [(ngModel)]="ticket_message" type="text" class="custom-ion-textarea" rows="2" placeholder=""></ion-textarea>
|
|
139
|
+
</ion-col>
|
|
140
|
+
<!-- expand="block" -->
|
|
141
|
+
<ion-col size="12" style="text-align: center;">
|
|
142
|
+
|
|
143
|
+
<!-- <ion-icon *ngIf="showSpinnerCreateTicket === false" style="font-size: 1.9em;" slot="start" name="checkmark-outline"></ion-icon> -->
|
|
144
|
+
<ion-button style="min-width: 153px;" color="primary" class="submit-btn" type="submit" (click)="createTicket()" [disabled]="ticket_subject === undefined || ticket_message === undefined || ticket_subject?.length === 0 || ticket_message?.length === 0">
|
|
145
|
+
<ion-icon *ngIf="showSpinnerCreateTicket === false" style="font-size: 1.9em;" slot="start" name="add-circle-outline"></ion-icon>
|
|
146
|
+
<ion-spinner *ngIf="showSpinnerCreateTicket === true" style="color: #fff; margin: 0px 0.3em 0px -0.3em;" name="bubbles" duration="2" ></ion-spinner>
|
|
147
|
+
{{'CreateTicket' | translate}}
|
|
148
|
+
</ion-button>
|
|
149
|
+
</ion-col>
|
|
150
|
+
|
|
151
|
+
</ion-row>
|
|
152
|
+
<!-- class="ion-align-items-center" -->
|
|
153
|
+
<ion-row style="text-align: center;" *ngIf="ticketCreationCompleted === true">
|
|
154
|
+
<ion-col size="12">
|
|
155
|
+
<ion-icon style="font-size: 3em;" color="success" name="checkmark-outline"></ion-icon>
|
|
156
|
+
</ion-col>
|
|
157
|
+
<ion-col size="12">
|
|
158
|
+
<label> {{'TicketSuccessfullyCreated' | translate }}</label>
|
|
159
|
+
</ion-col>
|
|
160
|
+
<ion-col size="12" class="ion-padding-vertical">
|
|
161
|
+
<ion-button color="success" class="submit-btn" type="submit" (click)="closeModalCreateTicketModal()">
|
|
162
|
+
{{'Continue' | translate }}
|
|
163
|
+
</ion-button>
|
|
164
|
+
</ion-col>
|
|
165
|
+
|
|
166
|
+
</ion-row>
|
|
167
|
+
|
|
168
|
+
</ion-grid>
|
|
169
|
+
|
|
170
|
+
</ion-content>
|
|
171
|
+
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
.requester-role-or-type {
|
|
2
|
+
font-size: 12px;
|
|
3
|
+
font-weight: 400;
|
|
4
|
+
color: rgba(0, 0, 0, 0.54);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.custom-ion-input {
|
|
8
|
+
border-radius: 4px;
|
|
9
|
+
border: 1px solid #ccc;
|
|
10
|
+
height: 36px;
|
|
11
|
+
color: #333;
|
|
12
|
+
background-color: #fff;
|
|
13
|
+
margin-top: 5px;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.custom-ion-textarea {
|
|
17
|
+
border-radius: 4px;
|
|
18
|
+
border: 1px solid #ccc;
|
|
19
|
+
color: #333;
|
|
20
|
+
background-color: #fff;
|
|
21
|
+
margin-top: 5px !important;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.custom-create-ticket-label {
|
|
25
|
+
font-size: 14px;
|
|
26
|
+
color: #7695a5;
|
|
27
|
+
font-weight: 500;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.custom-create-ticket-label-to-left {
|
|
31
|
+
font-size: 14px;
|
|
32
|
+
color: #0f62ff;
|
|
33
|
+
font-weight: 500;
|
|
34
|
+
float: right;
|
|
35
|
+
cursor: pointer;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.open-requester-details-disable {
|
|
39
|
+
// cursor: not-allowed;
|
|
40
|
+
// opacity: 0.5;
|
|
41
|
+
display: none;
|
|
42
|
+
}
|
|
43
|
+
.ion-grid-custom-padding {
|
|
44
|
+
padding: 5px 25px;
|
|
45
|
+
height: 100%;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
.center-content {
|
|
49
|
+
display: flex;
|
|
50
|
+
align-items: center;
|
|
51
|
+
justify-content: center;
|
|
52
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
import { IonicModule } from '@ionic/angular';
|
|
3
|
+
|
|
4
|
+
import { CreateTicketPage } from './create-ticket.page';
|
|
5
|
+
|
|
6
|
+
describe('CreateTicketPage', () => {
|
|
7
|
+
let component: CreateTicketPage;
|
|
8
|
+
let fixture: ComponentFixture<CreateTicketPage>;
|
|
9
|
+
|
|
10
|
+
beforeEach(async(() => {
|
|
11
|
+
TestBed.configureTestingModule({
|
|
12
|
+
declarations: [ CreateTicketPage ],
|
|
13
|
+
imports: [IonicModule.forRoot()]
|
|
14
|
+
}).compileComponents();
|
|
15
|
+
|
|
16
|
+
fixture = TestBed.createComponent(CreateTicketPage);
|
|
17
|
+
component = fixture.componentInstance;
|
|
18
|
+
fixture.detectChanges();
|
|
19
|
+
}));
|
|
20
|
+
|
|
21
|
+
it('should create', () => {
|
|
22
|
+
expect(component).toBeTruthy();
|
|
23
|
+
});
|
|
24
|
+
});
|