| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | <template> | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |   <section @keyup.ctrl.90="undoMerge"> | 
					
						
							|  |  |  |     <!-- Ingredient Link Editor --> | 
					
						
							|  |  |  |     <v-dialog v-model="dialog" width="600"> | 
					
						
							| 
									
										
										
										
											2021-11-20 14:30:38 -09:00
										 |  |  |       <v-card :ripple="false"> | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |         <v-app-bar dark color="primary" class="mt-n1 mb-3"> | 
					
						
							|  |  |  |           <v-icon large left> | 
					
						
							|  |  |  |             {{ $globals.icons.link }} | 
					
						
							|  |  |  |           </v-icon> | 
					
						
							|  |  |  |           <v-toolbar-title class="headline"> Ingredient Linker </v-toolbar-title> | 
					
						
							|  |  |  |           <v-spacer></v-spacer> | 
					
						
							|  |  |  |         </v-app-bar> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <v-card-text class="pt-4"> | 
					
						
							|  |  |  |           <p> | 
					
						
							|  |  |  |             {{ activeText }} | 
					
						
							|  |  |  |           </p> | 
					
						
							|  |  |  |           <v-divider class="mb-4"></v-divider> | 
					
						
							|  |  |  |           <v-checkbox | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |             v-for="ing in unusedIngredients" | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |             :key="ing.referenceId" | 
					
						
							|  |  |  |             v-model="activeRefs" | 
					
						
							|  |  |  |             :value="ing.referenceId" | 
					
						
							|  |  |  |             class="mb-n2 mt-n2" | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |           > | 
					
						
							|  |  |  |             <template #label> | 
					
						
							|  |  |  |               <div v-html="parseIngredientText(ing, disableAmount)"></div> | 
					
						
							|  |  |  |             </template> | 
					
						
							|  |  |  |           </v-checkbox> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |           <template v-if="usedIngredients.length > 0"> | 
					
						
							|  |  |  |             <h4 class="py-3 ml-1">Linked to other step</h4> | 
					
						
							|  |  |  |             <v-checkbox | 
					
						
							|  |  |  |               v-for="ing in usedIngredients" | 
					
						
							|  |  |  |               :key="ing.referenceId" | 
					
						
							|  |  |  |               v-model="activeRefs" | 
					
						
							|  |  |  |               :value="ing.referenceId" | 
					
						
							|  |  |  |               class="mb-n2 mt-n2" | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |               <template #label> | 
					
						
							|  |  |  |                 <div v-html="parseIngredientText(ing, disableAmount)"></div> | 
					
						
							|  |  |  |               </template> | 
					
						
							|  |  |  |             </v-checkbox> | 
					
						
							|  |  |  |           </template> | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |         </v-card-text> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <v-divider></v-divider> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         <v-card-actions> | 
					
						
							|  |  |  |           <BaseButton cancel @click="dialog = false"> </BaseButton> | 
					
						
							|  |  |  |           <v-spacer></v-spacer> | 
					
						
							|  |  |  |           <BaseButton color="info" @click="autoSetReferences"> | 
					
						
							|  |  |  |             <template #icon> {{ $globals.icons.robot }}</template> | 
					
						
							|  |  |  |             Auto | 
					
						
							|  |  |  |           </BaseButton> | 
					
						
							|  |  |  |           <BaseButton save @click="setIngredientIds"> </BaseButton> | 
					
						
							|  |  |  |         </v-card-actions> | 
					
						
							|  |  |  |       </v-card> | 
					
						
							|  |  |  |     </v-dialog> | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     <div class="d-flex justify-space-between justify-start"> | 
					
						
							|  |  |  |       <h2 class="mb-4 mt-1">{{ $t("recipe.instructions") }}</h2> | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |       <BaseButton v-if="!public" minor :to="$router.currentRoute.path + '/cook'" cancel color="primary"> | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |         <template #icon> | 
					
						
							|  |  |  |           {{ $globals.icons.primary }} | 
					
						
							|  |  |  |         </template> | 
					
						
							|  |  |  |         Cook | 
					
						
							|  |  |  |       </BaseButton> | 
					
						
							|  |  |  |     </div> | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |     <draggable | 
					
						
							|  |  |  |       :disabled="!edit" | 
					
						
							|  |  |  |       :value="value" | 
					
						
							|  |  |  |       handle=".handle" | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |       v-bind="{ | 
					
						
							|  |  |  |         animation: 200, | 
					
						
							|  |  |  |         group: 'description', | 
					
						
							|  |  |  |         ghostClass: 'ghost', | 
					
						
							|  |  |  |       }" | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |       @input="updateIndex" | 
					
						
							|  |  |  |       @start="drag = true" | 
					
						
							|  |  |  |       @end="drag = false" | 
					
						
							|  |  |  |     > | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |       <TransitionGroup type="transition" :name="!drag ? 'flip-list' : ''"> | 
					
						
							|  |  |  |         <div v-for="(step, index) in value" :key="step.id" class="list-group-item"> | 
					
						
							|  |  |  |           <v-app-bar | 
					
						
							|  |  |  |             v-if="showTitleEditor[step.id]" | 
					
						
							|  |  |  |             class="primary mx-1 mt-6" | 
					
						
							|  |  |  |             style="cursor: pointer" | 
					
						
							|  |  |  |             dark | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |             dense | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |             rounded | 
					
						
							|  |  |  |             @click="toggleCollapseSection(index)" | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |           > | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |             <v-toolbar-title v-if="!edit" class="headline"> | 
					
						
							| 
									
										
										
										
											2022-05-25 09:38:21 -08:00
										 |  |  |               <v-app-bar-title> {{ step.title }} </v-app-bar-title> | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |             </v-toolbar-title> | 
					
						
							|  |  |  |             <v-text-field | 
					
						
							|  |  |  |               v-if="edit" | 
					
						
							|  |  |  |               v-model="step.title" | 
					
						
							|  |  |  |               class="headline pa-0 mt-5" | 
					
						
							|  |  |  |               dense | 
					
						
							|  |  |  |               solo | 
					
						
							|  |  |  |               flat | 
					
						
							|  |  |  |               :placeholder="$t('recipe.section-title')" | 
					
						
							|  |  |  |               background-color="primary" | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |             </v-text-field> | 
					
						
							|  |  |  |           </v-app-bar> | 
					
						
							|  |  |  |           <v-hover v-slot="{ hover }"> | 
					
						
							|  |  |  |             <v-card | 
					
						
							|  |  |  |               class="ma-1" | 
					
						
							|  |  |  |               :class="[{ 'on-hover': hover }, isChecked(index)]" | 
					
						
							|  |  |  |               :elevation="hover ? 12 : 2" | 
					
						
							|  |  |  |               :ripple="false" | 
					
						
							|  |  |  |               @click="toggleDisabled(index)" | 
					
						
							|  |  |  |             > | 
					
						
							|  |  |  |               <v-card-title :class="{ 'pb-0': !isChecked(index) }"> | 
					
						
							|  |  |  |                 <span class="handle"> | 
					
						
							|  |  |  |                   <v-icon v-if="edit" size="26" class="pb-1">{{ $globals.icons.arrowUpDown }}</v-icon> | 
					
						
							|  |  |  |                   {{ $t("recipe.step-index", { step: index + 1 }) }} | 
					
						
							|  |  |  |                 </span> | 
					
						
							|  |  |  |                 <template v-if="edit"> | 
					
						
							|  |  |  |                   <div class="ml-auto"> | 
					
						
							|  |  |  |                     <BaseButtonGroup | 
					
						
							|  |  |  |                       :large="false" | 
					
						
							|  |  |  |                       :buttons="[ | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                           icon: $globals.icons.delete, | 
					
						
							|  |  |  |                           text: $tc('general.delete'), | 
					
						
							|  |  |  |                           event: 'delete', | 
					
						
							|  |  |  |                         }, | 
					
						
							|  |  |  |                         { | 
					
						
							|  |  |  |                           icon: $globals.icons.dotsVertical, | 
					
						
							|  |  |  |                           text: '', | 
					
						
							|  |  |  |                           event: 'open', | 
					
						
							|  |  |  |                           children: [ | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                               text: 'Toggle Section', | 
					
						
							|  |  |  |                               event: 'toggle-section', | 
					
						
							|  |  |  |                             }, | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                               text: 'Link Ingredients', | 
					
						
							|  |  |  |                               event: 'link-ingredients', | 
					
						
							|  |  |  |                             }, | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                               text: 'Merge Above', | 
					
						
							|  |  |  |                               event: 'merge-above', | 
					
						
							|  |  |  |                             }, | 
					
						
							|  |  |  |                             { | 
					
						
							|  |  |  |                               icon: previewStates[index] ? $globals.icons.edit : $globals.icons.eye, | 
					
						
							|  |  |  |                               text: previewStates[index] ? 'Edit Markdown' : 'Preview Markdown', | 
					
						
							|  |  |  |                               event: 'preview-step', | 
					
						
							|  |  |  |                             }, | 
					
						
							|  |  |  |                           ], | 
					
						
							|  |  |  |                         }, | 
					
						
							|  |  |  |                       ]" | 
					
						
							|  |  |  |                       @merge-above="mergeAbove(index - 1, index)" | 
					
						
							|  |  |  |                       @toggle-section="toggleShowTitle(step.id)" | 
					
						
							|  |  |  |                       @link-ingredients="openDialog(index, step.ingredientReferences, step.text)" | 
					
						
							|  |  |  |                       @preview-step="togglePreviewState(index)" | 
					
						
							|  |  |  |                       @delete="value.splice(index, 1)" | 
					
						
							|  |  |  |                     /> | 
					
						
							|  |  |  |                   </div> | 
					
						
							|  |  |  |                 </template> | 
					
						
							|  |  |  |                 <v-fade-transition> | 
					
						
							|  |  |  |                   <v-icon v-show="isChecked(index)" size="24" class="ml-auto" color="success"> | 
					
						
							|  |  |  |                     {{ $globals.icons.checkboxMarkedCircle }} | 
					
						
							|  |  |  |                   </v-icon> | 
					
						
							|  |  |  |                 </v-fade-transition> | 
					
						
							|  |  |  |               </v-card-title> | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  |               <!-- Content --> | 
					
						
							|  |  |  |               <v-card-text | 
					
						
							|  |  |  |                 v-if="edit" | 
					
						
							|  |  |  |                 :class="{ | 
					
						
							|  |  |  |                   blur: imageUploadMode, | 
					
						
							|  |  |  |                 }" | 
					
						
							|  |  |  |                 @drop.stop.prevent="handleImageDrop(index, $event)" | 
					
						
							|  |  |  |               > | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |                 <MarkdownEditor | 
					
						
							|  |  |  |                   v-model="value[index]['text']" | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  |                   class="mb-2" | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |                   :preview.sync="previewStates[index]" | 
					
						
							|  |  |  |                   :display-preview="false" | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  |                   :textarea="{ | 
					
						
							|  |  |  |                     hint: 'Attach images by dragging & dropping them into the editor', | 
					
						
							|  |  |  |                     persistentHint: true, | 
					
						
							|  |  |  |                   }" | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |                 /> | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |                 <div | 
					
						
							|  |  |  |                   v-for="ing in step.ingredientReferences" | 
					
						
							|  |  |  |                   :key="ing.referenceId" | 
					
						
							|  |  |  |                   v-html="getIngredientByRefId(ing.referenceId)" | 
					
						
							|  |  |  |                 /> | 
					
						
							|  |  |  |               </v-card-text> | 
					
						
							|  |  |  |               <v-expand-transition> | 
					
						
							|  |  |  |                 <div v-show="!isChecked(index) && !edit" class="m-0 p-0"> | 
					
						
							|  |  |  |                   <v-card-text class="markdown"> | 
					
						
							|  |  |  |                     <VueMarkdown class="markdown" :source="step.text"> </VueMarkdown> | 
					
						
							|  |  |  |                   </v-card-text> | 
					
						
							| 
									
										
										
										
											2022-01-09 21:04:24 -09:00
										 |  |  |                 </div> | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |               </v-expand-transition> | 
					
						
							|  |  |  |             </v-card> | 
					
						
							|  |  |  |           </v-hover> | 
					
						
							|  |  |  |         </div> | 
					
						
							|  |  |  |       </TransitionGroup> | 
					
						
							| 
									
										
										
										
											2021-09-09 08:51:29 -08:00
										 |  |  |     </draggable> | 
					
						
							|  |  |  |   </section> | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | </template> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  | <script lang="ts"> | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | import draggable from "vuedraggable"; | 
					
						
							| 
									
										
										
										
											2022-01-16 03:38:11 +01:00
										 |  |  | // @ts-ignore vue-markdown has no types
 | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | import VueMarkdown from "@adapttive/vue-markdown"; | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  | import { ref, toRefs, reactive, defineComponent, watch, onMounted, useContext } from "@nuxtjs/composition-api"; | 
					
						
							|  |  |  | import { RecipeStep, IngredientReferences, RecipeIngredient, RecipeAsset } from "~/types/api-types/recipe"; | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  | import { parseIngredientText } from "~/composables/recipes"; | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  | import { uuid4, detectServerBaseUrl } from "~/composables/use-utils"; | 
					
						
							|  |  |  | import { useUserApi, useStaticRoutes } from "~/composables/api"; | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | interface MergerHistory { | 
					
						
							|  |  |  |   target: number; | 
					
						
							|  |  |  |   source: number; | 
					
						
							|  |  |  |   targetText: string; | 
					
						
							|  |  |  |   sourceText: string; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | export default defineComponent({ | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |   components: { | 
					
						
							|  |  |  |     VueMarkdown, | 
					
						
							|  |  |  |     draggable, | 
					
						
							|  |  |  |   }, | 
					
						
							|  |  |  |   props: { | 
					
						
							|  |  |  |     value: { | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |       type: Array as () => RecipeStep[], | 
					
						
							| 
									
										
										
										
											2021-08-07 16:49:55 -08:00
										 |  |  |       required: true, | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |     }, | 
					
						
							|  |  |  |     edit: { | 
					
						
							|  |  |  |       type: Boolean, | 
					
						
							|  |  |  |       default: true, | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     ingredients: { | 
					
						
							|  |  |  |       type: Array as () => RecipeIngredient[], | 
					
						
							|  |  |  |       default: () => [], | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |     disableAmount: { | 
					
						
							|  |  |  |       type: Boolean, | 
					
						
							|  |  |  |       default: false, | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2021-12-05 11:55:46 -09:00
										 |  |  |     public: { | 
					
						
							|  |  |  |       type: Boolean, | 
					
						
							|  |  |  |       default: false, | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  |     recipeId: { | 
					
						
							|  |  |  |       type: String, | 
					
						
							|  |  |  |       default: "", | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     recipeSlug: { | 
					
						
							|  |  |  |       type: String, | 
					
						
							|  |  |  |       default: "", | 
					
						
							|  |  |  |     }, | 
					
						
							|  |  |  |     assets: { | 
					
						
							|  |  |  |       type: Array as () => RecipeAsset[], | 
					
						
							|  |  |  |       required: true, | 
					
						
							|  |  |  |     }, | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |   }, | 
					
						
							| 
									
										
										
										
											2021-10-31 14:46:46 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |   setup(props, context) { | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  |     const { req } = useContext(); | 
					
						
							|  |  |  |     const BASE_URL = detectServerBaseUrl(req); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     console.log("Base URL", BASE_URL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     const state = reactive({ | 
					
						
							|  |  |  |       dialog: false, | 
					
						
							|  |  |  |       disabledSteps: [] as number[], | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       unusedIngredients: [] as RecipeIngredient[], | 
					
						
							|  |  |  |       usedIngredients: [] as RecipeIngredient[], | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     }); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |     const showTitleEditor = ref<{ [key: string]: boolean }>({}); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     const actionEvents = [ | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         text: "Toggle Section", | 
					
						
							|  |  |  |         event: "toggle-section", | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         text: "Link Ingredients", | 
					
						
							|  |  |  |         event: "link-ingredients", | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |       { | 
					
						
							|  |  |  |         text: "Merge Above", | 
					
						
							|  |  |  |         event: "merge-above", | 
					
						
							|  |  |  |       }, | 
					
						
							|  |  |  |     ]; | 
					
						
							| 
									
										
										
										
											2021-08-01 19:24:47 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     // ===============================================================
 | 
					
						
							|  |  |  |     // UI State Helpers
 | 
					
						
							| 
									
										
										
										
											2022-02-27 12:48:21 -09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     function validateTitle(title: string | undefined) { | 
					
						
							| 
									
										
										
										
											2022-02-27 12:48:21 -09:00
										 |  |  |       return !(title === null || title === "" || title === undefined); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     watch(props.value, (v) => { | 
					
						
							|  |  |  |       state.disabledSteps = []; | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-22 11:52:57 -08:00
										 |  |  |       v.forEach((element: RecipeStep) => { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |         if (element.id !== undefined) { | 
					
						
							|  |  |  |           showTitleEditor.value[element.id] = validateTitle(element.title); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Eliminate state with an eager call to watcher?
 | 
					
						
							|  |  |  |     onMounted(() => { | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |       props.value.forEach((element) => { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |         if (element.id !== undefined) { | 
					
						
							|  |  |  |           showTitleEditor.value[element.id] = validateTitle(element.title); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2022-02-27 12:48:21 -09:00
										 |  |  | 
 | 
					
						
							|  |  |  |         showTitleEditor.value = { ...showTitleEditor.value }; | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |       }); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function toggleDisabled(stepIndex: number) { | 
					
						
							|  |  |  |       if (props.edit) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       if (state.disabledSteps.includes(stepIndex)) { | 
					
						
							|  |  |  |         const index = state.disabledSteps.indexOf(stepIndex); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |         if (index !== -1) { | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |           state.disabledSteps.splice(index, 1); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |         } | 
					
						
							|  |  |  |       } else { | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |         state.disabledSteps.push(stepIndex); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-02-27 12:48:21 -09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     function isChecked(stepIndex: number) { | 
					
						
							|  |  |  |       if (state.disabledSteps.includes(stepIndex) && !props.edit) { | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |         return "disabled-card"; | 
					
						
							|  |  |  |       } | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-02-27 12:48:21 -09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |     function toggleShowTitle(id: string) { | 
					
						
							|  |  |  |       showTitleEditor.value[id] = !showTitleEditor.value[id]; | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |       const temp = { ...showTitleEditor.value }; | 
					
						
							|  |  |  |       showTitleEditor.value = temp; | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-02-27 12:48:21 -09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     function updateIndex(data: RecipeStep) { | 
					
						
							|  |  |  |       context.emit("input", data); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // ===============================================================
 | 
					
						
							|  |  |  |     // Ingredient Linker
 | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |     const activeRefs = ref<string[]>([]); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     const activeIndex = ref(0); | 
					
						
							|  |  |  |     const activeText = ref(""); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |     function openDialog(idx: number, refs: IngredientReferences[], text: string) { | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       setUsedIngredients(); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |       activeText.value = text; | 
					
						
							|  |  |  |       activeIndex.value = idx; | 
					
						
							|  |  |  |       state.dialog = true; | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |       activeRefs.value = refs.map((ref) => ref.referenceId ?? ""); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function setIngredientIds() { | 
					
						
							|  |  |  |       const instruction = props.value[activeIndex.value]; | 
					
						
							|  |  |  |       instruction.ingredientReferences = activeRefs.value.map((ref) => { | 
					
						
							|  |  |  |         return { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |           referenceId: ref, | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |         }; | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |       state.dialog = false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |     function setUsedIngredients() { | 
					
						
							|  |  |  |       const usedRefs: { [key: string]: boolean } = {}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       props.value.forEach((element) => { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |         element.ingredientReferences?.forEach((ref) => { | 
					
						
							|  |  |  |           if (ref.referenceId !== undefined) { | 
					
						
							|  |  |  |             usedRefs[ref.referenceId] = true; | 
					
						
							|  |  |  |           } | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       state.usedIngredients = props.ingredients.filter((ing) => { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |         return ing.referenceId !== undefined && ing.referenceId in usedRefs; | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       state.unusedIngredients = props.ingredients.filter((ing) => { | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |         return !(ing.referenceId !== undefined && ing.referenceId in usedRefs); | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     function autoSetReferences() { | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  |       // Ignore matching blacklisted words when auto-linking - This is kind of a cludgey implementation. We're blacklisting common words but
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |       // other common phrases trigger false positives and I'm not sure how else to approach this. In the future I maybe look at looking directly
 | 
					
						
							|  |  |  |       // at the food variable and seeing if the food is in the instructions, but I still need to support those who don't want to provide the value
 | 
					
						
							|  |  |  |       // and only use the "notes" feature.
 | 
					
						
							|  |  |  |       const blackListedText = [ | 
					
						
							|  |  |  |         "and", | 
					
						
							|  |  |  |         "or", | 
					
						
							|  |  |  |         "the", | 
					
						
							|  |  |  |         "a", | 
					
						
							|  |  |  |         "an", | 
					
						
							|  |  |  |         "of", | 
					
						
							|  |  |  |         "in", | 
					
						
							|  |  |  |         "on", | 
					
						
							|  |  |  |         "to", | 
					
						
							|  |  |  |         "for", | 
					
						
							|  |  |  |         "by", | 
					
						
							|  |  |  |         "with", | 
					
						
							|  |  |  |         "without", | 
					
						
							|  |  |  |         "", | 
					
						
							|  |  |  |         " ", | 
					
						
							|  |  |  |       ]; | 
					
						
							|  |  |  |       const blackListedRegexMatch = /\d/gm; // Match Any Number
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Check if any of the words in the active text match the ingredient text
 | 
					
						
							|  |  |  |       const instructionsByWord = activeText.value.toLowerCase().split(" "); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       instructionsByWord.forEach((word) => { | 
					
						
							|  |  |  |         if (blackListedText.includes(word) || word.match(blackListedRegexMatch)) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         props.ingredients.forEach((ingredient) => { | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |           const searchText = parseIngredientText(ingredient, props.disableAmount); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |           if (ingredient.referenceId === undefined) { | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |           if (searchText.toLowerCase().includes(" " + word) && !activeRefs.value.includes(ingredient.referenceId)) { | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |             console.info("Word Matched", `'${word}'`, ingredient.note); | 
					
						
							|  |  |  |             activeRefs.value.push(ingredient.referenceId); | 
					
						
							|  |  |  |           } | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 07:15:23 +01:00
										 |  |  |     function getIngredientByRefId(refId: string) { | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       const ing = props.ingredients.find((ing) => ing.referenceId === refId) || ""; | 
					
						
							|  |  |  |       if (ing === "") { | 
					
						
							|  |  |  |         return ""; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |       return parseIngredientText(ing, props.disableAmount); | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // ===============================================================
 | 
					
						
							|  |  |  |     // Instruction Merger
 | 
					
						
							|  |  |  |     const mergeHistory = ref<MergerHistory[]>([]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function mergeAbove(target: number, source: number) { | 
					
						
							|  |  |  |       if (target < 0) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       mergeHistory.value.push({ | 
					
						
							|  |  |  |         target, | 
					
						
							|  |  |  |         source, | 
					
						
							|  |  |  |         targetText: props.value[target].text, | 
					
						
							|  |  |  |         sourceText: props.value[source].text, | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       props.value[target].text += " " + props.value[source].text; | 
					
						
							|  |  |  |       props.value.splice(source, 1); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function undoMerge(event: KeyboardEvent) { | 
					
						
							|  |  |  |       if (event.ctrlKey && event.code === "KeyZ") { | 
					
						
							|  |  |  |         if (!(mergeHistory.value?.length > 0)) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const lastMerge = mergeHistory.value.pop(); | 
					
						
							|  |  |  |         if (!lastMerge) { | 
					
						
							|  |  |  |           return; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         props.value[lastMerge.target].text = lastMerge.targetText; | 
					
						
							|  |  |  |         props.value.splice(lastMerge.source, 0, { | 
					
						
							| 
									
										
										
										
											2021-11-22 20:10:48 -09:00
										 |  |  |           id: uuid4(), | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |           title: "", | 
					
						
							|  |  |  |           text: lastMerge.sourceText, | 
					
						
							|  |  |  |           ingredientReferences: [], | 
					
						
							|  |  |  |         }); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-01-09 21:04:24 -09:00
										 |  |  |     const previewStates = ref<boolean[]>([]); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function togglePreviewState(index: number) { | 
					
						
							|  |  |  |       const temp = [...previewStates.value]; | 
					
						
							|  |  |  |       temp[index] = !temp[index]; | 
					
						
							|  |  |  |       previewStates.value = temp; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-03 19:43:56 -09:00
										 |  |  |     function toggleCollapseSection(index: number) { | 
					
						
							|  |  |  |       const sectionSteps: number[] = []; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       for (let i = index; i < props.value.length; i++) { | 
					
						
							|  |  |  |         if (!(i === index) && validateTitle(props.value[i].title)) { | 
					
						
							|  |  |  |           break; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |           sectionSteps.push(i); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const allCollapsed = sectionSteps.every((idx) => state.disabledSteps.includes(idx)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (allCollapsed) { | 
					
						
							|  |  |  |         state.disabledSteps = state.disabledSteps.filter((idx) => !sectionSteps.includes(idx)); | 
					
						
							|  |  |  |       } else { | 
					
						
							|  |  |  |         state.disabledSteps = [...state.disabledSteps, ...sectionSteps]; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |     const drag = ref(false); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  |     // ===============================================================
 | 
					
						
							|  |  |  |     // Image Uploader
 | 
					
						
							|  |  |  |     const api = useUserApi(); | 
					
						
							|  |  |  |     const { recipeAssetPath } = useStaticRoutes(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const imageUploadMode = ref(false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     function toggleDragMode() { | 
					
						
							|  |  |  |       console.log("Toggling Drag Mode"); | 
					
						
							|  |  |  |       imageUploadMode.value = !imageUploadMode.value; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     onMounted(() => { | 
					
						
							|  |  |  |       if (props.assets === undefined) { | 
					
						
							|  |  |  |         context.emit("update:assets", []); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     async function handleImageDrop(index: number, e: DragEvent) { | 
					
						
							|  |  |  |       if (!e.dataTransfer) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Check if the file is an image
 | 
					
						
							|  |  |  |       const file = e.dataTransfer.files[0]; | 
					
						
							|  |  |  |       if (!file || !file.type.startsWith("image/")) { | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       const { data } = await api.recipes.createAsset(props.recipeSlug, { | 
					
						
							|  |  |  |         name: file.name, | 
					
						
							|  |  |  |         icon: "mdi-file-image", | 
					
						
							|  |  |  |         file, | 
					
						
							|  |  |  |         extension: file.name.split(".").pop() || "", | 
					
						
							|  |  |  |       }); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       if (!data) { | 
					
						
							|  |  |  |         return; // TODO: Handle error
 | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       context.emit("update:assets", [...props.assets, data]); | 
					
						
							|  |  |  |       const assetUrl = BASE_URL + recipeAssetPath(props.recipeId, data.fileName as string); | 
					
						
							|  |  |  |       const text = `<img src="${assetUrl}" height="100%" width="100%"/>`; | 
					
						
							|  |  |  |       props.value[index].text += text; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     return { | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  |       // Image Uploader
 | 
					
						
							|  |  |  |       toggleDragMode, | 
					
						
							|  |  |  |       handleImageDrop, | 
					
						
							|  |  |  |       imageUploadMode, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       // Rest
 | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  |       drag, | 
					
						
							| 
									
										
										
										
											2022-01-09 21:04:24 -09:00
										 |  |  |       togglePreviewState, | 
					
						
							| 
									
										
										
										
											2022-03-03 19:43:56 -09:00
										 |  |  |       toggleCollapseSection, | 
					
						
							| 
									
										
										
										
											2022-01-09 21:04:24 -09:00
										 |  |  |       previewStates, | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |       ...toRefs(state), | 
					
						
							|  |  |  |       actionEvents, | 
					
						
							|  |  |  |       activeRefs, | 
					
						
							|  |  |  |       activeText, | 
					
						
							|  |  |  |       getIngredientByRefId, | 
					
						
							|  |  |  |       showTitleEditor, | 
					
						
							|  |  |  |       mergeAbove, | 
					
						
							|  |  |  |       openDialog, | 
					
						
							|  |  |  |       setIngredientIds, | 
					
						
							|  |  |  |       undoMerge, | 
					
						
							|  |  |  |       toggleDisabled, | 
					
						
							|  |  |  |       isChecked, | 
					
						
							|  |  |  |       toggleShowTitle, | 
					
						
							|  |  |  |       updateIndex, | 
					
						
							|  |  |  |       autoSetReferences, | 
					
						
							| 
									
										
										
										
											2021-11-06 11:28:47 -08:00
										 |  |  |       parseIngredientText, | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  |     }; | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  |   }, | 
					
						
							| 
									
										
										
										
											2021-11-05 15:48:10 -08:00
										 |  |  | }); | 
					
						
							| 
									
										
										
										
											2021-07-31 15:07:19 -08:00
										 |  |  | </script> | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-04-24 13:00:04 -08:00
										 |  |  | <style lang="css" scoped> | 
					
						
							| 
									
										
										
										
											2021-11-20 14:30:38 -09:00
										 |  |  | .v-card--link:before { | 
					
						
							|  |  |  |   background: none; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-04-24 13:00:04 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** Select all li under .markdown class */ | 
					
						
							|  |  |  | .markdown >>> ul > li { | 
					
						
							|  |  |  |   display: list-item; | 
					
						
							|  |  |  |   list-style-type: disc !important; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** Select all li under .markdown class */ | 
					
						
							|  |  |  | .markdown >>> ol > li { | 
					
						
							|  |  |  |   display: list-item; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-05-11 17:14:03 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | .flip-list-move { | 
					
						
							|  |  |  |   transition: transform 0.5s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | .no-move { | 
					
						
							|  |  |  |   transition: transform 0s; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | .ghost { | 
					
						
							|  |  |  |   opacity: 0.5; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | .list-group { | 
					
						
							|  |  |  |   min-height: 38px; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | .list-group-item { | 
					
						
							|  |  |  |   cursor: move; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | .list-group-item i { | 
					
						
							|  |  |  |   cursor: pointer; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2022-06-05 11:28:38 -08:00
										 |  |  | 
 | 
					
						
							|  |  |  | .blur { | 
					
						
							|  |  |  |   filter: blur(2px); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .upload-overlay { | 
					
						
							|  |  |  |   display: flex; | 
					
						
							|  |  |  |   justify-content: center; | 
					
						
							|  |  |  |   align-items: center; | 
					
						
							|  |  |  |   position: absolute; | 
					
						
							|  |  |  |   top: 0; | 
					
						
							|  |  |  |   left: 0; | 
					
						
							|  |  |  |   width: 100%; | 
					
						
							|  |  |  |   height: 100%; | 
					
						
							|  |  |  |   background: rgba(0, 0, 0, 0.5); | 
					
						
							|  |  |  |   z-index: 1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2021-11-20 14:30:38 -09:00
										 |  |  | </style> |