1
0
Fork 0
mirror of https://github.com/mealie-recipes/mealie.git synced 2025-08-02 20:15:24 +02:00

Feature/user photo storage (#877)

* add default assets for user profile

* add recipe avatar

* change user_id to UUID

* add profile image upload

* setup image cache keys

* cleanup tests and add image tests

* purge user data on delete

* new user repository tests

* add user_id validator for int -> UUID conversion

* delete depreciated route

* force set content type

* refactor tests to use temp directory

* validate parent exists before createing

* set user_id to correct type

* update instruction id

* reset primary key on migration
This commit is contained in:
Hayden 2021-12-18 19:04:36 -09:00 committed by GitHub
parent a2f8f27193
commit ea7c4771ee
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
64 changed files with 433 additions and 181 deletions

View file

@ -9,9 +9,8 @@
<v-divider class="mx-2"></v-divider>
<div class="d-flex flex-column">
<div class="d-flex mt-3" style="gap: 10px">
<v-avatar size="40">
<img alt="user" src="https://cdn.pixabay.com/photo/2020/06/24/19/12/cabbage-5337431_1280.jpg" />
</v-avatar>
<UserAvatar size="40" :user-id="$auth.user.id" />
<v-textarea
v-model="comment"
hide-details=""
@ -32,9 +31,7 @@
</div>
</div>
<div v-for="comment in comments" :key="comment.id" class="d-flex my-2" style="gap: 10px">
<v-avatar size="40">
<img alt="user" src="https://cdn.pixabay.com/photo/2020/06/24/19/12/cabbage-5337431_1280.jpg" />
</v-avatar>
<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>
@ -60,8 +57,12 @@
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,

View file

@ -0,0 +1,46 @@
<template>
<v-list-item-avatar v-if="list && userId">
<v-img :src="imageURL" :alt="userId" @load="error = false" @error="error = true"> </v-img>
</v-list-item-avatar>
<v-avatar v-else-if="userId" :size="size">
<v-img :src="imageURL" :alt="userId" @load="error = false" @error="error = true"> </v-img>
</v-avatar>
</template>
<script lang="ts">
import { defineComponent, toRefs, reactive, useContext, computed } from "@nuxtjs/composition-api";
export default defineComponent({
props: {
userId: {
type: String,
required: true,
},
list: {
type: Boolean,
default: false,
},
size: {
type: String,
default: "42",
},
},
setup(props) {
const state = reactive({
error: false,
});
const { $auth } = useContext();
const imageURL = computed(() => {
const key = $auth?.user?.cacheKey || "";
return `/api/media/users/${props.userId}/profile.webp?cacheKey=${key}`;
});
return {
imageURL,
...toRefs(state),
};
},
});
</script>

View file

@ -3,9 +3,7 @@
<!-- User Profile -->
<template v-if="$auth.user">
<v-list-item two-line to="/user/profile" exact>
<v-list-item-avatar color="accent" class="white--text">
<v-img :src="require(`~/static/account.png`)" />
</v-list-item-avatar>
<UserAvatar list :user-id="$auth.user.id" />
<v-list-item-content>
<v-list-item-title> {{ $auth.user.fullName }}</v-list-item-title>
@ -130,8 +128,12 @@
<script lang="ts">
import { defineComponent } from "@nuxtjs/composition-api";
import { SidebarLinks } from "~/types/application-types";
import UserAvatar from "~/components/Domain/User/UserAvatar.vue";
export default defineComponent({
components: {
UserAvatar,
},
props: {
value: {
type: Boolean,

View file

@ -17,10 +17,8 @@
hide-default-footer
disable-pagination
>
<template #item.avatar="">
<v-avatar>
<img src="https://i.pravatar.cc/300" alt="John" />
</v-avatar>
<template #item.avatar="{ item }">
<UserAvatar :user-id="item.id" />
</template>
<template #item.admin="{ item }">
{{ item.admin ? "Admin" : "User" }}
@ -66,8 +64,12 @@
import { defineComponent, ref, onMounted, useContext } from "@nuxtjs/composition-api";
import { useUserApi } from "~/composables/api";
import { UserOut } from "~/types/api-types/user";
import UserAvatar from "~/components/Domain/User/UserAvatar.vue";
export default defineComponent({
components: {
UserAvatar,
},
setup() {
const api = useUserApi();

View file

@ -2,12 +2,21 @@
<v-container class="narrow-container">
<BasePageTitle divider>
<template #header>
<v-img max-height="200" max-width="200" class="mb-2" :src="require('~/static/svgs/manage-profile.svg')"></v-img>
<div class="d-flex flex-column align-center justify-center">
<UserAvatar size="96" :user-id="$auth.user.id" />
<AppButtonUpload
class="my-1"
file-name="profile"
accept="image/*"
:url="`/api/users/${$auth.user.id}/image`"
@uploaded="$auth.fetchUser()"
/>
</div>
</template>
<template #title> Your Profile Settings </template>
</BasePageTitle>
<section>
<section class="mt-5">
<ToggleState tag="article">
<template #activator="{ toggle, state }">
<v-btn v-if="!state" color="info" class="mt-2 mb-n3" @click="toggle">
@ -105,8 +114,12 @@
<script lang="ts">
import { ref, reactive, defineComponent, computed, useContext, watch } from "@nuxtjs/composition-api";
import { useUserApi } from "~/composables/api";
import UserAvatar from "~/components/Domain/User/UserAvatar.vue";
export default defineComponent({
components: {
UserAvatar,
},
setup() {
const nuxtContext = useContext();
const user = computed(() => nuxtContext.$auth.user);

View file

@ -1,9 +1,8 @@
<template>
<v-container v-if="user">
<section class="d-flex flex-column align-center">
<v-avatar color="primary" size="75" class="mb-2">
<v-img :src="require(`~/static/account.png`)" />
</v-avatar>
<UserAvatar size="84" :user-id="$auth.user.id" />
<h2 class="headline">👋 Welcome, {{ user.fullName }}</h2>
<p class="subtitle-1 mb-0">
Manage your profile, recipes, and group settings.
@ -137,10 +136,13 @@ import UserProfileLinkCard from "@/components/Domain/User/UserProfileLinkCard.vu
import { useUserApi } from "~/composables/api";
import { validators } from "~/composables/use-validators";
import { alert } from "~/composables/use-toast";
import UserAvatar from "@/components/Domain/User/UserAvatar.vue";
export default defineComponent({
name: "UserProfile",
components: {
UserProfileLinkCard,
UserAvatar,
},
scrollToTop: true,
setup() {

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB