Merge branch 'main' into '1481-trying-to-contact-the-organizer-contact-crashes-the-app'
# Conflicts: # package.json
This commit is contained in:
commit
320c40e511
|
@ -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())}
|
||||
|
|
|
@ -9,13 +9,9 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Media do
|
|||
alias Mobilizon.Federation.ActivityStream
|
||||
alias Mobilizon.Medias
|
||||
alias Mobilizon.Medias.Media, as: MediaModel
|
||||
|
||||
alias Mobilizon.Service.HTTP.RemoteMediaDownloaderClient
|
||||
alias Mobilizon.Web.Upload
|
||||
|
||||
@http_options [
|
||||
ssl: [{:versions, [:"tlsv1.2"]}]
|
||||
]
|
||||
|
||||
@doc """
|
||||
Convert a media struct to an ActivityStream representation.
|
||||
"""
|
||||
|
@ -65,7 +61,7 @@ defmodule Mobilizon.Federation.ActivityStream.Converter.Media do
|
|||
defp upload_media(media_url, ""), do: upload_media(media_url, "unknown")
|
||||
|
||||
defp upload_media(media_url, name) do
|
||||
case Tesla.get(media_url, opts: @http_options) do
|
||||
case RemoteMediaDownloaderClient.get(media_url) do
|
||||
{:ok, %{body: body}} ->
|
||||
case Upload.store(%{body: body, name: name}) do
|
||||
{:ok, %{url: _url} = uploaded} ->
|
||||
|
|
|
@ -16,7 +16,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"
|
||||
}
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
"@apollo/client": "^3.3.16",
|
||||
"@framasoft/socket": "^1.0.0",
|
||||
"@framasoft/socket-apollo-link": "^1.0.0",
|
||||
"@oruga-ui/oruga-next": "0.8.12",
|
||||
"@oruga-ui/oruga-next": "^0.8.10",
|
||||
"@oruga-ui/theme-oruga": "^0.2.0",
|
||||
"@fullcalendar/core": "^6.1.10",
|
||||
"@fullcalendar/daygrid": "^6.1.10",
|
||||
|
|
|
@ -2316,24 +2316,3 @@ msgstr ""
|
|||
"información na páxina <a href=\"/about/instance\">\"Acerca de esta "
|
||||
"instancia\"</a>."
|
||||
|
||||
#: lib/web/templates/api/terms.html.heex:55
|
||||
msgctxt "terms"
|
||||
msgid ""
|
||||
"When we say “we”, “our”, or “us” in this document, we are referring to the "
|
||||
"owners, operators and administrators of this Mobilizon instance. The "
|
||||
"Mobilizon software is provided by the team of Mobilizon contributors, "
|
||||
"supported by <a href=\"https://framasoft.org\">Framasoft</a>, a French not-"
|
||||
"for-profit organization advocating for Free/Libre Software. Unless "
|
||||
"explicitly stated, this Mobilizon instance is an independent service using "
|
||||
"Mobilizon's source code. You may find more information about this instance "
|
||||
"on the <a href=\"/about/instance\">\"About this instance\"</a> page."
|
||||
msgstr ""
|
||||
"Cando dicimos \"nós\", \"noso\" ou \"a nós\" neste documento, referímonos ás "
|
||||
"persoas donas, operadoras e administradoras desta instancia Mobilizon. O "
|
||||
"software Mobilizon está proporcionado polo equipo de colaboradoras de "
|
||||
"Mobilizon, coa axuda de <a href=\"https://framasoft.org\">Framasoft</a>, "
|
||||
"unha organización francesa sen ánimo de lucro que fomenta o Software Libre. "
|
||||
"A non ser que se indique o contrario, esta instancia Mobilizon é un servizo "
|
||||
"independente que está a usar o código fonte de Mobilizon. Podes atopar máis "
|
||||
"información sobre esta instancia na páxina <a href=\"/about/"
|
||||
"instance\">Acerca desta instancia</a>."
|
||||
|
|
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-11-25 07:56+0000\n"
|
||||
"PO-Revision-Date: 2024-03-08 17:59+0000\n"
|
||||
"PO-Revision-Date: 2024-04-25 13:45+0000\n"
|
||||
"Last-Translator: Milo Ivir <mail@milotype.de>\n"
|
||||
"Language-Team: Croatian <https://weblate.framasoft.org/projects/mobilizon/"
|
||||
"backend/hr/>\n"
|
||||
|
@ -11,9 +11,9 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.4.2\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Weblate 5.5\n"
|
||||
|
||||
#: lib/web/templates/email/password_reset.html.heex:66
|
||||
#, elixir-autogen, elixir-format
|
||||
|
@ -2192,7 +2192,13 @@ msgid "Well done!"
|
|||
msgstr ""
|
||||
|
||||
#: lib/web/templates/api/terms.html.heex:55
|
||||
#, elixir-autogen, elixir-format, fuzzy
|
||||
#, elixir-autogen, elixir-format
|
||||
msgctxt "terms"
|
||||
msgid "When we say “we”, “our”, or “us” in this document, we are referring to the owners, operators and administrators of this Mobilizon instance. The Mobilizon software is provided by the team of Mobilizon contributors. Unless explicitly stated, this Mobilizon instance is an independent service using Mobilizon's source code. You may find more information about this instance on the <a href=\"/about/instance\">\"About this instance\"</a> page."
|
||||
msgstr ""
|
||||
"Kada u ovom dokumentu kažemo „mi”, „naš” ili „nas”, mislimo na vlasnike, "
|
||||
"operatere i administratore ove Mobilizon instance. Softver Mobilizon "
|
||||
"osigurava tim dopinositelja Mobilizona. Ukoliko nije izričito navedeno, ova "
|
||||
"je Mobilizon instanca neovisna usluga koja koristi Mobilizonov izvorni kod. "
|
||||
"Više informacija o ovoj instanci se mogu pronaći na stranici <a href=\"/"
|
||||
"about/instance\">„O ovoj instanci”</a>."
|
||||
|
|
|
@ -3,7 +3,7 @@ msgstr ""
|
|||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2021-11-25 07:56+0000\n"
|
||||
"PO-Revision-Date: 2024-03-08 15:25+0000\n"
|
||||
"PO-Revision-Date: 2024-04-25 13:45+0000\n"
|
||||
"Last-Translator: Milo Ivir <mail@milotype.de>\n"
|
||||
"Language-Team: Croatian <https://weblate.framasoft.org/projects/mobilizon/"
|
||||
"backend-errors/hr/>\n"
|
||||
|
@ -11,9 +11,9 @@ msgstr ""
|
|||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.4.2\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
|
||||
"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
"X-Generator: Weblate 5.5\n"
|
||||
|
||||
## This file is a PO Template file.
|
||||
##
|
||||
|
@ -837,52 +837,52 @@ msgstr "Moraš biti prijavljen/a"
|
|||
#: lib/graphql/resolvers/member.ex:118
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You can't accept this invitation with this profile."
|
||||
msgstr ""
|
||||
msgstr "Ovu pozivnicu ne možeš prihvatiti s ovim profilom."
|
||||
|
||||
#: lib/graphql/resolvers/member.ex:139
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You can't reject this invitation with this profile."
|
||||
msgstr ""
|
||||
msgstr "Ovu pozivnicu ne možeš odbiti s ovim profilom."
|
||||
|
||||
#: lib/graphql/resolvers/media.ex:71
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "File doesn't have an allowed MIME type."
|
||||
msgstr ""
|
||||
msgstr "Datoteka nema dozvoljenu MIME vrstu."
|
||||
|
||||
#: lib/graphql/resolvers/group.ex:244
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "Profile is not administrator for the group"
|
||||
msgstr ""
|
||||
msgstr "Profil nije administrator za grupu"
|
||||
|
||||
#: lib/graphql/resolvers/event.ex:385
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You can't edit this event."
|
||||
msgstr ""
|
||||
msgstr "Ovaj događaj ne možeš urediti."
|
||||
|
||||
#: lib/graphql/resolvers/event.ex:388
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You can't attribute this event to this profile."
|
||||
msgstr ""
|
||||
msgstr "Ovaj događaj ne možeš pripisati ovom profilu."
|
||||
|
||||
#: lib/graphql/resolvers/member.ex:142
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This invitation doesn't exist."
|
||||
msgstr ""
|
||||
msgstr "Ova pozivnica ne postoji."
|
||||
|
||||
#: lib/graphql/resolvers/member.ex:217
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This member already has been rejected."
|
||||
msgstr ""
|
||||
msgstr "Ovaj je član već odbijen."
|
||||
|
||||
#: lib/graphql/resolvers/member.ex:241
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "You don't have the right to remove this member."
|
||||
msgstr ""
|
||||
msgstr "Nemaš prava za uklanjanje ovog člana."
|
||||
|
||||
#: lib/mobilizon/actors/actor.ex:385
|
||||
#, elixir-autogen, elixir-format
|
||||
msgid "This username is already taken."
|
||||
msgstr ""
|
||||
msgstr "Ovo je korisničko ime već zauzeto."
|
||||
|
||||
#: lib/graphql/resolvers/discussion.ex:81
|
||||
#, elixir-autogen, elixir-format
|
||||
|
|
|
@ -8,45 +8,52 @@
|
|||
## to merge POT files into PO files.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2024-05-14 22:26+0000\n"
|
||||
"Last-Translator: Coen Holten <coenholten@proton.me>\n"
|
||||
"Language-Team: Dutch <https://weblate.framasoft.org/projects/mobilizon/"
|
||||
"backend-errors/nl/>\n"
|
||||
"Language: nl\n"
|
||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
"X-Generator: Weblate 5.5.5\n"
|
||||
|
||||
#: lib/mobilizon/discussions/discussion.ex:68
|
||||
#, elixir-autogen
|
||||
msgid "can't be blank"
|
||||
msgstr ""
|
||||
msgstr "kan niet leeg zijn"
|
||||
|
||||
msgid "has already been taken"
|
||||
msgstr ""
|
||||
msgstr "is al bezet"
|
||||
|
||||
msgid "is invalid"
|
||||
msgstr ""
|
||||
msgstr "is ongeldig"
|
||||
|
||||
msgid "must be accepted"
|
||||
msgstr ""
|
||||
msgstr "moet worden geaccepteerd"
|
||||
|
||||
msgid "has invalid format"
|
||||
msgstr ""
|
||||
msgstr "heeft ongeldig formaat"
|
||||
|
||||
msgid "has an invalid entry"
|
||||
msgstr ""
|
||||
msgstr "heeft een ongeldige invoer"
|
||||
|
||||
msgid "is reserved"
|
||||
msgstr ""
|
||||
msgstr "is gereserveerd"
|
||||
|
||||
msgid "does not match confirmation"
|
||||
msgstr ""
|
||||
msgstr "komt niet overeen met bevestiging"
|
||||
|
||||
msgid "is still associated with this entry"
|
||||
msgstr ""
|
||||
msgstr "is nog steeds gekoppeld aan deze invoer"
|
||||
|
||||
msgid "are still associated with this entry"
|
||||
msgstr ""
|
||||
msgstr "zijn nog steeds verbonden met deze invoer"
|
||||
|
||||
msgid "should be %{count} character(s)"
|
||||
msgid_plural "should be %{count} character(s)"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
msgstr[0] "moet %{count} karakter zijn"
|
||||
msgstr[1] "moet %{count} karakter(s) zijn"
|
||||
|
||||
msgid "should have %{count} item(s)"
|
||||
msgid_plural "should have %{count} item(s)"
|
||||
|
|
|
@ -22,7 +22,12 @@
|
|||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
import { computed, watch } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { locale } = useI18n({ useScope: "global" });
|
||||
|
||||
const localeConverted = locale.replace("_", "-");
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
|
@ -35,15 +40,15 @@ const props = withDefaults(
|
|||
const dateObj = computed<Date>(() => new Date(props.date));
|
||||
|
||||
const month = computed<string>(() =>
|
||||
dateObj.value.toLocaleString(undefined, { month: "short" })
|
||||
dateObj.value.toLocaleString(localeConverted, { month: "short" })
|
||||
);
|
||||
|
||||
const day = computed<string>(() =>
|
||||
dateObj.value.toLocaleString(undefined, { day: "numeric" })
|
||||
dateObj.value.toLocaleString(localeConverted, { day: "numeric" })
|
||||
);
|
||||
|
||||
const weekday = computed<string>(() =>
|
||||
dateObj.value.toLocaleString(undefined, { weekday: "short" })
|
||||
dateObj.value.toLocaleString(localeConverted, { weekday: "short" })
|
||||
);
|
||||
|
||||
const smallStyle = computed<string>(() => (props.small ? "1.2" : "2"));
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
<div class="flex-1" v-else>
|
||||
{{ `@${selectedActor.preferredUsername}` }}
|
||||
</div>
|
||||
<o-button type="text" @click="isComponentModalActive = true">
|
||||
<o-button @click="isComponentModalActive = true">
|
||||
{{ $t("Change") }}
|
||||
</o-button>
|
||||
</div>
|
||||
|
|
|
@ -13,8 +13,14 @@
|
|||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { computed } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
import Clock from "vue-material-design-icons/ClockTimeTenOutline.vue";
|
||||
|
||||
const { locale } = useI18n({ useScope: "global" });
|
||||
|
||||
const localeConverted = locale.replace("_", "-");
|
||||
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
date: string;
|
||||
|
@ -26,7 +32,7 @@ const props = withDefaults(
|
|||
const dateObj = computed<Date>(() => new Date(props.date));
|
||||
|
||||
const time = computed<string>(() =>
|
||||
dateObj.value.toLocaleTimeString(undefined, {
|
||||
dateObj.value.toLocaleTimeString(localeConverted, {
|
||||
hour: "2-digit",
|
||||
minute: "2-digit",
|
||||
})
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
</template>
|
||||
<o-taginput
|
||||
:modelValue="tagsStrings"
|
||||
@update:modelValue="updateTags"
|
||||
@remove="remove"
|
||||
@add="add"
|
||||
:data="filteredTags"
|
||||
:allow-autocomplete="true"
|
||||
:allow-new="true"
|
||||
|
@ -69,6 +70,8 @@ const id = computed((): string => {
|
|||
|
||||
const { load: fetchTags } = useFetchTags();
|
||||
|
||||
initTagsStringsValue();
|
||||
|
||||
const getFilteredTags = async (newText: string): Promise<void> => {
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -33,16 +33,16 @@
|
|||
"A resource has been created or updated": "Creouse ou actualizouse un recurso",
|
||||
"A short tagline for your instance homepage. Defaults to \"Gather ⋅ Organize ⋅ Mobilize\"": "Un pequeno subtítulo para o inicio da instancia. Por omisión \"Xuntar ⋅ Organizar ⋅ Mobilizar\"",
|
||||
"A twitter account handle to follow for event updates": "Alcume da conta de twitter para seguir actualizacións do evento",
|
||||
"A user-friendly, emancipatory and ethical tool for gathering, organising, and mobilising.": "Unha ferramenta amigable, emancipatoria e ética para xuntar, organizr e mobilizar.",
|
||||
"A user-friendly, emancipatory and ethical tool for gathering, organising, and mobilising.": "Unha ferramenta amigábel, emancipadora e ética para xuntar, organizar e mobilizar.",
|
||||
"A validation email was sent to {email}": "Enviouse un correo de validación a {email}",
|
||||
"API": "API",
|
||||
"Abandon editing": "Saír da edición",
|
||||
"About": "Acerca de",
|
||||
"About Mobilizon": "Acerca de Mobilizon",
|
||||
"About": "Sobre",
|
||||
"About Mobilizon": "Sobre Mobilizon",
|
||||
"About anonymous participation": "Acerca da participación anónima",
|
||||
"About instance": "Acerca da instancia",
|
||||
"About this event": "Acerca deste evento",
|
||||
"About this instance": "Acerca desta instancia",
|
||||
"About this event": "Sobre este evento",
|
||||
"About this instance": "Sobre esta instancia",
|
||||
"About {instance}": "Acerca de {instance}",
|
||||
"Accept": "Aceptar",
|
||||
"Accept follow": "Aceptar seguimento",
|
||||
|
@ -873,7 +873,7 @@
|
|||
"Please add as many details as possible to help identify the problem.": "Por favor engade tódolos detalles posibles para axudarnos a identificar o problema.",
|
||||
"Please check your spam folder if you didn't receive the email.": "Comproba o cartafol de spam se non recibiches o correo.",
|
||||
"Please contact this instance's Mobilizon admin if you think this is a mistake.": "Contacta coa administración da instancia Mobilizon se cres que é un erro.",
|
||||
"Please do not use it in any real way.": "Non o utilices para eventos reais.",
|
||||
"Please do not use it in any real way.": "Non o utilice para eventos reais.",
|
||||
"Please enter your password to confirm this action.": "Escribe o teu contrasinal para confirmar a acción.",
|
||||
"Please make sure the address is correct and that the page hasn't been moved.": "Comproba ben o enderezo e que a páxina non foi movida a outro lugar.",
|
||||
"Please read the {fullRules} published by {instance}'s administrators.": "Por favor le as {fullRules} publicadas pola administración de {instance}.",
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
"Access group memberships": "Pristupi članstvima grupa",
|
||||
"Access group suggested events": "Pristupi predloženim grupnim događajima",
|
||||
"Access group todo-lists": "Pristupi popisu grupnih zadataka",
|
||||
"Access group todo-lists": "Pristupi popisu zadataka grupe",
|
||||
"Access organized events": "Pristupi organiziranim događajima",
|
||||
"Access participations": "Pristupi sudjelovanjima",
|
||||
"Access your group's resources": "Pristupi resursima tvoje grupe",
|
||||
|
|
420
src/i18n/nl.json
420
src/i18n/nl.json
File diff suppressed because it is too large
Load Diff
|
@ -271,6 +271,7 @@
|
|||
>
|
||||
<template #default>
|
||||
<event-map
|
||||
v-if="showMap"
|
||||
:routingType="routingType ?? RoutingType.OPENSTREETMAP"
|
||||
:address="event.physicalAddress"
|
||||
@close="showMap = false"
|
||||
|
|
|
@ -23,10 +23,27 @@
|
|||
<div
|
||||
class="rounded p-3 flex-auto md:flex-none bg-zinc-300 dark:bg-zinc-700"
|
||||
>
|
||||
<o-field>
|
||||
<o-switch v-model="showUpcoming">{{
|
||||
showUpcoming ? t("Upcoming events") : t("Past events")
|
||||
}}</o-switch>
|
||||
<o-field
|
||||
class="date-filter"
|
||||
expanded
|
||||
:label="
|
||||
showUpcoming
|
||||
? t('Showing events starting on')
|
||||
: t('Showing events before')
|
||||
"
|
||||
labelFor="events-start-datepicker"
|
||||
>
|
||||
<o-datepicker
|
||||
v-model="datePick"
|
||||
:first-day-of-week="firstDayOfWeek"
|
||||
id="events-start-datepicker"
|
||||
/>
|
||||
<o-button
|
||||
@click="datePick = new Date()"
|
||||
class="reset-area !h-auto"
|
||||
icon-left="close"
|
||||
:title="t('Clear date filter field')"
|
||||
/>
|
||||
</o-field>
|
||||
<o-field v-if="showUpcoming">
|
||||
<o-checkbox v-model="showDrafts">{{ t("Drafts") }}</o-checkbox>
|
||||
|
@ -50,28 +67,6 @@
|
|||
)
|
||||
}}
|
||||
</p>
|
||||
<o-field
|
||||
class="date-filter"
|
||||
expanded
|
||||
:label="
|
||||
showUpcoming
|
||||
? t('Showing events starting on')
|
||||
: t('Showing events before')
|
||||
"
|
||||
labelFor="events-start-datepicker"
|
||||
>
|
||||
<o-datepicker
|
||||
v-model="dateFilter"
|
||||
:first-day-of-week="firstDayOfWeek"
|
||||
id="events-start-datepicker"
|
||||
/>
|
||||
<o-button
|
||||
@click="dateFilter = new Date()"
|
||||
class="reset-area !h-auto"
|
||||
icon-left="close"
|
||||
:title="t('Clear date filter field')"
|
||||
/>
|
||||
</o-field>
|
||||
</div>
|
||||
<div class="flex-1 min-w-[300px]">
|
||||
<section
|
||||
|
@ -250,27 +245,43 @@ const futurePage = ref(1);
|
|||
const pastPage = ref(1);
|
||||
const limit = ref(10);
|
||||
|
||||
function startOfDay(d: Date): string {
|
||||
const pad = (n: int): string => {
|
||||
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<string, Eventable[]> => {
|
||||
const monthlyEvents = (elements: Eventable[]): Map<string, Eventable[]> => {
|
||||
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<string, Eventable[]>, element: Eventable) => {
|
||||
const month = new Date(
|
||||
"role" in element ? element.event.beginsOn : element.beginsOn
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue