diff --git a/src/App.jsx b/src/App.jsx index 0b5a37b18..5c9a397d1 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -7,6 +7,7 @@ import { getMetadataRequest } from '@reducers/metadata'; import RouteChange from '@components/main/util/RouteChange'; import actions from '@components/main/util/routeChangeActions'; +import CookieNotice from '@components/main/body/CookieNotice'; import Routes from './Routes'; import Header from './components/main/header/Header'; import Footer from './components/main/footer/Footer'; @@ -26,10 +27,11 @@ const App = ({
- + + ); }; diff --git a/src/Routes.jsx b/src/Routes.jsx index aec28ce97..0f59829e0 100644 --- a/src/Routes.jsx +++ b/src/Routes.jsx @@ -4,6 +4,7 @@ import { Route, } from 'react-router-dom'; +import PrivacyPolicy from '@components/privacyPolicy/PrivacyPolicy'; import Contact from './components/contact/Contact'; import About from './components/about/About'; import Body from './components/main/body/Body'; @@ -13,6 +14,7 @@ export default function Routes() { + diff --git a/src/components/main/body/CookieNotice.jsx b/src/components/main/body/CookieNotice.jsx new file mode 100644 index 000000000..83f9f99b8 --- /dev/null +++ b/src/components/main/body/CookieNotice.jsx @@ -0,0 +1,63 @@ +import React from 'react'; +import PropTypes from 'proptypes'; +import { Link } from 'react-router-dom'; +import { connect } from 'react-redux'; +import { acceptCookies } from '@reducers/ui'; + +import Button from '@components/common/Button'; +import Icon from '@components/common/Icon'; + + +const CookieNotice = ({ + showCookieNotice, + acceptCookieNotice, +}) => { + const handleClick = () => { + acceptCookieNotice(); + sessionStorage.setItem('accept-cookies', true); + }; + + if (showCookieNotice) { + return ( +
+
+ + Cookies and Privacy Policy +
+
+ We use cookies and other tracking technologies to improve your browsing experience and to + better understand our website traffic. By browsing our website, you consent to our use of + cookies and other tracking technologies.  + Learn more +
+
+ ); + } + return null; +}; + +const mapStateToProps = state => ({ + showCookieNotice: !state.ui.cookiesAccepted, +}); + +const mapDispatchToProps = dispatch => ({ + acceptCookieNotice: () => dispatch(acceptCookies()), +}); + +CookieNotice.propTypes = { + showCookieNotice: PropTypes.bool.isRequired, + acceptCookieNotice: PropTypes.func.isRequired, +}; + +export default connect(mapStateToProps, mapDispatchToProps)(CookieNotice); diff --git a/src/components/main/footer/StaticFooter.jsx b/src/components/main/footer/StaticFooter.jsx index aa5640ab5..46a1b0339 100644 --- a/src/components/main/footer/StaticFooter.jsx +++ b/src/components/main/footer/StaticFooter.jsx @@ -1,4 +1,5 @@ import React from 'react'; +import { Link } from 'react-router-dom'; const StaticFooter = () => (
@@ -11,11 +12,7 @@ const StaticFooter = () => ( EmpowerLA
- {/* **** NEED TO REPLACE HREF WITH VALID LINK WHEN AVAILABLE **** */} - Terms & Conditions -   |   - {/* **** NEED TO REPLACE HREF WITH VALID LINK WHEN AVAILABLE **** */} - Privacy Policy + Privacy Policy
); diff --git a/src/components/main/header/Header.jsx b/src/components/main/header/Header.jsx index 625ea3fc6..64fb709a7 100644 --- a/src/components/main/header/Header.jsx +++ b/src/components/main/header/Header.jsx @@ -27,6 +27,9 @@ const Header = () => {

311

DATA

+
+ BETA +
diff --git a/src/components/main/util/routeChangeActions.js b/src/components/main/util/routeChangeActions.js index 5aed0c33c..85a2adc0d 100644 --- a/src/components/main/util/routeChangeActions.js +++ b/src/components/main/util/routeChangeActions.js @@ -1,5 +1,8 @@ import queryString from 'query-string'; import Mixpanel from '@utils/Mixpanel'; +import { acceptCookies } from '@reducers/ui'; +import store from '../../../redux/store'; + const handleReferralCode = ( location, @@ -25,8 +28,16 @@ const logAboutPageVisit = location => { } }; +const checkAcceptedCookies = () => { + const { ui } = store.getState(); + if (sessionStorage.getItem('accept-cookies') && !ui.cookiesAccepted) { + store.dispatch(acceptCookies()); + } +}; + export default [ handleReferralCode, logAboutPageVisit, + checkAcceptedCookies, ]; diff --git a/src/components/privacyPolicy/PrivacyPolicy.jsx b/src/components/privacyPolicy/PrivacyPolicy.jsx new file mode 100644 index 000000000..a43f9288d --- /dev/null +++ b/src/components/privacyPolicy/PrivacyPolicy.jsx @@ -0,0 +1,385 @@ +import React from 'react'; + +const PrivacyPolicy = () => ( +
+

Privacy policy

+

+ We respect your privacy, and recognize that we must maintain and use your information + responsibly. +

+ + {/* ---------- LEDE ---------- */} + +
+

+ {`311-data.org is a nonprofit website run by Hack for LA which is a brigade of Code for America Labs, Inc. + ("Code for America", "we", "us", "our"). This Privacy Policy describes how we collect, use, and protect your + personal information on our websites (Sites), including the `} + 311-Data Project Website +  ("311-data.org"), and our  + 311 Report Generator Website + {` ("https://hackforla.github.io/311-report/") By submitting your personal information on our websites, you agree + to the terms in this Privacy Policy. If you do not agree with these terms, please do not use our websites.`} +

+
+ + {/* ---------- OVERVIEW ---------- */} + +
+

Overview

+
    +
  • + {`We collect information from you when you visit and take actions on our website. We use this information to provide + the services you've requested.`} +
  • +
  • + We use cookies (such as those stored by Google Analytics) to provide a better + experience and improve our website. +
  • +
  • + We will not knowingly disclose or sell your personal information to any third + party, except as provided in this privacy policy. +
  • +
  • + Protecting your personal information is extremely important to us and we take all + reasonable measures to do so. +
  • +
+
+ + {/* ---------- PERSONAL INFORMATION WE COLLECT ---------- */} + +
+

The personal information we collect

+

Visiting 311-data.org

+
    +
  • + We automatically collect and store data about your visit to 311-data.org: +
      +
    • + Domain from which you access the Internet +
    • +
    • + Operating system on your computer and information about the browser you used + when visiting the site +
    • +
    • + Date and time of your visit +
    • +
    • + Pages you visited +
    • +
    • + Address of the website that connects you to the Site + (such as google.com or bing.com) +
    • +
    • + The queries you make on our site. (E.G. last 6 months of data for bulky items) +
    • +
    +
  • +
  • + None of the information we collect about you when you visit 311-data.org is personally + identifiable unless you submit your contact information in the form on the Contact Us + submit page. +
  • +
  • + We use this non personally identifiable information to understand how the 311-data.org + website is used, to improve the website, and to monitor usage for security purposes. +
  • +
  • + We will not collect personal information from you without your knowledge and consent, + except in a few limited circumstances as described in this policy. +
  • +
+ +

Filling in Webforms such as Contact Us

+
    +
  • + We use github to process requests from our contact us page. +
  • +
  • + When you submit the contact us form, your personal data will be transferred to github + and a ticket is created so someone from our team can get back to you. +
  • +
  • + The personal data we collect when you sign up to our mailing list includes: +
      +
    • + Your name +
    • +
    • + Your email address +
    • +
    • + Domain from which you access the Internet +
    • +
    • + IP address +
    • +
    • + Operating system on your computer and information about the browser you used when + visiting the site +
    • +
    • + Date and time when you submit the form +
    • +
    • + Address of the page on our website, or the third-party website that connected you + to sign-up form +
    • +
    +
  • +
  • + {`We use the collected email addresses of our contact us form to respond to people's requests. + If you are interested in additional information about Hack for LA or Code for America, feel free to reach out.`} +
  • +
  • + We use the personal data we collect to understand how people ask us questions and to + improve the experience of doing so. +
  • +
+ +

Google Analytics

+
    +
  • + We use Google Analytics to understand how visitors use our site and to gather aggregate + performance metrics. +
  • +
  • + We’ve set up Google Analytics so that it doesn’t collect your full IP address. +
  • +
  • + {`We don’t collect any personally identifiable information using Google Analytics, and we do not combine the information + collected through Google Analytics with any personally identifiable information.`} +
  • +
  • + {`Google Analytics places a cookie on your web browser to identify you as a unique user. This cookie cannot be used by anyone but Google. + Google's ability to use and share information collected by Google Analytics about your visits to this site is restricted by the `} + Google Analytics Terms of Use +  and the  + Google Privacy Policy + . +
  • +
+
+ + {/* ---------- COOKIES AND OTHER TRACKING TECHNOLOGIES ---------- */} + +
+

Cookies and other tracking technologies

+
    +
  • + Cookies are small text files that websites place on the computers and mobile devices of + people who visit those websites. Pixel tags (also called web beacons) are small blocks of + code placed on websites and emails. +
  • +
  • + We use cookies and other technologies like pixel tags to remember your preferences, + enhance your online experience, and to gather data on how you use our Sites to improve + the way we promote our content, programs, and events. +
  • +
  • + Your use of our Sites indicates your consent to such use of Cookies. +
  • +
+ +

Third party service providers

+

+ We use third-party service providers to track and analyze statistical usage and volume + information from our Site users. These third-party service providers use persistent + Cookies to help us to improve the user experience, manage the content on our Sites, and + analyze how users navigate and use the Sites. +

+

+ Third-party service providers we use include  + Google Analytics + {', '} + Mixpanel + {', '} + Eventbrite + {', '} + Donorbox + {', '} + Medium + {', '} + Twitter + {', '} + Facebook + {', '} + LinkedIn + . +

+ +

How to opt-out of the use of cookies

+

+ Most browsers are initially set up to accept HTTP cookies. If you want to restrict or + block the cookies that are set by our Site, or any other site, you can do so through your + browser setting. The ‘Help’ function in your browser should explain how. + Alternatively, you can visit  + www.aboutcookies.org + {', '} + which contains comprehensive information on how to do this on a wide variety of browsers. + You will find general information about cookies and details on how to delete cookies from + your machine. +

+
+ + {/* ---------- AS REQUIRED BY LAW AND SIMILAR DISCLOSURES ---------- */} + +
+

As required by law and similar disclosures

+
    +
  • + We may access, preserve, and disclose your information if we believe doing so is required + or appropriate to: +
      +
    • + comply with law enforcement requests and legal process, such as a court order or + subpoena; +
    • +
    • + respond to your requests; or +
    • +
    • + protect your, our, or others’ rights, property, or safety. +
    • +
    +
  • +
  • + For the avoidance of doubt, the disclosure of your information may occur if you post any + objectionable content on or through the Site. +
  • +
+
+ + {/* ---------- MERGER, SALE, OR OTHER ASSET TRANSFERS ---------- */} + +
+

Merger, sale, or other asset transfers

+
    +
  • + We may transfer your information to service providers, advisors, potential transactional + partners, or other third parties in connection with the consideration, negotiation, or + completion of a corporate transaction in which we are acquired by or merged with another + company or we sell, liquidate, or transfer all or a portion of our assets. The use of your + information following any of these events will be governed by the provisions of this + Privacy Policy in effect at the time the applicable information was collected. +
  • +
+
+ + {/* ---------- CONSENT ---------- */} + +
+

Consent

+
    +
  • + We may also disclose information from you or about you or your devices with your + permission. +
  • +
+
+ + {/* ---------- CHILDREN'S PRIVACY ---------- */} + +
+

Children’s privacy

+
    +
  • + We do not knowingly collect, maintain, or use personal information from children under + 13 years of age, and no part of our Site is directed to children. +
  • +
  • + If you learn that a child has provided us with personal information in violation of this + Privacy Policy, then you may alert us at  + info@codeforamerica.org + . +
  • +
+
+ + {/* ---------- SECURITY ---------- */} + +
+

Security

+
    +
  • + We make reasonable efforts to protect your information by using physical and electronic + safeguards designed to improve the security of the information we maintain. However, as + our Services are hosted electronically, we can make no guarantees as to the security or + privacy of your information. +
  • +
+
+ + {/* ---------- RIGHT TO BE FORGOTTEN AND RECTIFICATION ---------- */} + +
+

Right to be forgotten and rectification

+
    +
  • + You may request that we delete your personal data at any time. Requests can + be submitted to  + privacy@codeforamerica.org + . +
  • +
  • + You may request that we make corrections to your personal data at any time. You may + request that incomplete data be completed or that incorrect data be corrected. Requests + can be submitted to  + privacy@codeforamerica.org + . +
  • +
+
+ + {/* ---------- CHANGES ---------- */} + +
+

Changes

+

+ We may change this Privacy Policy from time to time. Please check this page frequently for + updates as your continued use of this site after any changes in this Privacy Policy will + constitute your acceptance of the changes. +

+
+ + {/* ---------- EFFECTIVE DATE ---------- */} + +
+

Effective Date

+

+ This version of the policy is effective  + July 29, 2019 + . +

+
+ + {/* ---------- QUESTIONS ---------- */} + +
+

Questions

+

+ If you have any questions, comments, concerns, or complaints related to our websites, please + contact us by email at  + info@codeforamerica.org + , by phone at  + (415) 816-1286 + , or by mail at: +
+
+ Code for America +
+ 155 9th Street +
+ San Francisco, CA 94103 +
+
+ We will do our best to resolve the issue. +

+
+
+); + +export default PrivacyPolicy; diff --git a/src/redux/reducers/ui.js b/src/redux/reducers/ui.js index 6e688af42..06b9f9c5e 100644 --- a/src/redux/reducers/ui.js +++ b/src/redux/reducers/ui.js @@ -8,6 +8,7 @@ export const types = { SHOW_COMPARISON_CHARTS: 'SHOW_COMPARISON_CHARTS', SHOW_FEEDBACK_SUCCESS: 'SHOW_FEEDBACK_SUCCESS', UPDATE_MAP_POSITION: 'UPDATE_MAP_POSITION', + ACCEPT_COOKIES: 'ACCEPT_COOKIES', }; export const toggleMenu = () => ({ @@ -44,6 +45,10 @@ export const updateMapPosition = position => ({ payload: position, }); +export const acceptCookies = () => ({ + type: types.ACCEPT_COOKIES, +}); + const initialState = { menu: { isOpen: true, @@ -56,6 +61,7 @@ const initialState = { showDataCharts: false, showComparisonCharts: false, displayFeedbackSuccess: false, + cookiesAccepted: false, }; export default (state = initialState, action) => { @@ -104,6 +110,11 @@ export default (state = initialState, action) => { ...state, map: action.payload, }; + case types.ACCEPT_COOKIES: + return { + ...state, + cookiesAccepted: true, + }; default: return state; } diff --git a/src/styles/main/_cookie-notice.scss b/src/styles/main/_cookie-notice.scss new file mode 100644 index 000000000..9bd7c72bf --- /dev/null +++ b/src/styles/main/_cookie-notice.scss @@ -0,0 +1,32 @@ +.cookie-notice { + position: fixed; + bottom: $footer-height; + right: 0; + margin-bottom: 20px; + margin-right: 10px; + padding: 15px; + background-color: $brand-bg-color; + color: $brand-text-color; + width: 325px; + max-width: 100%; + border-left: 4px solid $brand-cta1-color; + box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25); + z-index: $z-modal; + + .cookie-title { + font-family: $brand-heading-family; + margin-bottom: 5px; + } + + .text { + padding-right: 5px; + margin-bottom: 10px; + } + + #btn-cookie-notice { + @extend .cta-button; + font-size: 14px; + box-shadow: none; + float: right; + } +} \ No newline at end of file diff --git a/src/styles/main/_header.scss b/src/styles/main/_header.scss index d3cf2f008..3dc827070 100644 --- a/src/styles/main/_header.scss +++ b/src/styles/main/_header.scss @@ -19,4 +19,27 @@ padding-bottom: 2px; margin-bottom: -7px; } + + .beta-tag-wrapper { + padding-left: 0; + .beta-tag { + position:relative; + background:$brand-bg-color; + padding:3px; + border-radius:2px; + line-height: 12px; + font-size: 12px; + &:before { + position:absolute; + top:5px; + background: $brand-main-color; + margin-left:-10px; + z-index: -1; + border-top: 4px solid transparent; + border-right: 10px solid $brand-bg-color; + border-bottom: 4px solid transparent; + content:''; + } + } + } } diff --git a/src/styles/privacy/_privacy-policy.scss b/src/styles/privacy/_privacy-policy.scss new file mode 100644 index 000000000..34a10f74c --- /dev/null +++ b/src/styles/privacy/_privacy-policy.scss @@ -0,0 +1,45 @@ +.privacy-policy-container { + position: absolute; + top: $header-height; + bottom: $footer-height; + overflow-y: auto; + padding-top: 50px; + padding-bottom: 50px; + padding-left: 25%; + padding-right: 25%; + background-color: $brand-bg-color; + color: $brand-text-color; + + h1, h2, h3 { + font-family: $brand-text-family; + } + + h2 { + font-size: 24px; + } + + h3 { + font-size: 18px; + margin-top: 25px; + } + + p { + margin-top: 12px; + } + + section { + padding-top: 20px; + padding-bottom: 20px; + } + + ul { + list-style-type: disc; + li { + margin: 12px; + } + } + + .sub-list { + list-style-type: circle; + } +} \ No newline at end of file diff --git a/src/styles/styles.scss b/src/styles/styles.scss index 7d25eb5f2..4b793670b 100644 --- a/src/styles/styles.scss +++ b/src/styles/styles.scss @@ -14,6 +14,7 @@ @import './main/body'; @import './main/footer'; @import './main/staticfooter'; +@import './main/cookie-notice'; @import './menu/menu'; @import './menu/datepicker'; @@ -42,3 +43,5 @@ @import './contact/contactimage'; @import './contact/contactintro'; @import './contact/contactform'; + +@import './privacy/privacy-policy';