-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(analytics, ui): event based analytics service plus (pre alpha)ta…
…ilwind UI for the analytics config (#4031) Analytics Allow admin user to setup analytics events. When the enduser of the web interface executes an action ( for example clicks on the 'contact' button) a signal is send to a analytics service ( third party; site-improve, google, .. or emx2 analytics endpoint). The app maintainer can configure which events are send in response to what ui element the user interacts with ( initial 'click' event only). The maintainer can configure these events on a per schema basis. Tailwind (analytics) ui (pre alpha) - ui path: /apps/ui/#/ - login as admin to update analytics settings - analytics path: /ui/[schema-name]/analytics
- Loading branch information
1 parent
3a8e3ec
commit 370db33
Showing
133 changed files
with
3,666 additions
and
249 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# Logs | ||
logs | ||
*.log | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
pnpm-debug.log* | ||
lerna-debug.log* | ||
|
||
node_modules | ||
dist | ||
dist-ssr | ||
*.local | ||
|
||
# Editor directories and files | ||
.vscode/* | ||
!.vscode/extensions.json | ||
.idea | ||
.DS_Store | ||
*.suo | ||
*.ntvs* | ||
*.njsproj | ||
*.sln | ||
*.sw? |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
# Analytics module | ||
|
||
Goal of the module is to allow service maintainers to track certain user actions. | ||
For example maintainer of a Data Catalogue application might what to know when and by who a 'Contact' button is clicked. | ||
|
||
This module when installed sets up 'Triggers' attched to page elements ( for example a Button in a given location). | ||
Besides the need to install and configure this module in a app ( or compoment ), | ||
the triggers ( what events to run when ) should be created using the analytics api or web ui. | ||
|
||
### Install the module | ||
|
||
use package manager to install the module '@molgenis/emx2-analytics' | ||
|
||
```yarn add @molgenis/emx2-analytics``` (or use the * option for yarn workspaces) | ||
|
||
### Setup the triggers in the app | ||
```import { setupAnalytics } from "@molgenis/emx2-analytics"; ``` | ||
|
||
... | ||
|
||
``` setupAnalytics(schema, providers);``` | ||
|
||
schema: The name of the emx schema/database | ||
|
||
providers: A list of analytics profiders and there config options, for example; ```providers = [{ id: "site-improve", options: { analyticsKey } }];``` | ||
|
||
This setup should be run before the user interacts with the page | ||
|
||
During the setupAnalytics call 3 steps are taken | ||
- 1. For each provider the nessasary code is (fetched and) loaded | ||
- 2. The triggers configured for this schema are fetched from the backend | ||
- 3. For each triggers the DOM elements are located in the page and a eventhandler gets attached for the configured provider | ||
|
||
When the end user visits the page and triggers the event the attached eventhandler uses the provider script to send the event. | ||
|
||
The whole analyics module works an a fire-and-forget basis, if something goes wrong the end user is not notified ( except for the browser console error log) | ||
|
||
|
||
## Development | ||
|
||
includes playground 'app', run via `yarn dev` | ||
|
||
## Build | ||
|
||
`yarn build` | ||
|
||
## Release | ||
|
||
todo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8" /> | ||
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> | ||
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | ||
<title>Vite + Vue + TS</title> | ||
</head> | ||
<body> | ||
<div id="app"></div> | ||
<script type="module" src="/src/main.ts"></script> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
{ | ||
"name": "@molgenis/emx2-analytics", | ||
"description": "Molgenis EMX2 Analytics, client module", | ||
"license": "LGPL-3.0-or-later", | ||
"private": false, | ||
"version": "0.0.0", | ||
"type": "module", | ||
"scripts": { | ||
"dev": "vite", | ||
"build": "vue-tsc -b && vite build", | ||
"preview": "vite preview", | ||
"format": "prettier src --write --config ../.prettierrc.js", | ||
"checkFormat": "prettier src --check --config ../.prettierrc.js" | ||
}, | ||
"dependencies": { | ||
"vue": "^3.4.29" | ||
}, | ||
"devDependencies": { | ||
"@vitejs/plugin-vue": "^5.0.5", | ||
"prettier": "2.8.8", | ||
"typescript": "^5.2.2", | ||
"vite": "^5.3.1", | ||
"vite-plugin-dts": "^3.9.1", | ||
"vue-tsc": "^2.0.21" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"files": [ | ||
"dist", | ||
"src", | ||
"package.json", | ||
"README.md" | ||
], | ||
"main": "./dist/analytics.umd.js", | ||
"module": "./dist/analytics.es.js", | ||
"typings": "./dist/lib/**/*.d.ts", | ||
"exports": { | ||
".": { | ||
"import": "./dist/analytics.es.js", | ||
"require": "./dist/analytics.umd.js" | ||
}, | ||
"./dist/style.css": { | ||
"import": "./dist/style.css", | ||
"require": "./dist/style.css" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
<script setup lang="ts"> | ||
import { Ref, ref } from "vue"; | ||
import { setupAnalytics } from "./lib/analytics"; | ||
import { Trigger } from "./types/Trigger"; | ||
const analyticsKey = ref("1234"); | ||
// setupAnalytics("catalogue", [{ id: "site-improve", options: { analyticsKey: analyticsKey.value } }]); | ||
const schemaName = ref("catalogue"); | ||
const triggerName = ref(""); | ||
const cssSelector = ref(""); | ||
const triggers: Ref<Trigger[]> = ref([]); | ||
function fetchTriggers() { | ||
fetch(`/catalogue/api/trigger`).then(async (response) => { | ||
triggers.value = await response.json(); | ||
}); | ||
} | ||
fetchTriggers(); | ||
const addTriggerError = ref(""); | ||
function addTrigger() { | ||
if (triggerName.value && cssSelector.value) { | ||
fetch(`/${schemaName.value}/api/trigger`, { | ||
method: "POST", | ||
headers: { | ||
"Content-Type": "application/json", | ||
}, | ||
body: JSON.stringify({ | ||
name: triggerName.value, | ||
cssSelector: cssSelector.value, | ||
}), | ||
}) | ||
.then((response) => response.json()) | ||
.then((data) => { | ||
if (data.errors) { | ||
addTriggerError.value = data.errors; | ||
return; | ||
} else fetchTriggers(); | ||
}) | ||
.catch((error) => { | ||
console.error("Error:", error); | ||
addTriggerError.value = error; | ||
}); | ||
} | ||
} | ||
function testBtnClicked() { | ||
console.log("Test button clicked"); | ||
} | ||
function reRunSetup() { | ||
console.log("reRunSetup"); | ||
setupAnalytics("catalogue", [ | ||
{ id: "site-improve", options: { analyticsKey: analyticsKey.value } }, | ||
]); | ||
} | ||
</script> | ||
|
||
<template> | ||
<h1>Analytics</h1> | ||
|
||
<div id="page"> | ||
<div class="container"> | ||
<h2>Config</h2> | ||
<label for="id">Analytics key</label> | ||
<input id="id" v-model="analyticsKey" placeholder="event identifier" /> | ||
|
||
<button @click="reRunSetup">(re) run setup</button> | ||
{{ analyticsKey }} | ||
</div> | ||
<div class="container"> | ||
<h2>Add Trigger</h2> | ||
<label for="id">Event id</label> | ||
<input id="id" v-model="triggerName" placeholder="event identifier" /> | ||
<label for="selector">Dom element css selector</label> | ||
<input | ||
id="selector" | ||
type="textarea" | ||
v-model="cssSelector" | ||
placeholder="css selector for event" | ||
/> | ||
<button @click="addTrigger">Add Trigger</button> | ||
{{ addTriggerError }} | ||
</div> | ||
|
||
<div class="container"> | ||
<h2>Triggers for {{ schemaName }}</h2> | ||
<ul> | ||
<li v-if="!triggers.length">No trigger setup</li> | ||
<li v-else v-for="trigger in triggers"> | ||
<div> | ||
<dl> | ||
<dt>{{ trigger.name }}</dt> | ||
<dd>{{ trigger.cssSelector }}</dd> | ||
|
||
<dt v-if="trigger.appName">App</dt> | ||
<dd v-if="trigger.appName">{{ trigger.appName }}</dd> | ||
</dl> | ||
</div> | ||
</li> | ||
</ul> | ||
</div> | ||
|
||
<div> | ||
<button id="test-btn" @click="testBtnClicked">Test Button</button> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<style scoped> | ||
input { | ||
margin: 0.5rem 0 1rem 0; | ||
padding: 0.3rem 2rem 0.3rem 0.3rem; | ||
font-size: x-large; | ||
} | ||
#page { | ||
display: flex; | ||
justify-content: space-between; | ||
padding: 1rem; | ||
width: 100%; | ||
#list-container { | ||
padding-right: 5rem; | ||
} | ||
p, | ||
dt { | ||
font-weight: bold; | ||
} | ||
dl, | ||
dd { | ||
text-align: left; | ||
font-size: 0.9rem; | ||
} | ||
dd { | ||
font-family: monospace; | ||
margin-bottom: 1em; | ||
padding-left: 0; | ||
} | ||
.container { | ||
display: flex; | ||
flex-direction: column; | ||
border: 1px solid black; | ||
padding: 0rem 1rem 1rem 1rem; | ||
label { | ||
font-size: x-large; | ||
text-align: left; | ||
} | ||
button { | ||
margin-top: 1rem; | ||
padding: 0.5rem 1rem; | ||
font-size: x-large; | ||
background-color: rgb(242, 185, 14); | ||
} | ||
} | ||
#test-btn { | ||
padding: 0.5rem 1rem; | ||
font-size: x-large; | ||
background-color: rgb(76, 72, 211); | ||
color: white; | ||
} | ||
} | ||
</style> |
Oops, something went wrong.