From 253dde1f3e350eb14d35c47ab5da0d62314f0de2 Mon Sep 17 00:00:00 2001 From: batabana <36864084+batabana@users.noreply.github.com> Date: Fri, 15 Jul 2022 16:34:32 +0200 Subject: [PATCH 1/2] :recycle: Rewrite Twitter Card to TypeScript --- package.json | 1 + src/api/Ticker.ts | 29 ++++-- src/components/TickerResetModal.tsx | 1 - src/components/TwitterCard.js | 127 ------------------------- src/components/TwitterCard.tsx | 141 ++++++++++++++++++++++++++++ src/views/TickerView.tsx | 6 +- yarn.lock | 5 + 7 files changed, 169 insertions(+), 141 deletions(-) delete mode 100644 src/components/TwitterCard.js create mode 100644 src/components/TwitterCard.tsx diff --git a/package.json b/package.json index 0a66c989..1db8cbf3 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "@types/node": "^18.0.0", "@types/react-dom": "^17.0.17", "@types/react-router-dom": "^5.0.0", + "@types/react-twitter-auth": "^0.0.4", "@typescript-eslint/eslint-plugin": "^5.27.1", "@typescript-eslint/parser": "^5.27.1", "@webpack-cli/serve": "^1.7.0", diff --git a/src/api/Ticker.ts b/src/api/Ticker.ts index bc40f25c..01ef5ab9 100644 --- a/src/api/Ticker.ts +++ b/src/api/Ticker.ts @@ -36,6 +36,17 @@ export interface TickerInformation { export interface TickerTwitter { active: boolean connected: boolean + name: string + screen_name: string + description: string + image_url: string +} + +export interface TickerTwitterFormData { + active: boolean + disconnect: boolean + token: string + secret: string } export interface TickerLocation { @@ -43,15 +54,6 @@ export interface TickerLocation { lon: number } -/* -export function putTickerTwitter(data: any, id: number) { - return Auth.fetch(`${ApiUrl}/admin/tickers/${id}/twitter`, { - body: JSON.stringify(data), - method: 'PUT', - }) -} -*/ - export function useTickerApi(token: string) { const headers = { Accept: 'application/json', @@ -135,6 +137,14 @@ export function useTickerApi(token: string) { }).then(response => response.json()) } + const putTickerTwitter = (data: TickerTwitterFormData, ticker: Ticker) => { + return fetch(`${ApiUrl}/admin/tickers/${ticker.id}/twitter`, { + headers: headers, + body: JSON.stringify(data), + method: 'put', + }).then(response => response.json()) + } + return { deleteTicker, deleteTickerUser, @@ -145,5 +155,6 @@ export function useTickerApi(token: string) { putTicker, putTickerUsers, putTickerReset, + putTickerTwitter, } } diff --git a/src/components/TickerResetModal.tsx b/src/components/TickerResetModal.tsx index b1a583d4..fc86a56a 100644 --- a/src/components/TickerResetModal.tsx +++ b/src/components/TickerResetModal.tsx @@ -29,7 +29,6 @@ const TickerResetModal: FC = props => { queryClient.invalidateQueries(['messages', props.ticker.id]) queryClient.invalidateQueries(['tickerUsers', props.ticker.id]) queryClient.invalidateQueries(['ticker', props.ticker.id]) - // TODO: twitter }) .finally(() => { setOpen(false) diff --git a/src/components/TwitterCard.js b/src/components/TwitterCard.js deleted file mode 100644 index 73d1deb2..00000000 --- a/src/components/TwitterCard.js +++ /dev/null @@ -1,127 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import { ApiUrl } from '../api/Api' -import { Button, Card, Container, Icon } from 'semantic-ui-react' -import TwitterLogin from 'react-twitter-auth' -import { putTickerTwitter } from '../api/Ticker' - -export default class TwitterCard extends React.Component { - constructor(props) { - super(props) - } - - disconnect() { - this.update(false, '', '', true) - } - - connect(response) { - response.json().then(data => { - this.update(true, data.access_token, data.access_secret) - }) - } - - toggle() { - const twitter = this.props.ticker.twitter - this.update(!twitter.active) - } - - update(active, token, secret, disconnect) { - let formData = { - active: active, - disconnect: disconnect || false, - token: token || '', - secret: secret || '', - } - - putTickerTwitter(formData, this.props.ticker.id).then(response => { - this.props.callback(response.data.ticker) - }) - } - - render() { - const loginUrl = `${ApiUrl}/admin/auth/twitter` - const requestTokenUrl = `${ApiUrl}/admin/auth/twitter/request_token?callback=${encodeURI( - window.location.origin - )}` - const twitter = this.props.ticker.twitter || {} - - let toggleButton - if (twitter.active) { - toggleButton = ( - - ) - } else { - toggleButton = ( - - ) - } - - return twitter.connected ? ( - - - - - - {twitter.name} - - - - @{twitter.screen_name} - - - {twitter.description} - - - - {toggleButton} - - - - - - ) : ( - - - - You‘re currently not connected with Twitter. New messages will - not be published to your account. - - - { - alert(error) - }} - onSuccess={this.connect.bind(this)} - requestTokenUrl={requestTokenUrl} - showIcon={false} - > - - Connect - - - - - ) - } -} - -TwitterCard.propTypes = { - ticker: PropTypes.object.isRequired, - callback: PropTypes.func.isRequired, -} diff --git a/src/components/TwitterCard.tsx b/src/components/TwitterCard.tsx new file mode 100644 index 00000000..16ef00cb --- /dev/null +++ b/src/components/TwitterCard.tsx @@ -0,0 +1,141 @@ +import React, { FC, useCallback } from 'react' +import { useQueryClient } from 'react-query' +import TwitterLogin from 'react-twitter-auth' +import { Button, Card, Container, Icon } from 'semantic-ui-react' +import { ApiUrl } from '../api/Api' +import { Ticker, useTickerApi } from '../api/Ticker' +import useAuth from './useAuth' + +interface Props { + ticker: Ticker +} + +interface TwitterAuthResponseData { + access_secret: string + access_token: string +} + +const TwitterCard: FC = ({ ticker }) => { + const queryClient = useQueryClient() + const { token } = useAuth() + const { putTickerTwitter } = useTickerApi(token) + + const twitter = ticker.twitter || {} + const requestTokenUrl = `${ApiUrl}/admin/auth/twitter/request_token?callback=${encodeURI( + window.location.origin + )}` + const loginUrl = `${ApiUrl}/admin/auth/twitter` + + const updateTickerTwitter = useCallback( + (active: boolean, token = '', secret = '', disconnect = false) => { + const formData = { + active, + disconnect, + token, + secret, + } + + putTickerTwitter(formData, ticker).then(() => + queryClient.invalidateQueries(['ticker', ticker.id]) + ) + }, + [ticker, putTickerTwitter, queryClient] + ) + + const toggleActive = useCallback(() => { + updateTickerTwitter(!twitter.active) + }, [twitter.active, updateTickerTwitter]) + + const connect = useCallback( + (response: any) => { + response.json().then((data: TwitterAuthResponseData) => { + updateTickerTwitter(true, data.access_token, data.access_secret) + }) + }, + [updateTickerTwitter] + ) + + const disconnect = useCallback(() => { + updateTickerTwitter(false, '', '', true) + }, [updateTickerTwitter]) + + const alertError = useCallback((error: string) => { + alert(error) + }, []) + + return twitter.connected ? ( + + + + + + {twitter.name} + + + + @{twitter.screen_name} + + + {twitter.description} + + + + {twitter.active ? ( +