mirror of
				https://github.com/mealie-recipes/mealie.git
				synced 2025-10-31 10:13:32 -04:00 
			
		
		
		
	* update naming * refactor tests to use shared structure * shorten names * add tools test case * refactor to support multi-tenant * set group_id on creation * initial refactor for multitenant tags/cats * spelling * additional test case for same valued resources * fix recipe update tests * apply indexes to foreign keys * fix performance regressions * handle unknown exception * utility decorator for function debugging * migrate recipe_id to UUID * GUID for recipes * remove unused import * move image functions into package * move utilities to packages dir * update import * linter * image image and asset routes * update assets and images to use UUIDs * fix migration base * image asset test coverage * use ids for categories and tag crud functions * refactor recipe organizer test suite to reduce duplication * add uuid serlization utility * organizer base router * slug routes testing and fixes * fix postgres error * adopt UUIDs * move tags, categories, and tools under "organizers" umbrella * update composite label * generate ts types * fix import error * update frontend types * fix type errors * fix postgres errors * fix #978 * add null check for title validation * add note in docs on multi-tenancy
		
			
				
	
	
		
			118 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <div>
 | |
|     <v-card-title class="headline pb-3">
 | |
|       <v-icon class="mr-2">
 | |
|         {{ $globals.icons.commentTextMultipleOutline }}
 | |
|       </v-icon>
 | |
|       {{ $t("recipe.comments") }}
 | |
|     </v-card-title>
 | |
|     <v-divider class="mx-2"></v-divider>
 | |
|     <div class="d-flex flex-column">
 | |
|       <div class="d-flex mt-3" style="gap: 10px">
 | |
|         <UserAvatar size="40" :user-id="$auth.user.id" />
 | |
| 
 | |
|         <v-textarea
 | |
|           v-model="comment"
 | |
|           hide-details=""
 | |
|           dense
 | |
|           single-line
 | |
|           outlined
 | |
|           auto-grow
 | |
|           rows="2"
 | |
|           placeholder="Join the Conversation"
 | |
|         >
 | |
|         </v-textarea>
 | |
|       </div>
 | |
|       <div class="ml-auto mt-1">
 | |
|         <BaseButton small :disabled="!comment" @click="submitComment">
 | |
|           <template #icon>{{ $globals.icons.check }}</template>
 | |
|           {{ $t("general.submit") }}
 | |
|         </BaseButton>
 | |
|       </div>
 | |
|     </div>
 | |
|     <div v-for="comment in comments" :key="comment.id" class="d-flex my-2" style="gap: 10px">
 | |
|       <UserAvatar size="40" :user-id="comment.userId" />
 | |
|       <v-card outlined class="flex-grow-1">
 | |
|         <v-card-text class="pa-3 pb-0">
 | |
|           <p class="">{{ comment.user.username }} • {{ $d(Date.parse(comment.createdAt), "medium") }}</p>
 | |
|           {{ comment.text }}
 | |
|         </v-card-text>
 | |
|         <v-card-actions class="justify-end mt-0 pt-0">
 | |
|           <v-btn
 | |
|             v-if="$auth.user.id == comment.user.id || $auth.user.admin"
 | |
|             color="error"
 | |
|             text
 | |
|             x-small
 | |
|             @click="deleteComment(comment.id)"
 | |
|           >
 | |
|             Delete
 | |
|           </v-btn>
 | |
|         </v-card-actions>
 | |
|       </v-card>
 | |
|     </div>
 | |
|   </div>
 | |
| </template>
 | |
| 
 | |
| <script lang="ts">
 | |
| import { defineComponent, ref, toRefs, onMounted, reactive } from "@nuxtjs/composition-api";
 | |
| import { useUserApi } from "~/composables/api";
 | |
| import { RecipeComment } from "~/api/class-interfaces/recipes/types";
 | |
| import UserAvatar from "~/components/Domain/User/UserAvatar.vue";
 | |
| 
 | |
| export default defineComponent({
 | |
|   components: {
 | |
|     UserAvatar,
 | |
|   },
 | |
|   props: {
 | |
|     slug: {
 | |
|       type: String,
 | |
|       required: true,
 | |
|     },
 | |
|     recipeId: {
 | |
|       type: String,
 | |
|       required: true,
 | |
|     },
 | |
|   },
 | |
|   setup(props) {
 | |
|     const api = useUserApi();
 | |
| 
 | |
|     const comments = ref<RecipeComment[]>([]);
 | |
| 
 | |
|     const state = reactive({
 | |
|       comment: "",
 | |
|     });
 | |
| 
 | |
|     onMounted(async () => {
 | |
|       const { data } = await api.recipes.comments.byRecipe(props.slug);
 | |
| 
 | |
|       if (data) {
 | |
|         comments.value = data;
 | |
|       }
 | |
|     });
 | |
| 
 | |
|     async function submitComment() {
 | |
|       const { data } = await api.recipes.comments.createOne({
 | |
|         recipeId: props.recipeId,
 | |
|         text: state.comment,
 | |
|       });
 | |
| 
 | |
|       if (data) {
 | |
|         comments.value.push(data);
 | |
|       }
 | |
| 
 | |
|       state.comment = "";
 | |
|     }
 | |
| 
 | |
|     async function deleteComment(id: string) {
 | |
|       const { response } = await api.recipes.comments.deleteOne(id);
 | |
| 
 | |
|       if (response?.status === 200) {
 | |
|         comments.value = comments.value.filter((comment) => comment.id !== id);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     return { api, comments, ...toRefs(state), submitComment, deleteComment };
 | |
|   },
 | |
| });
 | |
| </script>
 |