Repository: directus/directus
File: app/src/utils/upload-files.ts (TypeScript)

Code before:
import { i18n } from '@/lang';
import { useServerStore } from '@/stores/server';
import { notify } from '@/utils/notify';
import { uploadFile } from '@/utils/upload-file';
import { unexpectedError } from './unexpected-error';
import type { File } from '@directus/types';
import PQueue from 'p-queue';
import type { Upload } from 'tus-js-client';

export async function uploadFiles(
	files: globalThis.File[],
	options?: {
		onProgressChange?: (percentages: number[]) => void;
		onChunkedUpload?: (controllers: (Upload | null)[]) => void;
		notifications?: boolean;
		preset?: Record<string, any>;
		folder?: string;
	},
): Promise<(File | undefined)[]> {
	const progressHandler = options?.onProgressChange || (() => undefined);
	const progressForFiles = files.map(() => 0);
	const uploadControllers: (Upload | null)[] = Array(files.length).fill(null);
	const serverStore = useServerStore();
	const maxParallelUploads = serverStore.info.uploads?.maxParallel ?? 0;
	const uploadQueue = maxParallelUploads > 0 ? new PQueue({ concurrency: maxParallelUploads }) : null;

	const startUpload = (file: globalThis.File, index: number) =>
		uploadFile(file, {
			...options,
			onProgressChange: (percentage: number) => {
				progressForFiles[index] = percentage;
				progressHandler(progressForFiles);
			},
			onChunkedUpload: (controller: Upload) => {
				uploadControllers[index] = controller;
				options?.onChunkedUpload?.(uploadControllers);
			},
		});

	try {
		const uploadedFiles = (
			maxParallelUploads === 0
				? await Promise.all(files.map((file, index) => startUpload(file, index)))
				: await Promise.all(files.map((file, index) => uploadQueue!.add(() => startUpload(file, index))))
		).filter((v) => v);

		if (options?.notifications) {
			notify({
				title: i18n.global.t('upload_files_success', { count: files.length }),
			});

Review comment (suggestion):
Let's always use the queue for a consistent usage lower down, as concurrency defaults to infinity it should have no impact. e.g.
```suggestion
    const queueOptions:Options<any, QueueAddOptions> = {};

		if(options?.maxParallel){
			queueOptions.concurrency = options?.maxParallel
		}
		
	 const uploadQueue = new PQueue(queueOptions);
```

Code after:
import type { File } from '@directus/types';
import PQueue from 'p-queue';
import type { Upload } from 'tus-js-client';
import { unexpectedError } from './unexpected-error';
import { i18n } from '@/lang';
import { notify } from '@/utils/notify';
import { uploadFile } from '@/utils/upload-file';

export async function uploadFiles(
	files: globalThis.File[],
	options?: {
		onProgressChange?: (percentages: number[]) => void;
		onChunkedUpload?: (controllers: (Upload | null)[]) => void;
		notifications?: boolean;
		preset?: Record<string, any>;
		folder?: string;
		maxConcurrency?: number;
	},
): Promise<(File | undefined)[]> {
	const progressHandler = options?.onProgressChange || (() => undefined);
	const progressForFiles = files.map(() => 0);
	const uploadControllers: (Upload | null)[] = Array(files.length).fill(null);

	const uploadQueue = new PQueue({
		concurrency: options?.maxConcurrency && options.maxConcurrency > 0 ? options.maxConcurrency : Infinity,
	});

	const startUpload = (file: globalThis.File, index: number) =>
		uploadFile(file, {
			...options,
			onProgressChange: (percentage: number) => {
				progressForFiles[index] = percentage;
				progressHandler(progressForFiles);
			},
			onChunkedUpload: (controller: Upload) => {
				uploadControllers[index] = controller;
				options?.onChunkedUpload?.(uploadControllers);
			},
		});

	try {
		const uploadedFiles = (
			await Promise.all(
				files.map((file, index) => uploadQueue.add(() => startUpload(file, index), { throwOnTimeout: true })),
			)
		).filter((v) => v);

		if (options?.notifications) {
			notify({
				title: i18n.global.t('upload_files_success', { count: files.length }),