Skip to content
Snippets Groups Projects
Verified Commit dbd57df3 authored by Jonathan Weth's avatar Jonathan Weth :keyboard:
Browse files

Merge branch '759-finalise-vuetify-app-as-spa' of...

Merge branch '759-finalise-vuetify-app-as-spa' of edugit.org:AlekSIS/official/AlekSIS-Core into 759-finalise-vuetify-app-as-spa
parents 292afdae 86bbe6ba
No related branches found
No related tags found
1 merge request!1123Resolve "Finalise Vuetify app as SPA"
<template>
<v-app v-cloak>
<loading
v-if="$apollo.loading && (!currentUser || !whoAmI || !systemProperties)"
v-if="$apollo.loading && !systemProperties"
>
</loading>
<div v-else>
......@@ -102,26 +102,26 @@
<v-btn icon color="white" v-if="needRefresh && refreshDismissed" @click="refreshDismissed = false">
<v-icon>mdi-update</v-icon>
</v-btn>
<div v-if="currentUser.isAuthenticated" class="d-flex">
<notification-list />
<div v-if="whoAmI && whoAmI.isAuthenticated" class="d-flex">
<notification-list v-if="!whoAmI.person.isDummy" />
<v-menu offset-y>
<template #activator="{ on, attrs }">
<v-avatar v-bind="attrs" v-on="on">
<img
v-if="
systemProperties.sitePreferences.accountPersonPreferPhoto &&
whoAmI.photo &&
whoAmI.photo.url
whoAmI.person.photo &&
whoAmI.person.photo.url
"
:src="whoAmI.photo.url"
:alt="whoAmI.fullName"
:title="whoAmI.fullName"
:src="whoAmI.person.photo.url"
:alt="whoAmI.person.fullName"
:title="whoAmI.person.fullName"
/>
<img
v-else-if="whoAmI.avatarUrl"
:src="whoAmI.avatarUrl"
:alt="whoAmI.fullName + '(' + $t('person.avatar') + ')'"
:title="whoAmI.fullName + '(' + $t('person.avatar') + ')'"
v-else-if="whoAmI.person.avatarUrl"
:src="whoAmI.person.avatarUrl"
:alt="whoAmI.person.fullName + '(' + $t('person.avatar') + ')'"
:title="whoAmI.person.fullName + '(' + $t('person.avatar') + ')'"
/>
<v-icon v-else>mdi-person</v-icon>
</v-avatar>
......@@ -129,7 +129,7 @@
<v-list>
<v-subheader>
{{ $t(whoAmI && whoAmI.isImpersonate ? "person.impersonation.impersonating" : "person.logged_in_as") }}
{{ whoAmI.fullName ? whoAmI.fullName : currentUser.username }}
{{ whoAmI.person.fullName ? whoAmI.person.fullName : whoAmI.username }}
</v-subheader>
<v-list-item
v-if="whoAmI && whoAmI.isImpersonate"
......@@ -167,12 +167,12 @@
<broadcast-channel-notification channel-name="cache-or-not" />
<broadcast-channel-notification channel-name="offline-fallback" />
<message-box type="error" v-if="whoAmI && whoAmI.isDummy">
<message-box type="error" v-if="whoAmI && whoAmI.person && whoAmI.person.isDummy">
{{ $t("base.person_is_dummy") }}
</message-box>
<message-box
type="error"
v-else-if="!whoAmI && !currentUser.isAnonymous"
v-else-if="whoAmI && !whoAmI.person && !whoAmI.isAnonymous"
>
{{ $t("base.user_not_linked_to_person") }}
</message-box>
......@@ -213,7 +213,7 @@
</v-container>
</v-main>
<celery-progress-bottom v-if="currentUser && !currentUser.isAnonymous" />
<celery-progress-bottom v-if="whoAmI && !whoAmI.isAnonymous" />
<v-footer
app
......@@ -334,7 +334,6 @@ import Loading from "./components/Loading.vue";
import BrandLogo from "./components/BrandLogo.vue";
import SnackbarItem from "./components/SnackbarItem.vue";
import gqlCurrentUser from "./currentUser.graphql";
import gqlWhoAmI from "./whoAmI.graphql";
import gqlMessages from "./messages.graphql";
import gqlSystemProperties from "./systemProperties.graphql";
......@@ -350,7 +349,6 @@ export default {
data() {
return {
drawer: this.$vuetify.breakpoint.lgAndUp,
currentUser: null,
whoAmI: null,
systemProperties: null,
messages: null,
......@@ -434,10 +432,6 @@ export default {
},
apollo: {
systemProperties: gqlSystemProperties,
currentUser: {
query: gqlCurrentUser,
pollInterval: 10000,
},
whoAmI: {
query: gqlWhoAmI,
pollInterval: 10000,
......@@ -482,8 +476,9 @@ export default {
this.$vuetify.theme.themes.dark.secondary =
newProperties.sitePreferences.themeSecondary;
},
whoAmI: function (person) {
this.$vuetify.theme.dark = person.preferences.themeDesignMode === "dark";
whoAmI: function (user) {
this.$vuetify.theme.dark = user.person && user.person.preferences.themeDesignMode === "dark";
this.$apollo.queries.permissionResults.refetch();
},
permissionResults: {
handler(newResults) {
......
......@@ -123,7 +123,7 @@ function addErrorSnackbarItem (messageKey) {
const retryLink = new RetryLink();
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors) addErrorSnackbarItem("graphql_errors.snackbar_error_message")
if (graphQLErrors) addErrorSnackbarItem("graphql.snackbar_error_message")
if (networkError) addErrorSnackbarItem("network_errors.snackbar_error_message")
});
......
......@@ -22,24 +22,29 @@
>
<v-icon
color="white"
v-if="data && data.myNotifications.unreadNotificationsCount > 0"
v-if="data && data.myNotifications.person && data.myNotifications.person.unreadNotificationsCount > 0"
>
mdi-bell-badge-outline
</v-icon>
<v-icon color="white" v-else>mdi-bell-outline</v-icon>
</v-btn>
</template>
<v-list nav three-line dense class="overflow-y-auto">
<v-skeleton-loader
v-if="loading"
class="mx-auto"
type="paragraph"
></v-skeleton-loader>
<v-list v-else nav three-line dense class="overflow-y-auto">
<template
v-if="
data &&
data.myNotifications &&
data.myNotifications.notifications.length
data.myNotifications.person &&
data.myNotifications.person.notifications &&
data.myNotifications.person.notifications.length
"
>
<v-subheader>{{ $t("notifications.notifications") }}</v-subheader>
<template
v-for="notification in data.myNotifications.notifications"
v-for="notification in data.myNotifications.person.notifications"
>
<NotificationItem
:key="notification.id"
......@@ -48,8 +53,8 @@
<v-divider
v-if="
notification !==
data.myNotifications.notifications[
data.myNotifications.notifications.length - 1
data.myNotifications.person.notifications[
data.myNotifications.person.notifications.length - 1
]
"
:key="notification.id + '-divider'"
......
{
myNotifications: whoAmI {
unreadNotificationsCount
notifications {
id
title
description
link
icon
created
sender
read
person {
unreadNotificationsCount
notifications {
id
title
description
link
icon
created
sender
read
}
}
}
}
{
currentUser {
isAuthenticated
isAnonymous
}
}
......@@ -175,11 +175,15 @@
"network_errors": {
"error_404": "404",
"page_not_found": "The requested page or resource could not be found.",
"take_me_back": "Take me back"
"take_me_back": "Take me back",
"snackbar_error_message": "A network error occurred. Please try again."
},
"service_worker": {
"new_version_available": "A new version of the app is available",
"update": "Update",
"dismiss": "Dismiss"
},
"graphql": {
"snackbar_error_message": "There was an error retrieving the page data. Please try again."
}
}
{
whoAmI {
unreadNotificationsCount
photo {
url
}
fullName
avatarUrl
isDummy
isImpersonate
preferences {
themeDesignMode
username
isAuthenticated
isAnonymous
person {
photo {
url
}
fullName
avatarUrl
isDummy
isImpersonate
preferences {
themeDesignMode
}
}
}
}
......@@ -31,12 +31,11 @@ class Query(graphene.ObjectType):
notifications = graphene.List(NotificationType)
current_user = graphene.Field(UserType)
persons = graphene.List(PersonType)
person_by_id = graphene.Field(PersonType, id=graphene.ID())
person_by_id_or_me = graphene.Field(PersonType, id=graphene.ID())
who_am_i = graphene.Field(PersonType)
who_am_i = graphene.Field(UserType)
system_properties = graphene.Field(SystemPropertiesType)
installed_apps = graphene.List(AppType)
......@@ -76,7 +75,7 @@ class Query(graphene.ObjectType):
return person
def resolve_person_by_id_or_me(root, info, id): # noqa
# Returns current user if id is None, else the person with the id
# Returns person associated with current user if id is None, else the person with the id
if id is None:
return info.context.user.person if has_person(info.context.user) else None
......@@ -86,12 +85,6 @@ class Query(graphene.ObjectType):
return person
def resolve_who_am_i(root, info, **kwargs):
if has_person(info.context.user):
return info.context.user.person
else:
return None
def resolve_current_user(root, info, **kwargs):
return info.context.user
def resolve_system_properties(root, info, **kwargs):
......
......@@ -10,6 +10,7 @@ from graphene_django.forms.mutation import DjangoModelFormMutation
from ..forms import PersonForm
from ..models import DummyPerson, Person
from ..util.core_helpers import get_site_preferences, is_impersonate
from .notification import NotificationType
class FieldFileType(graphene.ObjectType):
......@@ -33,13 +34,15 @@ class PersonType(DjangoObjectType):
full_name = graphene.String()
username = graphene.String()
userid = graphene.ID()
unread_notifications_count = graphene.Int()
photo = graphene.Field(FieldFileType)
avatar = graphene.Field(FieldFileType)
avatar_url = graphene.String()
avatar_content_url = graphene.String()
secondary_image_url = graphene.String()
notifications = graphene.List(NotificationType)
unread_notifications_count = graphene.Int()
is_dummy = graphene.Boolean()
is_impersonate = graphene.Boolean()
preferences = graphene.Field(PersonPreferencesType)
......@@ -56,6 +59,9 @@ class PersonType(DjangoObjectType):
def resolve_userid(root, info, **kwargs): # noqa
return root.user.id if root.user else None
def resolve_unread_notifications_count(root, info, **kwargs): # noqa
return root.unread_notifications_count
def resolve_photo(root, info, **kwargs):
if info.context.user.has_perm("core.view_photo_rule", root):
return root.photo
......
import graphene
from .person import PersonType
class UserType(graphene.ObjectType):
id = graphene.ID()
username = graphene.String()
first_name = graphene.String()
last_name = graphene.String()
is_authenticated = graphene.Boolean(required=True)
is_anonymous = graphene.Boolean(required=True)
person = graphene.Field(PersonType)
......@@ -62,7 +62,6 @@
<body class="without-menu">
<main role="main" id="mainReduced">
{% include 'core/partials/no_person.html' %}
{% block no_page_title %}
<h1>{% block page_title %}{% endblock %}</h1>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment