From 5ab8fe28886c161768e70e30f73f72e71f145cdc Mon Sep 17 00:00:00 2001 From: Thomas Citharel Date: Wed, 23 Oct 2019 12:36:11 +0200 Subject: [PATCH] Make tags clickable Signed-off-by: Thomas Citharel --- js/src/router/event.ts | 7 +++++ js/src/views/Event/Event.vue | 52 +++++++++++++++++++++++++++++++++--- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/js/src/router/event.ts b/js/src/router/event.ts index 8ea00b456..944580201 100644 --- a/js/src/router/event.ts +++ b/js/src/router/event.ts @@ -1,6 +1,7 @@ import EventList from '@/views/Event/EventList.vue'; import Location from '@/views/Location.vue'; import { RouteConfig } from 'vue-router'; +import { RouteName } from '@/router/index'; // tslint:disable:space-in-parens const participations = () => import(/* webpackChunkName: "participations" */ '@/views/Event/Participants.vue'); @@ -19,6 +20,7 @@ export enum EventRouteName { PARTICIPATIONS = 'Participations', EVENT = 'Event', LOCATION = 'Location', + TAG = 'Tag', } export const eventRoutes: RouteConfig[] = [ @@ -73,4 +75,9 @@ export const eventRoutes: RouteConfig[] = [ props: true, meta: { requiredAuth: false }, }, + { + path: '/tag/:tag', + name: EventRouteName.TAG, + redirect: '/search/:tag', + }, ]; diff --git a/js/src/views/Event/Event.vue b/js/src/views/Event/Event.vue index a0f4d4305..be089a1df 100644 --- a/js/src/views/Event/Event.vue +++ b/js/src/views/Event/Event.vue @@ -66,8 +66,14 @@ import {ParticipantRole} from "@/types/event.model"; {{ $t('Public event') }} {{ $t('Private event') }} - {{ tag.title }} - + + {{ tag.title }} +

@@ -155,7 +161,7 @@ import {ParticipantRole} from "@/types/event.model"; {{ $t("The event organizer didn't add any description.") }}

-
+
@@ -242,6 +248,7 @@ import IdentityPicker from '@/views/Account/IdentityPicker.vue'; import ParticipationButton from '@/components/Event/ParticipationButton.vue'; import { GraphQLError } from 'graphql'; import { RouteName } from '@/router'; +import HTML = Mocha.reporters.HTML; @Component({ components: { @@ -329,6 +336,41 @@ export default class Event extends EventMixin { mounted() { this.identity = this.currentActor; + + this.$watch('eventDescription', function (eventDescription) { + if (!eventDescription) return; + const eventDescriptionElement = this.$refs['eventDescriptionElement'] as HTMLElement; + + eventDescriptionElement.addEventListener('click', ($event) => { + // TODO: Find the right type for target + let { target } : { target: any } = $event; + while (target && target.tagName !== 'A') target = target.parentNode; + // handle only links that occur inside the component and do not reference external resources + if (target && target.matches('.hashtag') && target.href) { + // some sanity checks taken from vue-router: + // https://github.com/vuejs/vue-router/blob/dev/src/components/link.js#L106 + const { altKey, ctrlKey, metaKey, shiftKey, button, defaultPrevented } = $event; + // don't handle with control keys + if (metaKey || altKey || ctrlKey || shiftKey) return; + // don't handle when preventDefault called + if (defaultPrevented) return; + // don't handle right clicks + if (button !== undefined && button !== 0) return; + // don't handle if `target="_blank"` + if (target && target.getAttribute) { + const linkTarget = target.getAttribute('target'); + if (/\b_blank\b/i.test(linkTarget)) return; + } + // don't handle same page links/anchors + const url = new URL(target.href); + const to = url.pathname; + if (window.location.pathname !== to && $event.preventDefault) { + $event.preventDefault(); + this.$router.push(to); + } + } + }); + }); } /** @@ -821,6 +863,10 @@ export default class Event extends EventMixin { padding: 0.3rem; background: $secondary; color: #111; + + &:empty { + display: none; + } } } }