Fix Download button in resource dictionary creation not working 13/143513/1
authorFiete Ostkamp <fiete.ostkamp@telekom.de>
Thu, 5 Mar 2026 12:31:08 +0000 (13:31 +0100)
committerFiete Ostkamp <fiete.ostkamp@telekom.de>
Thu, 5 Mar 2026 12:32:57 +0000 (13:32 +0100)
- add functionality to save the ui state as a json file to
  the local machine

Issue-ID: CCSDK-4174
Change-Id: Ifb65ce3a74dc01e880a07d96261da49dd6b2b6de
Signed-off-by: Fiete Ostkamp <fiete.ostkamp@telekom.de>
cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.html
cds-ui/designer-client/src/app/modules/feature-modules/resource-dictionary/resource-dictionary-creation/resource-dictionary-creation.component.ts
cds-ui/e2e-playwright/tests/resource-dictionary.spec.ts

index 00d6e31..722688f 100644 (file)
@@ -50,7 +50,7 @@
                         <span>Clone</span>
                     </button>
 
-                    <a class="action-button">
+                    <a class="action-button" (click)="downloadDictionary()">
                         <i class="icon-download" aria-hidden="true"></i>
                         <span>Download</span>
                     </a>
             </div>
         </div>
     </div>
-</div>
\ No newline at end of file
+</div>
index 8eb126d..fbe5b08 100644 (file)
@@ -26,6 +26,7 @@ import { DictionaryMetadataComponent } from './dictionary-metadata/dictionary-me
 import { SourcesTemplateComponent } from './sources-template/sources-template.component';
 import { DictionaryCreationService } from './dictionary-creation.service';
 import { ToastrService } from 'ngx-toastr';
+import { saveAs } from 'file-saver';
 
 @Component({
   selector: 'app-resource-dictionary-creation',
@@ -92,6 +93,17 @@ export class ResourceDictionaryCreationComponent implements OnInit {
     // this.sourcesTemplateComponent.saveSorcesDataToStore();
   }
 
+  downloadDictionary() {
+    this.metadataTabComponent.saveMetaDataToStore();
+    this.dictionaryCreationStore.state$.subscribe(state => {
+      const metadata = state.metaData;
+      const blob = new Blob([JSON.stringify(metadata, null, 2)], { type: 'application/json' });
+      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
+      const baseName = (metadata && metadata.name) ? metadata.name : 'dictionary';
+      saveAs(blob, baseName + '-' + timestamp + '.json');
+    }).unsubscribe();
+  }
+
   goBackToDashBorad() {
     this.router.navigate(['/resource-dictionary']);
   }
index f66e352..2bf91aa 100644 (file)
@@ -217,3 +217,38 @@ test.describe('Resource Dictionary – create then list', () => {
         await expect(cards).toHaveCount(4);
     });
 });
+
+test.describe('Resource Dictionary – download dictionary', () => {
+    test('Download button triggers a JSON file download with timestamp in filename', async ({ page }) => {
+        // Navigate to the create dictionary page
+        await page.goto('/#/resource-dictionary/createDictionary');
+        await page.waitForLoadState('networkidle');
+
+        // Verify we are on the create dictionary page
+        await expect(page).toHaveURL(/createDictionary/);
+
+        // Locate the Download button
+        const downloadBtn = page.locator('a.action-button', { hasText: 'Download' });
+        await expect(downloadBtn).toBeVisible({ timeout: 10_000 });
+
+        // Listen for download event before clicking
+        const [download] = await Promise.all([
+            page.waitForEvent('download', { timeout: 15_000 }),
+            downloadBtn.click(),
+        ]);
+
+        // Verify the downloaded file has a .json extension and contains a timestamp pattern
+        const fileName = download.suggestedFilename();
+        expect(fileName).toMatch(/\.json$/);
+        // Timestamp pattern: YYYY-MM-DDTHH-MM-SS-mmmZ
+        expect(fileName).toMatch(/\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}/);
+
+        // Verify the file content is valid JSON
+        const filePath = await download.path();
+        if (filePath) {
+            const fs = require('fs');
+            const content = fs.readFileSync(filePath, 'utf-8');
+            expect(() => JSON.parse(content)).not.toThrow();
+        }
+    });
+});