Skip to content

Commit 0e951d5

Browse files
authored
Merge branch '3.x' into fix/multiselect-dropdown-out-of-bounds
2 parents f0c736b + 6d0de91 commit 0e951d5

File tree

18 files changed

+165
-52
lines changed

18 files changed

+165
-52
lines changed

Diff for: .github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ jobs:
108108
id: composer-cache
109109
run: |
110110
echo "::set-output name=dir::$(composer config cache-files-dir)"
111-
- uses: actions/cache@v2
111+
- uses: actions/cache@v4
112112
with:
113113
path: ${{ steps.composer-cache.outputs.dir }}
114114
key: ${{ matrix.os }}-${{ matrix.laravel }}-${{ matrix.php }}-${{ matrix.dbal }}-composer-${{ hashFiles('**/composer.lock') }}

Diff for: composer.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,9 @@
4848
"area17/phptorch": "dev-main",
4949
"chillerlan/php-qrcode": "~4.0",
5050
"friendsofphp/php-cs-fixer": "^3.0",
51+
"larastan/larastan": "^2.9",
5152
"nette/php-generator": "^4.0.3",
5253
"nunomaduro/collision": "^6.0 || ^7.0 || ^8.0",
53-
"nunomaduro/larastan": "^2.0",
5454
"orchestra/testbench": "^7.8 || ^8.0 || ^9.0",
5555
"orchestra/testbench-dusk": "^7.8 || ^8.0 || ^9.0",
5656
"phpunit/php-invoker": "^3.1 || ^4.0",

Diff for: docs/content/1_docs/4_form-fields/06_multi-select.md

+22-2
Original file line numberDiff line numberDiff line change
@@ -200,21 +200,38 @@ public function sectors() {
200200
- In your repository, make sure to sync the association when saving:
201201

202202
```php
203-
public function afterSave($object, $fields)
203+
public function afterSave($object, $fields): void
204204
{
205205
$object->sectors()->sync($fields['sectors'] ?? []);
206206

207207
parent::afterSave($object, $fields);
208208
}
209209
```
210210

211+
:::tabs=currenttab.FormBuilder&items.FormBuilder|FormView:::
212+
:::tab=name.FormBuilder:::
213+
214+
```php
215+
$form->add(
216+
MultiSelect::make()
217+
->name('sectors')
218+
->options(
219+
Options::fromArray(app()->make(SectorsRepository::class)->listAll()->toArray())
220+
)
221+
);
222+
```
223+
224+
:::#tab:::
225+
226+
:::tab=name.FormView:::
227+
211228
- In your controller, add to the formData the collection of options:
212229

213230
```php
214231
protected function formData($request)
215232
{
216233
return [
217-
'sectors' => app()->make(SectorRepository::class)->listAll()
234+
'sectors' => app()->make(SectorRepository::class)->listAll()->toArray()
218235
];
219236
}
220237
```
@@ -229,6 +246,9 @@ protected function formData($request)
229246
/>
230247
```
231248

249+
:::#tab:::
250+
:::#tabs:::
251+
232252
When used in a [block](../5_block-editor), no migration is needed.
233253

234254
## Multi Select Inline
Loading

Diff for: frontend/js/components/Dropdown.vue

+2-2
Original file line numberDiff line numberDiff line change
@@ -207,8 +207,8 @@
207207
if (!this.active) return
208208
209209
clearTimeout(this.timer)
210-
document.removeEventListener('click', this.closeFromDoc, true)
211-
document.removeEventListener('touchend', this.closeFromDoc, true)
210+
document.removeEventListener('click', this.closeFromDoc, false)
211+
document.removeEventListener('touchend', this.closeFromDoc, false)
212212
213213
if (this.fixed) {
214214
window.removeEventListener('scroll', this.closeFromDoc, true)

Diff for: frontend/js/components/MediaField.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -763,7 +763,7 @@
763763
}
764764
765765
.media__actions {
766-
min-width:45px * 3;
766+
flex-shrink: 0;
767767
768768
@media screen and (max-width: 1140px) {
769769
display: none !important;

Diff for: frontend/js/components/Slideshow.vue

+5
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
:index="index"
1616
:mediaContext="name"
1717
:cropContext="cropContext"
18+
:activeCrop="activeCrop"
1819
:hover="hoverable"
1920
:isSlide="true"
2021
:withAddInfo="withAddInfo"
@@ -70,6 +71,10 @@
7071
disabled: {
7172
type: Boolean,
7273
default: false
74+
},
75+
activeCrop: {
76+
type: Boolean,
77+
default: true
7378
}
7479
},
7580
data: function () {

Diff for: frontend/js/components/editor/EditorSidebarBlockList.vue

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<draggable class="editorSidebar__blocks"
55
:class="editorSidebarClasses"
66
v-model="blocks"
7-
:options="{
7+
v-bind="{
88
group: {
99
name: 'editorBlocks',
1010
pull: 'clone',

Diff for: frontend/js/components/media-library/Uploader.vue

+41-34
Original file line numberDiff line numberDiff line change
@@ -197,46 +197,53 @@
197197
this.uploadProgress(0)
198198
},
199199
_onSubmitCallback (id, name) {
200-
this.$emit('clear')
201-
// each upload session will add upload files with original filenames in a folder named using a uuid
202-
this.unique_folder_name = this.unique_folder_name || (this.uploaderConfig.endpointRoot + qq.getUniqueId())
203-
this._uploader.methods.setParams({
204-
unique_folder_name: this.unique_folder_name,
205-
media_to_replace_id: this.media_to_replace_id
206-
}, id)
200+
return new Promise((resolve, reject) => {
201+
// halt fine uploader upload until image is loaded
202+
// so we can send image dimensions with the upload
203+
const img = new Image()
204+
img.onload = () => {
205+
this.$emit('clear')
206+
// each upload session will add upload files with original filenames in a folder named using a uuid
207+
this.unique_folder_name = this.unique_folder_name || (this.uploaderConfig.endpointRoot + qq.getUniqueId())
207208
208-
// determine the image dimensions and add it to params sent on upload success
209-
const imageUrl = URL.createObjectURL(this._uploader.methods.getFile(id))
210-
const img = new Image()
209+
// determine the image dimensions and add it to params sent on upload success
210+
this._uploader.methods.setParams({
211+
width: img.width,
212+
height: img.height,
213+
unique_folder_name: this.unique_folder_name,
214+
media_to_replace_id: this.media_to_replace_id
215+
}, id)
211216
212-
img.onload = () => {
213-
this._uploader.methods.setParams({
214-
width: img.width,
215-
height: img.height,
216-
unique_folder_name: this.unique_folder_name,
217-
media_to_replace_id: this.media_to_replace_id
218-
}, id)
219-
this.media_to_replace_id = null
220-
}
217+
this.media_to_replace_id = null
221218
222-
img.src = imageUrl
219+
const media = {
220+
id: this._uploader.methods.getUuid(id),
221+
name: sanitizeFilename(name),
222+
progress: 0,
223+
error: false,
224+
errorMessage: null,
225+
isReplacement: !!this.media_to_replace_id,
226+
replacementId: this.media_to_replace_id
227+
}
223228
224-
const media = {
225-
id: this._uploader.methods.getUuid(id),
226-
name: sanitizeFilename(name),
227-
progress: 0,
228-
error: false,
229-
errorMessage: null,
230-
isReplacement: !!this.media_to_replace_id,
231-
replacementId: this.media_to_replace_id
232-
}
229+
if (this.type.value === 'file') {
230+
this.media_to_replace_id = null
231+
}
233232
234-
if (this.type.value === 'file') {
235-
this.media_to_replace_id = null
236-
}
233+
this.loadingMedias.push(media)
234+
this.loadingProgress(media)
235+
236+
// resolve the promise, allow the upload to continue
237+
resolve(img)
238+
}
239+
240+
img.onerror = (err) => {
241+
console.error(err) // eslint-disable-line
242+
reject(err);
243+
}
237244
238-
this.loadingMedias.push(media)
239-
this.loadingProgress(media)
245+
img.src = URL.createObjectURL(this._uploader.methods.getFile(id))
246+
});
240247
},
241248
_onProgressCallback (id, name, uploadedBytes, totalBytes) {
242249
const index = this.loadingMedias.findIndex((m) => m.id === this._uploader.methods.getUuid(id))

Diff for: frontend/js/utils/cropper.js

+26-1
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,37 @@
22
* Convert crop values between to given range
33
*/
44
export const cropConversion = (data, dest, origin) => {
5-
return {
5+
const d = {
66
x: Math.round(data.x * dest.width / origin.width),
77
y: Math.round(data.y * dest.height / origin.height),
88
width: Math.round(data.width * dest.width / origin.width),
99
height: Math.round(data.height * dest.height / origin.height)
1010
}
11+
12+
// Mike ([email protected]) --
13+
//
14+
// fixing the case of the square...
15+
// rounding errors often mean that a square crop appears to
16+
// generate non square outputs. Usually only out by a few pixels
17+
// but its noticeable with a square as you're expecting w === h
18+
//
19+
// first checking if the crop shape is (nearly) square
20+
// (its subject to its own rounding errors...)
21+
if (Math.abs(data.width - data.height) < 2) {
22+
// storing the difference between calculated width and height
23+
const diff = d.width - d.height;
24+
// setting height to equal width
25+
d.height = d.width;
26+
// we may have made the final crop taller,
27+
// which means we might try and crop dimensions lower than the original image height
28+
// so compensating, if we've cropped lower than the diff
29+
if (diff > 0 && d.y > diff) {
30+
d.y = d.y - diff;
31+
}
32+
}
33+
// -- Mike ([email protected])
34+
35+
return d;
1136
}
1237

1338
export default {

Diff for: package-lock.json

+5-4
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: phpstan.neon

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
includes:
2-
- ./vendor/nunomaduro/larastan/extension.neon
2+
- ./vendor/larastan/larastan/extension.neon
33
- phpstan-baseline.neon
44

55
parameters:

0 commit comments

Comments
 (0)