* build: create a new vite project for chrome extension * feat: configure theme per the frontend codebase for chrome extension * feat: inject the add to twenty button into linkedin profile page * feat: create the api key form ui and render it on the options page * feat: inject the add to twenty button into linkedin company page * feat: scrape required data from both the user profile and the company profile * refactor: move modules into options because it is the only page using react for now * fix: show add to twenty button without having to reload the single page application * fix: extract domain of the business website instead of scrapping the industry type * feat: store api key to local storage and open options page when trying to store data without setting a key * feat: send data to the backend upon click and store it to the database * fix: open options page upon clicking the extension icon * fix: update terminology from user to person to match the codebase convention * fix: adopt chrome extension to monorepo approach using nx and get the development server working * fix: update vite config for build command to work per the requirement * feat: add instructions in the readme file to install the extension for local testing * fix: move server base url to a dotenv file and replace the hard-coded url * feat: permit user to configure a custom route for the server from the options page * fix: fetch api key and route from local storage and display on options page to inform users of their choices * fix: move front base url to dotenv and replace the hard-coded url * fix: remove the trailing slash from person and company linkedin username * fix: improve code commenting to explain implementation somewhat better * ci: introduce a workflow to build chrome extension to ensure it can be published * fix: format files to display code in a consistent manner per the prettier configuration in codebase * fix: improve the commenting significantly to explain important and hard-to-understand parts of the code * fix: remove unused permissions from the manifest file for publishing to the chrome web store * Add nx * Fix vale --------- Co-authored-by: Charles Bochet <charles@twenty.com>
147 lines
3.7 KiB
TypeScript
147 lines
3.7 KiB
TypeScript
import styled from '@emotion/styled';
|
|
import { H2Title } from '../../ui/display/typography/components/H2Title';
|
|
import { useEffect, useState } from 'react';
|
|
import { TextInput } from '../../ui/input/components/TextInput';
|
|
import { Button } from '../../ui/input/button/Button';
|
|
import { Toggle } from '../../ui/input/components/Toggle';
|
|
|
|
const StyledContainer = styled.div<{ isToggleOn: boolean }>`
|
|
width: 400px;
|
|
margin: 0 auto;
|
|
background-color: ${({ theme }) => theme.background.primary};
|
|
padding: ${({ theme }) => theme.spacing(10)};
|
|
overflow: hidden;
|
|
transition: height 0.3s ease;
|
|
|
|
height: ${({ isToggleOn }) => (isToggleOn ? '450px' : '390px')};
|
|
max-height: ${({ isToggleOn }) => (isToggleOn ? '450px' : '390px')};
|
|
`;
|
|
|
|
const StyledHeader = styled.header`
|
|
text-align: center;
|
|
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
|
`;
|
|
|
|
const StyledImg = styled.img``;
|
|
|
|
const StyledMain = styled.main`
|
|
margin-bottom: ${({ theme }) => theme.spacing(8)};
|
|
`;
|
|
|
|
const StyledFooter = styled.footer`
|
|
display: flex;
|
|
`;
|
|
|
|
const StyledTitleContainer = styled.div`
|
|
flex: 0 0 80%;
|
|
`;
|
|
|
|
const StyledToggleContainer = styled.div`
|
|
flex: 0 0 20%;
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
`;
|
|
|
|
const StyledSection = styled.div<{ showSection: boolean }>`
|
|
transition:
|
|
max-height 0.3s ease,
|
|
opacity 0.3s ease;
|
|
overflow: hidden;
|
|
max-height: ${({ showSection }) => (showSection ? '200px' : '0')};
|
|
`;
|
|
|
|
export const ApiKeyForm = () => {
|
|
const [apiKey, setApiKey] = useState('');
|
|
const [route, setRoute] = useState('');
|
|
const [showSection, setShowSection] = useState(false);
|
|
|
|
useEffect(() => {
|
|
const getState = async () => {
|
|
const localStorage = await chrome.storage.local.get();
|
|
|
|
if (localStorage.apiKey) {
|
|
setApiKey(localStorage.apiKey);
|
|
}
|
|
|
|
if (localStorage.serverBaseUrl) {
|
|
setRoute(localStorage.serverBaseUrl);
|
|
}
|
|
};
|
|
|
|
void getState();
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
chrome.storage.local.set({ apiKey });
|
|
}, [apiKey]);
|
|
|
|
useEffect(() => {
|
|
chrome.storage.local.set({ serverBaseUrl: route });
|
|
}, [route]);
|
|
|
|
const handleGenerateClick = () => {
|
|
window.open(
|
|
`${import.meta.env.VITE_FRONT_BASE_URL}/settings/developers/api-keys`,
|
|
);
|
|
};
|
|
|
|
const handleToggle = () => {
|
|
setShowSection(!showSection);
|
|
};
|
|
|
|
return (
|
|
<StyledContainer isToggleOn={showSection}>
|
|
<StyledHeader>
|
|
<StyledImg src="/logo/32-32.png" alt="Twenty Logo" />
|
|
</StyledHeader>
|
|
|
|
<StyledMain>
|
|
<H2Title
|
|
title="Connect your account"
|
|
description="Input your key to link the extension to your workspace."
|
|
/>
|
|
<TextInput
|
|
label="Api key"
|
|
value={apiKey}
|
|
onChange={setApiKey}
|
|
placeholder="My API key"
|
|
/>
|
|
<Button
|
|
title="Generate a key"
|
|
fullWidth={false}
|
|
variant="primary"
|
|
accent="default"
|
|
size="small"
|
|
position="standalone"
|
|
soon={false}
|
|
disabled={false}
|
|
onClick={handleGenerateClick}
|
|
/>
|
|
</StyledMain>
|
|
|
|
<StyledFooter>
|
|
<StyledTitleContainer>
|
|
<H2Title
|
|
title="Custom route"
|
|
description="For developers interested in self-hosting or local testing of the extension."
|
|
/>
|
|
</StyledTitleContainer>
|
|
<StyledToggleContainer>
|
|
<Toggle value={showSection} onChange={handleToggle} />
|
|
</StyledToggleContainer>
|
|
</StyledFooter>
|
|
|
|
<StyledSection showSection={showSection}>
|
|
{showSection && (
|
|
<TextInput
|
|
label="Route"
|
|
value={route}
|
|
onChange={setRoute}
|
|
placeholder="My Route"
|
|
/>
|
|
)}
|
|
</StyledSection>
|
|
</StyledContainer>
|
|
);
|
|
};
|