Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ jobs:
- name: Setup environment
uses: ./.github/actions/setup-env
with:
node: 'false'
node: "false"

- name: Download backend build result
uses: ./.github/actions/download-backend-build
Expand Down Expand Up @@ -100,7 +100,7 @@ jobs:
if: ${{ always() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}
uses: actions/setup-node@v4
with:
node-version: '20'
node-version: "20"

- name: Convert JUnit to CTRF
if: ${{ always() && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }}
Expand Down Expand Up @@ -227,17 +227,25 @@ jobs:
- name: Setup environment
uses: ./.github/actions/setup-env
with:
java: 'false'
java: "false"

- name: Install dependencies
- name: Install library dependencies
run: npm ci
working-directory: ./library

- name: Lint library
run: npm run lint
working-directory: ./library

- name: Install webapp dependencies
run: npm ci
working-directory: ./webapp

- name: Typescript
- name: Typescript on webapp
run: npm run tsc
working-directory: ./webapp

- name: Eslint
- name: Eslint on webapp
run: npm run eslint
working-directory: ./webapp

Expand All @@ -262,6 +270,7 @@ jobs:
- name: Check it builds without ee directory
run: |
rm -rf ./src/ee
npm --prefix ../library install
npm install
npm run tsc
npm run build
Expand All @@ -276,7 +285,7 @@ jobs:
- name: Setup environment
uses: ./.github/actions/setup-env
with:
java: 'false'
java: "false"

- name: Install dependencies
run: npm ci
Expand All @@ -299,7 +308,7 @@ jobs:
- name: Setup environment
uses: ./.github/actions/setup-env
with:
java: 'false'
java: "false"

- name: Install dependencies
run: npm ci
Expand Down Expand Up @@ -330,7 +339,7 @@ jobs:
- name: Setup environment
uses: ./.github/actions/setup-env
with:
node: 'false'
node: "false"

- name: Run ktlint
run: ./gradlew ktlintCheck
Expand Down
4 changes: 2 additions & 2 deletions .gitpod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ tasks:
# Frontend cache
rm -f /workspace/.f
pushd webapp
npm --prefix ../library ci
npm ci
popd
touch /workspace/.f
Expand All @@ -21,7 +22,6 @@ tasks:
./gradlew server-app:unpack
touch /workspace/.b


- name: Backend
openMode: split-left
command: |
Expand Down Expand Up @@ -54,7 +54,7 @@ ports:
port: 8080
visibility: public
onOpen: ignore

- name: Frontend
port: 3000
visibility: public
Expand Down
2 changes: 1 addition & 1 deletion .husky/post-checkout
Original file line number Diff line number Diff line change
@@ -1 +1 @@
node webapp/scripts/updateBranchInfo.mjs
node webapp/scripts/updateBranchInfo.js
2 changes: 1 addition & 1 deletion .husky/post-commit
Original file line number Diff line number Diff line change
@@ -1 +1 @@
node webapp/scripts/updateBranchInfo.mjs
node webapp/scripts/updateBranchInfo.js
1 change: 1 addition & 0 deletions DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ git config blame.ignoreRevsFile .git-blame-ignore-revs
* With the prepared Idea run configuration `Frontend localhost`
* With command line:
```shell
npm --prefix library ci
cd webapp && npm ci && npm run start
```
3. Open your browser and go to http://localhost:3000.
Expand Down
8 changes: 8 additions & 0 deletions e2e/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 16 additions & 6 deletions gradle/webapp.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
apply from: './gradle/utils.gradle'

def libraryPath = "${project.projectDir}/library"
def webappPath = "${project.projectDir}/webapp"

task copyDist(type: Copy) {
Expand All @@ -13,22 +14,31 @@ task copyDist(type: Copy) {
dependsOn "buildWebapp"
}

task installLibraryDeps(type: Exec) {
onlyIf { System.getenv("SKIP_WEBAPP_BUILD") != "true" }
commandLine npmCommandName, "ci"
workingDir = libraryPath
inputs.file("${libraryPath}/package.json")
inputs.file("${libraryPath}/package-lock.json")
outputs.dir("${libraryPath}/node_modules")
}

task installWebappDeps(type: Exec) {
onlyIf { System.getenv("SKIP_WEBAPP_BUILD") != "true" }
commandLine npmCommandName, "ci"
workingDir = webappPath
inputs.file("${project.projectDir}/webapp/package.json")
inputs.file("${project.projectDir}/webapp/package-lock.json")
outputs.dir("${project.projectDir}/webapp/node_modules")
inputs.file("${webappPath}/package.json")
inputs.file("${webappPath}/package-lock.json")
outputs.dir("${webappPath}/node_modules")
}

task buildWebapp(type: Exec) {
onlyIf { System.getenv("SKIP_WEBAPP_BUILD") != "true" }
commandLine npmCommandName, "run", "build"
workingDir = webappPath
inputs.dir("${project.projectDir}/webapp/")
outputs.dir("${project.projectDir}/webapp/dist/")
dependsOn "installWebappDeps", "updateStaticTranslations"
inputs.dir(webappPath)
outputs.dir("${webappPath}/dist/")
dependsOn "installLibraryDeps", "installWebappDeps", "updateStaticTranslations"
}

task createBuildDir() {
Expand Down
3 changes: 3 additions & 0 deletions library/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# copy file to .env.local and fill in the API key to enable Tolgee in Storybook
VITE_APP_TOLGEE_API_URL=https://app.tolgee.io
VITE_APP_TOLGEE_API_KEY=
6 changes: 6 additions & 0 deletions library/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
dist/
node_modules/
*.local

*storybook.log
storybook-static/
1 change: 1 addition & 0 deletions library/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/dist/
19 changes: 19 additions & 0 deletions library/.storybook/main.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { StorybookConfig } from '@storybook/react-vite';

export default {
stories: ['../src/**/stories.@(js|jsx|ts|tsx)', '../src/**/*.@(md|mdx)'],
addons: [
'@storybook/addon-docs',
'@storybook/addon-a11y',
'@storybook/addon-themes',
'@tolgee/storybook-addon',
],
framework: {
name: '@storybook/react-vite',
options: {},
},
typescript: {
check: true,
reactDocgen: 'react-docgen-typescript',
},
} satisfies StorybookConfig;
54 changes: 54 additions & 0 deletions library/.storybook/preview.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { CssBaseline, ThemeProvider } from '@mui/material';
import type { Preview } from '@storybook/react-vite';
import { withThemeFromJSXProvider } from '@storybook/addon-themes';
import { configure } from 'storybook/test';
import { withTolgeeProvider } from '@tolgee/storybook-addon';
import { MuiLocalizationProvider } from 'lib.components/MuiLocalizationProvider';
import { locales } from 'lib.constants/locales';

import { getTheme } from '../../webapp/src/ThemeProvider'; // TODO migrate https://github.com/tolgee/tolgee-platform/issues/3326
import { branchName } from '../../webapp/src/branch.json';

const LANGUAGE = 'en';
const FEATURE_TAG = `draft: ${branchName.split('/').pop()}`;

configure({ testIdAttribute: 'data-cy' }); // instead of data-testid in findByTestId, getAllByTestId...

const preview: Preview = {
parameters: {
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/i,
},
},
},
decorators: [
withTolgeeProvider({
messageFormat: 'icu',
locales,
LocalizationProvider: MuiLocalizationProvider,
tolgee: {
language: LANGUAGE,
fallbackLanguage: LANGUAGE,
apiUrl: import.meta.env.VITE_APP_TOLGEE_API_URL,
apiKey: import.meta.env.VITE_APP_TOLGEE_API_KEY,
staticData: Object.fromEntries(
Object.entries(locales).map(([k, v]) => [k, v.translations]),
),
tagNewKeys: [FEATURE_TAG],
},
}),
withThemeFromJSXProvider({
GlobalStyles: CssBaseline,
Provider: ThemeProvider,
themes: {
Light: getTheme('light'),
Dark: getTheme('dark'),
},
defaultTheme: 'Light',
}),
],
} satisfies Preview;

export default preview;
71 changes: 71 additions & 0 deletions library/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# Component/Hook/... Library
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd probably give it a better title

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any suggestion please? 🐱

If there were no Hooks and such things, I would call it Component Library.

Design System also is not the thing.

Tolgee Library maybe?


This project is a library of components/hooks/... which are reused across other
Tolgee applications. This is not an application by itself, but there is a
Storybook instance integrated to display and let you try the components
individually or in preset combinations.

## Storybook

[Storybook](https://storybook.js.org/) is a catalog of components. This
particular instance hosts those of the Tolgee library.

### Setup Storybook

One time Storybook setup.

Install dependencies of Storybook and the library itself:

```shell
cd library
npm ci
```

Duplicate [.env](./.env) as [.env.local](./.env.local) and configure your
Tolgee API KEY.

Addon for Tolgee is preset, but its dependencies have to be also installed and
the addon built to work properly:

```shell
cd storybook-tolgee-addon
npm ci
npm run build
```

### Open Storybook

Every time you want to open Storybook run:

```shell
cd library
npm run storybook
```

Storybook should open in your browser, otherwise open <http://localhost:6006/>.

## Component Migration

- Apply the boy scout rule – improve names, aliases, subpaths, dependencies...
- Move the component/hook/... from `webapp/src/component/` directory under `library/src/components/` (note the plural – we are unifying it to plurals everywhere). If the component/hook/... is placed under a subpath, persist it.
- Keep one component per file. Constants reused elsewhere can be placed under `constants.ts`. Helper functions under `utils.ts`.
- Up until now, each component was a single file (e.g. `MfaBadge.tsx`), this is changing (not for hooks/...). Please create a directory named like the component (i.e. `MfaBadge`), move the component inside and name it `index.tsx`. This way the component can still be referenced the same path (omit `index.tsx` in the path).
- Remove the original component/hook/...
- Update dependencies. Within `webapp` use `@tginternal/library/` prefix (e.g. `@tginternal/library/hooks/useCurrentLanguage`). Within `library` use `lib.` prefix (e.g. `lib.hooks/useCurrentLanguage`). Referencing `webapp` from `library` might not be safe. At the moment, only a few prefixes are predefined in `library`'s [tsconfig.json](./tsconfig.json), [package.json](./package.json) and [vite.config.ts](./vite.config.ts), add more as you need them.
- Remember the boy scout rule.

## Component Documentation

- Read [writing stories](https://storybook.js.org/docs/writing-stories) Storybook docs.
- CSF docs:
- In the component directory, create `stories.ts` file.
- The component (object of `Meta` type) and its stories (objects of `Story` type) are declared and exported here.
- Many properties can be set here, but Storybook can derive a lot by itself, so check the defaults at first. Storybook inspects the component's code for prop names, comments... so rather spend time on the component than on the stories (TSDoc comments will bring the value also elsewhere).
- Many properties can be set on the component level for all stories or on the individual story level.
- For inspiration have a look on [MfaBadge/stories.ts](./src/components/MfaBadge/stories.ts).
- For details have a look on [CSF docs](https://storybook.js.org/docs/api/csf).
- MDX docs:
- If the autogenerated CSF documentation is not enough (e.g. additional formatted texts are needed), create `stories.mdx` file next to `stories.ts`.
- You have a free hand in writing arbitrary Markdown texts here and inserting stories from `stories.ts` to them. Please follow CSF structure and other MDX files.
- For inspiration have a look on [FlagImage/stories.mdx](./src/components/languages/FlagImage/stories.mdx).
- For details have a look on [MDX docs](https://storybook.js.org/docs/writing-docs/mdx).
Loading