Migrate to Vue 3 and Vite

Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
Thomas Citharel
2022-07-12 10:55:28 +02:00
parent 8f4099ee33
commit ee20e03cc2
464 changed files with 31515 additions and 32758 deletions

View File

@@ -0,0 +1,32 @@
import { IActivity } from "@/types/activity.model";
import { IMember } from "@/types/actor/member.model";
import { useCurrentActorClient } from "./apollo/actor";
export function useIsActivityAuthorCurrentActor() {
const { currentActor } = useCurrentActorClient();
return (activity: IActivity): boolean => {
return (
activity.author.id === currentActor.value?.id &&
currentActor.value?.id !== undefined
);
};
}
export function useIsActivityObjectCurrentActor() {
const { currentActor } = useCurrentActorClient();
return (activity: IActivity): boolean =>
(activity?.object as IMember)?.actor?.id === currentActor.value?.id &&
currentActor.value?.id !== undefined;
}
export function useActivitySubjectParams() {
return (activity: IActivity) =>
activity.subjectParams.reduce(
(acc: Record<string, string>, { key, value }) => {
acc[key] = value;
return acc;
},
{}
);
}

View File

@@ -0,0 +1,68 @@
import {
CURRENT_ACTOR_CLIENT,
GROUP_MEMBERSHIP_SUBSCRIPTION_CHANGED,
IDENTITIES,
PERSON_STATUS_GROUP,
} from "@/graphql/actor";
import { IGroup, IPerson, usernameWithDomain } from "@/types/actor";
import { useQuery } from "@vue/apollo-composable";
import { group } from "console";
import { computed, ref, Ref, unref } from "vue";
import { useCurrentUserClient } from "./user";
export function useCurrentActorClient() {
const {
result: currentActorResult,
error,
loading,
} = useQuery<{ currentActor: IPerson }>(CURRENT_ACTOR_CLIENT);
const currentActor = computed<IPerson | undefined>(
() => currentActorResult.value?.currentActor
);
return { currentActor, error, loading };
}
export function useCurrentUserIdentities() {
const { currentUser } = useCurrentUserClient();
const { result, error, loading } = useQuery<{ identities: IPerson[] }>(
IDENTITIES,
{},
() => ({
enabled: currentUser.value?.isLoggedIn === true,
})
);
const identities = computed(() => result.value?.identities);
return { identities, error, loading };
}
export function usePersonStatusGroup(
groupFederatedUsername: string | undefined | Ref<string | undefined>
) {
const { currentActor } = useCurrentActorClient();
const { result, error, loading, subscribeToMore } = useQuery<{
person: IPerson;
}>(
PERSON_STATUS_GROUP,
() => ({
id: currentActor.value?.id,
group: unref(groupFederatedUsername),
}),
() => ({
enabled:
currentActor.value?.id !== undefined &&
unref(groupFederatedUsername) !== undefined &&
unref(groupFederatedUsername) !== "",
})
);
subscribeToMore(() => ({
document: GROUP_MEMBERSHIP_SUBSCRIPTION_CHANGED,
variables: {
id: currentActor.value?.id,
group: unref(groupFederatedUsername),
},
}));
const person = computed(() => result.value?.person);
return { person, error, loading };
}

View File

@@ -0,0 +1,16 @@
import { REVERSE_GEOCODE } from "@/graphql/address";
import { useLazyQuery } from "@vue/apollo-composable";
import { IAddress } from "@/types/address.model";
type reverseGeoCodeType = {
latitude: number;
longitude: number;
zoom: number;
locale: string;
};
export function useReverseGeocode() {
return useLazyQuery<{ reverseGeocode: IAddress[] }, reverseGeoCodeType>(
REVERSE_GEOCODE
);
}

View File

@@ -0,0 +1,194 @@
import {
ABOUT,
ANALYTICS,
ANONYMOUS_ACTOR_ID,
ANONYMOUS_PARTICIPATION_CONFIG,
ANONYMOUS_REPORTS_CONFIG,
DEMO_MODE,
EVENT_CATEGORIES,
EVENT_PARTICIPANTS,
FEATURES,
GEOCODING_AUTOCOMPLETE,
LOCATION,
MAPS_TILES,
RESOURCE_PROVIDERS,
RESTRICTIONS,
TIMEZONES,
UPLOAD_LIMITS,
} from "@/graphql/config";
import { IAnonymousParticipationConfig, IConfig } from "@/types/config.model";
import { ApolloError } from "@apollo/client/core";
import { useQuery } from "@vue/apollo-composable";
import { computed, ref } from "vue";
export function useTimezones() {
const {
result: timezoneResult,
error,
loading,
} = useQuery<{
config: Pick<IConfig, "timezones">;
}>(TIMEZONES);
const timezones = computed(() => timezoneResult.value?.config?.timezones);
return { timezones, error, loading };
}
export function useAnonymousParticipationConfig() {
const anonymousParticipationConfig = ref<
IAnonymousParticipationConfig | undefined
>(undefined);
const error = ref<ApolloError | null>(null);
if (!anonymousParticipationConfig.value) {
const { onError, onResult } = useQuery<{
config: Pick<IConfig, "anonymous">;
}>(ANONYMOUS_PARTICIPATION_CONFIG);
onResult(({ data }) => {
anonymousParticipationConfig.value =
data.config?.anonymous?.participation;
});
onError((err) => (error.value = err));
}
return { anonymousParticipationConfig, error };
}
export function useAnonymousReportsConfig() {
const {
result: configResult,
error,
loading,
} = useQuery<{
config: Pick<IConfig, "anonymous">;
}>(ANONYMOUS_REPORTS_CONFIG);
const anonymousReportsConfig = computed(
() => configResult.value?.config?.anonymous?.participation
);
return { anonymousReportsConfig, error, loading };
}
export function useInstanceName() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "name">;
}>(ABOUT);
const instanceName = computed(() => result.value?.config?.name);
return { instanceName, error, loading };
}
export function useAnonymousActorId() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "anonymous">;
}>(ANONYMOUS_ACTOR_ID);
const anonymousActorId = computed(
() => result.value?.config?.anonymous?.actorId
);
return { anonymousActorId, error, loading };
}
export function useUploadLimits() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "uploadLimits">;
}>(UPLOAD_LIMITS);
const uploadLimits = computed(() => result.value?.config?.uploadLimits);
return { uploadLimits, error, loading };
}
export function useEventCategories() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "eventCategories">;
}>(EVENT_CATEGORIES);
const eventCategories = computed(() => result.value?.config.eventCategories);
return { eventCategories, error, loading };
}
export function useRestrictions() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "restrictions">;
}>(RESTRICTIONS);
const restrictions = computed(() => result.value?.config.restrictions);
return { restrictions, error, loading };
}
export function useExportFormats() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "exportFormats">;
}>(EVENT_PARTICIPANTS);
const exportFormats = computed(() => result.value?.config?.exportFormats);
return { exportFormats, error, loading };
}
export function useGeocodingAutocomplete() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "geocoding">;
}>(GEOCODING_AUTOCOMPLETE);
const geocodingAutocomplete = computed(
() => result.value?.config?.geocoding?.autocomplete
);
return { geocodingAutocomplete, error, loading };
}
export function useMapTiles() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "maps">;
}>(MAPS_TILES);
const tiles = computed(() => result.value?.config.maps.tiles);
return { tiles, error, loading };
}
export function useFeatures() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "features">;
}>(FEATURES);
const features = computed(() => result.value?.config.features);
return { features, error, loading };
}
export function useResourceProviders() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "resourceProviders">;
}>(RESOURCE_PROVIDERS);
const resourceProviders = computed(
() => result.value?.config.resourceProviders
);
return { resourceProviders, error, loading };
}
export function useServerProvidedLocation() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "location">;
}>(LOCATION);
const location = computed(() => result.value?.config.location);
return { location, error, loading };
}
export function useIsDemoMode() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "demoMode">;
}>(DEMO_MODE);
const isDemoMode = computed(() => result.value?.config.demoMode);
return { isDemoMode, error, loading };
}
export function useAnalytics() {
const { result, error, loading } = useQuery<{
config: Pick<IConfig, "analytics">;
}>(ANALYTICS);
const analytics = computed(() => result.value?.config.analytics);
return { analytics, error, loading };
}

View File

@@ -0,0 +1,51 @@
import { DELETE_EVENT, FETCH_EVENT, FETCH_EVENT_BASIC } from "@/graphql/event";
import { IEvent } from "@/types/event.model";
import { useMutation, useQuery } from "@vue/apollo-composable";
import { computed } from "vue";
export function useFetchEvent(uuid?: string) {
const {
result: fetchEventResult,
loading,
error,
onError,
onResult,
} = useQuery<{ event: IEvent }>(
FETCH_EVENT,
{
uuid,
},
() => ({
enabled: uuid !== undefined,
})
);
const event = computed(() => fetchEventResult.value?.event);
return { event, loading, error, onError, onResult };
}
export function useFetchEventBasic(uuid: string) {
const {
result: fetchEventResult,
loading,
error,
onResult,
onError,
} = useQuery<{ event: IEvent }>(FETCH_EVENT_BASIC, {
uuid,
});
const event = computed(() => fetchEventResult.value?.event);
return { event, loading, error, onResult, onError };
}
export function useDeleteEvent() {
return useMutation<{ id: string }, { eventId: string }>(DELETE_EVENT, () => ({
update(cache, { data }) {
cache.evict({ id: `Event:${data?.id}` });
cache.gc();
},
}));
}

View File

@@ -0,0 +1,113 @@
import { PERSON_MEMBERSHIPS } from "@/graphql/actor";
import {
CREATE_GROUP,
DELETE_GROUP,
FETCH_GROUP,
LEAVE_GROUP,
UPDATE_GROUP,
} from "@/graphql/group";
import { IGroup, IPerson } from "@/types/actor";
import { MemberRole } from "@/types/enums";
import { IMediaUploadWrapper } from "@/types/media.model";
import { ApolloCache, FetchResult, InMemoryCache } from "@apollo/client/core";
import { useMutation, useQuery } from "@vue/apollo-composable";
import { computed } from "vue";
import { useCurrentActorClient } from "./actor";
type useGroupOptions = {
beforeDateTime?: string | Date;
afterDateTime?: string | Date;
organisedEventsPage?: number;
organisedEventsLimit?: number;
postsPage?: number;
postsLimit?: number;
membersPage?: number;
membersLimit?: number;
discussionsPage?: number;
discussionsLimit?: number;
};
export function useGroup(
name: string | undefined,
options: useGroupOptions = {}
) {
console.debug("using group with", name);
const { result, error, loading, onError, refetch } = useQuery<
{
group: IGroup;
},
{
name: string;
beforeDateTime?: string | Date;
afterDateTime?: string | Date;
organisedEventsPage?: number;
organisedEventsLimit?: number;
postsPage?: number;
postsLimit?: number;
membersPage?: number;
membersLimit?: number;
discussionsPage?: number;
discussionsLimit?: number;
}
>(
FETCH_GROUP,
{
name: "hello",
...options,
},
{ enabled: name !== undefined }
);
const group = computed(() => result.value?.group);
return { group, error, loading, onError, refetch };
}
export function useCreateGroup(variables: {
preferredUsername: string;
name: string;
summary?: string;
avatar?: IMediaUploadWrapper;
banner?: IMediaUploadWrapper;
}) {
const { currentActor } = useCurrentActorClient();
return useMutation(CREATE_GROUP, () => ({
variables,
update: (store: ApolloCache<InMemoryCache>, { data }: FetchResult) => {
const query = {
query: PERSON_MEMBERSHIPS,
variables: {
id: currentActor.value?.id,
},
};
const membershipData = store.readQuery<{ person: IPerson }>(query);
if (!membershipData) return;
if (!currentActor.value) return;
const { person } = membershipData;
person.memberships.elements.push({
parent: data?.createGroup,
role: MemberRole.ADMINISTRATOR,
actor: currentActor.value,
insertedAt: new Date().toString(),
updatedAt: new Date().toString(),
});
store.writeQuery({ ...query, data: { person } });
},
}));
}
export function useUpdateGroup(variables: any) {
return useMutation<{ updateGroup: IGroup }>(UPDATE_GROUP, () => ({
variables,
}));
}
export function useDeleteGroup(variables: { groupId: string }) {
return useMutation<{ deleteGroup: IGroup }>(DELETE_GROUP, () => ({
variables,
}));
}
export function useLeaveGroup() {
return useMutation<{ leaveGroup: { id: string } }>(LEAVE_GROUP);
}

View File

@@ -0,0 +1,15 @@
import { CREATE_REPORT } from "@/graphql/report";
import { useMutation } from "@vue/apollo-composable";
export function useCreateReport() {
return useMutation<
{ createReport: { id: string } },
{
eventId?: string;
reportedId: string;
content?: string;
commentsIds?: string[];
forward?: boolean;
}
>(CREATE_REPORT);
}

View File

@@ -0,0 +1,18 @@
import { FILTER_TAGS } from "@/graphql/tags";
import { ITag } from "@/types/tag.model";
import { apolloClient } from "@/vue-apollo";
import { provideApolloClient, useQuery } from "@vue/apollo-composable";
export function fetchTags(text: string): Promise<ITag[]> {
return new Promise((resolve, reject) => {
const { onResult, onError } = provideApolloClient(apolloClient)(() =>
useQuery<{ tags: ITag[] }, { filter: string }>(FILTER_TAGS, {
filter: text,
})
);
onResult(({ data }) => resolve(data.tags));
onError((error) => reject(error));
});
}

View File

@@ -0,0 +1,114 @@
import { IDENTITIES, REGISTER_PERSON } from "@/graphql/actor";
import {
CURRENT_USER_CLIENT,
LOGGED_USER,
SET_USER_SETTINGS,
UPDATE_USER_LOCALE,
USER_SETTINGS,
} from "@/graphql/user";
import { IPerson } from "@/types/actor";
import { ICurrentUser, IUser } from "@/types/current-user.model";
import { ActorType } from "@/types/enums";
import { ApolloCache, FetchResult } from "@apollo/client/core";
import { useMutation, useQuery } from "@vue/apollo-composable";
import { computed } from "vue";
export function useCurrentUserClient() {
const {
result: currentUserResult,
error,
loading,
} = useQuery<{
currentUser: ICurrentUser;
}>(CURRENT_USER_CLIENT);
const currentUser = computed(() => currentUserResult.value?.currentUser);
return { currentUser, error, loading };
}
export function useLoggedUser() {
const { currentUser } = useCurrentUserClient();
const { result, error, onError } = useQuery<{ loggedUser: IUser }>(
LOGGED_USER,
{},
() => ({ enabled: currentUser.value?.id != null })
);
const loggedUser = computed(() => result.value?.loggedUser);
return { loggedUser, error, onError };
}
export function useUserSettings() {
const {
result: userSettingsResult,
error,
loading,
} = useQuery<{ loggedUser: IUser }>(USER_SETTINGS);
const loggedUser = computed(() => userSettingsResult.value?.loggedUser);
return { loggedUser, error, loading };
}
export async function doUpdateSetting(
variables: Record<string, unknown>
): Promise<void> {
useMutation<{ setUserSettings: string }>(SET_USER_SETTINGS, () => ({
variables,
}));
}
export async function updateLocale(locale: string) {
useMutation<{ id: string; locale: string }>(UPDATE_USER_LOCALE, () => ({
variables: {
locale,
},
}));
}
export function registerAccount(
variables: {
preferredUsername: string;
name: string;
summary: string;
email: string;
},
userAlreadyActivated: boolean
) {
return useMutation<
{ registerPerson: IPerson },
{
preferredUsername: string;
name: string;
summary: string;
email: string;
}
>(REGISTER_PERSON, () => ({
variables,
update: (
store: ApolloCache<{ registerPerson: IPerson }>,
{ data: localData }: FetchResult
) => {
if (userAlreadyActivated) {
const identitiesData = store.readQuery<{ identities: IPerson[] }>({
query: IDENTITIES,
});
if (identitiesData && localData) {
const newPersonData = {
...localData.registerPerson,
type: ActorType.PERSON,
};
store.writeQuery({
query: IDENTITIES,
data: {
...identitiesData,
identities: [...identitiesData.identities, newPersonData],
},
});
}
}
},
}));
}

View File

@@ -0,0 +1,23 @@
import { computed } from "vue";
import { useExportFormats, useUploadLimits } from "./apollo/config";
export const useHost = (): string => {
return window.location.hostname;
};
export const useAvatarMaxSize = (): number | undefined => {
const { uploadLimits } = useUploadLimits();
return uploadLimits.value?.avatar;
};
export const useBannerMaxSize = (): number | undefined => {
const { uploadLimits } = useUploadLimits();
return uploadLimits.value?.banner;
};
export const useParticipantsExportFormats = () => {
const { exportFormats } = useExportFormats();
return exportFormats.value?.eventParticipants;
};

View File