Files
Fuchs_Intranet/.github/instructions/frontend.instructions.md
T

176 lines
6.7 KiB
Markdown

# Frontend Instructions
## General Rules
- **Never edit files inside `wwwroot/` directly.** All output files are generated by the Gulp build pipeline.
- All stylesheet sources must be written in **SCSS** (`.scss`), not plain CSS.
- After adding or changing source files, ensure they are listed in `Fuchs/bdlconfig.json` so they are picked up by the build.
## Source File Locations
| Type | Source path |
|------|-------------|
| SCSS (shared/global) | `Fuchs/css/intranet/` |
| SCSS (module-specific) | `Fuchs/js/intranet/modules/<module>/` (co-located with the module JS) |
| JavaScript (core) | `Fuchs/js/intranet/` |
| JavaScript (modules) | `Fuchs/js/intranet/modules/<module>/` |
## Output / Bundle Locations
All bundles are written to `Fuchs/web/` by the Gulp pipeline. Do not reference these paths as source.
| Bundle | Context | Description |
|--------|---------|-------------|
| `web/fisb.min.css` | `intranet` | Bootstrap/login CSS |
| `web/fis.min.css` | `intranet` | Main intranet CSS |
| `web/fis.inv.min.css` | `intranet:inv` | Invoices module CSS |
| `web/fis.req.min.css` | `intranet:req` | Requests module CSS |
| `web/fis.rep.min.css` | `intranet:rep` | Reports module CSS |
| `web/fis.bam.min.css` | `intranet:bam` | BAM module CSS |
| `web/fisb.min.js` | `intranet` | Bootstrap/basic JS |
| `web/fis.min.js` | `intranet` | Main intranet JS |
| `web/fis.inv.de.js` | `intranet:inv` | Invoices module JS |
| `web/fis.req.de.js` | `intranet:req` | Requests module JS |
| `web/fis.rep.de.js` | `intranet:rep` | Reports module JS |
| `web/fis.bam.de.js` | `intranet:bam` | BAM module JS |
## bdlconfig.json Entry Format
`Fuchs/bdlconfig.json` drives all bundle definitions. Each entry has this shape:
```json
{
"context": "intranet",
"outputFileName": "web/<bundle-name>.min.css",
"inputFiles": [
"css/intranet/oci_variables.scss",
"css/intranet/fis_variables.scss",
"css/intranet/<your-file>.scss"
],
"minify": { "enabled": true }
}
```
### SCSS Variable Prepend Rule
Every CSS bundle **must** include the two variable files as the first `inputFiles` entries, in this order:
```
css/intranet/oci_variables.scss
css/intranet/fis_variables.scss
```
These define the shared design tokens used across all SCSS files. Omitting them will cause compilation errors.
### Module Co-location Pattern
Module-specific SCSS files live alongside their JavaScript counterparts under `js/intranet/modules/<module>/`. When adding a new module:
1. Create `js/intranet/modules/<module>/<module>.scss` for module styles.
2. Add that path to the appropriate context bundle in `bdlconfig.json` (after the variable files).
3. Create `js/intranet/modules/<module>/<module>.js` for module logic.
4. Add that path to the corresponding JS bundle in `bdlconfig.json`.
## Build Pipeline
The Gulp 4 pipeline (`Fuchs/gulpfile.js`) reads `bdlconfig.json` and `copyconfig.json`.
### Available Tasks
| Command | Description |
|---------|-------------|
| `gulp min:scss` | Compile and minify all SCSS bundles |
| `gulp min:js` | Concatenate and minify all JS bundles |
| `gulp min:html` | Minify HTML bundles |
| `gulp min` | Run `min:js`, `min:scss`, and `min:html` in parallel |
| `gulp copy` | Run file copy tasks from `copyconfig.json` |
| `gulp all` | Run `min` and `copy` in parallel (full build) |
| `gulp clean` | Delete all bundle output files |
| `gulp watch` | Watch source files and rebuild on change |
Run from the `Fuchs/` directory:
```powershell
cd Fuchs
npx gulp all
```
### How SCSS Compilation Works
- All `.scss` files listed in a bundle's `inputFiles` are concatenated into a single stream, then compiled with `node-sass` via `gulp-sass`.
- The output is then minified with `gulp-cssmin` and written to `web/<bundle>.min.css`.
- `.less` files in the same bundle are compiled separately and merged with the SCSS output before minification.
### How JS Bundling Works
- All JS files listed in `inputFiles` are concatenated with `gulp-concat`.
- Files listed in `inputFiles_tominify` are individually minified with `gulp-terser` before concatenation.
- When `minify.enabled` is `true` (default), the full bundle is also minified via `gulp-terser`.
## npm Dependencies
Runtime packages available via npm (do not copy these into source manually):
| Package | Usage |
|---------|-------|
| `jquery` | DOM/AJAX |
| `js-cookie` | Cookie access |
| `fg-loadcss` | Async CSS loading (`loadCSS.js`, `onloadCSS_array.js`) |
| `tinymce` | Rich text editor |
These are copied to `web/` or `wwwroot/lib/` via `copyconfig.json` entries and the `gulp copy` task.
| Package | Destination (gulp copy) | Served at |
|---------|------------------------|-----------|
| `jquery` + `js-cookie` | concatenated into `Fuchs/web/tools.js` | `~/web/tools.js` |
| `tinymce` | `wwwroot/lib/tinymce/` | `~/lib/tinymce/tinymce.min.js` |
## Layout Asset Wiring (`Views/Shared/_Layout.cshtml`)
Asset loading follows a strict order and is split by authentication state.
### Always loaded (before auth check)
```razor
<script src="~/web/tools.js" asp-append-version="true"></script>
```
`tools.js` contains jQuery and js-cookie. It must be first so all subsequent scripts can use `$` and `Cookies`.
### Auth-conditional bundles
```razor
@if (isAuth)
{
<script src="~/lib/tinymce/tinymce.min.js"></script>
<link rel="stylesheet" href="~/web/fis.min.css" asp-append-version="true" />
<script src="~/web/fis.min.js" asp-append-version="true"></script>
}
else
{
<link rel="stylesheet" href="~/web/fisb.min.css" asp-append-version="true" />
<script src="~/web/fisb.min.js" asp-append-version="true"></script>
}
```
- **Authenticated** (`fis.*`): full intranet styles + scripts + TinyMCE rich-text editor.
- **Unauthenticated** (`fisb.*`): login-page-only styles + scripts. TinyMCE is **not** loaded.
- TinyMCE is always loaded from `~/lib/tinymce/tinymce.min.js` (copied by `gulp copy` from `node_modules/tinymce`). Never use `~/Scripts/tinymce/` — that path does not exist.
### `$ocms.auth` injection (always)
A `<script>` block is always rendered (authenticated or not) that writes the `$ocms.auth` object with the current user's id, email, and authorization level. This lets client-side code read auth state without additional requests.
### Per-page module bundles (`@section CustomHeader`)
Module bundles (`fis.inv`, `fis.req`, `fis.rep`, `fis.bam`) are **not** loaded globally. Each view that needs them renders a `@section CustomHeader` block:
```razor
@section CustomHeader {
<link rel="stylesheet" href="~/web/fis.inv.min.css" asp-append-version="true" />
<script src="~/web/fis.inv.de.js" asp-append-version="true"></script>
}
```
`_Layout.cshtml` renders `@RenderSection("CustomHeader", required: false)` inside `<head>`, so only the relevant module assets are fetched for each page.