mirror of
https://framagit.org/framasoft/mobilizon.git
synced 2024-12-21 23:44:30 +00:00
Tried using front end to translate push notifications, not a good idea
Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
parent
bdae03fc52
commit
4a53e7518a
16 changed files with 523 additions and 290 deletions
|
@ -55,6 +55,7 @@ import RouteName from "../../router/name";
|
|||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
import { mixins } from "vue-class-component";
|
||||
import { convertActivity } from "@/services/activity-converter";
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
|
@ -67,35 +68,9 @@ export default class DiscussionActivityItem extends mixins(ActivityMixin) {
|
|||
ActivityDiscussionSubject = ActivityDiscussionSubject;
|
||||
|
||||
get translation(): string | undefined {
|
||||
switch (this.activity.subject) {
|
||||
case ActivityDiscussionSubject.DISCUSSION_CREATED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You created the discussion {discussion}.";
|
||||
}
|
||||
return "{profile} created the discussion {discussion}.";
|
||||
case ActivityDiscussionSubject.DISCUSSION_REPLIED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You replied to the discussion {discussion}.";
|
||||
}
|
||||
return "{profile} replied to the discussion {discussion}.";
|
||||
case ActivityDiscussionSubject.DISCUSSION_RENAMED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You renamed the discussion from {old_discussion} to {discussion}.";
|
||||
}
|
||||
return "{profile} renamed the discussion from {old_discussion} to {discussion}.";
|
||||
case ActivityDiscussionSubject.DISCUSSION_ARCHIVED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You archived the discussion {discussion}.";
|
||||
}
|
||||
return "{profile} archived the discussion {discussion}.";
|
||||
case ActivityDiscussionSubject.DISCUSSION_DELETED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You deleted the discussion {discussion}.";
|
||||
}
|
||||
return "{profile} deleted the discussion {discussion}.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
return convertActivity(this.activity, {
|
||||
isAuthorCurrentActor: this.isAuthorCurrentActor,
|
||||
});
|
||||
}
|
||||
|
||||
get iconColor(): string | undefined {
|
||||
|
|
|
@ -44,6 +44,7 @@ import { Component } from "vue-property-decorator";
|
|||
import RouteName from "../../router/name";
|
||||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
import { convertActivity } from "@/services/activity-converter";
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
|
@ -56,36 +57,9 @@ export default class EventActivityItem extends mixins(ActivityMixin) {
|
|||
RouteName = RouteName;
|
||||
|
||||
get translation(): string | undefined {
|
||||
switch (this.activity.subject) {
|
||||
case ActivityEventSubject.EVENT_CREATED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You created the event {event}.";
|
||||
}
|
||||
return "The event {event} was created by {profile}.";
|
||||
case ActivityEventSubject.EVENT_UPDATED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You updated the event {event}.";
|
||||
}
|
||||
return "The event {event} was updated by {profile}.";
|
||||
case ActivityEventSubject.EVENT_DELETED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You deleted the event {event}.";
|
||||
}
|
||||
return "The event {event} was deleted by {profile}.";
|
||||
case ActivityEventCommentSubject.COMMENT_POSTED:
|
||||
if (this.subjectParams.comment_reply_to) {
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You replied to a comment on the event {event}.";
|
||||
}
|
||||
return "{profile} replied to a comment on the event {event}.";
|
||||
}
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You posted a comment on the event {event}.";
|
||||
}
|
||||
return "{profile} posted a comment on the event {event}.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
return convertActivity(this.activity, {
|
||||
isAuthorCurrentActor: this.isAuthorCurrentActor,
|
||||
});
|
||||
}
|
||||
|
||||
get iconColor(): string | undefined {
|
||||
|
|
|
@ -77,6 +77,7 @@ import RouteName from "../../router/name";
|
|||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
import { mixins } from "vue-class-component";
|
||||
import { convertActivity } from "@/services/activity-converter";
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
|
@ -89,20 +90,9 @@ export default class GroupActivityItem extends mixins(ActivityMixin) {
|
|||
ActivityGroupSubject = ActivityGroupSubject;
|
||||
|
||||
get translation(): string | undefined {
|
||||
switch (this.activity.subject) {
|
||||
case ActivityGroupSubject.GROUP_CREATED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You created the group {group}.";
|
||||
}
|
||||
return "{profile} created the group {group}.";
|
||||
case ActivityGroupSubject.GROUP_UPDATED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You updated the group {group}.";
|
||||
}
|
||||
return "{profile} updated the group {group}.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
return convertActivity(this.activity, {
|
||||
isAuthorCurrentActor: this.isAuthorCurrentActor,
|
||||
});
|
||||
}
|
||||
|
||||
get iconColor(): string | undefined {
|
||||
|
|
|
@ -42,19 +42,13 @@
|
|||
</template>
|
||||
<script lang="ts">
|
||||
import { usernameWithDomain } from "@/types/actor";
|
||||
import { ActivityMemberSubject, MemberRole } from "@/types/enums";
|
||||
import { ActivityMemberSubject } from "@/types/enums";
|
||||
import { Component } from "vue-property-decorator";
|
||||
import RouteName from "../../router/name";
|
||||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
import { mixins } from "vue-class-component";
|
||||
|
||||
export const MEMBER_ROLE_VALUE: Record<string, number> = {
|
||||
[MemberRole.MEMBER]: 20,
|
||||
[MemberRole.MODERATOR]: 50,
|
||||
[MemberRole.ADMINISTRATOR]: 90,
|
||||
[MemberRole.CREATOR]: 100,
|
||||
};
|
||||
import { convertActivity } from "@/services/activity-converter";
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
|
@ -67,49 +61,10 @@ export default class MemberActivityItem extends mixins(ActivityMixin) {
|
|||
ActivityMemberSubject = ActivityMemberSubject;
|
||||
|
||||
get translation(): string | undefined {
|
||||
switch (this.activity.subject) {
|
||||
case ActivityMemberSubject.MEMBER_REQUEST:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You requested to join the group.";
|
||||
}
|
||||
return "{member} requested to join the group.";
|
||||
case ActivityMemberSubject.MEMBER_INVITED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You invited {member}.";
|
||||
}
|
||||
return "{member} was invited by {profile}.";
|
||||
case ActivityMemberSubject.MEMBER_ADDED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You added the member {member}.";
|
||||
}
|
||||
return "{profile} added the member {member}.";
|
||||
case ActivityMemberSubject.MEMBER_JOINED:
|
||||
return "{member} joined the group.";
|
||||
case ActivityMemberSubject.MEMBER_UPDATED:
|
||||
if (this.subjectParams.member_role && this.subjectParams.old_role) {
|
||||
return this.roleUpdate;
|
||||
}
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You updated the member {member}.";
|
||||
}
|
||||
return "{profile} updated the member {member}.";
|
||||
case ActivityMemberSubject.MEMBER_REMOVED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You excluded member {member}.";
|
||||
}
|
||||
return "{profile} excluded member {member}.";
|
||||
case ActivityMemberSubject.MEMBER_QUIT:
|
||||
return "{profile} quit the group.";
|
||||
case ActivityMemberSubject.MEMBER_REJECTED_INVITATION:
|
||||
return "{member} rejected the invitation to join the group.";
|
||||
case ActivityMemberSubject.MEMBER_ACCEPTED_INVITATION:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You accepted the invitation to join the group.";
|
||||
}
|
||||
return "{member} accepted the invitation to join the group.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
return convertActivity(this.activity, {
|
||||
isAuthorCurrentActor: this.isAuthorCurrentActor,
|
||||
isObjectMemberCurrentActor: this.isObjectMemberCurrentActor,
|
||||
});
|
||||
}
|
||||
|
||||
get icon(): string {
|
||||
|
@ -149,77 +104,6 @@ export default class MemberActivityItem extends mixins(ActivityMixin) {
|
|||
}
|
||||
}
|
||||
|
||||
get roleUpdate(): string | undefined {
|
||||
if (
|
||||
Object.keys(MEMBER_ROLE_VALUE).includes(this.subjectParams.member_role) &&
|
||||
Object.keys(MEMBER_ROLE_VALUE).includes(this.subjectParams.old_role)
|
||||
) {
|
||||
if (
|
||||
MEMBER_ROLE_VALUE[this.subjectParams.member_role] >
|
||||
MEMBER_ROLE_VALUE[this.subjectParams.old_role]
|
||||
) {
|
||||
switch (this.subjectParams.member_role) {
|
||||
case MemberRole.MODERATOR:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You promoted {member} to moderator.";
|
||||
}
|
||||
if (this.isObjectMemberCurrentActor) {
|
||||
return "You were promoted to moderator by {profile}.";
|
||||
}
|
||||
return "{profile} promoted {member} to moderator.";
|
||||
case MemberRole.ADMINISTRATOR:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You promoted {member} to administrator.";
|
||||
}
|
||||
if (this.isObjectMemberCurrentActor) {
|
||||
return "You were promoted to administrator by {profile}.";
|
||||
}
|
||||
return "{profile} promoted {member} to administrator.";
|
||||
default:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You promoted the member {member} to an unknown role.";
|
||||
}
|
||||
if (this.isObjectMemberCurrentActor) {
|
||||
return "You were promoted to an unknown role by {profile}.";
|
||||
}
|
||||
return "{profile} promoted {member} to an unknown role.";
|
||||
}
|
||||
} else {
|
||||
switch (this.subjectParams.member_role) {
|
||||
case MemberRole.MODERATOR:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You demoted {member} to moderator.";
|
||||
}
|
||||
if (this.isObjectMemberCurrentActor) {
|
||||
return "You were demoted to moderator by {profile}.";
|
||||
}
|
||||
return "{profile} demoted {member} to moderator.";
|
||||
case MemberRole.MEMBER:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You demoted {member} to simple member.";
|
||||
}
|
||||
if (this.isObjectMemberCurrentActor) {
|
||||
return "You were demoted to simple member by {profile}.";
|
||||
}
|
||||
return "{profile} demoted {member} to simple member.";
|
||||
default:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You demoted the member {member} to an unknown role.";
|
||||
}
|
||||
if (this.isObjectMemberCurrentActor) {
|
||||
return "You were demoted to an unknown role by {profile}.";
|
||||
}
|
||||
return "{profile} demoted {member} to an unknown role.";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You updated the member {member}.";
|
||||
}
|
||||
return "{profile} updated the member {member}";
|
||||
}
|
||||
}
|
||||
|
||||
get isObjectMemberCurrentActor(): boolean {
|
||||
return (
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
|
|
|
@ -41,6 +41,7 @@ import RouteName from "../../router/name";
|
|||
import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
||||
import ActivityMixin from "../../mixins/activity";
|
||||
import { mixins } from "vue-class-component";
|
||||
import { convertActivity } from "@/services/activity-converter";
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
|
@ -53,25 +54,9 @@ export default class PostActivityItem extends mixins(ActivityMixin) {
|
|||
ActivityPostSubject = ActivityPostSubject;
|
||||
|
||||
get translation(): string | undefined {
|
||||
switch (this.activity.subject) {
|
||||
case ActivityPostSubject.POST_CREATED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You created the post {post}.";
|
||||
}
|
||||
return "The post {post} was created by {profile}.";
|
||||
case ActivityPostSubject.POST_UPDATED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You updated the post {post}.";
|
||||
}
|
||||
return "The post {post} was updated by {profile}.";
|
||||
case ActivityPostSubject.POST_DELETED:
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You deleted the post {post}.";
|
||||
}
|
||||
return "The post {post} was deleted by {profile}.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
return convertActivity(this.activity, {
|
||||
isAuthorCurrentActor: this.isAuthorCurrentActor,
|
||||
});
|
||||
}
|
||||
|
||||
get iconColor(): string | undefined {
|
||||
|
|
|
@ -52,6 +52,7 @@ import PopoverActorCard from "../Account/PopoverActorCard.vue";
|
|||
import ActivityMixin from "../../mixins/activity";
|
||||
import { mixins } from "vue-class-component";
|
||||
import { Location } from "vue-router";
|
||||
import { convertActivity } from "@/services/activity-converter";
|
||||
|
||||
@Component({
|
||||
components: {
|
||||
|
@ -63,74 +64,10 @@ export default class ResourceActivityItem extends mixins(ActivityMixin) {
|
|||
RouteName = RouteName;
|
||||
|
||||
get translation(): string | undefined {
|
||||
switch (this.activity.subject) {
|
||||
case ActivityResourceSubject.RESOURCE_CREATED:
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
if (this.activity?.object?.type === "folder") {
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You created the folder {resource}.";
|
||||
}
|
||||
return "{profile} created the folder {resource}.";
|
||||
}
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You created the resource {resource}.";
|
||||
}
|
||||
return "{profile} created the resource {resource}.";
|
||||
case ActivityResourceSubject.RESOURCE_MOVED:
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
if (this.activity?.object?.type === "folder") {
|
||||
if (this.parentDirectory === null) {
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You moved the folder {resource} to the root folder.";
|
||||
}
|
||||
return "{profile} moved the folder {resource} to the root folder.";
|
||||
}
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You moved the folder {resource} into {new_path}.";
|
||||
}
|
||||
return "{profile} moved the folder {resource} into {new_path}.";
|
||||
}
|
||||
if (this.parentDirectory === null) {
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You moved the resource {resource} to the root folder.";
|
||||
}
|
||||
return "{profile} moved the resource {resource} to the root folder.";
|
||||
}
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You moved the resource {resource} into {new_path}.";
|
||||
}
|
||||
return "{profile} moved the resource {resource} into {new_path}.";
|
||||
case ActivityResourceSubject.RESOURCE_UPDATED:
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
if (this.activity?.object?.type === "folder") {
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You renamed the folder from {old_resource_title} to {resource}.";
|
||||
}
|
||||
return "{profile} renamed the folder from {old_resource_title} to {resource}.";
|
||||
}
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You renamed the resource from {old_resource_title} to {resource}.";
|
||||
}
|
||||
return "{profile} renamed the resource from {old_resource_title} to {resource}.";
|
||||
case ActivityResourceSubject.RESOURCE_DELETED:
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
if (this.activity?.object?.type === "folder") {
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You deleted the folder {resource}.";
|
||||
}
|
||||
return "{profile} deleted the folder {resource}.";
|
||||
}
|
||||
if (this.isAuthorCurrentActor) {
|
||||
return "You deleted the resource {resource}.";
|
||||
}
|
||||
return "{profile} deleted the resource {resource}.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
return convertActivity(this.activity, {
|
||||
isAuthorCurrentActor: this.isAuthorCurrentActor,
|
||||
parentDirectory: this.parentDirectory,
|
||||
});
|
||||
}
|
||||
|
||||
get iconColor(): string | undefined {
|
||||
|
|
|
@ -77,9 +77,14 @@ registerRoute(
|
|||
);
|
||||
|
||||
self.addEventListener("push", async (event: any) => {
|
||||
console.log("received push", event);
|
||||
const activity = event.data.json();
|
||||
console.log("received push", activity);
|
||||
|
||||
const template =
|
||||
convertActivity(activity) || "A push notification has been sent";
|
||||
|
||||
const options = {
|
||||
body: "Ceci est une notification envoyée par Mobilizon !",
|
||||
body: await translate(template),
|
||||
icon: "images/notification-flat.png",
|
||||
vibrate: [100, 50, 100],
|
||||
data: {
|
||||
|
@ -92,11 +97,6 @@ self.addEventListener("push", async (event: any) => {
|
|||
title: "Go to the site",
|
||||
icon: "images/checkmark.png",
|
||||
},
|
||||
{
|
||||
action: "close",
|
||||
title: "Close the notification",
|
||||
icon: "images/xmark.png",
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
@ -106,3 +106,69 @@ self.addEventListener("push", async (event: any) => {
|
|||
self.registration.showNotification("Push Notification", options)
|
||||
);
|
||||
});
|
||||
|
||||
async function translate(template: string): Promise<string> {
|
||||
const DEFAULT_LOCALE = "en_US";
|
||||
|
||||
let vueI18n = new VueI18n({
|
||||
locale: DEFAULT_LOCALE, // set locale
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
messages: en, // set locale messages
|
||||
fallbackLocale: DEFAULT_LOCALE,
|
||||
formatFallbackMessages: true,
|
||||
pluralizationRules,
|
||||
});
|
||||
|
||||
vueI18n = await loadLanguageAsync(vueI18n, getLocale());
|
||||
return vueI18n.t(template) as string;
|
||||
}
|
||||
|
||||
function getLocale(): string {
|
||||
const language = (
|
||||
(window.navigator as any).userLanguage || window.navigator.language
|
||||
).replace(/-/, "_");
|
||||
|
||||
return language && Object.prototype.hasOwnProperty.call(langs, language)
|
||||
? language
|
||||
: language.split("-")[0];
|
||||
}
|
||||
|
||||
export async function loadLanguageAsync(
|
||||
i18n: VueI18n,
|
||||
lang: string
|
||||
): Promise<VueI18n> {
|
||||
// If the same language
|
||||
if (i18n.locale === lang) {
|
||||
return Promise.resolve(setI18nLanguage(i18n, lang));
|
||||
}
|
||||
|
||||
// If the language hasn't been loaded yet
|
||||
const newMessages = await import(
|
||||
/* webpackChunkName: "lang-[request]" */ `@/i18n/${vueI18NfileForLanguage(
|
||||
lang
|
||||
)}.json`
|
||||
);
|
||||
i18n.setLocaleMessage(lang, newMessages.default);
|
||||
return setI18nLanguage(i18n, lang);
|
||||
}
|
||||
|
||||
function setI18nLanguage(i18n: VueI18n, lang: string): VueI18n {
|
||||
i18n.locale = lang;
|
||||
return i18n;
|
||||
}
|
||||
|
||||
function fileForLanguage(matches: Record<string, string>, lang: string) {
|
||||
if (Object.prototype.hasOwnProperty.call(matches, lang)) {
|
||||
return matches[lang];
|
||||
}
|
||||
return lang;
|
||||
}
|
||||
|
||||
function vueI18NfileForLanguage(lang: string) {
|
||||
const matches: Record<string, string> = {
|
||||
fr: "fr_FR",
|
||||
en: "en_US",
|
||||
};
|
||||
return fileForLanguage(matches, lang);
|
||||
}
|
||||
|
|
52
js/src/services/activity-converter.ts
Normal file
52
js/src/services/activity-converter.ts
Normal file
|
@ -0,0 +1,52 @@
|
|||
import { IActivity, IPatchedActivity } from "@/types/activity.model";
|
||||
import { IGroup } from "@/types/actor";
|
||||
import { IMember } from "@/types/actor/member.model";
|
||||
import { IDiscussion } from "@/types/discussions";
|
||||
import { ActivityType } from "@/types/enums";
|
||||
import { IEvent } from "@/types/event.model";
|
||||
import { IPost } from "@/types/post.model";
|
||||
import { IResource } from "@/types/resource";
|
||||
import { convertDiscussionActivity } from "./activity/discussion";
|
||||
import { convertEventActivity } from "./activity/event";
|
||||
import { convertGroupActivity } from "./activity/group";
|
||||
import { convertMemberActivity } from "./activity/member";
|
||||
import { convertPostActivity } from "./activity/post";
|
||||
import { convertResourceActivity } from "./activity/resource";
|
||||
import { convertActivityOptions, reduceSubjectParams } from "./activity/utils";
|
||||
|
||||
export function convertActivity(
|
||||
activity: IActivity,
|
||||
options: convertActivityOptions = {}
|
||||
): string | undefined {
|
||||
const converter = mapActivityTypeToFunction(activity.type);
|
||||
const patchedActivity = {
|
||||
...activity,
|
||||
subjectParams: reduceSubjectParams(activity),
|
||||
};
|
||||
return converter(patchedActivity, options);
|
||||
}
|
||||
|
||||
type activityConverter<T> = (
|
||||
activity: IPatchedActivity<T>,
|
||||
options: any
|
||||
) => string | undefined;
|
||||
|
||||
const mapActivityTypeToFunction = (
|
||||
activityType: string
|
||||
): activityConverter<any> => {
|
||||
switch (activityType) {
|
||||
case ActivityType.EVENT:
|
||||
return convertEventActivity as activityConverter<IEvent>;
|
||||
case ActivityType.POST:
|
||||
return convertPostActivity as activityConverter<IPost>;
|
||||
case ActivityType.MEMBER:
|
||||
return convertMemberActivity as activityConverter<IMember>;
|
||||
case ActivityType.RESOURCE:
|
||||
return convertResourceActivity as activityConverter<IResource>;
|
||||
case ActivityType.DISCUSSION:
|
||||
return convertDiscussionActivity as activityConverter<IDiscussion>;
|
||||
case ActivityType.GROUP:
|
||||
return convertGroupActivity as activityConverter<IGroup>;
|
||||
}
|
||||
return () => undefined;
|
||||
};
|
39
js/src/services/activity/discussion.ts
Normal file
39
js/src/services/activity/discussion.ts
Normal file
|
@ -0,0 +1,39 @@
|
|||
import { IPatchedActivity } from "@/types/activity.model";
|
||||
import { IDiscussion } from "@/types/discussions";
|
||||
import { ActivityDiscussionSubject } from "@/types/enums";
|
||||
import { convertActivityOptions } from "./utils";
|
||||
|
||||
export function convertDiscussionActivity(
|
||||
activity: IPatchedActivity<IDiscussion>,
|
||||
options: convertActivityOptions
|
||||
): string | undefined {
|
||||
switch (activity.subject) {
|
||||
case ActivityDiscussionSubject.DISCUSSION_CREATED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You created the discussion {discussion}.";
|
||||
}
|
||||
return "{profile} created the discussion {discussion}.";
|
||||
case ActivityDiscussionSubject.DISCUSSION_REPLIED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You replied to the discussion {discussion}.";
|
||||
}
|
||||
return "{profile} replied to the discussion {discussion}.";
|
||||
case ActivityDiscussionSubject.DISCUSSION_RENAMED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You renamed the discussion from {old_discussion} to {discussion}.";
|
||||
}
|
||||
return "{profile} renamed the discussion from {old_discussion} to {discussion}.";
|
||||
case ActivityDiscussionSubject.DISCUSSION_ARCHIVED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You archived the discussion {discussion}.";
|
||||
}
|
||||
return "{profile} archived the discussion {discussion}.";
|
||||
case ActivityDiscussionSubject.DISCUSSION_DELETED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You deleted the discussion {discussion}.";
|
||||
}
|
||||
return "{profile} deleted the discussion {discussion}.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
43
js/src/services/activity/event.ts
Normal file
43
js/src/services/activity/event.ts
Normal file
|
@ -0,0 +1,43 @@
|
|||
import { IPatchedActivity } from "@/types/activity.model";
|
||||
import {
|
||||
ActivityEventCommentSubject,
|
||||
ActivityEventSubject,
|
||||
} from "@/types/enums";
|
||||
import { IEvent } from "@/types/event.model";
|
||||
import { convertActivityOptions } from "./utils";
|
||||
|
||||
export function convertEventActivity(
|
||||
activity: IPatchedActivity<IEvent>,
|
||||
options: convertActivityOptions
|
||||
): string | undefined {
|
||||
switch (activity.subject) {
|
||||
case ActivityEventSubject.EVENT_CREATED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You created the event {event}.";
|
||||
}
|
||||
return "The event {event} was created by {profile}.";
|
||||
case ActivityEventSubject.EVENT_UPDATED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You updated the event {event}.";
|
||||
}
|
||||
return "The event {event} was updated by {profile}.";
|
||||
case ActivityEventSubject.EVENT_DELETED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You deleted the event {event}.";
|
||||
}
|
||||
return "The event {event} was deleted by {profile}.";
|
||||
case ActivityEventCommentSubject.COMMENT_POSTED:
|
||||
if (activity.subjectParams.comment_reply_to) {
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You replied to a comment on the event {event}.";
|
||||
}
|
||||
return "{profile} replied to a comment on the event {event}.";
|
||||
}
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You posted a comment on the event {event}.";
|
||||
}
|
||||
return "{profile} posted a comment on the event {event}.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
24
js/src/services/activity/group.ts
Normal file
24
js/src/services/activity/group.ts
Normal file
|
@ -0,0 +1,24 @@
|
|||
import { IPatchedActivity } from "@/types/activity.model";
|
||||
import { IGroup } from "@/types/actor";
|
||||
import { ActivityGroupSubject } from "@/types/enums";
|
||||
import { convertActivityOptions } from "./utils";
|
||||
|
||||
export function convertGroupActivity(
|
||||
activity: IPatchedActivity<IGroup>,
|
||||
options: convertActivityOptions
|
||||
): string | undefined {
|
||||
switch (activity.subject) {
|
||||
case ActivityGroupSubject.GROUP_CREATED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You created the group {group}.";
|
||||
}
|
||||
return "{profile} created the group {group}.";
|
||||
case ActivityGroupSubject.GROUP_UPDATED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You updated the group {group}.";
|
||||
}
|
||||
return "{profile} updated the group {group}.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
139
js/src/services/activity/member.ts
Normal file
139
js/src/services/activity/member.ts
Normal file
|
@ -0,0 +1,139 @@
|
|||
import { IPatchedActivity } from "@/types/activity.model";
|
||||
import { IMember } from "@/types/actor/member.model";
|
||||
import { ActivityMemberSubject, MemberRole } from "@/types/enums";
|
||||
import { convertActivityOptions } from "./utils";
|
||||
|
||||
export function convertMemberActivity(
|
||||
activity: IPatchedActivity<IMember>,
|
||||
options: convertActivityOptions
|
||||
): string | undefined {
|
||||
switch (activity.subject) {
|
||||
case ActivityMemberSubject.MEMBER_REQUEST:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You requested to join the group.";
|
||||
}
|
||||
return "{member} requested to join the group.";
|
||||
case ActivityMemberSubject.MEMBER_INVITED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You invited {member}.";
|
||||
}
|
||||
return "{member} was invited by {profile}.";
|
||||
case ActivityMemberSubject.MEMBER_ADDED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You added the member {member}.";
|
||||
}
|
||||
return "{profile} added the member {member}.";
|
||||
case ActivityMemberSubject.MEMBER_JOINED:
|
||||
return "{member} joined the group.";
|
||||
case ActivityMemberSubject.MEMBER_UPDATED:
|
||||
if (
|
||||
activity.subjectParams.member_role &&
|
||||
activity.subjectParams.old_role
|
||||
) {
|
||||
return roleUpdate(activity, options);
|
||||
}
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You updated the member {member}.";
|
||||
}
|
||||
return "{profile} updated the member {member}.";
|
||||
case ActivityMemberSubject.MEMBER_REMOVED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You excluded member {member}.";
|
||||
}
|
||||
return "{profile} excluded member {member}.";
|
||||
case ActivityMemberSubject.MEMBER_QUIT:
|
||||
return "{profile} quit the group.";
|
||||
case ActivityMemberSubject.MEMBER_REJECTED_INVITATION:
|
||||
return "{member} rejected the invitation to join the group.";
|
||||
case ActivityMemberSubject.MEMBER_ACCEPTED_INVITATION:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You accepted the invitation to join the group.";
|
||||
}
|
||||
return "{member} accepted the invitation to join the group.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const MEMBER_ROLE_VALUE: Record<string, number> = {
|
||||
[MemberRole.MEMBER]: 20,
|
||||
[MemberRole.MODERATOR]: 50,
|
||||
[MemberRole.ADMINISTRATOR]: 90,
|
||||
[MemberRole.CREATOR]: 100,
|
||||
};
|
||||
|
||||
function roleUpdate(
|
||||
activity: IPatchedActivity<IMember>,
|
||||
options: convertActivityOptions
|
||||
): string | undefined {
|
||||
if (
|
||||
Object.keys(MEMBER_ROLE_VALUE).includes(
|
||||
activity.subjectParams.member_role
|
||||
) &&
|
||||
Object.keys(MEMBER_ROLE_VALUE).includes(activity.subjectParams.old_role)
|
||||
) {
|
||||
if (
|
||||
MEMBER_ROLE_VALUE[activity.subjectParams.member_role] >
|
||||
MEMBER_ROLE_VALUE[activity.subjectParams.old_role]
|
||||
) {
|
||||
switch (activity.subjectParams.member_role) {
|
||||
case MemberRole.MODERATOR:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You promoted {member} to moderator.";
|
||||
}
|
||||
if (options.isObjectMemberCurrentActor) {
|
||||
return "You were promoted to moderator by {profile}.";
|
||||
}
|
||||
return "{profile} promoted {member} to moderator.";
|
||||
case MemberRole.ADMINISTRATOR:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You promoted {member} to administrator.";
|
||||
}
|
||||
if (options.isObjectMemberCurrentActor) {
|
||||
return "You were promoted to administrator by {profile}.";
|
||||
}
|
||||
return "{profile} promoted {member} to administrator.";
|
||||
default:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You promoted the member {member} to an unknown role.";
|
||||
}
|
||||
if (options.isObjectMemberCurrentActor) {
|
||||
return "You were promoted to an unknown role by {profile}.";
|
||||
}
|
||||
return "{profile} promoted {member} to an unknown role.";
|
||||
}
|
||||
} else {
|
||||
switch (activity.subjectParams.member_role) {
|
||||
case MemberRole.MODERATOR:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You demoted {member} to moderator.";
|
||||
}
|
||||
if (options.isObjectMemberCurrentActor) {
|
||||
return "You were demoted to moderator by {profile}.";
|
||||
}
|
||||
return "{profile} demoted {member} to moderator.";
|
||||
case MemberRole.MEMBER:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You demoted {member} to simple member.";
|
||||
}
|
||||
if (options.isObjectMemberCurrentActor) {
|
||||
return "You were demoted to simple member by {profile}.";
|
||||
}
|
||||
return "{profile} demoted {member} to simple member.";
|
||||
default:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You demoted the member {member} to an unknown role.";
|
||||
}
|
||||
if (options.isObjectMemberCurrentActor) {
|
||||
return "You were demoted to an unknown role by {profile}.";
|
||||
}
|
||||
return "{profile} demoted {member} to an unknown role.";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You updated the member {member}.";
|
||||
}
|
||||
return "{profile} updated the member {member}";
|
||||
}
|
||||
}
|
29
js/src/services/activity/post.ts
Normal file
29
js/src/services/activity/post.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { IPatchedActivity } from "@/types/activity.model";
|
||||
import { ActivityPostSubject } from "@/types/enums";
|
||||
import { IPost } from "@/types/post.model";
|
||||
import { convertActivityOptions } from "./utils";
|
||||
|
||||
export function convertPostActivity(
|
||||
activity: IPatchedActivity<IPost>,
|
||||
options: convertActivityOptions
|
||||
): string | undefined {
|
||||
switch (activity.subject) {
|
||||
case ActivityPostSubject.POST_CREATED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You created the post {post}.";
|
||||
}
|
||||
return "The post {post} was created by {profile}.";
|
||||
case ActivityPostSubject.POST_UPDATED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You updated the post {post}.";
|
||||
}
|
||||
return "The post {post} was updated by {profile}.";
|
||||
case ActivityPostSubject.POST_DELETED:
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You deleted the post {post}.";
|
||||
}
|
||||
return "The post {post} was deleted by {profile}.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
70
js/src/services/activity/resource.ts
Normal file
70
js/src/services/activity/resource.ts
Normal file
|
@ -0,0 +1,70 @@
|
|||
import { IPatchedActivity } from "@/types/activity.model";
|
||||
import { ActivityResourceSubject } from "@/types/enums";
|
||||
import { IResource } from "@/types/resource";
|
||||
import { convertActivityOptions } from "./utils";
|
||||
|
||||
export function convertResourceActivity(
|
||||
activity: IPatchedActivity<IResource>,
|
||||
options: convertActivityOptions
|
||||
): string | undefined {
|
||||
switch (activity.subject) {
|
||||
case ActivityResourceSubject.RESOURCE_CREATED:
|
||||
if (activity?.object?.type === "folder") {
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You created the folder {resource}.";
|
||||
}
|
||||
return "{profile} created the folder {resource}.";
|
||||
}
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You created the resource {resource}.";
|
||||
}
|
||||
return "{profile} created the resource {resource}.";
|
||||
case ActivityResourceSubject.RESOURCE_MOVED:
|
||||
if (activity?.object?.type === "folder") {
|
||||
if (options.parentDirectory === null) {
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You moved the folder {resource} to the root folder.";
|
||||
}
|
||||
return "{profile} moved the folder {resource} to the root folder.";
|
||||
}
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You moved the folder {resource} into {new_path}.";
|
||||
}
|
||||
return "{profile} moved the folder {resource} into {new_path}.";
|
||||
}
|
||||
if (options.parentDirectory === null) {
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You moved the resource {resource} to the root folder.";
|
||||
}
|
||||
return "{profile} moved the resource {resource} to the root folder.";
|
||||
}
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You moved the resource {resource} into {new_path}.";
|
||||
}
|
||||
return "{profile} moved the resource {resource} into {new_path}.";
|
||||
case ActivityResourceSubject.RESOURCE_UPDATED:
|
||||
if (activity?.object?.type === "folder") {
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You renamed the folder from {old_resource_title} to {resource}.";
|
||||
}
|
||||
return "{profile} renamed the folder from {old_resource_title} to {resource}.";
|
||||
}
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You renamed the resource from {old_resource_title} to {resource}.";
|
||||
}
|
||||
return "{profile} renamed the resource from {old_resource_title} to {resource}.";
|
||||
case ActivityResourceSubject.RESOURCE_DELETED:
|
||||
if (activity?.object?.type === "folder") {
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You deleted the folder {resource}.";
|
||||
}
|
||||
return "{profile} deleted the folder {resource}.";
|
||||
}
|
||||
if (options.isAuthorCurrentActor) {
|
||||
return "You deleted the resource {resource}.";
|
||||
}
|
||||
return "{profile} deleted the resource {resource}.";
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}
|
19
js/src/services/activity/utils.ts
Normal file
19
js/src/services/activity/utils.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
import { IActivity } from "@/types/activity.model";
|
||||
|
||||
export function reduceSubjectParams(
|
||||
activity: IActivity
|
||||
): Record<string, string> {
|
||||
return activity.subjectParams.reduce(
|
||||
(acc: Record<string, string>, { key, value }) => {
|
||||
acc[key] = value;
|
||||
return acc;
|
||||
},
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
export type convertActivityOptions = {
|
||||
isAuthorCurrentActor?: boolean;
|
||||
isObjectMemberCurrentActor?: boolean;
|
||||
parentDirectory?: string | undefined | null;
|
||||
};
|
|
@ -23,6 +23,7 @@ export type ActivitySubject =
|
|||
| ActivityGroupSubject
|
||||
| ActivityEventCommentSubject;
|
||||
|
||||
export type IActivityObject = IEvent | IPost | IGroup | IMember | IResource;
|
||||
export interface IActivity {
|
||||
id: string;
|
||||
type: ActivityType;
|
||||
|
@ -30,6 +31,12 @@ export interface IActivity {
|
|||
subjectParams: { key: string; value: string }[];
|
||||
author: IActor;
|
||||
group: IGroup;
|
||||
object: IEvent | IPost | IGroup | IMember | IResource;
|
||||
object: IActivityObject;
|
||||
insertedAt: string;
|
||||
}
|
||||
|
||||
export interface IPatchedActivity<T>
|
||||
extends Omit<IActivity, "subjectParams" | "object"> {
|
||||
subjectParams: Record<string, string>;
|
||||
object: T;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue