From a6d4d4ea3679c2159302a5bb8b08403b5a4a50ce Mon Sep 17 00:00:00 2001 From: Saumya Pandey Date: Thu, 10 Jun 2021 06:12:14 +0530 Subject: [PATCH] fix: Add Portugese, Brazil to language options (#2164) * Add Portugese, Brazil to language options * Upgrade date-fns package Co-authored-by: Tom Moor --- .../DocumentHistory/components/Revision.js | 4 +-- app/components/DocumentViews.js | 4 +-- app/components/LocaleTime.js | 27 ++++++++++--------- app/components/Time.js | 4 +-- app/hooks/useUserLocale.js | 2 +- app/models/Document.js | 3 +-- app/routes/authenticated.js | 7 +++-- app/scenes/Document/components/DataLoader.js | 11 +++++--- .../Document/components/SharePopover.js | 11 +++++--- app/scenes/UserProfile.js | 4 +-- package.json | 2 +- server/api/attachments.js | 4 +-- server/api/utils.js | 2 +- server/api/utils.test.js | 2 +- server/auth/index.js | 2 +- server/auth/providers/email.js | 2 +- server/models/User.js | 3 +-- server/models/View.js | 2 +- server/services/websockets.js | 2 +- server/utils/authentication.js | 2 +- server/utils/jwt.js | 2 +- server/utils/passport.js | 3 +-- server/utils/s3.js | 9 +++---- shared/i18n/index.js | 1 + shared/utils/date.js | 11 +++----- webpack.config.js | 21 +++++++++++---- yarn.lock | 8 +++--- 27 files changed, 85 insertions(+), 70 deletions(-) diff --git a/app/components/DocumentHistory/components/Revision.js b/app/components/DocumentHistory/components/Revision.js index 2c29cb2ea..f1469f89b 100644 --- a/app/components/DocumentHistory/components/Revision.js +++ b/app/components/DocumentHistory/components/Revision.js @@ -1,5 +1,5 @@ // @flow -import format from "date-fns/format"; +import { format } from "date-fns"; import * as React from "react"; import { NavLink } from "react-router-dom"; import styled, { withTheme } from "styled-components"; @@ -37,7 +37,7 @@ class RevisionListItem extends React.Component { {showMenu && ( diff --git a/app/components/DocumentViews.js b/app/components/DocumentViews.js index 143524647..0d012ee94 100644 --- a/app/components/DocumentViews.js +++ b/app/components/DocumentViews.js @@ -1,5 +1,5 @@ // @flow -import distanceInWordsToNow from "date-fns/distance_in_words_to_now"; +import { formatDistanceToNow } from "date-fns"; import { sortBy } from "lodash"; import { observer } from "mobx-react"; import * as React from "react"; @@ -55,7 +55,7 @@ function DocumentViews({ document, isOpen }: Props) { ? t("Currently editing") : t("Currently viewing") : t("Viewed {{ timeAgo }} ago", { - timeAgo: distanceInWordsToNow( + timeAgo: formatDistanceToNow( view ? new Date(view.lastViewedAt) : new Date() ), }); diff --git a/app/components/LocaleTime.js b/app/components/LocaleTime.js index c872cd36b..2e5f09b67 100644 --- a/app/components/LocaleTime.js +++ b/app/components/LocaleTime.js @@ -1,20 +1,21 @@ // @flow -import distanceInWordsToNow from "date-fns/distance_in_words_to_now"; -import format from "date-fns/format"; +import { format, formatDistanceToNow } from "date-fns"; +import { enUS, de, fr, es, it, ko, ptBR, pt, zhCN, ru } from "date-fns/locale"; import * as React from "react"; import Tooltip from "components/Tooltip"; import useUserLocale from "hooks/useUserLocale"; const locales = { - en: require(`date-fns/locale/en`), - de: require(`date-fns/locale/de`), - es: require(`date-fns/locale/es`), - fr: require(`date-fns/locale/fr`), - it: require(`date-fns/locale/it`), - ko: require(`date-fns/locale/ko`), - pt: require(`date-fns/locale/pt`), - zh: require(`date-fns/locale/zh_cn`), - ru: require(`date-fns/locale/ru`), + en_US: enUS, + de_DE: de, + es_ES: es, + fr_FR: fr, + it_IT: it, + ko_KR: ko, + pt_BR: ptBR, + pt_PT: pt, + zh_CN: zhCN, + ru_RU: ru, }; let callbacks = []; @@ -64,7 +65,7 @@ function LocaleTime({ }; }, []); - let content = distanceInWordsToNow(dateTime, { + let content = formatDistanceToNow(Date.parse(dateTime), { addSuffix, locale: userLocale ? locales[userLocale] : undefined, }); @@ -78,7 +79,7 @@ function LocaleTime({ return ( diff --git a/app/components/Time.js b/app/components/Time.js index 5ed0d931b..96a2e5faf 100644 --- a/app/components/Time.js +++ b/app/components/Time.js @@ -1,5 +1,5 @@ // @flow -import distanceInWordsToNow from "date-fns/distance_in_words_to_now"; +import { formatDistanceToNow } from "date-fns"; import * as React from "react"; const LocaleTime = React.lazy(() => @@ -15,7 +15,7 @@ type Props = { }; function Time(props: Props) { - let content = distanceInWordsToNow(props.dateTime, { + let content = formatDistanceToNow(Date.parse(props.dateTime), { addSuffix: props.addSuffix, }); diff --git a/app/hooks/useUserLocale.js b/app/hooks/useUserLocale.js index e786dff1e..bd7f4894f 100644 --- a/app/hooks/useUserLocale.js +++ b/app/hooks/useUserLocale.js @@ -8,5 +8,5 @@ export default function useUserLocale() { return undefined; } - return auth.user.language.split("_")[0]; + return auth.user.language; } diff --git a/app/models/Document.js b/app/models/Document.js index c6061ff2a..553106cde 100644 --- a/app/models/Document.js +++ b/app/models/Document.js @@ -1,6 +1,5 @@ // @flow -import addDays from "date-fns/add_days"; -import differenceInDays from "date-fns/difference_in_days"; +import { addDays, differenceInDays } from "date-fns"; import invariant from "invariant"; import { action, computed, observable, set } from "mobx"; import parseTitle from "shared/utils/parseTitle"; diff --git a/app/routes/authenticated.js b/app/routes/authenticated.js index 876cadcf2..5bc7caa1f 100644 --- a/app/routes/authenticated.js +++ b/app/routes/authenticated.js @@ -3,7 +3,6 @@ import * as React from "react"; import { Switch, Redirect, type Match } from "react-router-dom"; import Archive from "scenes/Archive"; import Collection from "scenes/Collection"; -import KeyedDocument from "scenes/Document/KeyedDocument"; import DocumentNew from "scenes/DocumentNew"; import Drafts from "scenes/Drafts"; import Error404 from "scenes/Error404"; @@ -23,7 +22,11 @@ import { matchDocumentSlug as slug } from "utils/routeHelpers"; const SettingsRoutes = React.lazy(() => import(/* webpackChunkName: "settings" */ "./settings") ); - +const KeyedDocument = React.lazy(() => + import( + /* webpackChunkName: "keyed-document" */ "scenes/Document/KeyedDocument" + ) +); const NotFound = () => ; const RedirectDocument = ({ match }: { match: Match }) => ( { // search for exact internal document const slug = parseDocumentSlug(term); try { - const { document } = await this.props.documents.fetch(slug); - const time = distanceInWordsToNow(document.updatedAt, { + const { + document, + }: { document: Document } = await this.props.documents.fetch(slug); + + const time = formatDistanceToNow(Date.parse(document.updatedAt), { addSuffix: true, }); return [ @@ -118,7 +121,7 @@ class DataLoader extends React.Component { return sortBy( results.map((document) => { - const time = distanceInWordsToNow(document.updatedAt, { + const time = formatDistanceToNow(document.updatedAt, { addSuffix: true, }); return { diff --git a/app/scenes/Document/components/SharePopover.js b/app/scenes/Document/components/SharePopover.js index 18698d87a..f0500522f 100644 --- a/app/scenes/Document/components/SharePopover.js +++ b/app/scenes/Document/components/SharePopover.js @@ -1,5 +1,5 @@ // @flow -import distanceInWordsToNow from "date-fns/distance_in_words_to_now"; +import { formatDistanceToNow } from "date-fns"; import invariant from "invariant"; import { observer } from "mobx-react"; import { GlobeIcon, PadlockIcon } from "outline-icons"; @@ -118,9 +118,12 @@ function SharePopover({ document, share, sharedParent, onSubmit }: Props) { <> .{" "} {t("The shared link was last accessed {{ timeAgo }}.", { - timeAgo: distanceInWordsToNow(share.lastAccessedAt, { - addSuffix: true, - }), + timeAgo: formatDistanceToNow( + Date.parse(share.lastAccessedAt), + { + addSuffix: true, + } + ), })} )} diff --git a/app/scenes/UserProfile.js b/app/scenes/UserProfile.js index 4fdcac06d..c5c74ff08 100644 --- a/app/scenes/UserProfile.js +++ b/app/scenes/UserProfile.js @@ -1,5 +1,5 @@ // @flow -import distanceInWordsToNow from "date-fns/distance_in_words_to_now"; +import { formatDistanceToNow } from "date-fns"; import { observer } from "mobx-react"; import { EditIcon } from "outline-icons"; import * as React from "react"; @@ -52,7 +52,7 @@ function UserProfile(props: Props) { ? t("Joined") : t("Invited")}{" "} {t("{{ time }} ago.", { - time: distanceInWordsToNow(new Date(user.createdAt)), + time: formatDistanceToNow(new Date(user.createdAt)), })} {user.isAdmin && ( {t("Admin")} diff --git a/package.json b/package.json index 582ae5257..4c462d8d7 100644 --- a/package.json +++ b/package.json @@ -92,7 +92,7 @@ "compressorjs": "^1.0.7", "copy-to-clipboard": "^3.0.6", "core-js": "^3.10.2", - "date-fns": "1.29.0", + "date-fns": "2.22.1", "dd-trace": "^0.32.2", "debug": "^4.1.1", "dotenv": "^4.0.0", diff --git a/server/api/attachments.js b/server/api/attachments.js index 677765bb6..77143e291 100644 --- a/server/api/attachments.js +++ b/server/api/attachments.js @@ -1,5 +1,5 @@ // @flow -import format from "date-fns/format"; +import { format } from "date-fns"; import Router from "koa-router"; import { v4 as uuidv4 } from "uuid"; import { NotFoundError } from "../errors"; @@ -39,7 +39,7 @@ router.post("attachments.create", auth(), async (ctx) => { const bucket = acl === "public-read" ? "public" : "uploads"; const key = `${bucket}/${user.id}/${s3Key}/${name}`; const credential = makeCredential(); - const longDate = format(new Date(), "YYYYMMDDTHHmmss\\Z"); + const longDate = format(new Date(), "yyyyMMdd'T'HHmmss'Z'"); const policy = makePolicy(credential, longDate, acl, contentType); const endpoint = publicS3Endpoint(); const url = `${endpoint}/${key}`; diff --git a/server/api/utils.js b/server/api/utils.js index 3bd36029e..81fbbb2f1 100644 --- a/server/api/utils.js +++ b/server/api/utils.js @@ -1,5 +1,5 @@ // @flow -import subDays from "date-fns/sub_days"; +import { subDays } from "date-fns"; import debug from "debug"; import Router from "koa-router"; import { AuthenticationError } from "../errors"; diff --git a/server/api/utils.test.js b/server/api/utils.test.js index 56f105fe4..e6d8ed100 100644 --- a/server/api/utils.test.js +++ b/server/api/utils.test.js @@ -1,5 +1,5 @@ /* eslint-disable flowtype/require-valid-file-annotation */ -import subDays from "date-fns/sub_days"; +import { subDays } from "date-fns"; import TestServer from "fetch-test-server"; import app from "../app"; import { Attachment, Document } from "../models"; diff --git a/server/auth/index.js b/server/auth/index.js index 6e08b475f..b1064829c 100644 --- a/server/auth/index.js +++ b/server/auth/index.js @@ -1,6 +1,6 @@ // @flow import passport from "@outlinewiki/koa-passport"; -import addMonths from "date-fns/add_months"; +import { addMonths } from "date-fns"; import debug from "debug"; import Koa from "koa"; import bodyParser from "koa-body"; diff --git a/server/auth/providers/email.js b/server/auth/providers/email.js index 4bf6cd768..fc20ff52e 100644 --- a/server/auth/providers/email.js +++ b/server/auth/providers/email.js @@ -1,5 +1,5 @@ // @flow -import subMinutes from "date-fns/sub_minutes"; +import { subMinutes } from "date-fns"; import Router from "koa-router"; import { find } from "lodash"; import { AuthorizationError } from "../../errors"; diff --git a/server/models/User.js b/server/models/User.js index 4c4638c96..a07c02cb9 100644 --- a/server/models/User.js +++ b/server/models/User.js @@ -1,7 +1,6 @@ // @flow import crypto from "crypto"; -import addMinutes from "date-fns/add_minutes"; -import subMinutes from "date-fns/sub_minutes"; +import { addMinutes, subMinutes } from "date-fns"; import JWT from "jsonwebtoken"; import { v4 as uuidv4 } from "uuid"; import { languages } from "../../shared/i18n"; diff --git a/server/models/View.js b/server/models/View.js index 7607aebc8..45e07d65e 100644 --- a/server/models/View.js +++ b/server/models/View.js @@ -1,5 +1,5 @@ // @flow -import subMilliseconds from "date-fns/sub_milliseconds"; +import { subMilliseconds } from "date-fns"; import { USER_PRESENCE_INTERVAL } from "../../shared/constants"; import { User } from "../models"; import { DataTypes, Op, sequelize } from "../sequelize"; diff --git a/server/services/websockets.js b/server/services/websockets.js index e4940f18a..10f2708c1 100644 --- a/server/services/websockets.js +++ b/server/services/websockets.js @@ -1,5 +1,5 @@ // @flow -import subHours from "date-fns/sub_hours"; +import { subHours } from "date-fns"; import type { Event } from "../events"; import { socketio } from "../main"; import { diff --git a/server/utils/authentication.js b/server/utils/authentication.js index ead036ec7..7c9bf7032 100644 --- a/server/utils/authentication.js +++ b/server/utils/authentication.js @@ -1,7 +1,7 @@ // @flow import querystring from "querystring"; import * as Sentry from "@sentry/node"; -import addMonths from "date-fns/add_months"; +import { addMonths } from "date-fns"; import { type Context } from "koa"; import { pick } from "lodash"; import { User, Event, Team } from "../models"; diff --git a/server/utils/jwt.js b/server/utils/jwt.js index 9168ab626..0a91c8898 100644 --- a/server/utils/jwt.js +++ b/server/utils/jwt.js @@ -1,5 +1,5 @@ // @flow -import subMinutes from "date-fns/sub_minutes"; +import { subMinutes } from "date-fns"; import JWT from "jsonwebtoken"; import { AuthenticationError } from "../errors"; import { Team, User } from "../models"; diff --git a/server/utils/passport.js b/server/utils/passport.js index 4d94bb1a0..0055f24b1 100644 --- a/server/utils/passport.js +++ b/server/utils/passport.js @@ -1,6 +1,5 @@ // @flow -import addMinutes from "date-fns/add_minutes"; -import subMinutes from "date-fns/sub_minutes"; +import { addMinutes, subMinutes } from "date-fns"; import { type Request } from "koa"; import { OAuthStateMismatchError } from "../errors"; import { getCookieDomain } from "./domains"; diff --git a/server/utils/s3.js b/server/utils/s3.js index df41da0fd..121be2b8e 100644 --- a/server/utils/s3.js +++ b/server/utils/s3.js @@ -2,8 +2,7 @@ import crypto from "crypto"; import * as Sentry from "@sentry/node"; import AWS from "aws-sdk"; -import addHours from "date-fns/add_hours"; -import format from "date-fns/format"; +import { addHours, format } from "date-fns"; import fetch from "fetch-with-proxy"; const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY; @@ -36,7 +35,7 @@ export const makeCredential = () => { const credential = AWS_ACCESS_KEY_ID + "/" + - format(new Date(), "YYYYMMDD") + + format(new Date(), "yyyyMMdd") + "/" + AWS_REGION + "/s3/aws4_request"; @@ -62,7 +61,7 @@ export const makePolicy = ( { "x-amz-credential": credential }, { "x-amz-date": longDate }, ], - expiration: format(tomorrow, "YYYY-MM-DDTHH:mm:ss\\Z"), + expiration: format(tomorrow, "yyyy-MM-dd'T'HH:mm:ss'Z'"), }; return Buffer.from(JSON.stringify(policy)).toString("base64"); @@ -71,7 +70,7 @@ export const makePolicy = ( export const getSignature = (policy: any) => { const kDate = hmac( "AWS4" + AWS_SECRET_ACCESS_KEY, - format(new Date(), "YYYYMMDD") + format(new Date(), "yyyyMMdd") ); const kRegion = hmac(kDate, AWS_REGION); const kService = hmac(kRegion, "s3"); diff --git a/shared/i18n/index.js b/shared/i18n/index.js index 9be2fb6e8..847c318ef 100644 --- a/shared/i18n/index.js +++ b/shared/i18n/index.js @@ -13,6 +13,7 @@ export const languageOptions = [ { label: "Français (France)", value: "fr_FR" }, { label: "Italiano (Italia)", value: "it_IT" }, { label: "한국어 (Korean)", value: "ko_KR" }, + { label: "Português (Brazil)", value: "pt_BR" }, { label: "Português (Portugal)", value: "pt_PT" }, { label: "Pусский (Россия)", value: "ru_RU" }, ]; diff --git a/shared/utils/date.js b/shared/utils/date.js index d19518b55..1d4a6e7b4 100644 --- a/shared/utils/date.js +++ b/shared/utils/date.js @@ -1,8 +1,5 @@ // @flow -import subDays from "date-fns/sub_days"; -import subMonth from "date-fns/sub_months"; -import subWeek from "date-fns/sub_weeks"; -import subYear from "date-fns/sub_years"; +import { subDays, subMonths, subWeeks, subYears } from "date-fns"; export function subtractDate( date: Date, @@ -12,11 +9,11 @@ export function subtractDate( case "day": return subDays(date, 1); case "week": - return subWeek(date, 1); + return subWeeks(date, 1); case "month": - return subMonth(date, 1); + return subMonths(date, 1); case "year": - return subYear(date, 1); + return subYears(date, 1); default: return date; } diff --git a/webpack.config.js b/webpack.config.js index f5f8785d1..1987c1de1 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -99,13 +99,24 @@ module.exports = { moduleIds: 'hashed', chunkIds: 'named', splitChunks: { + chunks: 'async', + minSize: 20000, + minChunks: 1, + maxAsyncRequests: 30, + maxInitialRequests: 30, + enforceSizeThreshold: 50000, cacheGroups: { - vendor: { + defaultVendors: { test: /[\\/]node_modules[\\/]/, - name: 'vendors', - chunks: 'initial', + priority: -10, + reuseExistingChunk: true, }, - }, - }, + default: { + minChunks: 2, + priority: -20, + reuseExistingChunk: true, + } + } + } } }; diff --git a/yarn.lock b/yarn.lock index 9f3768120..025994c03 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4381,10 +4381,10 @@ data-urls@^2.0.0: whatwg-mimetype "^2.3.0" whatwg-url "^8.0.0" -date-fns@1.29.0: - version "1.29.0" - resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-1.29.0.tgz#12e609cdcb935127311d04d33334e2960a2a54e6" - integrity sha512-lbTXWZ6M20cWH8N9S6afb0SBm6tMk+uUg6z3MqHPKE9atmsY3kJkTm8vKe93izJ2B2+q5MV990sM2CHgtAZaOw== +date-fns@2.22.1: + version "2.22.1" + resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.22.1.tgz#1e5af959831ebb1d82992bf67b765052d8f0efc4" + integrity sha512-yUFPQjrxEmIsMqlHhAhmxkuH769baF21Kk+nZwZGyrMoyLA+LugaQtC0+Tqf9CBUUULWwUJt6Q5ySI3LJDDCGg== dd-trace@^0.32.2: version "0.32.2"