Skip to content

Commit

Permalink
Merge branch 'main' into feat/add-missing-exports-condition
Browse files Browse the repository at this point in the history
  • Loading branch information
VmMad committed Oct 9, 2024
2 parents d03e08a + 6fb51f6 commit a34707f
Show file tree
Hide file tree
Showing 75 changed files with 2,304 additions and 318 deletions.
6 changes: 0 additions & 6 deletions .eslintrc.js

This file was deleted.

44 changes: 44 additions & 0 deletions cookie-manager/core/clientSideOnly.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Service } from './types'
import { GOOGLE_ANALYTICS_EXPIRATION_DAYS } from './constants'

export const loadGoogleAnalytics = (
id: Service['id'],
setServicesInitialized: (bool: boolean) => void
): void => {
function gtag(_key: string, _value: unknown, _config?: { cookie_expires: number }) {
// eslint-disable-next-line prefer-rest-params
window.dataLayer.push(arguments)
}
window.dataLayer = window.dataLayer || []

gtag('js', new Date())
gtag('config', id, { cookie_expires: GOOGLE_ANALYTICS_EXPIRATION_DAYS * 24 * 60 * 60 })

const script = document.createElement('script')
script.src = `https://www.googletagmanager.com/gtag/js?id=${id}`
document.body.appendChild(script)
setServicesInitialized(true)
}

export const removeGoogleAnalytics = (id: Service['id']): void => {
const scripts = Array.from(document.getElementsByTagName('script'))
if (scripts && scripts.length) {
scripts
.find((script) => script?.src === `https://www.googletagmanager.com/gtag/js?id=${id}`)
?.remove()
scripts
.find((script) => script?.src === 'https://www.google-analytics.com/analytics.js')
?.remove()
}
}

export const updatePathGA = (id: Service['id'], path: string): void => {
function gtag(_key: string, _value: unknown, _pagePathObject: { page_path: string }) {
// eslint-disable-next-line prefer-rest-params
window.dataLayer.push(arguments)
}
window.dataLayer = window.dataLayer || []
gtag('config', id, {
page_path: path
})
}
File renamed without changes.
6 changes: 6 additions & 0 deletions cookie-manager/core/enums.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export enum SupportedService {
GoogleAnalyticsUniversal = 'googleAnalyticsUniversal',
GoogleAnalytics4 = 'googleAnalytics4',
CustomCookie = 'customNecessaryCookies'
}

export enum CookieCategory {
Functionality = 'Functionality',
Statistics = 'Statistics',
Expand Down
7 changes: 7 additions & 0 deletions cookie-manager/core/initialStates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { Service, ServiceCookie } from './types'

export const INITIAL_SHOW_COOKIE_DISCLAIMER: boolean = false
export const INITIAL_CONFIGURED_SERVICES: Service[] = []
export const INITIAL_SERVICES_INITIALIZED: boolean = false
export const INITIAL_NECESSARY_COOKIES: ServiceCookie[] = []
export const INITIAL_ADDITIONAL_COOKIES: ServiceCookie[] = []
149 changes: 149 additions & 0 deletions cookie-manager/core/services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
import {
GoogleOwnCookies,
SKCM_GA_GOOGLE_ANALYTICS_4_COOKIE,
SKCM_GA_GOOGLE_ANALYTICS_UNIVERSAL_COOKIE
} from './cookieLib'
import { CookieCategory, SupportedService } from './enums'
import type { Service, ServiceCookie, SKCMConfiguration } from './types'
import { deleteCookie, getCookie, setCookie } from './utils'
import { loadGoogleAnalytics, removeGoogleAnalytics } from './clientSideOnly'
import { COOKIE_EXPIRATION_DAYS } from './constants'

export function initializeServices(
servicesInitialized: boolean,
configuredServices: Service[],
setServicesInitialized: (bool: boolean) => void
): void {
if (!servicesInitialized) {
const googleAnalyticsUniversalConfig = configuredServices.find(
({ type }) => type === SupportedService.GoogleAnalyticsUniversal
)
const googleAnalytics4Config = configuredServices.find(
({ type }) => type === SupportedService.GoogleAnalytics4
)
if (googleAnalyticsUniversalConfig?.enabled) {
loadGoogleAnalytics(googleAnalyticsUniversalConfig.id, setServicesInitialized)
} else {
if (googleAnalytics4Config?.enabled) {
loadGoogleAnalytics(googleAnalytics4Config.id, setServicesInitialized)
}
}
}
}

interface InitConfiguredServicesArgs {
services: SKCMConfiguration['services']
onConfiguredServicesInitialized: (
configuredServices: Service[],
necessaryCookies: ServiceCookie[]
) => void
}
export function initializeConfiguredServices({
services: {
googleAnalyticsUniversalId,
googleAnalytics4Id,
adCookiesEnabled,
customNecessaryCookies
} = {},
onConfiguredServicesInitialized
}: InitConfiguredServicesArgs): void {
let _configuredServices: Service[] = []
let _necessaryCookies: ServiceCookie[] = []
if (googleAnalyticsUniversalId) {
_configuredServices.push({
type: SupportedService.GoogleAnalyticsUniversal,
id: googleAnalyticsUniversalId,
enabled: getCookie(SKCM_GA_GOOGLE_ANALYTICS_UNIVERSAL_COOKIE?.name) === 'true',
cookies: GoogleOwnCookies.GoogleAnalyticsUniversal
})
_necessaryCookies.push(SKCM_GA_GOOGLE_ANALYTICS_UNIVERSAL_COOKIE)
}
if (googleAnalytics4Id) {
_configuredServices.push({
type: SupportedService.GoogleAnalytics4,
id: googleAnalytics4Id,
enabled: getCookie(SKCM_GA_GOOGLE_ANALYTICS_4_COOKIE?.name) === 'true',
cookies: GoogleOwnCookies.GoogleAnalytics4
})
_necessaryCookies.push(SKCM_GA_GOOGLE_ANALYTICS_4_COOKIE)
}
if (customNecessaryCookies) {
_necessaryCookies = [..._necessaryCookies, ...customNecessaryCookies]
}
if (!adCookiesEnabled) {
const filteredCookies = _configuredServices.map((service) => ({
...service,
cookies: service?.cookies?.filter((cookie) => cookie?.category !== CookieCategory.Advertising)
}))
_configuredServices = filteredCookies
}

onConfiguredServicesInitialized?.(_configuredServices, _necessaryCookies)
}

export function stopCoreServices(
configuredServices: Service[],
removeAdditionalCookiesCb: () => void,
setServicesInitialized: (bool: boolean) => void
): void {
const googleAnalyticsUniversalConfig = configuredServices?.find(
({ type }) => type === SupportedService.GoogleAnalyticsUniversal
)
const googleAnalytics4Config = configuredServices?.find(
({ type }) => type === SupportedService.GoogleAnalytics4
)
removeGoogleAnalytics(googleAnalytics4Config?.id)
removeGoogleAnalytics(googleAnalyticsUniversalConfig?.id)
removeAdditionalCookiesCb()

setServicesInitialized?.(false)
}

export function setNecessaryCookies(
value: 'true' | 'false',
configuredServices: Service[],
necessaryCookies: ServiceCookie[],
setConfiguredServices: (services: Service[]) => void
): void {
const SKCM_NECESSARY_COOKIES: string[] = [
SKCM_GA_GOOGLE_ANALYTICS_UNIVERSAL_COOKIE?.name,
SKCM_GA_GOOGLE_ANALYTICS_4_COOKIE?.name
]
// set cookies
const neededCookies =
necessaryCookies?.filter(
(cookie) => cookie?.showDisclaimerIfMissing && SKCM_NECESSARY_COOKIES.includes(cookie?.name)
) ?? []
for (let i = 0; i < neededCookies?.length; i++) {
setCookie(neededCookies[i]?.name, value, COOKIE_EXPIRATION_DAYS)
}
// enable services
const _configuredServices = configuredServices?.map((service) => ({
...service,
enabled: value === 'true'
}))
setConfiguredServices(_configuredServices)
}

export function clearAdditionalCookies(necessaryCookies: ServiceCookie[]): void {
const _necessaryCookies = necessaryCookies.map((cookie) => cookie.name)
document.cookie
?.split('; ')
?.map((cookie) => cookie.split('=')[0])
.forEach((cookie) => {
if (!_necessaryCookies.includes(cookie)) {
deleteCookie(cookie)
}
})
}

// Check user has all needed necessary cookies already set
export function checkAllRequiredCookies(necessaryCookies: ServiceCookie[]): boolean {
const neededCookies = necessaryCookies?.filter((cookie) => cookie?.showDisclaimerIfMissing) ?? []
for (let i = 0; i < neededCookies?.length; i++) {
if (!getCookie(neededCookies[i].name)?.length) {
return false
}
}
return true
}
8 changes: 1 addition & 7 deletions cookie-manager/core/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
import type { CookieCategory } from './enums'

export enum SupportedService {
GoogleAnalyticsUniversal = 'googleAnalyticsUniversal',
GoogleAnalytics4 = 'googleAnalytics4',
CustomCookie = 'customNecessaryCookies'
}
import type { CookieCategory, SupportedService } from './enums'

export type Service = {
type: SupportedService
Expand Down
14 changes: 12 additions & 2 deletions cookie-manager/core/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Service, ServiceCookie, Theme } from './types'
import { DEFAULT_THEME_COLORS } from './constants'
import type { Theme } from './types'

/*
* General utils for managing cookies in Typescript.
Expand All @@ -13,13 +13,14 @@ export function getCookie(name: string): string | undefined {
return parts?.pop()?.split(';')?.shift() ?? undefined
}
}

export const setCookie = (name: string, val: string, expDays: number): void => {
const date = new Date()
const value = val
date.setTime(date.getTime() + expDays * 24 * 60 * 60 * 1000)
document.cookie = name + '=' + value + '; expires=' + date.toUTCString() + '; path=/'
}
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types

export function deleteCookie(name: string) {
const date = new Date()
date.setTime(date.getTime() + -1 * 24 * 60 * 60 * 1000)
Expand All @@ -35,3 +36,12 @@ export const getInlineStyle = (theme: Theme = {}): string => {
const mergedTheme = { ...DEFAULT_THEME_COLORS, ...theme }
return formatStyles(mergedTheme)
}

export function getAdditionalCookiesFromConfiguredServices(services: Service[]): ServiceCookie[] {
return services.reduce((accumulator, service) => {
const cookiesName = accumulator.map((cookie) => cookie.name)
const serviceCookies =
service?.cookies?.filter((cookie) => !cookiesName.includes(cookie.name)) ?? []
return accumulator.concat(serviceCookies)
}, [] as ServiceCookie[])
}
3 changes: 2 additions & 1 deletion cookie-manager/react/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module.exports = {
}
},
parserOptions: {
project: true
project: true,
ecmaVersion: 8
}
}
Loading

0 comments on commit a34707f

Please sign in to comment.