Skip to content

Commit

Permalink
tsc
Browse files Browse the repository at this point in the history
  • Loading branch information
tommoor committed Dec 29, 2023
2 parents 65be484 + 01c806d commit a41a217
Show file tree
Hide file tree
Showing 517 changed files with 10,753 additions and 9,193 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Expand Up @@ -3,7 +3,7 @@ version: 2.1
defaults: &defaults
working_directory: ~/outline
docker:
- image: cimg/node:18.12
- image: cimg/node:20.10
- image: cimg/redis:5.0
- image: cimg/postgres:14.2
environment:
Expand Down
5 changes: 5 additions & 0 deletions .env.sample
Expand Up @@ -195,3 +195,8 @@ RATE_LIMITER_DURATION_WINDOW=60
# Iframely API config
# IFRAMELY_URL=
# IFRAMELY_API_KEY=

# Enable unsafe-inline in script-src CSP directive
# Setting it to true allows React dev tools add-on in
# Firefox to successfully detect the project
DEVELOPMENT_UNSAFE_INLINE_CSP=false
2 changes: 1 addition & 1 deletion Dockerfile
Expand Up @@ -5,7 +5,7 @@ ARG APP_PATH
WORKDIR $APP_PATH

# ---
FROM node:18-alpine AS runner
FROM node:20-alpine AS runner

RUN apk update && apk add --no-cache curl && apk add --no-cache ca-certificates

Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.base
@@ -1,5 +1,5 @@
ARG APP_PATH=/opt/outline
FROM node:18-alpine AS deps
FROM node:20-alpine AS deps

ARG APP_PATH
WORKDIR $APP_PATH
Expand Down
6 changes: 3 additions & 3 deletions Makefile
@@ -1,5 +1,5 @@
up:
docker-compose up -d redis postgres s3
docker-compose up -d redis postgres
yarn install-local-ssl
yarn install --pure-lockfile
yarn dev:watch
Expand All @@ -8,14 +8,14 @@ build:
docker-compose build --pull outline

test:
docker-compose up -d redis postgres s3
docker-compose up -d redis postgres
yarn sequelize db:drop --env=test
yarn sequelize db:create --env=test
NODE_ENV=test yarn sequelize db:migrate --env=test
yarn test

watch:
docker-compose up -d redis postgres s3
docker-compose up -d redis postgres
yarn sequelize db:drop --env=test
yarn sequelize db:create --env=test
NODE_ENV=test yarn sequelize db:migrate --env=test
Expand Down
76 changes: 74 additions & 2 deletions app/actions/definitions/developer.tsx
@@ -1,4 +1,5 @@
import { ToolsIcon, TrashIcon, UserIcon } from "outline-icons";
import copy from "copy-to-clipboard";
import { CopyIcon, ToolsIcon, TrashIcon, UserIcon } from "outline-icons";
import * as React from "react";
import { toast } from "sonner";
import { createAction } from "~/actions";
Expand All @@ -8,6 +9,71 @@ import { client } from "~/utils/ApiClient";
import Logger from "~/utils/Logger";
import { deleteAllDatabases } from "~/utils/developer";

export const copyId = createAction({
name: ({ t }) => t("Copy ID"),
icon: <CopyIcon />,
keywords: "uuid",
section: DeveloperSection,
children: ({
currentTeamId,
currentUserId,
activeCollectionId,
activeDocumentId,
}) => {
function copyAndToast(text: string | null | undefined) {
if (text) {
copy(text);
toast.success("Copied to clipboard");
}
}

return [
createAction({
name: "Copy User ID",
section: DeveloperSection,
icon: <CopyIcon />,
visible: () => !!currentUserId,
perform: () => copyAndToast(currentUserId),
}),
createAction({
name: "Copy Team ID",
section: DeveloperSection,
icon: <CopyIcon />,
visible: () => !!currentTeamId,
perform: () => copyAndToast(currentTeamId),
}),
createAction({
name: "Copy Collection ID",
icon: <CopyIcon />,
section: DeveloperSection,
visible: () => !!activeCollectionId,
perform: () => copyAndToast(activeCollectionId),
}),
createAction({
name: "Copy Document ID",
icon: <CopyIcon />,
section: DeveloperSection,
visible: () => !!activeDocumentId,
perform: () => copyAndToast(activeDocumentId),
}),
createAction({
name: "Copy Team ID",
icon: <CopyIcon />,
section: DeveloperSection,
visible: () => !!currentTeamId,
perform: () => copyAndToast(currentTeamId),
}),
createAction({
name: "Copy Release ID",
icon: <CopyIcon />,
section: DeveloperSection,
visible: () => !!env.RELEASE,
perform: () => copyAndToast(env.RELEASE),
}),
];
},
});

export const clearIndexedDB = createAction({
name: ({ t }) => t("Delete IndexedDB cache"),
icon: <TrashIcon />,
Expand Down Expand Up @@ -67,7 +133,13 @@ export const developer = createAction({
icon: <ToolsIcon />,
iconInContextMenu: false,
section: DeveloperSection,
children: [clearIndexedDB, toggleDebugLogging, createToast, createTestUsers],
children: [
copyId,
clearIndexedDB,
toggleDebugLogging,
createToast,
createTestUsers,
],
});

export const rootDeveloperActions = [developer];
88 changes: 85 additions & 3 deletions app/actions/definitions/documents.tsx
@@ -1,3 +1,4 @@
import copy from "copy-to-clipboard";
import invariant from "invariant";
import {
DownloadIcon,
Expand All @@ -23,11 +24,15 @@ import {
UnpublishIcon,
PublishIcon,
CommentIcon,
GlobeIcon,
CopyIcon,
} from "outline-icons";
import * as React from "react";
import { toast } from "sonner";
import { ExportContentType, TeamPreference } from "@shared/types";
import MarkdownHelper from "@shared/utils/MarkdownHelper";
import { getEventFiles } from "@shared/utils/files";
import SharePopover from "~/scenes/Document/components/SharePopover";
import DocumentDelete from "~/scenes/DocumentDelete";
import DocumentMove from "~/scenes/DocumentMove";
import DocumentPermanentDelete from "~/scenes/DocumentPermanentDelete";
Expand All @@ -45,6 +50,7 @@ import {
newDocumentPath,
searchPath,
documentPath,
urlify,
} from "~/utils/routeHelpers";

export const openDocument = createAction({
Expand Down Expand Up @@ -320,6 +326,40 @@ export const unsubscribeDocument = createAction({
},
});

export const shareDocument = createAction({
name: ({ t }) => t("Share"),
analyticsName: "Share document",
section: DocumentSection,
icon: <GlobeIcon />,
perform: async ({ activeDocumentId, stores, currentUserId, t }) => {
if (!activeDocumentId || !currentUserId) {
return;
}

const document = stores.documents.get(activeDocumentId);
const share = stores.shares.getByDocumentId(activeDocumentId);
const sharedParent = stores.shares.getByDocumentParents(activeDocumentId);
if (!document) {
return;
}

stores.dialogs.openModal({
title: t("Share this document"),
isCentered: true,
content: (
<SharePopover
document={document}
share={share}
sharedParent={sharedParent}
onRequestClose={stores.dialogs.closeAllModals}
hideTitle
visible
/>
),
});
},
});

export const downloadDocumentAsHTML = createAction({
name: ({ t }) => t("HTML"),
analyticsName: "Download document as HTML",
Expand Down Expand Up @@ -396,6 +436,47 @@ export const downloadDocument = createAction({
],
});

export const copyDocumentAsMarkdown = createAction({
name: ({ t }) => t("Copy as Markdown"),
section: DocumentSection,
keywords: "clipboard",
visible: ({ activeDocumentId }) => !!activeDocumentId,
perform: ({ stores, activeDocumentId, t }) => {
const document = activeDocumentId
? stores.documents.get(activeDocumentId)
: undefined;
if (document) {
copy(MarkdownHelper.toMarkdown(document));
toast.success(t("Markdown copied to clipboard"));
}
},
});

export const copyDocumentLink = createAction({
name: ({ t }) => t("Copy link"),
section: DocumentSection,
keywords: "clipboard",
visible: ({ activeDocumentId }) => !!activeDocumentId,
perform: ({ stores, activeDocumentId, t }) => {
const document = activeDocumentId
? stores.documents.get(activeDocumentId)
: undefined;
if (document) {
copy(urlify(documentPath(document)));
toast.success(t("Link copied to clipboard"));
}
},
});

export const copyDocument = createAction({
name: ({ t }) => t("Copy"),
analyticsName: "Copy document",
section: DocumentSection,
icon: <CopyIcon />,
keywords: "clipboard",
children: [copyDocumentLink, copyDocumentAsMarkdown],
});

export const duplicateDocument = createAction({
name: ({ t, isContextMenu }) =>
isContextMenu ? t("Duplicate") : t("Duplicate document"),
Expand Down Expand Up @@ -703,7 +784,7 @@ export const archiveDocument = createAction({
});

export const deleteDocument = createAction({
name: ({ t }) => t("Delete"),
name: ({ t }) => `${t("Delete")}…`,
analyticsName: "Delete document",
section: DocumentSection,
icon: <TrashIcon />,
Expand Down Expand Up @@ -781,8 +862,7 @@ export const openDocumentComments = createAction({
const can = stores.policies.abilities(activeDocumentId ?? "");
return (
!!activeDocumentId &&
can.read &&
!can.restore &&
can.comment &&
!!stores.auth.team?.getPreference(TeamPreference.Commenting)
);
},
Expand Down Expand Up @@ -854,6 +934,8 @@ export const rootDocumentActions = [
deleteDocument,
importDocument,
downloadDocument,
copyDocumentLink,
copyDocumentAsMarkdown,
starDocument,
unstarDocument,
publishDocument,
Expand Down
4 changes: 3 additions & 1 deletion app/actions/index.ts
Expand Up @@ -116,6 +116,8 @@ export function actionToKBar(
icon: resolvedIcon,
perform: action.perform ? () => action.perform?.(context) : undefined,
},
].concat(
// @ts-expect-error ts-migrate(2769) FIXME: No overload matches this call.
].concat(children.map((child) => ({ ...child, parent: action.id })));
children.map((child) => ({ ...child, parent: child.parent ?? action.id }))
);
}
8 changes: 5 additions & 3 deletions app/components/Authenticated.tsx
Expand Up @@ -2,6 +2,7 @@ import { observer } from "mobx-react";
import * as React from "react";
import { useTranslation } from "react-i18next";
import { Redirect } from "react-router-dom";
import useCurrentUser from "~/hooks/useCurrentUser";
import useStores from "~/hooks/useStores";
import { changeLanguage } from "~/utils/language";
import LoadingIndicator from "./LoadingIndicator";
Expand All @@ -13,10 +14,11 @@ type Props = {
const Authenticated = ({ children }: Props) => {
const { auth } = useStores();
const { i18n } = useTranslation();
const language = auth.user?.language;
const user = useCurrentUser({ rejectOnEmpty: false });
const language = user?.language;

// Watching for language changes here as this is the earliest point we have
// the user available and means we can start loading translations faster
// Watching for language changes here as this is the earliest point we might have the user
// available and means we can start loading translations faster
React.useEffect(() => {
void changeLanguage(language, i18n);
}, [i18n, language]);
Expand Down

0 comments on commit a41a217

Please sign in to comment.