diff --git a/.gitignore b/.gitignore index dab9540..4fa2755 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,11 @@ nul # Local backup downloads — these should never be in git backups/ + +# Django collected static files — build artifact, not source. +# `python manage.py collectstatic` regenerates this from `static/` and +# installed-app static dirs on every deploy. Tracking the output caused +# recurring "Ver XX.YY" auto-commits from Flatlogic's web UI whenever the +# VM regenerated it post-deploy. The VM's filesystem still holds this +# directory — it's just no longer in git. See CLAUDE.md → Static Assets. +staticfiles/ diff --git a/CLAUDE.md b/CLAUDE.md index 5a503ce..76cc19e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -43,7 +43,7 @@ core/ — Single main app: ALL business logic, models, views, forms, admin/ — base_site.html override (adds admin CSS tweaks, e.g. taller M2M pickers) ai/ — Flatlogic AI proxy client (not used in app logic) static/css/ — custom.css (CSS variables, component styles, tooltip overrides) -staticfiles/ — Collected static assets (Bootstrap, admin) +staticfiles/ — Collected static assets (Bootstrap, admin) — NOT in git (build artifact, regenerated by collectstatic) ``` ## Key Models @@ -240,6 +240,35 @@ disk but the VM's `staticfiles/` hasn't been refreshed, Apache serves the old collected copy. Have Gemini run `python3 manage.py collectstatic --noinput` after any PR that touches `static/`. +### `staticfiles/` is NOT tracked in git (since Apr 2026) +`staticfiles/` is gitignored because it's a **build artifact** — `collectstatic` +regenerates it from `static/` and each installed-app's static dirs on every +deploy. Previously it was tracked, which caused two problems: + +1. **Flatlogic-auto-noise commits.** Every time Gemini ran `collectstatic`, + Flatlogic's web UI detected the modified files in `staticfiles/` and + auto-committed them with a generic `Ver XX.YY` message (e.g. the notorious + "Ver 30.04 Fix reports and add Supervisor" commit that diverged our branch + from GitHub in Apr 2026). These commits reached gitea but not GitHub, + creating recurring reconciliation pain. +2. **Misleading diffs in PRs.** Every CSS change showed up twice in git + (once in `static/`, once in `staticfiles/`), doubling review surface. + +**Deploy consequence**: after pulling a commit that modifies `static/` files, +Gemini MUST run `collectstatic` BEFORE restarting the service. If the pull +removed the `staticfiles/` directory from the working tree (which happens +the first time after the gitignore change), collectstatic recreates everything +from source. Brief window (~seconds) of possible 404s on static assets during +the deploy; acceptable at this scale. + +**First-time migration note**: the commit that added `staticfiles/` to +`.gitignore` also removed all previously-tracked files via +`git rm -r --cached staticfiles/`. The VM's filesystem still holds the +directory — git just stops tracking it. On next deploy the pull will +delete the working-tree copies (because they no longer exist in the +commit tree), so `collectstatic --noinput` MUST run immediately after +pull to repopulate. After that, all is stable. + ## PDF Generation (WeasyPrint) Migrated from xhtml2pdf in Nov 2026. WeasyPrint is a browser-grade HTML→PDF renderer — it supports real CSS (flexbox, grid, `@font-face`, shadows, `border-radius`, proper cascade) that xhtml2pdf could not handle. diff --git a/staticfiles/@popperjs/core/LICENSE.md b/staticfiles/@popperjs/core/LICENSE.md deleted file mode 100644 index 0370c45..0000000 --- a/staticfiles/@popperjs/core/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2019 Federico Zivolo - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/staticfiles/@popperjs/core/README.md b/staticfiles/@popperjs/core/README.md deleted file mode 100644 index 53be7b9..0000000 --- a/staticfiles/@popperjs/core/README.md +++ /dev/null @@ -1,376 +0,0 @@ - -

- Popper -

- -
-

Tooltip & Popover Positioning Engine

-
- -

- - npm version - - - npm downloads per month (popper.js + @popperjs/core) - - - Rolling Versions - -

- -
- - -**Positioning tooltips and popovers is difficult. Popper is here to help!** - -Given an element, such as a button, and a tooltip element describing it, Popper -will automatically put the tooltip in the right place near the button. - -It will position _any_ UI element that "pops out" from the flow of your document -and floats near a target element. The most common example is a tooltip, but it -also includes popovers, drop-downs, and more. All of these can be generically -described as a "popper" element. - -## Demo - -[![Popper visualized](https://i.imgur.com/F7qWsmV.jpg)](https://popper.js.org) - -## Docs - -- [v2.x (latest)](https://popper.js.org/docs/v2/) -- [v1.x](https://popper.js.org/docs/v1/) - -We've created a -[Migration Guide](https://popper.js.org/docs/v2/migration-guide/) to help you -migrate from Popper 1 to Popper 2. - -To contribute to the Popper website and documentation, please visit the -[dedicated repository](https://github.com/popperjs/website). - -## Why not use pure CSS? - -- **Clipping and overflow issues**: Pure CSS poppers will not be prevented from - overflowing clipping boundaries, such as the viewport. It will get partially - cut off or overflows if it's near the edge since there is no dynamic - positioning logic. When using Popper, your popper will always be positioned in - the right place without needing manual adjustments. -- **No flipping**: CSS poppers will not flip to a different placement to fit - better in view if necessary. While you can manually adjust for the main axis - overflow, this feature cannot be achieved via CSS alone. Popper automatically - flips the tooltip to make it fit in view as best as possible for the user. -- **No virtual positioning**: CSS poppers cannot follow the mouse cursor or be - used as a context menu. Popper allows you to position your tooltip relative to - any coordinates you desire. -- **Slower development cycle**: When pure CSS is used to position popper - elements, the lack of dynamic positioning means they must be carefully placed - to consider overflow on all screen sizes. In reusable component libraries, - this means a developer can't just add the component anywhere on the page, - because these issues need to be considered and adjusted for every time. With - Popper, you can place your elements anywhere and they will be positioned - correctly, without needing to consider different screen sizes, layouts, etc. - This massively speeds up development time because this work is automatically - offloaded to Popper. -- **Lack of extensibility**: CSS poppers cannot be easily extended to fit any - arbitrary use case you may need to adjust for. Popper is built with - extensibility in mind. - -## Why Popper? - -With the CSS drawbacks out of the way, we now move on to Popper in the -JavaScript space itself. - -Naive JavaScript tooltip implementations usually have the following problems: - -- **Scrolling containers**: They don't ensure the tooltip stays with the - reference element while scrolling when inside any number of scrolling - containers. -- **DOM context**: They often require the tooltip move outside of its original - DOM context because they don't handle `offsetParent` contexts. -- **Compatibility**: Popper handles an incredible number of edge cases regarding - different browsers and environments (mobile viewports, RTL, scrollbars enabled - or disabled, etc.). Popper is a popular and well-maintained library, so you - can be confident positioning will work for your users on any device. -- **Configurability**: They often lack advanced configurability to suit any - possible use case. -- **Size**: They are usually relatively large in size, or require an ancient - jQuery dependency. -- **Performance**: They often have runtime performance issues and update the - tooltip position too slowly. - -**Popper solves all of these key problems in an elegant, performant manner.** It -is a lightweight ~3 kB library that aims to provide a reliable and extensible -positioning engine you can use to ensure all your popper elements are positioned -in the right place. - -When you start writing your own popper implementation, you'll quickly run into -all of the problems mentioned above. These widgets are incredibly common in our -UIs; we've done the hard work figuring this out so you don't need to spend hours -fixing and handling numerous edge cases that we already ran into while building -the library! - -Popper is used in popular libraries like Bootstrap, Foundation, Material UI, and -more. It's likely you've already used popper elements on the web positioned by -Popper at some point in the past few years. - -Since we write UIs using powerful abstraction libraries such as React or Angular -nowadays, you'll also be glad to know Popper can fully integrate with them and -be a good citizen together with your other components. Check out `react-popper` -for the official Popper wrapper for React. - -## Installation - -### 1. Package Manager - -```bash -# With npm -npm i @popperjs/core - -# With Yarn -yarn add @popperjs/core -``` - -### 2. CDN - -```html - - - - - -``` - -### 3. Direct Download? - -Managing dependencies by "directly downloading" them and placing them into your -source code is not recommended for a variety of reasons, including missing out -on feat/fix updates easily. Please use a versioning management system like a CDN -or npm/Yarn. - -## Usage - -The most straightforward way to get started is to import Popper from the `unpkg` -CDN, which includes all of its features. You can call the `Popper.createPopper` -constructor to create new popper instances. - -Here is a complete example: - -```html - -Popper example - - - - - - - - -``` - -Visit the [tutorial](https://popper.js.org/docs/v2/tutorial/) for an example of -how to build your own tooltip from scratch using Popper. - -### Module bundlers - -You can import the `createPopper` constructor from the fully-featured file: - -```js -import { createPopper } from '@popperjs/core'; - -const button = document.querySelector('#button'); -const tooltip = document.querySelector('#tooltip'); - -// Pass the button, the tooltip, and some options, and Popper will do the -// magic positioning for you: -createPopper(button, tooltip, { - placement: 'right', -}); -``` - -All the modifiers listed in the docs menu will be enabled and "just work", so -you don't need to think about setting Popper up. The size of Popper including -all of its features is about 5 kB minzipped, but it may grow a bit in the -future. - -#### Popper Lite (tree-shaking) - -If bundle size is important, you'll want to take advantage of tree-shaking. The -library is built in a modular way to allow to import only the parts you really -need. - -```js -import { createPopperLite as createPopper } from '@popperjs/core'; -``` - -The Lite version includes the most necessary modifiers that will compute the -offsets of the popper, compute and add the positioning styles, and add event -listeners. This is close in bundle size to pure CSS tooltip libraries, and -behaves somewhat similarly. - -However, this does not include the features that makes Popper truly useful. - -The two most useful modifiers not included in Lite are `preventOverflow` and -`flip`: - -```js -import { - createPopperLite as createPopper, - preventOverflow, - flip, -} from '@popperjs/core'; - -const button = document.querySelector('#button'); -const tooltip = document.querySelector('#tooltip'); - -createPopper(button, tooltip, { - modifiers: [preventOverflow, flip], -}); -``` - -As you make more poppers, you may be finding yourself needing other modifiers -provided by the library. - -See [tree-shaking](https://popper.js.org/docs/v2/performance/#tree-shaking) for more -information. - -## Distribution targets - -Popper is distributed in 3 different versions, in 3 different file formats. - -The 3 file formats are: - -- `esm` (works with `import` syntax — **recommended**) -- `umd` (works with `