mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
Move Storybook back into web (#13219)
GitOrigin-RevId: 61b69b5fd178dd4f5ab26858c434f959dfc410bc
This commit is contained in:
parent
b228c9016e
commit
76d195cd39
11 changed files with 7034 additions and 1466 deletions
8153
package-lock.json
generated
8153
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -49,7 +49,6 @@
|
||||||
"services/third-party-datastore",
|
"services/third-party-datastore",
|
||||||
"services/third-party-references",
|
"services/third-party-references",
|
||||||
"services/tpdsworker",
|
"services/tpdsworker",
|
||||||
"services/web",
|
"services/web"
|
||||||
"tools/storybook"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
62
services/web/.storybook/main.ts
Normal file
62
services/web/.storybook/main.ts
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
import type { StorybookConfig } from '@storybook/react-webpack5'
|
||||||
|
import path from 'node:path'
|
||||||
|
|
||||||
|
const rootDir = path.resolve(__dirname, '..')
|
||||||
|
|
||||||
|
// NOTE: must be set before webpack config is imported
|
||||||
|
process.env.SHARELATEX_CONFIG = path.join(rootDir, 'config/settings.webpack.js')
|
||||||
|
|
||||||
|
const config: StorybookConfig = {
|
||||||
|
core: {
|
||||||
|
disableTelemetry: true,
|
||||||
|
},
|
||||||
|
staticDirs: [path.join(rootDir, 'public')],
|
||||||
|
stories: [
|
||||||
|
path.join(rootDir, 'frontend/stories/**/*.stories.{js,jsx,ts,tsx}'),
|
||||||
|
path.join(rootDir, 'modules/**/stories/**/*.stories.{js,jsx,ts,tsx}'),
|
||||||
|
],
|
||||||
|
addons: [
|
||||||
|
'@storybook/addon-links',
|
||||||
|
'@storybook/addon-essentials',
|
||||||
|
'@storybook/addon-interactions',
|
||||||
|
'@storybook/addon-a11y',
|
||||||
|
],
|
||||||
|
framework: {
|
||||||
|
name: '@storybook/react-webpack5',
|
||||||
|
options: {},
|
||||||
|
},
|
||||||
|
docs: {
|
||||||
|
autodocs: 'tag',
|
||||||
|
},
|
||||||
|
babel: options => {
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
plugins: [
|
||||||
|
// ensure that TSX files are transformed before other plugins run
|
||||||
|
['@babel/plugin-transform-typescript', { isTSX: true }],
|
||||||
|
...(options.plugins ?? []),
|
||||||
|
],
|
||||||
|
}
|
||||||
|
},
|
||||||
|
webpackFinal: storybookConfig => {
|
||||||
|
return {
|
||||||
|
...storybookConfig,
|
||||||
|
resolve: {
|
||||||
|
...storybookConfig.resolve,
|
||||||
|
fallback: {
|
||||||
|
...storybookConfig.resolve?.fallback,
|
||||||
|
fs: false,
|
||||||
|
os: false,
|
||||||
|
module: false,
|
||||||
|
},
|
||||||
|
extensions: ['.js', '.jsx', '.mjs', '.ts', '.tsx', '.json'],
|
||||||
|
alias: {
|
||||||
|
...storybookConfig.resolve?.alias,
|
||||||
|
// custom prefixes for import paths
|
||||||
|
'@': path.join(rootDir, 'frontend/js/'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
export default config
|
3
services/web/.storybook/manager.css
Normal file
3
services/web/.storybook/manager.css
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
.sidebar-container a[title='Overleaf'] {
|
||||||
|
max-width: 100px;
|
||||||
|
}
|
15
services/web/.storybook/manager.ts
Normal file
15
services/web/.storybook/manager.ts
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { addons } from '@storybook/addons'
|
||||||
|
import { create } from '@storybook/theming'
|
||||||
|
|
||||||
|
import './manager.css'
|
||||||
|
|
||||||
|
import brandImage from '../public/img/ol-brand/overleaf.svg'
|
||||||
|
|
||||||
|
const theme = create({
|
||||||
|
base: 'light',
|
||||||
|
brandTitle: 'Overleaf',
|
||||||
|
brandUrl: 'https://www.overleaf.com',
|
||||||
|
brandImage,
|
||||||
|
})
|
||||||
|
|
||||||
|
addons.setConfig({ theme })
|
101
services/web/.storybook/preview.tsx
Normal file
101
services/web/.storybook/preview.tsx
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
import type { Preview } from '@storybook/react'
|
||||||
|
|
||||||
|
// Storybook does not (currently) support async loading of "stories". Therefore
|
||||||
|
// the strategy in frontend/js/i18n.js does not work (because we cannot wait on
|
||||||
|
// the promise to resolve).
|
||||||
|
// Therefore we have to use the synchronous method for configuring
|
||||||
|
// react-i18next. Because this, we can only hard-code a single language.
|
||||||
|
import i18n from 'i18next'
|
||||||
|
import { initReactI18next } from 'react-i18next'
|
||||||
|
// @ts-ignore
|
||||||
|
import en from '../../../services/web/locales/en.json'
|
||||||
|
import { ExposedSettings } from '../types/exposed-settings'
|
||||||
|
import { User } from '../types/user'
|
||||||
|
|
||||||
|
window.i18n = window.i18n || {}
|
||||||
|
window.i18n.currentLangCode = window.i18n.currentLangCode || 'en'
|
||||||
|
i18n.use(initReactI18next).init({
|
||||||
|
lng: 'en',
|
||||||
|
|
||||||
|
// still using the v3 plural suffixes
|
||||||
|
compatibilityJSON: 'v3',
|
||||||
|
|
||||||
|
resources: {
|
||||||
|
en: { translation: en },
|
||||||
|
},
|
||||||
|
|
||||||
|
react: {
|
||||||
|
useSuspense: false,
|
||||||
|
transSupportBasicHtmlNodes: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
interpolation: {
|
||||||
|
prefix: '__',
|
||||||
|
suffix: '__',
|
||||||
|
unescapeSuffix: 'HTML',
|
||||||
|
skipOnVariables: true,
|
||||||
|
escapeValue: false,
|
||||||
|
defaultVariables: {
|
||||||
|
appName: 'Overleaf',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
// avoid some errors by creating these objects in advance
|
||||||
|
window.user = {} as User
|
||||||
|
window.ExposedSettings = {} as ExposedSettings
|
||||||
|
|
||||||
|
const preview: Preview = {
|
||||||
|
parameters: {
|
||||||
|
// Automatically mark prop-types like onClick, onToggle, etc as Storybook
|
||||||
|
// "actions", so that they are logged in the Actions pane at the bottom of the
|
||||||
|
// viewer
|
||||||
|
actions: { argTypesRegex: '^on.*' },
|
||||||
|
docs: {
|
||||||
|
// render stories in iframes, to isolate modals
|
||||||
|
inlineStories: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
globalTypes: {
|
||||||
|
theme: {
|
||||||
|
name: 'Theme',
|
||||||
|
description: 'Editor theme',
|
||||||
|
defaultValue: 'main-',
|
||||||
|
toolbar: {
|
||||||
|
icon: 'circlehollow',
|
||||||
|
items: [
|
||||||
|
{ value: 'main-', title: 'Default' },
|
||||||
|
{ value: 'main-light-', title: 'Light' },
|
||||||
|
{ value: 'main-ieee-', title: 'IEEE' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
loaders: [
|
||||||
|
async ({ globals }) => {
|
||||||
|
const { theme } = globals
|
||||||
|
|
||||||
|
return {
|
||||||
|
// NOTE: this uses `${theme}style.less` rather than `${theme}.less`
|
||||||
|
// so that webpack only bundles files ending with "style.less"
|
||||||
|
activeStyle: await import(
|
||||||
|
`!!to-string-loader!css-loader!less-loader!../../../services/web/frontend/stylesheets/${theme}style.less`
|
||||||
|
),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
decorators: [
|
||||||
|
(Story, context) => {
|
||||||
|
const { activeStyle } = context.loaded
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{activeStyle && <style>{activeStyle.default}</style>}
|
||||||
|
<Story {...context} />
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
export default preview
|
|
@ -552,6 +552,15 @@ tar:
|
||||||
COMPOSE_PROJECT_NAME=tar_$(BUILD_DIR_NAME) $(DOCKER_COMPOSE) run --rm tar
|
COMPOSE_PROJECT_NAME=tar_$(BUILD_DIR_NAME) $(DOCKER_COMPOSE) run --rm tar
|
||||||
COMPOSE_PROJECT_NAME=tar_$(BUILD_DIR_NAME) $(DOCKER_COMPOSE) down -v -t 0
|
COMPOSE_PROJECT_NAME=tar_$(BUILD_DIR_NAME) $(DOCKER_COMPOSE) down -v -t 0
|
||||||
|
|
||||||
|
build_storybook:
|
||||||
|
npm run build-storybook
|
||||||
|
if [[ -n "$(BRANCH_NAME)" ]]; then \
|
||||||
|
echo "Renaming storybook-static -> $(BRANCH_NAME)."; \
|
||||||
|
d=$$(dirname "$(BRANCH_NAME)"); \
|
||||||
|
mkdir -p "storybook-output/$$d"; \
|
||||||
|
mv storybook-static "storybook-output/$$d/$$(basename "$(BRANCH_NAME)")/"; \
|
||||||
|
fi
|
||||||
|
|
||||||
MODULE_TARGETS = \
|
MODULE_TARGETS = \
|
||||||
$(TEST_ACCEPTANCE_MODULES_SAAS) \
|
$(TEST_ACCEPTANCE_MODULES_SAAS) \
|
||||||
$(TEST_ACCEPTANCE_MODULES_SERVER_CE) \
|
$(TEST_ACCEPTANCE_MODULES_SERVER_CE) \
|
||||||
|
|
78
services/web/cloudbuild-storybook-index.html.m4
Normal file
78
services/web/cloudbuild-storybook-index.html.m4
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
divert(`-1')
|
||||||
|
define(`foreach', `pushdef(`$1')_foreach($@)popdef(`$1')')
|
||||||
|
define(`_arg1', `$1')
|
||||||
|
define(`_foreach', `ifelse(`$2', `()', `',
|
||||||
|
`define(`$1', _arg1$2)$3`'$0(`$1', (shift$2), `$3')')')
|
||||||
|
divert`'dnl
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Overleaf Storybook builds</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color: #fff;
|
||||||
|
color: #5d6879;
|
||||||
|
font-family: Lato,sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
line-height: 1.5625;
|
||||||
|
min-height: 100%;
|
||||||
|
position: relative;
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
color: rgb(80, 80, 80);
|
||||||
|
font-family: Merriweather, serif;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.35;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
margin-top: 0px;
|
||||||
|
padding-top: 100px;
|
||||||
|
}
|
||||||
|
.navbar-default {
|
||||||
|
background-color: #1e2530;
|
||||||
|
border-color: transparent;
|
||||||
|
height: 68px;
|
||||||
|
padding: 15px 10px;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
width: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.navbar-default .navbar-brand {
|
||||||
|
background-image: url(https://cdn.overleaf.com/images/overleaf-white-65b70e33f35fccdf6f8d.svg);
|
||||||
|
background-position: 0;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: contain;
|
||||||
|
bottom: 5px;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
top: 5px;
|
||||||
|
width: 130px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<nav class="navbar-default">
|
||||||
|
<a class="navbar-brand" href="https://www.overleaf.com/"></a>
|
||||||
|
</nav>
|
||||||
|
<h1>Overleaf Storybook builds</h1>
|
||||||
|
<h2>Branches:</h2>
|
||||||
|
<ul>
|
||||||
|
foreach(DIR, (LIST),
|
||||||
|
<li>
|
||||||
|
<a href="DIR/">DIR/</a>
|
||||||
|
<a href="https://github.com/overleaf/internal/tree/DIR">
|
||||||
|
<img src="https://github.com/favicon.ico" alt="GitHub" width="15em">
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
)
|
||||||
|
</ul>
|
||||||
|
<small>
|
||||||
|
Last updated on syscmd(date)dnl
|
||||||
|
for ifdef(`BRANCH_NAME',<a href="BRANCH_NAME/">BRANCH_NAME</a>,unknown branch)
|
||||||
|
(<a href="https://console.cloud.google.com/cloud-build/builds?project=overleaf-dev&pageState=(%22builds%22:(%22f%22:%22%255B%257B_22k_22_3A_22Trigger%2520Name_22_2C_22t_22_3A10_2C_22v_22_3A_22_5C_22storybook-pr-trigger_5C_22_22_2C_22s_22_3Atrue_2C_22i_22_3A_22triggerName_22%257D_2C%257B_22k_22_3A_22_22_2C_22t_22_3A10_2C_22v_22_3A_22_5C_22OR_5C_22_22_2C_22o_22_3Atrue_2C_22s_22_3Atrue%257D_2C%257B_22k_22_3A_22Trigger%2520Name_22_2C_22t_22_3A10_2C_22v_22_3A_22_5C_22storybook-push-trigger_5C_22_22_2C_22s_22_3Atrue_2C_22i_22_3A_22triggerName_22%257D%255D%22))">build history</a>).
|
||||||
|
</small>
|
||||||
|
</body>
|
||||||
|
</html>
|
63
services/web/cloudbuild-storybook.yaml
Normal file
63
services/web/cloudbuild-storybook.yaml
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
steps:
|
||||||
|
- id: build-storybook
|
||||||
|
name: 'node:18.18.2'
|
||||||
|
env:
|
||||||
|
- 'BRANCH_NAME=$BRANCH_NAME'
|
||||||
|
- 'BUILD_ID=$BUILD_ID'
|
||||||
|
script: |
|
||||||
|
#!/bin/bash
|
||||||
|
set -e
|
||||||
|
make -C services/web BRANCH_NAME="${BRANCH_NAME:-$BUILD_ID}" build_storybook
|
||||||
|
|
||||||
|
- id: deploy-storybook
|
||||||
|
name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
|
||||||
|
env:
|
||||||
|
- 'BRANCH_NAME=$BRANCH_NAME'
|
||||||
|
- 'BUILD_ID=$BUILD_ID'
|
||||||
|
- 'BUCKET=gs://overleaf-dev-storybook'
|
||||||
|
dir: services/web
|
||||||
|
script: |
|
||||||
|
#!/bin/bash
|
||||||
|
: ${BRANCH_NAME:=$BUILD_ID}
|
||||||
|
[[ "$BRANCH_NAME" ]] || {
|
||||||
|
echo 1>&2 "ERROR: BRANCH_NAME not set"
|
||||||
|
exit 2
|
||||||
|
}
|
||||||
|
gsutil -m copy -r storybook-output/* "${BUCKET}/"
|
||||||
|
waitFor:
|
||||||
|
- build-storybook
|
||||||
|
|
||||||
|
- id: read-storybook-bucket
|
||||||
|
name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
|
||||||
|
dir: services/web
|
||||||
|
env:
|
||||||
|
- 'BUCKET=gs://overleaf-dev-storybook'
|
||||||
|
script: |
|
||||||
|
#!/bin/bash
|
||||||
|
set -ex
|
||||||
|
gsutil ls "${BUCKET}/" \
|
||||||
|
| sed -E "s@^${BUCKET}/([^/]+)/@\1@" \
|
||||||
|
> storybook-bucket-listing.txt
|
||||||
|
waitFor:
|
||||||
|
- deploy-storybook
|
||||||
|
|
||||||
|
- id: create-storybook-index
|
||||||
|
name: 'node:18.18.2'
|
||||||
|
dir: services/web
|
||||||
|
env:
|
||||||
|
- 'BRANCH_NAME=$BRANCH_NAME'
|
||||||
|
script: |
|
||||||
|
#!/bin/bash
|
||||||
|
set -ex
|
||||||
|
LIST=$(tr '\n' , < storybook-bucket-listing.txt)
|
||||||
|
m4 -DLIST="$LIST" -DBRANCH_NAME="$BRANCH_NAME" cloudbuild-storybook-index.html.m4 > storybook-index.html
|
||||||
|
waitFor:
|
||||||
|
- read-storybook-bucket
|
||||||
|
|
||||||
|
- id: update-storybook-index
|
||||||
|
name: 'gcr.io/google.com/cloudsdktool/cloud-sdk'
|
||||||
|
dir: services/web
|
||||||
|
entrypoint: 'gsutil'
|
||||||
|
args: [ "copy", "storybook-index.html", "gs://overleaf-dev-storybook/index.html" ]
|
||||||
|
waitFor:
|
||||||
|
- create-storybook-index
|
|
@ -39,6 +39,8 @@
|
||||||
"lezer-latex:benchmark": "node scripts/lezer-latex/benchmark.mjs",
|
"lezer-latex:benchmark": "node scripts/lezer-latex/benchmark.mjs",
|
||||||
"lezer-latex:benchmark-incremental": "node scripts/lezer-latex/test-incremental-parser.mjs",
|
"lezer-latex:benchmark-incremental": "node scripts/lezer-latex/test-incremental-parser.mjs",
|
||||||
"routes": "bin/routes",
|
"routes": "bin/routes",
|
||||||
|
"storybook": "storybook dev -p 6006",
|
||||||
|
"build-storybook": "storybook build",
|
||||||
"local:nodemon": "set -a;. ../../config/dev-environment.env;. ./docker-compose.common.env;. ../../config/local-dev.env;. ./local-dev.env;. ../../config/local.env; set +a; echo $SHARELATEX_CONFIG; WEB_PORT=13000 LISTEN_ADDRESS=0.0.0.0 npm run nodemon",
|
"local:nodemon": "set -a;. ../../config/dev-environment.env;. ./docker-compose.common.env;. ../../config/local-dev.env;. ./local-dev.env;. ../../config/local.env; set +a; echo $SHARELATEX_CONFIG; WEB_PORT=13000 LISTEN_ADDRESS=0.0.0.0 npm run nodemon",
|
||||||
"local:webpack": "set -a;. ../../config/dev-environment.env;. ./docker-compose.common.env;. ../../config/local-dev.env;. ./local-dev.env;. ../../config/local.env; set +a; PORT=13808 SHARELATEX_CONFIG=$(pwd)/config/settings.webpack.js npm run webpack",
|
"local:webpack": "set -a;. ../../config/dev-environment.env;. ./docker-compose.common.env;. ../../config/local-dev.env;. ./local-dev.env;. ../../config/local.env; set +a; PORT=13808 SHARELATEX_CONFIG=$(pwd)/config/settings.webpack.js npm run webpack",
|
||||||
"local:test:acceptance:run_dir": "set -a;. $(pwd)/docker-compose.common.env;. $(pwd)/local-test.env; set +a; npm run test:acceptance:run_dir",
|
"local:test:acceptance:run_dir": "set -a;. $(pwd)/docker-compose.common.env;. $(pwd)/local-test.env; set +a; npm run test:acceptance:run_dir",
|
||||||
|
@ -211,6 +213,15 @@
|
||||||
"@replit/codemirror-indentation-markers": "overleaf/codemirror-indentation-markers#1b1f93c0bcd04293aea6986aa2275185b2c56803",
|
"@replit/codemirror-indentation-markers": "overleaf/codemirror-indentation-markers#1b1f93c0bcd04293aea6986aa2275185b2c56803",
|
||||||
"@replit/codemirror-vim": "overleaf/codemirror-vim#07f1b50f4b2e703792da75a29e9e1e479b6b7067",
|
"@replit/codemirror-vim": "overleaf/codemirror-vim#07f1b50f4b2e703792da75a29e9e1e479b6b7067",
|
||||||
"@sentry/browser": "^7.8.1",
|
"@sentry/browser": "^7.8.1",
|
||||||
|
"@storybook/addon-a11y": "^7.5.1",
|
||||||
|
"@storybook/addon-essentials": "^7.5.1",
|
||||||
|
"@storybook/addon-interactions": "^7.5.1",
|
||||||
|
"@storybook/addon-links": "^7.5.1",
|
||||||
|
"@storybook/addons": "^7.5.1",
|
||||||
|
"@storybook/blocks": "^7.5.1",
|
||||||
|
"@storybook/react": "^7.5.1",
|
||||||
|
"@storybook/react-webpack5": "^7.5.1",
|
||||||
|
"@storybook/testing-library": "^0.2.2",
|
||||||
"@testing-library/cypress": "^10.0.1",
|
"@testing-library/cypress": "^10.0.1",
|
||||||
"@testing-library/dom": "^9.3.0",
|
"@testing-library/dom": "^9.3.0",
|
||||||
"@testing-library/react": "^12.1.5",
|
"@testing-library/react": "^12.1.5",
|
||||||
|
@ -332,6 +343,7 @@
|
||||||
"sinon-chai": "^3.7.0",
|
"sinon-chai": "^3.7.0",
|
||||||
"sinon-mongoose": "^2.3.0",
|
"sinon-mongoose": "^2.3.0",
|
||||||
"socket.io-mock": "^1.3.1",
|
"socket.io-mock": "^1.3.1",
|
||||||
|
"storybook": "^7.4.0",
|
||||||
"strict-event-emitter": "^0.5.1",
|
"strict-event-emitter": "^0.5.1",
|
||||||
"terser-webpack-plugin": "^5.3.9",
|
"terser-webpack-plugin": "^5.3.9",
|
||||||
"thread-loader": "^4.0.2",
|
"thread-loader": "^4.0.2",
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
"modules/**/test/frontend/**/*.*",
|
"modules/**/test/frontend/**/*.*",
|
||||||
"frontend/stories/**/*.*",
|
"frontend/stories/**/*.*",
|
||||||
"modules/**/stories/**/*.*",
|
"modules/**/stories/**/*.*",
|
||||||
|
".storybook/*.*",
|
||||||
"cypress",
|
"cypress",
|
||||||
"types"
|
"types"
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue