From fa52bc5afdb5fa15d65a3c52a6a2287f27fc9582 Mon Sep 17 00:00:00 2001 From: Tom Moor Date: Sun, 18 Apr 2021 18:34:49 -0700 Subject: [PATCH] chore: Slack integration screen improvements (#2049) * feat: Add collection iconography and colors to Slack settings page fix: Use standardized list components fix: Slack icon size chore: Convert to translation strings * fix: Missing translation, convert to Scene --- app/components/{ => AuthLogo}/SlackLogo.js | 0 app/components/AuthLogo/index.js | 2 +- app/components/Sidebar/Settings.js | 4 +- .../{Sidebar/icons/Slack.js => SlackIcon.js} | 0 .../icons/Zapier.js => ZapierIcon.js} | 0 app/scenes/Settings/Slack.js | 206 +++++++++--------- app/scenes/Settings/components/SlackButton.js | 23 +- package.json | 2 +- server/auth/providers/slack.js | 2 +- server/models/User.js | 10 +- shared/i18n/locales/en_US/translation.json | 8 + 11 files changed, 130 insertions(+), 127 deletions(-) rename app/components/{ => AuthLogo}/SlackLogo.js (100%) rename app/components/{Sidebar/icons/Slack.js => SlackIcon.js} (100%) rename app/components/{Sidebar/icons/Zapier.js => ZapierIcon.js} (100%) diff --git a/app/components/SlackLogo.js b/app/components/AuthLogo/SlackLogo.js similarity index 100% rename from app/components/SlackLogo.js rename to app/components/AuthLogo/SlackLogo.js diff --git a/app/components/AuthLogo/index.js b/app/components/AuthLogo/index.js index c7d0d66f..d2b444f2 100644 --- a/app/components/AuthLogo/index.js +++ b/app/components/AuthLogo/index.js @@ -1,9 +1,9 @@ // @flow import * as React from "react"; import styled from "styled-components"; -import SlackLogo from "../SlackLogo"; import GoogleLogo from "./GoogleLogo"; import MicrosoftLogo from "./MicrosoftLogo"; +import SlackLogo from "./SlackLogo"; type Props = {| providerName: string, diff --git a/app/components/Sidebar/Settings.js b/app/components/Sidebar/Settings.js index 72ac4d03..240d1812 100644 --- a/app/components/Sidebar/Settings.js +++ b/app/components/Sidebar/Settings.js @@ -19,14 +19,14 @@ import styled from "styled-components"; import Flex from "components/Flex"; import Scrollable from "components/Scrollable"; +import SlackIcon from "components/SlackIcon"; +import ZapierIcon from "components/ZapierIcon"; import Sidebar from "./Sidebar"; import Header from "./components/Header"; import Section from "./components/Section"; import SidebarLink from "./components/SidebarLink"; import TeamButton from "./components/TeamButton"; import Version from "./components/Version"; -import SlackIcon from "./icons/Slack"; -import ZapierIcon from "./icons/Zapier"; import env from "env"; import useCurrentTeam from "hooks/useCurrentTeam"; import useStores from "hooks/useStores"; diff --git a/app/components/Sidebar/icons/Slack.js b/app/components/SlackIcon.js similarity index 100% rename from app/components/Sidebar/icons/Slack.js rename to app/components/SlackIcon.js diff --git a/app/components/Sidebar/icons/Zapier.js b/app/components/ZapierIcon.js similarity index 100% rename from app/components/Sidebar/icons/Zapier.js rename to app/components/ZapierIcon.js diff --git a/app/scenes/Settings/Slack.js b/app/scenes/Settings/Slack.js index 1e58d1e7..83eee9e8 100644 --- a/app/scenes/Settings/Slack.js +++ b/app/scenes/Settings/Slack.js @@ -1,138 +1,136 @@ // @flow import { find } from "lodash"; -import { inject, observer } from "mobx-react"; +import { observer } from "mobx-react"; import * as React from "react"; +import { useTranslation, Trans } from "react-i18next"; import styled from "styled-components"; import getQueryVariable from "shared/utils/getQueryVariable"; -import AuthStore from "stores/AuthStore"; -import CollectionsStore from "stores/CollectionsStore"; -import IntegrationsStore from "stores/IntegrationsStore"; import Button from "components/Button"; -import CenteredContent from "components/CenteredContent"; +import CollectionIcon from "components/CollectionIcon"; +import Heading from "components/Heading"; import HelpText from "components/HelpText"; +import List from "components/List"; +import ListItem from "components/List/Item"; import Notice from "components/Notice"; -import PageTitle from "components/PageTitle"; +import Scene from "components/Scene"; +import SlackIcon from "components/SlackIcon"; import SlackButton from "./components/SlackButton"; import env from "env"; +import useCurrentTeam from "hooks/useCurrentTeam"; +import useStores from "hooks/useStores"; -type Props = { - collections: CollectionsStore, - integrations: IntegrationsStore, - auth: AuthStore, -}; +function Slack() { + const team = useCurrentTeam(); + const { collections, integrations } = useStores(); + const { t } = useTranslation(); + const error = getQueryVariable("error"); -@observer -class Slack extends React.Component { - error: ?string; + React.useEffect(() => { + collections.fetchPage({ limit: 100 }); + integrations.fetchPage({ limit: 100 }); + }, [collections, integrations]); - componentDidMount() { - this.error = getQueryVariable("error"); - this.props.collections.fetchPage({ limit: 100 }); - this.props.integrations.fetchPage(); - } + const commandIntegration = find(integrations.slackIntegrations, { + type: "command", + }); - get commandIntegration() { - return find(this.props.integrations.slackIntegrations, { - type: "command", - }); - } - - render() { - const { collections, integrations, auth } = this.props; - const teamId = auth.team ? auth.team.id : ""; - - return ( - - -

Slack

- {this.error === "access_denied" && ( - + return ( + }> + Slack + {error === "access_denied" && ( + + Whoops, you need to accept the permissions in Slack to connect Outline to your team. Try again? - - )} - {this.error === "unauthenticated" && ( - + + + )} + {error === "unauthenticated" && ( + + Something went wrong while authenticating your request. Please try logging in again? - + + + )} + + }} + /> + +

+ {commandIntegration ? ( + + ) : ( + )} - - Preview Outline links your team mates share and use the{" "} - /outline slash command in Slack to search for documents - in your team’s wiki. - -

- {this.commandIntegration ? ( - - ) : ( - - )} -

-

 

+

+

 

-

Collections

- +

{t("Collections")}

+ + Connect Outline collections to Slack channels and messages will be - posted in Slack when documents are published or updated. - + automatically posted to Slack when documents are published or updated. + +
- - {collections.orderedData.map((collection) => { - const integration = find(integrations.slackIntegrations, { - collectionId: collection.id, - }); - - if (integration) { - return ( - - - {collection.name} posting activity to the{" "} - {integration.settings.channel} Slack - channel - - - - ); - } + + {collections.orderedData.map((collection) => { + const integration = find(integrations.slackIntegrations, { + collectionId: collection.id, + }); + if (integration) { return ( - - {collection.name} + } + subtitle={ + {{ channelName }} channel`} + values={{ channelName: integration.settings.channel }} + components={{ em: }} + /> + } + actions={ + + } + /> + ); + } + + return ( + } + actions={ - - ); - })} - -
- ); - } + } + /> + ); + })} + + + ); } -const List = styled.ol` - list-style: none; - margin: 8px 0; - padding: 0; -`; - -const ListItem = styled.li` - display: flex; - justify-content: space-between; - align-items: center; - padding: 8px 0; - border-bottom: 1px solid #eaebea; -`; - const Code = styled.code` padding: 4px 6px; margin: 0 2px; @@ -140,4 +138,4 @@ const Code = styled.code` border-radius: 4px; `; -export default inject("collections", "integrations", "auth")(Slack); +export default observer(Slack); diff --git a/app/scenes/Settings/components/SlackButton.js b/app/scenes/Settings/components/SlackButton.js index fec74ee7..7eeefe88 100644 --- a/app/scenes/Settings/components/SlackButton.js +++ b/app/scenes/Settings/components/SlackButton.js @@ -1,19 +1,20 @@ // @flow import * as React from "react"; -import styled from "styled-components"; +import { useTranslation } from "react-i18next"; import { slackAuth } from "shared/utils/routeHelpers"; import Button from "components/Button"; -import SlackLogo from "components/SlackLogo"; +import SlackIcon from "components/SlackIcon"; import env from "env"; -type Props = { +type Props = {| scopes?: string[], redirectUri: string, state?: string, label?: string, -}; +|}; function SlackButton({ state = "", scopes, redirectUri, label }: Props) { + const { t } = useTranslation(); const handleClick = () => (window.location.href = slackAuth( state, @@ -25,22 +26,12 @@ function SlackButton({ state = "", scopes, redirectUri, label }: Props) { return ( ); } -const SpacedSlackLogo = styled(SlackLogo)` - padding-right: 4px; -`; - export default SlackButton; diff --git a/package.json b/package.json index bfedc8ef..0fc919b4 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "build:webpack": "webpack --config webpack.config.prod.js", "build": "yarn clean && yarn build:webpack && yarn build:i18n && yarn build:server", "start": "node ./build/server/index.js", - "dev": "nodemon --exec \"yarn build:server && yarn build:i18n && node build/server/index.js\" -e js --ignore build/ --ignore app/", + "dev": "nodemon --exec \"yarn build:server && yarn build:i18n && node --inspect=0.0.0.0 build/server/index.js\" -e js --ignore build/ --ignore app/", "lint": "eslint app server shared", "deploy": "git push heroku master", "heroku-postbuild": "yarn build && yarn db:migrate", diff --git a/server/auth/providers/slack.js b/server/auth/providers/slack.js index 3c1e8acd..bedec9bb 100644 --- a/server/auth/providers/slack.js +++ b/server/auth/providers/slack.js @@ -149,7 +149,7 @@ if (SLACK_CLIENT_ID) { } // this code block accounts for the root domain being unable to - // access authentcation for subdomains. We must forward to the + // access authentication for subdomains. We must forward to the // appropriate subdomain to complete the oauth flow if (!user) { try { diff --git a/server/models/User.js b/server/models/User.js index 8842c56a..439e7d0e 100644 --- a/server/models/User.js +++ b/server/models/User.js @@ -10,8 +10,14 @@ import { sendEmail } from "../mailer"; import { DataTypes, sequelize, encryptedFields, Op } from "../sequelize"; import { DEFAULT_AVATAR_HOST } from "../utils/avatars"; import { publicS3Endpoint, uploadToS3FromUrl } from "../utils/s3"; -import UserAuthentication from "./UserAuthentication"; -import { Star, Team, Collection, NotificationSetting, ApiKey } from "."; +import { + UserAuthentication, + Star, + Team, + Collection, + NotificationSetting, + ApiKey, +} from "."; const User = sequelize.define( "user", diff --git a/shared/i18n/locales/en_US/translation.json b/shared/i18n/locales/en_US/translation.json index 60f27277..a8b3071e 100644 --- a/shared/i18n/locales/en_US/translation.json +++ b/shared/i18n/locales/en_US/translation.json @@ -348,6 +348,7 @@ "Shared": "Shared", "by {{ name }}": "by {{ name }}", "Last accessed": "Last accessed", + "Add to Slack": "Add to Slack", "Import started": "Import started", "Export in progress…": "Export in progress…", "It is possible to import a zip file of folders and Markdown files previously exported from an Outline instance. Support will soon be added for importing from other services.": "It is possible to import a zip file of folders and Markdown files previously exported from an Outline instance. Support will soon be added for importing from other services.", @@ -384,6 +385,13 @@ "You can globally enable and disable public document sharing in the security settings.": "You can globally enable and disable public document sharing in the security settings.", "Shared documents": "Shared documents", "No share links, yet.": "No share links, yet.", + "Whoops, you need to accept the permissions in Slack to connect Outline to your team. Try again?": "Whoops, you need to accept the permissions in Slack to connect Outline to your team. Try again?", + "Something went wrong while authenticating your request. Please try logging in again?": "Something went wrong while authenticating your request. Please try logging in again?", + "Get rich previews of Outline links shared in Slack and use the {{ command }} slash command to search for documents without leaving your chat.": "Get rich previews of Outline links shared in Slack and use the {{ command }} slash command to search for documents without leaving your chat.", + "Connect Outline collections to Slack channels and messages will be automatically posted to Slack when documents are published or updated.": "Connect Outline collections to Slack channels and messages will be automatically posted to Slack when documents are published or updated.", + "Connected to the {{ channelName }} channel": "Connected to the {{ channelName }} channel", + "Disconnect": "Disconnect", + "Connect": "Connect", "You’ve not starred any documents yet.": "You’ve not starred any documents yet.", "There are no templates just yet.": "There are no templates just yet.", "You can create templates to help your team create consistent and accurate documentation.": "You can create templates to help your team create consistent and accurate documentation.",