Skip to content

Commit 84b2898

Browse files
Merge pull request #1689 from adobe/DevToMaster1208
DevToMaster1208
2 parents 6b71ab6 + 0bdb606 commit 84b2898

File tree

10 files changed

+304
-49
lines changed

10 files changed

+304
-49
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
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" xmlns:rep="internal"
3+
jcr:mixinTypes="[rep:AccessControllable]"
4+
jcr:primaryType="sling:Folder"
5+
lcFolder="{Long}0"
6+
type="lcFolder"
7+
/>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:dam="http://www.day.com/dam/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0" xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:fd="http://www.adobe.com/aemfd/fd/1.0"
3+
jcr:primaryType="dam:Asset">
4+
<jcr:content
5+
jcr:lastModified="{Date}2023-01-25T17:24:29.344+05:30"
6+
jcr:primaryType="dam:AssetContent"
7+
sling:resourceType="fd/fm/af/render"
8+
guide="1"
9+
type="guide">
10+
<metadata
11+
fd:version="2.1"
12+
jcr:primaryType="nt:unstructured"
13+
allowedRenderFormat="HTML"
14+
author="admin"
15+
availableInMobileApp="{Boolean}false"
16+
dorTemplateChanged="Boolean"
17+
dorType="none"
18+
formmodel="none"
19+
hasCustomThumbnail="{Boolean}false"
20+
themeRef="/libs/fd/af/themes/canvas"
21+
title="Adaptive Form V4 (IT)"/>
22+
</jcr:content>
23+
</jcr:root>

it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/datepicker/basic/.content.xml

Lines changed: 53 additions & 34 deletions
Large diffs are not rendered by default.

it/content/src/main/content/jcr_root/content/forms/af/core-components-it/samples/fileinput/fileinputv4/basic/.content.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
jcr:lastModifiedBy="admin"
3030
jcr:primaryType="nt:unstructured"
3131
jcr:title="File Input - 1"
32-
sling:resourceType="core/fd/components/form/fileinput/v3/fileinput"
32+
sling:resourceType="core/fd/components/form/fileinput/v4/fileinput"
3333
accept="[audio/*, video/*, image/*, text/*, application/pdf]"
3434
buttonText="Attach Files"
3535
enabled="{Boolean}true"
@@ -43,15 +43,15 @@
4343
<fileinput2
4444
jcr:primaryType="nt:unstructured"
4545
jcr:title="File Input - 2"
46-
sling:resourceType="core/fd/components/form/fileinput/v3/fileinput"
46+
sling:resourceType="core/fd/components/form/fileinput/v4/fileinput"
4747
accept="[audio/*, video/*, image/*, text/*, application/pdf]"
4848
fieldType="file-input"
4949
name="fileinput2"
5050
type="file"/>
5151
<fileinput3
5252
jcr:primaryType="nt:unstructured"
5353
jcr:title="File Input - 3"
54-
sling:resourceType="core/fd/components/form/fileinput/v3/fileinput"
54+
sling:resourceType="core/fd/components/form/fileinput/v4/fileinput"
5555
accept="[application/pdf]"
5656
description="This is long description"
5757
fieldType="file-input"
@@ -63,7 +63,7 @@
6363
<fileinput4
6464
jcr:primaryType="nt:unstructured"
6565
jcr:title="File Input - 4"
66-
sling:resourceType="core/fd/components/form/fileinput/v3/fileinput"
66+
sling:resourceType="core/fd/components/form/fileinput/v4/fileinput"
6767
accept="[application/x-msdownload,application/vnd.ms-outlook,application/pdf]"
6868
description="This is long description"
6969
fieldType="file-input"
@@ -77,7 +77,7 @@
7777
jcr:lastModifiedBy="admin"
7878
jcr:primaryType="nt:unstructured"
7979
jcr:title="File Input - 5"
80-
sling:resourceType="core/fd/components/form/fileinput/v3/fileinput"
80+
sling:resourceType="core/fd/components/form/fileinput/v4/fileinput"
8181
accept="[audio/*, video/*, image/*, text/*, application/pdf]"
8282
buttonText="Attach Files"
8383
enabled="{Boolean}true"
@@ -91,7 +91,7 @@
9191
<fileinput6
9292
jcr:primaryType="nt:unstructured"
9393
jcr:title="File Input - 6"
94-
sling:resourceType="core/fd/components/form/fileinput/v3/fileinput"
94+
sling:resourceType="core/fd/components/form/fileinput/v4/fileinput"
9595
accept="[audio/*, video/*, image/*, text/*, application/pdf]"
9696
buttonText="Attach Files"
9797
enabled="{Boolean}true"

ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/datepicker/v1/datepicker/clientlibs/site/js/datepickerwidget.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1209,10 +1209,25 @@ if (typeof window.DatePickerWidget === 'undefined') {
12091209
// If value is already a Date object and it's valid, use it as is
12101210
currDate = value;
12111211
} else {
1212-
// Otherwise, construct a new Date object
1213-
currDate = new Date(value);
1214-
const timezoneOffset = currDate.getTimezoneOffset();
1215-
currDate.setMinutes(currDate.getMinutes() + timezoneOffset);
1212+
// Check if value is empty
1213+
if (!value || value.trim() === '') {
1214+
currDate = new Date();
1215+
} else {
1216+
let displayFormat = this.#model._jsonModel?.displayFormat;
1217+
// If displayFormat is null/undefined, use default parsing
1218+
if (!displayFormat) {
1219+
currDate = new Date(value);
1220+
} else {
1221+
// Use FormView.Formatters.parseDate for custom formats
1222+
currDate = FormView.Formatters.parseDate(value, this.#lang || 'en', displayFormat);
1223+
// If parseDate failed (returned null), fallback to default parsing
1224+
if (currDate === null) {
1225+
currDate = new Date(value);
1226+
}
1227+
const timezoneOffset = currDate.getTimezoneOffset();
1228+
currDate.setMinutes(currDate.getMinutes() + timezoneOffset);
1229+
}
1230+
}
12161231
}
12171232

12181233
if (!isNaN(currDate) && value != null) {
@@ -1223,7 +1238,7 @@ if (typeof window.DatePickerWidget === 'undefined') {
12231238
} else {
12241239
this.selectedYear
12251240
= this.selectedMonth
1226-
= this.selectedYear
1241+
= this.selectedDay
12271242
= -1;
12281243
}
12291244
if (this.#curInstance != null) {
@@ -1257,5 +1272,4 @@ if (typeof window.DatePickerWidget === 'undefined') {
12571272
}
12581273

12591274
}
1260-
1261-
}
1275+
}

ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v3/fileinput/clientlibs/site/js/fileinputwidget.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,5 +89,40 @@ if (typeof window.FileInputWidget === 'undefined') {
8989
fileItem.appendChild(fileEndContainer);
9090
return fileItem;
9191
}
92+
93+
handleClick (event){
94+
let elem = event.target,
95+
text = elem.parentElement.previousSibling.textContent,
96+
index = this.getIndexOfText(text, elem.parentElement),
97+
url = elem.parentElement.previousSibling.dataset.key,
98+
objectUrl = elem.parentElement.previousSibling.dataset.objectUrl;
99+
if (index !== -1) {
100+
this.values.splice(index, 1);
101+
this.fileArr.splice(index, 1);
102+
// set the model with the new value
103+
this.model.value = this.fileArr;
104+
// value and fileArr contains items of both URL and file types, hence while removing from DOM
105+
// get the correct index as per this.#widget.files
106+
let domIndex = Array.from(this.widget.files).findIndex(function(file) {
107+
return file.name === text;
108+
});
109+
this.deleteFilesFromInputDom([domIndex]);
110+
if (url != null) {
111+
// remove the data so that others don't use this url
112+
delete elem.parentElement.previousSibling.dataset.key;
113+
}
114+
if(objectUrl) {
115+
// revoke the object URL to avoid memory leaks in browser
116+
// since file is anyways getting deleted, remove the object URL's too
117+
window.URL.revokeObjectURL(objectUrl);
118+
}
119+
}
120+
// Remove the dom from view
121+
//All bound events and jQuery data associated with the element are also removed
122+
elem.parentElement.parentElement.remove();
123+
// Set the focus on file upload button after click of close
124+
this.widget.focus();
125+
126+
}
92127
}
93128
}

ui.af.apps/src/main/content/jcr_root/apps/core/fd/components/form/fileinput/v4/fileinput/clientlibs/site/js/fileinputwidget.js

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,5 +188,40 @@ if (typeof window.FileInputWidget === 'undefined') {
188188
};
189189
return messages[invalidFeature];
190190
}
191+
192+
handleClick (event){
193+
let elem = event.target,
194+
text = elem.parentElement.previousSibling.textContent,
195+
index = this.getIndexOfText(text, elem.parentElement),
196+
url = elem.parentElement.previousSibling.dataset.key,
197+
objectUrl = elem.parentElement.previousSibling.dataset.objectUrl;
198+
if (index !== -1) {
199+
this.values.splice(index, 1);
200+
this.fileArr.splice(index, 1);
201+
// set the model with the new value
202+
this.model.value = this.fileArr;
203+
// value and fileArr contains items of both URL and file types, hence while removing from DOM
204+
// get the correct index as per this.#widget.files
205+
let domIndex = Array.from(this.widget.files).findIndex(function(file) {
206+
return file.name === text;
207+
});
208+
this.deleteFilesFromInputDom([domIndex]);
209+
if (url != null) {
210+
// remove the data so that others don't use this url
211+
delete elem.parentElement.previousSibling.dataset.key;
212+
}
213+
if(objectUrl) {
214+
// revoke the object URL to avoid memory leaks in browser
215+
// since file is anyways getting deleted, remove the object URL's too
216+
window.URL.revokeObjectURL(objectUrl);
217+
}
218+
}
219+
// Remove the dom from view
220+
//All bound events and jQuery data associated with the element are also removed
221+
elem.parentElement.parentElement.remove();
222+
// Set the focus on file upload button after click of close
223+
this.widget.focus();
224+
225+
}
191226
}
192227
}

ui.tests/test-module/specs/datepicker/datepicker.runtime.cy.js

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,9 @@ describe("Form Runtime with Date Picker", () => {
415415

416416
cy.get(`#${datePicker7}`).find("input").should("have.attr", "type", "text"); // Custom format uses text input
417417
cy.get(`#${datePicker7}`).find(".cmp-adaptiveform-datepicker__calendar-icon").should("have.attr", "tabindex", "0");
418-
cy.get(`#${datePicker7}`).find("input").focus().tab();
418+
419+
// Test that calendar icon can be focused and activated
420+
cy.get(`#${datePicker7}`).find(".cmp-adaptiveform-datepicker__calendar-icon").focus();
419421
cy.focused().should("have.class", "cmp-adaptiveform-datepicker__calendar-icon");
420422
cy.focused().type("{enter}");
421423
cy.get(".datetimepicker").should("be.visible");
@@ -442,6 +444,7 @@ describe("Form Runtime with Date Picker", () => {
442444
cy.get(`#${datePicker7}`).find(".cmp-adaptiveform-datepicker__calendar-icon").focus().type("{enter}");
443445
cy.get(".datetimepicker").should("be.visible");
444446
cy.get("body").type("{esc}");
447+
});
445448

446449
// Mobile Touch Functionality Tests
447450
describe("Mobile Touch Functionality", () => {
@@ -510,4 +513,95 @@ describe("Form Runtime with Date Picker", () => {
510513
})
511514
});
512515
});
513-
})
516+
it("Test dd/MM/yyyy format - verify July is highlighted for 03/07/2025", () => {
517+
// Test the datepicker component configured with dd/MM/yyyy format
518+
519+
let targetDatepicker = null;
520+
let targetModel = null;
521+
522+
// Find the datepicker with dd/MM/yyyy format
523+
cy.wrap(null).then(() => {
524+
for (const [fieldId, fieldView] of Object.entries(formContainer._fields)) {
525+
const model = fieldView.getModel();
526+
if (model && model._jsonModel && model._jsonModel.displayFormat === "dd/MM/yyyy") {
527+
targetDatepicker = fieldId;
528+
targetModel = model;
529+
cy.log(`Found dd/MM/yyyy datepicker: ${fieldId}`);
530+
break;
531+
}
532+
}
533+
534+
// Log all available datepickers for debugging
535+
if (!targetDatepicker) {
536+
cy.log("Available datepickers:");
537+
Object.entries(formContainer._fields).forEach(([id, field]) => {
538+
const model = field.getModel();
539+
const displayFormat = model._jsonModel?.displayFormat;
540+
cy.log(`- ${id}: displayFormat = ${displayFormat}`);
541+
});
542+
}
543+
});
544+
545+
// Only proceed if we found the datepicker
546+
cy.then(() => {
547+
if (!targetDatepicker) {
548+
cy.log("No datepicker with dd/MM/yyyy format found. Skipping test.");
549+
return;
550+
}
551+
552+
// Test the main bug: "03/07/2025" should show July, not March
553+
cy.get(`#${targetDatepicker}`).should('exist').then(() => {
554+
555+
const testDate = "03/07/2025"; // 3rd July 2025
556+
557+
cy.log(`Testing: ${testDate} (should be July 2025, NOT March 2025)`);
558+
559+
// Enter the date
560+
cy.get(`#${targetDatepicker}`).find("input").clear().type(testDate).blur();
561+
562+
// Check model value
563+
cy.wrap(null).then(() => {
564+
if (targetModel) {
565+
const modelValue = targetModel.getState().value;
566+
cy.log(`Model value: ${modelValue}`);
567+
568+
// Should be 2025-07-03 (July), not 2025-03-07 (March)
569+
if (modelValue === "2025-07-03") {
570+
cy.log("SUCCESS: Model correctly stores July");
571+
} else if (modelValue === "2025-03-07") {
572+
cy.log("BUG: Model incorrectly stores March");
573+
}
574+
}
575+
});
576+
577+
// Open calendar and check month
578+
cy.get(`#${targetDatepicker}`).find(".cmp-adaptiveform-datepicker__calendar-icon")
579+
.should('be.visible')
580+
.click({force: true});
581+
582+
cy.wait(1000);
583+
584+
// Check calendar month
585+
cy.get('body').then(($body) => {
586+
if ($body.find('.datetimepicker:visible').length > 0) {
587+
cy.get(".dp-caption").should("be.visible").then(($caption) => {
588+
const captionText = $caption.text();
589+
cy.log(`Calendar shows: ${captionText}`);
590+
591+
// Critical test: should show July, not March
592+
if (captionText.includes("July") && captionText.includes("2025")) {
593+
expect(captionText).to.include("July");
594+
} else if (captionText.includes("March")) {
595+
}
596+
});
597+
598+
// Close calendar
599+
cy.get("body").click(10, 10);
600+
} else {
601+
cy.log("Calendar widget not available");
602+
}
603+
});
604+
});
605+
});
606+
});
607+
});

ui.tests/test-module/specs/fileinput/fileinputv3.runtime.cy.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,20 @@ describe("Form with File Input V-3 - Basic Tests", () => {
173173
getFormObjTest(['empty.pdf', 'empty.pdf', 'empty.pdf', 'empty.pdf', 'empty.pdf'])
174174
});
175175

176+
it("check delete functionality of duplicate files", () => {
177+
let sampleFileNames = ['sample2.txt', 'sample.txt', 'sample2.txt'];
178+
const fileInput = "input[name='fileinput1']";
179+
180+
// Attach files
181+
cy.attachFile(fileInput, [sampleFileNames[0]]);
182+
cy.attachFile(fileInput, [sampleFileNames[1]]);
183+
cy.attachFile(fileInput, [sampleFileNames[2]]);
184+
185+
deleteSelectedFiles(fileInput, sampleFileNames);
186+
187+
cy.get('.cmp-adaptiveform-fileinput__fileitem').should('have.length', 0);
188+
});
189+
176190
it("should toggle description and tooltip", () => {
177191
cy.toggleDescriptionTooltip(bemBlock, 'fileinput_tooltip_scenario_test');
178192
})

ui.tests/test-module/specs/fileinput/fileinputv4.runtime.cy.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,20 @@ describe("Form with File Input V-4 - Basic Tests", () => {
181181
getFormObjTest(['empty.pdf', 'empty.pdf', 'empty.pdf', 'empty.pdf', 'empty.pdf'])
182182
});
183183

184+
it("check delete functionality of duplicate files", () => {
185+
let sampleFileNames = ['sample2.txt', 'sample.txt', 'sample2.txt'];
186+
const fileInput = "input[name='fileinput1']";
187+
188+
// Attach files
189+
cy.attachFile(fileInput, [sampleFileNames[0]]);
190+
cy.attachFile(fileInput, [sampleFileNames[1]]);
191+
cy.attachFile(fileInput, [sampleFileNames[2]]);
192+
193+
deleteSelectedFiles(fileInput, sampleFileNames);
194+
195+
cy.get('.cmp-adaptiveform-fileinput__fileitem').should('have.length', 0);
196+
});
197+
184198
it("should toggle description and tooltip", () => {
185199
cy.toggleDescriptionTooltip(bemBlock, 'fileinput_tooltip_scenario_test');
186200
});

0 commit comments

Comments
 (0)