Skip to content

Commit 3c8e7dd

Browse files
authored
Merge pull request #3193 from AlchemyCMS/backport/7.4-stable/pr-3192
[7.4-stable] Fix image cropper
2 parents 9d5fe03 + d67f6b1 commit 3c8e7dd

File tree

4 files changed

+68
-20
lines changed

4 files changed

+68
-20
lines changed

.github/workflows/build_test.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ jobs:
3434
runs-on: ubuntu-22.04
3535
name: Build JS packages
3636
needs: check_bun_lock
37-
if: needs.check_bun_lock.outputs.bun_lock_changed == 'true'
3837
steps:
3938
- uses: actions/checkout@v4
4039
- name: Setup Bun
@@ -49,8 +48,10 @@ jobs:
4948
- name: Install dependencies
5049
run: bun install
5150
- name: bun build
51+
if: needs.check_bun_lock.outputs.bun_lock_changed == 'true'
5252
run: bun run --bun build
5353
- uses: actions/upload-artifact@v4
54+
if: needs.check_bun_lock.outputs.bun_lock_changed == 'true'
5455
with:
5556
name: javascript-bundles
5657
path: vendor/javascript
@@ -59,7 +60,6 @@ jobs:
5960
permissions:
6061
contents: read
6162
needs: [check_bun_lock, build_javascript]
62-
if: ${{ success('check_bun_lock') && !failure('build_javascript') }}
6363
runs-on: ubuntu-22.04
6464
strategy:
6565
fail-fast: false

app/javascript/alchemy_admin/image_cropper.js

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,38 +6,29 @@ export default class ImageCropper {
66
#cropFromField = null
77
#cropSizeField = null
88

9-
constructor(
10-
image,
11-
minSize,
12-
defaultBox,
13-
aspectRatio,
14-
formFieldIds,
15-
elementId
16-
) {
9+
constructor(image, defaultBox, aspectRatio, formFieldIds, elementId) {
1710
this.image = image
18-
this.minSize = minSize
1911
this.defaultBox = defaultBox
2012
this.aspectRatio = aspectRatio
2113
this.#cropFromField = document.getElementById(formFieldIds[0])
2214
this.#cropSizeField = document.getElementById(formFieldIds[1])
2315
this.elementId = elementId
2416
this.dialog = Alchemy.currentDialog()
25-
this.dialog.options.closed = () => this.destroy()
17+
if (this.dialog) {
18+
this.dialog.options.closed = () => this.destroy()
19+
this.bind()
20+
}
2621
this.init()
27-
this.bind()
2822
}
2923

3024
get cropperOptions() {
3125
return {
3226
aspectRatio: this.aspectRatio,
3327
viewMode: 1,
3428
zoomable: false,
35-
minCropBoxWidth: this.minSize && this.minSize[0],
36-
minCropBoxHeight: this.minSize && this.minSize[1],
37-
ready: (event) => {
38-
const cropper = event.target.cropper
39-
cropper.setData(this.box)
40-
},
29+
checkCrossOrigin: false, // Prevent CORS issues
30+
checkOrientation: false, // Prevent loading the image via AJAX which can cause CORS issues
31+
data: this.box,
4132
cropend: () => {
4233
const data = this.#cropper.getData(true)
4334
this.update(data)

app/views/alchemy/admin/crop.html.erb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
new ImageLoader(image);
2727
new ImageCropper(
2828
image,
29-
<%= @settings[:min_size].to_json %>,
3029
<%= @settings[:default_box].to_json %>,
3130
<%= @settings[:ratio] %>,
3231
[
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import ImageCropper from "alchemy_admin/image_cropper"
2+
3+
describe("ImageCropper", () => {
4+
describe("cropperOptions", () => {
5+
beforeEach(() => {
6+
document.body.innerHTML = `
7+
<div id="element_id">
8+
<input id="crop_from" type="hidden" value="0x423" />
9+
<input id="crop_size" type="hidden" value="1200x480" />
10+
</div>
11+
`
12+
Alchemy.currentDialog = jest.fn()
13+
})
14+
15+
it("is sets initial data", () => {
16+
const image = new Image()
17+
const cropper = new ImageCropper(
18+
image,
19+
{},
20+
1,
21+
["crop_from", "crop_size"],
22+
"element_id"
23+
)
24+
expect(cropper.cropperOptions["data"]).toEqual({
25+
height: 480,
26+
width: 1200,
27+
x: 0,
28+
y: 423
29+
})
30+
})
31+
32+
it("does not set min crop size", () => {
33+
const image = new Image()
34+
const cropper = new ImageCropper(
35+
image,
36+
{},
37+
1,
38+
["crop_from", "crop_size"],
39+
"element_id"
40+
)
41+
expect(cropper.cropperOptions["minCropBoxWidth"]).toBeUndefined()
42+
expect(cropper.cropperOptions["minCropBoxHeight"]).toBeUndefined()
43+
})
44+
45+
it("prevents CORS issues", () => {
46+
const image = new Image()
47+
const cropper = new ImageCropper(
48+
image,
49+
{},
50+
1,
51+
["crop_from", "crop_size"],
52+
"element_id"
53+
)
54+
expect(cropper.cropperOptions["checkCrossOrigin"]).toBe(false)
55+
expect(cropper.cropperOptions["checkOrientation"]).toBe(false)
56+
})
57+
})
58+
})

0 commit comments

Comments
 (0)