ngx-firebase-cms
Version:
Angular Content Management System using Google Firebase (Authentication, Storage & Firestore)
351 lines • 33.5 kB
JavaScript
/**
* @fileoverview added by tsickle
* @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
import { Component, ElementRef, ViewChild, HostListener } from '@angular/core';
import { UnsubscriptionService } from '../../service/unsubscription.service';
import { FormBuilder, FormControl, Validators } from '@angular/forms';
import { AngularFireAuth } from '@angular/fire/auth';
import { NzMessageService, NzNotificationService } from 'ng-zorro-antd';
import { AngularFireStorage } from '@angular/fire/storage';
import { AuthService } from '../../service/auth.service';
import { HelperService } from '../../service/helper.service';
import * as firebase from 'firebase/app';
import { of } from 'rxjs';
import { AngularFirestore } from '@angular/fire/firestore';
export class ProfileComponent {
/**
* @param {?} unsubscription
* @param {?} afAuth
* @param {?} afs
* @param {?} message
* @param {?} storage
* @param {?} auth
* @param {?} fb
* @param {?} notification
* @param {?} helper
*/
constructor(unsubscription, afAuth, afs, message, storage, auth, fb, notification, helper) {
this.unsubscription = unsubscription;
this.afAuth = afAuth;
this.afs = afs;
this.message = message;
this.storage = storage;
this.auth = auth;
this.fb = fb;
this.notification = notification;
this.helper = helper;
this.titlebar = {
title: "Profile",
description: "Edit your profile",
breadcrumbs: [
{
title: "Profile",
icon: 'team'
}
]
};
this.showChangePassword = false;
this.isLoading = false;
this.showDisplayName = false;
this.profileURL = null;
this.beforeUpload = (/**
* @param {?} file
* @return {?}
*/
(file) => {
if (file['type'] != "image/jpeg") {
this.message.error("File type should be JPEG");
return false;
}
else if (file['size'] / 1024 / 1024 > 1) {
this.message.error("File size should be less than 1 Mb");
return false;
}
else {
return true;
}
});
this.uploadProfilePic = (/**
* @param {?} item
* @return {?}
*/
(item) => {
this.message.success(`File is uploading`);
/** @type {?} */
let timestamp = new Date().valueOf();
/** @type {?} */
let filePath = `/profile/${timestamp}.jpeg`;
/** @type {?} */
let file = item['file'];
/** @type {?} */
const task = this.storage.upload(filePath, file)
.then((/**
* @param {?} res
* @return {?}
*/
res => {
return this.storage.ref(filePath).getDownloadURL().toPromise();
}))
.then((/**
* @param {?} res
* @return {?}
*/
res => {
return this.afs.collection("users").doc(this.auth.uid).update({
"profileURL": res,
"uploadTime": firebase.firestore.FieldValue.serverTimestamp()
});
}))
.then((/**
* @param {?} res
* @return {?}
*/
res => {
this.auth.log(`changed profile pic ${timestamp}.jpeg`);
this.message.success("File Uploaded");
})).catch((/**
* @param {?} err
* @return {?}
*/
err => {
this.message.error(err);
}));
return of().subscribe((/**
* @param {?} event
* @return {?}
*/
(event) => {
if (event['percent'] != 100) {
item.onProgress(event, item.file);
}
else {
item.onSuccess(event['body'], item.file, event);
}
}), (/**
* @param {?} err
* @return {?}
*/
(err) => {
item.onError(err, item.file);
}));
});
}
/**
* @return {?}
*/
ngOnInit() {
this.sub = this.auth.user$.subscribe((/**
* @param {?} res
* @return {?}
*/
res => {
this.profileURL = res.profileURL;
}), (/**
* @param {?} err
* @return {?}
*/
err => { }));
this.initForm();
}
/**
* @return {?}
*/
ngOnDestroy() {
this.sub.unsubscribe();
}
/**
* @return {?}
*/
initForm() {
this.passwordForm = this.fb.group({
"previousPassword": new FormControl({ value: "", disabled: false }, [Validators.required]),
"newPassword": new FormControl({ value: "", disabled: false }, [Validators.required]),
});
this.displayNameForm = this.fb.group({
"displayName": new FormControl({ "value": this.auth.displayName, disabled: false }, [Validators.required])
});
}
/**
* @return {?}
*/
changePassword() {
if (typeof this.passwordForm.value["newPassword"] == "string")
this.passwordForm.controls["newPassword"].setValue(this.passwordForm.value["newPassword"].trim());
if (this.passwordForm.valid && !this.isLoading) {
this.isLoading = true;
this.afAuth.auth.signInWithEmailAndPassword(this.auth.email, this.passwordForm.value['previousPassword']).then((/**
* @param {?} res
* @return {?}
*/
res => {
/** @type {?} */
let user = this.afAuth.auth.currentUser;
return user.updatePassword(this.passwordForm.value["newPassword"]);
}))
.then((/**
* @param {?} res
* @return {?}
*/
res => {
this.auth.log(` updated the password`);
this.message.success(`Change the password`);
this.showChangePassword = !this.showChangePassword;
}))
.catch((/**
* @param {?} err
* @return {?}
*/
err => {
this.message.error(err);
}));
}
else {
this.passwordForm.controls["newPassword"].markAsDirty();
}
}
/**
* @return {?}
*/
changeDisplayName() {
if (typeof this.displayNameForm.value["displayName"] == "string")
this.displayNameForm.controls["displayName"].setValue(this.displayNameForm.value["displayName"].trim());
if (this.displayNameForm.valid && !this.isLoading) {
this.isLoading = true;
this.afs.collection("users").doc(this.auth.uid).update({
"displayName": this.displayNameForm.value["displayName"],
"uploadTime": firebase.firestore.FieldValue.serverTimestamp()
}).then((/**
* @param {?} res
* @return {?}
*/
res => {
this.isLoading = false;
this.showDisplayName = !this.showDisplayName;
}));
}
else {
this.displayNameForm.controls["displayName"].markAsDirty();
}
}
/**
* @return {?}
*/
getProfilePic() {
return (this.profileURL) ? { 'background-image': 'url(\'' + this.profileURL + '\')' } : {};
}
/**
* @param {?} e
* @return {?}
*/
keyboardEvent(e) {
if (this.showChangePassword && e.key == 'Escape') {
this.notification.blank("ESC", "Escape modal");
this.showChangePassword = false;
}
if (this.showDisplayName && e.key == 'Escape') {
this.notification.blank("ESC", "Escape modal");
this.showDisplayName = false;
}
if (this.showChangePassword) {
if (e.ctrlKey && e.key == 'Enter') {
this.notification.blank("⌃ ENTER", "Form Submission");
this.changePassword();
}
}
if (this.showDisplayName && e.ctrlKey && e.key == 'Enter') {
this.notification.blank("⌃ ENTER", "Form Submission");
this.changeDisplayName();
}
}
}
ProfileComponent.decorators = [
{ type: Component, args: [{
selector: 'aq-profile',
template: "<aq-title-bar [data]=\"titlebar\"></aq-title-bar>\n\n<div class=\"container\">\n <h3>{{ (auth.user$ | async)?.displayName }}</h3>\n <p>Email: {{ (auth.user$ | async)?.email }}</p>\n <p>Roles: {{ (auth.user$ | async)?.roles }}</p>\n <p>Created on: {{ (auth.user$ | async)?.createdTime.toDate() | date: 'medium' }}</p>\n <p>Last login: {{ auth.lastLogin | date: 'medium' }}</p>\n\n <button class=\"m-r-10\" nz-tooltip nzTitle=\"Change Password\" nz-button (click)=\"showChangePassword=true\">\n <i nz-icon type=\"security-scan\" theme=\"outline\"></i> Password\n </button>\n\n <button class=\"m-r-10\" nz-tooltip nzTitle=\"Change Display Name\" nz-button (click)=\"showDisplayName=true\">\n <i nz-icon type=\"font-colors\" theme=\"outline\"></i> Display Name\n </button>\n\n <nz-upload class=\"m-r-10\" [nzBeforeUpload]=\"beforeUpload\" [nzCustomRequest]=\"uploadProfilePic\"\n [nzShowUploadList]=\"false\">\n <button #uploadButton nz-tooltip nzTitle=\"Change Profile Image\" nz-button>\n <i nz-icon type=\"picture\" theme=\"outline\"></i> Profile Image\n </button>\n </nz-upload>\n</div>\n\n<nz-drawer nzWidth=\"100%\" [nzVisible]=\"showChangePassword\" nzTitle=\"Change Password\" (nzOnClose)=\"showChangePassword = !showChangePassword\">\n <form nz-form [formGroup]=\"passwordForm\" (ngSubmit)=\"changePassword()\">\n <nz-form-item>\n <nz-form-control>\n <label>Previous Password</label>\n <input type=\"password\" nz-input formControlName=\"previousPassword\" placeholder=\"Previous Password\"\n autocomplete=\"password\" autofocus>\n <nz-form-explain\n *ngIf=\"passwordForm.get('previousPassword').dirty && passwordForm.get('previousPassword').errors\">\n Please input\n your previous password!</nz-form-explain>\n </nz-form-control>\n </nz-form-item>\n <nz-form-item>\n <nz-form-control>\n <label>New Password</label>\n <input type=\"password\" nz-input formControlName=\"newPassword\" placeholder=\"New Password\" autocomplete=\"password\" autofocus>\n <nz-form-explain\n *ngIf=\"passwordForm.get('newPassword').dirty && passwordForm.get('newPassword').errors\">Please input\n your new\n password!</nz-form-explain>\n </nz-form-control>\n </nz-form-item>\n </form>\n <div class=\"footer\">\n <button type=\"button\" (click)=\"changePassword()\" class=\"ant-btn ant-btn-primary\">Submit </button>\n <button type=\"button\" (click)=\"showChangePassword = !showChangePassword\" class=\"ant-btn\">Cancel </button>\n </div>\n</nz-drawer>\n\n<nz-drawer nzWidth=\"100%\" [nzVisible]=\"showDisplayName\" nzTitle=\"Change Display Name\" (nzOnClose)=\"showDisplayName = !showDisplayName\">\n <form nz-form [formGroup]=\"displayNameForm\" (ngSubmit)=\"changeDisplayName()\">\n <nz-form-item>\n <nz-form-control>\n <label>Your Display Name</label>\n <input type=\"text\" nz-input formControlName=\"displayName\" placeholder=\"Please enter your display name\"\n autocomplete=\"displayName\" autofocus>\n <nz-form-explain\n *ngIf=\"displayNameForm.get('displayName').dirty && displayNameForm.get('displayName').errors\">Please\n input\n your Display Name!</nz-form-explain>\n </nz-form-control>\n </nz-form-item>\n </form>\n <div class=\"footer\">\n <button type=\"button\" (click)=\"changeDisplayName()\" class=\"ant-btn ant-btn-primary\">Submit </button>\n <button type=\"button\" (click)=\"showDisplayName = !showDisplayName\" class=\"ant-btn\">Cancel </button>\n </div>\n</nz-drawer>\n",
styles: [".img-rounded{border-radius:50%;width:80%;position:relative}.img-rounded:hover{opacity:1}.footer{position:absolute;bottom:0;width:100%;border-top:1px solid #e8e8e8;padding:10px 16px;left:0;z-index:9999;background:#fff}.footer button{margin-left:10px}.m-r-10{margin-right:10px}.w-200{width:200px}.user-profile{width:200px;height:200px;background:0 0/cover #efefef;border-radius:50%}"]
}] }
];
/** @nocollapse */
ProfileComponent.ctorParameters = () => [
{ type: UnsubscriptionService },
{ type: AngularFireAuth },
{ type: AngularFirestore },
{ type: NzMessageService },
{ type: AngularFireStorage },
{ type: AuthService },
{ type: FormBuilder },
{ type: NzNotificationService },
{ type: HelperService }
];
ProfileComponent.propDecorators = {
uploadButton: [{ type: ViewChild, args: ['uploadButton',] }],
keyboardEvent: [{ type: HostListener, args: ['document:keydown', ['$event'],] }]
};
if (false) {
/** @type {?} */
ProfileComponent.prototype.uploadButton;
/** @type {?} */
ProfileComponent.prototype.titlebar;
/** @type {?} */
ProfileComponent.prototype.showChangePassword;
/** @type {?} */
ProfileComponent.prototype.passwordForm;
/** @type {?} */
ProfileComponent.prototype.displayNameForm;
/** @type {?} */
ProfileComponent.prototype.isLoading;
/** @type {?} */
ProfileComponent.prototype.showDisplayName;
/** @type {?} */
ProfileComponent.prototype.profileURL;
/** @type {?} */
ProfileComponent.prototype.sub;
/** @type {?} */
ProfileComponent.prototype.beforeUpload;
/** @type {?} */
ProfileComponent.prototype.uploadProfilePic;
/**
* @type {?}
* @private
*/
ProfileComponent.prototype.unsubscription;
/**
* @type {?}
* @private
*/
ProfileComponent.prototype.afAuth;
/**
* @type {?}
* @private
*/
ProfileComponent.prototype.afs;
/**
* @type {?}
* @private
*/
ProfileComponent.prototype.message;
/**
* @type {?}
* @private
*/
ProfileComponent.prototype.storage;
/** @type {?} */
ProfileComponent.prototype.auth;
/**
* @type {?}
* @private
*/
ProfileComponent.prototype.fb;
/**
* @type {?}
* @private
*/
ProfileComponent.prototype.notification;
/**
* @type {?}
* @private
*/
ProfileComponent.prototype.helper;
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZmlsZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290Ijoibmc6Ly9uZ3gtZmlyZWJhc2UtY21zLyIsInNvdXJjZXMiOlsibGliL2NvbXBvbmVudC9wcm9maWxlL3Byb2ZpbGUuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFVLFVBQVUsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBRXZGLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxNQUFNLHNDQUFzQyxDQUFDO0FBQzdFLE9BQU8sRUFBYSxXQUFXLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2pGLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUscUJBQXFCLEVBQTZCLE1BQU0sZUFBZSxDQUFDO0FBQ25HLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQzNELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDN0QsT0FBTyxLQUFLLFFBQVEsTUFBTSxjQUFjLENBQUM7QUFFekMsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMxQixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQVEzRCxNQUFNLE9BQU8sZ0JBQWdCOzs7Ozs7Ozs7Ozs7SUFzQjNCLFlBQ1UsY0FBcUMsRUFDckMsTUFBdUIsRUFDdkIsR0FBcUIsRUFDckIsT0FBeUIsRUFDekIsT0FBMkIsRUFDNUIsSUFBaUIsRUFDaEIsRUFBZSxFQUNmLFlBQW1DLEVBQ25DLE1BQXFCO1FBUnJCLG1CQUFjLEdBQWQsY0FBYyxDQUF1QjtRQUNyQyxXQUFNLEdBQU4sTUFBTSxDQUFpQjtRQUN2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LENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFBO2dCQUNyRCxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUE7YUFDdEI7U0FDRjtRQUVELElBQUksSUFBSSxDQUFDLGVBQWUsSUFBSSxDQUFDLENBQUMsT0FBTyxJQUFJLENBQUMsQ0FBQyxHQUFHLElBQUksT0FBTyxFQUFFO1lBQ3pELElBQUksQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQyxDQUFBO1lBQ3JELElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFBO1NBQ3pCO0lBQ0gsQ0FBQzs7O1lBeEtGLFNBQVMsU0FBQztnQkFDVCxRQUFRLEVBQUUsWUFBWTtnQkFDdEIsdTRIQUF1Qzs7YUFFeEM7Ozs7WUFqQlEscUJBQXFCO1lBRXJCLGVBQWU7WUFRZixnQkFBZ0I7WUFQaEIsZ0JBQWdCO1lBQ2hCLGtCQUFrQjtZQUNsQixXQUFXO1lBSkEsV0FBVztZQUVKLHFCQUFxQjtZQUd2QyxhQUFhOzs7MkJBYW5CLFNBQVMsU0FBQyxjQUFjOzRCQTJJeEIsWUFBWSxTQUFDLGtCQUFrQixFQUFFLENBQUMsUUFBUSxDQUFDOzs7O0lBM0k1Qyx3Q0FBbUQ7O0lBRW5ELG9DQVNDOztJQUVELDhDQUEwQjs7SUFDMUIsd0NBQXVCOztJQUN2QiwyQ0FBMEI7O0lBQzFCLHFDQUFpQjs7SUFDakIsMkNBQXVCOztJQUN2QixzQ0FBaUI7O0lBQ2pCLCtCQUFHOztJQXdFSCx3Q0FVQzs7SUFFRCw0Q0E4QkM7Ozs7O0lBL0dDLDBDQUE2Qzs7Ozs7SUFDN0Msa0NBQStCOzs7OztJQUMvQiwrQkFBNkI7Ozs7O0lBQzdCLG1DQUFpQzs7Ozs7SUFDakMsbUNBQW1DOztJQUNuQyxnQ0FBd0I7Ozs7O0lBQ3hCLDhCQUF1Qjs7Ozs7SUFDdkIsd0NBQTJDOzs7OztJQUMzQyxrQ0FBNkIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgRWxlbWVudFJlZiwgVmlld0NoaWxkLCBIb3N0TGlzdGVuZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IEJyZWFkY3J1bWIgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2UvYnJlYWRjcnVtYic7XG5pbXBvcnQgeyBVbnN1YnNjcmlwdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlL3Vuc3Vic2NyaXB0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgRm9ybUdyb3VwLCBGb3JtQnVpbGRlciwgRm9ybUNvbnRyb2wsIFZhbGlkYXRvcnMgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZUF1dGggfSBmcm9tICdAYW5ndWxhci9maXJlL2F1dGgnO1xuaW1wb3J0IHsgTnpNZXNzYWdlU2VydmljZSwgTnpOb3RpZmljYXRpb25TZXJ2aWNlLCBVcGxvYWRYSFJBcmdzLCBVcGxvYWRGaWxlIH0gZnJvbSAnbmctem9ycm8tYW50ZCc7XG5pbXBvcnQgeyBBbmd1bGFyRmlyZVN0b3JhZ2UgfSBmcm9tICdAYW5ndWxhci9maXJlL3N0b3JhZ2UnO1xuaW1wb3J0IHsgQXV0aFNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlL2F1dGguc2VydmljZSc7XG5pbXBvcnQgeyBIZWxwZXJTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZS9oZWxwZXIuc2VydmljZSc7XG5pbXBvcnQgKiBhcyBmaXJlYmFzZSBmcm9tICdmaXJlYmFzZS9hcHAnO1xuaW1wb3J0IHsgSHR0cEV2ZW50IH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uL2h0dHAnO1xuaW1wb3J0IHsgb2YgfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEFuZ3VsYXJGaXJlc3RvcmUgfSBmcm9tICdAYW5ndWxhci9maXJlL2ZpcmVzdG9yZSc7XG5pbXBvcnQgeyBUaXRsZWJhciB9IGZyb20gJy4uLy4uL2ludGVyZmFjZS90aXRsZWJhcic7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2FxLXByb2ZpbGUnLFxuICB0ZW1wbGF0ZVVybDogJy4vcHJvZmlsZS5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3Byb2ZpbGUuY29tcG9uZW50LmNzcyddXG59KVxuZXhwb3J0IGNsYXNzIFByb2ZpbGVDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQge1xuICBAVmlld0NoaWxkKCd1cGxvYWRCdXR0b24nKSB1cGxvYWRCdXR0b246IEVsZW1lbnRSZWZcblxuICB0aXRsZWJhcjogVGl0bGViYXIgPSB7XG4gICAgdGl0bGU6IFwiUHJvZmlsZVwiLFxuICAgIGRlc2NyaXB0aW9uOiBcIkVkaXQgeW91ciBwcm9maWxlXCIsXG4gICAgYnJlYWRjcnVtYnM6IFtcbiAgICAgIHtcbiAgICAgICAgdGl0bGU6IFwiUHJvZmlsZVwiLFxuICAgICAgICBpY29uOiAndGVhbSdcbiAgICAgIH1cbiAgICBdXG4gIH1cblxuICBzaG93Q2hhbmdlUGFzc3dvcmQgPSBmYWxzZVxuICBwYXNzd29yZEZvcm06IEZvcm1Hcm91cFxuICBkaXNwbGF5TmFtZUZvcm06IEZvcm1Hcm91cFxuICBpc0xvYWRpbmcgPSBmYWxzZVxuICBzaG93RGlzcGxheU5hbWUgPSBmYWxzZVxuICBwcm9maWxlVVJMID0gbnVsbFxuICBzdWJcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwcml2YXRlIHVuc3Vic2NyaXB0aW9uOiBVbnN1YnNjcmlwdGlvblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBhZkF1dGg6IEFuZ3VsYXJGaXJlQXV0aCxcbiAgICBwcml2YXRlIGFmczogQW5ndWxhckZpcmVzdG9yZSxcbiAgICBwcml2YXRlIG1lc3NhZ2U6IE56TWVzc2FnZVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBzdG9yYWdlOiBBbmd1bGFyRmlyZVN0b3JhZ2UsXG4gICAgcHVibGljIGF1dGg6IEF1dGhTZXJ2aWNlLFxuICAgIHByaXZhdGUgZmI6IEZvcm1CdWlsZGVyLFxuICAgIHByaXZhdGUgbm90aWZpY2F0aW9uOiBOek5vdGlmaWNhdGlvblNlcnZpY2UsXG4gICAgcHJpdmF0ZSBoZWxwZXI6IEhlbHBlclNlcnZpY2VcbiAgKSB7IH1cblxuICBuZ09uSW5pdCgpIHtcbiAgICB0aGlzLnN1YiA9IHRoaXMuYXV0aC51c2VyJC5zdWJzY3JpYmUocmVzID0+IHtcbiAgICAgIHRoaXMucHJvZmlsZVVSTCA9IHJlcy5wcm9maWxlVVJMXG4gICAgfSwgZXJyID0+IHt9KVxuICAgIHRoaXMuaW5pdEZvcm0oKVxuICB9XG5cbiAgbmdPbkRlc3Ryb3koKSB7XG4gICAgdGhpcy5zdWIudW5zdWJzY3JpYmUoKVxuICB9XG5cbiAgaW5pdEZvcm0oKSB7XG4gICAgdGhpcy5wYXNzd29yZEZvcm0gPSB0aGlzLmZiLmdyb3VwKHtcbiAgICAgIFwicHJldmlvdXNQYXNzd29yZFwiOiBuZXcgRm9ybUNvbnRyb2woeyB2YWx1ZTogXCJcIiwgZGlzYWJsZWQ6IGZhbHNlIH0sIFtWYWxpZGF0b3JzLnJlcXVpcmVkXSksXG4gICAgICBcIm5ld1Bhc3N3b3JkXCI6IG5ldyBGb3JtQ29udHJvbCh7IHZhbHVlOiBcIlwiLCBkaXNhYmxlZDogZmFsc2UgfSwgW1ZhbGlkYXRvcnMucmVxdWlyZWRdKSxcbiAgICB9KVxuICAgIHRoaXMuZGlzcGxheU5hbWVGb3JtID0gdGhpcy5mYi5ncm91cCh7XG4gICAgICBcImRpc3BsYXlOYW1lXCI6IG5ldyBGb3JtQ29udHJvbCh7IFwidmFsdWVcIjogdGhpcy5hdXRoLmRpc3BsYXlOYW1lLCBkaXNhYmxlZDogZmFsc2UgfSwgW1ZhbGlkYXRvcnMucmVxdWlyZWRdKVxuICAgIH0pXG4gIH1cblxuICBjaGFuZ2VQYXNzd29yZCgpIHtcbiAgICBpZiAodHlwZW9mIHRoaXMucGFzc3dvcmRGb3JtLnZhbHVlW1wibmV3UGFzc3dvcmRcIl0gPT0gXCJzdHJpbmdcIikgdGhpcy5wYXNzd29yZEZvcm0uY29udHJvbHNbXCJuZXdQYXNzd29yZFwiXS5zZXRWYWx1ZSh0aGlzLnBhc3N3b3JkRm9ybS52YWx1ZVtcIm5ld1Bhc3N3b3JkXCJdLnRyaW0oKSlcbiAgICBpZiAodGhpcy5wYXNzd29yZEZvcm0udmFsaWQgJiYgIXRoaXMuaXNMb2FkaW5nKSB7XG4gICAgICB0aGlzLmlzTG9hZGluZyA9IHRydWVcbiAgICAgIHRoaXMuYWZBdXRoLmF1dGguc2lnbkluV2l0aEVtYWlsQW5kUGFzc3dvcmQodGhpcy5hdXRoLmVtYWlsLCB0aGlzLnBhc3N3b3JkRm9ybS52YWx1ZVsncHJldmlvdXNQYXNzd29yZCddKS50aGVuKHJlcyA9PiB7XG4gICAgICAgIGxldCB1c2VyID0gdGhpcy5hZkF1dGguYXV0aC5jdXJyZW50VXNlclxuICAgICAgICByZXR1cm4gdXNlci51cGRhdGVQYXNzd29yZCh0aGlzLnBhc3N3b3JkRm9ybS52YWx1ZVtcIm5ld1Bhc3N3b3JkXCJdKVxuICAgICAgfSlcbiAgICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgICB0aGlzLmF1dGgubG9nKGAgdXBkYXRlZCB0aGUgcGFzc3dvcmRgKVxuICAgICAgICAgIHRoaXMubWVzc2FnZS5zdWNjZXNzKGBDaGFuZ2UgdGhlIHBhc3N3b3JkYClcbiAgICAgICAgICB0aGlzLnNob3dDaGFuZ2VQYXNzd29yZCA9ICF0aGlzLnNob3dDaGFuZ2VQYXNzd29yZFxuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgICB0aGlzLm1lc3NhZ2UuZXJyb3IoZXJyKVxuICAgICAgICB9KVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnBhc3N3b3JkRm9ybS5jb250cm9sc1tcIm5ld1Bhc3N3b3JkXCJdLm1hcmtBc0RpcnR5KClcbiAgICB9XG4gIH1cblxuICBjaGFuZ2VEaXNwbGF5TmFtZSgpIHtcbiAgICBpZiAodHlwZW9mIHRoaXMuZGlzcGxheU5hbWVGb3JtLnZhbHVlW1wiZGlzcGxheU5hbWVcIl0gPT0gXCJzdHJpbmdcIikgdGhpcy5kaXNwbGF5TmFtZUZvcm0uY29udHJvbHNbXCJkaXNwbGF5TmFtZVwiXS5zZXRWYWx1ZSh0aGlzLmRpc3BsYXlOYW1lRm9ybS52YWx1ZVtcImRpc3BsYXlOYW1lXCJdLnRyaW0oKSlcbiAgICBpZiAodGhpcy5kaXNwbGF5TmFtZUZvcm0udmFsaWQgJiYgIXRoaXMuaXNMb2FkaW5nKSB7XG4gICAgICB0aGlzLmlzTG9hZGluZyA9IHRydWVcbiAgICAgIHRoaXMuYWZzLmNvbGxlY3Rpb24oXCJ1c2Vyc1wiKS5kb2ModGhpcy5hdXRoLnVpZCkudXBkYXRlKHtcbiAgICAgICAgXCJkaXNwbGF5TmFtZVwiOiB0aGlzLmRpc3BsYXlOYW1lRm9ybS52YWx1ZVtcImRpc3BsYXlOYW1lXCJdLFxuICAgICAgICBcInVwbG9hZFRpbWVcIjogZmlyZWJhc2UuZmlyZXN0b3JlLkZpZWxkVmFsdWUuc2VydmVyVGltZXN0YW1wKClcbiAgICAgIH0pLnRoZW4ocmVzID0+IHtcbiAgICAgICAgdGhpcy5pc0xvYWRpbmcgPSBmYWxzZVxuICAgICAgICB0aGlzLnNob3dEaXNwbGF5TmFtZSA9ICF0aGlzLnNob3dEaXNwbGF5TmFtZVxuICAgICAgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kaXNwbGF5TmFtZUZvcm0uY29udHJvbHNbXCJkaXNwbGF5TmFtZVwiXS5tYXJrQXNEaXJ0eSgpXG4gICAgfVxuICB9XG5cbiAgYmVmb3JlVXBsb2FkID0gKGZpbGU6IFVwbG9hZEZpbGUpOiBib29sZWFuID0+IHtcbiAgICBpZiAoZmlsZVsndHlwZSddICE9IFwiaW1hZ2UvanBlZ1wiKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UuZXJyb3IoXCJGaWxlIHR5cGUgc2hvdWxkIGJlIEpQRUdcIilcbiAgICAgIHJldHVybiBmYWxzZVxuICAgIH0gZWxzZSBpZiAoZmlsZVsnc2l6ZSddIC8gMTAyNCAvIDEwMjQgPiAxKSB7XG4gICAgICB0aGlzLm1lc3NhZ2UuZXJyb3IoXCJGaWxlIHNpemUgc2hvdWxkIGJlIGxlc3MgdGhhbiAxIE1iXCIpXG4gICAgICByZXR1cm4gZmFsc2VcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRydWVcbiAgICB9XG4gIH1cblxuICB1cGxvYWRQcm9maWxlUGljID0gKGl0ZW06IFVwbG9hZFhIUkFyZ3MpID0+IHtcbiAgICB0aGlzLm1lc3NhZ2Uuc3VjY2VzcyhgRmlsZSBpcyB1cGxvYWRpbmdgKVxuICAgIGxldCB0aW1lc3RhbXAgPSBuZXcgRGF0ZSgpLnZhbHVlT2YoKVxuICAgIGxldCBmaWxlUGF0aCA9IGAvcHJvZmlsZS8ke3RpbWVzdGFtcH0uanBlZ2BcbiAgICBsZXQgZmlsZSA9IGl0ZW1bJ2ZpbGUnXVxuICAgIGNvbnN0IHRhc2sgPSB0aGlzLnN0b3JhZ2UudXBsb2FkKGZpbGVQYXRoLCBmaWxlKVxuICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc3RvcmFnZS5yZWYoZmlsZVBhdGgpLmdldERvd25sb2FkVVJMKCkudG9Qcm9taXNlKClcbiAgICAgIH0pXG4gICAgICAudGhlbihyZXMgPT4ge1xuICAgICAgICByZXR1cm4gdGhpcy5hZnMuY29sbGVjdGlvbihcInVzZXJzXCIpLmRvYyh0aGlzLmF1dGgudWlkKS51cGRhdGUoe1xuICAgICAgICAgIFwicHJvZmlsZVVSTFwiOiByZXMsXG4gICAgICAgICAgXCJ1cGxvYWRUaW1lXCI6IGZpcmViYXNlLmZpcmVzdG9yZS5GaWVsZFZhbHVlLnNlcnZlclRpbWVzdGFtcCgpXG4gICAgICAgIH0pXG4gICAgICB9KVxuICAgICAgLnRoZW4ocmVzID0+IHtcbiAgICAgICAgdGhpcy5hdXRoLmxvZyhgY2hhbmdlZCBwcm9maWxlIHBpYyAke3RpbWVzdGFtcH0uanBlZ2ApXG4gICAgICAgIHRoaXMubWVzc2FnZS5zdWNjZXNzKFwiRmlsZSBVcGxvYWRlZFwiKVxuICAgICAgfSkuY2F0Y2goZXJyID0+IHtcbiAgICAgICAgdGhpcy5tZXNzYWdlLmVycm9yKGVycilcbiAgICAgIH0pXG4gICAgcmV0dXJuIG9mKCkuc3Vic2NyaWJlKChldmVudDogSHR0cEV2ZW50PHt9PikgPT4ge1xuICAgICAgaWYgKGV2ZW50WydwZXJjZW50J10gIT0gMTAwKSB7XG4gICAgICAgIGl0ZW0ub25Qcm9ncmVzcyhldmVudCwgaXRlbS5maWxlKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGl0ZW0ub25TdWNjZXNzKGV2ZW50Wydib2R5J10sIGl0ZW0uZmlsZSwgZXZlbnQpO1xuICAgICAgfVxuICAgIH0sIChlcnIpID0+IHtcbiAgICAgIGl0ZW0ub25FcnJvcihlcnIsIGl0ZW0uZmlsZSk7XG4gICAgfSlcbiAgfVxuXG4gIGdldFByb2ZpbGVQaWMoKSB7XG4gICAgcmV0dXJuICh0aGlzLnByb2ZpbGVVUkwpID8geyAnYmFja2dyb3VuZC1pbWFnZSc6ICd1cmwoXFwnJyArIHRoaXMucHJvZmlsZVVSTCArICdcXCcpJyB9IDoge31cbiAgfVxuXG4gIEBIb3N0TGlzdGVuZXIoJ2RvY3VtZW50OmtleWRvd24nLCBbJyRldmVudCddKVxuICBrZXlib2FyZEV2ZW50KGU6IEtleWJvYXJkRXZlbnQpIHtcbiAgICBpZiAodGhpcy5zaG93Q2hhbmdlUGFzc3dvcmQgJiYgZS5rZXkgPT0gJ0VzY2FwZScpIHtcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uLmJsYW5rKFwiRVNDXCIsIFwiRXNjYXBlIG1vZGFsXCIpXG4gICAgICB0aGlzLnNob3dDaGFuZ2VQYXNzd29yZCA9IGZhbHNlXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2hvd0Rpc3BsYXlOYW1lICYmIGUua2V5ID09ICdFc2NhcGUnKSB7XG4gICAgICB0aGlzLm5vdGlmaWNhdGlvbi5ibGFuayhcIkVTQ1wiLCBcIkVzY2FwZSBtb2RhbFwiKVxuICAgICAgdGhpcy5zaG93RGlzcGxheU5hbWUgPSBmYWxzZVxuICAgIH1cblxuICAgIGlmICh0aGlzLnNob3dDaGFuZ2VQYXNzd29yZCkge1xuICAgICAgaWYgKGUuY3RybEtleSAmJiBlLmtleSA9PSAnRW50ZXInKSB7XG4gICAgICAgIHRoaXMubm90aWZpY2F0aW9uLmJsYW5rKFwi4oyDIEVOVEVSXCIsIFwiRm9ybSBTdWJtaXNzaW9uXCIpXG4gICAgICAgIHRoaXMuY2hhbmdlUGFzc3dvcmQoKVxuICAgICAgfVxuICAgIH1cbiAgICBcbiAgICBpZiAodGhpcy5zaG93RGlzcGxheU5hbWUgJiYgZS5jdHJsS2V5ICYmIGUua2V5ID09ICdFbnRlcicpIHtcbiAgICAgIHRoaXMubm90aWZpY2F0aW9uLmJsYW5rKFwi4oyDIEVOVEVSXCIsIFwiRm9ybSBTdWJtaXNzaW9uXCIpXG4gICAgICB0aGlzLmNoYW5nZURpc3BsYXlOYW1lKClcbiAgICB9XG4gIH1cbn1cbiJdfQ==