diff --git a/js/src/components/Editor.vue b/js/src/components/Editor.vue index e1c7b39d2..62ae45490 100644 --- a/js/src/components/Editor.vue +++ b/js/src/components/Editor.vue @@ -384,7 +384,7 @@ export default class EditorComponent extends Vue { searchText: query, }, }); - // TODO: TipTap doesn't handle async for onFilter, hence the following line. + // TipTap doesn't handle async for onFilter, hence the following line. this.filteredActors = result.data.searchPersons.elements; return this.filteredActors; }, diff --git a/js/src/components/Event/ShareEventModal.vue b/js/src/components/Event/ShareEventModal.vue index 9d599f2df..f4055f2da 100644 --- a/js/src/components/Event/ShareEventModal.vue +++ b/js/src/components/Event/ShareEventModal.vue @@ -72,7 +72,6 @@ - diff --git a/js/src/graphql/event.ts b/js/src/graphql/event.ts index 1c547802c..4b0085837 100644 --- a/js/src/graphql/event.ts +++ b/js/src/graphql/event.ts @@ -1,4 +1,5 @@ import gql from "graphql-tag"; +import { GROUP_FIELDS_FRAGMENTS } from "./group"; const participantQuery = ` role, @@ -622,3 +623,54 @@ export const GROUP_MEMBERSHIP_SUBSCRIPTION_CHANGED = gql` } } `; + +export const FETCH_GROUP_EVENTS = gql` + query( + $name: String! + $afterDateTime: DateTime + $beforeDateTime: DateTime + $organisedEventsPage: Int + $organisedEventslimit: Int + ) { + group(preferredUsername: $name) { + id + preferredUsername + domain + name + organizedEvents( + afterDatetime: $afterDateTime + beforeDatetime: $beforeDateTime + page: $organisedEventsPage + limit: $organisedEventslimit + ) { + elements { + id + uuid + title + beginsOn + draft + options { + maximumAttendeeCapacity + } + participantStats { + participant + notApproved + } + attributedTo { + id + preferredUsername + name + domain + } + organizerActor { + id + preferredUsername + name + domain + } + } + total + } + } + } +`; diff --git a/js/src/i18n/en_US.json b/js/src/i18n/en_US.json index d98ee3686..0db363aeb 100644 --- a/js/src/i18n/en_US.json +++ b/js/src/i18n/en_US.json @@ -442,7 +442,6 @@ "Actor": "Actor", "Text": "Text", "Upcoming events": "Upcoming events", - "View all upcoming events": "View all upcoming events", "Resources": "Resources", "Public page": "Public page", "Discussions": "Discussions", @@ -810,5 +809,6 @@ "Your participation will be validated once you click the confirmation link into the email.": "Your participation will be validated once you click the confirmation link into the email.", "Unable to load event for participation. The error details are provided below:": "Unable to load event for participation. The error details are provided below:", "Unable to save your participation in this browser.": "Unable to save your participation in this browser.", - "return to the event's page": "return to the event's page" + "return to the event's page": "return to the event's page", + "View all events": "View all events" } diff --git a/js/src/i18n/fr_FR.json b/js/src/i18n/fr_FR.json index 1da661f47..f84e45794 100644 --- a/js/src/i18n/fr_FR.json +++ b/js/src/i18n/fr_FR.json @@ -903,5 +903,6 @@ "Unable to load event for participation. The error details are provided below:": "Impossible de charger l'événement pour la participation. Les détails de l'erreur sont disponibles ci-dessous :", "Unable to save your participation in this browser.": "Échec de la sauvegarde de votre participation dans ce navigateur.", "return to the event's page": "retourner sur la page de l'événement", - "You may now close this window, or {return_to_event}.": "Vous pouvez maintenant fermer cette fenêtre, ou bien {return_to_event}." + "You may now close this window, or {return_to_event}.": "Vous pouvez maintenant fermer cette fenêtre, ou bien {return_to_event}.", + "View all events": "Voir tous les événements" } diff --git a/js/src/mixins/group.ts b/js/src/mixins/group.ts index 0abd0bcd9..43d0d3f1d 100644 --- a/js/src/mixins/group.ts +++ b/js/src/mixins/group.ts @@ -14,6 +14,8 @@ import { Component, Vue } from "vue-property-decorator"; variables() { return { name: this.$route.params.preferredUsername, + beforeDateTime: null, + afterDateTime: new Date(), }; }, skip() { diff --git a/js/src/views/Event/GroupEvents.vue b/js/src/views/Event/GroupEvents.vue index 7f37e7a3b..ed1f20892 100644 --- a/js/src/views/Event/GroupEvents.vue +++ b/js/src/views/Event/GroupEvents.vue @@ -51,7 +51,7 @@ {{ showPassedEvents ? $t("Past events") : $t("Upcoming events") }} {{ $t("Past events") }} - + {{ $t("No events found") }} + + @@ -75,15 +85,17 @@ diff --git a/js/src/views/Group/Group.vue b/js/src/views/Group/Group.vue index 616a494dd..b3a7631fd 100644 --- a/js/src/views/Group/Group.vue +++ b/js/src/views/Group/Group.vue @@ -362,18 +362,26 @@ :key="event.uuid" class="organized-event" /> - {{ $t("View all upcoming events") }} + +
+

{{ $t("No public upcoming events") }}

{{ $t("No public upcoming events") }}

- + + {{ $t("View all events") }}
{{ $t("Latest posts") }} @@ -383,18 +391,19 @@ :key="post.id" :post="post" /> - {{ $t("View all posts") }}

{{ $t("No posts yet") }}

- + + {{ $t("View all posts") }}
key; +localVue.use(VueRouter); +const router = new VueRouter({ routes, mode: "history" }); + +const groupPreferredUsername = "my_group"; +const groupDomain = "remotedomain.net"; +const groupUsername = `${groupPreferredUsername}@${groupDomain}`; + +const defaultSlotText = "A list of elements"; +const createSlotButtonText = "+ Post a public message"; + +type Props = { + title?: string; + icon?: string; + privateSection?: boolean; + route?: Location; +}; + +const baseProps: Props = { + title: "My group section", + icon: "bullhorn", + route: { + name: RouteName.POSTS, + params: { + preferredUsername: groupUsername, + }, + }, +}; + +const generateWrapper = (customProps: Props = {}) => { + return mount(GroupSection, { + localVue, + router, + propsData: { ...baseProps, ...customProps }, + slots: { + default: `
${defaultSlotText}
`, + create: `{{ $t("${createSlotButtonText}") }}`, + }, + }); +}; + +describe("GroupSection", () => { + it("renders group section with basic informations", () => { + const wrapper = generateWrapper({}); + + expect( + wrapper + .find(".group-section-title h2 span.icon i") + .classes(`mdi-${baseProps.icon}`) + ).toBe(true); + + expect(wrapper.find(".group-section-title h2 span:last-child").text()).toBe( + baseProps.title + ); + + expect(wrapper.find(".group-section-title a").attributes("href")).toBe( + `/@${groupUsername}/p` + ); + + expect(wrapper.find(".group-section-title").classes("privateSection")).toBe( + true + ); + + expect(wrapper.find(".main-slot div").text()).toBe(defaultSlotText); + expect(wrapper.find(".create-slot a").text()).toBe(createSlotButtonText); + expect(wrapper.find(".create-slot a").attributes("href")).toBe( + `/@${groupUsername}/p/new` + ); + expect(wrapper.html()).toMatchSnapshot(); + }); + + it("renders public group section", () => { + const wrapper = generateWrapper({ privateSection: false }); + + expect(wrapper.find(".group-section-title").classes("privateSection")).toBe( + false + ); + expect(wrapper.html()).toMatchSnapshot(); + }); +}); diff --git a/js/tests/unit/specs/components/Group/__snapshots__/GroupSection.spec.ts.snap b/js/tests/unit/specs/components/Group/__snapshots__/GroupSection.spec.ts.snap new file mode 100644 index 000000000..f77d39f5b --- /dev/null +++ b/js/tests/unit/specs/components/Group/__snapshots__/GroupSection.spec.ts.snap @@ -0,0 +1,25 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`GroupSection renders group section with basic informations 1`] = ` +
+
+

My group section

View all +
+
+
A list of elements
+
+ +
+`; + +exports[`GroupSection renders public group section 1`] = ` +
+
+

My group section

View all +
+
+
A list of elements
+
+ +
+`; diff --git a/vetur.config.js b/vetur.config.js new file mode 100644 index 000000000..159e82e29 --- /dev/null +++ b/vetur.config.js @@ -0,0 +1,5 @@ +// vetur.config.js +/** @type {import('vls').VeturConfig} */ +module.exports = { + projects: ["./js"], +};