Skip to content

Commit 59cb739

Browse files
authored
Merge pull request #16908 from craftcms/feature/cms-1373-warn-when-moving-large-asset-folders
Feature/cms 1373 warn when moving large asset folders
2 parents ce7f97b + b008b30 commit 59cb739

File tree

11 files changed

+453
-257
lines changed

11 files changed

+453
-257
lines changed

CHANGELOG-WIP.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Release Notes for Craft CMS 4.15 (WIP)
22

33
### Content Management
4+
- The Assets index page now prompts for confirmation when moving more than 50 assets, or assets totalling more than 50MB, at once. ([#16908](https://github.com/craftcms/cms/pull/16908))
5+
- The success notification displayed after an asset move now includes an “Undo” button, if less than 50 assets/50MB were involved in the move. ([#16908](https://github.com/craftcms/cms/pull/16908))
46
- Window scrolling is now blocked when a modal window is open. ([#16768](https://github.com/craftcms/cms/pull/16768))
57

68
### Administration

src/controllers/AssetsController.php

+46
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
use craft\assetpreviews\Image as ImagePreview;
1212
use craft\base\Element;
1313
use craft\base\LocalFsInterface;
14+
use craft\db\Query;
15+
use craft\db\Table;
1416
use craft\elements\Asset;
1517
use craft\elements\conditions\ElementCondition;
1618
use craft\errors\AssetException;
@@ -1348,4 +1350,48 @@ public function actionGenerateFallbackTransform(string $transform): Response
13481350
'inline' => true,
13491351
]);
13501352
}
1353+
1354+
/**
1355+
* Returns the total number of assets, and their total file size, based on their IDs and/or folder IDs.
1356+
*
1357+
* @return Response
1358+
* @throws BadRequestHttpException
1359+
* @since 4.15.0
1360+
*/
1361+
public function actionMoveInfo(): Response
1362+
{
1363+
$this->requireCpRequest();
1364+
$this->requirePostRequest();
1365+
1366+
$folderIds = Craft::$app->getRequest()->getBodyParam('folderIds', []);
1367+
$assetIds = Craft::$app->getRequest()->getBodyParam('assetIds', []);
1368+
1369+
if (!empty($folderIds)) {
1370+
// Add descendant folders
1371+
$assetsService = Craft::$app->getAssets();
1372+
foreach ($folderIds as $folderId) {
1373+
$folder = $assetsService->getFolderById($folderId);
1374+
if (!$folder) {
1375+
throw new BadRequestHttpException("Invalid folder ID: $folderId");
1376+
}
1377+
$descendants = $assetsService->getAllDescendantFolders($folder);
1378+
array_push($folderIds, ...array_keys($descendants));
1379+
}
1380+
}
1381+
1382+
$query = (new Query())
1383+
->from(Table::ASSETS)
1384+
->where([
1385+
'or',
1386+
['id' => $assetIds],
1387+
['folderId' => array_unique($folderIds)],
1388+
]);
1389+
$count = (int)$query->count();
1390+
$totalSize = (int)$query->sum('[[size]]');
1391+
1392+
return $this->asJson([
1393+
'count' => $count,
1394+
'totalSize' => $totalSize,
1395+
]);
1396+
}
13511397
}

src/elements/actions/MoveAssets.php

+17-12
Original file line numberDiff line numberDiff line change
@@ -83,19 +83,24 @@ public function getTriggerHtml(): ?string
8383
defaultSource: Craft.elementIndex.sourceKey,
8484
defaultSourcePath: Craft.elementIndex.sourcePath,
8585
},
86-
onSelect: ([targetFolder]) => {
86+
onSelect: async ([targetFolder]) => {
8787
const mover = new Craft.AssetMover();
88-
mover.moveFolders(selectedFolderIds, targetFolder.folderId).then((totalFoldersMoved) => {
89-
mover.moveAssets(selectedAssetIds, targetFolder.folderId).then((totalAssetsMoved) => {
90-
const totalItemsMoved = totalFoldersMoved + totalAssetsMoved;
91-
if (totalItemsMoved) {
92-
Craft.cp.displayNotice(Craft.t('app', '{totalItems, plural, =1{Item} other{Items}} moved.', {
93-
totalItems: totalItemsMoved,
94-
}));
95-
Craft.elementIndex.updateElements(true);
96-
}
97-
});
98-
});
88+
const moveParams = await mover.getMoveParams(selectedFolderIds, selectedAssetIds);
89+
if (!moveParams.proceed) {
90+
return;
91+
}
92+
const totalFoldersMoved = await mover.moveFolders(selectedFolderIds, targetFolder.folderId, Craft.elementIndex.currentFolderId);
93+
const totalAssetsMoved = await mover.moveAssets(selectedAssetIds, targetFolder.folderId, Craft.elementIndex.currentFolderId);
94+
const totalItemsMoved = totalFoldersMoved + totalAssetsMoved;
95+
if (totalItemsMoved) {
96+
mover.successNotice(
97+
moveParams,
98+
Craft.t('app', '{totalItems, plural, =1{Item} other{Items}} moved.', {
99+
totalItems: totalItemsMoved,
100+
})
101+
);
102+
Craft.elementIndex.updateElements(true);
103+
}
99104
},
100105
});
101106
},

src/services/Assets.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -485,7 +485,7 @@ public function findFolders(mixed $criteria = []): array
485485
* @param string $orderBy
486486
* @param bool $withParent Whether the parent folder should be included in the results
487487
* @param bool $asTree Whether the folders should be returned hierarchically
488-
* @return VolumeFolder[]
488+
* @return array<int,VolumeFolder> The descendant folders, indexed by their IDs
489489
*/
490490
public function getAllDescendantFolders(
491491
VolumeFolder $parentFolder,

src/translations/en/app.php

+3
Original file line numberDiff line numberDiff line change
@@ -153,11 +153,13 @@
153153
'Are you sure you want to delete “{name}”?' => 'Are you sure you want to delete “{name}”?',
154154
'Are you sure you want to discard the pending project config YAML changes?' => 'Are you sure you want to discard the pending project config YAML changes?',
155155
'Are you sure you want to discard your changes?' => 'Are you sure you want to discard your changes?',
156+
'Are you sure you want to move the selected items?' => 'Are you sure you want to move the selected items?',
156157
'Are you sure you want to permanently delete the selected {type}?' => 'Are you sure you want to permanently delete the selected {type}?',
157158
'Are you sure you want to release all jobs in the queue?' => 'Are you sure you want to release all jobs in the queue?',
158159
'Are you sure you want to release the job “{description}”?' => 'Are you sure you want to release the job “{description}”?',
159160
'Are you sure you want to restart the job “{description}”? Any progress could be lost.' => 'Are you sure you want to restart the job “{description}”? Any progress could be lost.',
160161
'Are you sure you want to transfer your license to this domain?' => 'Are you sure you want to transfer your license to this domain?',
162+
'Are you sure you want to undo the move?' => 'Are you sure you want to undo the move?',
161163
'Are you sure you want to uninstall {plugin}? You will lose all of its associated data.' => 'Are you sure you want to uninstall {plugin}? You will lose all of its associated data.',
162164
'Area' => 'Area',
163165
'As currency values' => 'As currency values',
@@ -932,6 +934,7 @@
932934
'More…' => 'More…',
933935
'Move down' => 'Move down',
934936
'Move folder' => 'Move folder',
937+
'Move reverted.' => 'Move reverted.',
935938
'Move to the left' => 'Move to the left',
936939
'Move to the right' => 'Move to the right',
937940
'Move to' => 'Move to',

src/web/assets/cp/CpAsset.php

+3
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ private function _registerTranslations(View $view): void
129129
'Are you sure you want to delete this {type}?',
130130
'Are you sure you want to delete “{name}”?',
131131
'Are you sure you want to discard your changes?',
132+
'Are you sure you want to move the selected items?',
132133
'Are you sure you want to transfer your license to this domain?',
134+
'Are you sure you want to undo the move?',
133135
'Ascending',
134136
'Assets',
135137
'Breadcrumbs',
@@ -235,6 +237,7 @@ private function _registerTranslations(View $view): void
235237
'More…',
236238
'Move down',
237239
'Move folder',
240+
'Move reverted.',
238241
'Move to the left',
239242
'Move to the right',
240243
'Move to',

src/web/assets/cp/dist/cp.js

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

src/web/assets/cp/dist/cp.js.map

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

src/web/assets/cp/src/js/AssetIndex.js

+34-25
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ Craft.AssetIndex = Craft.BaseElementIndex.extend(
8989
Garnish.$bod.addClass('dragging');
9090
this.itemDrag.$draggee.closest('tr,li').addClass('draggee');
9191
},
92-
onDragStop: () => {
92+
onDragStop: async () => {
9393
Garnish.$bod.removeClass('dragging');
9494

9595
const $draggee = this.itemDrag.$draggee;
@@ -115,30 +115,39 @@ Craft.AssetIndex = Craft.BaseElementIndex.extend(
115115
});
116116

117117
const mover = new Craft.AssetMover();
118-
mover
119-
.moveFolders(folderIds, targetFolderId)
120-
.then((totalFoldersMoved) => {
121-
mover
122-
.moveAssets(assetIds, targetFolderId)
123-
.then((totalAssetsMoved) => {
124-
const totalItemsMoved =
125-
totalFoldersMoved + totalAssetsMoved;
126-
if (totalItemsMoved) {
127-
Craft.cp.displayNotice(
128-
Craft.t(
129-
'app',
130-
'{totalItems, plural, =1{Item} other{Items}} moved.',
131-
{
132-
totalItems: totalItemsMoved,
133-
}
134-
)
135-
);
136-
Craft.elementIndex.updateElements(true);
137-
} else {
138-
$draggee.closest('tr,li').removeClass('draggee');
139-
}
140-
});
141-
});
118+
119+
const moveParams = await mover.getMoveParams(folderIds, assetIds);
120+
if (!moveParams.proceed) {
121+
$draggee.closest('tr,li').removeClass('draggee');
122+
return;
123+
}
124+
125+
const totalFoldersMoved = await mover.moveFolders(
126+
folderIds,
127+
targetFolderId,
128+
this.currentFolderId
129+
);
130+
const totalAssetsMoved = await mover.moveAssets(
131+
assetIds,
132+
targetFolderId,
133+
this.currentFolderId
134+
);
135+
const totalItemsMoved = totalFoldersMoved + totalAssetsMoved;
136+
if (totalItemsMoved) {
137+
mover.successNotice(
138+
moveParams,
139+
Craft.t(
140+
'app',
141+
'{totalItems, plural, =1{Item} other{Items}} moved.',
142+
{
143+
totalItems: totalItemsMoved,
144+
}
145+
)
146+
);
147+
Craft.elementIndex.updateElements(true);
148+
} else {
149+
$draggee.closest('tr,li').removeClass('draggee');
150+
}
142151
},
143152
});
144153

0 commit comments

Comments
 (0)