Compare commits

...

8 Commits

Author SHA1 Message Date
Joshua Chen 543b5df52b
better? 2022-01-16 20:34:03 +08:00
Joshua Chen f1b5b66813
get latest value 2022-01-16 19:12:33 +08:00
Joshua Chen 137c31550d
Better styling 2022-01-16 19:07:33 +08:00
Joshua Chen 293ac8bf6a
fix 2022-01-16 17:31:47 +08:00
Joshua Chen 888d259313
dismiss 2022-01-16 17:19:15 +08:00
Joshua Chen 7a17da02cd
temporarily disable 2022-01-16 17:13:35 +08:00
Joshua Chen 6139b89e21
fix 2022-01-16 17:10:03 +08:00
Joshua Chen 14046ed738
feat(gtag): cookie consent banner 2022-01-16 16:58:49 +08:00
10 changed files with 181 additions and 12 deletions

View File

@ -0,0 +1,20 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import fs from 'fs-extra';
import {fileURLToPath} from 'url';
/**
* Copy all untyped and static assets files to lib.
*/
const srcDir = fileURLToPath(new URL('src', import.meta.url));
const libDir = fileURLToPath(new URL('lib', import.meta.url));
await fs.copy(srcDir, libDir, {
filter(filepath) {
return !/__tests__/.test(filepath) && !/\.tsx?$/.test(filepath);
},
});

View File

@ -5,8 +5,11 @@
"main": "lib/index.js",
"types": "src/plugin-google-gtag.d.ts",
"scripts": {
"build": "tsc",
"watch": "tsc --watch"
"build": "yarn build:server && yarn build:browser && yarn build:copy && yarn build:format",
"build:server": "tsc --project tsconfig.server.json",
"build:browser": "tsc --project tsconfig.browser.json",
"build:copy": "node copyUntypedFiles.mjs",
"build:format": "prettier --config ../../.prettierrc --write \"lib/**/*.js\""
},
"publishConfig": {
"access": "public"
@ -19,7 +22,9 @@
"license": "MIT",
"dependencies": {
"@docusaurus/core": "2.0.0-beta.14",
"@docusaurus/theme-common": "2.0.0-beta.14",
"@docusaurus/utils-validation": "2.0.0-beta.14",
"clsx": "^1.1.1",
"tslib": "^2.3.1"
},
"devDependencies": {

View File

@ -5,20 +5,50 @@
* LICENSE file in the root directory of this source tree.
*/
import React from 'react';
import ReactDOM from 'react-dom';
import CookieConsent from '@theme/CookieConsent';
import ExecutionEnvironment from '@docusaurus/ExecutionEnvironment';
import globalData from '@generated/globalData';
import type {PluginOptions} from '@docusaurus/plugin-google-gtag';
declare global {
interface Window {
'ga-disable-MEASUREMENT_ID': boolean;
}
}
export default (function () {
if (!ExecutionEnvironment.canUseDOM) {
return null;
}
window.onload = () => {
const cookieConsentResponse = JSON.parse(
localStorage.getItem('docusaurus.cookieConsent') ?? 'null',
) as boolean | null;
if (cookieConsentResponse === null) {
const consentBannerContainer = document.createElement('div');
document
.getElementById('__docusaurus')!
.appendChild(consentBannerContainer);
ReactDOM.render(<CookieConsent />, consentBannerContainer);
}
};
const {trackingID} = globalData['docusaurus-plugin-google-gtag']
.default as PluginOptions;
return {
onRouteUpdate({location}: {location: Location}) {
// Always get the latest value on every route transition
const cookieConsentResponse = JSON.parse(
localStorage.getItem('docusaurus.cookieConsent') ?? 'null',
) as boolean | null;
if (!cookieConsentResponse) {
window['ga-disable-MEASUREMENT_ID'] = true;
return;
}
// Always refer to the variable on window in-case it gets overridden elsewhere.
window.gtag('config', trackingID, {
page_path: location.pathname,

View File

@ -35,6 +35,13 @@ export default function pluginGoogleGtag(
return isProd ? [path.resolve(__dirname, './gtag')] : [];
},
getThemePath() {
return path.resolve(__dirname, '../lib/theme');
},
getTypeScriptThemePath() {
return path.resolve(__dirname, '../src/theme');
},
injectHtmlTags() {
if (!isProd) {
return {};

View File

@ -5,9 +5,15 @@
* LICENSE file in the root directory of this source tree.
*/
declare module '@docusaurus/plugin-google-gtag' {
export type PluginOptions = {
trackingID: string;
anonymizeIP: boolean;
};
export type Options = Partial<PluginOptions>;
}
declare module '@theme/CookieConsent' {
export default function CookieConsent(): JSX.Element | null;
}

View File

@ -0,0 +1,48 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
import React, {useState} from 'react';
import clsx from 'clsx';
import styles from './styles.module.css';
import {createStorageSlot} from '@docusaurus/theme-common';
const storage = createStorageSlot('docusaurus.cookieConsent');
export default function CookieConsent(): JSX.Element | null {
const [dismissed, setDismissed] = useState(false);
if (dismissed) {
return null;
}
return (
<div className={styles.banner}>
<p className={styles.text}>
This website uses cookies to help us improve. Click &quot;accept&quot;
to allow us to continue using cookies.
</p>
<div className={styles.buttons}>
<button
type="button"
className={clsx('clean-btn', styles.button)}
onClick={() => {
storage.set('true');
setDismissed(true);
}}>
Accept
</button>
<button
type="button"
className={clsx('clean-btn', styles.button)}
onClick={() => {
storage.set('false');
setDismissed(true);
}}>
Deny
</button>
</div>
</div>
);
}

View File

@ -0,0 +1,43 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
.banner {
background-color: var(--ifm-color-emphasis-200);
position: fixed;
bottom: 20px;
right: 20px;
width: 300px;
height: 200px;
border-radius: var(--ifm-global-radius);
box-shadow: 0 1.5px 6px 0 rgba(0, 0, 0, 0.15) inset;
}
.text {
font-size: small;
padding: 30px;
}
.buttons {
position: absolute;
bottom: 20px;
display: flex;
justify-content: center;
width: 100%;
}
.button {
width: 100px;
background-color: #d0d0d0 !important;
margin: 10px;
/* TODO this is because the CSS is imported as a client module as well, and happens to be before Infima */
padding: 5px !important;
border-radius: var(--ifm-global-radius);
}
html[data-theme='dark'] .button {
background: #333333 !important;
}

View File

@ -0,0 +1,8 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "esnext",
"jsx": "react-native"
},
"include": ["src/theme/", "src/*.d.ts"]
}

View File

@ -0,0 +1,4 @@
{
"extends": "./tsconfig.json",
"include": ["src/*.ts", "src/*.tsx"]
}

View File

@ -300,11 +300,9 @@ const config = {
theme: {
customCss: [require.resolve('./src/css/custom.css')],
},
gtag: !isDeployPreview
? {
gtag: {
trackingID: 'UA-141789564-1',
}
: undefined,
},
}),
],
],