Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Mykola-Veryha/b1c6c09a26f4290967a8f0d1172e4c08 to your computer and use it in GitHub Desktop.

Select an option

Save Mykola-Veryha/b1c6c09a26f4290967a8f0d1172e4c08 to your computer and use it in GitHub Desktop.
Filament FilePond Validation Plugin
const FilePondPluginFilenameLengthValidation = ({ addFilter, utils }) => {
const { Type } = utils;
function validateFile(file, maxLength, errorMessage) {
return file.name?.length > maxLength
? { status: { main: errorMessage.replace('{maxLength}', maxLength), sub: '' }}
: true;
}
addFilter('ALLOW_FILE', (file, { query }) => {
return validateFile(file, query('GET_MAX_FILENAME_LENGTH'), query('GET_MAX_FILENAME_LENGTH_EXCEEDED'));
});
addFilter('LOAD_FILE', (file, { query }) => {
// The query transforms the name using `GET_${fromCamels(key, '_').toUpperCase()}`,
// which corresponds to the maxFilenameLength value.
const result = validateFile(file, query('GET_MAX_FILENAME_LENGTH'), query('GET_MAX_FILENAME_LENGTH_EXCEEDED'));
// If validation fails, reject the file. Otherwise, continue with the file
return result !== true ? Promise.reject(result) : Promise.resolve(file);
});
return {
options: {
maxFilenameLength: [null, Type.INT],
maxFilenameLengthExceeded: ['', Type.STRING],
},
};
};
const FilePondPluginFilenameRegexValidation = ({ addFilter, utils }) => {
const { Type } = utils;
function validateFile(file, filenameRegex, errorMessage) {
// Extract filename without extension
const lastDotIndex = file.name.lastIndexOf('.');
const filenameWithoutExt = lastDotIndex !== -1 ? file.name.substring(0, lastDotIndex) : file.name;
return !(new RegExp(filenameRegex)).test(filenameWithoutExt)
? { status: { main: errorMessage, sub: '' } }
: true;
}
addFilter('ALLOW_FILE', (file, { query }) => {
return validateFile(file, query('GET_FILENAME_REGEX'), query('GET_FILENAME_REGEX_FAILS'));
});
addFilter('LOAD_FILE', (file, { query }) => {
const result = validateFile(file, query('GET_FILENAME_REGEX'), query('GET_FILENAME_REGEX_FAILS'));
// If validation fails, reject the file. Otherwise, continue with the file
return result !== true ? Promise.reject(result) : Promise.resolve(file);
});
return {
options: {
filenameRegex: ['', Type.STRING],
filenameRegexFails: ['', Type.STRING],
},
};
};
document.addEventListener('FilePond:loaded', (event) => {
const { registerPlugin, setOptions } = event.detail;
registerPlugin(FilePondPluginFilenameLengthValidation);
registerPlugin(FilePondPluginFilenameRegexValidation);
setOptions({
labelMaxFileSizeExceeded: 'The file is too large. Maximum file size is 100MB',
labelFileTypeNotAllowed: 'File of invalid type',
maxFilenameLengthExceeded: 'The file name exceeds the maximum character limit. Please rename your file and ensure it is no longer than {maxLength} characters.',
filenameRegexFails: 'The filename contains invalid characters. Please use only letters, numbers, underscores.',
});
});
document.addEventListener('FilePond:init', (event) => {
const { pond } = event.detail;
const fileUploadElement = event.target?.closest('.fi-fo-file-upload');
const maxFilenameLength = fileUploadElement?.dataset?.maxFilenameLength;
if (maxFilenameLength) {
pond.setOptions({ maxFilenameLength });
} else {
console.warn('Warning: "data-max-filename-length" attribute is not set. Please check your field configuration.');
}
const filenameRegex = fileUploadElement?.dataset?.filenameRegex;
if (filenameRegex) {
pond.setOptions({ filenameRegex });
} else {
console.warn('Warning: "data-filename-regex" attribute is not set. Please check your field configuration.');
}
function addInProgressClass() {
const fileStatusMain = document.querySelector('.filepond--file-status-main');
if (fileStatusMain) {
const isUploading = fileStatusMain.textContent.toLocaleLowerCase().includes('uploading');
const isUploadComplete = fileStatusMain.textContent.toLocaleLowerCase().includes('upload complete');
fileStatusMain.classList.toggle('in-progress', isUploading);
fileStatusMain.classList.toggle('complete', isUploadComplete);
fileStatusMain.classList.toggle('empty', !fileStatusMain.innerHTML.trim());
}
}
function resizeFilepondRoot() {
const fileStatus = document.querySelector('.filepond--file-status');
const filepondRootWrapper = document.querySelector('.filepond--root:has(.filepond--item)')?.parentElement;
if (fileStatus && filepondRootWrapper) {
filepondRootWrapper.style.height = 'auto'; // Reset height to auto to calculate new height
const newHeight = filepondRootWrapper.offsetHeight + fileStatus.offsetHeight;
filepondRootWrapper.style.setProperty('height', newHeight + 'px');
fileStatus.querySelector('.filepond--file-status-main')
.style
.setProperty('bottom', `-${fileStatus.offsetHeight - 20}px`);
} else {
// Reset the height when there's no file status message
const wrapper = document.querySelector('.filepond--root')?.parentElement;
if (wrapper) {
wrapper.style.height = 'auto';
}
}
}
const observer = new MutationObserver(() => {
addInProgressClass();
resizeFilepondRoot();
});
const filepondRoot = document.querySelector('.filepond--root');
if (filepondRoot) {
observer.observe(filepondRoot, { childList: true, subtree: true });
}
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment