Skip to content

Commit

Permalink
adds conditional cookie banner for notifying users that data is being…
Browse files Browse the repository at this point in the history
… collected
  • Loading branch information
seanfeld committed Aug 1, 2023
1 parent 7b60c82 commit 6c8a8e9
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 0 deletions.
17 changes: 17 additions & 0 deletions app/cdap/components/CookieBanner/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright © 2023 Cask Data, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/

export const DEFAULT_COOKIE_LINK = 'https://policies.google.com/technologies/cookies';
144 changes: 144 additions & 0 deletions app/cdap/components/CookieBanner/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
/*
* Copyright © 2023 Cask Data, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
import React, { useState } from 'react';
import styled from 'styled-components';
import SnackBar from '@material-ui/core/Snackbar';
import Button from '@material-ui/core/Button';
import IconButton from '@material-ui/core/IconButton';
import ClearIcon from '@material-ui/icons/Clear';
import Container from '@material-ui/core/Container';
import Cookies from 'universal-cookie';
import T from 'i18n-react';
import { DEFAULT_COOKIE_LINK } from './constants';

const okText = 'commons.gotIt';
const learnMore = 'commons.learnMore';
const cookieBannerText = 'commons.cookieBanner';

const thirteenMonths = new Date();
thirteenMonths.setMonth(thirteenMonths.getMonth() + 13);

const cookies = new Cookies();
const cdapDataCookieWithTag = (tag: string) => {
return `CDAP_DATA_CONSENT_COOKIE_${tag}`;
};

interface IBannerProps {
cookieName: string;
cookieLink: string;
cookieText: string;
}

type IModalBodyProps = Omit<IBannerProps, 'cookieName'> & {
close: () => void;
};

const SnackbarContainer = styled(Container)`
&& {
background-color: #333333;
border-radius: 4px;
display: flex;
padding: 20px;
}
`;

const SnackbarText = styled.span`
color: white;
flex: 3;
font-size: 13px;
font-weight: 400;
line-height: 20px;
a {
color: #a1c2fa;
}
`;

const ActionsContainer = styled.div`
flex: 1;
display: flex;
justify-content: space-evenly;
`;

const ConsentButton = styled(Button)`
&&& {
color: #a1c2fa;
font-size: 14px;
whitespace: nowrap;
}
`;

const SnackbarContent = ({ cookieLink, cookieText, close }: IModalBodyProps) => {
return (
<SnackbarContainer fixed maxWidth="md">
<SnackbarText>
{cookieText} <a href={cookieLink}>{T.translate(learnMore).toString()}</a>
</SnackbarText>
<ActionsContainer>
<ConsentButton variant="text" onClick={close}>
{T.translate(okText).toString()}
</ConsentButton>
<IconButton onClick={close} aria-label="close">
<ClearIcon fontSize="large" style={{ color: 'white' }} />
</IconButton>
</ActionsContainer>
</SnackbarContainer>
);
};

/**
* If the user has analytics enabled and if the consent cookie doesn't exist
* on their computer, show the cookie banner
*/
export const CookieBanner = () => {
const gtm = window.CDAP_CONFIG.googleTagManager;
if (gtm === '') {
return null;
}

const cookieText =
window.CDAP_CONFIG.cookieBannerText || T.translate(cookieBannerText).toString();
const cookieLink = window.CDAP_CONFIG.cookieBannerLink || DEFAULT_COOKIE_LINK;
const dataCookie = cdapDataCookieWithTag(gtm);
const cdapDataConsented = cookies.get(dataCookie);
if (!cdapDataConsented && cookieLink !== '' && cookieText !== '') {
return <Banner cookieName={dataCookie} cookieLink={cookieLink} cookieText={cookieText} />;
}

return null;
};

const Banner = ({ cookieName, cookieLink, cookieText }: IBannerProps) => {
const [open, setOpen] = useState(true);

const handleClose = () => {
setOpen(false);
cookies.set(cookieName, true, {
expires: thirteenMonths,
path: '/',
});
};

return (
<SnackBar
anchorOrigin={{ vertical: 'bottom', horizontal: 'center' }}
open={open}
onClose={handleClose}
style={{ display: 'flex' }}
>
<SnackbarContent close={handleClose} cookieLink={cookieLink} cookieText={cookieText} />
</SnackBar>
);
};
2 changes: 2 additions & 0 deletions app/cdap/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import ee from 'event-emitter';
import globalEvents from 'services/global-events';
import { handlePageLevelError, objectQuery, setupExperiments } from 'services/helpers';
import history from 'services/history';
import { CookieBanner } from 'components/CookieBanner';
// See ./graphql/fragements/README.md
import introspectionQueryResultData from '../../graphql/fragments/fragmentTypes.json';

Expand Down Expand Up @@ -365,6 +366,7 @@ class CDAP extends Component {
objectQuery(this.state, 'pageLevelError', 'errorCode') === 403;
return (
<Router history={history}>
<CookieBanner />
<ApolloProvider client={client}>
<div className="cdap-container">
<Helmet title={Theme.productName} />
Expand Down
3 changes: 3 additions & 0 deletions app/cdap/text/text-en.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ commons:
apply: Apply
as: as
back: Back
learnMore: Learn More
gotIt: Ok, Got it.
cookieBanner: CDF uses cookies from Google to deliver and enhance the quality of its services and to analyze traffic.
cask: CASK
cdap: CDAP
clickhere: click here
Expand Down
3 changes: 3 additions & 0 deletions server/express.js
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,9 @@ function makeApp(authAddress, cdapConfig, uiSettings) {
featureFlags: cdapConfig.featureFlags,
analyticsTag: cdapConfig['ui.analyticsTag'],
googleTagManager: cdapConfig['ui.GTM'],
cookieBannerText: cdapConfig['ui.cookieBannerText'],
cookieBannerLink: cdapConfig['ui.cookieBannerLink']

});

res.header({
Expand Down

0 comments on commit 6c8a8e9

Please sign in to comment.