Skip to content

Commit

Permalink
Add linter to Chrome Extension (twentyhq#4044). (twentyhq#4174)
Browse files Browse the repository at this point in the history
* feat: configure eslint rules by replicating those in the twenty-front package and introduce scripts for linting, formatting code and removing build output

* fix: ensure each file of the extension package satisfies linting rules and disable some rules where necessary

* fix: update relative imports to absolute imports throughout extension code with the defined tilde and at symbols

* fix: import the updated ui module from the front package to the chrome extension package to prevent eslint rules from breaking subject to the recent merged changes into main

* fix: commit the case change for files that were missed by Git in the earlier commits due to default configuration
  • Loading branch information
mabdullahabaid authored Feb 25, 2024
1 parent 8dd06bd commit c274d35
Show file tree
Hide file tree
Showing 67 changed files with 783 additions and 567 deletions.
19 changes: 19 additions & 0 deletions packages/twenty-chrome-extension/.eslintrc-ci.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
module.exports = {
extends: ['./.eslintrc.cjs'],
rules: {
'no-console': 'error',
},
overrides: [
{
files: [
'.storybook/**/*',
'**/*.stories.tsx',
'**/*.test.ts',
'**/*.test.tsx',
],
rules: {
'no-console': 'off',
},
},
],
};
65 changes: 54 additions & 11 deletions packages/twenty-chrome-extension/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,18 +1,61 @@
// eslint-disable-next-line
const path = require('path');

module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:@nx/react',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:storybook/recommended',
'../../.eslintrc.js',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
plugins: ['react-hooks', 'react-refresh'],
ignorePatterns: ['!**/*', 'node_modules', 'dist'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
'@nx/workspace-effect-components': 'error',
'@nx/workspace-no-hardcoded-colors': 'error',
'@nx/workspace-matching-state-variable': 'error',
'@nx/workspace-sort-css-properties-alphabetically': 'error',
'@nx/workspace-styled-components-prefixed-with-styled': 'error',
'@nx/workspace-no-state-useref': 'error',
'@nx/workspace-component-props-naming': 'error',

'react/no-unescaped-entities': 'off',
'react/prop-types': 'off',
'react/jsx-key': 'off',
'react/display-name': 'off',
'react/jsx-uses-react': 'off',
'react/react-in-jsx-scope': 'off',
'react/jsx-no-useless-fragment': 'off',
'react/jsx-props-no-spreading': [
'error',
{
explicitSpread: 'ignore',
},
],
},
}
overrides: [
{
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
parserOptions: {
project: ['packages/twenty-chrome-extension/tsconfig.*?.json'],
},
rules: {},
},
{
files: ['.storybook/main.@(js|cjs|mjs|ts)'],
rules: {
'storybook/no-uninstalled-addons': [
'error',
{ packageJsonLocation: path.resolve('../../package.json') },
],
},
},
{
files: ['.storybook/**/*', '**/*.stories.tsx', '**/*.test.@(ts|tsx)'],
rules: {
'no-console': 'off',
},
},
],
};
8 changes: 6 additions & 2 deletions packages/twenty-chrome-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@
"type": "module",
"scripts": {
"nx": "NX_DEFAULT_PROJECT=twenty-chrome-extension node ../../node_modules/nx/bin/nx.js",
"start": "vite",
"build": "tsc && vite build"
"clean": "rimraf ./dist",
"start": "yarn clean && vite",
"build": "yarn clean && tsc && vite build",
"lint": "eslint . --report-unused-disable-directives --max-warnings 0 --config .eslintrc.cjs",
"fmt": "prettier --check \"src/**/*.ts\" \"src/**/*.tsx\"",
"fmt:fix": "prettier --cache --write \"src/**/*.ts\" \"src/**/*.tsx\""
},
"dependencies": {
"@types/chrome": "^0.0.256"
Expand Down
8 changes: 3 additions & 5 deletions packages/twenty-chrome-extension/src/background/index.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
import { openOptionsPage } from './utils/openOptionsPage';

console.log('Background Script Works');
import { openOptionsPage } from '~/background/utils/openOptionsPage';

// Open options page programmatically in a new tab.
chrome.runtime.onInstalled.addListener(function (details) {
chrome.runtime.onInstalled.addListener((details) => {
if (details.reason === 'install') {
openOptionsPage();
}
});

// Open options page when extension icon is clicked.
chrome.action.onClicked.addListener(function () {
chrome.action.onClicked.addListener(() => {
openOptionsPage();
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
function createNewButton(
/* eslint-disable @nx/workspace-no-hardcoded-colors */
const createNewButton = (
text: string,
onClickHandler: () => void,
): HTMLButtonElement {
): HTMLButtonElement => {
const newButton: HTMLButtonElement = document.createElement('button');
newButton.textContent = text;

Expand Down Expand Up @@ -52,6 +53,6 @@ function createNewButton(
});

return newButton;
}
};

export default createNewButton;
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import handleQueryParams from '../utils/handleQueryParams';
import requestDb from '../utils/requestDb';
import createNewButton from './createButton';
import extractCompanyLinkedinLink from './utils/extractCompanyLinkedinLink';
import extractDomain from './utils/extractDomain';
import createNewButton from '~/contentScript/createButton';
import extractCompanyLinkedinLink from '~/contentScript/utils/extractCompanyLinkedinLink';
import extractDomain from '~/contentScript/utils/extractDomain';
import handleQueryParams from '~/utils/handleQueryParams';
import requestDb from '~/utils/requestDb';

function insertButtonForCompany(): void {
const insertButtonForCompany = (): void => {
// Select the element in which to create the button.
const parentDiv: HTMLDivElement | null = document.querySelector(
'.org-top-card-primary-actions__inner',
Expand Down Expand Up @@ -101,6 +101,6 @@ function insertButtonForCompany(): void {

Object.assign(newButtonCompany.style, buttonSpecificStyles);
}
}
};

export default insertButtonForCompany;
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import handleQueryParams from '../utils/handleQueryParams';
import requestDb from '../utils/requestDb';
import createNewButton from './createButton';
import extractFirstAndLastName from './utils/extractFirstAndLastName';
import createNewButton from '~/contentScript/createButton';
import extractFirstAndLastName from '~/contentScript/utils/extractFirstAndLastName';
import handleQueryParams from '~/utils/handleQueryParams';
import requestDb from '~/utils/requestDb';

function insertButtonForPerson(): void {
const insertButtonForPerson = (): void => {
// Select the element in which to create the button.
const parentDiv: HTMLDivElement | null = document.querySelector(
'.pv-top-card-v2-ctas',
Expand Down Expand Up @@ -114,6 +114,6 @@ function insertButtonForPerson(): void {

Object.assign(newButtonPerson.style, buttonSpecificStyles);
}
}
};

export default insertButtonForPerson;
4 changes: 2 additions & 2 deletions packages/twenty-chrome-extension/src/contentScript/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import insertButtonForPerson from './extractPersonProfile';
import insertButtonForCompany from './extractCompanyProfile';
import insertButtonForCompany from '~/contentScript/extractCompanyProfile';
import insertButtonForPerson from '~/contentScript/extractPersonProfile';

// Inject buttons into the DOM when SPA is reloaded on the resource url.
// e.g. reload the page when on https://www.linkedin.com/in/mabdullahabaid/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
function extractDomain(url: string | null) {
const extractDomain = (url: string | null) => {
if (!url) return '';

const hostname = new URL(url).hostname;
Expand All @@ -10,6 +10,6 @@ function extractDomain(url: string | null) {
}

return domain;
}
};

export default extractDomain;
1 change: 1 addition & 0 deletions packages/twenty-chrome-extension/src/manifest.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { defineManifest } from '@crxjs/vite-plugin';

import packageData from '../package.json';

export default defineManifest({
Expand Down
7 changes: 4 additions & 3 deletions packages/twenty-chrome-extension/src/options/Options.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import styled from '@emotion/styled';
import { ApiKeyForm } from './modules/api-key/components/ApiKeyForm';

import { ApiKeyForm } from '@/api-key/components/ApiKeyForm';

const StyledContainer = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.noisy};
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
justify-content: center;
`;

const Options = () => {
Expand Down
11 changes: 6 additions & 5 deletions packages/twenty-chrome-extension/src/options/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './Options';
import '../index.css';
import { AppThemeProvider } from './modules/ui/theme/components/AppThemeProvider';
import { ThemeType } from './modules/ui/theme/constants/theme';

import { AppThemeProvider } from '@/ui/theme/components/AppThemeProvider';
import { ThemeType } from '@/ui/theme/constants/ThemeLight';
import App from '~/options/Options';

import '~/index.css';

ReactDOM.createRoot(document.getElementById('app') as HTMLElement).render(
<AppThemeProvider>
Expand All @@ -14,6 +16,5 @@ ReactDOM.createRoot(document.getElementById('app') as HTMLElement).render(
);

declare module '@emotion/react' {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface Theme extends ThemeType {}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
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';
import styled from '@emotion/styled';

import { H2Title } from '@/ui/display/typography/components/H2Title';
import { Button } from '@/ui/input/button/Button';
import { TextInput } from '@/ui/input/components/TextInput';
import { Toggle } from '@/ui/input/components/Toggle';

const StyledContainer = styled.div<{ isToggleOn: boolean }>`
width: 400px;
Expand All @@ -18,8 +19,8 @@ const StyledContainer = styled.div<{ isToggleOn: boolean }>`
`;

const StyledHeader = styled.header`
text-align: center;
margin-bottom: ${({ theme }) => theme.spacing(8)};
text-align: center;
`;

const StyledImg = styled.img``;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ const StyledLabel = styled.span`
const StyledInputContainer = styled.div`
display: flex;
align-items: center;
border: 1px solid #ccc;
border: 1px solid ${({ theme }) => theme.color.gray30};
border-radius: 4px;
padding: 8px;
`;
Expand All @@ -46,12 +46,12 @@ const StyledInput = styled.input`
font-size: 14px;
&::placeholder {
color: #aaa;
color: ${({ theme }) => theme.font.color.light};
}
`;

const StyledErrorHelper = styled.div`
color: #ff0000;
color: ${({ theme }) => theme.color.red};
font-size: 12px;
padding: 5px 0;
`;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { ThemeProvider } from '@emotion/react';

import { lightTheme } from '../constants/theme';
import { THEME_LIGHT } from '@/ui/theme/constants/ThemeLight';

type AppThemeProviderProps = {
children: JSX.Element;
};

const AppThemeProvider: React.FC<AppThemeProviderProps> = ({ children }) => {
const theme = lightTheme;
const theme = THEME_LIGHT;

return <ThemeProvider theme={theme}>{children}</ThemeProvider>;
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { COLOR } from '@/ui/theme/constants/Colors';

export const ACCENT_DARK = {
primary: COLOR.blueAccent75,
secondary: COLOR.blueAccent80,
tertiary: COLOR.blueAccent85,
quaternary: COLOR.blueAccent90,
accent3570: COLOR.blueAccent70,
accent4060: COLOR.blueAccent60,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { COLOR } from '@/ui/theme/constants/Colors';

export const ACCENT_LIGHT = {
primary: COLOR.blueAccent25,
secondary: COLOR.blueAccent20,
tertiary: COLOR.blueAccent15,
quaternary: COLOR.blueAccent10,
accent3570: COLOR.blueAccent35,
accent4060: COLOR.blueAccent40,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export const ANIMATION = {
duration: {
instant: 0.075,
fast: 0.15,
normal: 0.3,
},
};

export type AnimationDuration = 'instant' | 'fast' | 'normal';
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/* eslint-disable @nx/workspace-no-hardcoded-colors */
import DarkNoise from '@/ui/theme/assets/dark-noise.jpg';
import { COLOR } from '@/ui/theme/constants/Colors';
import { GRAY_SCALE } from '@/ui/theme/constants/GrayScale';
import { RGBA } from '@/ui/theme/constants/Rgba';

export const BACKGROUND_DARK = {
noisy: `url(${DarkNoise.toString()});`,
primary: GRAY_SCALE.gray85,
secondary: GRAY_SCALE.gray80,
tertiary: GRAY_SCALE.gray75,
quaternary: GRAY_SCALE.gray70,
danger: COLOR.red80,
transparent: {
primary: RGBA(GRAY_SCALE.gray85, 0.8),
secondary: RGBA(GRAY_SCALE.gray80, 0.8),
strong: RGBA(GRAY_SCALE.gray0, 0.14),
medium: RGBA(GRAY_SCALE.gray0, 0.1),
light: RGBA(GRAY_SCALE.gray0, 0.06),
lighter: RGBA(GRAY_SCALE.gray0, 0.03),
danger: RGBA(COLOR.red, 0.08),
},
overlay: RGBA(GRAY_SCALE.gray80, 0.8),
radialGradient: `radial-gradient(50% 62.62% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`,
radialGradientHover: `radial-gradient(76.32% 95.59% at 50% 0%, #505050 0%, ${GRAY_SCALE.gray60} 100%)`,
};
Loading

0 comments on commit c274d35

Please sign in to comment.