ui: Remove photo cropper element
It turns out the cropper is _way_ too hard to use on mobile. The cropper handles are much too small for a touch screen. Maybe I can figure out how to improve the UX eventually, but for now, Tabitha requested that we remove that functionality.bugfix/ci-buildah
parent
9cef220f90
commit
3b586413ff
|
@ -6,133 +6,12 @@
|
||||||
"": {
|
"": {
|
||||||
"name": "receipts",
|
"name": "receipts",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shoelace-style/shoelace": "^2.20.0",
|
"@shoelace-style/shoelace": "^2.20.0"
|
||||||
"cropperjs": "^2.0.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"esbuild": "^0.25.0"
|
"esbuild": "^0.25.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@cropper/element": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/element/-/element-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-lsthn0nQq73GExUE7Mg/ss6Q3RXADGDv055hxoLFwvl/wGHgy6ZkYlfLZ/VmgBHC6jDK5IgPBFnqrPqlXWSGBA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/utils": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cropper/element-canvas": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/element-canvas/-/element-canvas-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-GPtGJgSm92crJhhhwUsaMw3rz2KfJWWSz7kRAlufFEV/EHTP5+6r6/Z1BCGRna830i+Avqbm435XLOtA7PVJwA==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/element": "^2.0.0",
|
|
||||||
"@cropper/utils": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cropper/element-crosshair": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/element-crosshair/-/element-crosshair-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-KfPfyrdeFvUC31Ws7ATtcalWWSaMtrC6bMoCipZhqbUOE7wZoL4ecDSL6BUOZxPa74awZUqfzirCDjHvheBfyw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/element": "^2.0.0",
|
|
||||||
"@cropper/utils": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cropper/element-grid": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/element-grid/-/element-grid-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-i78SQ0IJTLFveKX6P7svkfMYVdgHrQ8ZmmEw8keFy9n1ZVbK+SK0UHK5FNMRNI/gtVhKJOGEnK/zeyjUdj4Iyw==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/element": "^2.0.0",
|
|
||||||
"@cropper/utils": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cropper/element-handle": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/element-handle/-/element-handle-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-ZJvW+0MkK9E8xYymGdoruaQn2kwjSHFpNSWinjyq6csuVQiCPxlX5ovAEDldmZ9MWePPtWEi3vLKQOo2Yb0T8g==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/element": "^2.0.0",
|
|
||||||
"@cropper/utils": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cropper/element-image": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/element-image/-/element-image-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-9BxiTS/aHRmrjopaFQb9mQQXmx4ruhYHGkDZMVz24AXpMFjUY6OpqrWse/WjzD9tfhMFvEdu17b3VAekcAgpeg==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/element": "^2.0.0",
|
|
||||||
"@cropper/element-canvas": "^2.0.0",
|
|
||||||
"@cropper/utils": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cropper/element-selection": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/element-selection/-/element-selection-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-ensNnbIfJsJ8bhbJTH/RXtk2URFvTOO4TvfRk461n2FPEC588D7rwBmUJxQg74IiTi4y1JbCI+6j+4LyzYBLCQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/element": "^2.0.0",
|
|
||||||
"@cropper/element-canvas": "^2.0.0",
|
|
||||||
"@cropper/element-image": "^2.0.0",
|
|
||||||
"@cropper/utils": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cropper/element-shade": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/element-shade/-/element-shade-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-jv/2bbNZnhU4W+T4G0c8ADocLIZvQFTXgCf2RFDNhI5UVxurzWBnDdb8Mx8LnVplnkTqO+xUmHZYve0CwgWo+Q==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/element": "^2.0.0",
|
|
||||||
"@cropper/element-canvas": "^2.0.0",
|
|
||||||
"@cropper/element-selection": "^2.0.0",
|
|
||||||
"@cropper/utils": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cropper/element-viewer": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/element-viewer/-/element-viewer-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-zY+3VRN5TvpM8twlphYtXw0tzJL2VgzeK7ufhL1BixVqOdRxwP13TprYIhqwGt9EW/SyJZUiaIu396T89kRX8A==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/element": "^2.0.0",
|
|
||||||
"@cropper/element-canvas": "^2.0.0",
|
|
||||||
"@cropper/element-image": "^2.0.0",
|
|
||||||
"@cropper/element-selection": "^2.0.0",
|
|
||||||
"@cropper/utils": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cropper/elements": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/elements/-/elements-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-PQkPo1nUjxLFUQuHYu+6atfHxpX9B41Xribao6wpvmvmNIFML6LQdNqqWYb6LyM7ujsu71CZdBiMT5oetjJVoQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/element": "^2.0.0",
|
|
||||||
"@cropper/element-canvas": "^2.0.0",
|
|
||||||
"@cropper/element-crosshair": "^2.0.0",
|
|
||||||
"@cropper/element-grid": "^2.0.0",
|
|
||||||
"@cropper/element-handle": "^2.0.0",
|
|
||||||
"@cropper/element-image": "^2.0.0",
|
|
||||||
"@cropper/element-selection": "^2.0.0",
|
|
||||||
"@cropper/element-shade": "^2.0.0",
|
|
||||||
"@cropper/element-viewer": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/@cropper/utils": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/@cropper/utils/-/utils-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-cprLYr+7kK3faGgoOsTW9gIn5sefDr2KwOmgyjzIXk+8PLpW8FgFKEg5FoWfRD5zMAmkCBuX6rGKDK3VdUEGrg==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/@ctrl/tinycolor": {
|
"node_modules/@ctrl/tinycolor": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.1.0.tgz",
|
||||||
|
@ -680,16 +559,6 @@
|
||||||
"@floating-ui/utils": "^0.2.5"
|
"@floating-ui/utils": "^0.2.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/cropperjs": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/cropperjs/-/cropperjs-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-TO2j0Qre01kPHbow4FuTrbdEB4jTmGRySxW49jyEIqlJZuEBfrvCTT0vC3eRB2WBXudDfKi1Onako6DKWKxeAQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"@cropper/elements": "^2.0.0",
|
|
||||||
"@cropper/utils": "^2.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.1.3",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
|
||||||
|
|
|
@ -2,8 +2,7 @@
|
||||||
"name": "receipts",
|
"name": "receipts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@shoelace-style/shoelace": "^2.20.0",
|
"@shoelace-style/shoelace": "^2.20.0"
|
||||||
"cropperjs": "^2.0.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"esbuild": "^0.25.0"
|
"esbuild": "^0.25.0"
|
||||||
|
|
|
@ -12,7 +12,6 @@ import SlButton from "@shoelace-style/shoelace/dist/components/button/button.js"
|
||||||
import SlDetails from "@shoelace-style/shoelace/dist/components/details/details.js";
|
import SlDetails from "@shoelace-style/shoelace/dist/components/details/details.js";
|
||||||
import SlIconButton from "@shoelace-style/shoelace/dist/components/icon-button/icon-button.js";
|
import SlIconButton from "@shoelace-style/shoelace/dist/components/icon-button/icon-button.js";
|
||||||
import { setBasePath } from "@shoelace-style/shoelace/dist/utilities/base-path.js";
|
import { setBasePath } from "@shoelace-style/shoelace/dist/utilities/base-path.js";
|
||||||
import Cropper from "cropperjs";
|
|
||||||
|
|
||||||
import { notify } from "./alert";
|
import { notify } from "./alert";
|
||||||
|
|
||||||
|
@ -25,30 +24,19 @@ const video = photoview.querySelector("video")!;
|
||||||
const btnshutter = photoview.querySelector(
|
const btnshutter = photoview.querySelector(
|
||||||
" sl-icon-button[label='Take Photo']",
|
" sl-icon-button[label='Take Photo']",
|
||||||
) as SlIconButton;
|
) as SlIconButton;
|
||||||
const btncrop = photoview.querySelector(
|
|
||||||
" sl-icon-button[label='Crop']",
|
|
||||||
) as SlIconButton;
|
|
||||||
const btnreset = photoview.querySelector(
|
const btnreset = photoview.querySelector(
|
||||||
" sl-icon-button[label='Start Over']",
|
" sl-icon-button[label='Start Over']",
|
||||||
) as SlIconButton;
|
) as SlIconButton;
|
||||||
const btnsubmit = form.querySelector("sl-button[type='submit']") as SlButton;
|
|
||||||
|
|
||||||
let cropper: Cropper | null = null;
|
|
||||||
let initialized = false;
|
let initialized = false;
|
||||||
|
|
||||||
async function clearCamera() {
|
async function clearCamera() {
|
||||||
if (cropper) {
|
|
||||||
cropper.getCropperCanvas()?.remove();
|
|
||||||
cropper = null;
|
|
||||||
}
|
|
||||||
video.pause();
|
video.pause();
|
||||||
video.srcObject = null;
|
video.srcObject = null;
|
||||||
video.classList.add("invisible");
|
video.classList.add("invisible");
|
||||||
video.parentNode?.querySelectorAll("canvas").forEach((e) => e.remove());
|
video.parentNode?.querySelectorAll("canvas").forEach((e) => e.remove());
|
||||||
btnshutter.disabled = true;
|
btnshutter.disabled = true;
|
||||||
btnshutter.classList.add("invisible");
|
btnshutter.classList.add("invisible");
|
||||||
btncrop.disabled = true;
|
|
||||||
btncrop.classList.add("invisible");
|
|
||||||
btnreset.disabled = true;
|
btnreset.disabled = true;
|
||||||
btnreset.classList.add("invisible");
|
btnreset.classList.add("invisible");
|
||||||
photoview.classList.remove("invisible");
|
photoview.classList.remove("invisible");
|
||||||
|
@ -78,7 +66,8 @@ async function startCamera() {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function submitForm(data: FormData) {
|
async function submitForm(data: FormData) {
|
||||||
btnsubmit.loading = true;
|
const btn = form.querySelector("sl-button[type='submit']") as SlButton;
|
||||||
|
btn.loading = true;
|
||||||
let r: Response | null = null;
|
let r: Response | null = null;
|
||||||
try {
|
try {
|
||||||
r = await fetch("", {
|
r = await fetch("", {
|
||||||
|
@ -93,7 +82,7 @@ async function submitForm(data: FormData) {
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
btnsubmit.loading = false;
|
btn.loading = false;
|
||||||
if (r) {
|
if (r) {
|
||||||
if (r.ok) {
|
if (r.ok) {
|
||||||
notify(
|
notify(
|
||||||
|
@ -121,11 +110,11 @@ async function submitForm(data: FormData) {
|
||||||
}
|
}
|
||||||
|
|
||||||
function takePhoto() {
|
function takePhoto() {
|
||||||
btnsubmit.disabled = true;
|
|
||||||
btnshutter.disabled = true;
|
btnshutter.disabled = true;
|
||||||
btnshutter.classList.add("invisible");
|
btnshutter.classList.add("invisible");
|
||||||
video.pause();
|
video.pause();
|
||||||
const canvas = document.createElement("canvas");
|
const canvas = document.createElement("canvas");
|
||||||
|
canvas.setAttribute("id", "camera-photo");
|
||||||
const context = canvas.getContext("2d");
|
const context = canvas.getContext("2d");
|
||||||
if (!context) {
|
if (!context) {
|
||||||
notify(
|
notify(
|
||||||
|
@ -144,10 +133,6 @@ function takePhoto() {
|
||||||
video.srcObject = null;
|
video.srcObject = null;
|
||||||
video.classList.add("invisible");
|
video.classList.add("invisible");
|
||||||
video.parentNode!.appendChild(canvas);
|
video.parentNode!.appendChild(canvas);
|
||||||
cropper = new Cropper(canvas);
|
|
||||||
cropper.getCropperCanvas()!.style.height = `${height}px`;
|
|
||||||
btncrop.disabled = false;
|
|
||||||
btncrop.classList.remove("invisible");
|
|
||||||
btnreset.disabled = false;
|
btnreset.disabled = false;
|
||||||
btnreset.classList.remove("invisible");
|
btnreset.classList.remove("invisible");
|
||||||
}
|
}
|
||||||
|
@ -168,21 +153,6 @@ btnshutter.addEventListener("click", async () => {
|
||||||
takePhoto();
|
takePhoto();
|
||||||
});
|
});
|
||||||
|
|
||||||
btncrop.addEventListener("click", async () => {
|
|
||||||
btnsubmit.disabled = false;
|
|
||||||
if (cropper) {
|
|
||||||
const canvas = await cropper.getCropperSelection()?.$toCanvas();
|
|
||||||
if (canvas) {
|
|
||||||
canvas.setAttribute("id", "camera-photo");
|
|
||||||
video.parentNode!.appendChild(canvas);
|
|
||||||
cropper.getCropperCanvas()?.remove();
|
|
||||||
btncrop.disabled = true;
|
|
||||||
btncrop.classList.add("invisible");
|
|
||||||
cropper = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
btnreset.addEventListener("click", () => {
|
btnreset.addEventListener("click", () => {
|
||||||
clearCamera();
|
clearCamera();
|
||||||
startCamera();
|
startCamera();
|
||||||
|
|
|
@ -39,9 +39,6 @@
|
||||||
<sl-tooltip content="Take Photo">
|
<sl-tooltip content="Take Photo">
|
||||||
<sl-icon-button name="camera" label="Take Photo"></sl-icon-button>
|
<sl-icon-button name="camera" label="Take Photo"></sl-icon-button>
|
||||||
</sl-tooltip>
|
</sl-tooltip>
|
||||||
<sl-tooltip content="Crop">
|
|
||||||
<sl-icon-button name="crop" label="Crop"></sl-icon-button>
|
|
||||||
</sl-tooltip>
|
|
||||||
<sl-tooltip content="Start Over">
|
<sl-tooltip content="Start Over">
|
||||||
<sl-icon-button
|
<sl-icon-button
|
||||||
name="trash"
|
name="trash"
|
||||||
|
|
Loading…
Reference in New Issue