From 03b2d027427f3e5ce25e35b50420102b3c581c75 Mon Sep 17 00:00:00 2001 From: Redblueflame Date: Fri, 9 Apr 2021 04:44:25 +0200 Subject: [PATCH] Change ads provider, and add consent system for advertising (#155) * Add GAM integration & base for GPDR consent * Moved consent to a specific page. * Added functionality to the privacy page, and desactivate tracking if consent is not given. * Added GeoEdge support, and fixed auth issues * Fix actions issue * Fix actions issue, attempt 2 * Added a module for analytics with consent support. * Remove unnecessary function * Add support for runtime config --- .eslintignore | 3 + assets/styles/components.scss | 53 ++ components/{ => ads}/Advertisement.vue | 21 +- components/ads/CookieConsent.vue | 77 +++ components/ads/ReviewPopup.vue | 24 + components/layout/MFooter.vue | 5 + components/layout/ModPage.vue | 18 +- components/ui/Popup.vue | 6 +- layouts/default.vue | 1 + middleware/ads_tracking.js | 8 + middleware/auth.js | 2 + modules/analytics/lib/constants.js | 6 + modules/analytics/lib/module.js | 22 + modules/analytics/lib/templates/plugin.js | 64 ++ modules/analytics/package.json | 31 + modules/gpt-ads/lib/constants.js | 16 + modules/gpt-ads/lib/module.js | 34 ++ modules/gpt-ads/lib/templates/component.js | 256 ++++++++ modules/gpt-ads/lib/templates/plugin.js | 111 ++++ modules/gpt-ads/package.json | 35 ++ nuxt.config.js | 39 +- package-lock.json | 671 ++++++++++++++++++++- package.json | 3 +- pages/dashboard.vue | 19 +- pages/dashboard/privacy.vue | 161 +++++ pages/mods.vue | 6 +- pages/user/_id.vue | 6 +- privacy-toggles.js | 18 + store/consent.js | 59 ++ 29 files changed, 1729 insertions(+), 46 deletions(-) create mode 100644 .eslintignore rename components/{ => ads}/Advertisement.vue (56%) create mode 100644 components/ads/CookieConsent.vue create mode 100644 components/ads/ReviewPopup.vue create mode 100644 middleware/ads_tracking.js create mode 100644 modules/analytics/lib/constants.js create mode 100644 modules/analytics/lib/module.js create mode 100644 modules/analytics/lib/templates/plugin.js create mode 100644 modules/analytics/package.json create mode 100644 modules/gpt-ads/lib/constants.js create mode 100644 modules/gpt-ads/lib/module.js create mode 100644 modules/gpt-ads/lib/templates/component.js create mode 100644 modules/gpt-ads/lib/templates/plugin.js create mode 100644 modules/gpt-ads/package.json create mode 100644 pages/dashboard/privacy.vue create mode 100644 privacy-toggles.js create mode 100644 store/consent.js diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 000000000..5c80a71cf --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +node_modules/ +jspm_packages/ +modules/* diff --git a/assets/styles/components.scss b/assets/styles/components.scss index 6edba8b63..a4000bc1a 100644 --- a/assets/styles/components.scss +++ b/assets/styles/components.scss @@ -420,3 +420,56 @@ } } +.switch { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + -webkit-tap-highlight-color: transparent; + cursor: pointer; + &:focus { + outline: 0; + } + +} + + + +.stylized-toggle { + height: 32px; + width: 52px; + border-radius: 16px; + display: inline-block; + position: relative; + margin: 0; + border: 2px solid var(--color-button-bg); + transition: all .2s ease; + background: var(--color-button-bg); + + &:after { + content: ''; + position: absolute; + top: 2px; + left: 2px; + width: 24px; + height: 24px; + border-radius: 50%; + background: white; + box-shadow: 0 1px 2px rgba(44,44,44,.2); + transition: all .2s cubic-bezier(.5,.1,.75,1.35); + } + &:checked { + background: var(--color-brand); + border: 2px solid var(--color-brand); + &:after { + transform: translatex(20px); + } + } + &:hover &:focus { + background: var(--color-button-bg); + border: 2px solid var(--color-button-bg); + } + &:hover:checked &:focus:checked { + background: var(--color-brand); + border: 2px solid var(--color-brand); + } +} diff --git a/components/Advertisement.vue b/components/ads/Advertisement.vue similarity index 56% rename from components/Advertisement.vue rename to components/ads/Advertisement.vue index 6d813ba6d..aea6dd4cd 100644 --- a/components/Advertisement.vue +++ b/components/ads/Advertisement.vue @@ -1,25 +1,23 @@ + + diff --git a/components/ads/ReviewPopup.vue b/components/ads/ReviewPopup.vue new file mode 100644 index 000000000..dc90291d8 --- /dev/null +++ b/components/ads/ReviewPopup.vue @@ -0,0 +1,24 @@ + + + + + diff --git a/components/layout/MFooter.vue b/components/layout/MFooter.vue index b251f2b74..97a847444 100644 --- a/components/layout/MFooter.vue +++ b/components/layout/MFooter.vue @@ -26,6 +26,11 @@ Twitter + © Guavy LLC
Version: {{ version }} diff --git a/components/layout/ModPage.vue b/components/layout/ModPage.vue index 658288904..aa5cbb0e0 100644 --- a/components/layout/ModPage.vue +++ b/components/layout/ModPage.vue @@ -65,9 +65,8 @@
@@ -133,9 +132,8 @@
@@ -333,10 +331,8 @@ @@ -364,7 +360,7 @@ import ExternalIcon from '~/assets/images/utils/external.svg?inline' import ForgeIcon from '~/assets/images/categories/forge.svg?inline' import FabricIcon from '~/assets/images/categories/fabric.svg?inline' -import Advertisement from '~/components/Advertisement' +import Advertisement from '~/components/ads/Advertisement' export default { name: 'ModPage', diff --git a/components/ui/Popup.vue b/components/ui/Popup.vue index 299b55c37..32c8bf0cf 100644 --- a/components/ui/Popup.vue +++ b/components/ui/Popup.vue @@ -23,7 +23,7 @@ export default { .popup-overlay { top: 0; left: 0; - z-index: 1; + z-index: 10; position: fixed; width: 100%; height: 100%; @@ -38,11 +38,11 @@ export default { top: 50%; left: 50%; transform: translate(-50%, -50%); - z-index: 2; + z-index: 11; box-shadow: 0 2px 3px 1px var(--color-button-bg); border-radius: 10px; max-height: 80%; overflow-y: auto; - background-color: var(--color-bg); + background-color: var(--color-raised-bg); } diff --git a/layouts/default.vue b/layouts/default.vue index 1024a5bc1..a2461a7c9 100644 --- a/layouts/default.vue +++ b/layouts/default.vue @@ -96,6 +96,7 @@
+ + + + + + diff --git a/pages/mods.vue b/pages/mods.vue index f7b0498d7..6e4ee893b 100644 --- a/pages/mods.vue +++ b/pages/mods.vue @@ -63,7 +63,7 @@ >
- +

Loading...

@@ -279,7 +279,7 @@ @input="toggleLicense" />
- + @@ -313,7 +313,7 @@ import FabricLoader from '~/assets/images/categories/fabric.svg?inline' import SearchIcon from '~/assets/images/utils/search.svg?inline' import ExitIcon from '~/assets/images/utils/exit.svg?inline' -import Advertisement from '~/components/Advertisement' +import Advertisement from '~/components/ads/Advertisement' export default { auth: false, diff --git a/pages/user/_id.vue b/pages/user/_id.vue index acd18248e..2624a54e9 100644 --- a/pages/user/_id.vue +++ b/pages/user/_id.vue @@ -55,11 +55,11 @@ - +
- +
({ + is_consent_given: false, + scopes_allowed: [], + loaded: false, +}) +export const mutations = { + loaded(state) { + state.loaded = true + }, + set_consent(state, val) { + state.is_consent_given = val + }, + add_scope(state, val) { + // Check if the scope is not already provided + if (state.scopes_allowed.includes(val)) return + state.scopes_allowed.push(val) + }, + remove_scope(state, val) { + const pos = state.scopes_allowed.findIndex((el) => el === val) + if (pos >= 0) state.scopes_allowed.splice(pos, 1) + }, +} +export const actions = { + loadFromCookies(state, $cookies) { + if (state.state.loaded) { + return + } + state.commit('set_consent', $cookies.get('modrinth-consent') === true) + const scopes = $cookies.get('modrinth-scopes') + if (scopes == null) return + scopes.split(',').forEach((elem) => { + state.commit('add_scope', elem) + }) + state.commit('loaded') + }, + save(state, $cookies) { + $cookies.set('modrinth-consent', state.state.is_consent_given, parameters) + $cookies.set('modrinth-version', VERSION, parameters) + $cookies.set( + 'modrinth-scopes', + state.state.scopes_allowed.join(','), + parameters + ) + }, +} +export const getters = { + is_scope_allowed: (state) => (id) => { + return state.scopes_allowed.contains(id) + }, +}