Skip to content

Commit b0c4425

Browse files
added new support for extensions
1 parent e87da79 commit b0c4425

File tree

7 files changed

+152
-6
lines changed

7 files changed

+152
-6
lines changed

ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/_cq_dialog/.content.xml

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
jcr:primaryType="nt:unstructured"
1919
jcr:title="Adaptive Form File Attachment"
2020
sling:resourceType="cq/gui/components/authoring/dialog"
21-
extraClientlibs="[core.forms.components.fileinput.v1.editor]"
21+
extraClientlibs="[core.forms.components.fileinput.v3.editor]"
2222
helpPath="https://www.adobe.com/go/aem_af_cmp_fileinput_v2"
2323
trackingFeature="core-components:adaptiveform-fileinput:v2">
2424
<content
@@ -98,7 +98,19 @@
9898
jcr:primaryType="nt:unstructured"
9999
sling:resourceType="granite/ui/components/coral/foundation/container">
100100
<items jcr:primaryType="nt:unstructured">
101+
<mimeType
102+
wrapperClass="cmp-adaptiveform-fileinput__mimeType"
103+
jcr:primaryType="nt:unstructured"
104+
sling:resourceType="fd/af/authoring/components/granite/form/formsmultifield"
105+
fieldLabel="Allowed file types"
106+
defaultValue="">
107+
<field
108+
name="./accept"
109+
jcr:primaryType="nt:unstructured"
110+
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"/>
111+
</mimeType>
101112
<extensions
113+
wrapperClass="cmp-adaptiveform-fileinput__extensions"
102114
jcr:primaryType="nt:unstructured"
103115
sling:resourceType="fd/af/authoring/components/granite/form/formsmultifield"
104116
fieldLabel="Allowed file extensions"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
3+
jcr:primaryType="sling:Folder"/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
3+
jcr:primaryType="cq:ClientLibraryFolder"
4+
categories="[core.forms.components.fileinput.v3.editor]"
5+
jsProcessor="[default:none,min:gcc;languageIn=ECMASCRIPT_2021;languageOut=ECMASCRIPT_2021]"
6+
dependencies="[core.forms.components.base.v1.editor, core.forms.components.commons.v1.editor.utils]"/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
###############################################################################
2+
# Copyright 2025 Adobe
3+
#
4+
# Licensed under the Apache License, Version 2.0 (the "License");
5+
# you may not use this file except in compliance with the License.
6+
# You may obtain a copy of the License at
7+
#
8+
# http://www.apache.org/licenses/LICENSE-2.0
9+
#
10+
# Unless required by applicable law or agreed to in writing, software
11+
# distributed under the License is distributed on an "AS IS" BASIS,
12+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
# See the License for the specific language governing permissions and
14+
# limitations under the License.
15+
###############################################################################
16+
17+
#base=js
18+
editDialog.js
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*******************************************************************************
2+
* Copyright 2025 Adobe
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
******************************************************************************/
16+
(function($) {
17+
"use strict";
18+
let EDIT_DIALOG = ".cmp-adaptiveform-fileinput__editdialog",
19+
FILEINPUT_MIMETYPE = EDIT_DIALOG + " .cmp-adaptiveform-fileinput__mimeType",
20+
FILEINPUT_EXTENSIONS = EDIT_DIALOG + " .cmp-adaptiveform-fileinput__extensions",
21+
Utils = window.CQ.FormsCoreComponents.Utils.v1;
22+
23+
function handleMimeType(dialog) {
24+
let mimeTypeWrapper = dialog.find(FILEINPUT_MIMETYPE);
25+
let mimeTypeField = mimeTypeWrapper.find("coral-multifield");
26+
let extensionsField = dialog.find(FILEINPUT_EXTENSIONS + " coral-multifield");
27+
28+
function updateMimeTypeState() {
29+
let hasExtensions = extensionsField.find('coral-multifield-item').length > 0;
30+
31+
// Disable the entire multifield and its contents
32+
mimeTypeField.css({
33+
'pointer-events': hasExtensions ? 'none' : 'auto',
34+
'opacity': hasExtensions ? '0.5' : '1'
35+
});
36+
mimeTypeField.prop('disabled', hasExtensions);
37+
38+
// Disable delete icons and their SVGs
39+
mimeTypeField.find('coral-icon[icon="delete"], ._coral-Icon--svg').css({
40+
'pointer-events': hasExtensions ? 'none' : 'auto'
41+
});
42+
43+
// Handle MIME type items if extensions exist
44+
if (hasExtensions) {
45+
// Keep first item, remove others
46+
let firstItem = mimeTypeField.find('coral-multifield-item').first();
47+
mimeTypeField.find('coral-multifield-item:not(:first)').remove();
48+
49+
// Set value of first item to */*
50+
firstItem.find('input').val('*/*');
51+
}
52+
}
53+
54+
// Watch for changes in both fields
55+
extensionsField.on('change', updateMimeTypeState);
56+
mimeTypeField.on('change', updateMimeTypeState);
57+
58+
// Check initial state without triggering events
59+
let hasExtensions = extensionsField.find('coral-multifield-item').length > 0;
60+
if (hasExtensions) {
61+
mimeTypeField.css({
62+
'pointer-events': 'none',
63+
'opacity': '0.5'
64+
});
65+
mimeTypeField.prop('disabled', true);
66+
mimeTypeField.find('coral-icon[icon="delete"], ._coral-Icon--svg').css({
67+
'pointer-events': 'none'
68+
});
69+
}
70+
}
71+
72+
$(document).on('dialog-loaded', EDIT_DIALOG, function(e) {
73+
handleMimeType($(this));
74+
});
75+
76+
Utils.initializeEditDialog(EDIT_DIALOG)(handleMimeType);
77+
78+
})(jQuery);

ui.frontend/src/view/FormFileInputWidgetBase.js

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,10 +85,12 @@ class FormFileInputWidgetBase {
8585
// initialize the regex initially
8686
this.regexMimeTypeList = this.options.accept.map(function (value, i) {
8787
try {
88+
// Special case for */* to match all MIME types
89+
if (value.trim() === '*/*') {
90+
return /.*/; // Match any MIME type
91+
}
8892
return new RegExp(value.trim());
8993
} catch (e) {
90-
// failure during regex parsing, don't return anything specific to this value since the value contains
91-
// incorrect regex string
9294
if (window.console) {
9395
console.log(e);
9496
}
@@ -470,8 +472,11 @@ class FormFileInputWidgetBase {
470472
let mimeType = file.type || self.extensionToMimeTypeMap[extension];
471473

472474
// If no MIME type is detected, check if the file extension is in the accept list
473-
if (!mimeType) {
475+
if (!mimeType && this.options.acceptExtensions) {
474476
isMatch = this.options.acceptExtensions.some(function(acceptPattern) {
477+
if(!acceptPattern) {
478+
return false;
479+
}
475480
// Remove leading dot if present and convert to lowercase
476481
let cleanPattern = acceptPattern.replace(/^\./, '').toLowerCase();
477482
return cleanPattern === extension;

ui.tests/test-module/specs/fileinput/fileinput.authoring.cy.js

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,28 @@ describe('Page - Authoring', function () {
101101
it ('open edit dialog of FileInput', function(){
102102
testFileInputBehaviour(fileInputEditPathSelector, fileInputDrop);
103103
})
104+
105+
it('verify mime type is disabled when extensions are present', function() {
106+
// Setup component
107+
dropFileInputInContainer();
108+
cy.openEditableToolbar(sitesSelectors.overlays.overlay.component + fileInputEditPathSelector);
109+
cy.invokeEditableAction("[data-action='CONFIGURE']");
110+
111+
// Add an extension
112+
cy.get('.cmp-adaptiveform-fileinput__extensions coral-multifield-add').click();
113+
cy.get('.cmp-adaptiveform-fileinput__extensions input').first().type('.pdf');
114+
115+
// Verify MIME type is disabled and has single */* value
116+
cy.get('.cmp-adaptiveform-fileinput__mimeType coral-multifield')
117+
.should('have.css', 'pointer-events', 'none')
118+
.find('coral-multifield-item')
119+
.should('have.length', 1)
120+
.find('input')
121+
.should('have.value', '*/*');
122+
123+
cy.get('.cq-dialog-cancel').click();
124+
cy.deleteComponentByPath(fileInputDrop);
125+
});
104126
})
105127

106128
context('Open Sites Editor', function () {
@@ -123,8 +145,10 @@ describe('Page - Authoring', function () {
123145
testFileInputBehaviour(fileInputEditPathSelector, fileInputDrop, true);
124146
});
125147

126-
it('open edit dialog of aem forms FileInput and check validation', function() {
127-
testFileInputValidationBehaviour(fileInputEditPathSelector, fileInputDrop, true);
148+
it('open edit dialog of aem forms FileInput and check validation', () => {
149+
if(toggle_array.includes("FT_FORMS-18927")) {
150+
testFileInputValidationBehaviour(fileInputEditPathSelector, fileInputDrop, true);
151+
}
128152
});
129153

130154
});

0 commit comments

Comments
 (0)