Merge remote-tracking branch 'origin/main'

This commit is contained in:
778a69cd 2023-12-05 17:41:28 +01:00
commit daf33b747c
15 changed files with 157 additions and 103 deletions

View file

@ -5,6 +5,50 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## 4.0.0 (2023-12-05)
### Breaking changes
#### Release (binary package) installations
- We now produce packages for different distributions targets (Debian Bookworm, Debian Bullseye, Ubuntu Jammy, Ubuntu Focal, Ubuntu Bionic, Fedora 38 and Fedora 39). Be sure to pick the right one for your system, as there can be issues with OpenSSL versions differing from inside the Mobilizon package and on your system.
- The `https://joinmobilizon.org/latest-package` URL now links to the latest package builded against Debian Bookworm. Make sure to follow the documentation if you're not using this.
- There's also an `arm64` package build on Debian Bullseye for now.
#### Source installations
- Elixir 15 is now required
- The content of the `js` directory is now at the root of the repository, so you don't need to `cd js` anymore
- No need for `yarn` anymore, simply use `npm` instead for `npm i` and `npm run build`
### New features
- Event organizers and groups can be contacted through private messages (including PMs from 3rd-party micro-blogging fediverse services)
- Event organizers can send private announcements to event participants (approved or not)
### Improvements
- Anonymous participation e-mails now contain links to cancel your participation
- ActivityPub improvements for compatibility with https://event-federation.eu
- ICS export fixes for descriptions and adding event status
### Changes since 4.0.0-rc.1
* refactor: to lower cyclomatic complexity ([147096c](https://framagit.org/framasoft/mobilizon/commits/147096c))
* fix(activitypub): compact ical:status in activitystream data ([5e8f9af](https://framagit.org/framasoft/mobilizon/commits/5e8f9af)), closes [#1378](https://framagit.org/framasoft/mobilizon/issues/1378)
* fix(activitypub): fix receiving comments ([f1084c1](https://framagit.org/framasoft/mobilizon/commits/f1084c1))
* fix(backend): handle ecto errors when fetching and create entities ([89d1ee4](https://framagit.org/framasoft/mobilizon/commits/89d1ee4))
* fix(front): fix tag loading ([f81472e](https://framagit.org/framasoft/mobilizon/commits/f81472e))
* fix(front): make recipient field placeholder translatable ([10ce812](https://framagit.org/framasoft/mobilizon/commits/10ce812))
* fix(front): only show participants & announcements menu items to organizers ([c4d2ec6](https://framagit.org/framasoft/mobilizon/commits/c4d2ec6))
* Translated using Weblate (Croatian) ([a26ff98](https://framagit.org/framasoft/mobilizon/commits/a26ff98))
* Translated using Weblate (Croatian) ([1683f01](https://framagit.org/framasoft/mobilizon/commits/1683f01))
* Translated using Weblate (Croatian) ([aa7f870](https://framagit.org/framasoft/mobilizon/commits/aa7f870))
* Translated using Weblate (Croatian) ([1ce34ea](https://framagit.org/framasoft/mobilizon/commits/1ce34ea))
* Translated using Weblate (Croatian) ([5e7edc0](https://framagit.org/framasoft/mobilizon/commits/5e7edc0))
* Translated using Weblate (Croatian) ([d777d88](https://framagit.org/framasoft/mobilizon/commits/d777d88))
* Translated using Weblate (Croatian) ([0118d97](https://framagit.org/framasoft/mobilizon/commits/0118d97))
* Translated using Weblate (Croatian) ([805e931](https://framagit.org/framasoft/mobilizon/commits/805e931))
## 4.0.0-rc.1 (2023-12-04) ## 4.0.0-rc.1 (2023-12-04)
* fix: prevent sending group physical address if it's empty and allow empty text for timezone ([32caebb](https://framagit.org/framasoft/mobilizon/commits/32caebb)), closes [#1357](https://framagit.org/framasoft/mobilizon/issues/1357) * fix: prevent sending group physical address if it's empty and allow empty text for timezone ([32caebb](https://framagit.org/framasoft/mobilizon/commits/32caebb)), closes [#1357](https://framagit.org/framasoft/mobilizon/issues/1357)

View file

@ -42,28 +42,12 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
end end
@spec fetch_and_create(String.t(), Keyword.t()) :: @spec fetch_and_create(String.t(), Keyword.t()) ::
{:ok, map(), struct()} | {:error, atom()} | :error {:ok, map(), struct()} | {:error, atom()} | {:error, Ecto.Changeset.t()} | :error
def fetch_and_create(url, options \\ []) do def fetch_and_create(url, options \\ []) do
case fetch(url, options) do case fetch(url, options) do
{:ok, data} when is_map(data) -> {:ok, data} when is_map(data) ->
if origin_check?(url, data) do if origin_check?(url, data) do
case Transmogrifier.handle_incoming(%{ pass_to_transmogrifier(data)
"type" => "Create",
"to" => data["to"],
"cc" => data["cc"],
"actor" => data["actor"] || data["attributedTo"],
"attributedTo" => data["attributedTo"] || data["actor"],
"object" => data
}) do
{:ok, entity, structure} ->
{:ok, entity, structure}
{:error, error} when is_atom(error) ->
{:error, error}
:error ->
{:error, :transmogrifier_error}
end
else else
Logger.warning("Object origin check failed") Logger.warning("Object origin check failed")
{:error, :object_origin_check_failed} {:error, :object_origin_check_failed}
@ -98,6 +82,34 @@ defmodule Mobilizon.Federation.ActivityPub.Fetcher do
end end
end end
@spec pass_to_transmogrifier(map()) ::
{:ok, map(), struct()}
| {:error, atom()}
| {:error, Ecto.Changeset.t()}
| {:error, :transmogrifier_error}
defp pass_to_transmogrifier(data) do
case Transmogrifier.handle_incoming(%{
"type" => "Create",
"to" => data["to"],
"cc" => data["cc"],
"actor" => data["actor"] || data["attributedTo"],
"attributedTo" => data["attributedTo"] || data["actor"],
"object" => data
}) do
{:ok, entity, structure} ->
{:ok, entity, structure}
{:error, error} when is_atom(error) ->
{:error, error}
{:error, %Ecto.Changeset{} = err} ->
{:error, err}
:error ->
{:error, :transmogrifier_error}
end
end
@type fetch_actor_errors :: @type fetch_actor_errors ::
:json_decode_error | :actor_deleted | :http_error | :actor_not_allowed_type :json_decode_error | :actor_deleted | :http_error | :actor_not_allowed_type

View file

@ -76,12 +76,10 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
Actions.Create.create(:conversation, object_data, false) Actions.Create.create(:conversation, object_data, false)
object_data when is_map(object_data) -> object_data when is_map(object_data) ->
case Discussions.get_comment_from_url_with_preload(object_data.url) do handle_comment_or_discussion(object_data)
{:error, :comment_not_found} ->
object_data {:error, err} ->
|> transform_object_data_for_discussion() {:error, err}
|> save_comment_or_discussion()
end
end end
{:ok, %Comment{} = comment} -> {:ok, %Comment{} = comment} ->
@ -1019,6 +1017,19 @@ defmodule Mobilizon.Federation.ActivityPub.Transmogrifier do
is_nil(object_data.title) or object_data.title == "" is_nil(object_data.title) or object_data.title == ""
end end
defp handle_comment_or_discussion(object_data) do
case Discussions.get_comment_from_url_with_preload(object_data.url) do
{:error, :comment_not_found} ->
object_data
|> transform_object_data_for_discussion()
|> save_comment_or_discussion()
{:ok, %Comment{} = comment} ->
# Object already exists
{:ok, nil, comment}
end
end
# Comment and conversations have different attributes for actor and groups # Comment and conversations have different attributes for actor and groups
@spec transform_object_data_for_discussion(map()) :: map() @spec transform_object_data_for_discussion(map()) :: map()
defp transform_object_data_for_discussion(object_data) do defp transform_object_data_for_discussion(object_data) do

View file

@ -1,7 +1,7 @@
defmodule Mobilizon.Mixfile do defmodule Mobilizon.Mixfile do
use Mix.Project use Mix.Project
@version "4.0.0-rc.1" @version "4.0.0"
def project do def project do
[ [

View file

@ -1,6 +1,6 @@
{ {
"name": "mobilizon", "name": "mobilizon",
"version": "4.0.0-rc.1", "version": "4.0.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-25 07:55+0000\n" "POT-Creation-Date: 2021-11-25 07:55+0000\n"
"PO-Revision-Date: 2022-10-23 23:00+0000\n" "PO-Revision-Date: 2023-12-04 18:10+0000\n"
"Last-Translator: Milo Ivir <mail@milotype.de>\n" "Last-Translator: Milo Ivir <mail@milotype.de>\n"
"Language-Team: Croatian <https://weblate.framasoft.org/projects/mobilizon/" "Language-Team: Croatian <https://weblate.framasoft.org/projects/mobilizon/"
"activity/hr/>\n" "activity/hr/>\n"
@ -11,9 +11,9 @@ msgstr ""
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.14.1\n" "X-Generator: Weblate 5.2.1\n"
## This file is a PO Template file. ## This file is a PO Template file.
## ##
@ -486,73 +486,77 @@ msgstr "%{profile} su odobrili člana %{member}."
#: lib/web/templates/email/activity/_event_activity_item.text.eex:31 #: lib/web/templates/email/activity/_event_activity_item.text.eex:31
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "%{profile} joined your event %{event}." msgid "%{profile} joined your event %{event}."
msgstr "" msgstr "%{profile} se pridružio/la tvom događaju %{event}."
#: lib/web/views/email_view.ex:61 #: lib/web/views/email_view.ex:61
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "An anonymous profile" msgid "An anonymous profile"
msgstr "" msgstr "Anonimni profil"
#: lib/web/templates/email/email_anonymous_activity.html.heex:107 #: lib/web/templates/email/email_anonymous_activity.html.heex:107
#: lib/web/templates/email/email_anonymous_activity.text.eex:14 #: lib/web/templates/email/email_anonymous_activity.text.eex:14
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format
msgid "%{profile} has posted a private announcement about event %{event}." msgid "%{profile} has posted a private announcement about event %{event}."
msgstr "%{profile} su objavili najavu za događaj %{event}." msgstr "%{profile} je objavio/la privatnu najavu za događaj %{event}."
#: lib/web/templates/email/email_anonymous_activity.html.heex:50 #: lib/web/templates/email/email_anonymous_activity.html.heex:50
#: lib/web/templates/email/email_anonymous_activity.text.eex:6 #: lib/web/templates/email/email_anonymous_activity.text.eex:6
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format
msgid "%{profile} has posted a public announcement under event %{event}." msgid "%{profile} has posted a public announcement under event %{event}."
msgstr "%{profile} su objavili najavu za događaj %{event}." msgstr "%{profile} je objavio/la javnu najavu za događaj %{event}."
#: lib/web/templates/email/activity/_conversation_activity_item.html.heex:3 #: lib/web/templates/email/activity/_conversation_activity_item.html.heex:3
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format
msgid "%{profile} mentionned you in a %{conversation}." msgid "%{profile} mentionned you in a %{conversation}."
msgstr "%{profile} su vas spomenuli u komentaru događaja %{event}." msgstr "%{profile} te je spomenuo/la u konverzaciji %{conversation}."
#: lib/web/templates/email/activity/_conversation_activity_item.text.eex:1 #: lib/web/templates/email/activity/_conversation_activity_item.text.eex:1
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format
msgid "%{profile} mentionned you in a conversation." msgid "%{profile} mentionned you in a conversation."
msgstr "%{profile} su vas spomenuli u komentaru događaja %{event}." msgstr "%{profile} te je spomenuo/la u jednoj konverzaciji."
#: lib/service/activity/renderer/conversation.ex:36 #: lib/service/activity/renderer/conversation.ex:36
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "%{profile} replied to your message" msgid "%{profile} replied to your message"
msgstr "" msgstr "%{profile} je odgovorio/la na tvoju poruku"
#: lib/web/templates/email/activity/_conversation_activity_item.html.heex:10 #: lib/web/templates/email/activity/_conversation_activity_item.html.heex:10
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format
msgid "%{profile} replied you in a %{conversation}." msgid "%{profile} replied you in a %{conversation}."
msgstr "%{profile} su odgovorili na razgovor %{discussion}." msgstr "%{profile} ti je odgovorio/la u jednoj %{conversation}."
#: lib/web/templates/email/activity/_conversation_activity_item.text.eex:6 #: lib/web/templates/email/activity/_conversation_activity_item.text.eex:6
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "%{profile} replied you in a conversation." msgid "%{profile} replied you in a conversation."
msgstr "" msgstr "%{profile} ti je odgovorio/la u jednoj konverzaciji."
#: lib/service/activity/renderer/conversation.ex:49 #: lib/service/activity/renderer/conversation.ex:49
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "%{profile} sent a private message about event %{event}" msgid "%{profile} sent a private message about event %{event}"
msgstr "" msgstr "%{profile} je poslao/la privatnu poruku o događaju %{event}"
#: lib/service/activity/renderer/conversation.ex:23 #: lib/service/activity/renderer/conversation.ex:23
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "%{profile} sent you a message" msgid "%{profile} sent you a message"
msgstr "" msgstr "%{profile} ti je poslao/la poruku"
#: lib/web/email/activity.ex:52 #: lib/web/email/activity.ex:52
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Informations about your event %{event}" msgid "Informations about your event %{event}"
msgstr "" msgstr "Informacije o tvom događaju %{event}"
#: lib/web/templates/email/email_anonymous_activity.html.heex:118 #: lib/web/templates/email/email_anonymous_activity.html.heex:118
#: lib/web/templates/email/email_anonymous_activity.text.eex:20 #: lib/web/templates/email/email_anonymous_activity.text.eex:20
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "It might give details on how to join the event, so make sure to read it appropriately." msgid "It might give details on how to join the event, so make sure to read it appropriately."
msgstr "" msgstr ""
"Može sadržavati pojedinosti o tome kako se pridružiti događaju, stoga ga "
"svakako pročitaj."
#: lib/web/templates/email/email_anonymous_activity.html.heex:156 #: lib/web/templates/email/email_anonymous_activity.html.heex:156
#: lib/web/templates/email/email_anonymous_activity.text.eex:28 #: lib/web/templates/email/email_anonymous_activity.text.eex:28
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "This information is sent privately to you as a person who registered for this event. Share the informations above with other people with caution." msgid "This information is sent privately to you as a person who registered for this event. Share the informations above with other people with caution."
msgstr "" msgstr ""
"Ove informacije se šalju privatno tebi kao osobi koja se prijavila za ovaj "
"događaj. Dijeli gore navedene informacije s drugima s oprezom."

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-25 07:56+0000\n" "POT-Creation-Date: 2021-11-25 07:56+0000\n"
"PO-Revision-Date: 2023-05-27 13:05+0000\n" "PO-Revision-Date: 2023-12-04 18:10+0000\n"
"Last-Translator: Milo Ivir <mail@milotype.de>\n" "Last-Translator: Milo Ivir <mail@milotype.de>\n"
"Language-Team: Croatian <https://weblate.framasoft.org/projects/mobilizon/" "Language-Team: Croatian <https://weblate.framasoft.org/projects/mobilizon/"
"backend/hr/>\n" "backend/hr/>\n"
@ -13,7 +13,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "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" "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.17\n" "X-Generator: Weblate 5.2.1\n"
#: lib/web/templates/email/password_reset.html.heex:66 #: lib/web/templates/email/password_reset.html.heex:66
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
@ -1451,7 +1451,7 @@ msgstr ""
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Your instance's moderation team has decided to suspend <b>%{group_name}</b> (%{group_address}). You are no longer a member of this group." msgid "Your instance's moderation team has decided to suspend <b>%{group_name}</b> (%{group_address}). You are no longer a member of this group."
msgstr "" msgstr ""
"Tim za moderiranje tvoje instance je odlučio suspendirati grupu " "Tim za moderiranje tvoje instance je odlučio suspendiratigrupu "
"<b>%{group_name}</b> (%{group_address}). Više nisi član ove grupe." "<b>%{group_name}</b> (%{group_address}). Više nisi član ove grupe."
#: lib/web/templates/email/actor_suspension_participants.html.heex:18 #: lib/web/templates/email/actor_suspension_participants.html.heex:18
@ -2105,9 +2105,9 @@ msgid "As this group was located on this instance, all of its data has been irre
msgstr "" msgstr ""
#: lib/web/templates/email/report.text.eex:11 #: lib/web/templates/email/report.text.eex:11
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format
msgid "Events" msgid "Events"
msgstr "Događaj" msgstr "Događaji"
#: lib/web/templates/email/report.html.heex:115 #: lib/web/templates/email/report.html.heex:115
#, elixir-autogen, elixir-format, fuzzy #, elixir-autogen, elixir-format, fuzzy

View file

@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: PACKAGE VERSION\n" "Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2021-11-25 07:56+0000\n" "POT-Creation-Date: 2021-11-25 07:56+0000\n"
"PO-Revision-Date: 2023-04-11 18:20+0000\n" "PO-Revision-Date: 2023-12-04 18:30+0000\n"
"Last-Translator: Milo Ivir <mail@milotype.de>\n" "Last-Translator: Milo Ivir <mail@milotype.de>\n"
"Language-Team: Croatian <https://weblate.framasoft.org/projects/mobilizon/" "Language-Team: Croatian <https://weblate.framasoft.org/projects/mobilizon/"
"backend-errors/hr/>\n" "backend-errors/hr/>\n"
@ -13,7 +13,7 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && " "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" "n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Generator: Weblate 4.16.4\n" "X-Generator: Weblate 5.2.1\n"
## This file is a PO Template file. ## This file is a PO Template file.
## ##
@ -1427,7 +1427,7 @@ msgstr ""
#: lib/graphql/resolvers/conversation.ex:161 #: lib/graphql/resolvers/conversation.ex:161
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format
msgid "Conversation needs to mention at least one participant that's not yourself" msgid "Conversation needs to mention at least one participant that's not yourself"
msgstr "" msgstr "Konverzacija treba spomenuti barem jednog sudionika koji nisi ti"
#: lib/graphql/resolvers/participant.ex:396 #: lib/graphql/resolvers/participant.ex:396
#, elixir-autogen, elixir-format #, elixir-autogen, elixir-format

View file

@ -107,11 +107,7 @@
{{ t("Actions") }} {{ t("Actions") }}
</o-button> </o-button>
</template> </template>
<o-dropdown-item <o-dropdown-item aria-role="listitem" has-link v-if="canManageEvent">
aria-role="listitem"
has-link
v-if="canManageEvent || !event?.draft"
>
<router-link <router-link
class="flex gap-1" class="flex gap-1"
:to="{ :to="{
@ -123,11 +119,7 @@
{{ t("Participations") }} {{ t("Participations") }}
</router-link> </router-link>
</o-dropdown-item> </o-dropdown-item>
<o-dropdown-item <o-dropdown-item aria-role="listitem" has-link v-if="canManageEvent">
aria-role="listitem"
has-link
v-if="canManageEvent || !event?.draft"
>
<router-link <router-link
class="flex gap-1" class="flex gap-1"
:to="{ :to="{

View file

@ -1,7 +1,7 @@
<template> <template>
<Story> <Story>
<Variant title="new"> <Variant title="new">
<TagInput v-model="tags" :fetch-tags="fetchTags" /> <TagInput v-model="tags" />
</Variant> </Variant>
<!-- <Variant title="small"> <!-- <Variant title="small">
<TagInput v-model="tags" /> <TagInput v-model="tags" />
@ -15,9 +15,4 @@ import { reactive } from "vue";
import TagInput from "./TagInput.vue"; import TagInput from "./TagInput.vue";
const tags = reactive<ITag[]>([{ title: "Hello", slug: "hello" }]); const tags = reactive<ITag[]>([{ title: "Hello", slug: "hello" }]);
const fetchTags = async () =>
new Promise<ITag[]>((resolve) => {
resolve([{ title: "Welcome", slug: "welcome" }]);
});
</script> </script>

View file

@ -34,10 +34,11 @@ import { ITag } from "../../types/tag.model";
import debounce from "lodash/debounce"; import debounce from "lodash/debounce";
import { computed, onBeforeMount, ref } from "vue"; import { computed, onBeforeMount, ref } from "vue";
import HelpCircleOutline from "vue-material-design-icons/HelpCircleOutline.vue"; import HelpCircleOutline from "vue-material-design-icons/HelpCircleOutline.vue";
import { useFetchTags } from "@/composition/apollo/tags";
import { FILTER_TAGS } from "@/graphql/tags";
const props = defineProps<{ const props = defineProps<{
modelValue: ITag[]; modelValue: ITag[];
fetchTags: (text: string) => Promise<ITag[]>;
}>(); }>();
const emit = defineEmits(["update:modelValue"]); const emit = defineEmits(["update:modelValue"]);
@ -56,9 +57,14 @@ const id = computed((): string => {
return `tag-input-${componentId}`; return `tag-input-${componentId}`;
}); });
const { load: fetchTags } = useFetchTags();
const getFilteredTags = async (newText: string): Promise<void> => { const getFilteredTags = async (newText: string): Promise<void> => {
text.value = newText; text.value = newText;
tags.value = await props.fetchTags(newText); const res = await fetchTags(FILTER_TAGS, { filter: newText });
if (res) {
tags.value = res.tags;
}
}; };
const debouncedGetFilteredTags = debounce(getFilteredTags, 200); const debouncedGetFilteredTags = debounce(getFilteredTags, 200);

View file

@ -1,24 +1,7 @@
import { FILTER_TAGS } from "@/graphql/tags"; import { FILTER_TAGS } from "@/graphql/tags";
import { ITag } from "@/types/tag.model"; import { ITag } from "@/types/tag.model";
import { apolloClient } from "@/vue-apollo"; import { useLazyQuery } from "@vue/apollo-composable";
import { provideApolloClient, useLazyQuery } from "@vue/apollo-composable";
export async function fetchTags(text: string): Promise<ITag[]> { export function useFetchTags() {
try { return useLazyQuery<{ tags: ITag[] }, { filter: string }>(FILTER_TAGS);
const { load: loadFetchTagsQuery } = useLazyQuery<
{ tags: ITag[] },
{ filter: string }
>(FILTER_TAGS);
const res = await provideApolloClient(apolloClient)(() =>
loadFetchTagsQuery(FILTER_TAGS, {
filter: text,
})
);
if (!res) return [];
return res.tags;
} catch (e) {
console.error(e);
return [];
}
} }

View file

@ -124,6 +124,7 @@
"Are you sure you want to cancel the event creation? You'll lose all modifications.": "Jeste li sigurni da želite poništiti stvaranje događaja? Izgubiti ćete sve izmjene.", "Are you sure you want to cancel the event creation? You'll lose all modifications.": "Jeste li sigurni da želite poništiti stvaranje događaja? Izgubiti ćete sve izmjene.",
"Are you sure you want to cancel the event edition? You'll lose all modifications.": "Jeste li sigurni da želite poništiti uređivanje događaja? Izgubiti ćete sve izmjene.", "Are you sure you want to cancel the event edition? You'll lose all modifications.": "Jeste li sigurni da želite poništiti uređivanje događaja? Izgubiti ćete sve izmjene.",
"Are you sure you want to cancel your participation at event \"{title}\"?": "Jeste li sigurni da ne želite više sudjelovati u događaju \"{title}\"?", "Are you sure you want to cancel your participation at event \"{title}\"?": "Jeste li sigurni da ne želite više sudjelovati u događaju \"{title}\"?",
"Are you sure you want to delete this entire conversation?": "Stvarno želiš izbrisati ovu cijelu konverzaciju?",
"Are you sure you want to delete this entire discussion?": "Jeste li sigurni da želite izbrisati cijeli razgovor?", "Are you sure you want to delete this entire discussion?": "Jeste li sigurni da želite izbrisati cijeli razgovor?",
"Are you sure you want to delete this event? This action cannot be reverted.": "Jeste li sigurni da želite izbrisati ovaj događaj? Nećete moći poništiti ovu odluku.", "Are you sure you want to delete this event? This action cannot be reverted.": "Jeste li sigurni da želite izbrisati ovaj događaj? Nećete moći poništiti ovu odluku.",
"Are you sure you want to delete this post? This action cannot be reverted.": "Stvarno želiš izbrisati ovaj događaj? Ovo je nepovratna radnja.", "Are you sure you want to delete this post? This action cannot be reverted.": "Stvarno želiš izbrisati ovaj događaj? Ovo je nepovratna radnja.",
@ -199,6 +200,7 @@
"Closed": "Zatvoreno", "Closed": "Zatvoreno",
"Comment body": "Tekst komentara", "Comment body": "Tekst komentara",
"Comment deleted": "Komentar obrisan", "Comment deleted": "Komentar obrisan",
"Comment from a private conversation": "Komentiraj iz privatne konverzacije",
"Comment from {'@'}{username} reported": "Komentar od {'@'}{username} prijavljen", "Comment from {'@'}{username} reported": "Komentar od {'@'}{username} prijavljen",
"Comment text can't be empty": "Komentar ne smije biti prazan", "Comment text can't be empty": "Komentar ne smije biti prazan",
"Comments": "Komentari", "Comments": "Komentari",
@ -214,6 +216,8 @@
"Congratulations, your account is now created!": "Čestitke, kreirali ste račun!", "Congratulations, your account is now created!": "Čestitke, kreirali ste račun!",
"Contact": "Kontaktiraj", "Contact": "Kontaktiraj",
"Continue editing": "Nastavi uređivanje", "Continue editing": "Nastavi uređivanje",
"Conversation with {participants}": "Konverzacija sa sudionicima {participants}",
"Conversations": "Konverzacije",
"Cookies and Local storage": "Kolačići i Lokalno spremište", "Cookies and Local storage": "Kolačići i Lokalno spremište",
"Copy URL to clipboard": "Kopiraj URL u međuspremnik", "Copy URL to clipboard": "Kopiraj URL u međuspremnik",
"Copy details to clipboard": "Kopiraj detalje u međuspremnik", "Copy details to clipboard": "Kopiraj detalje u međuspremnik",
@ -264,13 +268,14 @@
"Default Mobilizon terms": "Zadani Mobilizon uvjeti", "Default Mobilizon terms": "Zadani Mobilizon uvjeti",
"Delete": "Izbriši", "Delete": "Izbriši",
"Delete account": "Izbriši račun", "Delete account": "Izbriši račun",
"Delete conversation": "Izbriši razgovor", "Delete conversation": "Izbriši konverzaciju",
"Delete discussion": "Izbriši razgovor", "Delete discussion": "Izbriši razgovor",
"Delete event": "Izbriši događaj", "Delete event": "Izbriši događaj",
"Delete everything": "Izbriši sve", "Delete everything": "Izbriši sve",
"Delete group": "Izbriši grupu", "Delete group": "Izbriši grupu",
"Delete my account": "Izbriši moj račun", "Delete my account": "Izbriši moj račun",
"Delete post": "Izbriši objavu", "Delete post": "Izbriši objavu",
"Delete this conversation": "Izbriši ovu konverzaciju",
"Delete this discussion": "Izbriši razgovor", "Delete this discussion": "Izbriši razgovor",
"Delete this identity": "Izbriši ovaj identitet", "Delete this identity": "Izbriši ovaj identitet",
"Delete your identity": "Izbriši svoj identitet", "Delete your identity": "Izbriši svoj identitet",
@ -458,6 +463,7 @@
"I want to allow people to participate without an account.": "Želim dopustiti ljudima da sudjeluju i bez računa.", "I want to allow people to participate without an account.": "Želim dopustiti ljudima da sudjeluju i bez računa.",
"I want to approve every participation request": "Želim odobriti svaki zahtjev za sudjelovanje", "I want to approve every participation request": "Želim odobriti svaki zahtjev za sudjelovanje",
"I've been mentionned in a comment under an event": "Spomenut/a sam u komentaru u jednom događaju", "I've been mentionned in a comment under an event": "Spomenut/a sam u komentaru u jednom događaju",
"I've been mentionned in a conversation": "Spomenut/a sam u konverzaciji",
"I've been mentionned in a group discussion": "Spomenut/a sam u diskusiji grupe", "I've been mentionned in a group discussion": "Spomenut/a sam u diskusiji grupe",
"I've clicked on X, then on Y": "Pritisnuo/la sam X, zatim Y", "I've clicked on X, then on Y": "Pritisnuo/la sam X, zatim Y",
"ICS feed for events": "ICS feed za događaje", "ICS feed for events": "ICS feed za događaje",
@ -514,7 +520,7 @@
"Join group": "Pridruži se grupi", "Join group": "Pridruži se grupi",
"Join group {group}": "Pridruži se grupi {group}", "Join group {group}": "Pridruži se grupi {group}",
"Join {instance}, a Mobilizon instance": "Pridruži se instanci {instance}, Mobilizon instanca", "Join {instance}, a Mobilizon instance": "Pridruži se instanci {instance}, Mobilizon instanca",
"Keep the entire conversation about a specific topic together on a single page.": "Držite zajedno cijeli razgovor o nekoj temi na jednoj stranici.", "Keep the entire conversation about a specific topic together on a single page.": "Zadrži cijelu konverzaciju o nekoj temi na jednoj stranici.",
"Key words": "Ključne riječi", "Key words": "Ključne riječi",
"Keyword, event title, group name, etc.": "Ključna riječ, naslov događaja, ime grupe itd.", "Keyword, event title, group name, etc.": "Ključna riječ, naslov događaja, ime grupe itd.",
"Language": "Jezik", "Language": "Jezik",
@ -540,6 +546,7 @@
"Light": "Svijetla", "Light": "Svijetla",
"Limited number of places": "Ograničeni broj mjesta", "Limited number of places": "Ograničeni broj mjesta",
"List": "Popis", "List": "Popis",
"List of conversations": "Popis konverzacija",
"List title": "Naslov popisa", "List title": "Naslov popisa",
"Live": "Uživo", "Live": "Uživo",
"Load more": "Učitaj više", "Load more": "Učitaj više",
@ -703,6 +710,7 @@
"Open": "Otvori", "Open": "Otvori",
"Open a topic on our forum": "Otvori temu na našem forumu", "Open a topic on our forum": "Otvori temu na našem forumu",
"Open an issue on our bug tracker (advanced users)": "Otvori problem na našem bug tragaču (napredni korisnici)", "Open an issue on our bug tracker (advanced users)": "Otvori problem na našem bug tragaču (napredni korisnici)",
"Open conversations": "Otvori konverzacije",
"Open main menu": "Otvori glavni izbornik", "Open main menu": "Otvori glavni izbornik",
"Open user menu": "Otvori korisnički izbornik", "Open user menu": "Otvori korisnički izbornik",
"Opened reports": "Otvorene prijave", "Opened reports": "Otvorene prijave",
@ -887,6 +895,7 @@
"Send password reset": "Pošalji zahtjev za obnavljanje lozinke", "Send password reset": "Pošalji zahtjev za obnavljanje lozinke",
"Send the confirmation email again": "Pošalji e-mail za potvrdu ponovo", "Send the confirmation email again": "Pošalji e-mail za potvrdu ponovo",
"Send the report": "Pošalji izvještaj", "Send the report": "Pošalji izvještaj",
"Sent to {count} participants": "Poslano nijednom sudioniku|Poslano jednom sudioniku|Poslano {count} sudionicima",
"Set an URL to a page with your own privacy policy.": "Postavi URL na stranicu sa vašom osobnom politikom privatnosti.", "Set an URL to a page with your own privacy policy.": "Postavi URL na stranicu sa vašom osobnom politikom privatnosti.",
"Set an URL to a page with your own terms.": "Postavi URL za stranicu s tvojim uvjetima.", "Set an URL to a page with your own terms.": "Postavi URL za stranicu s tvojim uvjetima.",
"Settings": "Postavke", "Settings": "Postavke",
@ -969,6 +978,7 @@
"The event {event} was deleted by {profile}.": "{profile} su izbrisali događaj {event}.", "The event {event} was deleted by {profile}.": "{profile} su izbrisali događaj {event}.",
"The event {event} was updated by {profile}.": "{profile} su ažurirali događaj {event}.", "The event {event} was updated by {profile}.": "{profile} su ažurirali događaj {event}.",
"The events you created are not shown here.": "Događaji koje ste stvorili nisu prikazani ovdje.", "The events you created are not shown here.": "Događaji koje ste stvorili nisu prikazani ovdje.",
"The following participants are groups, which means group members are able to reply to this conversation:": "Sljedeći sudionici su grupe, što znači da članovi grupe mogu odgovoriti na ovu konverzaciju:",
"The geolocation prompt was denied.": "Upit za geolokaliziranje je odbijen.", "The geolocation prompt was denied.": "Upit za geolokaliziranje je odbijen.",
"The group can now be joined by anyone, but new members need to be approved by an administrator.": "Grupi se sada svatko može pridružiti, ali nove članove mora odobriti administrator.", "The group can now be joined by anyone, but new members need to be approved by an administrator.": "Grupi se sada svatko može pridružiti, ali nove članove mora odobriti administrator.",
"The group can now be joined by anyone.": "Grupi se sada svatko može pridružiti.", "The group can now be joined by anyone.": "Grupi se sada svatko može pridružiti.",
@ -999,6 +1009,7 @@
"There are {participants} participants.": "{participants} sudionika.", "There are {participants} participants.": "{participants} sudionika.",
"There is no activity yet. Start doing some things to see activity appear here.": "Još nema aktivnosti. Počnite nešto raditi kako bi se aktivnosti ovdje pojavile.", "There is no activity yet. Start doing some things to see activity appear here.": "Još nema aktivnosti. Počnite nešto raditi kako bi se aktivnosti ovdje pojavile.",
"There will be no way to recover your data.": "Neće biti načina vratiti vaše podatke.", "There will be no way to recover your data.": "Neće biti načina vratiti vaše podatke.",
"There's no conversations yet": "Još nema konverzacija",
"There's no discussions yet": "Nema razgovora", "There's no discussions yet": "Nema razgovora",
"These events may interest you": "Možda vas interesiraju ovi događaji", "These events may interest you": "Možda vas interesiraju ovi događaji",
"These feeds contain event data for the events for which any of your profiles is a participant or creator. You should keep these private. You can find feeds for specific profiles on each profile edition page.": "Ovi feedovi sadrže podatke događaja za događaje za koje je ovaj specifični profil sudionik ili organizator. Trebali biste ih držati privatnim. Feedovi za sve vaše profile možete pronaći u stranici profila.", "These feeds contain event data for the events for which any of your profiles is a participant or creator. You should keep these private. You can find feeds for specific profiles on each profile edition page.": "Ovi feedovi sadrže podatke događaja za događaje za koje je ovaj specifični profil sudionik ili organizator. Trebali biste ih držati privatnim. Feedovi za sve vaše profile možete pronaći u stranici profila.",
@ -1006,6 +1017,7 @@
"This Mobilizon instance and this event organizer allows anonymous participations, but requires validation through email confirmation.": "Ova instanca i ovi organizatori dozvoljavaju anonimne prijave, ali očekuju ovjerenje kroz email potvrdu.", "This Mobilizon instance and this event organizer allows anonymous participations, but requires validation through email confirmation.": "Ova instanca i ovi organizatori dozvoljavaju anonimne prijave, ali očekuju ovjerenje kroz email potvrdu.",
"This URL doesn't seem to be valid": "Čini se da je ovaj URL neispravan", "This URL doesn't seem to be valid": "Čini se da je ovaj URL neispravan",
"This URL is not supported": "Ovaj URL nije podržan", "This URL is not supported": "Ovaj URL nije podržan",
"This announcement will be send to all participants with the statuses selected below. They will not be allowed to reply to your announcement, but they can create a new conversation with you.": "Ova će se objava poslati svim sudionicima s dolje odabranim stanjima. Neće moći odgovoriti na tvoju objavu, ali mogu stvoriti novu konverzaciju s tobom.",
"This application will be allowed to list group followers in all of the groups you're a member of": "Ova će aplikacija smjeti prikazati popis pratioca grupe u svim grupama čiji si član", "This application will be allowed to list group followers in all of the groups you're a member of": "Ova će aplikacija smjeti prikazati popis pratioca grupe u svim grupama čiji si član",
"This event has been cancelled.": "Ovaj je događaj otkazan.", "This event has been cancelled.": "Ovaj je događaj otkazan.",
"This event is accessible only through it's link. Be careful where you post this link.": "Ovaj je događaj dostupan samo kroz njegovu poveznicu. Budite pažljivi gdje šaljete ovu poveznicu.", "This event is accessible only through it's link. Be careful where you post this link.": "Ovaj je događaj dostupan samo kroz njegovu poveznicu. Budite pažljivi gdje šaljete ovu poveznicu.",
@ -1197,6 +1209,7 @@
"You don't follow any instances yet.": "Ne pratite nijednu instancu.", "You don't follow any instances yet.": "Ne pratite nijednu instancu.",
"You don't have any upcoming events. Maybe try another filter?": "Nemaš nijedan nadolazeći događaj. Želiš li probati jedan drugi filtar?", "You don't have any upcoming events. Maybe try another filter?": "Nemaš nijedan nadolazeći događaj. Želiš li probati jedan drugi filtar?",
"You excluded member {member}.": "Isključili ste člana {member}.", "You excluded member {member}.": "Isključili ste člana {member}.",
"You have access to this conversation as a member of the {group} group": "Imaš pristup ovoj konverzaciji kao član grupe {group}",
"You have attended {count} events in the past.": "Broj događaja kojima si prisustvovao/la u prošlosti: 0.|Broj događaja kojima si prisustvovao/la u prošlosti: 1.|Broj događaja kojima si prisustvovao/la u prošlosti: {count}.", "You have attended {count} events in the past.": "Broj događaja kojima si prisustvovao/la u prošlosti: 0.|Broj događaja kojima si prisustvovao/la u prošlosti: 1.|Broj događaja kojima si prisustvovao/la u prošlosti: {count}.",
"You have been invited by {invitedBy} to the following group:": "{invitedBy} su vas pozvali u grupu:", "You have been invited by {invitedBy} to the following group:": "{invitedBy} su vas pozvali u grupu:",
"You have been removed from this group's members.": "Izbačeni ste iz ove grupe.", "You have been removed from this group's members.": "Izbačeni ste iz ove grupe.",

View file

@ -56,11 +56,7 @@
</option> </option>
</o-select> </o-select>
</o-field> </o-field>
<tag-input <tag-input v-model="event.tags" class="flex-1" />
v-model="event.tags"
class="flex-1"
:fetch-tags="fetchTags"
/>
</div> </div>
<o-field <o-field
@ -626,7 +622,6 @@ import {
useTimezones, useTimezones,
} from "@/composition/apollo/config"; } from "@/composition/apollo/config";
import { useMutation } from "@vue/apollo-composable"; import { useMutation } from "@vue/apollo-composable";
import { fetchTags } from "@/composition/apollo/tags";
import { Dialog } from "@/plugins/dialog"; import { Dialog } from "@/plugins/dialog";
import { Notifier } from "@/plugins/notifier"; import { Notifier } from "@/plugins/notifier";
import { useHead } from "@unhead/vue"; import { useHead } from "@unhead/vue";

View file

@ -32,7 +32,7 @@
/> />
</o-field> </o-field>
<tag-input v-model="editablePost.tags" :fetch-tags="fetchTags" /> <tag-input v-model="editablePost.tags" />
<o-field :label="t('Post')"> <o-field :label="t('Post')">
<p v-if="errors.body" class="help is-danger">{{ errors.body }}</p> <p v-if="errors.body" class="help is-danger">{{ errors.body }}</p>
@ -158,7 +158,6 @@ import { useI18n } from "vue-i18n";
import { computed, inject, onMounted, ref, watch } from "vue"; import { computed, inject, onMounted, ref, watch } from "vue";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { useMutation, useQuery } from "@vue/apollo-composable"; import { useMutation, useQuery } from "@vue/apollo-composable";
import { fetchTags } from "@/composition/apollo/tags";
import { Dialog } from "@/plugins/dialog"; import { Dialog } from "@/plugins/dialog";
const props = withDefaults( const props = withDefaults(