{"version":3,"sources":["webpack:///./app/javascript/src/lib/upload.ts","webpack:///./app/javascript/src/lib/rec/recTagSuggestions.ts?d202","webpack:///./app/javascript/src/lib/rec/recTagSuggestions.ts","webpack:///./app/javascript/src/lib/rec/recTagSuggestions.vue","webpack:///./app/javascript/src/lib/rec/recTagSuggestions.vue?5343","webpack:///./app/javascript/src/lib/rec/recModal.ts?6c9d","webpack:///./app/javascript/src/lib/rec/recModal.ts","webpack:///./app/javascript/src/lib/rec/recModal.vue","webpack:///./app/javascript/src/lib/rec/recModal.vue?4f65","webpack:///./app/javascript/src/lib/rec/rec.ts","webpack:///./app/javascript/src/lib/components/autofocus.ts","webpack:///./app/javascript/src/lib/components/autosize.ts","webpack:///./app/javascript/src/lib/photo_upload/photoUploadModal.ts","webpack:///./app/javascript/src/lib/components/circleProgress.vue?d98f","webpack:///./app/javascript/src/lib/components/circleProgress.vue?023f","webpack:///./app/javascript/src/vendor/easing.ts","webpack:///./app/javascript/src/lib/components/circleProgress.ts?58e6","webpack:///./app/javascript/src/lib/components/circleProgress.ts","webpack:///./app/javascript/src/lib/components/circleProgress.vue","webpack:///./app/javascript/src/lib/photo_upload/photoUploadPreviews.vue?9b17","webpack:///./app/javascript/src/lib/photo_upload/photoUploadPreviews.ts?0a9c","webpack:///./app/javascript/src/lib/photo_upload/photoUploadPreviews.ts","webpack:///./app/javascript/src/lib/photo_upload/photoUploadPreviews.vue","webpack:///./app/javascript/src/lib/photo_upload/photoUploadPreviews.scss","webpack:///./app/javascript/src/lib/rec/recTagSuggestions.scss","webpack:///./app/javascript/src/lib/rec/recModal.scss"],"names":["Dropzone","Upload","element","options","defaultResizeTo","onDropzoneAddedFile","file","a","onBegin","getSignedUrl","json","handleError","signedUrlData","signed_url_data","imageUrl","image_url","accepted","dropzone","enqueueFile","onDropzoneSending","xhr","headers","Object","entries","headerName","headerValue","setRequestHeader","onDropzoneSuccess","onSuccess","key","onDropzoneError","error","this","$element","document","querySelector","validateElement","disableDragDropNavigation","dropzoneOptions","CSS","supports","resizeImage","width","height","resizeMethod","callback","createThumbnail","dataUrl","canvas","resizeMimeType","type","resizedDataURL","toDataURL","resizeQuality","submitRequest","formData","files","length","Error","transformedFile","get","paramName","onreadystatechange","console","log","readyState","e","ontimeout","onerror","send","on","removeAllFiles","signingUrl","csrfFetch","method","response","status","window","addEventListener","disableDropDefault","removeEventListener","removeFile","onError","assign","clickable","$uploadButton","maxFiles","previewTemplate","createImageThumbnails","baseDropzoneOptions","url","signed_url","autoQueue","acceptedFiles","parallelUploads","resizeHeight","resizeTo","resizeWidth","dataset","dataTransfer","effectAllowed","dropEffect","preventDefault","Prop","Number","default","Boolean","Component","tags","loadSuggestions","Routes","gameSuggestedTags","res","track","map","x","noun","modal","inModal","push","id","other","tag","$el","$refs","suggestions","indexOf","$emit","except","Vue","set","_vm","_h","$createElement","_c","_self","staticClass","_l","ref","refInFor","class","disabled","style","backgroundColor","color","$event","emitSelect","_v","_s","icon","n","_e","animationDelay","components","AppBtn","AppCircleProgress","AppPhotoUploadPreviews","AppRecTagSuggestions","directives","AppAutofocus","AppAutosize","HTMLElement","Watch","immediate","suggestion","business","product","review","search","topic","tagKey","tagName","tagNoun","name","phone","email","website","address","notes","photoCount","karma","isDone","isClosed","hasAdded","hasError","retry","showSuggestions","tagsLoading","submitting","doneProgress","autofocusIndex","loadTags","$nextTick","state","initSearchAutocomplete","initTagAutocomplete","submitSuggestion","toggleHamburger","hideAll","MicroModal","show","awaitCloseAnimation","disableFocus","onClose","clear","setTag","businessName","close","$photos","photos","submit","nameHasChanged","submitNotes","URLSearchParams","location","has","history","replaceState","pathname","reload","ajaxBusinessTags","$suggestions","enableAll","clearTag","disableAllExcept","autocomplete","focus","$autocomplete","limit","places","beforeNavigate","tagAutocomplete","onSelect","item","post","gameAddProductReview","gameAddBusinessReview","bind","isNewProduct","was_new_review","trackEventForBusiness","gameAddNotes","photoUpload","reviewUrl","highlight","selector","href","$modal","visibility","zIndex","openShareModal","$source","dialog","link","event","b","properties","business_id","src","trackClick","searchBusinesses","searchProducts","cities","tag_name","toLowerCase","JSON","stringify","toFixed","capitalize","signedPhotoUrl","origin","fcMetadata","user_city","attrs","modalTitle","_m","rawName","value","expression","searchUrl","autocompletePlaceholder","domProps","target","composing","citiesUrl","userCity","handleTagSuggestion","topicName","tagsPlaceholder","tagsJson","photoSigningUrl","photoAttachTo","photoAdded","trackPhotoClick","karmaFormatted","viewBusiness","shareReview","recModal","initRecModal","querySelectorAll","forEach","$i","openRecModal","$from","mountVueComponent","$on","undefined","logged_in","usersMe","createElement","className","body","insertBefore","lastChild","AppRecModal","handleRecModalClose","$search","$dialog","$content","content","elementIsTagSuggestion","classList","add","transition","then","remove","DELAY","DURATION","transitionCss","delay","duration","from","opacity","$tag","children","contains","el","wait","update","binding","oldValue","inserted","_node","initAutosize","PhotoUpload","$wrapper","removedIds","$previews","appendChild","parseAttachTo","attach","path","preview","dataURL","enableDragDropNavigation","count","attachCallback","request","ajaxRemovePhotos","ids","splice","businessKey","addBusinessPhotos","photo","image","$preview","attachTo","split","attachToBusiness","$button","previewsContainer","addRemoveLinks","dictDefaultMessage","bezier","kSampleStepSize","A","aA1","aA2","B","C","calcBezier","aT","getSlope","mX1","mY1","mX2","mY2","sampleValues","Float32Array","i","getTForX","aX","intervalStart","currentSample","kSplineTableSize","guessForT","initialSlope","aGuessT","currentSlope","newtonRaphsonIterate","aA","aB","currentX","currentT","Math","abs","binarySubdivide","t","easeOutCubic","required","String","transientProgress","progress","clamp","newProgress","oldProgress","animation","pause","anime","targets","anim","complete","min","max","thickness","size","filledBorder","PI","radius","circumference","component","viewbox","filledCircumference","inputValue","$formGroup","$btn","title","closest","wrapper","$form","attachToInput","hasRemoved","showExisting","submitRemoved","upload","$frag","createDocumentFragment","parentElement","removeExistingPhoto","prepend","combineWith","$e","replace","_t"],"mappings":"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","file":"js/1-619d07b5c4bb049d0b7a.chunk.js","sourcesContent":["import * as Dropzone from 'dropzone';\nimport 'formdata-polyfill';\nimport csrfFetch from './csrfFetch';\n\nDropzone.autoDiscover = false;\n\nexport interface Options {\n onBegin?(): void;\n onSuccess?(key): void;\n onError?(error): void;\n\n // Max height/width. Defaults to 1024\n resizeTo?: number;\n}\n\nexport default class Upload {\n public defaultResizeTo = 1024;\n public imageUrl: string;\n protected readonly $element: HTMLElement;\n protected readonly options: Options;\n protected readonly dropzone: Dropzone;\n\n static readonly paramName = 'file';\n\n // element must provide a path to the signed url endpoint in dataset.url\n constructor(element: HTMLElement | string, options: Options = {}) {\n if (typeof element === 'string') {\n this.$element = document.querySelector(element) as HTMLElement;\n } else {\n this.$element = element;\n }\n\n this.options = options;\n\n this.validateElement();\n\n this.disableDragDropNavigation();\n\n this.dropzone = new Dropzone(this.$element, this.dropzoneOptions);\n\n // This method is overridden to prevent issues with EXIF orientation\n //\n // The original method restores EXIF data after correcting for it. For browsers\n // that use `image-orientation: from image` this isn't necessary. This version doesn't\n // include that step & has been modified slightly to use newer language features.\n //\n // See: https://github.com/enyo/dropzone/pull/1876\n if (CSS.supports('image-orientation', 'from-image')) {\n this.dropzone.resizeImage = (file, width, height, resizeMethod, callback) => {\n return this.dropzone.createThumbnail(\n file,\n width,\n height,\n resizeMethod,\n true,\n (dataUrl, canvas) => {\n if (canvas == null) {\n // The image has not been resized\n return callback(file);\n }\n\n const resizeMimeType = this.dropzone.options.resizeMimeType ?? file.type;\n const resizedDataURL = canvas.toDataURL(\n resizeMimeType,\n this.dropzone.options.resizeQuality,\n );\n return callback(Dropzone.dataURItoBlob(resizedDataURL));\n },\n );\n };\n }\n\n this.dropzone.submitRequest = (xhr, formData, files) => {\n if (files.length != 1) {\n throw new Error('We do not support uploadMultiple');\n }\n\n // Override this method to send just the file itself, rather than a mutlipart form.\n // - formData is a FormData object containing the multipart data\n // - files is an array of File objects containing the original (non-resized) files\n //\n // Default implementation calls:\n // xhr.send(formData);\n // which submits as multipart form.\n //\n // We pull the resized file out of the formData using its param name\n\n const transformedFile = formData.get(Upload.paramName);\n if (transformedFile == null) {\n throw new Error('File not found');\n }\n\n // HACKHACK: Mobile safari is aggressively garbage collecting this\n // blob before it gets sent. Attach it to the xhr so that it will\n // live as long as the request.\n xhr.onreadystatechange = function () {\n try {\n // Don't delete. Mission critical log statement. See above.\n console.log(`${xhr.readyState}: ${transformedFile}`);\n } catch (e) {}\n };\n\n // Dropzone doesn't handle timeouts, so we route them to the dropzone\n // error handler.\n xhr.ontimeout = function () {\n console.log('upload timeout');\n xhr.onerror(files, xhr);\n };\n\n xhr.send(transformedFile);\n };\n\n this.dropzone.on('addedfile', this.onDropzoneAddedFile);\n this.dropzone.on('sending', this.onDropzoneSending);\n this.dropzone.on('success', this.onDropzoneSuccess);\n this.dropzone.on('error', this.onDropzoneError);\n }\n\n public reset(): void {\n this.dropzone.removeAllFiles();\n }\n\n protected async getSignedUrl() {\n if (this.signingUrl == null) {\n throw new Error('Must provide dataset.url');\n }\n\n const response = await csrfFetch(this.signingUrl, {\n method: 'POST',\n });\n if (response.status !== 200) {\n // console.error(response);\n throw new Error('getSignedUrl failed');\n }\n return await response.json();\n }\n\n protected validateElement() {\n if (this.signingUrl == null) {\n throw new Error('Must provide dataset.url');\n }\n }\n\n // By default, if you drop your photo anywhere outside the dropzone chrome\n // will navigate to it. Disable this\n protected disableDragDropNavigation() {\n window.addEventListener('dragover', disableDropDefault, false);\n window.addEventListener('drop', disableDropDefault, false);\n }\n\n // This re-enables the default drag & drop behavior\n protected enableDragDropNavigation() {\n window.removeEventListener('dragover', disableDropDefault, false);\n window.removeEventListener('drop', disableDropDefault, false);\n }\n\n //\n // events\n //\n\n protected onDropzoneAddedFile = async file => {\n if (this.options.onBegin != null) {\n this.options.onBegin();\n }\n\n // Get a signed url for direct upload\n let json;\n\n try {\n json = await this.getSignedUrl();\n } catch (e) {\n // console.error(e);\n this.handleError(file, 'Could not upload file');\n return;\n }\n\n // Stash the json for later use\n file.signedUrlData = json.signed_url_data;\n this.imageUrl = json.image_url;\n // Now we are ready to proceed with the upload. Check\n // accepted state to protect against multiple files.\n if (file.accepted) {\n this.dropzone.enqueueFile(file);\n }\n };\n\n protected onDropzoneSending = (file, xhr) => {\n // Append our headers\n const headers = file.signedUrlData.headers;\n for (const [headerName, headerValue] of Object.entries(headers)) {\n if (headerValue) {\n xhr.setRequestHeader(headerName, headerValue);\n }\n }\n };\n\n protected onDropzoneSuccess = file => {\n if (this.options.onSuccess != null) {\n const { key } = file.signedUrlData;\n this.options.onSuccess(key);\n }\n };\n\n protected onDropzoneError = (file, error) => {\n this.handleError(file, error);\n };\n\n protected handleError(file, error) {\n // Remove the thumbnail preview\n this.dropzone.removeFile(file);\n\n if (this.options.onError != null) {\n this.options.onError(error);\n }\n }\n\n //\n // getters\n //\n\n protected get dropzoneOptions(): any {\n return Object.assign(\n {\n paramName: Upload.paramName,\n clickable: this.$uploadButton,\n maxFiles: 1,\n previewTemplate: '
', // no preview\n createImageThumbnails: false,\n },\n this.baseDropzoneOptions,\n );\n }\n\n protected get baseDropzoneOptions(): any {\n return {\n url: files => {\n if (files.length != 1) {\n throw new Error('We do not support uploadMultiple');\n }\n\n return files[0].signedUrlData.signed_url;\n },\n method: 'PUT',\n // we manually enqueue after we have a signed url\n autoQueue: false,\n acceptedFiles: 'image/*',\n parallelUploads: 1,\n // don't let dropzone set a cache control header, because GCS stores it\n headers: { 'Cache-Control': null },\n\n // for resizeImage\n resizeMimeType: 'image/jpeg',\n resizeHeight: this.options.resizeTo || this.defaultResizeTo,\n resizeWidth: this.options.resizeTo || this.defaultResizeTo,\n resizeQuality: 0.85,\n };\n }\n\n protected get signingUrl() {\n return this.$element.dataset.url || null;\n }\n\n protected get $uploadButton() {\n return this.$element.querySelector('.edit-button') as HTMLElement;\n }\n}\n\nfunction disableDropDefault(e) {\n if (e.dataTransfer) {\n e.dataTransfer.effectAllowed = 'none';\n e.dataTransfer.dropEffect = 'none';\n }\n e.preventDefault();\n}\n","import mod from \"-!../../../../../node_modules/babel-loader/lib/index.js??ref--5-0!./recTagSuggestions.ts?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../../../node_modules/babel-loader/lib/index.js??ref--5-0!./recTagSuggestions.ts?vue&type=script&lang=ts&\"","import Vue from 'vue';\nimport Component from 'vue-class-component';\nimport { Prop } from 'vue-property-decorator';\nimport { ApiTag } from '../api';\nimport { get } from '../rest';\nimport Routes from '../routes';\nimport { track } from '../track';\n\nexport interface Tag extends ApiTag {\n disabled?: boolean;\n other?: boolean;\n}\n\n@Component\nexport default class AppRecTagSuggestions extends Vue {\n public $refs: {\n suggestions: HTMLDivElement[];\n };\n\n public tags: Tag[] = [];\n\n @Prop({ type: Number, default: 6 })\n public size: number;\n\n @Prop(Boolean)\n public inModal: boolean;\n\n created() {\n this.loadSuggestions();\n }\n\n // Loads the suggested tags from the API\n public async loadSuggestions() {\n // Uncomment to test the loading scenario.\n // await wait(5000);\n\n const res = await get(Routes.gameSuggestedTags());\n this.tags = res.tags;\n\n // Track the list of suggestions\n track('View Suggested Rec Categories', {\n tags: this.tags.map(x => x.noun),\n modal: this.inModal,\n });\n\n // If there's at least one suggestion\n if (this.tags.length) {\n // Add an \"Other\" option\n this.tags.push({\n id: -1,\n noun: 'Other',\n other: true,\n });\n }\n }\n\n // Emits the 'select' event\n emitSelect(tag: Tag) {\n // Find the element that corresponds to the selected tag\n const $el = this.$refs.suggestions[this.tags.indexOf(tag)];\n // Track the selection\n track('Click Suggested Rec Tag', {\n tag: tag.noun,\n modal: this.inModal,\n });\n // Emit the event\n this.$emit('select', tag, $el);\n }\n\n // Disables all tags\n public disableAllExcept(except?: Tag) {\n for (const tag of this.tags) {\n // If this tag is the exception, skip it\n if (tag === except) {\n continue;\n }\n Vue.set(tag, 'disabled', true);\n }\n }\n\n // Enables all tags\n public enableAll() {\n for (const tag of this.tags) {\n Vue.delete(tag, 'disabled');\n }\n }\n}\n","import { render, staticRenderFns } from \"./recTagSuggestions.vue?vue&type=template&id=4ffe4d60&scoped=true&lang=pug&\"\nimport script from \"./recTagSuggestions.ts?vue&type=script&lang=ts&\"\nexport * from \"./recTagSuggestions.ts?vue&type=script&lang=ts&\"\nimport style0 from \"./recTagSuggestions.scss?vue&type=style&index=0&id=4ffe4d60&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"4ffe4d60\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"suggestions\"},[_vm._l((_vm.tags),function(tag){return _c('div',{ref:\"suggestions\",refInFor:true,staticClass:\"suggestion\",class:{ disabled: tag.disabled, other: tag.other },style:({ backgroundColor: tag.color }),on:{\"click\":function($event){return _vm.emitSelect(tag)}}},[_c('div',{staticClass:\"name\"},[_vm._v(_vm._s(tag.noun))]),_c('div',{staticClass:\"tag-image\"},[_c('div',{class:tag.icon})])])}),_vm._l((_vm.size),function(n){return (!_vm.tags.length)?_c('div',{staticClass:\"placeholder\",style:({ animationDelay: ((500 + 250 * n) + \"ms\") })}):_vm._e()})],2)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../../../node_modules/babel-loader/lib/index.js??ref--5-0!./recModal.ts?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../../../node_modules/babel-loader/lib/index.js??ref--5-0!./recModal.ts?vue&type=script&lang=ts&\"","import MicroModal from 'micromodal';\nimport { hideAll } from 'tippy.js';\nimport Vue from 'vue';\nimport Component from 'vue-class-component';\nimport { Prop, Watch } from 'vue-property-decorator';\nimport { ApiBusiness, ApiProduct, ApiReview } from '../api';\nimport tagAutocomplete from '../autocomplete/tagAutocomplete';\nimport { AppAutofocus } from '../components/autofocus';\nimport { AppAutosize } from '../components/autosize';\nimport AppBtn from '../components/btn.vue';\nimport AppCircleProgress from '../components/circleProgress.vue';\nimport { fcMetadata } from '../fc_metadata';\nimport { toggleHamburger } from '../hamburger';\nimport { highlight } from '../highlighter';\nimport AppPhotoUploadPreviews from '../photo_upload/photoUploadPreviews.vue';\nimport { get, post } from '../rest';\nimport Routes, {\n ApiGameAddBusinessReviewResponse,\n ApiGameAddNotesResponse,\n ApiGameAddProductReviewResponse,\n ApiTagsResponse,\n} from '../routes';\nimport { BusinessSuggestion, DefaultSuggestion, PlaceSuggestion, search } from '../search';\nimport { openShareModal } from '../share';\nimport { track } from '../track';\nimport { capitalize } from '../util';\n// @ts-ignore\nimport { Tag } from './recTagSuggestions.ts';\nimport AppRecTagSuggestions from './recTagSuggestions.vue';\n\ntype Suggestion = BusinessSuggestion | DefaultSuggestion | PlaceSuggestion;\ntype State = 'search' | 'topic' | 'tag' | 'notes' | 'done' | 'error' | 'closed';\ntype Topic = 'business' | 'product';\n\n@Component({\n components: {\n AppBtn,\n AppCircleProgress,\n AppPhotoUploadPreviews,\n AppRecTagSuggestions,\n },\n directives: {\n AppAutofocus,\n AppAutosize,\n },\n})\nexport default class AppRecModal extends Vue {\n public suggestion: Suggestion | null = null;\n public business: ApiBusiness | null = null;\n public product: ApiProduct | null = null;\n public review: ApiReview | null = null;\n public search = '';\n public topic: Topic | null = null;\n public tagKey = '';\n public tagName = '';\n public tagNoun = '';\n public name = '';\n public phone = '';\n public email = '';\n public website = '';\n public address = '';\n public notes = '';\n public photoCount = 0;\n public karma = 400;\n public isDone = false;\n public isClosed = false;\n public hasAdded = false;\n public hasError = false;\n public retry: (() => Promise) | null = null;\n public showSuggestions = false;\n\n public tags: string[] = [];\n public tagsLoading = true;\n public submitting = false;\n public doneProgress = 0;\n\n // To trigger the autofocus for inputs, we need to tell it that it's a new\n // instance of the modal so that it'll trigger again. We just increment this\n // each time we show the modal again.\n public autofocusIndex = 0;\n\n public $refs: {\n modal: HTMLDivElement;\n dialog: HTMLDivElement;\n content: HTMLDivElement;\n suggestions: AppRecTagSuggestions;\n autocomplete: HTMLInputElement;\n tagName: HTMLInputElement;\n phone: HTMLInputElement;\n email: HTMLInputElement;\n website: HTMLInputElement;\n address: HTMLInputElement;\n notes: HTMLTextAreaElement;\n photos: AppPhotoUploadPreviews;\n };\n\n @Prop(HTMLElement)\n public $from: HTMLElement | null;\n\n get searchUrl() {\n if (this.topic === 'business') {\n return Routes.searchBusinesses(this.tagKey);\n }\n return Routes.searchProducts(this.tagKey);\n }\n\n get citiesUrl() {\n return Routes.cities();\n }\n\n get state(): State {\n if (this.isClosed) {\n return 'closed';\n }\n if (this.hasError) {\n return 'error';\n }\n if (!this.topic) {\n return 'topic';\n }\n if (!this.suggestion) {\n return 'search';\n }\n if (!this.suggestion.tag_name && this.topic !== 'product') {\n return 'tag';\n }\n if (!this.isDone) {\n return 'notes';\n }\n return 'done';\n }\n\n get autocompletePlaceholder() {\n // This condition checks tagName instead of tagNoun in order to\n // avoid issues with the 'Other' pseudotag\n if (this.tagName) {\n return `Which ${this.tagNoun.toLowerCase()}?`;\n }\n if (this.topic === 'business') {\n return 'Who would you like to recommend?';\n }\n return 'What would you like to recommend?';\n }\n\n get isNewProduct() {\n return this.topic === 'product' && !(this.suggestion as any)?.id;\n }\n\n get nameHasChanged() {\n return this.name !== this.suggestion?.name && this.name.length >= 3;\n }\n\n get tagsJson() {\n // The tag autocomplete needs a JSON dataset.\n return JSON.stringify(this.tags);\n }\n\n get tagsPlaceholder() {\n return 'Doctor, Hair, Plumber, etc';\n }\n\n get karmaFormatted() {\n return this.karma < 1000 ? `${this.karma}` : `${(this.karma / 1000).toFixed(1)}k`;\n }\n\n get modalTitle() {\n if (this.topic) {\n return `New ${capitalize(this.topic)} Recommendation`;\n }\n return 'New Recommendation';\n }\n\n get photoAttachTo() {\n return `review#${this.review?.id}`;\n }\n\n get photoSigningUrl() {\n return Routes.signedPhotoUrl();\n }\n\n get reviewUrl() {\n if (this.review == null) {\n return '';\n }\n if (this.product) {\n return `${location.origin}/p/${this.product.key!}#review-${this.review.id}`;\n }\n return `${location.origin}/${this.business!.key!}#review-${this.review.id}`;\n }\n\n get topicName() {\n switch (this.topic) {\n case 'business':\n return 'pro';\n case 'product':\n return 'product';\n default:\n return '';\n }\n }\n\n get userCity() {\n return fcMetadata.user_city;\n }\n\n public mounted() {\n // Start loading the tags immediately so that we have them if we need\n // to ask them to choose a tag for their recommendation.\n this.loadTags();\n }\n\n @Watch('state', { immediate: true })\n public async onStageChange() {\n // Gotta wait for the DOM to apply any data changes.\n await this.$nextTick();\n\n switch (this.state) {\n case 'search':\n this.initSearchAutocomplete();\n break;\n\n case 'tag':\n this.initTagAutocomplete();\n break;\n\n case 'notes':\n // Mark that they've added a recommendation so that we know to reload the\n // page when they close.\n this.hasAdded = true;\n\n // When switching to the notes page, we want to immediately apply their\n // chosen option for the business they're recommending.\n this.submitSuggestion();\n break;\n\n case 'done':\n this.doneProgress = 0;\n await this.$nextTick();\n this.doneProgress = 100;\n break;\n }\n }\n\n public show(\n options: {\n businessName?: string;\n tag?: Tag;\n topic?: string;\n } = {},\n ) {\n // If they opened the rec modal from the hamburger menu, make sure it's\n // closed.\n toggleHamburger(false);\n hideAll();\n\n MicroModal.show('rec-modal', {\n awaitCloseAnimation: true,\n disableFocus: true,\n onClose: () => this.onClose(),\n });\n\n this.clear();\n\n // If they've already selected a tag\n if (options.tag) {\n // Apply it and hide the suggestions\n this.setTag(options.tag);\n this.showSuggestions = false;\n } else {\n this.showSuggestions = true;\n }\n\n this.search = options.businessName ?? '';\n this.topic = (options.topic || null) as Topic;\n\n // Leave this out of clear since if they keep adding more recommendations we\n // still want to store that they've added at least one.\n this.hasAdded = false;\n\n track('Open Rec Modal');\n }\n\n public close() {\n MicroModal.close('rec-modal');\n }\n\n public async submit() {\n if (this.state === 'tag') {\n // Once this gets set, the state will change, and the suggestion will\n // submit through the @Watch above.\n // Use Vue.set here to ensure that the property is reactive.\n Vue.set(this.suggestion!, 'tag_name', this.tagName);\n Vue.set(this.suggestion!, 'phone', this.phone);\n Vue.set(this.suggestion!, 'email', this.email);\n Vue.set(this.suggestion!, 'website', this.website);\n Vue.set(this.suggestion!, 'address', this.address);\n this.tagKey = '';\n this.tagName = '';\n this.tagNoun = '';\n this.phone = '';\n this.email = '';\n this.website = '';\n this.address = '';\n } else if (this.state === 'notes') {\n const $photos = this.$refs.photos as any;\n await $photos.submit();\n if (this.notes || $photos.photos.length || this.nameHasChanged) {\n await this.submitNotes();\n }\n this.isDone = true;\n }\n }\n\n public restart() {\n this.clear();\n this.showSuggestions = true;\n track('Restart Rec Modal');\n }\n\n private clear() {\n // Clear everything out to start fresh.\n this.suggestion = null;\n this.business = null;\n this.review = null;\n this.search = '';\n this.tagKey = '';\n this.tagName = '';\n this.tagNoun = '';\n this.topic = null;\n this.phone = '';\n this.email = '';\n this.website = '';\n this.address = '';\n this.notes = '';\n this.doneProgress = 0;\n this.karma = 0;\n this.isDone = false;\n this.isClosed = false;\n this.hasError = false;\n this.retry = null;\n ++this.autofocusIndex;\n }\n\n private onClose() {\n // Emit a Vue event for this closing\n this.$emit('close');\n\n if (new URLSearchParams(location.search).has('add')) {\n // This will remove the query from the URL so that going back to this\n // page in history won't pop the modal up again after they've closed\n // it.\n history.replaceState(history.state, '', location.pathname);\n }\n\n if (this.hasAdded) {\n // We reload the page if they've added at least one recommendation so that\n // we can show it on the page.\n window.location.reload();\n }\n\n this.isClosed = true;\n this.showSuggestions = false;\n }\n\n private async loadTags() {\n // Uncomment to test the loading scenario.\n // await wait(5000);\n\n this.tags = await get(Routes.ajaxBusinessTags());\n this.tagsLoading = false;\n }\n\n private clearTag() {\n this.tagKey = '';\n this.tagName = '';\n this.tagNoun = '';\n }\n\n private setTag(tag: Tag) {\n this.tagKey = tag.key || '';\n this.tagName = tag.name || '';\n this.tagNoun = tag.noun || '';\n }\n\n private handleTagSuggestion(tag: Tag) {\n const $suggestions = this.$refs.suggestions as any;\n // If this was already selected\n if (tag.disabled === false) {\n // Deselect it\n $suggestions.enableAll();\n this.clearTag();\n return;\n }\n // Emphasize the selected suggestion\n tag.disabled = false;\n $suggestions.disableAllExcept(tag);\n // Update the current tag\n this.setTag(tag);\n // Focus on the search input\n this.$refs.autocomplete.focus();\n }\n\n private initSearchAutocomplete() {\n const $autocomplete = this.$refs.autocomplete;\n search($autocomplete, {\n limit: 6,\n places: this.topic == 'business',\n beforeNavigate: (suggestion: Suggestion) => {\n // We don't submit until they press Save.\n this.suggestion = suggestion;\n return null;\n },\n });\n }\n\n private initTagAutocomplete() {\n tagAutocomplete(this.$refs.tagName, {\n onSelect: (e: Event, item: string) => {\n this.tagName = item;\n },\n });\n }\n\n private async submitSuggestion() {\n if (!this.suggestion) {\n return;\n }\n\n this.submitting = true;\n this.hasError = false;\n let response;\n try {\n if (this.topic === 'product') {\n response = await post(\n Routes.gameAddProductReview(this.suggestion),\n );\n } else {\n response = await post(\n Routes.gameAddBusinessReview(this.suggestion),\n );\n }\n } catch (e) {\n console.error(e);\n this.hasError = true;\n this.retry = this.submitSuggestion.bind(this);\n return;\n }\n\n if (this.topic === 'product') {\n this.product = response.product;\n } else {\n this.business = response.business;\n }\n if (this.isNewProduct) {\n this.name = this.product?.name || '';\n } else {\n this.name = '';\n }\n this.review = response.review;\n this.karma = response.karma;\n this.submitting = false;\n\n // If they had selected a review they already submitted before, it's\n // basically a no-op. Take them to the \"finished\" page and skip showing\n // notes.\n if (!response.was_new_review) {\n this.trackEventForBusiness('Added Duplicate Review');\n this.isDone = true;\n return;\n }\n\n this.trackEventForBusiness('Add Review');\n }\n\n private async submitNotes() {\n if (!this.review) {\n return;\n }\n\n this.hasError = false;\n let response;\n try {\n const $photos = this.$refs.photos as any;\n response = await post(\n Routes.gameAddNotes(this.review.id, this.notes, $photos.photos, this.name),\n );\n $photos.photoUpload.track();\n } catch (e) {\n console.error(e);\n this.hasError = true;\n this.retry = this.submitNotes.bind(this);\n return;\n }\n\n this.karma = response.karma;\n\n this.trackEventForBusiness('Add Note');\n }\n\n private viewBusiness() {\n if (!this.review || !this.reviewUrl) {\n return;\n }\n // This will scroll to the user's review after redirecting to the business page\n highlight({ selector: this.notes ? `.review-${this.review.id}` : '.small-reviews' });\n location.href = this.reviewUrl;\n }\n\n private async shareReview() {\n const $modal = this.$refs.modal;\n $modal.style.visibility = 'hidden';\n $modal.style.zIndex = '-1';\n await openShareModal({\n $source: this.$refs.dialog,\n link: this.reviewUrl,\n });\n $modal.style.visibility = '';\n $modal.style.zIndex = '';\n }\n\n private photoAdded() {\n this.photoCount++;\n }\n\n private trackEventForBusiness(event: string) {\n if (!this.business) {\n return;\n }\n\n const b = this.business;\n const properties = {\n business: b.name,\n business_id: b.id,\n tag: b.tag!.name,\n phone: b.phone,\n email: b.email,\n website: b.website,\n address: b.address,\n src: 'recmodal',\n };\n track(event, properties);\n }\n\n private trackPhotoClick() {\n (this.$refs.photos as any).photoUpload.trackClick();\n }\n}\n","import { render, staticRenderFns } from \"./recModal.vue?vue&type=template&id=d3caae68&scoped=true&lang=pug&\"\nimport script from \"./recModal.ts?vue&type=script&lang=ts&\"\nexport * from \"./recModal.ts?vue&type=script&lang=ts&\"\nimport style0 from \"./recModal.scss?vue&type=style&index=0&id=d3caae68&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"d3caae68\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:\"modal\",staticClass:\"modal\",attrs:{\"id\":\"rec-modal\"}},[_c('div',{ref:\"dialog\",staticClass:\"modal-dialog\"},[_c('div',{ref:\"content\",staticClass:\"modal-content\"},[_c('div',{staticClass:\"modal-header\"},[_c('h5',{staticClass:\"modal-title\"},[_vm._v(_vm._s(_vm.modalTitle))]),_c('button',{staticClass:\"close\",attrs:{\"data-micromodal-close\":\"1\"}},[_vm._v(\"×\")])]),_c('div',{staticClass:\"modal-body\"},[(_vm.state === \"topic\")?_c('div',{key:\"topic\"},[_c('div',{staticClass:\"question\"},[_vm._v(\"What would you like to recommend?\")]),_c('div',{staticClass:\"answers\"},[_c('div',{staticClass:\"answer\",on:{\"click\":function($event){_vm.topic = \"business\"}}},[_c('header',[_vm._v(\"Business\")]),_c('div',{staticClass:\"eg\"},[_vm._v(\"Local professionals\")]),_vm._m(0)]),_c('div',{staticClass:\"answer\",on:{\"click\":function($event){_vm.topic = \"product\"}}},[_c('header',[_vm._v(\"Product\")]),_c('div',{staticClass:\"eg\"},[_vm._v(\"Things you own\")]),_vm._m(1)])])]):(_vm.state === \"search\")?_c('div',{key:\"search\",class:\"search-topic-\" + _vm.topic},[_c('input',{directives:[{name:\"app-autofocus\",rawName:\"v-app-autofocus\",value:(_vm.autofocusIndex),expression:\"autofocusIndex\"},{name:\"model\",rawName:\"v-model\",value:(_vm.search),expression:\"search\"}],ref:\"autocomplete\",staticClass:\"form-control search search-no-icon\",attrs:{\"type\":\"text\",\"autocapitalize\":\"off\",\"autocomplete\":\"off\",\"autocorrect\":\"off\",\"maxlength\":\"128\",\"data-search-url\":_vm.searchUrl,\"placeholder\":_vm.autocompletePlaceholder},domProps:{\"value\":(_vm.search)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.search=$event.target.value}}}),(_vm.topic === \"business\")?_c('div',{staticClass:\"search-location\"},[_c('a',{attrs:{\"href\":_vm.citiesUrl}},[_vm._v(\"Searching near \"),_c('div',{staticClass:\"search-location-city\"},[_vm._v(_vm._s(_vm.userCity.name))])])]):_vm._e(),(_vm.showSuggestions && _vm.topic === \"business\")?_c('app-rec-tag-suggestions',{ref:\"suggestions\",attrs:{\"in-modal\":\"\"},on:{\"select\":_vm.handleTagSuggestion}}):_vm._e(),(_vm.topic === \"product\")?_c('div',{staticClass:\"product-search-suggestions\"},[_c('div',{staticClass:\"prompt\"},[_vm._v(\"Enter the name of the product\")]),_vm._m(2)]):_vm._e()],1):(_vm.state === \"tag\")?_c('div',{key:\"tag\"},[(_vm.tagsLoading)?_c('div',[_vm._m(3)]):_c('div',[_c('h5',[_vm._v(_vm._s(_vm.suggestion.name))]),_c('div',{staticClass:\"row form-group mt-3\"},[_c('label',{staticClass:\"form-control-label col-form-label col-12\"},[_vm._v(_vm._s((\"Choose a category for this \" + _vm.topicName + \":\")))]),_c('div',{staticClass:\"col-12\"},[_c('input',{directives:[{name:\"app-autofocus\",rawName:\"v-app-autofocus\",value:(_vm.autofocusIndex),expression:\"autofocusIndex\"},{name:\"model\",rawName:\"v-model\",value:(_vm.tagName),expression:\"tagName\"}],ref:\"tagName\",staticClass:\"form-control\",attrs:{\"type\":\"text\",\"autocomplete\":\"off\",\"spellcheck\":\"false\",\"placeholder\":_vm.tagsPlaceholder,\"data-tags\":_vm.tagsJson},domProps:{\"value\":(_vm.tagName)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.tagName=$event.target.value}}})])]),(_vm.topic === \"business\")?_c('div',{staticClass:\"additional-info d-none d-md-block toggle\"},[_vm._m(4),_c('div',{staticClass:\"extra-fields\"},[_c('div',{staticClass:\"row form-group mt-3\"},[_c('label',{staticClass:\"form-control-label col-form-label col-2\"},[_vm._v(\"Phone:\")]),_c('div',{staticClass:\"col-10\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.phone),expression:\"phone\"}],ref:\"phone\",staticClass:\"form-control string tel optional\",attrs:{\"type\":\"tel\",\"autocomplete\":\"off\",\"spellcheck\":\"false\",\"placeholder\":\"(206) 555-1212\"},domProps:{\"value\":(_vm.phone)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.phone=$event.target.value}}})])]),_c('div',{staticClass:\"row form-group mt-3\"},[_c('label',{staticClass:\"form-control-label col-form-label col-2\"},[_vm._v(\"Email:\")]),_c('div',{staticClass:\"col-10\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.email),expression:\"email\"}],ref:\"email\",staticClass:\"form-control\",attrs:{\"type\":\"email\",\"autocomplete\":\"off\",\"spellcheck\":\"false\",\"placeholder\":\"contact@thisbusiness.com\"},domProps:{\"value\":(_vm.email)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.email=$event.target.value}}})])]),_c('div',{staticClass:\"row form-group mt-3\"},[_c('label',{staticClass:\"form-control-label col-form-label col-2\"},[_vm._v(\"Website:\")]),_c('div',{staticClass:\"col-10\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.website),expression:\"website\"}],ref:\"website\",staticClass:\"form-control\",attrs:{\"type\":\"url\",\"autocomplete\":\"off\",\"spellcheck\":\"false\",\"placeholder\":\"https://www.example.com\"},domProps:{\"value\":(_vm.website)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.website=$event.target.value}}})])]),_c('div',{staticClass:\"row form-group mt-3\"},[_c('label',{staticClass:\"form-control-label col-form-label col-2\"},[_vm._v(\"Address:\")]),_c('div',{staticClass:\"col-10\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.address),expression:\"address\"}],ref:\"address\",staticClass:\"form-control\",attrs:{\"type\":\"text\",\"autocomplete\":\"off\",\"spellcheck\":\"false\",\"placeholder\":\"123 Main St, Seattle, WA 98104\"},domProps:{\"value\":(_vm.address)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.address=$event.target.value}}})])]),_vm._m(5)])]):_vm._e(),_c('div',{staticClass:\"controls mt-4\"},[_c('app-btn',{on:{\"click\":function($event){return _vm.submit()}}},[_vm._v(\"Add\")])],1)])]):(_vm.state === \"notes\")?_c('div',{key:\"notes\"},[(_vm.submitting)?_c('div',[_vm._m(6)]):_c('div',[_c('div',{staticClass:\"anim-zoom-in\"},[_c('div',{staticClass:\"alert alert-success\"},[_vm._v(\"Your recommendation has been added.\")]),_c('div',{staticClass:\"lead-in\"},[_vm._v(_vm._s((\"Tell us why you love\" + (_vm.topic === \"product\" ? \" your\" : \"\"))))]),(!_vm.isNewProduct)?_c('h5',[_vm._v(_vm._s(_vm.suggestion.name))]):_c('div',{staticClass:\"name form-group\"},[_c('input',{directives:[{name:\"model\",rawName:\"v-model\",value:(_vm.name),expression:\"name\"}],ref:\"name\",staticClass:\"form-control string optional\",attrs:{\"maxlength\":\"128\"},domProps:{\"value\":(_vm.name)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.name=$event.target.value}}})]),_c('div',{staticClass:\"notes form-group combined-with-photo-upload\"},[_c('textarea',{directives:[{name:\"app-autofocus\",rawName:\"v-app-autofocus\",value:(_vm.autofocusIndex),expression:\"autofocusIndex\"},{name:\"app-autosize\",rawName:\"v-app-autosize\"},{name:\"model\",rawName:\"v-model\",value:(_vm.notes),expression:\"notes\"}],ref:\"notes\",staticClass:\"form-control\",attrs:{\"placeholder\":\"Share a few words!\",\"rows\":\"4\",\"maxlength\":\"4096\"},domProps:{\"value\":(_vm.notes)},on:{\"input\":function($event){if($event.target.composing){ return; }_vm.notes=$event.target.value}}}),_c('div',{staticClass:\"photo-upload-clickable\"}),_c('div',{staticClass:\"dropzone-wrapper\"}),_c('app-photo-upload-previews',{ref:\"photos\",attrs:{\"url\":_vm.photoSigningUrl,\"attachTo\":_vm.photoAttachTo,\"type\":\"Review\"},on:{\"added\":_vm.photoAdded,\"click\":_vm.trackPhotoClick}})],1)]),_c('div',{staticClass:\"controls mt-4\"},[(!_vm.notes && !_vm.photoCount && !_vm.nameHasChanged)?_c('app-btn',{attrs:{\"variant\":\"outline\"},on:{\"click\":function($event){return _vm.submit()}}},[_vm._v(\"Maybe later\")]):_c('app-btn',{on:{\"click\":function($event){return _vm.submit()}}},[_vm._v(\"Save\")])],1)])]):(_vm.state === \"done\")?_c('div',{key:\"done\"},[_c('div',{staticClass:\"text-center\"},[_c('h4',[_vm._v(\"Thanks for your recommendation!\")]),_c('div',{staticClass:\"done-progress mt-4\"},[_c('app-circle-progress',{staticClass:\"progress-indicator\",attrs:{\"progress\":_vm.doneProgress,\"thickness\":3,\"size\":250,\"color\":\"#1f9e9e\"}}),_c('div',{staticClass:\"text anim-zoom-pop\"},[_vm._v(_vm._s(_vm.karmaFormatted))])],1),_c('div',{staticClass:\"karma-label mt-2\"},[_vm._v(\"Your Karma\")]),_c('div',{staticClass:\"end-btns mt-4\"},[_c('app-btn',{attrs:{\"variant\":\"outline\"},on:{\"click\":function($event){return _vm.viewBusiness()}}},[_vm._v(\"View Recommendation\")]),_c('app-btn',{on:{\"click\":function($event){return _vm.shareReview()}}},[_vm._v(\"Share Recommendation\")])],1)])]):(_vm.state === \"error\")?_c('div',{key:\"error\"},[_c('div',{staticClass:\"text-center\"},[_c('h4',{staticClass:\"mb-3\"},[_vm._v(\"Something went wrong\")]),_c('app-btn',{on:{\"click\":function($event){return _vm.retry()}}},[_vm._v(\"Retry\")])],1)]):_vm._e()])])])])}\nvar staticRenderFns = [function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('ul',[_c('li',[_vm._v(\"Doctors\")]),_c('li',[_vm._v(\"Hair Salons\")]),_c('li',[_vm._v(\"Auto Mechanics\")])])},function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('ul',[_c('li',[_vm._v(\"Bikes\")]),_c('li',[_vm._v(\"Vacuum Cleaners\")]),_c('li',[_vm._v(\"Water Bottles\")])])},function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('ul',[_c('li',[_vm._v(\"Brompton Electric Bike\")]),_c('li',[_vm._v(\"Miele Vacuum\")]),_c('li',[_vm._v(\"Hydro Flask\")])])},function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"d-flex align-items-center\"},[_c('div',{staticClass:\"progress-spinner\"}),_c('strong',{staticClass:\"ml-3\"},[_vm._v(\"Loading...\")])])},function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"show-more row form-text mt-3 col-12\"},[_c('a',{attrs:{\"href\":\"#\",\"data-toggle\":\"toggle\",\"data-target\":\".additional-info\"}},[_vm._v(\"Add more contact info\")])])},function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"row col-10\"},[_c('small',{staticClass:\"text-muted form-text\"},[_vm._v(\"These are all optional, just fill in what you can.\")])])},function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{staticClass:\"d-flex align-items-center\"},[_c('div',{staticClass:\"progress-spinner\"}),_c('strong',{staticClass:\"ml-3\"},[_vm._v(\"Adding...\")])])}]\n\nexport { render, staticRenderFns }","import Routes from '../../lib/routes';\nimport { fcMetadata } from '../fc_metadata';\nimport transition, { transitionCss } from '../transition';\nimport { mountVueComponent } from '../vue';\n// @ts-ignore\nimport AppRecModalType from './recModal.ts';\nimport AppRecModal from './recModal.vue';\n// @ts-ignore\nimport { Tag } from './recTagSuggestions.ts';\nimport AppRecTagSuggestions from './recTagSuggestions.vue';\n\n/**\n * The first time we initialize the rec modal, we store it here and leave it in\n * the DOM (just hide/show it).\n */\nlet recModal: AppRecModalType | null = null;\n\nexport function initRecModal() {\n document.querySelectorAll('.open-rec-modal').forEach(($i: HTMLElement) => {\n const { topic } = $i.dataset;\n $i.addEventListener('click', () => openRecModal({ $from: $i, topic }));\n });\n document.querySelectorAll('.mount-rec-tag-suggestions').forEach($i => {\n const suggestions = mountVueComponent($i, AppRecTagSuggestions);\n suggestions.$on('select', (tag: Tag, $el: HTMLElement) => {\n openRecModal({\n tag,\n topic: !tag.other ? 'business' : undefined,\n $from: $el,\n });\n });\n });\n}\n\ninterface RecModalOptions {\n $from?: HTMLElement;\n tag?: Tag;\n topic?: string;\n}\n\nexport async function openRecModal(options: RecModalOptions = {}) {\n if (!fcMetadata.logged_in) {\n window.location.href = Routes.usersMe(true);\n return;\n }\n\n // If we haven't created the global rec modal yet, let's create/mount it. From\n // then on we can just show/hide it.\n if (!recModal) {\n const $modal = document.createElement('div');\n $modal.className = 'mount-rec-modal';\n document.body.insertBefore($modal, document.body.lastChild);\n recModal = mountVueComponent('.mount-rec-modal', AppRecModal);\n recModal.$on('close', handleRecModalClose);\n }\n\n // default rec search term to contents of header search box\n const $search = document.querySelector('#search_box') as HTMLInputElement;\n recModal.show({\n businessName: $search?.value,\n tag: options.tag,\n topic: options.topic,\n });\n\n // If $from was omitted, stop here\n const { $from } = options;\n if (!$from) {\n return;\n }\n\n // Wait for the element to update its state\n await recModal.$nextTick();\n\n // Animate the modal from the $from element\n const $dialog = recModal.$refs.dialog;\n const $content = recModal.$refs.content;\n // Style initial state\n if (elementIsTagSuggestion($from)) {\n // This sets to the visibility while the modal is open; when the modal is\n // closed, handleRecModalClose resets this property\n recModal.$from = $from;\n $from.style.visibility = 'hidden';\n }\n\n // Animate the modal from the $from element\n $dialog.classList.add('opening');\n transition($from, $dialog).then(() => $dialog.classList.remove('opening'));\n // Fade in modal contents after a delay\n const DURATION = 400; // ms\n const DELAY = DURATION * 0.75;\n transitionCss($content, {\n delay: DELAY,\n duration: DURATION - DELAY,\n from: {\n opacity: '0',\n },\n });\n}\n\nfunction handleRecModalClose() {\n if (!recModal) {\n return;\n }\n // If this isn't from a tag suggestion, do nothing\n const $tag = recModal.$from as HTMLElement | null;\n recModal.$from = null;\n if (!$tag || !elementIsTagSuggestion($tag)) {\n return;\n }\n // Animate the modal back to the source\n const $dialog = recModal.$refs.dialog;\n // Initial state\n $dialog.style.opacity = '0'; // Hide the modal\n $tag.style.visibility = ''; // Show the suggested tag\n $tag.style.zIndex = '100'; // Make sure it appears on top of other elements\n // Animate the suggested tag element from the modal element\n transition($dialog, $tag).then(() => {\n // Reset inline styles\n $dialog.style.opacity = '';\n $tag.style.zIndex = '';\n });\n // Fade in child elements after a delay\n const DURATION = 400; // ms\n const DELAY = DURATION * 0.75;\n transitionCss($tag.children, {\n delay: DELAY,\n duration: DURATION - DELAY,\n from: {\n opacity: '0',\n },\n });\n}\n\n// Helper methods\n\n// Whether the given element is a suggestion element within an\n// AppRecTagSuggestion component\nfunction elementIsTagSuggestion($el: HTMLElement): boolean {\n return $el.classList.contains('suggestion');\n}\n","import { DirectiveOptions } from 'vue';\nimport { wait } from '../util';\n\n/**\n * Simple directive to autofocus an input element when it gets mounted into the\n * DOM.\n */\nexport const AppAutofocus: DirectiveOptions = {\n async bind(el) {\n // Gotta wait till the input is fully bound to the DOM.\n await wait(0);\n el.focus();\n },\n update(el, binding) {\n // This gets called any time the component re-renders. We need to make sure\n // to only re-focus if our binding changed.\n if (binding.value !== binding.oldValue) {\n el.focus();\n }\n },\n};\n","import { DirectiveOptions } from 'vue';\nimport { wait } from '../../lib/util';\nimport { initAutosize } from '../autosize';\n\n/**\n * Initializes autosize on the element.\n */\nexport const AppAutosize: DirectiveOptions = {\n async inserted(el, _node) {\n // Wait for the input to be mounted into the DOM.\n await wait(0);\n initAutosize(el);\n },\n};\n","import MicroModal from 'micromodal';\nimport { post, request } from '../rest';\nimport Routes from '../routes';\nimport { track } from '../track';\nimport Upload, { Options } from '../upload';\n\n//\n// A component that allows users to upload multiple files at once (although not\n// in parallel)\n//\n// This can take various options to listen to events, and will automatically\n// create an area where users can drop files or click to select from a file picker\n// dialog prompt. Selected files are shown as previews & progress for each upload\n// is shown individually.\n//\n// This can be displayed as a modal using Micromodal, or used directly within\n// any other wrapper element.\n//\n\nexport interface PhotoInfo {\n // path to the uploaded photo\n path: string;\n // base-64 image used for preview\n preview: string;\n // dimensions\n width?: number;\n height?: number;\n}\n\ninterface PhotoUploadOptions extends Options {\n // The record type to attach this to after upload\n attachTo?: string;\n // The callback used when attaching these files after upload\n attachCallback?(photos: PhotoInfo[]): Promise;\n // The button that should open the file picker\n $button?: HTMLElement;\n // The element to attach Dropzone to\n $element?: HTMLElement;\n // The element to contain Dropzone previews in\n $previews?: HTMLElement;\n // The signing URL\n url?: string;\n // Whether to reload when the modal is closed (if any photos were uploaded)\n reload?: boolean;\n // The type of parent record (used for analytics)\n type?: string;\n // Called when the modal has closed\n callback?(photos: PhotoInfo[]): void;\n}\n\nexport default class PhotoUpload extends Upload {\n public defaultResizeTo = 2048;\n public readonly options: PhotoUploadOptions;\n private readonly $wrapper: HTMLElement;\n private removedIds: string[] = [];\n\n static readonly paramName = 'file';\n\n constructor($wrapper: HTMLElement, options: PhotoUploadOptions = {}) {\n super(options.$element ?? document.createElement('div'), options);\n (options.$previews ?? this.$element).classList.add('dropzone-wrapper');\n this.$wrapper = $wrapper;\n this.options = options;\n if (!options.$element) {\n this.$wrapper.appendChild(this.$element);\n }\n\n // Handle simple record creation for uploads\n this.parseAttachTo();\n }\n\n // Removes all photos from this component\n public clear() {\n for (const file of this.dropzone.files) {\n this.dropzone.removeFile(file);\n }\n }\n\n //\n // modal\n //\n\n public show() {\n // Setup the modal elements.\n\n MicroModal.show('photo-upload-modal', {\n disableFocus: true,\n onClose: this.onClose.bind(this),\n });\n\n this.trackClick();\n }\n\n public onClose() {\n this.$element?.remove();\n this.attach();\n if (this.options.callback) {\n this.options.callback(\n this.dropzone.files.map(x => ({\n path: x.signedUrlData.key,\n preview: x.dataURL,\n })),\n );\n }\n const count = this.dropzone.files.length;\n if (count) {\n this.track();\n if (this.options.reload) {\n location.reload();\n }\n }\n this.enableDragDropNavigation();\n }\n\n //\n // attachTo helpers\n //\n\n // Tracks clicking on the upload photos button\n public trackClick() {\n if (!this.options.type) {\n return;\n }\n track(`Click Upload ${this.options.type} Photos`);\n }\n\n // Tracks photos being uploaded\n public track() {\n const count = this.dropzone.files.length;\n if (!this.options.type || !count) {\n return;\n }\n track(`Upload ${this.options.type} Photos`, { count });\n }\n\n // Attempts to attach all of the files from the Dropzone\n public attach() {\n if (!this.options.attachCallback) {\n return;\n }\n const { photos } = this;\n if (!photos.length) {\n return;\n }\n this.options.attachCallback(this.photos);\n return;\n }\n\n // Submits IDs of existing photos that have been removed\n public async submitRemoved() {\n await request(Routes.ajaxRemovePhotos(), 'DELETE', { ids: this.removedIds });\n this.removedIds.splice(0);\n }\n\n public attachToBusiness(businessKey: string, photos: PhotoInfo[]) {\n return post(Routes.addBusinessPhotos(businessKey), {\n photo: photos.map(x => ({\n image: x.path,\n width: x.width,\n height: x.height,\n })),\n });\n }\n\n //\n // events\n //\n\n public removeExistingPhoto($preview: HTMLElement, id: string) {\n this.removedIds.push(id);\n $preview.remove();\n }\n\n // Parses the type specified in the options.attachTo (if provided), and sets\n // the appropriate callback for successful uploads\n private parseAttachTo() {\n if (!this.options.attachTo) {\n return;\n }\n const [type, id] = this.options.attachTo.split('#');\n if (!this.options.attachCallback) {\n if (type === 'business') {\n this.options.attachCallback = this.attachToBusiness.bind(this, id);\n }\n }\n }\n\n //\n // getters\n //\n\n public get hasRemoved(): boolean {\n return this.removedIds.length > 0;\n }\n\n public get photos(): PhotoInfo[] {\n return this.dropzone.files.map(file => {\n const path = file.signedUrlData.key;\n const { width, height } = file;\n return { path, width, height };\n });\n }\n\n public get $previews(): HTMLElement {\n return this.options.$previews ?? this.$element;\n }\n\n protected get dropzoneOptions(): any {\n return Object.assign(\n {\n paramName: PhotoUpload.paramName,\n clickable: this.options.$button ?? this.$element,\n previewsContainer: this.options.$previews,\n addRemoveLinks: true,\n maxFiles: 4,\n dictDefaultMessage: 'Drop files here or click to upload',\n },\n this.baseDropzoneOptions,\n );\n }\n\n protected get signingUrl() {\n return this.options.url || null;\n }\n}\n","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js!../../../../../node_modules/css-loader/dist/cjs.js??ref--1-1!../../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--1-3!../../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./circleProgress.vue?vue&type=style&index=0&id=42cd0160&lang=scss&scoped=true&\"","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('svg',{attrs:{\"width\":_vm.size,\"height\":_vm.size,\"viewBox\":(\"0 0 \" + _vm.viewbox + \" \" + _vm.viewbox)}},[_c('circle',{attrs:{\"cx\":_vm.viewbox / 2,\"cy\":_vm.viewbox / 2,\"r\":_vm.radius,\"fill\":\"none\",\"stroke\":_vm.color || '#ffffff',\"stroke-width\":_vm.thickness * 2}}),_c('circle',{attrs:{\"cx\":_vm.viewbox / 2,\"cy\":_vm.viewbox / 2,\"r\":_vm.radius,\"fill\":\"none\",\"stroke\":_vm.color || '#ffffff',\"stroke-width\":_vm.filledBorder,\"stroke-dasharray\":_vm.circumference,\"stroke-dashoffset\":_vm.filledCircumference}})])}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","// From: BezierEasing https://github.com/gre/bezier-easing\nconst bezier = (() => {\n const kSplineTableSize = 11;\n const kSampleStepSize = 1.0 / (kSplineTableSize - 1.0);\n\n function A(aA1: number, aA2: number) {\n return 1.0 - 3.0 * aA2 + 3.0 * aA1;\n }\n function B(aA1: number, aA2: number) {\n return 3.0 * aA2 - 6.0 * aA1;\n }\n function C(aA1: number) {\n return 3.0 * aA1;\n }\n\n function calcBezier(aT: number, aA1: number, aA2: number) {\n return ((A(aA1, aA2) * aT + B(aA1, aA2)) * aT + C(aA1)) * aT;\n }\n function getSlope(aT: number, aA1: number, aA2: number) {\n return 3.0 * A(aA1, aA2) * aT * aT + 2.0 * B(aA1, aA2) * aT + C(aA1);\n }\n\n function binarySubdivide(aX: number, aA: number, aB: number, mX1: number, mX2: number) {\n let currentX: number;\n let currentT: number;\n let i = 0;\n do {\n currentT = aA + (aB - aA) / 2.0;\n currentX = calcBezier(currentT, mX1, mX2) - aX;\n if (currentX > 0.0) {\n aB = currentT;\n } else {\n aA = currentT;\n }\n } while (Math.abs(currentX) > 0.0000001 && ++i < 10);\n return currentT;\n }\n\n function newtonRaphsonIterate(aX: number, aGuessT: number, mX1: number, mX2: number) {\n for (let i = 0; i < 4; ++i) {\n const currentSlope = getSlope(aGuessT, mX1, mX2);\n if (currentSlope === 0.0) {\n return aGuessT;\n }\n const currentX = calcBezier(aGuessT, mX1, mX2) - aX;\n aGuessT -= currentX / currentSlope;\n }\n return aGuessT;\n }\n\n function _bezier(mX1: number, mY1: number, mX2: number, mY2: number) {\n if (!(0 <= mX1 && mX1 <= 1 && 0 <= mX2 && mX2 <= 1)) {\n throw new Error(`Invalid input.`);\n }\n const sampleValues = new Float32Array(kSplineTableSize);\n\n if (mX1 !== mY1 || mX2 !== mY2) {\n for (let i = 0; i < kSplineTableSize; ++i) {\n sampleValues[i] = calcBezier(i * kSampleStepSize, mX1, mX2);\n }\n }\n\n function getTForX(aX: number) {\n let intervalStart = 0;\n let currentSample = 1;\n const lastSample = kSplineTableSize - 1;\n\n for (; currentSample !== lastSample && sampleValues[currentSample] <= aX; ++currentSample) {\n intervalStart += kSampleStepSize;\n }\n\n --currentSample;\n\n const dist =\n (aX - sampleValues[currentSample]) /\n (sampleValues[currentSample + 1] - sampleValues[currentSample]);\n const guessForT = intervalStart + dist * kSampleStepSize;\n const initialSlope = getSlope(guessForT, mX1, mX2);\n\n if (initialSlope >= 0.001) {\n return newtonRaphsonIterate(aX, guessForT, mX1, mX2);\n } else if (initialSlope === 0.0) {\n return guessForT;\n } else {\n return binarySubdivide(aX, intervalStart, intervalStart + kSampleStepSize, mX1, mX2);\n }\n }\n\n return (t: number) => {\n if (mX1 === mY1 && mX2 === mY2) {\n return t;\n }\n if (t === 0 || t === 1) {\n return t;\n }\n return calcBezier(getTForX(t), mY1, mY2);\n };\n }\n\n return _bezier;\n})();\n\n// https://matthewlein.com/tools/ceaser\n\n// Cubic\nexport const easeInCubic = bezier(0.55, 0.055, 0.675, 0.19);\nexport const easeOutCubic = bezier(0.215, 0.61, 0.355, 1);\nexport const easeInOutCubic = bezier(0.645, 0.045, 0.355, 1);\n\n// Circ\nexport const easeInCirc = bezier(0.6, 0.04, 0.98, 0.335);\nexport const easeOutCirc = bezier(0.075, 0.82, 0.165, 1);\nexport const easeInOutCirc = bezier(0.785, 0.135, 0.15, 0.86);\n\n// Expo\nexport const easeInExpo = bezier(0.95, 0.05, 0.795, 0.035);\nexport const easeOutExpo = bezier(0.19, 1, 0.22, 1);\nexport const easeInOutExpo = bezier(1, 0, 0, 1);\n\n// Quad\nexport const easeInQuad = bezier(0.55, 0.085, 0.68, 0.53);\nexport const easeOutQuad = bezier(0.25, 0.46, 0.45, 0.94);\nexport const easeInOutQuad = bezier(0.455, 0.03, 0.515, 0.955);\n\n// Quart\nexport const easeInQuart = bezier(0.895, 0.03, 0.685, 0.22);\nexport const easeOutQuart = bezier(0.165, 0.84, 0.44, 1);\nexport const easeInOutQuart = bezier(0.77, 0, 0.175, 1);\n\n// Quint\nexport const easeInQuint = bezier(0.755, 0.05, 0.855, 0.06);\nexport const easeOutQuint = bezier(0.23, 1, 0.32, 1);\nexport const easeInOutQuint = bezier(0.86, 0, 0.07, 1);\n\n// Sine\nexport const easeInSine = bezier(0.47, 0, 0.745, 0.715);\nexport const easeOutSine = bezier(0.39, 0.575, 0.565, 1);\nexport const easeInOutSine = bezier(0.445, 0.05, 0.55, 0.95);\n\n// Back\nexport const easeInBack = bezier(0.6, -0.28, 0.735, 0.045);\nexport const easeOutBack = bezier(0.175, 0.885, 0.32, 1.275);\nexport const easeInOutBack = bezier(0.68, -0.55, 0.265, 1.55);\n","import mod from \"-!../../../../../node_modules/babel-loader/lib/index.js??ref--5-0!./circleProgress.ts?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../../../node_modules/babel-loader/lib/index.js??ref--5-0!./circleProgress.ts?vue&type=script&lang=ts&\"","import anime from 'animejs';\nimport Vue from 'vue';\nimport Component from 'vue-class-component';\nimport { Prop, Watch } from 'vue-property-decorator';\nimport { easeOutCubic } from '../../vendor/easing';\n\n/**\n * This is a component that compiles SVG to show a circular progress bar that\n * can be filled up and controlled with the `progress` prop. Most of the code is\n * from https://codepen.io/xgad/post/svg-radial-progress-meters\n *\n * It will animate progress changes.\n */\n@Component({})\nexport default class AppCircleProgress extends Vue {\n @Prop({ type: Number, required: true })\n public size: number;\n\n @Prop(Number)\n public progress: number;\n\n @Prop(String)\n public color?: string;\n\n @Prop({ type: Number, default: 1 })\n public thickness: number;\n\n private transientProgress = 0;\n private animation?: anime.AnimeInstance;\n\n public get filledBorder() {\n return 5 * this.thickness;\n }\n\n public created() {\n // Don't animate the initial value\n if (this.progress) {\n this.transientProgress = this.clamp(this.progress);\n }\n }\n\n @Watch('progress')\n public onProgressChange(newProgress: number, oldProgress = 0) {\n // Ensure we stay in range\n oldProgress = this.clamp(oldProgress);\n newProgress = this.clamp(newProgress);\n\n if (this.animation) {\n this.animation.pause();\n this.animation = undefined;\n }\n\n // Don't animate when progress is reset.\n if (newProgress === 0) {\n this.transientProgress = newProgress;\n return;\n }\n\n this.animation = anime({\n targets: this.$el,\n duration: 1000,\n update: anim => {\n this.transientProgress =\n easeOutCubic(anim.progress / 100) * (newProgress - oldProgress) + oldProgress;\n },\n complete: () => {\n this.animation = undefined;\n },\n });\n }\n\n get radius() {\n return this.size / 2 - this.filledBorder / 2;\n }\n\n get viewbox() {\n return this.size + this.filledBorder;\n }\n\n get circumference() {\n return 2 * Math.PI * this.radius;\n }\n\n get filledCircumference() {\n return this.circumference * (1 - this.transientProgress / 100);\n }\n\n // Clamp a number to the range from 0 to 100\n private clamp(progress: number) {\n return Math.min(Math.max(progress, 0), 100);\n }\n}\n","import { render, staticRenderFns } from \"./circleProgress.vue?vue&type=template&id=42cd0160&scoped=true&lang=pug&\"\nimport script from \"./circleProgress.ts?vue&type=script&lang=ts&\"\nexport * from \"./circleProgress.ts?vue&type=script&lang=ts&\"\nimport style0 from \"./circleProgress.vue?vue&type=style&index=0&id=42cd0160&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"42cd0160\",\n null\n \n)\n\nexport default component.exports","var render = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return _c('div',{ref:\"wrapper\",staticClass:\"photo-upload-previews\"},[_vm._t(\"default\"),(_vm.name)?_c('input',{attrs:{\"type\":\"hidden\",\"name\":_vm.name},domProps:{\"value\":_vm.inputValue}}):_vm._e()],2)}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","import mod from \"-!../../../../../node_modules/babel-loader/lib/index.js??ref--5-0!./photoUploadPreviews.ts?vue&type=script&lang=ts&\"; export default mod; export * from \"-!../../../../../node_modules/babel-loader/lib/index.js??ref--5-0!./photoUploadPreviews.ts?vue&type=script&lang=ts&\"","import Vue from 'vue';\nimport Component from 'vue-class-component';\nimport { Prop } from 'vue-property-decorator';\nimport PhotoUpload, { PhotoInfo } from './photoUploadModal';\n\n@Component\nexport default class AppPhotoUploadPreviews extends Vue {\n public $refs: {\n wrapper: HTMLDivElement;\n };\n\n public $button: HTMLElement | undefined;\n public inputValue = '';\n public photoUpload: PhotoUpload;\n\n // Which parent record the photo should have (e.g. \"business#fresh-chalk-seattle\")\n @Prop(String)\n public attachTo: string;\n\n // The name of a text input that the component should appear inside of\n @Prop(String)\n public combineWith: string;\n\n // The name of a hidden that will send data when a
is submitted (e.g. \"conversation[photos]\")\n @Prop(String)\n public name: string;\n\n // The signing URL\n @Prop(String)\n public url: string;\n\n // The type of parent record (used for analytics)\n @Prop(String)\n public type: string;\n\n // New photos (in the format used for submitting to the server)\n public get photos() {\n return this.photoUpload.photos.map(x => ({\n image: x.path,\n width: x.width,\n height: x.height,\n }));\n }\n\n // The containing this component\n public get $form() {\n return this.$el.closest('form');\n }\n\n // The .form-group that contains the input this is combined with (if there is one)\n public get $formGroup() {\n if (!this.combineWith) {\n return;\n }\n const $e = document.querySelector(\n `.form-group.${this.combineWith.replace(/(\\w+)\\[(\\w+)\\]/, '$1_$2')}`,\n );\n if (!$e) {\n return;\n }\n return $e as HTMLElement;\n }\n\n public clear() {\n this.photoUpload.clear();\n }\n\n private async created() {\n await this.$nextTick();\n // If there's a combineWith property\n let $previews;\n let { $formGroup } = this;\n if ($formGroup) {\n const $btn = (this.$button = document.createElement('div'));\n $btn.className = 'photo-upload-clickable';\n $btn.title = 'Add Photos';\n $btn.addEventListener('click', () => {\n $formGroup?.querySelector('textarea')?.focus();\n this.photoUpload.trackClick();\n });\n $formGroup.classList.add('combined-with-photo-upload');\n $formGroup.appendChild($btn);\n $previews = document.createElement('div');\n $formGroup.appendChild($previews);\n } else if (this.$el.closest('#rec-modal')) {\n // In the RecModal we need to query for the button, because the usual\n // combineWith logic won't work inside of a Vue component\n this.$button = document.querySelector('#rec-modal .photo-upload-clickable') as HTMLElement;\n $formGroup = document.querySelector('#rec-modal .form-group') as HTMLElement;\n $previews = document.querySelector('#rec-modal .dropzone-wrapper') as HTMLElement;\n }\n // Create the dropzone component\n this.photoUpload = new PhotoUpload(this.$refs.wrapper, {\n $button: this.$button,\n $element: $formGroup,\n $previews,\n url: this.url,\n type: this.type,\n attachTo: this.attachTo,\n onSuccess: () => this.$emit('added'),\n });\n this.$el.addEventListener('click', this.$emit.bind(this, 'click'));\n // Detect form\n const { $form } = this;\n if ($form) {\n $form.addEventListener('submit', e => {\n // If this should use a hidden input\n if (this.name) {\n this.attachToInput(this.photoUpload.photos);\n }\n if (!this.photoUpload.hasRemoved) {\n this.photoUpload.track();\n return;\n }\n e.preventDefault();\n // Submit removed photos via AJAX\n this.submit().then(() => {\n $form.submit();\n });\n });\n }\n // Show existing photos\n this.showExisting();\n }\n\n // Submits all of the images in the Dropzone\n private async submit() {\n if (this.photoUpload.hasRemoved) {\n await this.photoUpload.submitRemoved();\n }\n }\n\n // Updates the hidden input to reflect the JSON encoded photos info\n private attachToInput(photos: PhotoInfo[]) {\n this.inputValue = JSON.stringify(\n photos.map(x => ({\n image: x.path,\n width: x.width,\n height: x.height,\n })),\n );\n }\n\n // Adds existing photos to the UI if they're found in this component's wrapper\n private showExisting() {\n // Load existing photos\n const upload = this.photoUpload;\n const $frag = document.createDocumentFragment();\n this.$el.parentElement\n ?.querySelectorAll('.existing-photos .dz-preview')\n .forEach(($preview: HTMLElement) => {\n const { id } = $preview.dataset;\n $preview\n .querySelector('.dz-remove')\n ?.addEventListener('click', upload.removeExistingPhoto.bind(upload, $preview, id));\n $frag.appendChild($preview);\n });\n upload.$previews.prepend($frag);\n }\n}\n","import { render, staticRenderFns } from \"./photoUploadPreviews.vue?vue&type=template&id=1a21ff1a&scoped=true&lang=pug&\"\nimport script from \"./photoUploadPreviews.ts?vue&type=script&lang=ts&\"\nexport * from \"./photoUploadPreviews.ts?vue&type=script&lang=ts&\"\nimport style0 from \"./photoUploadPreviews.scss?vue&type=style&index=0&id=1a21ff1a&lang=scss&scoped=true&\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"1a21ff1a\",\n null\n \n)\n\nexport default component.exports","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js!../../../../../node_modules/css-loader/dist/cjs.js??ref--1-1!../../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--1-3!./photoUploadPreviews.scss?vue&type=style&index=0&id=1a21ff1a&lang=scss&scoped=true&\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js!../../../../../node_modules/css-loader/dist/cjs.js??ref--1-1!../../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--1-3!./recTagSuggestions.scss?vue&type=style&index=0&id=4ffe4d60&lang=scss&scoped=true&\"","export * from \"-!../../../../../node_modules/mini-css-extract-plugin/dist/loader.js!../../../../../node_modules/css-loader/dist/cjs.js??ref--1-1!../../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../../node_modules/postcss-loader/src/index.js??ref--1-2!../../../../../node_modules/sass-loader/dist/cjs.js??ref--1-3!./recModal.scss?vue&type=style&index=0&id=d3caae68&lang=scss&scoped=true&\""],"sourceRoot":""}