diff --git a/lib/federation/activity_pub/publisher.ex b/lib/federation/activity_pub/publisher.ex
index 257a2f6be..2b3d2629a 100644
--- a/lib/federation/activity_pub/publisher.ex
+++ b/lib/federation/activity_pub/publisher.ex
@@ -7,6 +7,7 @@ defmodule Mobilizon.Federation.ActivityPub.Publisher do
alias Mobilizon.Config
alias Mobilizon.Federation.ActivityPub.{Activity, Federator, Relay, Transmogrifier, Visibility}
alias Mobilizon.Federation.HTTPSignatures.Signature
+ alias Mobilizon.Service.HTTP.ActivityPub, as: ActivityPubClient
require Logger
import Mobilizon.Federation.ActivityPub.Utils,
@@ -95,16 +96,16 @@ defmodule Mobilizon.Federation.ActivityPub.Publisher do
date: date
})
- Tesla.post(
- inbox,
- json,
- headers: [
- {"Content-Type", "application/activity+json"},
- {"signature", signature},
- {"digest", digest},
- {"date", date}
- ]
- )
+ headers = [
+ {"Content-Type", "application/activity+json"},
+ {"signature", signature},
+ {"digest", digest},
+ {"date", date}
+ ]
+
+ client = ActivityPubClient.client(headers: headers)
+
+ ActivityPubClient.post(client, inbox, json)
end
@spec convert_followers_in_recipients(list(String.t())) :: {list(String.t()), list(String.t())}
diff --git a/package-lock.json b/package-lock.json
index 3b2b9ccac..8006b8a60 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,7 +15,7 @@
"@fullcalendar/daygrid": "^6.1.10",
"@fullcalendar/interaction": "^6.1.10",
"@fullcalendar/vue3": "^6.1.10",
- "@oruga-ui/oruga-next": "^0.8.2",
+ "@oruga-ui/oruga-next": "^0.8.10",
"@oruga-ui/theme-oruga": "^0.2.0",
"@sentry/tracing": "^7.1",
"@sentry/vue": "^7.1",
@@ -3138,9 +3138,9 @@
"dev": true
},
"node_modules/@oruga-ui/oruga-next": {
- "version": "0.8.5",
- "resolved": "https://registry.npmjs.org/@oruga-ui/oruga-next/-/oruga-next-0.8.5.tgz",
- "integrity": "sha512-HnODRTrurmke7O5rRNdrbqYuNIdMrnBJ+P3jh6J7/Lk/zgMnpsObSGj/6JfQRvdf5Wq++Ch5yVUys0V4Lm08JQ==",
+ "version": "0.8.10",
+ "resolved": "https://registry.npmjs.org/@oruga-ui/oruga-next/-/oruga-next-0.8.10.tgz",
+ "integrity": "sha512-ETPSoGZu1parbj8C3V2ZojQnN4ptQMiJEwS9Hx44NcaDzu4q/FDsYkKYiz6G9kx8cDceXXxvydfOUpZePVVdzw==",
"peerDependencies": {
"vue": "^3.0.0"
}
diff --git a/package.json b/package.json
index d2b5182ef..83aed32c2 100644
--- a/package.json
+++ b/package.json
@@ -36,7 +36,7 @@
"@fullcalendar/daygrid": "^6.1.10",
"@fullcalendar/interaction": "^6.1.10",
"@fullcalendar/vue3": "^6.1.10",
- "@oruga-ui/oruga-next": "^0.8.2",
+ "@oruga-ui/oruga-next": "^0.8.10",
"@oruga-ui/theme-oruga": "^0.2.0",
"@fullcalendar/core": "^6.1.10",
"@fullcalendar/daygrid": "^6.1.10",
diff --git a/src/components/Event/OrganizerPickerWrapper.vue b/src/components/Event/OrganizerPickerWrapper.vue
index e1caf711f..b898ae79e 100644
--- a/src/components/Event/OrganizerPickerWrapper.vue
+++ b/src/components/Event/OrganizerPickerWrapper.vue
@@ -32,7 +32,7 @@
{{ `@${selectedActor.preferredUsername}` }}
-
+
{{ $t("Change") }}
diff --git a/src/components/Event/TagInput.vue b/src/components/Event/TagInput.vue
index dad5c7b9c..b8702c410 100644
--- a/src/components/Event/TagInput.vue
+++ b/src/components/Event/TagInput.vue
@@ -15,7 +15,8 @@
{
const { load: fetchTags } = useFetchTags();
+initTagsStringsValue();
+
const getFilteredTags = async (newText: string): Promise => {
text.value = newText;
const res = await fetchTags(
@@ -91,11 +94,16 @@ const filteredTags = computed((): ITag[] => {
);
});
-watch(props.modelValue, (newValue, oldValue) => {
- if (newValue != oldValue) {
- tagsStrings.value = propsValue.value.map((tag: ITag) => tag.title);
- }
-});
+// TODO It seems that '@update:modelValue="updateTags"' does not works anymore...
+// so temporarily call the function updateTags() at remove and add tag event
+// https://github.com/oruga-ui/oruga/issues/967
+function remove() {
+ updateTags(tagsStrings.value);
+}
+
+function add() {
+ updateTags(tagsStrings.value);
+}
const updateTags = (newTagsStrings: string[]) => {
const tagEntities = newTagsStrings.map((tag: string | ITag) => {
@@ -106,4 +114,34 @@ const updateTags = (newTagsStrings: string[]) => {
});
emit("update:modelValue", tagEntities);
};
+
+function isArraysEquals(array1: string[], array2: string[]) {
+ if (array1.length !== array2.length) {
+ return false;
+ }
+
+ for (let i = 0; i < array1.length; i++) {
+ if (array1[i] !== array2[i]) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function initTagsStringsValue() {
+ // This is useful when tag data is already cached from the API during navigation inside the app
+ tagsStrings.value = propsValue.value.map((tag: ITag) => tag.title);
+
+ // This watch() function is useful when tag data loads directly from the API upon page load
+ watch(propsValue, () => {
+ const newTagsStrings = propsValue.value.map((tag: ITag) => tag.title);
+
+ // Changing tagsStrings.value triggers updateTags(), updateTags() triggers this watch() function again.
+ // To stop the loop, edit tagsStrings.value only if it has changed !
+ if (!isArraysEquals(tagsStrings.value, newTagsStrings)) {
+ tagsStrings.value = newTagsStrings;
+ }
+ });
+}
diff --git a/src/views/Event/MyEventsView.vue b/src/views/Event/MyEventsView.vue
index 7cf8bcf43..4045a33e5 100644
--- a/src/views/Event/MyEventsView.vue
+++ b/src/views/Event/MyEventsView.vue
@@ -23,10 +23,27 @@
-
- {{
- showUpcoming ? t("Upcoming events") : t("Past events")
- }}
+
+
+
{{ t("Drafts") }}
@@ -50,28 +67,6 @@
)
}}
-
-
-
-
{
+ return (n > 9 ? "" : "0") + n.toString();
+ };
+ return (
+ d.getFullYear() +
+ "-" +
+ pad(d.getMonth() + 1) +
+ "-" +
+ pad(d.getDate()) +
+ "T00:00:00Z"
+ );
+}
+
const showUpcoming = useRouteQuery("showUpcoming", true, booleanTransformer);
const showDrafts = useRouteQuery("showDrafts", true, booleanTransformer);
const showAttending = useRouteQuery("showAttending", true, booleanTransformer);
const showMyGroups = useRouteQuery("showMyGroups", false, booleanTransformer);
-const dateFilter = useRouteQuery("dateFilter", new Date(), {
+const dateFilter = useRouteQuery("dateFilter", startOfDay(new Date()), {
fromQuery(query) {
if (query && /(\d{4}-\d{2}-\d{2})/.test(query)) {
- return new Date(`${query}T00:00:00Z`);
+ return `${query}T00:00:00Z`;
}
- return new Date();
+ return startOfDay(new Date());
},
- toQuery(value: Date) {
- const pad = (number: number) => {
- if (number < 10) {
- return "0" + number;
- }
- return number;
- };
- return `${value.getFullYear()}-${pad(value.getMonth() + 1)}-${pad(
- value.getDate()
- )}`;
+ toQuery(value: string) {
+ return value.slice(0, 10);
+ },
+});
+
+// bridge between datepicker expecting a Date object and dateFilter being a string
+const datePick = computed({
+ get: () => {
+ return new Date(dateFilter.value);
+ },
+ set: (d: Date) => {
+ dateFilter.value = startOfDay(d);
},
});
@@ -323,10 +334,7 @@ const pastParticipations = computed(
}
);
-const monthlyEvents = (
- elements: Eventable[],
- revertSort = false
-): Map => {
+const monthlyEvents = (elements: Eventable[]): Map => {
const res = elements.filter((element: Eventable) => {
if ("role" in element) {
return (
@@ -336,19 +344,12 @@ const monthlyEvents = (
}
return element.beginsOn != null;
});
- if (revertSort) {
- res.sort((a: Eventable, b: Eventable) => {
- const aTime = "role" in a ? a.event.beginsOn : a.beginsOn;
- const bTime = "role" in b ? b.event.beginsOn : b.beginsOn;
- return new Date(bTime).getTime() - new Date(aTime).getTime();
- });
- } else {
- res.sort((a: Eventable, b: Eventable) => {
- const aTime = "role" in a ? a.event.beginsOn : a.beginsOn;
- const bTime = "role" in b ? b.event.beginsOn : b.beginsOn;
- return new Date(aTime).getTime() - new Date(bTime).getTime();
- });
- }
+ // sort by start date, ascending
+ res.sort((a: Eventable, b: Eventable) => {
+ const aTime = "role" in a ? a.event.beginsOn : a.beginsOn;
+ const bTime = "role" in b ? b.event.beginsOn : b.beginsOn;
+ return new Date(aTime).getTime() - new Date(bTime).getTime();
+ });
return res.reduce((acc: Map, element: Eventable) => {
const month = new Date(
"role" in element ? element.event.beginsOn : element.beginsOn
diff --git a/src/views/Posts/EditView.vue b/src/views/Posts/EditView.vue
index db018434c..91564253b 100644
--- a/src/views/Posts/EditView.vue
+++ b/src/views/Posts/EditView.vue
@@ -195,6 +195,10 @@ onMounted(async () => {
pictureFile.value = await buildFileFromIMedia(post.value?.picture);
});
+// This is useful when post data is already cached from the API during navigation inside the app
+editablePost.value = { ...editablePost.value, ...post.value };
+
+// This watch() function is useful when post data loads directly from the API upon page load
watch(post, async (newPost: IPost | undefined, oldPost: IPost | undefined) => {
if (oldPost?.picture !== newPost?.picture) {
pictureFile.value = await buildFileFromIMedia(post.value?.picture);