Skip to content

Commit

Permalink
feat: 🎨 Create a plugin matomo for vue
Browse files Browse the repository at this point in the history
  • Loading branch information
Carolinedanslesnuages committed Feb 13, 2025
1 parent e1b417a commit d773642
Show file tree
Hide file tree
Showing 7 changed files with 286 additions and 48 deletions.
50 changes: 39 additions & 11 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,18 +52,12 @@ services:
- KEYCLOAK_ADMIN=admin
- KEYCLOAK_ADMIN_PASSWORD=password
ports:
- 8082:8080
- "8082:8080"
healthcheck:
test:
"exec 3<>/dev/tcp/127.0.0.1/9000; echo -e 'GET /health/ready HTTP/1.1\r
Host: localhost:9000\r
Connection: close\r
\r
' >&3;cat <&3 | grep -q '\"status\": \"UP\"' && exit 0 || exit 1"
test: >
exec 3<>/dev/tcp/127.0.0.1/9000;
echo -e "GET /health/ready HTTP/1.1\r\nHost: localhost:9000\r\nConnection: close\r\n\r\n" >&3;
cat <&3 | grep -q '\"status\": \"UP\"' && exit 0 || exit 1
interval: 5s
timeout: 10s
retries: 5
Expand All @@ -82,9 +76,43 @@ services:
depends_on:
- backend

# Ajout du service MySQL pour Matomo en local
db:
image: mariadb:10.5
container_name: matomo-db
restart: always
environment:
MYSQL_ROOT_PASSWORD: matomo
MYSQL_DATABASE: matomo
MYSQL_USER: matomo
MYSQL_PASSWORD: matomo
volumes:
- db_data:/var/lib/mysql
matomo:
image: matomo
container_name: matomo
restart: always
ports:
- "8083:80"
environment:
MATOMO_DATABASE_HOST: db
MATOMO_DATABASE_ADAPTER: mysql
MATOMO_DATABASE_TABLES_PREFIX: matomo_
MATOMO_DATABASE_USERNAME: matomo
MATOMO_DATABASE_PASSWORD: matomo
MATOMO_DATABASE_DBNAME: matomo
depends_on:
- db
volumes:
- matomo_data:/var/www/html

krakend:
image: devopsfaith/krakend
ports:
- "8080:8080"
volumes:
- ./krakend.json:/etc/krakend/krakend.json

volumes:
db_data:
matomo_data:
4 changes: 3 additions & 1 deletion frontend/.env.development
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ VITE_RDA_KEYCLOAK_AUTH_SERVER_URL=http://localhost:8082
VITE_RDA_KEYCLOAK_REALM=referentiel-applications
VITE_RDA_KEYCLOAK_CLIENT_ID=referentiel-applications
VITE_RDA_API_URL=http://localhost:3500
VITE_APP_VERSION=development
VITE_APP_VERSION=development
VITE_MATOMO_URL=http://localhost:8083
VITE_MATOMO_SITE_ID=1
9 changes: 9 additions & 0 deletions frontend/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

85 changes: 57 additions & 28 deletions frontend/src/App.vue
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
<script setup lang="ts">
import { ref, computed } from "vue";
import { ref, computed, getCurrentInstance } from "vue";
import { useRegisterSW } from "virtual:pwa-register/vue";
import useToaster from "./composables/use-toaster";
import { routeNames } from "./router/route-names";
import { authentication } from "./services/authentication";
import Applications from "@/api/application";
import { useRouter } from "vue-router";
const router = useRouter();
const instance = getCurrentInstance();
const trackSearch = () => {
if (searchQuery.value.trim()) {
instance?.proxy?.$matomo?.trackEvent("Search", "Performed", searchQuery.value);
}
};
const authenticated = ref(false);
const unauthenticatedQuickLinks = ref<QuickLink[]>([]);
Expand Down Expand Up @@ -85,21 +95,29 @@ watch(searchQuery, (newVal) => {
}
debounceTimeout = setTimeout(async () => {
try {
trackSearch();
isLoading.value = true;
errorMessage.value = "";
const results = await Applications.getAllApplicationBySearch(newVal);
searchResults.value = results || [];
} catch (error) {
instance?.proxy?.$matomo?.trackEvent("Error", "Search Error", error.message);
errorMessage.value = "Une erreur est survenue lors du chargement des applications.";
} finally {
isLoading.value = false;
}
}, 300);
});
const trackResultSelection = (appLabel: string) => {
instance?.proxy?.$matomo?.trackEvent("Search", "Result Selected", appLabel);
clearSearch();
};
const clearSearch = () => {
searchQuery.value = "";
searchResults.value = [];
instance?.proxy?.$matomo.trackEvent("search", "click", "search-result");
};
const { setScheme, theme } = useScheme();
Expand All @@ -115,28 +133,29 @@ function close() {
</script>

<template>
<DsfrHeader
v-model="searchQuery"
:service-description="serviceDescription"
:service-title="serviceTitle"
:logo-text="logoText"
:quick-links="quickLinks"
show-beta
:showSearch="authenticated"
/>

<div v-if="searchQuery && (searchResults.length || isLoading || errorMessage)" class="search-results-dropdown">
<div v-if="isLoading" class="loading-message">Chargement...</div>
<div v-if="errorMessage" class="error-message">{{ errorMessage }}</div>
<ul v-if="searchResults.length">
<li v-for="(app, index) in searchResults" @click="clearSearch" :key="index">
<router-link :to="{ name: 'application', params: { id: app.id } }">
{{ app.label || "Application" }}
</router-link>
</li>
</ul>
<div class="header-container">
<DsfrHeader
v-model="searchQuery"
:service-description="serviceDescription"
:service-title="serviceTitle"
:logo-text="logoText"
:quick-links="quickLinks"
show-beta
:showSearch="authenticated"
/>

<div v-if="searchQuery && (searchResults.length || isLoading || errorMessage)" class="search-results-dropdown">
<div v-if="isLoading" class="loading-message">Chargement...</div>
<div v-if="errorMessage" class="error-message">{{ errorMessage }}</div>
<ul v-if="searchResults.length">
<li v-for="(app, index) in searchResults" :key="index" @click="trackResultSelection(app.label)">
<router-link :to="{ name: 'application', params: { id: app.id } }">
{{ app.label || "Application" }}
</router-link>
</li>
</ul>
</div>
</div>

<div class="fr-container fr-mt-3w fr-mt-md-5w fr-mb-5w">
<router-view :key="$route.fullPath" />
</div>
Expand All @@ -159,19 +178,22 @@ function close() {
</template>

<style scoped>
.header-container {
position: relative;
}
.search-results-dropdown {
position: absolute;
top: 112px;
left: 79%;
transform: translateX(-50%);
top: 100%;
right: 0;
background-color: white;
width: 90%;
width: 100%;
max-width: 384px;
border: 1px solid #ccc;
border-radius: 4px;
z-index: 1000;
padding: 1rem;
margin-top: 0.5rem;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
overflow: hidden;
}
.search-results-dropdown ul {
Expand All @@ -181,7 +203,14 @@ function close() {
}
.search-results-dropdown li {
margin: 0.5rem 0;
padding: 0.5rem 1rem;
cursor: pointer;
transition: background-color 0.2s;
}
/* Ajout d'un effet survol */
.search-results-dropdown li:hover {
background-color: #f0f0f0;
}
.loading-message,
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// @ts-nocheck
// Generated by unplugin-vue-components
// Read more: https://github.com/vuejs/core/pull/3399
export {};
export {}

/* prettier-ignore */
declare module 'vue' {
Expand Down
32 changes: 25 additions & 7 deletions frontend/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,36 @@
import { VIcon } from "@gouvminint/vue-dsfr";
import { createPinia } from "pinia";
import { createApp } from "vue";
import App from "./App.vue";

import { createPinia } from "pinia";
import router from "./router/index";
import "@gouvfr/dsfr/dist/core/core.main.min.css";
import { VIcon } from "@gouvminint/vue-dsfr";

// Importation des styles DSFR et personnalisés
import "@gouvfr/dsfr/dist/core/core.main.min.css";
import "@gouvfr/dsfr/dist/component/component.main.min.css";
import "@gouvfr/dsfr/dist/utility/utility.main.min.css";

import "@gouvminint/vue-dsfr/styles";
import "@gouvfr/dsfr/dist/scheme/scheme.min.css";

import "@gouvfr/dsfr/dist/utility/icons/icons.min.css";
import "./main.css";
import MatomoPlugin from "./plugins/MatomoPlugin";

const app = createApp(App);

app.use(MatomoPlugin, {
host: import.meta.env.VITE_MATOMO_URL,
siteId: Number(import.meta.env.VITE_MATOMO_SITE_ID),
router,
debug: import.meta.env.DEBUG === "true",
enableHeartBeatTimer: true,
});

app.use(createPinia());
app.use(router);
app.component("VIcon", VIcon);

app.mount("#app");

createApp(App).use(createPinia()).component("VICon", VIcon).use(router).mount("#app");
router.afterEach((to) => {
console.log("trackPageView", to.fullPath);
app.config.globalProperties.$matomo?.trackPageView(to.fullPath);
});
Loading

0 comments on commit d773642

Please sign in to comment.