diff --git a/js/package.json b/js/package.json index cabd2a04..b687e60a 100644 --- a/js/package.json +++ b/js/package.json @@ -4,7 +4,7 @@ "private": true, "scripts": { "serve": "vue-cli-service serve", - "build": "vue-cli-service build", + "build": "vue-cli-service build --modern", "test:unit": "vue-cli-service test:unit", "test:e2e": "vue-cli-service test:e2e", "lint": "vue-cli-service lint" diff --git a/js/src/graphql/admin.ts b/js/src/graphql/admin.ts index b135a001..292ef241 100644 --- a/js/src/graphql/admin.ts +++ b/js/src/graphql/admin.ts @@ -4,6 +4,7 @@ export const DASHBOARD = gql` query { dashboard { lastPublicEventPublished { + id uuid title picture { @@ -12,10 +13,24 @@ export const DASHBOARD = gql` url } } + lastGroupCreated { + id + preferredUsername + domain + name + avatar { + id + url + } + } numberOfUsers numberOfEvents numberOfComments numberOfReports + numberOfGroups + numberOfFollowers + numberOfFollowings + numberOfConfirmedParticipationsToLocalEvents } } `; diff --git a/js/src/i18n/en_US.json b/js/src/i18n/en_US.json index 33f56d79..44a48d42 100644 --- a/js/src/i18n/en_US.json +++ b/js/src/i18n/en_US.json @@ -281,7 +281,7 @@ "Public feeds": "Public feeds", "Public iCal Feed": "Public iCal Feed", "Publish": "Publish", - "Published events": "Published events", + "Published events with {comments} comments and {participations} confirmed participations": "Published events with {comments} comments and {participations} confirmed participations", "RSS/Atom Feed": "RSS/Atom Feed", "Read Framasoft’s statement of intent on the Framablog": "Read Framasoft’s statement of intent on the Framablog", "Redirecting to event…": "Redirecting to event…", @@ -800,5 +800,8 @@ "To register for an event by choosing one of your identities": "To register for an event by choosing one of your identities", "To create or join an group and start organizing with other people": "To create or join an group and start organizing with other people", "About {instance}": "About {instance}", - "Please read the {fullRules} published by {instance}'s administrators.": "Please read the {fullRules} published by {instance}'s administrators." + "Please read the {fullRules} published by {instance}'s administrators.": "Please read the {fullRules} published by {instance}'s administrators.", + "Instances following you": "Instances following you", + "Instances you follow": "Instances you follow", + "Last group created": "Last group created" } diff --git a/js/src/i18n/fr_FR.json b/js/src/i18n/fr_FR.json index f2591f63..5ae9009c 100644 --- a/js/src/i18n/fr_FR.json +++ b/js/src/i18n/fr_FR.json @@ -532,7 +532,7 @@ "Public page": "Page publique", "Publication date": "Date de publication", "Publish": "Publier", - "Published events": "Événements publiés", + "Published events with {comments} comments and {participations} confirmed participations": "Événements publiés avec {comments} commentaires et {participations} participations confirmées", "RSS/Atom Feed": "Flux RSS/Atom", "Radius": "Rayon", "Read Framasoft’s statement of intent on the Framablog": "Lire la note d’intention de Framasoft sur le Framablog", @@ -850,5 +850,8 @@ "To register for an event by choosing one of your identities": "Pour s'inscrire à un évènement en choisissant une de vos identités", "To create or join an group and start organizing with other people": "Pour créer ou rejoindre un groupe et commencer à vous organiser avec d'autres personnes", "About {instance}": "À propos de {instance}", - "Please read the {fullRules} published by {instance}'s administrators.": "Merci de lire les {fullRules} publiées par les administrateur·ices de {instance}." + "Please read the {fullRules} published by {instance}'s administrators.": "Merci de lire les {fullRules} publiées par les administrateur·ices de {instance}.", + "Instances following you": "Instances vous suivant", + "Instances you follow": "Instances que vous suivez", + "Last group created": "Dernier groupe créé" } diff --git a/js/src/router/actor.ts b/js/src/router/actor.ts index 012dc67a..28c6e866 100644 --- a/js/src/router/actor.ts +++ b/js/src/router/actor.ts @@ -1,7 +1,4 @@ import { RouteConfig } from "vue-router"; -import CreateGroup from "@/views/Group/Create.vue"; -import Group from "@/views/Group/Group.vue"; -import MyGroups from "@/views/Group/MyGroups.vue"; export enum ActorRouteName { GROUP = "Group", @@ -14,20 +11,20 @@ export const actorRoutes: RouteConfig[] = [ { path: "/groups/create", name: ActorRouteName.CREATE_GROUP, - component: CreateGroup, + component: () => import(/* webpackChunkName: "CreateGroup" */ "@/views/Group/Create.vue"), meta: { requiredAuth: true }, }, { path: "/@:preferredUsername", name: ActorRouteName.GROUP, - component: Group, + component: () => import(/* webpackChunkName: "Group" */ "@/views/Group/Group.vue"), props: true, meta: { requiredAuth: false }, }, { path: "/groups/me", name: ActorRouteName.MY_GROUPS, - component: MyGroups, + component: () => import(/* webpackChunkName: "MyGroups" */ "@/views/Group/MyGroups.vue"), meta: { requiredAuth: true }, }, ]; diff --git a/js/src/router/discussion.ts b/js/src/router/discussion.ts index 1767c284..0fb62b37 100644 --- a/js/src/router/discussion.ts +++ b/js/src/router/discussion.ts @@ -1,7 +1,4 @@ import { RouteConfig } from "vue-router"; -import CreateDiscussion from "@/views/Discussions/Create.vue"; -import DiscussionsList from "@/views/Discussions/DiscussionsList.vue"; -import discussion from "@/views/Discussions/Discussion.vue"; export enum DiscussionRouteName { DISCUSSION_LIST = "DISCUSSION_LIST", @@ -13,21 +10,24 @@ export const discussionRoutes: RouteConfig[] = [ { path: "/@:preferredUsername/discussions", name: DiscussionRouteName.DISCUSSION_LIST, - component: DiscussionsList, + component: () => + import(/* webpackChunkName: "DiscussionsList" */ "@/views/Discussions/DiscussionsList.vue"), props: true, meta: { requiredAuth: false }, }, { path: "/@:preferredUsername/discussions/new", name: DiscussionRouteName.CREATE_DISCUSSION, - component: CreateDiscussion, + component: () => + import(/* webpackChunkName: "CreateDiscussion" */ "@/views/Discussions/Create.vue"), props: true, meta: { requiredAuth: true }, }, { path: "/@:preferredUsername/c/:slug/:comment_id?", name: DiscussionRouteName.DISCUSSION, - component: discussion, + component: () => + import(/* webpackChunkName: "Discussion" */ "@/views/Discussions/Discussion.vue"), props: true, meta: { requiredAuth: false }, }, diff --git a/js/src/router/error.ts b/js/src/router/error.ts index 83022661..fc2f5af1 100644 --- a/js/src/router/error.ts +++ b/js/src/router/error.ts @@ -1,6 +1,5 @@ import { beforeRegisterGuard } from "@/router/guards/register-guard"; import { RouteConfig } from "vue-router"; -import ErrorPage from "../views/Error.vue"; export enum ErrorRouteName { ERROR = "Error", @@ -10,7 +9,7 @@ export const errorRoutes: RouteConfig[] = [ { path: "/error", name: ErrorRouteName.ERROR, - component: ErrorPage, + component: () => import(/* webpackChunkName: "Error" */ "../views/Error.vue"), beforeEnter: beforeRegisterGuard, }, ]; diff --git a/js/src/router/event.ts b/js/src/router/event.ts index c7ec47cb..6dbc6add 100644 --- a/js/src/router/event.ts +++ b/js/src/router/event.ts @@ -1,7 +1,4 @@ import { RouteConfig, Route } from "vue-router"; -import EventList from "../views/Event/EventList.vue"; -import Location from "../views/Location.vue"; -import Search from "../views/Search.vue"; const participations = () => import(/* webpackChunkName: "participations" */ "@/views/Event/Participants.vue"); @@ -29,7 +26,7 @@ export const eventRoutes: RouteConfig[] = [ { path: "/events/list/:location?", name: EventRouteName.EVENT_LIST, - component: EventList, + component: () => import(/* webpackChunkName: "EventList" */ "@/views/Event/EventList.vue"), meta: { requiredAuth: false }, }, { @@ -68,7 +65,7 @@ export const eventRoutes: RouteConfig[] = [ { path: "/location/new", name: EventRouteName.LOCATION, - component: Location, + component: () => import(/* webpackChunkName: "Location" */ "@/views/Location.vue"), meta: { requiredAuth: true }, }, { @@ -105,7 +102,7 @@ export const eventRoutes: RouteConfig[] = [ { path: "/tag/:tag", name: EventRouteName.TAG, - component: Search, + component: () => import(/* webpackChunkName: "Search" */ "@/views/Search.vue"), props: true, meta: { requiredAuth: false }, }, diff --git a/js/src/router/index.ts b/js/src/router/index.ts index 2ce38554..6412f937 100644 --- a/js/src/router/index.ts +++ b/js/src/router/index.ts @@ -2,13 +2,11 @@ import Vue from "vue"; import Router, { Route } from "vue-router"; import VueScrollTo from "vue-scrollto"; import { PositionResult } from "vue-router/types/router.d"; -import PageNotFound from "../views/PageNotFound.vue"; import Home from "../views/Home.vue"; import { eventRoutes } from "./event"; import { actorRoutes } from "./actor"; import { errorRoutes } from "./error"; import { authGuardIfNeeded } from "./guards/auth-guard"; -import Search from "../views/Search.vue"; import { settingsRoutes } from "./settings"; import { groupsRoutes } from "./groups"; import { discussionRoutes } from "./discussion"; @@ -51,7 +49,7 @@ const router = new Router({ { path: "/search", name: RouteName.SEARCH, - component: Search, + component: () => import(/* webpackChunkName: "search" */ "../views/Search.vue"), props: true, meta: { requiredAuth: false }, }, @@ -115,12 +113,13 @@ const router = new Router({ { path: "/auth/:provider/callback", name: "auth-callback", - component: () => import("@/views/User/ProviderValidation.vue"), + component: () => + import(/* webpackChunkName: "ProviderValidation" */ "@/views/User/ProviderValidation.vue"), }, { path: "/404", name: RouteName.PAGE_NOT_FOUND, - component: PageNotFound, + component: () => import(/* webpackChunkName: "search" */ "../views/PageNotFound.vue"), meta: { requiredAuth: false }, }, { diff --git a/js/src/router/settings.ts b/js/src/router/settings.ts index b1cf752d..a2a70071 100644 --- a/js/src/router/settings.ts +++ b/js/src/router/settings.ts @@ -1,23 +1,4 @@ import { RouteConfig } from "vue-router"; -import Settings from "@/views/Settings.vue"; -import AccountSettings from "@/views/Settings/AccountSettings.vue"; -import Preferences from "@/views/Settings/Preferences.vue"; -import Notifications from "@/views/Settings/Notifications.vue"; -import Dashboard from "@/views/Admin/Dashboard.vue"; -import AdminSettings from "@/views/Admin/Settings.vue"; -import Follows from "@/views/Admin/Follows.vue"; -import Followings from "@/components/Admin/Followings.vue"; -import Followers from "@/components/Admin/Followers.vue"; -import ReportList from "@/views/Moderation/ReportList.vue"; -import Report from "@/views/Moderation/Report.vue"; -import Logs from "@/views/Moderation/Logs.vue"; -import EditIdentity from "@/views/Account/children/EditIdentity.vue"; -import Users from "../views/Admin/Users.vue"; -import Profiles from "../views/Admin/Profiles.vue"; -import AdminProfile from "../views/Admin/AdminProfile.vue"; -import AdminUserProfile from "../views/Admin/AdminUserProfile.vue"; -import GroupProfiles from "../views/Admin/GroupProfiles.vue"; -import AdminGroupProfile from "../views/Admin/AdminGroupProfile.vue"; export enum SettingsRouteName { SETTINGS = "SETTINGS", @@ -49,7 +30,7 @@ export enum SettingsRouteName { export const settingsRoutes: RouteConfig[] = [ { path: "/settings", - component: Settings, + component: () => import(/* webpackChunkName: "Settings" */ "@/views/Settings.vue"), props: true, meta: { requiredAuth: true }, redirect: { name: SettingsRouteName.ACCOUNT_SETTINGS }, @@ -63,21 +44,24 @@ export const settingsRoutes: RouteConfig[] = [ { path: "account/general", name: SettingsRouteName.ACCOUNT_SETTINGS_GENERAL, - component: AccountSettings, + component: () => + import(/* webpackChunkName: "AccountSettings" */ "@/views/Settings/AccountSettings.vue"), props: true, meta: { requiredAuth: true }, }, { path: "preferences", name: SettingsRouteName.PREFERENCES, - component: Preferences, + component: () => + import(/* webpackChunkName: "Preferences" */ "@/views/Settings/Preferences.vue"), props: true, meta: { requiredAuth: true }, }, { path: "notifications", name: SettingsRouteName.NOTIFICATIONS, - component: Notifications, + component: () => + import(/* webpackChunkName: "Notifications" */ "@/views/Settings/Notifications.vue"), props: true, meta: { requiredAuth: true }, }, @@ -89,55 +73,61 @@ export const settingsRoutes: RouteConfig[] = [ { path: "admin/dashboard", name: SettingsRouteName.ADMIN_DASHBOARD, - component: Dashboard, + component: () => import(/* webpackChunkName: "Dashboard" */ "@/views/Admin/Dashboard.vue"), meta: { requiredAuth: true }, }, { path: "admin/settings", name: SettingsRouteName.ADMIN_SETTINGS, - component: AdminSettings, + component: () => + import(/* webpackChunkName: "AdminSettings" */ "@/views/Admin/Settings.vue"), props: true, meta: { requiredAuth: true }, }, { path: "admin/users", name: SettingsRouteName.USERS, - component: Users, + component: () => import(/* webpackChunkName: "Users" */ "@/views/Admin/Users.vue"), props: true, meta: { requiredAuth: true }, }, { path: "admin/users/:id", name: SettingsRouteName.ADMIN_USER_PROFILE, - component: AdminUserProfile, + component: () => + import(/* webpackChunkName: "AdminUserProfile" */ "@/views/Admin/AdminUserProfile.vue"), props: true, meta: { requiredAuth: true }, }, { path: "admin/profiles", name: SettingsRouteName.PROFILES, - component: Profiles, + component: () => + import(/* webpackChunkName: "AdminProfiles" */ "@/views/Admin/Profiles.vue"), props: true, meta: { requiredAuth: true }, }, { path: "admin/profiles/:id", name: SettingsRouteName.ADMIN_PROFILE, - component: AdminProfile, + component: () => + import(/* webpackChunkName: "AdminProfile" */ "@/views/Admin/AdminProfile.vue"), props: true, meta: { requiredAuth: true }, }, { path: "admin/groups", name: SettingsRouteName.ADMIN_GROUPS, - component: GroupProfiles, + component: () => + import(/* webpackChunkName: "GroupProfiles" */ "@/views/Admin/GroupProfiles.vue"), props: true, meta: { requiredAuth: true }, }, { path: "admin/groups/:id", name: SettingsRouteName.ADMIN_GROUP_PROFILE, - component: AdminGroupProfile, + component: () => + import(/* webpackChunkName: "AdminGroupProfile" */ "@/views/Admin/AdminGroupProfile.vue"), props: true, meta: { requiredAuth: true }, }, @@ -145,17 +135,19 @@ export const settingsRoutes: RouteConfig[] = [ path: "admin/relays", name: SettingsRouteName.RELAYS, redirect: { name: SettingsRouteName.RELAY_FOLLOWINGS }, - component: Follows, + component: () => import(/* webpackChunkName: "Follows" */ "@/views/Admin/Follows.vue"), children: [ { path: "followings", name: SettingsRouteName.RELAY_FOLLOWINGS, - component: Followings, + component: () => + import(/* webpackChunkName: "Followings" */ "@/components/Admin/Followings.vue"), }, { path: "followers", name: SettingsRouteName.RELAY_FOLLOWERS, - component: Followers, + component: () => + import(/* webpackChunkName: "Followers" */ "@/components/Admin/Followers.vue"), }, ], props: true, @@ -169,21 +161,23 @@ export const settingsRoutes: RouteConfig[] = [ { path: "/moderation/reports/:filter?", name: SettingsRouteName.REPORTS, - component: ReportList, + component: () => + import(/* webpackChunkName: "ReportList" */ "@/views/Moderation/ReportList.vue"), props: true, meta: { requiredAuth: true }, }, { path: "/moderation/report/:reportId", name: SettingsRouteName.REPORT, - component: Report, + component: () => import(/* webpackChunkName: "Report" */ "@/views/Moderation/Report.vue"), props: true, meta: { requiredAuth: true }, }, { path: "/moderation/logs", name: SettingsRouteName.REPORT_LOGS, - component: Logs, + component: () => + import(/* webpackChunkName: "ModerationLogs" */ "@/views/Moderation/Logs.vue"), props: true, meta: { requiredAuth: true }, }, @@ -195,13 +189,19 @@ export const settingsRoutes: RouteConfig[] = [ { path: "/identity/create", name: SettingsRouteName.CREATE_IDENTITY, - component: EditIdentity, + component: () => + import( + /* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue" + ), props: (route) => ({ identityName: route.params.identityName, isUpdate: false }), }, { path: "/identity/update/:identityName?", name: SettingsRouteName.UPDATE_IDENTITY, - component: EditIdentity, + component: () => + import( + /* webpackChunkName: "EditIdentity" */ "@/views/Account/children/EditIdentity.vue" + ), props: (route) => ({ identityName: route.params.identityName, isUpdate: true }), }, ], diff --git a/js/src/router/user.ts b/js/src/router/user.ts index e5f5e98e..96989b5a 100644 --- a/js/src/router/user.ts +++ b/js/src/router/user.ts @@ -16,7 +16,7 @@ export const userRoutes: RouteConfig[] = [ { path: "/register/user", name: UserRouteName.REGISTER, - component: () => import("@/views/User/Register.vue"), + component: () => import(/* webpackChunkName: "RegisterUser" */ "@/views/User/Register.vue"), props: true, meta: { requiredAuth: false }, beforeEnter: beforeRegisterGuard, @@ -24,7 +24,8 @@ export const userRoutes: RouteConfig[] = [ { path: "/register/profile", name: UserRouteName.REGISTER_PROFILE, - component: () => import("@/views/Account/Register.vue"), + component: () => + import(/* webpackChunkName: "RegisterProfile" */ "@/views/Account/Register.vue"), // We can only pass string values through params, therefore props: (route) => ({ email: route.params.email, @@ -35,42 +36,46 @@ export const userRoutes: RouteConfig[] = [ { path: "/resend-instructions", name: UserRouteName.RESEND_CONFIRMATION, - component: () => import("@/views/User/ResendConfirmation.vue"), + component: () => + import(/* webpackChunkName: "ResendConfirmation" */ "@/views/User/ResendConfirmation.vue"), props: true, meta: { requiresAuth: false }, }, { path: "/password-reset/send", name: UserRouteName.SEND_PASSWORD_RESET, - component: () => import("@/views/User/SendPasswordReset.vue"), + component: () => + import(/* webpackChunkName: "SendPasswordReset" */ "@/views/User/SendPasswordReset.vue"), props: true, meta: { requiresAuth: false }, }, { path: "/password-reset/:token", name: UserRouteName.PASSWORD_RESET, - component: () => import("@/views/User/PasswordReset.vue"), + component: () => + import(/* webpackChunkName: "PasswordReset" */ "@/views/User/PasswordReset.vue"), meta: { requiresAuth: false }, props: true, }, { path: "/validate/email/:token", name: UserRouteName.EMAIL_VALIDATE, - component: () => import("@/views/User/EmailValidate.vue"), + component: () => + import(/* webpackChunkName: "EmailValidate" */ "@/views/User/EmailValidate.vue"), props: true, meta: { requiresAuth: false }, }, { path: "/validate/:token", name: UserRouteName.VALIDATE, - component: () => import("@/views/User/Validate.vue"), + component: () => import(/* webpackChunkName: "Validate" */ "@/views/User/Validate.vue"), props: true, meta: { requiresAuth: false }, }, { path: "/login", name: UserRouteName.LOGIN, - component: () => import("@/views/User/Login.vue"), + component: () => import(/* webpackChunkName: "Login" */ "@/views/User/Login.vue"), props: true, meta: { requiredAuth: false }, }, diff --git a/js/src/types/admin.model.ts b/js/src/types/admin.model.ts index cf50a4f3..16534d35 100644 --- a/js/src/types/admin.model.ts +++ b/js/src/types/admin.model.ts @@ -1,11 +1,17 @@ import { IEvent } from "@/types/event.model"; +import { IGroup } from "./actor"; export interface IDashboard { lastPublicEventPublished: IEvent; + lastGroupCreated: IGroup; numberOfUsers: number; numberOfEvents: number; numberOfComments: number; numberOfReports: number; + numberOfGroups: number; + numberOfFollowers: number; + numberOfFollowings: number; + numberOfConfirmedParticipationsToLocalEvents: number; } export enum InstanceTermsType { diff --git a/js/src/views/Admin/Dashboard.vue b/js/src/views/Admin/Dashboard.vue index 18b55838..c7186642 100644 --- a/js/src/views/Admin/Dashboard.vue +++ b/js/src/views/Admin/Dashboard.vue @@ -18,11 +18,23 @@

{{ dashboard.numberOfEvents }}

-

{{ $t("Published events") }}

+

-

{{ dashboard.numberOfComments }}

-

{{ $t("Comments") }}

+ +

{{ dashboard.numberOfGroups }}

+

{{ $t("Groups") }}

+
@@ -32,29 +44,66 @@

{{ $t("Users") }}

+
+ +

{{ dashboard.numberOfFollowers }}

+

{{ $t("Instances following you") }}

+
+
+
+

{{ dashboard.numberOfReports }}

{{ $t("Opened reports") }}

+
+ +

{{ dashboard.numberOfFollowings }}

+

{{ $t("Instances you follow") }}

+
+
-
- +
+
-

{{ $t("Last published event") }}

-

{{ dashboard.lastPublicEventPublished.title }}

-
- -
+ +

{{ $t("Last published event") }}

+

{{ dashboard.lastPublicEventPublished.title }}

+
+ +
+
- +
+
+
+ +

{{ $t("Last group created") }}

+

+ {{ + dashboard.lastGroupCreated.name || + dashboard.lastGroupCreated.preferredUsername + }} +

+
+ +
+
+
+
@@ -65,6 +114,7 @@ import { Component, Vue } from "vue-property-decorator"; import { DASHBOARD } from "@/graphql/admin"; import { IDashboard } from "@/types/admin.model"; +import { usernameWithDomain } from "@/types/actor"; import RouteName from "../../router/name"; @Component({ @@ -85,6 +135,8 @@ export default class Dashboard extends Vue { dashboard!: IDashboard; RouteName = RouteName; + + usernameWithDomain = usernameWithDomain; } diff --git a/js/src/views/Group/GroupSettings.vue b/js/src/views/Group/GroupSettings.vue index 223d29ed..e57ad2a1 100644 --- a/js/src/views/Group/GroupSettings.vue +++ b/js/src/views/Group/GroupSettings.vue @@ -114,7 +114,7 @@ - + {{ $t("You are not an administrator for this group.") }} diff --git a/js/src/views/Home.vue b/js/src/views/Home.vue index f8689a8e..e2731630 100644 --- a/js/src/views/Home.vue +++ b/js/src/views/Home.vue @@ -34,7 +34,7 @@