mirror of
https://github.com/twentyhq/twenty.git
synced 2024-12-22 19:41:53 +03:00
Add a custom rule to prevent colors from being hardcoded outside of theme (#288)
* Add a custom rule to prevent colors from being hardcoded in ESLint * Refactor colors * Create packages folder and fix colors * Remove external dependency for css alphabetical order linting * Fix install with yarn --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
parent
bf6fb0ba70
commit
31f3950439
@ -6,5 +6,5 @@
|
||||
"ghcr.io/devcontainers-contrib/features/jshint:2": {}
|
||||
},
|
||||
"forwardPorts": [3000, 3001, 5432],
|
||||
"postCreateCommand": "cd front && npm install && cd ../server && npm install"
|
||||
"postCreateCommand": "cd front && yarn && cd ../server && yarn"
|
||||
}
|
13
.github/workflows/ci-chromatic.yaml
vendored
13
.github/workflows/ci-chromatic.yaml
vendored
@ -16,17 +16,6 @@ jobs:
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- name: Front / Write .env
|
||||
run: |
|
||||
cd front
|
||||
@ -34,7 +23,7 @@ jobs:
|
||||
echo "REACT_APP_API_URL: $REACT_APP_API_URL" >> .env
|
||||
echo "REACT_APP_AUTH_URL: $REACT_APP_AUTH_URL" >> .env
|
||||
- name: Front / Install Dependencies
|
||||
run: cd front && npm install
|
||||
run: cd front && yarn
|
||||
- name: Publish to Chromatic
|
||||
uses: chromaui/action@v1
|
||||
with:
|
||||
|
15
.github/workflows/ci-docs.yaml
vendored
15
.github/workflows/ci-docs.yaml
vendored
@ -10,18 +10,7 @@ jobs:
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- name: Docs / Install Dependencies
|
||||
run: cd docs && npm install
|
||||
run: cd docs && yarn
|
||||
- name: Docs / Build Documentation
|
||||
run: cd docs && npm run build
|
||||
run: cd docs && yarn build
|
||||
|
21
.github/workflows/ci-front.yaml
vendored
21
.github/workflows/ci-front.yaml
vendored
@ -13,17 +13,6 @@ jobs:
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- name: Front / Write .env
|
||||
run: |
|
||||
cd front
|
||||
@ -31,18 +20,18 @@ jobs:
|
||||
echo "REACT_APP_API_URL: $REACT_APP_API_URL" >> .env
|
||||
echo "REACT_APP_AUTH_URL: $REACT_APP_AUTH_URL" >> .env
|
||||
- name: Front / Install Dependencies
|
||||
run: cd front && npm install
|
||||
run: cd front && yarn
|
||||
- name: Front / Install Playwright
|
||||
run: cd front && npx playwright install --with-deps
|
||||
- name: Front / Run linter
|
||||
run: cd front && npm run lint
|
||||
run: cd front && yarn lint
|
||||
- name: Front / Build Storybook
|
||||
run: cd front && npm run build-storybook --quiet
|
||||
run: cd front && yarn build-storybook --quiet
|
||||
- name: Front / Run storybook tests
|
||||
run: |
|
||||
cd front && npx concurrently -k -s first -n "SB,TEST" -c "magenta,blue" \
|
||||
"npx http-server storybook-static --silent --port 6006" \
|
||||
"npm run coverage"
|
||||
"yarn coverage"
|
||||
- name: Front / Run jest tests
|
||||
run: |
|
||||
cd front && npm run test
|
||||
cd front && yarn test
|
||||
|
17
.github/workflows/ci-server.yaml
vendored
17
.github/workflows/ci-server.yaml
vendored
@ -10,21 +10,10 @@ jobs:
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "18"
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- name: Server / Install Dependencies
|
||||
run: cd server && npm install
|
||||
run: cd server && yarn install
|
||||
- name: Server / Run linter
|
||||
run: cd server && npm run lint
|
||||
run: cd server && yarn lint
|
||||
- name: Server / Run jest tests
|
||||
run: |
|
||||
cd server && npm run test
|
||||
cd server && yarn test
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,2 +1,3 @@
|
||||
**/**/.env
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
node_modules/
|
@ -88,16 +88,16 @@ Most default value should work out of the box, but don't forget to update the da
|
||||
On the frontend:
|
||||
```
|
||||
cd front
|
||||
npm install
|
||||
yarn
|
||||
```
|
||||
|
||||
On the server side:
|
||||
```
|
||||
cd server
|
||||
npm install
|
||||
npm run prisma:migrate
|
||||
yarn
|
||||
yarn prisma:migrate
|
||||
```
|
||||
You can also add `npm run prisma:seed` to seed the database with mock data.
|
||||
You can also add `yarn prisma:seed` to seed the database with mock data.
|
||||
|
||||
### 5. Auth Setup
|
||||
Right now the only way to authenticate yourself is to setup Google Sign-in in `server/.env`
|
||||
@ -107,10 +107,10 @@ We will add an easier option soon.
|
||||
On the frontend:
|
||||
```
|
||||
cd front
|
||||
npm run start
|
||||
yarn start
|
||||
```
|
||||
On the server side:
|
||||
```
|
||||
cd server
|
||||
npm run start
|
||||
yarn start
|
||||
```
|
||||
|
13378
docs/package-lock.json
generated
13378
docs/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
8061
docs/yarn.lock
Normal file
8061
docs/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -5,7 +5,7 @@ module.exports = {
|
||||
tsconfigRootDir: __dirname,
|
||||
sourceType: 'module',
|
||||
},
|
||||
plugins: ['@typescript-eslint/eslint-plugin', 'simple-import-sort', 'better-styled-components'],
|
||||
plugins: ['@typescript-eslint/eslint-plugin', 'simple-import-sort', 'twenty'],
|
||||
extends: [
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
@ -45,6 +45,7 @@ module.exports = {
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'simple-import-sort/imports': 'error',
|
||||
'simple-import-sort/exports': 'error',
|
||||
'better-styled-components/sort-declarations-alphabetically': 2
|
||||
},
|
||||
'twenty/sort-css-properties-alphabetically': 'error',
|
||||
'twenty/no-hardcoded-colors': 'error'
|
||||
}
|
||||
};
|
||||
|
@ -6,7 +6,7 @@ This project was bootstrapped with [Create React App](https://github.com/faceboo
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm start`
|
||||
### `yarn start`
|
||||
|
||||
Runs the app in the development mode.\
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
@ -14,12 +14,12 @@ Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
The page will reload if you make edits.\
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### `npm test`
|
||||
### `yarn test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.\
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `npm run build`
|
||||
### `yarn build`
|
||||
|
||||
Builds the app for production to the `build` folder.\
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
@ -29,7 +29,7 @@ Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `npm run eject`
|
||||
### `yarn eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
|
39485
front/package-lock.json
generated
39485
front/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,7 @@
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.7.5",
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@emotion/react": "^11.10.6",
|
||||
"@emotion/styled": "^11.10.5",
|
||||
"@hello-pangea/dnd": "^16.2.0",
|
||||
@ -115,7 +116,6 @@
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-config-react-app": "^7.0.1",
|
||||
"eslint-config-standard-with-typescript": "^23.0.0",
|
||||
"eslint-plugin-better-styled-components": "^1.1.2",
|
||||
"eslint-plugin-import": "^2.26.0",
|
||||
"eslint-plugin-n": "^15.5.1",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
@ -123,6 +123,7 @@
|
||||
"eslint-plugin-react": "^7.31.11",
|
||||
"eslint-plugin-simple-import-sort": "^10.0.0",
|
||||
"eslint-plugin-storybook": "^0.6.11",
|
||||
"eslint-plugin-twenty": "file:../packages/eslint-plugin-twenty",
|
||||
"http-server": "^14.1.1",
|
||||
"mock-apollo-client": "^1.2.1",
|
||||
"msw": "^1.2.1",
|
||||
|
@ -2,7 +2,7 @@
|
||||
/* tslint:disable */
|
||||
|
||||
/**
|
||||
* Mock Service Worker (1.2.1).
|
||||
* Mock Service Worker (1.2.2).
|
||||
* @see https://github.com/mswjs/msw
|
||||
* - Please do NOT modify this file.
|
||||
* - Please do NOT serve this file on production.
|
||||
|
@ -49,9 +49,11 @@ const StyledDate = styled.div`
|
||||
const StyledTooltip = styled(Tooltip)`
|
||||
background-color: ${(props) => props.theme.primaryBackground};
|
||||
|
||||
box-shadow: 0px 2px 4px 3px rgba(0, 0, 0, 0.04);
|
||||
box-shadow: 0px 2px 4px 3px
|
||||
${(props) => props.theme.lightBackgroundTransparent};
|
||||
|
||||
box-shadow: 2px 4px 16px 6px rgba(0, 0, 0, 0.12);
|
||||
box-shadow: 2px 4px 16px 6px
|
||||
${(props) => props.theme.lightBackgroundTransparent};
|
||||
|
||||
color: ${(props) => props.theme.text100};
|
||||
|
||||
|
@ -4,7 +4,7 @@ import { Command } from 'cmdk';
|
||||
export const StyledDialog = styled(Command.Dialog)`
|
||||
background: ${(props) => props.theme.primaryBackground};
|
||||
border-radius: ${(props) => props.theme.borderRadius};
|
||||
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.09);
|
||||
box-shadow: ${(props) => props.theme.modalBoxShadow};
|
||||
font-family: ${(props) => props.theme.fontFamily};
|
||||
left: 50%;
|
||||
max-width: 640px;
|
||||
@ -45,7 +45,7 @@ export const StyledItem = styled(Command.Item)`
|
||||
transition-property: none;
|
||||
user-select: none;
|
||||
&:hover {
|
||||
background: ${(props) => props.theme.clickableElementBackgroundHover};
|
||||
background: ${(props) => props.theme.lightBackgroundTransparent};
|
||||
}
|
||||
&[data-selected='true'] {
|
||||
background: ${(props) => props.theme.secondaryBackground};
|
||||
|
@ -2,7 +2,7 @@ import styled from '@emotion/styled';
|
||||
|
||||
export const HoverableMenuItem = styled.div`
|
||||
align-items: center;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
background: ${(props) => props.theme.primaryBackground};
|
||||
border-radius: 4px;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
@ -14,6 +14,6 @@ export const HoverableMenuItem = styled.div`
|
||||
width: 100%;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
background: ${(props) => props.theme.lightBackgroundTransparent};
|
||||
}
|
||||
`;
|
||||
|
@ -26,7 +26,7 @@ const StyledCalendarContainer = styled.div<StyledCalendarContainerProps>`
|
||||
background: ${(props) => props.theme.secondaryBackground};
|
||||
border: 1px solid ${(props) => props.theme.primaryBorder};
|
||||
border-radius: 8px;
|
||||
box-shadow: 0px 3px 12px rgba(0, 0, 0, 0.09);
|
||||
box-shadow: ${(props) => props.theme.modalBoxShadow};
|
||||
left: -10px;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
|
@ -127,7 +127,7 @@ const StyledContainer = styled.div`
|
||||
margin: 2px;
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
background: ${(props) => props.theme.lightBackgroundTransparent};
|
||||
}
|
||||
|
||||
&:first-of-type {
|
||||
@ -172,7 +172,7 @@ const StyledContainer = styled.div`
|
||||
border-radius: 4px;
|
||||
padding-top: 6px;
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
background: ${(props) => props.theme.lightBackgroundTransparent};
|
||||
}
|
||||
}
|
||||
& .react-datepicker__navigation--previous {
|
||||
|
@ -90,7 +90,7 @@ const StyledDropdownItem = styled.li`
|
||||
width: calc(160px - ${(props) => props.theme.spacing(4)});
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
background: ${(props) => props.theme.lightBackgroundTransparent};
|
||||
}
|
||||
`;
|
||||
|
||||
@ -112,7 +112,7 @@ const StyledDropdownTopOption = styled.li`
|
||||
calc(${(props) => props.theme.spacing(2)});
|
||||
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
background: ${(props) => props.theme.lightBackgroundTransparent};
|
||||
}
|
||||
user-select: none;
|
||||
`;
|
||||
|
@ -22,7 +22,8 @@ type StyledItemProps = {
|
||||
|
||||
const StyledItem = styled.button<StyledItemProps>`
|
||||
align-items: center;
|
||||
background: ${(props) => (props.active ? 'rgba(0, 0, 0, 0.04)' : 'inherit')};
|
||||
background: ${(props) =>
|
||||
props.active ? props.theme.lightBackgroundTransparent : 'inherit'};
|
||||
border: none;
|
||||
border-radius: 4px;
|
||||
color: ${(props) => {
|
||||
@ -47,7 +48,7 @@ const StyledItem = styled.button<StyledItemProps>`
|
||||
padding-top: ${(props) => props.theme.spacing(1)};
|
||||
pointer-events: ${(props) => (props.soon ? 'none' : 'auto')};
|
||||
:hover {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
background: ${(props) => props.theme.lightBackgroundTransparent};
|
||||
color: ${(props) => (props.danger ? props.theme.red : props.theme.text100)};
|
||||
}
|
||||
user-select: none;
|
||||
@ -67,7 +68,7 @@ const StyledSoonPill = styled.div`
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 50px;
|
||||
background-color: rgba(0, 0, 0, 0.04);
|
||||
background-color: ${(props) => props.theme.lightBackgroundTransparent};
|
||||
font-size: ${(props) => props.theme.fontSizeExtraSmall};
|
||||
padding: ${(props) => props.theme.spacing(1)}
|
||||
${(props) => props.theme.spacing(2)} ${(props) => props.theme.spacing(1)}
|
||||
|
@ -20,7 +20,7 @@ const StyledButton = styled.button`
|
||||
|
||||
width: 24px;
|
||||
&:hover {
|
||||
background: ${(props) => props.theme.clickableElementBackgroundHover};
|
||||
background: ${(props) => props.theme.lightBackgroundTransparent};
|
||||
}
|
||||
svg {
|
||||
color: ${(props) => props.theme.text40};
|
||||
|
@ -48,12 +48,15 @@ const lightThemeSpecific = {
|
||||
|
||||
primaryBackgroundTransparent: 'rgba(255, 255, 255, 0.8)',
|
||||
secondaryBackgroundTransparent: 'rgba(252, 252, 252, 0.8)',
|
||||
strongBackgroundTransparent: 'rgba(0, 0, 0, 0.16)',
|
||||
mediumBackgroundTransparent: 'rgba(0, 0, 0, 0.08)',
|
||||
lightBackgroundTransparent: 'rgba(0, 0, 0, 0.04)',
|
||||
lighterBackgroundTransparent: 'rgba(0, 0, 0, 0.02)',
|
||||
|
||||
primaryBorder: 'rgba(0, 0, 0, 0.08)',
|
||||
lightBorder: '#f5f5f5',
|
||||
mediumBorder: '#ebebeb',
|
||||
|
||||
clickableElementBackgroundHover: 'rgba(0, 0, 0, 0.04)',
|
||||
clickableElementBackgroundTransition: 'background 0.1s ease',
|
||||
|
||||
text100: '#000',
|
||||
@ -93,8 +96,11 @@ const darkThemeSpecific: typeof lightThemeSpecific = {
|
||||
|
||||
primaryBackgroundTransparent: 'rgba(20, 20, 20, 0.8)',
|
||||
secondaryBackgroundTransparent: 'rgba(23, 23, 23, 0.8)',
|
||||
strongBackgroundTransparent: 'rgba(255, 255, 255, 0.09)',
|
||||
mediumBackgroundTransparent: 'rgba(255, 255, 255, 0.06)',
|
||||
lightBackgroundTransparent: 'rgba(255, 255, 255, 0.03)',
|
||||
lighterBackgroundTransparent: 'rgba(255, 255, 255, 0.02)',
|
||||
|
||||
clickableElementBackgroundHover: 'rgba(0, 0, 0, 0.04)',
|
||||
clickableElementBackgroundTransition: 'background 0.1s ease',
|
||||
|
||||
primaryBorder: 'rgba(255, 255, 255, 0.08)',
|
||||
@ -148,7 +154,7 @@ export const hoverBackground = (props: any) =>
|
||||
css`
|
||||
transition: background 0.1s ease;
|
||||
&:hover {
|
||||
background: rgba(0, 0, 0, 0.04);
|
||||
background: ${props.theme.lightBackgroundTransparent};
|
||||
}
|
||||
`;
|
||||
|
||||
|
17119
front/yarn.lock
Normal file
17119
front/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
@ -15,25 +15,25 @@ sh:
|
||||
@docker-compose exec twenty-dev sh
|
||||
|
||||
front-start:
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/front && npm run start"
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/front && yarn start"
|
||||
|
||||
front-test:
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/front && npm run test"
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/front && yarn test"
|
||||
|
||||
front-graphql-generate:
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/server && npm run graphql:generate"
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/server && yarn graphql:generate"
|
||||
|
||||
front-storybook:
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/front && npm run storybook"
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/front && yarn storybook"
|
||||
|
||||
server-start:
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/server && npm run start:dev"
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/server && yarn start:dev"
|
||||
|
||||
server-prisma-generate:
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/server && npm run prisma:generate"
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/server && yarn prisma:generate"
|
||||
|
||||
server-prisma-migrate:
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/server && npm run prisma:migrate"
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/server && yarn prisma:migrate"
|
||||
|
||||
server-prisma-seed:
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/server && npm run prisma:seed"
|
||||
@docker-compose exec twenty-dev sh -c "cd /app/server && yarn prisma:seed"
|
||||
|
6
infra/dev/package-lock.json
generated
Normal file
6
infra/dev/package-lock.json
generated
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "dev",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {}
|
||||
}
|
@ -1,17 +1,19 @@
|
||||
FROM node:18.16.0 as front
|
||||
FROM node:18.16-bullseye as front
|
||||
|
||||
COPY /../../packages /app/packages
|
||||
|
||||
WORKDIR /app/front
|
||||
|
||||
COPY ../../front/package.json .
|
||||
COPY ../../front/package-lock.json .
|
||||
RUN npm install
|
||||
COPY ../../front/yarn.lock .
|
||||
RUN yarn install
|
||||
RUN npx playwright install-deps
|
||||
|
||||
WORKDIR /app/server
|
||||
|
||||
COPY ../../server/package.json .
|
||||
COPY ../../server/package-lock.json .
|
||||
RUN npm install
|
||||
COPY ../../server/yarn.lock .
|
||||
RUN yarn install
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
FROM node:18.16.0-alpine as docs
|
||||
FROM node:18.16-bullseye as docs
|
||||
|
||||
WORKDIR /app/docs
|
||||
|
||||
COPY ../../docs/package.json .
|
||||
COPY ../../docs/package-lock.json .
|
||||
RUN npm install
|
||||
COPY ../../docs/yarn.lock .
|
||||
RUN yarn
|
||||
|
||||
COPY ../../docs .
|
||||
|
||||
CMD ["npm", "run", "start"]
|
||||
CMD ["npm", "run", "start"]
|
@ -3,12 +3,12 @@ FROM node:18.16.0-alpine as docs
|
||||
WORKDIR /app/docs
|
||||
|
||||
COPY ./docs/package.json .
|
||||
COPY ./docs/package-lock.json .
|
||||
RUN npm install
|
||||
COPY ./docs/yarn.lock .
|
||||
RUN yarn install
|
||||
|
||||
COPY ./docs .
|
||||
RUN npm run build
|
||||
|
||||
RUN npm install -g serve
|
||||
RUN yarn install -g serve
|
||||
|
||||
CMD ["serve", "-s", "./build"]
|
||||
|
@ -6,9 +6,9 @@ ARG REACT_APP_AUTH_URL
|
||||
WORKDIR /app/front
|
||||
COPY ./front .
|
||||
|
||||
RUN npm install
|
||||
RUN npm run build
|
||||
RUN yarn install --install-links
|
||||
RUN yarn build
|
||||
|
||||
RUN npm install -g serve
|
||||
RUN yarn install -g serve
|
||||
|
||||
CMD ["serve", "-s", "build"]
|
||||
|
@ -2,12 +2,12 @@ FROM node:18.16.0-alpine as server
|
||||
|
||||
WORKDIR /app/server
|
||||
COPY ./server/package.json ./
|
||||
COPY ./server/package-lock.json ./
|
||||
RUN npm install
|
||||
COPY ./server/yarn.lock ./
|
||||
RUN yarn install
|
||||
|
||||
COPY ./server .
|
||||
RUN npx prisma generate
|
||||
|
||||
RUN npm run build
|
||||
RUN yarn build
|
||||
|
||||
CMD ["node", "dist/main"]
|
||||
|
10
packages/eslint-plugin-twenty/index.js
Normal file
10
packages/eslint-plugin-twenty/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const noHardcodedColors = require('./rules/no-hardcoded-colors');
|
||||
const cssAlphabetically = require('./rules/sort-css-properties-alphabetically');
|
||||
|
||||
module.exports = {
|
||||
rules: {
|
||||
'no-hardcoded-colors': noHardcodedColors,
|
||||
'sort-css-properties-alphabetically': cssAlphabetically,
|
||||
},
|
||||
};
|
8
packages/eslint-plugin-twenty/package.json
Normal file
8
packages/eslint-plugin-twenty/package.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "eslint-plugin-twenty",
|
||||
"version": "0.0.1",
|
||||
"main": "index.js",
|
||||
"dependencies": {
|
||||
"postcss": "^8.4.24"
|
||||
}
|
||||
}
|
24
packages/eslint-plugin-twenty/rules/no-hardcoded-colors.js
Normal file
24
packages/eslint-plugin-twenty/rules/no-hardcoded-colors.js
Normal file
@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
create: function (context) {
|
||||
return {
|
||||
TaggedTemplateExpression(node) {
|
||||
if (context.getFilename().endsWith('themes.ts')) {
|
||||
return;
|
||||
}
|
||||
|
||||
node.quasi.quasis.forEach((quasi) => {
|
||||
const colorRegex =
|
||||
/(?:rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})(,\s*\d+\.?\d*)?\))|(?:#[0-9a-fA-F]{6})/i;
|
||||
|
||||
if (colorRegex.test(quasi.value.raw)) {
|
||||
context.report({
|
||||
node,
|
||||
message:
|
||||
'Do not use hardcoded RGBA or Hex colors. Please use a color from the theme file.',
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
@ -0,0 +1,208 @@
|
||||
"use strict";
|
||||
const postcss = require("postcss");
|
||||
|
||||
function isStyledTagname(node) {
|
||||
return (
|
||||
(node.tag.type === "Identifier" && node.tag.name === "css") ||
|
||||
(node.tag.type === "MemberExpression" &&
|
||||
node.tag.object.name === "styled") ||
|
||||
(node.tag.type === "CallExpression" &&
|
||||
(node.tag.callee.name === "styled" ||
|
||||
(node.tag.callee.object &&
|
||||
((node.tag.callee.object.callee &&
|
||||
node.tag.callee.object.callee.name === "styled") ||
|
||||
(node.tag.callee.object.object &&
|
||||
node.tag.callee.object.object.name === "styled")))))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* An atomic rule is a rule without nested rules.
|
||||
*/
|
||||
function isValidAtomicRule(rule) {
|
||||
const decls = rule.nodes.filter(node => node.type === "decl");
|
||||
if (decls.length < 0) {
|
||||
return { isValid: true };
|
||||
}
|
||||
|
||||
for (let i = 1; i < decls.length; i++) {
|
||||
const current = decls[i].prop;
|
||||
const prev = decls[i - 1].prop;
|
||||
if (current < prev) {
|
||||
const loc = {
|
||||
start: {
|
||||
line: decls[i - 1].source.start.line,
|
||||
column: decls[i - 1].source.start.column - 1
|
||||
},
|
||||
end: {
|
||||
line: decls[i].source.end.line,
|
||||
column: decls[i].source.end.column - 1
|
||||
}
|
||||
};
|
||||
|
||||
return { isValid: false, loc };
|
||||
}
|
||||
}
|
||||
|
||||
return { isValid: true };
|
||||
}
|
||||
|
||||
function isValidRule(rule) {
|
||||
// check each rule recursively
|
||||
const { isValid, loc } = rule.nodes.reduce(
|
||||
(map, node) => {
|
||||
return node.type === "rule" ? isValidRule(node) : map;
|
||||
},
|
||||
{ isValid: true }
|
||||
);
|
||||
|
||||
// if there is any invalid rule, return result
|
||||
if (!isValid) {
|
||||
return { isValid, loc };
|
||||
}
|
||||
|
||||
// check declarations
|
||||
return isValidAtomicRule(rule);
|
||||
}
|
||||
|
||||
function getNodeStyles(node) {
|
||||
const [firstQuasi, ...quasis] = node.quasi.quasis;
|
||||
// remove line break added to the first quasi
|
||||
const lineBreakCount = node.quasi.loc.start.line - 1;
|
||||
let styles = `${"\n".repeat(lineBreakCount)}${" ".repeat(
|
||||
node.quasi.loc.start.column + 1
|
||||
)}${firstQuasi.value.raw}`;
|
||||
|
||||
// replace expression by spaces and line breaks
|
||||
quasis.forEach(({ value, loc }, idx) => {
|
||||
const prevLoc = idx === 0 ? firstQuasi.loc : quasis[idx - 1].loc;
|
||||
const lineBreaksCount = loc.start.line - prevLoc.end.line;
|
||||
const spacesCount =
|
||||
loc.start.line === prevLoc.end.line
|
||||
? loc.start.column - prevLoc.end.column + 2
|
||||
: loc.start.column + 1;
|
||||
styles = `${styles}${" "}${"\n".repeat(lineBreaksCount)}${" ".repeat(
|
||||
spacesCount
|
||||
)}${value.raw}`;
|
||||
});
|
||||
|
||||
return styles;
|
||||
}
|
||||
|
||||
function create(context) {
|
||||
return {
|
||||
TaggedTemplateExpression(node) {
|
||||
if (isStyledTagname(node)) {
|
||||
try {
|
||||
const root = postcss.parse(getNodeStyles(node));
|
||||
|
||||
const { isValid, loc } = isValidRule(root);
|
||||
|
||||
if (!isValid) {
|
||||
return context.report({
|
||||
node,
|
||||
messageId: "sort-css-properties-alphabetically",
|
||||
loc,
|
||||
fix: fixer =>
|
||||
fix({
|
||||
rule: root,
|
||||
fixer,
|
||||
src: context.getSourceCode()
|
||||
})
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function fix({ rule, fixer, src }) {
|
||||
let fixings = [];
|
||||
|
||||
// concat fixings recursively
|
||||
rule.nodes.forEach(node => {
|
||||
if (node.type === "rule") {
|
||||
fixings = [...fixings, ...fix({ rule: node, fixer, src })];
|
||||
}
|
||||
});
|
||||
|
||||
const declarations = rule.nodes.filter(node => node.type === "decl");
|
||||
const sortedDeclarations = sortDeclarations(declarations);
|
||||
|
||||
declarations.forEach((decl, idx) => {
|
||||
if (!areSameDeclarations(decl, sortedDeclarations[idx])) {
|
||||
try {
|
||||
const range = getDeclRange({ decl, src });
|
||||
const sortedDeclText = getDeclText({
|
||||
decl: sortedDeclarations[idx],
|
||||
src
|
||||
});
|
||||
|
||||
fixings.push(fixer.removeRange([range.startIdx, range.endIdx + 1]));
|
||||
fixings.push(
|
||||
fixer.insertTextAfterRange(
|
||||
[range.startIdx, range.startIdx],
|
||||
sortedDeclText
|
||||
)
|
||||
);
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
return fixings;
|
||||
}
|
||||
|
||||
function areSameDeclarations(a, b) {
|
||||
return (
|
||||
a.source.start.line === b.source.start.line &&
|
||||
a.source.start.column === b.source.start.column
|
||||
);
|
||||
}
|
||||
|
||||
function getDeclRange({ decl, src }) {
|
||||
const loc = {
|
||||
start: {
|
||||
line: decl.source.start.line,
|
||||
column: decl.source.start.column - 1
|
||||
},
|
||||
end: {
|
||||
line: decl.source.end.line,
|
||||
column: decl.source.end.column - 1
|
||||
}
|
||||
};
|
||||
|
||||
const startIdx = src.getIndexFromLoc(loc.start);
|
||||
const endIdx = src.getIndexFromLoc(loc.end);
|
||||
return { startIdx, endIdx };
|
||||
}
|
||||
|
||||
function getDeclText({ decl, src }) {
|
||||
const { startIdx, endIdx } = getDeclRange({ decl, src });
|
||||
return src.getText().substring(startIdx, endIdx + 1);
|
||||
}
|
||||
|
||||
function sortDeclarations(declarations) {
|
||||
return declarations
|
||||
.slice()
|
||||
.sort((declA, declB) => (declA.prop > declB.prop ? 1 : -1));
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
meta: {
|
||||
docs: {
|
||||
description: "Styles are sorted alphabetically.",
|
||||
category: "Fill me in",
|
||||
recommended: false
|
||||
},
|
||||
messages: {
|
||||
"sort-css-properties-alphabetically":
|
||||
"Declarations should be sorted alphabetically."
|
||||
},
|
||||
fixable: "code"
|
||||
},
|
||||
create
|
||||
};
|
27
packages/eslint-plugin-twenty/yarn.lock
Normal file
27
packages/eslint-plugin-twenty/yarn.lock
Normal file
@ -0,0 +1,27 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
nanoid@^3.3.6:
|
||||
version "3.3.6"
|
||||
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c"
|
||||
integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==
|
||||
|
||||
picocolors@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
postcss@^8.4.24:
|
||||
version "8.4.24"
|
||||
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.24.tgz#f714dba9b2284be3cc07dbd2fc57ee4dc972d2df"
|
||||
integrity sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==
|
||||
dependencies:
|
||||
nanoid "^3.3.6"
|
||||
picocolors "^1.0.0"
|
||||
source-map-js "^1.0.2"
|
||||
|
||||
source-map-js@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c"
|
||||
integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==
|
@ -36,26 +36,26 @@ $ npm install
|
||||
|
||||
```bash
|
||||
# development
|
||||
$ npm run start
|
||||
$ npm start
|
||||
|
||||
# watch mode
|
||||
$ npm run start:dev
|
||||
$ npm start:dev
|
||||
|
||||
# production mode
|
||||
$ npm run start:prod
|
||||
$ npm start:prod
|
||||
```
|
||||
|
||||
## Test
|
||||
|
||||
```bash
|
||||
# unit tests
|
||||
$ npm run test
|
||||
$ npm test
|
||||
|
||||
# e2e tests
|
||||
$ npm run test:e2e
|
||||
$ npm test:e2e
|
||||
|
||||
# test coverage
|
||||
$ npm run test:cov
|
||||
$ npm test:cov
|
||||
```
|
||||
|
||||
## Support
|
||||
|
9667
server/package-lock.json
generated
9667
server/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -24,10 +24,12 @@
|
||||
"prisma:seed": "npx prisma db seed"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/server": "^4.7.3",
|
||||
"@nestjs/apollo": "^11.0.5",
|
||||
"@nestjs/common": "^9.0.0",
|
||||
"@nestjs/config": "^2.3.2",
|
||||
"@nestjs/core": "^9.0.0",
|
||||
"@nestjs/graphql": "^11.0.6",
|
||||
"@nestjs/jwt": "^10.0.3",
|
||||
"@nestjs/passport": "^9.0.3",
|
||||
"@nestjs/platform-express": "^9.0.0",
|
||||
|
5933
server/yarn.lock
Normal file
5933
server/yarn.lock
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user