Browse Source

Merge pull request #225 from pinry/feature/personal-profile

Feature/personal profile
tags/v2.1.4
Ji Qu 4 years ago
committed by GitHub
parent
commit
40326133c4
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 196 additions and 4 deletions
  1. +1
    -1
      pinry-spa/package.json
  2. +137
    -0
      pinry-spa/src/components/UserProfileCard.vue
  3. +17
    -0
      pinry-spa/src/components/api.js
  4. +3
    -0
      pinry-spa/src/views/Boards4User.vue
  5. +3
    -0
      pinry-spa/src/views/Pins4User.vue
  6. +3
    -3
      pinry-spa/yarn.lock
  7. +15
    -0
      users/serializers.py
  8. +17
    -0
      users/views.py

+ 1
- 1
pinry-spa/package.json View File

@@ -9,7 +9,7 @@
},
"dependencies": {
"axios": "^0.19.0",
"buefy": "^0.8.8",
"buefy": "^0.8.20",
"core-js": "^3.3.2",
"register-service-worker": "^1.6.2",
"vue": "^2.6.10",


+ 137
- 0
pinry-spa/src/components/UserProfileCard.vue View File

@@ -0,0 +1,137 @@
<template>
<div class="user-profile-card">
<div id="user-home-container">
<div class="card">
<div class="card-content">
<div class="media">
<div class="media-left">
<figure class="image is-48x48">
<b-skeleton width="48px" height="48px" :active="avatarLoading"></b-skeleton>
<img
@load="onAvatarLoaded"
v-show="!avatarLoading"
:src="user.avatar"
alt="avatar"
>
</figure>
</div>
<div class="media-content" v-show="!avatarLoading">
<p class="title is-4">{{ user.username }}</p>
<p class="subtitle is-6">@{{ location }}</p>
</div>
</div>
<div class="content">
Yet another Pinry user.
<br>
</div>

<div class="tabs is-toggle">
<ul>
<li :class="trueFalse2Class(inPins)">
<a @click="go2UserPins">
<b-icon
type="is-dark"
icon="image"
custom-size="mdi-24px">
</b-icon>
<span>Pins</span>
</a>
</li>
<li :class="trueFalse2Class(inBoard)">
<a @click="go2UserBoard">
<b-icon
type="is-dark"
icon="folder-multiple-image"
custom-size="mdi-24px">
</b-icon>
<span>Boards</span>
</a>
</li>
</ul>
</div>

</div>
</div>
</div>
</div>
</template>

<script>
import api from './api';

export default {
name: 'UserProfileCard.vue',
props: {
username: String,
inBoard: {
type: Boolean,
default: false,
},
inPins: {
type: Boolean,
default: false,
},
},
data() {
return {
location: window.location.host,
avatarLoading: true,
user: {
avatar: '',
username: '',
},
};
},
beforeMount() {
this.initializeUser(this.username);
},
methods: {
go2UserBoard() {
this.$router.push(
{ name: 'boards4user', params: { username: this.username } },
);
},
go2UserPins() {
this.$router.push(
{ name: 'user', params: { user: this.username } },
);
},
trueFalse2Class(boolValue) {
if (boolValue) {
return 'is-active';
}
return '';
},
onAvatarLoaded() {
this.avatarLoading = false;
},
initializeUser(username) {
const self = this;
api.User.fetchUserInfoByName(username).then(
(user) => {
if (user === null) {
self.$router.push(
{ name: 'PageNotFound' },
);
} else {
self.user.avatar = `//gravatar.com/avatar/${user.gravatar}`;
self.user.username = user.username;
self.user.meta = user;
}
},
);
},
},
};
</script>

<style lang="scss" scoped>
#user-home-container {
margin-top: 2rem;
margin-left: auto;
margin-right: auto;
box-shadow: 5px 5px 2px 1px rgba(0, 0, 255, .1);
}
@import '../components/utils/grid-layout';
@include screen-grid-layout("#user-home-container");
</style>

+ 17
- 0
pinry-spa/src/components/api.js View File

@@ -238,6 +238,23 @@ const User = {
},
);
},
fetchUserInfoByName(username) {
/* returns null if user not logged in */
const url = `${API_PREFIX}profile/public-users/?username=${username}`;
return new Promise(
(resolve) => {
axios.get(url).then(
(resp) => {
const users = resp.data;
if (users.length === 0) {
return resolve(null);
}
return resolve(users[0]);
},
);
},
);
},
fetchUserInfo(force = false) {
/* returns null if user not logged in */
const self = this;


+ 3
- 0
pinry-spa/src/views/Boards4User.vue View File

@@ -1,12 +1,14 @@
<template>
<div class="boards-for-user">
<PHeader></PHeader>
<UserProfileCard :in-board="true" :username="filters.boardUsername"></UserProfileCard>
<Boards :filters="filters"></Boards>
</div>
</template>

<script>
import PHeader from '../components/PHeader.vue';
import UserProfileCard from '../components/UserProfileCard.vue';
import Boards from '../components/Boards.vue';

export default {
@@ -18,6 +20,7 @@ export default {
},
components: {
PHeader,
UserProfileCard,
Boards,
},
created() {


+ 3
- 0
pinry-spa/src/views/Pins4User.vue View File

@@ -1,12 +1,14 @@
<template>
<div class="pins-for-user">
<PHeader></PHeader>
<UserProfileCard :in-pins="true" :username="filters.userFilter"></UserProfileCard>
<Pins :pin-filters="filters"></Pins>
</div>
</template>

<script>
import PHeader from '../components/PHeader.vue';
import UserProfileCard from '../components/UserProfileCard.vue';
import Pins from '../components/Pins.vue';

export default {
@@ -18,6 +20,7 @@ export default {
},
components: {
PHeader,
UserProfileCard,
Pins,
},
created() {


+ 3
- 3
pinry-spa/yarn.lock View File

@@ -1602,9 +1602,9 @@ browserslist@^4.0.0, browserslist@^4.6.0, browserslist@^4.7.3, browserslist@^4.8
electron-to-chromium "^1.3.322"
node-releases "^1.1.42"

buefy@^0.8.8:
version "0.8.8"
resolved "https://registry.npm.taobao.org/buefy/download/buefy-0.8.8.tgz#dc6a26c74793a6e28ee435d5ee06bdfe811dc9f4"
buefy@^0.8.20:
version "0.8.20"
resolved "https://registry.yarnpkg.com/buefy/-/buefy-0.8.20.tgz#75708800548220654575903d031a81fc8575b7f3"
dependencies:
bulma "0.7.5"



+ 15
- 0
users/serializers.py View File

@@ -6,6 +6,21 @@ from rest_framework.exceptions import ValidationError
from users.models import User


class PublicUserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = (
'username',
'gravatar',
settings.DRF_URL_FIELD_NAME,
)
extra_kwargs = {
settings.DRF_URL_FIELD_NAME: {
"view_name": "public-users:user-detail",
},
}


class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User


+ 17
- 0
users/views.py View File

@@ -7,6 +7,7 @@ from django.contrib.auth.decorators import login_required
from django.http import HttpResponseRedirect, HttpResponseBadRequest, HttpResponse
from django.urls import reverse
from django.utils.functional import lazy
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import mixins, routers
from rest_framework.permissions import BasePermission
from rest_framework.renderers import JSONRenderer
@@ -20,6 +21,21 @@ def reverse_lazy(name=None, *args):
return lazy(reverse, str)(name, args=args)


class PublicUserViewSet(
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet,
):
serializer_class = UserSerializer
filter_backends = (DjangoFilterBackend, )
filter_fields = ("username", )
pagination_class = None

def get_queryset(self):
username = self.request.GET.get("username", "")
return User.objects.filter(username=username)


class UserViewSet(
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
@@ -87,3 +103,4 @@ def logout_user(request):

drf_router = routers.DefaultRouter()
drf_router.register(r'users', UserViewSet, basename="user")
drf_router.register(r'public-users', PublicUserViewSet, basename="public-user")

Loading…
Cancel
Save