Initial kitchen scaffold — Phase 1 kitchen port (build-verified 2026-07-11)
FastAPI backend (Python 3.11, MSSQL ODBC for SambaPOS, Azure DI OCR),
kitchen_db on central PG. React/TS/Vite frontend with navy sidebar layout.
Backend: auth.py (APP_SLUG=kitchen, SimpleNamespace — archive routes use
.kitchen_id/.is_admin without modification), main.py (51 migrations, scheduler,
internal router for KDS bookings feed), api/internal.py, full archive API
(31 routers: invoices, recipes, menus, sambapos, resos, newbook, disputes,
purchase_orders, etc.), models, migrations, OCR pipeline.
kitchen_id pinned to 1 (B1 — single hotel).
Frontend: AuthGate (app=kitchen, token shim for archive compat — B5b pending),
Layout (navy sidebar, 6 sections, Lucide icons, teal --app-primary),
App.tsx (Outlet pattern, UploadApp outside Layout), index.css (full :root block).
strict: false — archive components have type issues; build clean.
Note: 45 archive components call fetch('/api/...') without /kitchen/ prefix
(B5b). Runtime 404s; deferred until after initial testing.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
commit
8d688b459d
10003 changed files with 1928395 additions and 0 deletions
229
frontend/node_modules/browser-image-compression/README.md
generated
vendored
Normal file
229
frontend/node_modules/browser-image-compression/README.md
generated
vendored
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
# Browser Image Compression
|
||||
[](https://www.npmjs.com/package/browser-image-compression)
|
||||
[](https://github.com/Donaldcwl/browser-image-compression)
|
||||
[](https://github.com/Donaldcwl/browser-image-compression)
|
||||
|
||||
Javascript module to be run in the web browser for image compression.
|
||||
|
||||
## Features
|
||||
- You can use this module to compress jpeg, png, webp, and bmp images by reducing **resolution** or **storage size** before uploading to the application server to save bandwidth.
|
||||
- **Multi-thread** (web worker) non-blocking compression is supported through options.
|
||||
|
||||
|
||||
## Demo / Example
|
||||
open https://donaldcwl.github.io/browser-image-compression/example/basic.html
|
||||
|
||||
or check the "[example]" folder in this repo
|
||||
|
||||
|
||||
## Usage
|
||||
```html
|
||||
<input type="file" accept="image/*" onchange="handleImageUpload(event);">
|
||||
```
|
||||
### async await syntax:
|
||||
```javascript
|
||||
async function handleImageUpload(event) {
|
||||
|
||||
const imageFile = event.target.files[0];
|
||||
console.log('originalFile instanceof Blob', imageFile instanceof Blob); // true
|
||||
console.log(`originalFile size ${imageFile.size / 1024 / 1024} MB`);
|
||||
|
||||
const options = {
|
||||
maxSizeMB: 1,
|
||||
maxWidthOrHeight: 1920,
|
||||
useWebWorker: true,
|
||||
}
|
||||
try {
|
||||
const compressedFile = await imageCompression(imageFile, options);
|
||||
console.log('compressedFile instanceof Blob', compressedFile instanceof Blob); // true
|
||||
console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // smaller than maxSizeMB
|
||||
|
||||
await uploadToServer(compressedFile); // write your own logic
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
### Promise.then().catch() syntax:
|
||||
<details>
|
||||
<summary>Click to expand</summary>
|
||||
|
||||
```javascript
|
||||
function handleImageUpload(event) {
|
||||
|
||||
var imageFile = event.target.files[0];
|
||||
console.log('originalFile instanceof Blob', imageFile instanceof Blob); // true
|
||||
console.log(`originalFile size ${imageFile.size / 1024 / 1024} MB`);
|
||||
|
||||
var options = {
|
||||
maxSizeMB: 1,
|
||||
maxWidthOrHeight: 1920,
|
||||
useWebWorker: true
|
||||
}
|
||||
imageCompression(imageFile, options)
|
||||
.then(function (compressedFile) {
|
||||
console.log('compressedFile instanceof Blob', compressedFile instanceof Blob); // true
|
||||
console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // smaller than maxSizeMB
|
||||
|
||||
return uploadToServer(compressedFile); // write your own logic
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error.message);
|
||||
});
|
||||
}
|
||||
```
|
||||
</details>
|
||||
|
||||
## Installing
|
||||
### Use as ES module:
|
||||
You can install it via npm or yarn
|
||||
```bash
|
||||
npm install browser-image-compression --save
|
||||
# or
|
||||
yarn add browser-image-compression
|
||||
```
|
||||
```javascript
|
||||
import imageCompression from 'browser-image-compression';
|
||||
```
|
||||
(can be used in frameworks like React, Angular, Vue etc)
|
||||
|
||||
(work with bundlers like webpack and rollup)
|
||||
|
||||
### (or) Load UMD js file:
|
||||
You can download imageCompression from the [dist folder][dist].
|
||||
|
||||
Alternatively, you can use a CDN like [delivrjs]:
|
||||
```html
|
||||
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/browser-image-compression@2.0.1/dist/browser-image-compression.js"></script>
|
||||
```
|
||||
|
||||
|
||||
## Support
|
||||
If this project helps you reduce the time to develop, you can buy me a cup of coffee :)
|
||||
|
||||
<a href="https://donaldcwl.github.io/donation/" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-red.png" alt="Buy Me A Coffee" height=60 width=217 ></a>
|
||||
|
||||
(powered by Stripe)
|
||||
|
||||
## API
|
||||
### Main function
|
||||
```javascript
|
||||
// you should provide one of maxSizeMB, maxWidthOrHeight in the options
|
||||
const options: Options = {
|
||||
maxSizeMB: number, // (default: Number.POSITIVE_INFINITY)
|
||||
maxWidthOrHeight: number, // compressedFile will scale down by ratio to a point that width or height is smaller than maxWidthOrHeight (default: undefined)
|
||||
// but, automatically reduce the size to smaller than the maximum Canvas size supported by each browser.
|
||||
// Please check the Caveat part for details.
|
||||
onProgress: Function, // optional, a function takes one progress argument (percentage from 0 to 100)
|
||||
useWebWorker: boolean, // optional, use multi-thread web worker, fallback to run in main-thread (default: true)
|
||||
libURL: string, // optional, the libURL of this library for importing script in Web Worker (default: https://cdn.jsdelivr.net/npm/browser-image-compression/dist/browser-image-compression.js)
|
||||
preserveExif: boolean, // optional, use preserve Exif metadata for JPEG image e.g., Camera model, Focal length, etc (default: false)
|
||||
|
||||
signal: AbortSignal, // optional, to abort / cancel the compression
|
||||
|
||||
// following options are for advanced users
|
||||
maxIteration: number, // optional, max number of iteration to compress the image (default: 10)
|
||||
exifOrientation: number, // optional, see https://stackoverflow.com/a/32490603/10395024
|
||||
fileType: string, // optional, fileType override e.g., 'image/jpeg', 'image/png' (default: file.type)
|
||||
initialQuality: number, // optional, initial quality value between 0 and 1 (default: 1)
|
||||
alwaysKeepResolution: boolean // optional, only reduce quality, always keep width and height (default: false)
|
||||
}
|
||||
|
||||
imageCompression(file: File, options: Options): Promise<File>
|
||||
```
|
||||
|
||||
#### Caveat
|
||||
Each browser limits [the maximum size](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas#maximum_canvas_size) of a browser Canvas object. <br/>
|
||||
So, we resize the image to less than the maximum size that each browser restricts. <br/>
|
||||
(However, the `proportion/ratio` of the image remains.)
|
||||
|
||||
#### Abort / Cancel Compression
|
||||
To use this feature, please check the browser compatibility: https://caniuse.com/?search=AbortController
|
||||
```javascript
|
||||
function handleImageUpload(event) {
|
||||
|
||||
var imageFile = event.target.files[0];
|
||||
|
||||
var controller = new AbortController();
|
||||
|
||||
var options = {
|
||||
// other options here
|
||||
signal: controller.signal,
|
||||
}
|
||||
imageCompression(imageFile, options)
|
||||
.then(function (compressedFile) {
|
||||
return uploadToServer(compressedFile); // write your own logic
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.log(error.message); // output: I just want to stop
|
||||
});
|
||||
|
||||
// simulate abort the compression after 1.5 seconds
|
||||
setTimeout(function () {
|
||||
controller.abort(new Error('I just want to stop'));
|
||||
}, 1500);
|
||||
}
|
||||
```
|
||||
|
||||
### Helper function
|
||||
- for advanced users only, most users won't need to use the helper functions
|
||||
```javascript
|
||||
imageCompression.getDataUrlFromFile(file: File): Promise<base64 encoded string>
|
||||
imageCompression.getFilefromDataUrl(dataUrl: string, filename: string, lastModified?: number): Promise<File>
|
||||
imageCompression.loadImage(url: string): Promise<HTMLImageElement>
|
||||
imageCompression.drawImageInCanvas(img: HTMLImageElement, fileType?: string): HTMLCanvasElement | OffscreenCanvas
|
||||
imageCompression.drawFileInCanvas(file: File, options?: Options): Promise<[ImageBitmap | HTMLImageElement, HTMLCanvasElement | OffscreenCanvas]>
|
||||
imageCompression.canvasToFile(canvas: HTMLCanvasElement | OffscreenCanvas, fileType: string, fileName: string, fileLastModified: number, quality?: number): Promise<File>
|
||||
imageCompression.getExifOrientation(file: File): Promise<number> // based on https://stackoverflow.com/a/32490603/10395024
|
||||
imageCompression.copyExifWithoutOrientation(copyExifFromFile: File, copyExifToFile: File): Promise<File> // based on https://gist.github.com/tonytonyjan/ffb7cd0e82cb293b843ece7e79364233
|
||||
```
|
||||
|
||||
|
||||
## Browsers support
|
||||
|
||||
| [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/edge/edge_48x48.png" alt="IE / Edge" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>IE / Edge | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/firefox/firefox_48x48.png" alt="Firefox" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Firefox | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/chrome/chrome_48x48.png" alt="Chrome" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Chrome | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari/safari_48x48.png" alt="Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/safari-ios/safari-ios_48x48.png" alt="iOS Safari" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>iOS Safari | [<img src="https://raw.githubusercontent.com/alrra/browser-logos/master/src/opera/opera_48x48.png" alt="Opera" width="24px" height="24px" />](http://godban.github.io/browsers-support-badges/)<br/>Opera |
|
||||
| --------- | --------- | --------- | --------- | --------- | --------- |
|
||||
| IE10, IE11, Edge| last 2 versions| last 2 versions| last 2 versions| last 2 versions| last 2 versions
|
||||
|
||||
### IE support
|
||||
This library uses ES features such as Promise API, globalThis. If you need to support browsers that do not support new ES features like IE. You can include the core-js polyfill in your project.
|
||||
|
||||
You can include the following script to load the core-js polyfill:
|
||||
```html
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/core-js/3.21.1/minified.min.js"></script>
|
||||
```
|
||||
|
||||
### Webp support
|
||||
The webp compression is supported on major browsers. Please see https://caniuse.com/mdn-api_offscreencanvas_converttoblob_option_type_parameter_webp for browser compatibility.
|
||||
|
||||
|
||||
## Remarks for compression to work in Web Worker
|
||||
The browser needs to support "OffscreenCanvas" API in order to take advantage of non-blocking compression. If the browser does not support "OffscreenCanvas" API, the main thread is used instead. See https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas#browser_compatibility for browser compatibility of "OffscreenCanvas" API.
|
||||
|
||||
|
||||
## Typescript type definitions
|
||||
Typescript definitions are included in the package & referenced in the `types` section of the `package.json`
|
||||
|
||||
|
||||
## Remarks on Content Security Policy (CSP)
|
||||
If your website has CSP enabled and you want to use Web Worker (useWebWorker: true), please add the following to the response header
|
||||
`content-security-policy: script-src 'self' blob: https://cdn.jsdelivr.net`
|
||||
|
||||
- `blob:` is for loading Web Worker script
|
||||
- `https://cdn.jsdelivr.net` is for importing this library from CDN inside Web Worker script. If you don't want to load this library from CDN, you can set your self hosted library URL in `options.libURL`.
|
||||
|
||||
|
||||
## Contribution
|
||||
1. fork the repo and git clone it
|
||||
2. run `npm run watch` # it will watch code change in lib/ folder and generate js in dist/ folder
|
||||
3. add/update code in lib/ folder
|
||||
4. try the code by opening example/development.html which will load the js in dist/ folder
|
||||
5. add/update test in test/ folder
|
||||
6. `npm run test`
|
||||
7. push to your forked repo on github
|
||||
8. make a pull request to dev branch of this repo
|
||||
|
||||
[dist]: https://github.com/Donaldcwl/browser-image-compression/tree/master/dist
|
||||
[example]: https://github.com/Donaldcwl/browser-image-compression/tree/master/example
|
||||
[delivrjs]: https://cdn.jsdelivr.net/
|
||||
Loading…
Add table
Add a link
Reference in a new issue