about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--app/javascript/flavours/glitch/features/privacy_policy/index.js60
-rw-r--r--app/javascript/flavours/glitch/features/ui/components/link_footer.js2
-rw-r--r--app/javascript/flavours/glitch/features/ui/index.js2
-rw-r--r--app/javascript/flavours/glitch/features/ui/util/async-components.js4
-rw-r--r--app/javascript/flavours/glitch/styles/components/columns.scss3
-rw-r--r--app/javascript/flavours/glitch/styles/components/index.scss1
-rw-r--r--app/javascript/flavours/glitch/styles/components/privacy_policy.scss84
7 files changed, 154 insertions, 2 deletions
diff --git a/app/javascript/flavours/glitch/features/privacy_policy/index.js b/app/javascript/flavours/glitch/features/privacy_policy/index.js
new file mode 100644
index 000000000..816010294
--- /dev/null
+++ b/app/javascript/flavours/glitch/features/privacy_policy/index.js
@@ -0,0 +1,60 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { title } from 'flavours/glitch/initial_state';
+import { Helmet } from 'react-helmet';
+import { FormattedMessage, FormattedDate, injectIntl, defineMessages } from 'react-intl';
+import Column from 'flavours/glitch/components/column';
+import api from 'flavours/glitch/api';
+import Skeleton from 'flavours/glitch/components/skeleton';
+
+const messages = defineMessages({
+  title: { id: 'privacy_policy.title', defaultMessage: 'Privacy Policy' },
+});
+
+export default @injectIntl
+class PrivacyPolicy extends React.PureComponent {
+
+  static propTypes = {
+    intl: PropTypes.object,
+  };
+
+  state = {
+    content: null,
+    lastUpdated: null,
+    isLoading: true,
+  };
+
+  componentDidMount () {
+    api().get('/api/v1/instance/privacy_policy').then(({ data }) => {
+      this.setState({ content: data.content, lastUpdated: data.updated_at, isLoading: false });
+    }).catch(() => {
+      this.setState({ isLoading: false });
+    });
+  }
+
+  render () {
+    const { intl } = this.props;
+    const { isLoading, content, lastUpdated } = this.state;
+
+    return (
+      <Column>
+        <div className='scrollable privacy-policy'>
+          <div className='column-title'>
+            <h3><FormattedMessage id='privacy_policy.title' defaultMessage='Privacy Policy' /></h3>
+            <p><FormattedMessage id='privacy_policy.last_updated' defaultMessage='Last updated {date}' values={{ date: isLoading ? <Skeleton width='10ch' /> : <FormattedDate value={lastUpdated} year='numeric' month='short' day='2-digit' /> }} /></p>
+          </div>
+
+          <div
+            className='privacy-policy__body'
+            dangerouslySetInnerHTML={{ __html: content }}
+          />
+        </div>
+
+        <Helmet>
+          <title>{intl.formatMessage(messages.title)} - {title}</title>
+        </Helmet>
+      </Column>
+    );
+  }
+
+}
diff --git a/app/javascript/flavours/glitch/features/ui/components/link_footer.js b/app/javascript/flavours/glitch/features/ui/components/link_footer.js
index cd32c8a3d..8c55a7337 100644
--- a/app/javascript/flavours/glitch/features/ui/components/link_footer.js
+++ b/app/javascript/flavours/glitch/features/ui/components/link_footer.js
@@ -54,7 +54,7 @@ class LinkFooter extends React.PureComponent {
     items.push(<a key='about' href='/about/more' target='_blank'><FormattedMessage id='navigation_bar.info' defaultMessage='About' /></a>);
     items.push(<a key='mastodon' href='https://joinmastodon.org' target='_blank'><FormattedMessage id='getting_started.what_is_mastodon' defaultMessage='About Mastodon' /></a>);
     items.push(<a key='docs' href='https://docs.joinmastodon.org' target='_blank'><FormattedMessage id='getting_started.documentation' defaultMessage='Documentation' /></a>);
-    items.push(<a key='privacy-policy' href='/privacy-policy' target='_blank'><FormattedMessage id='getting_started.privacy_policy' defaultMessage='Privacy Policy' /></a>);
+    items.push(<Link key='privacy-policy' to='/privacy-policy'><FormattedMessage id='getting_started.privacy_policy' defaultMessage='Privacy Policy' /></Link>);
     items.push(<Link key='hotkeys' to='/keyboard-shortcuts'><FormattedMessage id='navigation_bar.keyboard_shortcuts' defaultMessage='Hotkeys' /></Link>);
 
     if (profileDirectory) {
diff --git a/app/javascript/flavours/glitch/features/ui/index.js b/app/javascript/flavours/glitch/features/ui/index.js
index 8ea7a0b02..ea99e5097 100644
--- a/app/javascript/flavours/glitch/features/ui/index.js
+++ b/app/javascript/flavours/glitch/features/ui/index.js
@@ -53,6 +53,7 @@ import {
   Explore,
   FollowRecommendations,
   About,
+  PrivacyPolicy,
 } from './util/async-components';
 import { HotKeys } from 'react-hotkeys';
 import { me, title } from 'flavours/glitch/initial_state';
@@ -186,6 +187,7 @@ class SwitchingColumnsArea extends React.PureComponent {
           <WrappedRoute path='/getting-started' component={GettingStarted} content={children} />
           <WrappedRoute path='/keyboard-shortcuts' component={KeyboardShortcuts} content={children} />
           <WrappedRoute path='/about' component={About} content={children} />
+          <WrappedRoute path='/privacy-policy' component={PrivacyPolicy} content={children} />
 
           <WrappedRoute path={['/home', '/timelines/home']} component={HomeTimeline} content={children} />
           <WrappedRoute path={['/public', '/timelines/public']} exact component={PublicTimeline} content={children} />
diff --git a/app/javascript/flavours/glitch/features/ui/util/async-components.js b/app/javascript/flavours/glitch/features/ui/util/async-components.js
index 7ef06ceb7..5bf8d7fd6 100644
--- a/app/javascript/flavours/glitch/features/ui/util/async-components.js
+++ b/app/javascript/flavours/glitch/features/ui/util/async-components.js
@@ -185,3 +185,7 @@ export function Explore () {
 export function About () {
   return import(/*webpackChunkName: "features/glitch/async/about" */'flavours/glitch/features/about');
 }
+
+export function PrivacyPolicy () {
+  return import(/*webpackChunkName: "features/glitch/async/privacy_policy" */'flavours/glitch/features/privacy_policy');
+}
diff --git a/app/javascript/flavours/glitch/styles/components/columns.scss b/app/javascript/flavours/glitch/styles/components/columns.scss
index b63f2c86f..1827e8c01 100644
--- a/app/javascript/flavours/glitch/styles/components/columns.scss
+++ b/app/javascript/flavours/glitch/styles/components/columns.scss
@@ -357,7 +357,8 @@ $ui-header-height: 55px;
 
   > .scrollable {
     background: $ui-base-color;
-    border-radius: 0 0 4px 4px;
+    border-bottom-left-radius: 4px;
+    border-bottom-right-radius: 4px;
   }
 }
 
diff --git a/app/javascript/flavours/glitch/styles/components/index.scss b/app/javascript/flavours/glitch/styles/components/index.scss
index 1c3540b33..a04482a79 100644
--- a/app/javascript/flavours/glitch/styles/components/index.scss
+++ b/app/javascript/flavours/glitch/styles/components/index.scss
@@ -1778,3 +1778,4 @@ noscript {
 @import 'announcements';
 @import 'explore';
 @import 'signed_out';
+@import 'privacy_policy';
diff --git a/app/javascript/flavours/glitch/styles/components/privacy_policy.scss b/app/javascript/flavours/glitch/styles/components/privacy_policy.scss
new file mode 100644
index 000000000..f69bf1a07
--- /dev/null
+++ b/app/javascript/flavours/glitch/styles/components/privacy_policy.scss
@@ -0,0 +1,84 @@
+.privacy-policy {
+  background: $ui-base-color;
+  padding: 20px;
+
+  @media screen and (min-width: $no-gap-breakpoint) {
+    border-radius: 4px;
+  }
+
+  &__body {
+    margin-top: 20px;
+    color: $secondary-text-color;
+    font-size: 15px;
+    line-height: 22px;
+
+    h1,
+    p,
+    ul,
+    ol {
+      margin-bottom: 20px;
+    }
+
+    ul {
+      list-style: disc;
+    }
+
+    ol {
+      list-style: decimal;
+    }
+
+    ul,
+    ol {
+      padding-left: 1em;
+    }
+
+    li {
+      margin-bottom: 10px;
+
+      &::marker {
+        color: $darker-text-color;
+      }
+
+      &:last-child {
+        margin-bottom: 0;
+      }
+    }
+
+    h1 {
+      color: $primary-text-color;
+      font-size: 19px;
+      line-height: 24px;
+      font-weight: 700;
+      margin-top: 30px;
+
+      &:first-child {
+        margin-top: 0;
+      }
+    }
+
+    strong {
+      font-weight: 700;
+      color: $primary-text-color;
+    }
+
+    em {
+      font-style: italic;
+    }
+
+    a {
+      color: $highlight-text-color;
+      text-decoration: underline;
+
+      &:focus,
+      &:hover,
+      &:active {
+        text-decoration: none;
+      }
+    }
+
+    hr {
+      border: 1px solid lighten($ui-base-color, 4%);
+      margin: 30px 0;
+    }
+  }
+}