{"version":3,"sources":["webpack:///./src/pages/not-found.ts","webpack:///./src/pages/not-found.html","webpack:///./src/pages/password-create.ts","webpack:///./src/pages/password-create.html","webpack:///./src/pages/password-reset.ts","webpack:///./src/pages/password-reset.html","webpack:///./src/pages/profile-edit.ts","webpack:///./src/pages/profile-edit.html","webpack:///./src/pages/projects.ts","webpack:///./src/pages/projects.html"],"names":["NotFound","module","exports","PasswordCreate","router","api","alerts","controllerFactory","loading","error","errorMessage","resetToken","resetComplete","userEmail","reqList","requirements","minimum","message","fulfilled","undefined","lowercase","uppercase","number","special","match","this","controller","createForCurrentScope","params","secret","auth","authentication","navigateToRoute","result","authManagement","create","action","level","label","dismissable","password","then","email","catch","finally","validate","res","results","length","forEach","r","rule","value","messageKey","propertyName","ensure","required","minLength","withMessage","matches","satisfiesRule","on","PasswordReset","instructionsSent","emailInput","emailValid","valid","log","getLogger","ProfileEdit","editing","visible","getUserImageName","f","name","fileName","fileId","editObject","id","orgId","me","organizationId","organizations","get","org","organization","files","getProfile","$event","profileUrl","detail","created","user","object","Error","data","fullname","$oldPassword","oldPassword","users","patch","Object","assign","e","ProjectPage","ea","dialogService","storage","actions","program","mapAdaptor","breadcrumbs","config","projects","addresses","subs","projectQuery","onProjectCreated","project","query","$select","$modify","updateLayer","layerId","onProjectRemoved","currentInstruction","projectId","remove","i","slice","onUserPatched","programUsersVisible","program_id","programUsersRoles","toGeoJSON","update","getAddresses","searchValue","selectedValue","Promise","resolve","extent","map","getView","getCenter","p1","geocode","find","$search","$center","join","expanded","expandedChanged","debug","programId","load","mapConfig","configs","type","mapOptions","locationTracking","locationTrackingEnabled","sub","dispose","destroy","route","redirect","moduleId","fallbackRoute","setTimeout","mapVisible","window","dispatchEvent","Event","cancel","isEditing","layer","getVectorLayer","setVisible","createLayer","layerOptions","style","thumbnailField","labelField","dfpReady","source","url","serviceType","baseUrl","API_HOST","typeId","$eager","updatedAt","$gt","subtract","toDate","getSource","refresh","clear","geomField","address","feature","getFeature","zoom","properties","clearSelection","geometry","coordinates","getVectorLayerSource","removeFeature","open","viewModel","model","geom","JSON","stringify","whenClosed","wasCancelled","setProperties","output","createLayers","updateMapProjects","usersVisible","programUsersVisibleChanged","ev","projectQueryCache","projectsLayer","getUrl","setParams","force","edit","events","eventEmitter","event","fn","OL_MAP_CREATED"],"mappings":"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","file":"app~2fe2fb58.bd54e080266c1591aed3.chunk.js","sourcesContent":["export class NotFound {\n}\n","// Module\nvar code = \"<template> <div class=\\\"px-4\\\"> <h1>Page not found</h1> <p>This page doesn't exist, or you don't have permission to view it.</p> <p class=\\\"mb-7\\\">If you think this is an error, please report an issue.</p> <a route-href=\\\"home\\\" mdc-button raised><mdc-icon>arrow_back</mdc-icon>Return Home</a> </div> </template>\";\n// Exports\nmodule.exports = code;","import { Router } from 'aurelia-router';\nimport { autoinject, bindable } from 'aurelia-framework';\nimport { DatafiProAPI } from 'services/api/DatafiProAPI';\nimport { AlertService } from 'services/util/Alert';\nimport { ValidationController, ValidationControllerFactory, ValidationRules } from 'aurelia-validation';\nimport { PasswordRequirements} from '@wsb_dev/datafi-shared/lib/types/Password';\n\ninterface ValidateTokenResponse {\n    action: string;\n    message?: string;\n    email?: string;\n}\n\n@autoinject\nexport class PasswordCreate {\n    loading = true;\n    error = false;\n    errorMessage = '';\n    resetToken = '';\n    resetComplete = false;\n    userEmail = '';\n    @bindable password: string;\n    controller: ValidationController;\n    reqList = ['minimum', 'lowercase', 'uppercase', 'number', 'special', 'match']\n    requirements: PasswordRequirements = {\n        minimum: { message: '8 character minimum', fulfilled: undefined },\n        lowercase: { message: 'Use at least one lower case letter', fulfilled: undefined },\n        uppercase: { message: 'Use at least one upper case letter', fulfilled: undefined },\n        number: { message: 'Use at least one number', fulfilled: undefined },\n        special: { message: 'Use at least one special character', fulfilled: undefined },\n        match: { message: 'Passwords must match', fulfilled: undefined },\n    }\n\n    constructor(\n        private router: Router,\n        private api: DatafiProAPI,\n        private alerts: AlertService,\n        private controllerFactory: ValidationControllerFactory,\n    ) { this.controller = this.controllerFactory.createForCurrentScope(); }\n\n    async activate(params: { secret: string }): Promise<void> {\n        this.resetToken = params.secret;\n        if (this.api.auth.authentication) {\n            this.router.navigateToRoute('home');\n        }\n        const result: ValidateTokenResponse = await this.api.authManagement.create({\n            action: 'validate-token',\n            secret: this.resetToken,\n        });\n        if (result && result.action !== 'error' && result.action === 'token-valid') {\n            this.loading = false;\n        } else if (result && result.action === 'error') {\n            this.error = true;\n            this.errorMessage = result.message;\n            this.loading = false;\n        } else {\n            this.alerts.create({\n                level: 'error',\n                label: 'Invalid response from server',\n                dismissable: true,\n            });\n        }\n    }\n\n    async confirm(): Promise<void> {\n        this.loading = true;\n\n        this.api.authManagement.create({\n            action: 'reset-password',\n            secret: this.resetToken,\n            password: this.password,\n        })\n            .then((result) => {\n                if (result?.action === 'reset-password') {\n                    this.userEmail = result.email;\n                    this.resetComplete = true;\n                } else {\n                    this.alerts.create({\n                        level: 'error',\n                        label: 'Invalid response from server',\n                        dismissable: true,\n                    });\n                }\n            })\n            .catch(() => {\n                this.alerts.create({\n                    level: 'error',\n                    label: 'Invalid response from server',\n                    dismissable: true,\n                });\n            })\n            .finally(() => {\n                this.loading = false;\n            });\n    }\n\n    updateValidation(): void {\n        this.controller.validate().then((res) => {\n            if (res.results.length) {\n                res.results.forEach((r) => {\n                    const message = r.rule.message?.value || r.rule.messageKey;\n                    if (this.requirements[message]) {\n                        this.requirements[message].fulfilled = r.message || !this[r.propertyName] || !this.password ? false : true;\n\n                    }\n                });\n            }\n        });\n    }\n}\n\nValidationRules\n    .ensure('password').required()\n    .minLength(8).withMessage('minimum')\n    .matches(/[a-z]/).withMessage('lowercase')\n    .matches(/[A-Z]/).withMessage('uppercase')\n    .matches(/\\d/).withMessage('number')\n    .matches(/\\W/).withMessage('special')\n    .ensure('confirmPassword').required()\n    .satisfiesRule('matchesProperty', 'password').withMessage('match')\n    .on(PasswordCreate);\n","// Module\nvar code = \"<template> <div class=\\\"login-styles flex-1 justify-center align-center\\\"> <div if.bind=\\\"!resetComplete\\\" class=\\\"login-container text-center\\\"> <div if.bind=\\\"loading\\\" class=\\\"loading-overlay\\\"></div> <div if.bind=\\\"error\\\" class=\\\"px-4\\\"> <h2 class=\\\"text-center mb-4\\\">Error</h2> <div class=\\\"text-error mb-5\\\"> <p>${errorMessage}</p> </div> <a mdc-button raised class=\\\"w-100 mx-auto my-3\\\" route-href=\\\"password-reset\\\"> <mdc-icon>keyboard_backspace</mdc-icon> Try Again </a> </div> <div if.bind=\\\"!error\\\" class=\\\"px-4\\\"> <p if.bind=\\\"api.auth.authentication\\\">You are logged in as: ${api.auth.authentication.user.username}</p> <form else class=\\\"d-inline-block text-left m-4 page--login--form\\\" input.delegate=\\\"updateValidation()\\\"> <h2 class=\\\"text-center mb-7\\\">Reset Password</h2> <div class=\\\"password-wrapper mb-5\\\"> <mdc-text-field outlined value.bind=\\\"password & validate\\\" type.bind=\\\"passwordVisible ? 'text' : 'password'\\\" label=\\\"New Password\\\"> </mdc-text-field> <span class=\\\"toggle-password\\\" click.delegate=\\\"passwordVisible = !passwordVisible\\\"> <mdc-icon if.bind=\\\"passwordVisible\\\">visibility</mdc-icon> <mdc-icon if.bind=\\\"!passwordVisible\\\">visibility_off</mdc-icon> </span> </div> <div class=\\\"password-wrapper mb-5\\\"> <mdc-text-field outlined value.bind=\\\"confirmPassword & validate\\\" type.bind=\\\"confirmPasswordVisible ? 'text' : 'password'\\\" label=\\\"Confirm Password\\\"> </mdc-text-field> <span class=\\\"toggle-password\\\" click.delegate=\\\"confirmPasswordVisible = !confirmPasswordVisible\\\"> <mdc-icon if.bind=\\\"confirmPasswordVisible\\\">visibility</mdc-icon> <mdc-icon if.bind=\\\"!confirmPasswordVisible\\\">visibility_off</mdc-icon> </span> </div> <ul class=\\\"validation-ui p-0 mb-7\\\"> <li repeat.for=\\\"req of reqList\\\" class=\\\"flex-1 align-center mb-3 ${requirements[req].fulfilled === undefined ? '' : requirements[req].fulfilled ? 'text-success' : 'text-error'}\\\"> <mdc-icon if.bind=\\\"requirements[req].fulfilled === undefined\\\" class=\\\"mr-3\\\">remove_circle</mdc-icon> <mdc-icon if.bind=\\\"requirements[req].fulfilled\\\" class=\\\"mr-3\\\">check_circle</mdc-icon> <mdc-icon if.bind=\\\"requirements[req].fulfilled === false\\\" class=\\\"mr-3\\\">cancel</mdc-icon> <p class=\\\"m-0\\\">${requirements[req].message}</p> </li> </ul> <button click.delegate=\\\"confirm()\\\" type=\\\"submit\\\" class=\\\"w-100 mx-auto mb-3\\\" mdc-button raised> <mdc-icon>login</mdc-icon> Reset Password </button> </form> </div> <mdc-linear-progress open.bind=\\\"loading\\\"></mdc-linear-progress> </div> <div else class=\\\"login-container text-center px-4\\\"> <div class=\\\"px-4\\\"> <h2 class=\\\"text-center mb-4\\\">Password Reset</h2> <div class=\\\"mb-5\\\"> <p> The password for ${userEmail} has been successfully reset.<br/> Click the button below to log in again. </p> </div> <a mdc-button raised class=\\\"w-100 mb-4\\\" route-href=\\\"login\\\"> <mdc-icon>login</mdc-icon>Back to Login </a> </div> </div> </div> </template> \";\n// Exports\nmodule.exports = code;","import { Router } from 'aurelia-router';\nimport { autoinject } from 'aurelia-framework';\nimport { DatafiProAPI } from 'services/api/DatafiProAPI';\nimport { ValidationController, ValidationControllerFactory, ValidationRules } from 'aurelia-validation';\n\n@autoinject\nexport class PasswordReset {\n    loading = false;\n    instructionsSent = false;\n    emailInput = '';\n    controller: ValidationController;\n    emailValid = false;\n\n    constructor(\n        private router: Router,\n        private api: DatafiProAPI,\n        private controllerFactory: ValidationControllerFactory,\n    ) { this.controller = this.controllerFactory.createForCurrentScope(); }\n\n    async activate(): Promise<void> {\n        if (this.api.auth.authentication) {\n            this.router.navigateToRoute('home');\n        }\n    }\n\n    async resetPassword(): Promise<void> {\n        this.loading = true;\n        this.api.authManagement.create({\n            action: 'send-password-reset',\n            email: this.emailInput,\n        });\n        this.instructionsSent = true;\n        this.loading = false;\n    }\n\n    resetForm() {\n        this.loading = false;\n        this.instructionsSent = false;\n        this.emailInput = '';\n        this.emailValid = false;\n    }\n\n    validateEmail() {\n        this.controller.validate().then((res) => {\n            this.emailValid = res.valid;\n        });\n    }\n}\n\nValidationRules\n    .ensure('emailInput').required().withMessage('An email is required.')\n    .matches(/^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,4}$/).withMessage('Please enter a valid email.')\n    .on(PasswordReset);\n","// Module\nvar code = \"<template> <div class=\\\"login-styles flex-1 justify-center align-center\\\"> <div if.bind=\\\"!instructionsSent\\\" class=\\\"login-container text-center\\\"> <div if.bind=\\\"loading\\\" class=\\\"loading-overlay\\\"></div> <div class=\\\"px-4\\\"> <p if.bind=\\\"api.auth.authentication\\\">You are logged in as: ${api.auth.authentication.user.username}</p> <form else class=\\\"d-inline-block text-left m-4 page--login--form\\\"> <h2 class=\\\"text-center\\\">Reset Password</h2> <p class=\\\"mb-3 mt-0 d-inline-block\\\">Enter the email associated with your account. If the email exists, we'll send you instructions to reset your password. </p> <div class=\\\"my-3\\\"> <mdc-text-field outlined value.bind=\\\"emailInput & validate\\\" input.delegate=\\\"validateEmail()\\\" type=\\\"text\\\" label=\\\"Email\\\" label=\\\"Type 'error'\\\"> </mdc-text-field> <mdc-text-field-helper-line> <mdc-text-field-helper-text validation>Required</mdc-text-field-helper-text> </mdc-text-field-helper-line> </div> <button disabled.bind=\\\"!emailValid\\\" click.delegate=\\\"resetPassword()\\\" type=\\\"submit\\\" class=\\\"w-100 mx-auto mb-3\\\" mdc-button raised> <mdc-icon>arrow_forward</mdc-icon> Reset </button> <a mdc-button outlined class=\\\"w-100 mb-4\\\" route-href=\\\"login\\\"> <mdc-icon>arrow_back</mdc-icon>Back to Login </a> </form> </div> <mdc-linear-progress open.bind=\\\"loading\\\"></mdc-linear-progress> </div> <div else class=\\\"login-container text-center px-4\\\"> <p if.bind=\\\"api.auth.authentication\\\">You are logged in as: ${api.auth.authentication.user.username}</p> <form else class=\\\"d-inline-block text-center m-4 page--login--form\\\" submit.trigger=\\\"login()\\\"> <h2 class=\\\"text-center\\\">Please check your email</h2> <p class=\\\"mb-3 mt-0 d-inline-block\\\"> If there is an account linked to <span>${emailInput}</span>, you will receive instructions on how to reset your password. </p> <p>Check your email to follow the instructions.</p> <a mdc-button raised class=\\\"w-100 mx-auto my-3\\\" route-href=\\\"login\\\"> <mdc-icon>login</mdc-icon>Back to Login </a> <a mdc-button outlined class=\\\"w-100\\\" href=\\\"#\\\" click.delegate=\\\"resetForm()\\\"> <mdc-icon>refresh</mdc-icon>Resend instructions </a> <a if.bind=\\\" flags.login_helpdesk_link\\\" href=\\\"https://forms.datafi.pro/single/9ed6pd2K?&d[survey_id]=2153&d[program_id]=256\\\" target=\\\"_blank\\\" class=\\\"divider-style-text my-4\\\"> If you still have trouble, contact Helpdesk </a> </form> </div> </div> </template>\";\n// Exports\nmodule.exports = code;","import { ValidationController } from 'aurelia-validation';\nimport { ValidationControllerFactory } from 'aurelia-validation';\n\nimport { AlertService } from '../services/util/Alert';\nimport { autoinject } from 'aurelia-dependency-injection';\nimport { DatafiProAPI } from '../services/api/DatafiProAPI';\nimport { IUploadEventDetail } from '../components/mdc-upload-field/mdc-upload-field';\nimport { EditableUser } from '../types/EditableUser';\nimport { IGeneratePath, generatePath } from '@wsb_dev/datafi-shared/lib/util/files/generatePath';\nimport { LogManager } from 'aurelia-framework';\n\nconst log = LogManager.getLogger('dfp:profile-edit');\n@autoinject\nexport class ProfileEdit {\n    editObject: EditableUser;\n    controller: ValidationController;\n    organization: any;\n    editing = false;\n    visible = true;\n\n    constructor(\n        private controllerFactory: ValidationControllerFactory,\n        private alerts: AlertService,\n        private api: DatafiProAPI,\n    ) {\n        const orgId = this.api.auth.me?.organizationId;\n\n        this.api.organizations.get(orgId ? orgId : 0).then((org) => {\n            this.organization = org;\n        });\n    }\n\n    editProfile() {\n        this.editing = true;\n        this.editObject = new EditableUser(this.api.auth.me, this.api.files);\n        this.editObject.getProfile();\n        this.controller = this.controllerFactory.createForCurrentScope();\n    }\n\n    cancelEdit() {\n        this.editing = false;\n        this.editObject = new EditableUser(this.api.auth.me, this.api.files);\n    }\n\n    updateUserProfile($event: CustomEvent<IUploadEventDetail>){\n        this.editObject.profileUrl = $event.detail.created[0].id;\n    }\n\n    saveEdit (user: EditableUser) {\n        return this.controller.validate({\n            object: user,\n        }).then((result) => {\n            if (!result.valid) {\n                this.editing = true;\n                throw new Error('Form is not valid');\n            }\n            const data: any = {\n                email: user.email,\n                fullname: user.fullname,\n                profileUrl: user.profileUrl,\n            };\n\n            if (user.password) {\n                data.password = user.password;\n                data.$oldPassword = user.oldPassword;\n            }\n\n            return this.api.users.patch(user.id, data);\n        }).then((user) => {\n            this.editing = false;\n\n            this.alerts.create({\n                label: 'Profile saved successfully',\n                dismissable: true,\n            });\n\n            Object.assign(this.api.auth.me, user);\n            if(user.profileUrl){\n                this.api.auth.me.getProfile(true);\n            }\n\n        }).catch((e) => {\n            log.error(e);\n\n            this.alerts.create({\n                label: e.message,\n                level: 'error',\n                dismissable: true,\n            });\n        });\n    }\n\n    getUserImageName = (f: File): string => {\n        return generatePath({\n            name: 'profile',\n            fileName: f.name,\n            fileId: this.editObject.id,\n        } as IGeneratePath) as string;\n    }\n}\n","// Module\nvar code = \"<template> <require from=\\\"../components/mdc-upload-field/mdc-upload-field\\\"></require> <div if.bind=\\\"!editing\\\" class=\\\"profile-edit\\\"> <h2>${api.auth.me.fullname}</h2> <p>${api.auth.me.roles[0].role.role_name | title} | ${organization.name | title}</p> <p>${api.auth.me.email}</p> <div class=\\\"divider mt-8 mb-7\\\"></div> <ul class=\\\"user-links\\\"> <li> <button class=\\\"button--color--background\\\" mdc-elevation=\\\"0\\\" mdc-fab mini icon=\\\"settings\\\" tabindex=\\\"0\\\" click.delegate=\\\"editProfile(user)\\\" mdc-tooltip=\\\"Edit Account\\\"></button> </li> </ul> </div> <div if.bind=\\\"editing\\\"> <div class=\\\"divider text-center\\\" data-content=\\\"Edit Profile\\\"></div> <mdc-text-field disabled.bind=\\\"api.auth.me.microsoftId\\\" outlined class=\\\"profile-density-outlined\\\" value.bind=\\\"editObject.fullname & validate\\\" label=\\\"Full name\\\"></mdc-text-field> <mdc-text-field-helper-line> <mdc-text-field-helper-text validation>Required</mdc-text-field-helper-text> </mdc-text-field-helper-line> <mdc-text-field disabled.bind=\\\"api.auth.me.microsoftId\\\" outlined class=\\\"profile-density-outlined\\\" value.bind=\\\"editObject.email & validate\\\" label=\\\"Email\\\"></mdc-text-field> <mdc-text-field-helper-line> <mdc-text-field-helper-text validation>Required</mdc-text-field-helper-text> </mdc-text-field-helper-line> <div class=\\\"divider text-center\\\" data-content=\\\"Upload Profile Image\\\"></div> <mdc-upload-field get-file-name.bind=\\\"getUserImageName\\\" single.bind=\\\"true\\\" created.trigger=\\\"updateUserProfile($event)\\\" style=\\\"display:block\\\"></mdc-upload-field> <div class=\\\"divider text-center\\\" data-content=\\\"Change Password\\\"></div> <mdc-text-field type=\\\"password\\\" label=\\\"Current Password\\\" outlined value.bind=\\\"editObject.oldPassword & validate\\\"></mdc-text-field> <mdc-text-field-helper-line> <mdc-text-field-helper-text validation>Required</mdc-text-field-helper-text> </mdc-text-field-helper-line> <mdc-text-field value.bind=\\\"editObject.password & validate\\\" type=\\\"password\\\" label=\\\"New Password\\\" outlined></mdc-text-field> <mdc-text-field-helper-line> <mdc-text-field-helper-text validation>Required</mdc-text-field-helper-text> </mdc-text-field-helper-line> <mdc-text-field value.bind=\\\"editObject.confirmPassword & validate\\\" type=\\\"password\\\" label=\\\"Confirm New password\\\" outlined></mdc-text-field> <mdc-text-field-helper-line> <mdc-text-field-helper-text validation>Required</mdc-text-field-helper-text> </mdc-text-field-helper-line> <div class=\\\"divider mt-8 mb-7\\\"></div> <div class=\\\"column\\\"> <button class=\\\"button--color--secondary\\\" click.delegate=\\\"cancelEdit()\\\" type=\\\"submit\\\" mdc-button>Cancel</button> <button class=\\\"button--raised--secondary\\\" click.delegate=\\\"saveEdit(editObject)\\\" type=\\\"submit\\\" mdc-button raised> <mdc-icon>save</mdc-icon><span>Save</span> </button> </div> </div> </template> \";\n// Exports\nmodule.exports = code;","import { ProjectFilter } from './../components/projects/project-list/events/ProjectFilter';\nimport { MapAdaptor } from './../services/util/MapAdaptor';\n\nimport { Feature, Map } from 'ol';\nimport { toLonLat } from 'ol/proj';\n\nimport isequal from 'lodash.isequal';\nimport uniqwith from 'lodash.uniqwith';\n\n// aurelia\nimport { LogManager, autoinject, bindable } from 'aurelia-framework';\nimport { PLATFORM } from 'aurelia-pal';\nimport { DialogService } from 'aurelia-dialog';\nimport { Router, RouterConfiguration, Redirect } from 'aurelia-router';\nimport { Subscription } from 'aurelia-event-aggregator';\n\nimport { ProjectEditor } from '../components/projects/project-edit/project-edit';\nimport { defaultMap } from './../components/projects/data/defaultMap';\n\nimport { ActionService } from './../services/actions/ActionService';\nimport { BrowserStorage } from '../services/util/BrowserStorage';\nimport { AlertService } from '../services/util/Alert';\n\nimport { GeocodeResult } from '@wsb_dev/datafi-shared/lib/types/Geocode';\nimport { Events } from '@wsb_dev/datafi-shared/lib/types/Events';\nimport { ActiveProgram } from '../services/util/ActiveProgram';\n\nimport { subscribe } from '../util/decorators/subscribe';\nimport { ValidatedProject } from '../types/Project';\nimport { debounced } from '../util/decorators/debounced';\nimport { Geometry } from 'ol/geom';\n\nimport { ProjectBreadcrumbsService } from '../services/assets/ProjectBreadcrumbs';\nimport { ProgramUserRole, Project } from '@wsb_dev/datafi-shared/lib/types';\nimport { DatafiProAPI } from '../services/api/DatafiProAPI';\nimport { EventAggregatorWrapper } from '../util/events/eventAggregatorWrapper';\nimport { ValidatedUser } from '../types/Users';\nimport { IThumbnailOptions } from '../components/ol-map/styles/thumbnailStyle';\nimport PQueue from 'p-queue';\nimport { StorageItem } from '../services/util/_StorageBase';\nimport { AppConfig } from '../services/util/AppConfig';\nimport { DFPUrlObj, IUrlParams, createLayerCacheKey } from '../components/ol-map/sources/dfpSourceUrlGeojson';\nimport Cluster from 'ol/source/Cluster';\nimport VectorSource from 'ol/source/Vector';\nimport dayjs from 'dayjs';\n\nconst log = LogManager.getLogger('dfp:projects');\n\n@subscribe({\n    events: [\n        { eventEmitter: 'api.projects', event: 'created', fn: 'onProjectCreated' },\n        { eventEmitter: 'api.projects', event: 'removed', fn: 'onProjectRemoved' },\n        { eventEmitter: 'api.programUsersRoles', event: 'patched', fn: 'onUserPatched' },\n\n        { eventEmitter: 'ea', event: Events.OL_MAP_CREATED, fn: 'setupMap' },\n        { eventEmitter: 'ea', event: ProjectFilter, fn: 'handleProjectFilter' },\n    ],\n})\n@autoinject\nexport class ProjectPage {\n    /**============================================\n     *               Data props\n     *=============================================**/\n    @bindable expanded: boolean;\n    @bindable mapVisible: boolean;\n    programId: number;\n\n    @bindable projects: any[] = [];\n\n    @bindable address: Feature<Geometry>;\n    @bindable addresses: GeocodeResult[] = [];\n    @bindable addressSearch: string;\n    @bindable programUsersVisible: boolean;\n\n    locationTracking: boolean;\n\n    isEditing: boolean;\n\n    mapOptions: any;\n    map: Map;\n    mapLoading: boolean;\n    projectsQueue: PQueue;\n\n    router: Router;\n\n    subs: Subscription[] = [];\n\n    projectQuery: Record<string, any> = {};\n    projectQueryCache: string;\n\n    users: ValidatedUser[] = [];\n\n    constructor(\n        private api: DatafiProAPI,\n        private ea: EventAggregatorWrapper,\n        private dialogService: DialogService,\n        private storage: BrowserStorage,\n        private alerts: AlertService,\n        private actions: ActionService, // used in view\n        private program: ActiveProgram,\n        private mapAdaptor: MapAdaptor,\n        private breadcrumbs: ProjectBreadcrumbsService,\n        private config: AppConfig,\n    ) {\n\n        // expand/hide map\n        this.storage.get('projects_expanded')\n            .then((expanded) => {\n                this.expanded = expanded.data;\n                this.expandedChanged(this.expanded);\n            })\n            .catch((e) => {\n                log.debug(e);\n                this.expanded = false;\n                this.expandedChanged(this.expanded);\n            });\n    }\n\n    /**============================================\n     *               Event handlers\n     *=============================================**/\n\n    onProjectCreated = (project: Project): void => {\n        if ((this.api.auth.me.organizationId === project.organizationId) || project.organizationId === 0) {\n            this.api.projects.get(project.id, { query: { $select: ['geom'], $modify: 'toGeoJSON' } }).then((project) => {\n                this.mapAdaptor.updateLayer({\n                    layerId: 'projectFeatures',\n                    create: [project],\n                });\n            });\n        }\n    }\n\n    onProjectRemoved = (project: Project): void => {\n        if (project.id === this.router.currentInstruction.params.projectId) {\n            this.router.navigateToRoute('list');\n        }\n\n        this.mapAdaptor.updateLayer({\n            layerId: 'projectFeatures',\n            remove: [project],\n        });\n\n        for (let i = 0; i < this.projects.length; i++) {\n            if (this.projects[i].id === project.id) {\n                // remove project from our list\n                this.projects = [\n                    ...this.projects.slice(0, i),\n                    ...this.projects.slice(i + 1),\n                ];\n                return;\n            }\n        }\n    }\n\n    onUserPatched = (user: ProgramUserRole): void => {\n        if (!this.programUsersVisible || user.program_id !== this.program.id) {\n            return;\n        }\n\n        this.api.programUsersRoles.get(user.id, {\n            query: {\n                $modify: { toGeoJSON: [] },\n            },\n        }).then((user) => {\n            this.mapAdaptor.updateLayer({\n                layerId: 'userFeatures',\n                update: [user],\n            });\n        });\n    }\n\n    /**============================================\n     *               Methods\n     *=============================================**/\n\n    canActivate() {\n        if (!this.api.auth.me) return new Redirect('/login');\n    }\n\n    async activate(params) {\n        // set data model init\n        if (params.programId === this.program.id) {\n            return;\n        }\n\n        return this.program.load(params.programId, true).then(async () => {\n            // get the cached program id\n            const id = `projectQuery-${params.programId}`;\n            const { data: projectQuery } = await this.storage.get(id)\n                .catch((e) => ({ id: id, data: {} } as StorageItem));\n            this.projectQuery = {\n                ...this.program.projectQuery,\n                ...projectQuery,\n                program_id: this.program.id,\n            };\n\n            const mapConfig = this.program.configs?.find((config) => config.type === 'ol-map');\n            this.mapOptions = mapConfig?.data || defaultMap;\n            this.locationTracking = this.program.locationTrackingEnabled;\n        });\n\n    }\n\n    detached() {\n        this.mapAdaptor.map = null;\n        this.subs.forEach((sub) => sub.dispose());\n        this.users.forEach((user) => user.destroy());\n    }\n\n    configureRouter(config: RouterConfiguration, router: Router) {\n        config.map([\n            // program level\n            { route: '', redirect: 'list' },\n            { name: 'list', route: ['list', 'list/:tabId'], moduleId: PLATFORM.moduleName('../components/projects/project-tabs/project-tabs') },\n            { name: 'survey', route: 'survey/:surveyId', moduleId: PLATFORM.moduleName('../components/surveys/survey-list/survey-list') },\n            { name: 'assets', route: ['assets'], moduleId: PLATFORM.moduleName('../components/assets/asset-type-list/asset-type-list') },\n            { name: 'assets-table', route: ['assets/:typeId'], moduleId: PLATFORM.moduleName('../components/assets/asset-table/asset-table') },\n\n            // project level\n            { name: 'project-detail', route: ':projectId', moduleId: PLATFORM.moduleName('../components/projects/project-tabs/project-tabs')},\n            { name: 'project-survey', route: ':projectId/survey/:surveyId', moduleId: PLATFORM.moduleName('../components/surveys/survey-list/survey-list') },\n            { name: 'project-assets', route: [':projectId/assets'], moduleId: PLATFORM.moduleName('../components/assets/asset-type-list/asset-type-list') },\n            { name: 'project-assets-table', route: [':projectId/assets/:typeId'], moduleId: PLATFORM.moduleName('../components/assets/asset-table/asset-table') },\n\n            // asset\n\n        ]);\n\n        config.fallbackRoute('list');\n\n        this.router = router;\n\n    }\n\n    expandedChanged(expanded) {\n        this.storage.create({\n            id: 'projects_expanded',\n            data: expanded,\n        });\n        setTimeout(() => {\n            this.mapVisible = !expanded;\n            window.dispatchEvent(new Event('resize'));\n            if (!this.mapVisible) {\n                this.mapAdaptor.cancel();\n                this.isEditing = false;\n            }\n        }, 600);\n    }\n\n    async programUsersVisibleChanged(visible: boolean): Promise<void> {\n        this.storage.create({\n            id: 'program_users_visible',\n            data: visible,\n        });\n        if (!visible) {\n            const layer = await this.mapAdaptor.getVectorLayer({layerId: 'userFeatures'});\n            layer?.setVisible(false);\n            return;\n        }\n\n        const layer = await this.mapAdaptor.updateLayer({\n            layerId: 'userFeatures',\n            createLayer: true,\n            layerOptions: {\n                style: {\n                    type: 'style/thumbnailStyle',\n                    thumbnailField: 'user._blobs.profile.url',\n                    labelField: 'user.fullname',\n                } as IThumbnailOptions,\n                dfpReady: true,\n                source: {\n                    type: 'dfp/source/VectorDFP',\n                    url: {\n                        type: 'url/dfp/GeoJSON',\n                        serviceType: 'programs-users-roles',\n                        baseUrl: this.config.API_HOST,\n                        programId: this.program.id,\n                        typeId: 0,\n                        query: {\n                            $select: ['updatedAt'],\n                            $eager: 'user',\n                            updatedAt: {\n                                $gt: dayjs().subtract(1, 'week').toDate(),\n                            },\n                        },\n                    } as IUrlParams,\n                },\n            },\n        });\n\n        layer?.setVisible(true);\n        layer?.getSource().refresh();\n    }\n\n    addressesChanged(addresses) {\n        this.mapAdaptor.updateLayer({\n            layerId: 'addressFeatures',\n            create: addresses,\n            clear: true,\n            createLayer: true,\n            geomField: 'geometry',\n        });\n    }\n\n    async addressChanged(address) {\n        if (!address) {\n            return;\n        }\n        const feature = await this.mapAdaptor.getFeature({ name: address }, 'addressFeatures', 'name');\n        this.mapAdaptor.zoom(feature);\n    }\n\n    // we use arrow syntax because it binds `this` to the function\n    // and is necessary because we are passing this function to\n    // a child component\n    getAddresses = (searchValue, selectedValue) => {\n\n        if (selectedValue) {\n            return Promise.resolve(this.addresses);\n        }\n\n        if (!searchValue) {\n            this.addresses = [];\n            return Promise.resolve();\n        }\n\n        // refresh geocoder\n        const extent = this.map.getView().getCenter();\n        const p1 = toLonLat([extent[0], extent[1]]);\n\n        return this.api.geocode.find({\n            query: {\n                $search: searchValue,\n                $center: p1.join(','),\n            },\n        }).then((results: GeocodeResult[]) => {\n            this.addresses = results;\n            return this.addresses;\n        });\n    }\n\n    addressDisplay(address) {\n        if (!address) {\n            return;\n        }\n        return address.properties.name;\n    }\n\n    async createProject() {\n        this.mapAdaptor.clearSelection();\n        this.isEditing = true;\n        this.alerts.create({\n            label: 'Click on the map to draw your project boundary',\n            dismissable: true,\n        });\n\n        return this.mapAdaptor.create('projectFeatures').then(async ({ geometry, feature }) => {\n            const removeDuplicateCoords = uniqwith(geometry.coordinates[0], isequal);\n            if (removeDuplicateCoords.length < 3) {\n                const source = await this.mapAdaptor.getVectorLayerSource({ layerId: 'projectFeatures' });\n                source.removeFeature(feature);\n                this.alerts.create({\n                    label: 'Please add at least 3 points',\n                    level: 'error',\n                    dismissable: true,\n                });\n                return;\n            }\n\n            return this.dialogService.open({\n                viewModel: ProjectEditor, model: new ValidatedProject({\n                    program_id: this.program.id,\n                    geom: JSON.stringify(geometry),\n                }),\n            }).whenClosed(async (result) => {\n                if (result.wasCancelled) {\n                    const source = await this.mapAdaptor.getVectorLayerSource({ layerId: 'projectFeatures' });\n                    source.removeFeature(feature);\n                    this.alerts.create({\n                        label: 'New Project cancelled',\n                        dismissable: true,\n                    });\n                    return;\n                }\n\n                this.alerts.create({\n                    label: 'Project created',\n                    level: 'success',\n                    dismissable: true,\n                });\n\n                feature.setProperties(result.output);\n            });\n        }).catch((e) => {\n            this.alerts.create({\n                label: e.message,\n                level: 'error',\n                dismissable: true,\n            });\n        }).finally(() => this.isEditing = false);\n    }\n\n    async setupMap(map: Map) {\n        this.map = map;\n        this.mapAdaptor.map = this.map;\n        this.createLayers();\n        this.updateMapProjects(true);\n        this.storage.get('program_users_visible')\n            .then((usersVisible) => {\n                this.programUsersVisible = usersVisible.data;\n                this.programUsersVisibleChanged(this.programUsersVisible);\n            })\n            .catch((e) => {\n                log.debug(e);\n                this.programUsersVisible = false;\n                this.programUsersVisibleChanged(this.programUsersVisible);\n            });\n    }\n\n    handleProjectFilter(ev: ProjectFilter) {\n        this.projectQuery = ev.query;\n        this.updateMapProjects();\n    }\n\n    async createLayers() {\n        this.projectQueryCache = createLayerCacheKey(this.projectQuery);\n        const projectsLayer = await this.mapAdaptor.getVectorLayer({\n            layerId: 'projectFeatures',\n            createLayer: true,\n            updateLayer: true,\n            layerOptions: {\n                dfpReady: true,\n                visible: true,\n                source: {\n                    type: 'dfp/source/VectorDFP',\n                    url: {\n                        type: 'url/dfp/GeoJSON',\n                        serviceType: 'projects',\n                        baseUrl: this.config.API_HOST,\n                        programId: this.program.id,\n                        typeId: 0,\n                    } as IUrlParams,\n                },\n            },\n        });\n        (projectsLayer.getSource()?.getUrl() as DFPUrlObj)?.setParams({ query: this.projectQuery }, projectsLayer);\n        projectsLayer?.setVisible(true);\n    }\n\n    @debounced(200)\n    async updateMapProjects(force = false) {\n        const query = this.projectQuery;\n        const layer = await this.mapAdaptor.getVectorLayer({ layerId: 'projectFeatures' });\n        if (!layer) {\n            return;\n        }\n        let source = layer?.getSource() as VectorSource | Cluster;\n        if (source instanceof Cluster) {\n            source = source.getSource();\n        }\n\n        const url = source.getUrl() as DFPUrlObj;\n        url.setParams({ query }, layer);\n\n    }\n\n    editProjectGeometry(project) {\n        this.mapAdaptor.clearSelection();\n        this.isEditing = true;\n\n        this.alerts.create({\n            label: 'Edit the project by dragging on its boundary points',\n            dismissable: true,\n        });\n\n        this.mapAdaptor.edit(project, 'projectFeatures')\n            .then((result) => {\n                const geom = result.geometry;\n                this.alerts.create({\n                    label: 'Saving edits...',\n                    dismissable: true,\n                });\n                return this.api.projects.patch(project.id, {\n                    geom: JSON.stringify(geom),\n                });\n            })\n            .then(() => {\n                this.alerts.create({\n                    label: 'Project updated',\n                    level: 'success',\n                    dismissable: true,\n                });\n            })\n            .catch((e) => {\n                this.alerts.create({\n                    label: e.message,\n                    level: 'error',\n                    dismissable: true,\n                });\n            })\n            .finally(() => this.isEditing = false);\n    }\n}\n","// Module\nvar code = \"<template> <require from=\\\"../components/ol-map/ol-map\\\"></require> <require from=\\\"../components/action-button/action-button\\\"></require> <require from=\\\"../components/gps-button/gps-button\\\"></require> <require from=\\\"../components/basemap-toggle/basemap-toggle\\\"></require> <require from=\\\"../components/projects/project-breadcrumbs/project-breadcrumbs\\\"></require> <require from=\\\"../components/ol-map-legend/ol-map-legend\\\"></require> <require from=\\\"../components/ol-map-selection/ol-map-selection\\\"></require> <div class=\\\"empty\\\" if.bind=\\\"api.auth.authentication && !program.id && !program.promise\\\"> <mdc-icon>error</mdc-icon> <p>Select a program to get started</p> <div> <a mdc-button raised href=\\\"/\\\"> <mdc-icon>login</mdc-icon> Go to programs </a> </div> </div> <div class=\\\"page-projects container w-100 p-0 m-0\\\" css=\\\"${program.id ? '' : 'display: none;'}\\\"> <div class=\\\"columns col-gapless w-100\\\"> <div class=\\\"sidebar column ${expanded ? 'col-12' : 'col-5 col-xl-6 col-lg-6 col-md-6 col-sm-12'}\\\"> <div class=\\\"sidebar-container d-flex flex-column\\\"> <mdc-linear-progress open.bind=\\\"mapLoading\\\"></mdc-linear-progress> <div class=\\\"d-flex justify-between\\\"> <project-breadcrumbs data-tour-id=\\\"program-breadcrumbs\\\"></project-breadcrumbs> <div mdc-menu-surface-anchor ref=\\\"settingsAnchor\\\" class=\\\"float-right m-6\\\"> <button mdc-fab mini icon=\\\"settings\\\" data-tour-id=\\\"program-map-menu\\\" click.trigger=\\\"settings.open = !settings.open\\\"></button> <mdc-menu anchor-corner=\\\"BOTTOM_LEFT\\\" default-focus-state=\\\"NONE\\\" hoist-to-body view-model.ref=\\\"settings\\\" anchor.bind=\\\"settingsAnchor\\\"> <mdc-form-field class=\\\"m-6 d-block\\\"> <button mdc-switch class=\\\"m-2 no-icon-switch\\\" selected.bind=\\\"expanded\\\"></button> <label if.bind=\\\"expanded\\\">Show Map</label> <label else>Hide Map</label> </mdc-form-field> <mdc-form-field class=\\\"m-6 d-block\\\"> <button mdc-switch class=\\\"m-2 no-icon-switch\\\" disabled.bind=\\\"locationTracking\\\" selected.bind=\\\"program.locationTrackingEnabled\\\"></button> <label>Share location with program users</label> </mdc-form-field> <mdc-form-field if.bind=\\\"api.auth.me | hasPermission:program:'api/v1/programs-users-roles':'find'\\\" class=\\\"m-6 d-block\\\"> <button mdc-switch class=\\\"m-2 no-icon-switch\\\" selected.bind=\\\"programUsersVisible\\\"></button> <label>Show program users on map</label> </mdc-form-field> </mdc-menu> </div> </div> <div class=\\\"flex-grow-1\\\"> <router-view class=\\\"d-block h-100 d-flex flex-column\\\"></router-view> </div> </div> </div> <div if.bind=\\\"mapVisible && mapOptions\\\" class=\\\"column ${expanded ? 'col-12' : 'col-7 col-xl-6 col-lg-6 col-md-6 col-sm-12'}\\\"> <ol-map options.bind=\\\"mapOptions\\\" background=\\\"#f7f6f4\\\" map.one-time=\\\"webmap\\\"> <div slot=\\\"top-left\\\" mdc-menu-surface-anchor if.bind=\\\"!expanded\\\"> <div class=\\\"m-1 pointer-auto\\\"> <mdc-text-field class=\\\"density-outlined-text-field\\\" label=\\\"Find an address\\\" ref=\\\"addressInput\\\" outlined data-tour-id=\\\"program-map-search\\\"></mdc-text-field> <mdc-text-field-helper-line></mdc-text-field-helper-line> <mdc-lookup preload-options value-field.bind=\\\"addressDisplay\\\" display-field.bind=\\\"addressDisplay\\\" options.bind=\\\"getAddresses\\\" input.bind=\\\"addressInput\\\" value.bind=\\\"address\\\"> </mdc-lookup> </div> <div class=\\\"float-left pointer-auto\\\" data-tour-id=\\\"program-map-tools\\\"> <button mdc-fab mini class=\\\"button--shape--square ${showLegend ? 'button--color--grey--primary' : ''}\\\" icon=\\\"format_list_bulleted\\\" click.delegate=\\\"(showLegend = !showLegend) && (showSelection = false)\\\" title=\\\"Show/hide map legend.\\\"></button> <button mdc-fab mini class=\\\"button--shape--square ml-1 ${showSelection ? 'button--color--grey--primary' : ''}\\\" icon=\\\"manage_search\\\" click.delegate=\\\"(showSelection = !showSelection) && (showLegend = false)\\\" title=\\\"Show/hide map selection\\\"></button> <gps-button></gps-button> <span if.bind=\\\"!breadcrumbs.project && !isEditing && program.settings.tabs.projects | default:true\\\"> <button class=\\\"button--shape--square\\\" mdc-fab mini icon=\\\"add\\\" if.bind=\\\"api.auth.me | hasPermission:program:'api/v1/projects':'create'\\\" click.delegate=\\\"createProject()\\\" data-tour-id=\\\"add-project-button\\\"></button> </span> <span if.bind=\\\"!isEditing && breadcrumbs.project\\\"> <button class=\\\"button--shape--square\\\" mdc-fab mini title=\\\"Edit Boundary\\\" icon=\\\"edit\\\" if.bind=\\\"api.auth.me | hasPermission:program:'api/v1/projects':'patch'\\\" click.delegate=\\\"editProjectGeometry(breadcrumbs.project)\\\"></button> </span> <button class=\\\"button--shape--square button--color--danger\\\" mdc-fab mini title=\\\"Cancel Edits\\\" if.bind=\\\"isEditing\\\" icon=\\\"clear\\\" click.delegate=\\\"mapAdaptor.cancel()\\\"></button> <button class=\\\"m-1 button--shape--square button--color--success\\\" mdc-fab mini title=\\\"Save Edits\\\" if.bind=\\\"isEditing\\\" click.delegate=\\\"mapAdaptor.finish()\\\" icon=\\\"check\\\"></button> <div mdc-menu-surface-anchor> <ol-map-legend if.bind=\\\"showLegend\\\" map.bind=\\\"map\\\"></ol-map-legend> </div> <div mdc-menu-surface-anchor> <ol-map-selection if.bind=\\\"showSelection\\\" map.bind=\\\"map\\\" map-adaptor.bind=\\\"mapAdaptor\\\"> </ol-map-selection> </div> </div> </div> <div slot=\\\"bottom-left\\\" mdc-menu-surface-anchor if.bind=\\\"!expanded\\\"> <basemap-toggle map.bind=\\\"map\\\" layer-ids.bind=\\\"['mapbox-aerial', 'mapbox-gray']\\\" class=\\\"pointer-auto\\\"> </basemap-toggle> </div> <div slot=\\\"top-right\\\" mdc-menu-surface-anchor if.bind=\\\"!expanded\\\"> </div> </ol-map> </div> </div> </div> </template>\";\n// Exports\nmodule.exports = code;"],"sourceRoot":""}