update frontend lib : remove histoire (obselete) + update vitest - #1815

This commit is contained in:
Laurent GAY
2025-10-24 13:00:15 +02:00
committed by setop
parent ffa3e0ebd7
commit d971fd77af
192 changed files with 4767 additions and 5300 deletions

View File

@@ -1,20 +0,0 @@
<template>
<Story>
<Variant title="empty">
<InstanceContactLink />
</Variant>
<Variant title="string">
<InstanceContactLink contact="someone" />
</Variant>
<Variant title="email">
<InstanceContactLink contact="someone@somewhere.tld" />
</Variant>
<Variant title="url">
<InstanceContactLink contact="https://somewhere.com" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import InstanceContactLink from "./InstanceContactLink.vue";
</script>

View File

@@ -1,52 +0,0 @@
<template>
<Story>
<Variant title="local">
<ActorCard :actor="stateLocal"></ActorCard>
<template #controls>
<HstText v-model="stateLocal.preferredUsername" title="username" />
<HstText v-model="stateLocal.name" title="Name" />
</template>
</Variant>
<Variant title="remote">
<ActorCard :actor="stateRemote"></ActorCard>
<template #controls>
<HstText v-model="stateRemote.preferredUsername" title="username" />
<HstText v-model="stateRemote.name" title="Name" />
<HstText v-model="stateRemote.domain" title="Domain" />
<HstText v-model="avatarUrl" title="Avatar" />
</template>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import ActorCard from "./ActorCard.vue";
import { reactive, ref } from "vue";
import { IActor } from "@/types/actor";
import { ActorType } from "@/types/enums";
const avatarUrl = ref<string>(
"https://stockage.framapiaf.org/framapiaf/accounts/avatars/000/000/399/original/52b08a3e80b43d40.jpg"
);
const stateLocal = reactive<IActor>({
name: "Thomas Citharel",
preferredUsername: "tcit",
avatar: null,
domain: null,
url: "",
summary: "",
suspended: false,
type: ActorType.PERSON,
});
const stateRemote = reactive<IActor>({
name: "Framasoft",
preferredUsername: "framasoft",
avatar: { url: avatarUrl.value, id: "", name: "", alt: "", metadata: {} },
domain: "framapiaf.org",
url: "",
summary: "",
suspended: false,
type: ActorType.PERSON,
});
</script>

View File

@@ -1,52 +0,0 @@
<template>
<Story>
<Variant title="local">
<ActorInline :actor="stateLocal" />
<template #controls>
<HstText v-model="stateLocal.preferredUsername" title="username" />
<HstText v-model="stateLocal.name" title="Name" />
</template>
</Variant>
<Variant title="remote">
<ActorInline :actor="stateRemote" />
<template #controls>
<HstText v-model="stateRemote.preferredUsername" title="username" />
<HstText v-model="stateRemote.name" title="Name" />
<HstText v-model="stateRemote.domain" title="Domain" />
<HstText v-model="avatarUrl" title="Avatar" />
</template>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import ActorInline from "./ActorInline.vue";
import { reactive, ref } from "vue";
import { IActor } from "@/types/actor";
import { ActorType } from "@/types/enums";
const avatarUrl = ref<string>(
"https://stockage.framapiaf.org/framapiaf/accounts/avatars/000/000/399/original/52b08a3e80b43d40.jpg"
);
const stateLocal = reactive<IActor>({
name: "Thomas Citharel",
preferredUsername: "tcit",
avatar: null,
domain: null,
url: "",
summary: "",
suspended: false,
type: ActorType.PERSON,
});
const stateRemote = reactive<IActor>({
name: "Framasoft",
preferredUsername: "framasoft",
avatar: { url: avatarUrl.value, id: "", name: "", alt: "", metadata: {} },
domain: "framapiaf.org",
url: "",
summary: "",
suspended: false,
type: ActorType.PERSON,
});
</script>

View File

@@ -1,59 +0,0 @@
<template>
<Story>
<Variant :setup-app="setupApp" title="Person">
<div class="p-5">
<PopoverActorCard :actor="baseActor">
<div><b> Popover me !</b></div></PopoverActorCard
>
</div>
</Variant>
<Variant :setup-app="setupApp" title="Group">
<div class="p-5">
<PopoverActorCard :actor="group">
<div><b> Popover me !</b></div></PopoverActorCard
>
</div>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import PopoverActorCard from "./PopoverActorCard.vue";
import FloatingVue from "floating-vue";
import "floating-vue/dist/style.css";
import { ActorType } from "@/types/enums";
const baseActorAvatar = {
id: "",
name: "",
alt: "",
metadata: {},
url: "https://social.tcit.fr/system/accounts/avatars/000/000/001/original/a28c50ce5f2b13fd.jpg",
};
const baseActor = {
name: "Thomas Citharel",
preferredUsername: "tcit",
avatar: baseActorAvatar,
domain: null,
url: "",
summary: "",
suspended: false,
type: ActorType.PERSON,
};
const group = {
...baseActor,
name: "Framasoft",
preferredUsername: "framasoft",
domain: "mobilizon.fr",
avatar: {
...baseActorAvatar,
url: "https://stockage.framapiaf.org/framapiaf/accounts/avatars/000/000/399/original/52b08a3e80b43d40.jpg",
},
};
function setupApp({ app }) {
app.use(FloatingVue);
}
</script>

View File

@@ -1,29 +0,0 @@
<template>
<Story>
<Variant>
<div class="p-5">
<ProfileOnboarding
:current-actor="baseActor"
instance-name="Instance name"
/>
</div>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import ProfileOnboarding from "./ProfileOnboarding.vue";
import { ActorType } from "@/types/enums";
import { IPerson } from "@/types/actor";
const baseActor: IPerson = {
name: "Thomas Citharel",
preferredUsername: "tcit",
avatar: null,
domain: null,
url: "",
summary: "",
suspended: false,
type: ActorType.PERSON,
};
</script>

View File

@@ -1,31 +0,0 @@
<template>
<Story>
<Variant title="Basic">
<AddressInfo :address="address" />
</Variant>
<Variant title="Basic with timezone">
<AddressInfo
:address="address"
:show-timezone="true"
:user-timezone="'Europe/Berlin'"
/>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { IAddress } from "@/types/address.model";
import { reactive } from "vue";
import AddressInfo from "./AddressInfo.vue";
const address = reactive<IAddress>({
description: "Locaux Motiv",
street: "10 Rue Jangot",
locality: "Lyon",
postalCode: "69007",
region: "Auvergne Rhône-Alpes",
country: "France",
type: "",
timezone: "Europe/Dublin",
});
</script>

View File

@@ -1,27 +0,0 @@
<template>
<Story>
<Variant title="with locality">
<InlineAddress :physicalAddress="address" />
</Variant>
<Variant title="without locality">
<InlineAddress :physicalAddress="{ ...address, locality: null }" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { IAddress } from "@/types/address.model";
import { reactive } from "vue";
import InlineAddress from "./InlineAddress.vue";
const address = reactive<IAddress>({
description: "Locaux Motiv",
street: "10 Rue Jangot",
locality: "Lyon",
postalCode: "69007",
region: "Auvergne Rhône-Alpes",
country: "France",
type: "",
timezone: "Europe/Dublin",
});
</script>

View File

@@ -1,29 +0,0 @@
<template>
<Story>
<Variant title="Basic">
<section class="flex flex-wrap gap-3 md:gap-5">
<CategoryCard :category="category" />
</section>
</Variant>
<Variant title="Details">
<section class="flex flex-wrap gap-3 md:gap-5">
<CategoryCard
:category="{ ...category, key: 'OUTDOORS_ADVENTURE' }"
:with-details="true"
/>
</section>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { CategoryStatsModel } from "@/types/stats.model";
import { reactive } from "vue";
import CategoryCard from "./CategoryCard.vue";
const category = reactive<CategoryStatsModel>({
key: "PHOTOGRAPHY",
number: 5,
label: "Hello",
});
</script>

View File

@@ -1,190 +0,0 @@
<template>
<Story :setup-app="setupApp">
<Variant title="Basic">
<Comment
:comment="comment"
:event="event"
:currentActor="baseActor"
@create-comment="logEvent('Create comment', $event)"
@delete-comment="logEvent('Delete comment', $event)"
@report-comment="logEvent('Report comment', $event)"
/>
</Variant>
<Variant title="Announcement">
<Comment
:comment="{ ...comment, isAnnouncement: true }"
:event="event"
:currentActor="baseActor"
@create-comment="logEvent('Create comment', $event)"
@delete-comment="logEvent('Delete comment', $event)"
@report-comment="logEvent('Report comment', $event)"
/>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { IPerson } from "@/types/actor";
import { IComment } from "@/types/comment.model";
import {
ActorType,
CommentModeration,
EventJoinOptions,
EventStatus,
EventVisibility,
} from "@/types/enums";
import { IEvent } from "@/types/event.model";
import { reactive } from "vue";
import Comment from "./EventComment.vue";
import FloatingVue from "floating-vue";
import "floating-vue/dist/style.css";
import { logEvent } from "histoire/client";
import { createMemoryHistory, createRouter } from "vue-router";
function setupApp({ app }) {
app.use(FloatingVue);
app.use(
createRouter({
history: createMemoryHistory(),
routes: [
{
path: "/event/:uuid",
name: "Event",
component: { render: () => null },
},
],
})
);
}
const baseActorAvatar = {
id: "",
name: "",
alt: "",
metadata: {},
url: "https://social.tcit.fr/system/accounts/avatars/000/000/001/original/a28c50ce5f2b13fd.jpg",
};
const baseActor: IPerson = {
name: "Thomas Citharel",
preferredUsername: "tcit",
avatar: baseActorAvatar,
domain: null,
url: "",
summary: "",
suspended: false,
type: ActorType.PERSON,
id: "598",
};
const baseEvent: IEvent = {
uuid: "an-uuid",
title: "A very interesting event",
description: "Things happen",
beginsOn: new Date().toISOString(),
endsOn: new Date().toISOString(),
physicalAddress: {
description: "Somewhere",
street: "",
locality: "",
region: "",
country: "",
type: "",
postalCode: "",
},
picture: {
id: "",
name: "",
alt: "",
metadata: {},
url: "https://mobilizon.fr/media/81d9c76aaf740f84eefb28cf2b9988bdd2495ab1f3246159fd688e242155cb23.png?name=Screenshot_20220315_171848.png",
},
url: "",
local: true,
slug: "",
publishAt: new Date().toISOString(),
status: EventStatus.CONFIRMED,
visibility: EventVisibility.PUBLIC,
joinOptions: EventJoinOptions.FREE,
draft: false,
participantStats: {
notApproved: 0,
notConfirmed: 0,
rejected: 0,
participant: 0,
creator: 0,
moderator: 0,
administrator: 0,
going: 0,
},
participants: { total: 0, elements: [] },
relatedEvents: [],
tags: [{ slug: "something", title: "Something" }],
attributedTo: undefined,
organizerActor: {
...baseActor,
name: "Hello",
avatar: {
...baseActorAvatar,
url: "https://mobilizon.fr/media/653c2dcbb830636e0db975798163b85e038dfb7713e866e96d36bd411e105e3c.png?name=festivalsanantes%27s%20avatar.png",
},
},
comments: [],
options: {
maximumAttendeeCapacity: 0,
remainingAttendeeCapacity: 0,
showRemainingAttendeeCapacity: false,
anonymousParticipation: false,
hideOrganizerWhenGroupEvent: false,
offers: [],
participationConditions: [],
attendees: [],
program: "",
commentModeration: CommentModeration.ALLOW_ALL,
showParticipationPrice: false,
showStartTime: false,
showEndTime: false,
timezone: null,
isOnline: false,
},
metadata: [],
contacts: [],
language: "en",
category: "hello",
};
const event = reactive<IEvent>(baseEvent);
const comment = reactive<IComment>({
text: "hello",
local: true,
actor: baseActor,
totalReplies: 5,
replies: [
{
text: "a reply!",
id: "90",
actor: baseActor,
updatedAt: new Date().toISOString(),
url: "http://somewhere.tld",
replies: [],
totalReplies: 0,
isAnnouncement: false,
local: false,
},
{
text: "a reply to another reply!",
id: "92",
actor: baseActor,
updatedAt: new Date().toISOString(),
url: "http://somewhere.tld",
replies: [],
totalReplies: 0,
isAnnouncement: false,
local: false,
},
],
isAnnouncement: false,
updatedAt: new Date().toISOString(),
url: "http://somewhere.tld",
});
</script>

View File

@@ -1,50 +0,0 @@
<template>
<Story>
<Variant title="Basic">
<DiscussionComment v-model="comment" :currentActor="baseActor" />
</Variant>
<Variant title="Deleted comment">
<DiscussionComment v-model="deletedComment" :currentActor="baseActor" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { IPerson } from "@/types/actor";
import { IComment } from "@/types/comment.model";
import { ActorType } from "@/types/enums";
import { reactive } from "vue";
import DiscussionComment from "./DiscussionComment.vue";
const baseActorAvatar = {
id: "",
name: "",
alt: "",
metadata: {},
url: "https://social.tcit.fr/system/accounts/avatars/000/000/001/original/a28c50ce5f2b13fd.jpg",
};
const baseActor: IPerson = {
name: "Thomas Citharel",
preferredUsername: "tcit",
avatar: baseActorAvatar,
domain: null,
url: "",
summary: "",
suspended: false,
type: ActorType.PERSON,
id: "598",
};
const comment = reactive<IComment>({
text: "Hello there",
publishedAt: new Date().toString(),
actor: baseActor,
});
const deletedComment = reactive<IComment>({
...comment,
actor: null,
deletedAt: new Date().toString(),
});
</script>

View File

@@ -1,33 +0,0 @@
<template>
<Story>
<Variant title="Basic">
<DiscussionListItem :discussion="discussion" />
</Variant>
<Variant title="Deleted comment">
<DiscussionListItem :discussion="discussionWithDeletedComment" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { IDiscussion } from "@/types/discussions";
import { reactive } from "vue";
import DiscussionListItem from "@/components/Discussion/DiscussionListItem.vue";
const discussion = reactive<IDiscussion>({
title: "A discussion",
comments: { total: 5, elements: [] },
insertedAt: new Date().toString(),
updatedAt: new Date().toString(),
deletedAt: null,
lastComment: { text: "Hello there", publishedAt: new Date().toString() },
});
const discussionWithDeletedComment = reactive<IDiscussion>({
...discussion,
lastComment: {
...discussion.lastComment,
deletedAt: new Date().toString(),
},
});
</script>

View File

@@ -1,14 +0,0 @@
<template>
<Story>
<Variant title="new">
<DateCalendarIcon :date="new Date().toString()" />
</Variant>
<Variant title="small">
<DateCalendarIcon :date="new Date().toString()" :small="true" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import DateCalendarIcon from "./DateCalendarIcon.vue";
</script>

View File

@@ -1,148 +0,0 @@
<template>
<Story title="EventCard">
<Variant title="default">
<EventCard :event="event" />
</Variant>
<Variant title="long">
<EventCard :event="longEvent" />
</Variant>
<Variant title="tentative">
<EventCard :event="tentativeEvent" />
</Variant>
<Variant title="cancelled">
<EventCard :event="cancelledEvent" />
</Variant>
<Variant title="Row mode">
<EventCard :event="longEvent" mode="row" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { IActor } from "@/types/actor";
import {
ActorType,
CommentModeration,
EventJoinOptions,
EventStatus,
EventVisibility,
} from "@/types/enums";
import { IEvent } from "@/types/event.model";
import { reactive } from "vue";
import EventCard from "./EventCard.vue";
const baseActorAvatar = {
id: "",
name: "",
alt: "",
metadata: {},
url: "https://social.tcit.fr/system/accounts/avatars/000/000/001/original/a28c50ce5f2b13fd.jpg",
};
const baseActor: IActor = {
name: "Thomas Citharel",
preferredUsername: "tcit",
avatar: baseActorAvatar,
domain: null,
url: "",
summary: "",
suspended: false,
type: ActorType.PERSON,
};
const baseEvent: IEvent = {
uuid: "",
title: "A very interesting event",
description: "Things happen",
beginsOn: new Date().toISOString(),
endsOn: new Date().toISOString(),
physicalAddress: {
description: "Somewhere",
street: "",
locality: "",
region: "",
country: "",
type: "",
postalCode: "",
},
picture: {
id: "",
name: "",
alt: "",
metadata: {},
url: "https://mobilizon.fr/media/81d9c76aaf740f84eefb28cf2b9988bdd2495ab1f3246159fd688e242155cb23.png?name=Screenshot_20220315_171848.png",
},
url: "",
local: true,
slug: "",
publishAt: new Date().toISOString(),
status: EventStatus.CONFIRMED,
visibility: EventVisibility.PUBLIC,
joinOptions: EventJoinOptions.FREE,
draft: false,
participantStats: {
notApproved: 0,
notConfirmed: 0,
rejected: 0,
participant: 0,
creator: 0,
moderator: 0,
administrator: 0,
going: 0,
},
participants: { total: 0, elements: [] },
relatedEvents: [],
tags: [{ slug: "something", title: "Something" }],
attributedTo: undefined,
organizerActor: {
...baseActor,
name: "Hello",
avatar: {
...baseActorAvatar,
url: "https://mobilizon.fr/media/653c2dcbb830636e0db975798163b85e038dfb7713e866e96d36bd411e105e3c.png?name=festivalsanantes%27s%20avatar.png",
},
},
comments: [],
options: {
maximumAttendeeCapacity: 0,
remainingAttendeeCapacity: 0,
showRemainingAttendeeCapacity: false,
anonymousParticipation: false,
hideOrganizerWhenGroupEvent: false,
offers: [],
participationConditions: [],
attendees: [],
program: "",
commentModeration: CommentModeration.ALLOW_ALL,
showParticipationPrice: false,
showStartTime: false,
showEndTime: false,
timezone: null,
isOnline: false,
},
metadata: [],
contacts: [],
language: "en",
category: "hello",
};
const event = reactive<IEvent>(baseEvent);
const longEvent = reactive<IEvent>({
...baseEvent,
title:
"A very long title that will have trouble to display because it will take multiple lines but where will it stop ?! Maybe after 3 lines is enough. Let's say so. But if it doesn't work, we really need to truncate it at some point. Definitively.",
});
const tentativeEvent = reactive<IEvent>({
...baseEvent,
status: EventStatus.TENTATIVE,
});
const cancelledEvent = reactive<IEvent>({
...baseEvent,
status: EventStatus.CANCELLED,
});
</script>

View File

@@ -1,143 +0,0 @@
<template>
<Story title="EventListViewCard">
<Variant title="default">
<EventListViewCard :event="baseEvent" />
</Variant>
<Variant title="long">
<EventListViewCard :event="longEvent" />
</Variant>
<!-- <Variant title="tentative">
<EventListViewCard :event="tentativeEvent" />
</Variant>
<Variant title="cancelled">
<EventListViewCard :event="cancelledEvent" />
</Variant> -->
</Story>
</template>
<script lang="ts" setup>
import { IActor } from "@/types/actor";
import {
ActorType,
CommentModeration,
EventJoinOptions,
EventStatus,
EventVisibility,
} from "@/types/enums";
import { IEvent } from "@/types/event.model";
import { reactive } from "vue";
import EventListViewCard from "./EventListViewCard.vue";
const baseActorAvatar = {
id: "",
name: "",
alt: "",
metadata: {},
url: "https://social.tcit.fr/system/accounts/avatars/000/000/001/original/a28c50ce5f2b13fd.jpg",
};
const baseActor: IActor = {
name: "Thomas Citharel",
preferredUsername: "tcit",
avatar: baseActorAvatar,
domain: null,
url: "",
summary: "",
suspended: false,
type: ActorType.PERSON,
};
const baseEvent: IEvent = {
uuid: "",
title: "A very interesting event",
description: "Things happen",
beginsOn: new Date().toISOString(),
endsOn: new Date().toISOString(),
physicalAddress: {
description: "Somewhere",
street: "",
locality: "",
region: "",
country: "",
type: "",
postalCode: "",
},
picture: {
id: "",
name: "",
alt: "",
metadata: {},
url: "https://mobilizon.fr/media/81d9c76aaf740f84eefb28cf2b9988bdd2495ab1f3246159fd688e242155cb23.png?name=Screenshot_20220315_171848.png",
},
url: "",
local: true,
slug: "",
publishAt: new Date().toISOString(),
status: EventStatus.CONFIRMED,
visibility: EventVisibility.PUBLIC,
joinOptions: EventJoinOptions.FREE,
draft: false,
participantStats: {
notApproved: 0,
notConfirmed: 0,
rejected: 0,
participant: 0,
creator: 0,
moderator: 0,
administrator: 0,
going: 0,
},
participants: { total: 0, elements: [] },
relatedEvents: [],
tags: [{ slug: "something", title: "Something" }],
attributedTo: undefined,
organizerActor: {
...baseActor,
name: "Hello",
avatar: {
...baseActorAvatar,
url: "https://mobilizon.fr/media/653c2dcbb830636e0db975798163b85e038dfb7713e866e96d36bd411e105e3c.png?name=festivalsanantes%27s%20avatar.png",
},
},
comments: [],
options: {
maximumAttendeeCapacity: 0,
remainingAttendeeCapacity: 0,
showRemainingAttendeeCapacity: false,
anonymousParticipation: false,
hideOrganizerWhenGroupEvent: false,
offers: [],
participationConditions: [],
attendees: [],
program: "",
commentModeration: CommentModeration.ALLOW_ALL,
showParticipationPrice: false,
showStartTime: false,
showEndTime: false,
timezone: null,
isOnline: false,
},
metadata: [],
contacts: [],
language: "en",
category: "hello",
};
const longEvent = reactive<IEvent>({
...baseEvent,
title:
"A very long title that will have trouble to display because it will take multiple lines but where will it stop ?! Maybe after 3 lines is enough. Let's say so.",
});
// const tentativeEvent = reactive<IEvent>({
// ...baseEvent,
// status: EventStatus.TENTATIVE,
// });
// const cancelledEvent = reactive<IEvent>({
// ...baseEvent,
// status: EventStatus.CANCELLED,
// });
</script>

View File

@@ -1,56 +0,0 @@
<template>
<Story :setup-app="setupApp">
<Variant>
<OrganizerPicker
v-model="actor"
:identities="identities"
v-model:actor-filter="actorFilter"
:groupMemberships="[]"
:current-actor="currentActor"
@update:actor-filter="logEvent('Actor Filter updated', $event)"
@update:model-value="logEvent('Selected actor updated', $event)"
/>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import OrganizerPicker from "./OrganizerPicker.vue";
import { createMemoryHistory, createRouter } from "vue-router";
import { reactive, ref } from "vue";
import { ActorType } from "@/types/enums";
import { logEvent } from "histoire/client";
const currentActor = reactive({
id: "59",
preferredUsername: "me",
name: "Someone",
type: ActorType.PERSON,
});
const actor = reactive({
id: "5",
preferredUsername: "hello",
name: "Sigmund",
type: ActorType.PERSON,
});
const group = reactive({
id: "89",
preferredUsername: "congregation",
name: "College",
type: ActorType.GROUP,
});
const identities = [actor, group];
const actorFilter = ref("");
function setupApp({ app }) {
app.use(
createRouter({
history: createMemoryHistory(),
routes: [{ path: "/", name: "home", component: { render: () => null } }],
})
);
}
</script>

View File

@@ -1,89 +0,0 @@
<template>
<Story :setup-app="setupApp">
<Variant>
<OrganizerPickerWrapper
v-model="actor"
@update:model-value="logEvent('Value', $event)"
@update:contacts="logEvent('Contacts', $event)"
/>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import OrganizerPickerWrapper from "./OrganizerPickerWrapper.vue";
import { DefaultApolloClient } from "@vue/apollo-composable";
import { createMockClient } from "mock-apollo-client";
import { cache } from "@/apollo/memory";
import { ICurrentUserRole } from "@/types/enums";
import { PERSON_GROUP_MEMBERSHIPS } from "@/graphql/actor";
import { createMemoryHistory, createRouter } from "vue-router";
import { IDENTITIES } from "@/graphql/actor";
import { reactive } from "vue";
import { logEvent } from "histoire/client";
const actor = reactive({
id: "5",
preferredUsername: "hello",
name: "Sigmund",
});
function setupApp({ app }) {
const defaultResolvers = {
Query: {
currentUser: (): Record<string, any> => ({
email: "user@mail.com",
id: "2",
role: ICurrentUserRole.USER,
isLoggedIn: true,
__typename: "CurrentUser",
}),
currentActor: (): Record<string, any> => ({
id: "67",
preferredUsername: "someone",
name: "Personne",
avatar: null,
__typename: "CurrentActor",
}),
},
};
const mockClient = createMockClient({
cache,
resolvers: defaultResolvers,
});
mockClient.setRequestHandler(
PERSON_GROUP_MEMBERSHIPS,
() =>
new Promise((resolve) =>
resolve({
data: {
person: { id: "5", memberships: { total: 0, elements: [] } },
},
})
)
);
mockClient.setRequestHandler(
IDENTITIES,
() =>
new Promise((resolve) =>
resolve({
data: {
loggedUser: {
actors: [{ id: "9", preferredUsername: "sam", name: "Samuel" }],
},
},
})
)
);
app.provide(DefaultApolloClient, mockClient);
app.use(
createRouter({
history: createMemoryHistory(),
routes: [{ path: "/", name: "home", component: { render: () => null } }],
})
);
}
</script>

View File

@@ -1,114 +0,0 @@
<template>
<Story>
<Variant title="Unlogged">
<ParticipationButton
:event="event"
:current-actor="emptyCurrentActor"
:participation="undefined"
:identities="[]"
/>
</Variant>
<Variant title="Basic">
<ParticipationButton
:event="event"
:current-actor="currentActor"
:participation="undefined"
:identities="identities"
@join-event="logEvent('Join event', $event)"
@join-modal="logEvent('Join modal', $event)"
@confirm-leave="logEvent('Confirm leave', $event)"
/>
</Variant>
<Variant title="Basic with confirmation">
<ParticipationButton
:event="{ ...event, joinOptions: EventJoinOptions.RESTRICTED }"
:current-actor="currentActor"
:participation="undefined"
:identities="identities"
@join-event-with-confirmation="
logEvent('Join Event with confirmation', $event)
"
@join-modal="logEvent('Join modal', $event)"
/>
</Variant>
<Variant title="Participating">
<ParticipationButton
:event="event"
:current-actor="currentActor"
:participation="participation"
:identities="identities"
@confirm-leave="logEvent('Confirm leave', $event)"
/>
</Variant>
<Variant title="Pending approval">
<ParticipationButton
:event="event"
:current-actor="currentActor"
:participation="{
...participation,
role: ParticipantRole.NOT_APPROVED,
}"
:identities="identities"
@confirm-leave="logEvent('Confirm leave', $event)"
/>
</Variant>
<Variant title="Rejected">
<ParticipationButton
:event="event"
:current-actor="currentActor"
:participation="{
...participation,
role: ParticipantRole.REJECTED,
}"
:identities="identities"
@confirm-leave="logEvent('Confirm leave', $event)"
/>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { IPerson } from "@/types/actor";
import { EventJoinOptions, ParticipantRole } from "@/types/enums";
import { IEvent } from "@/types/event.model";
import ParticipationButton from "./ParticipationButton.vue";
import { logEvent } from "histoire/client";
import { IParticipant } from "@/types/participant.model";
const emptyCurrentActor: IPerson = {};
const currentActor: IPerson = {
id: "1",
preferredUsername: "tcit",
name: "Thomas",
avatar: {
url: "https://mobilizon.fr/media/3a5f18c058a8193b1febfaf561f94ae8b91f85ac64c01ddf5ad7b251fb43baf5.jpg?name=profil.jpg",
},
};
const participation: IParticipant = {
actor: currentActor,
role: ParticipantRole.PARTICIPANT,
};
const identities: IPerson[] = [
currentActor,
{
id: "2",
preferredUsername: "another",
name: "Another",
avatar: {
url: "https://mobilizon.fr/media/95ab5ba92287ab4857bb517cadae2a7ab6a553748d1c48cefc27e2b7ab640fea.jpg?name=FB_IMG_16150214351371162.jpg",
},
},
];
const event: IEvent = {
title: "hello",
url: "https://mobilizon.fr/events/an-uuid",
options: {
anonymousParticipation: false,
},
joinOptions: EventJoinOptions.FREE,
};
</script>

View File

@@ -1,29 +0,0 @@
<template>
<Story>
<Variant title="Public">
<ShareEventModal :event="event" />
</Variant>
<Variant title="Private">
<ShareEventModal
:event="{ ...event, visibility: EventVisibility.PRIVATE }"
/>
</Variant>
<Variant title="Cancelled">
<ShareEventModal :event="{ ...event, status: EventStatus.CANCELLED }" />
</Variant>
<Variant title="No seats left">
<ShareEventModal :event="event" :event-capacity-o-k="false" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { EventVisibility, EventStatus } from "@/types/enums";
import ShareEventModal from "./ShareEventModal.vue";
const event = {
title: "hello",
url: "https://mobilizon.fr/events/an-uuid",
visibility: EventVisibility.PUBLIC,
};
</script>

View File

@@ -1,17 +0,0 @@
<template>
<Story>
<Variant title="row">
<SkeletonEventResult />
</Variant>
<Variant title="column">
<SkeletonEventResult view-mode="column" />
</Variant>
<Variant title="not minimal">
<SkeletonEventResult :minimal="false" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import SkeletonEventResult from "./SkeletonEventResult.vue";
</script>

View File

@@ -1,18 +0,0 @@
<template>
<Story>
<Variant title="new">
<TagInput v-model="tags" />
</Variant>
<!-- <Variant title="small">
<TagInput v-model="tags" />
</Variant> -->
</Story>
</template>
<script lang="ts" setup>
import { ITag } from "@/types/tag.model";
import { reactive } from "vue";
import TagInput from "./TagInput.vue";
const tags = reactive<ITag[]>([{ title: "Hello", slug: "hello" }]);
</script>

View File

@@ -1,60 +0,0 @@
<template>
<Story>
<Variant title="Empty">
<div class="p-5">
<GroupCard :group="basicGroup" />
</div>
</Variant>
<Variant title="With media">
<div class="p-5">
<GroupCard :group="groupWithMedia" />
</div>
</Variant>
<Variant title="with followers or members">
<div class="p-5">
<GroupCard :group="groupWithFollowersOrMembers" />
</div>
</Variant>
<Variant title="Row mode">
<GroupCard :group="groupWithFollowersOrMembers" mode="row" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { IGroup } from "@/types/actor";
import GroupCard from "./GroupCard.vue";
const basicGroup: IGroup = {
name: "Framasoft",
preferredUsername: "framasoft",
avatar: null,
domain: "mobilizon.fr",
url: "",
summary: "",
suspended: false,
members: { total: 0, elements: [] },
followers: { total: 0, elements: [] },
};
const groupWithMedia: IGroup = {
...basicGroup,
banner: {
url: "https://mobilizon.fr/media/a8227a16cc80b3d20ff5ee549a29c1b20a0ca1547f8861129aae9f00c3c69d12.jpg?name=framasoft%27s%20banner.jpg",
},
avatar: {
url: "https://mobilizon.fr/media/890f5396ef80081a6b1b18a5db969746cf8bb340e8a4e657d665e41f6646c539.jpg?name=framasoft%27s%20avatar.jpg",
},
};
const groupWithFollowersOrMembers: IGroup = {
...groupWithMedia,
members: { total: 2, elements: [] },
followers: { total: 5, elements: [] },
summary:
"You can also use variant modifiers to target media queries like responsive breakpoints, dark mode, prefers-reduced-motion, and more. For example, use md:h-full to apply the h-full utility at only medium screen sizes and above.",
physicalAddress: {
description: "Nantes",
},
};
</script>

View File

@@ -1,91 +0,0 @@
<template>
<Story>
<Variant title="simple member">
<div class="p-5">
<GroupMemberCard :member="basicMember" />
</div>
</Variant>
<Variant title="moderator">
<div class="p-5">
<GroupMemberCard :member="moderatorMember" />
</div>
</Variant>
<Variant title="administrator">
<div class="p-5">
<GroupMemberCard :member="adminMember" />
</div>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { IActor } from "@/types/actor";
import { IMember } from "@/types/actor/member.model";
import { MemberRole } from "@/types/enums";
import GroupMemberCard from "./GroupMemberCard.vue";
const baseActorAvatar = {
id: "",
name: "",
alt: "",
metadata: {},
url: "https://social.tcit.fr/system/accounts/avatars/000/000/001/original/a28c50ce5f2b13fd.jpg",
};
const basePerson: IActor = {
name: "Thomas Citharel",
preferredUsername: "tcit",
avatar: baseActorAvatar,
domain: null,
url: "",
summary: "",
suspended: false,
};
const basicGroup: IActor = {
name: "Framasoft",
preferredUsername: "framasoft",
avatar: {
url: "https://mobilizon.fr/media/ff5b2d425fb73e17fcbb56a1a032359ee0b21453c11af59e103e783817a32fdf.png?name=framasoft%27s%20avatar.png",
},
domain: "mobilizon.fr",
url: "",
summary: `<p><strong>La Fediverse</strong>, <strong>c'est la <em><u>Féd</u>ération qui englobe l'Un<u>ivers</u> des réseaux sociaux libres et décentralisés,</em> </strong>dont Mobilizon (évènements), Mastodon (microblog), Peertube (vidéos), Pixelfed (photos), Funkwhale (musique), Matrix (messagerie instantanée)... et tant d'autres font partie.</p><p><strong>Et "La Fediverse <em>Nantaise</em>" est un collectif cherchant à faire connaître localement tout le potentiel de ces réseaux ! :-)</strong></p>`,
suspended: false,
members: { total: 0, elements: [] },
followers: { total: 0, elements: [] },
};
const basicMember: IMember = {
parent: basicGroup as IActor,
actor: basePerson,
role: MemberRole.MEMBER,
};
const moderatorMember: IMember = {
parent: basicGroup,
actor: basePerson,
role: MemberRole.MODERATOR,
};
const adminMember: IMember = {
parent: basicGroup,
actor: basePerson,
role: MemberRole.ADMINISTRATOR,
};
// const groupWithMedia = {
// ...basicGroup,
// banner: {
// url: "https://mobilizon.fr/media/7b340fe641e7ad711ebb6f8821b5ce824992db08701e37ebb901c175436aaafc.jpg?name=framasoft%27s%20banner.jpg",
// },
// avatar: {
// url: "https://mobilizon.fr/media/ff5b2d425fb73e17fcbb56a1a032359ee0b21453c11af59e103e783817a32fdf.png?name=framasoft%27s%20avatar.png",
// },
// };
// const groupWithFollowersOrMembers = {
// ...groupWithMedia,
// members: { total: 2, elements: [] },
// followers: { total: 5, elements: [] },
// };
</script>

View File

@@ -1,16 +0,0 @@
<template>
<Story :setup-app="setupApp">
<Variant>
<CategoriesPreview />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { apolloClient } from "@/vue-apollo";
import { DefaultApolloClient } from "@vue/apollo-composable";
import CategoriesPreview from "./CategoriesPreview.vue";
function setupApp({ app }) {
app.provide(DefaultApolloClient, apolloClient);
}
</script>

View File

@@ -1,10 +0,0 @@
<template>
<Story>
<Variant>
<MobilizonPresentation />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import MobilizonPresentation from "./MobilizonPresentation.vue";
</script>

View File

@@ -1,22 +0,0 @@
<template>
<Story :setup-app="setupApp">
<Variant>
<SearchFields
:search="''"
:location="{}"
@update:location="logEvent('update location', $event)"
@update:search="logEvent('update search', $event)"
/>
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { apolloClient } from "@/vue-apollo";
import { DefaultApolloClient } from "@vue/apollo-composable";
import SearchFields from "./SearchFields.vue";
import { logEvent } from "histoire/client";
function setupApp({ app }) {
app.provide(DefaultApolloClient, apolloClient);
}
</script>

View File

@@ -1,23 +0,0 @@
<template>
<Story>
<Variant :title="'Open'">
<UnloggedIntroduction :config="config" />
</Variant>
<Variant :title="'Closed'">
<UnloggedIntroduction :config="configClosed" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { reactive } from "vue";
import UnloggedIntroduction from "./UnloggedIntroduction.vue";
const config = reactive({
name: "My instance name",
description: "An instance that doesn't exist",
slogan: "Test! Test! Test!",
registrationsOpen: true,
});
const configClosed = reactive({ ...config, registrationsOpen: false });
</script>

View File

@@ -1,48 +0,0 @@
<template>
<Story>
<Variant title="Public">
<PostListItem :post="post" />
</Variant>
<Variant title="Long">
<PostListItem :post="longPost" />
</Variant>
<Variant title="Is member">
<PostListItem :post="longPost" :is-current-actor-member="true" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { IPost } from "@/types/post.model";
import PostListItem from "./PostListItem.vue";
const post: IPost = {
title: "Musique sur Nantes : un groupe à développer ensemble !",
url: "https://mobilizon.fr/p/an-uuid",
insertedAt: new Date(),
author: {
name: "I'm the author",
preferredUsername: "the_author",
},
tags: [
{ slug: "musique", title: "Musique" },
{ slug: "concert", title: "Concert" },
],
picture: {
url: "https://mobilizon.fr/media/70e930f488788afdf5d024be5ac2f9c9f0e1b166e16f645beb2c344cdcc65d62.jpg?name=musiquesurnantesbanner.jpg",
},
};
const longPost = {
...post,
title:
"Musique sur Nantes : un groupe à développer ensemble ! Musique sur Nantes : un groupe à développer ensemble !",
tags: [
...(post.tags ?? []),
{ slug: "verylongtagwhathappensthen", title: "VeryLongTagWhatHappensThen" },
{ slug: "justanother", title: "Just another" },
],
};
</script>

View File

@@ -1,20 +0,0 @@
<template>
<Story>
<Variant title="Public">
<SharePostModal :post="{ ...post, visibility: PostVisibility.PUBLIC }" />
</Variant>
<Variant title="Private">
<SharePostModal :post="post" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import { PostVisibility } from "@/types/enums";
import SharePostModal from "./SharePostModal.vue";
const post = {
title: "hello",
url: "https://mobilizon.fr/p/an-uuid",
};
</script>

View File

@@ -1,13 +0,0 @@
<template>
<Story>
<Variant title="Public">
<AuthProviders :oauthProviders="providers" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import AuthProviders from "./AuthProviders.vue";
const providers = [{ id: "keycloak", label: "Entreprise" }, { id: "google" }];
</script>

View File

@@ -1,16 +0,0 @@
<template>
<Story :layout="{ type: 'grid', width: 60 }">
<Variant title="Google">
<MaterialIcon :icon="['', 'google']" />
</Variant>
<Variant title="Calendar">
<MaterialIcon :icon="['', 'calendar']" />
</Variant>
<Variant title="Account Multiple Plus">
<MaterialIcon :icon="['', 'account-multiple-plus']" />
</Variant>
</Story>
</template>
<script lang="ts" setup>
import MaterialIcon from "./MaterialIcon.vue";
</script>

View File

@@ -1,17 +0,0 @@
import { defineSetupVue3 } from "@histoire/plugin-vue";
import { orugaConfig } from "./oruga-config";
import { i18n } from "./utils/i18n";
import Oruga from "@oruga-ui/oruga-next";
import "@oruga-ui/oruga-next/dist/oruga-full-vars.css";
import "./assets/tailwind.css";
import "./assets/oruga-tailwindcss.css";
import locale from "date-fns/locale/en-US";
import MaterialIcon from "./components/core/MaterialIcon.vue";
export const setupVue3 = defineSetupVue3(({ app }) => {
// Vue plugin
app.use(i18n);
app.use(Oruga, orugaConfig);
app.component("material-icon", MaterialIcon);
app.provide("dateFnsLocale", locale);
});