From b141ca89835e2c5bb0a628c8f452d7dbd7ce49c6 Mon Sep 17 00:00:00 2001 From: vinoth-Kumar-S <31274282+vinoth-Kumar-S@users.noreply.github.com> Date: Wed, 13 Sep 2023 15:15:15 +0530 Subject: [PATCH] Adding Angular Diagram Save and Export video Adding Angular Diagram Save and Export video --- README.md | 32 ++++++++- angular.json | 100 ++++++++++++++++++++++++++ package.json | 42 +++++++++++ src/app/app.component.css | 7 ++ src/app/app.component.html | 127 ++++++++++++++++++++++++++++++++++ src/app/app.component.spec.ts | 27 ++++++++ src/app/app.component.ts | 93 +++++++++++++++++++++++++ src/app/app.module.ts | 22 ++++++ src/assets/images/Marker.png | Bin 0 -> 2899 bytes src/favicon.ico | Bin 0 -> 948 bytes src/index.html | 13 ++++ src/main.ts | 7 ++ src/styles.css | 6 ++ tsconfig.app.json | 14 ++++ tsconfig.json | 34 +++++++++ tsconfig.spec.json | 14 ++++ 16 files changed, 537 insertions(+), 1 deletion(-) create mode 100644 angular.json create mode 100644 package.json create mode 100644 src/app/app.component.css create mode 100644 src/app/app.component.html create mode 100644 src/app/app.component.spec.ts create mode 100644 src/app/app.component.ts create mode 100644 src/app/app.module.ts create mode 100644 src/assets/images/Marker.png create mode 100644 src/favicon.ico create mode 100644 src/index.html create mode 100644 src/main.ts create mode 100644 src/styles.css create mode 100644 tsconfig.app.json create mode 100644 tsconfig.json create mode 100644 tsconfig.spec.json diff --git a/README.md b/README.md index ddd07c4..2a5ecff 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,32 @@ -# how-to-save-and-export-an-Angular-diagram +# How to Save and Export an Angular Diagram + A quick start Angular project that shows how to save and export an Angular Diagram component. This project includes a code snippet to save and load the Diagram as a JSON string and file stream. It also includes a code snippet to export the Diagram in PNG format. + +The serialization documentation for the Syncfusion Angular Diagram component: +https://ej2.syncfusion.com/angular/documentation/diagram/serialization + +The print and export documentation for the Syncfusion Angular Diagram component: +https://ej2.syncfusion.com/angular/documentation/diagram/export + +Check out the online serialization example for the Angular Diagram component: +https://ej2.syncfusion.com/angular/demos/#/material3/diagram/serialization + +Check out the online export and print example for the Angular Diagram component: +https://ej2.syncfusion.com/angular/demos/#/material3/diagram/print-export + +Refer to this video for getting started with the Angular Diagram component: +https://www.youtube.com/watch?v=TObiS2Lj87U + +Refer to this video for creating and customizing nodes in the Angular Diagram component: +https://www.youtube.com/watch?v=OnI_SMaYLOk + +Refer to this video for adding and customizing connectors in the Angular Diagram component: +https://www.youtube.com/watch?v=fwK8CWWBwZ4 + +## Project prerequisites + +Make sure that you have the latest versions of NodeJS and Visual Studio Code in your machine before starting to work on this project. + +### How to run this application? + +To run this application, you need to clone the `how-to-save-and-export-an-Angular-diagram` repository and then open it in Visual Studio Code. Now, simply install all the necessary react packages into your current project using the `npm install` command and run your project using the `ng serve` command. diff --git a/angular.json b/angular.json new file mode 100644 index 0000000..5d52b4e --- /dev/null +++ b/angular.json @@ -0,0 +1,100 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "myangularproject": { + "projectType": "application", + "schematics": {}, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/myangularproject", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": [ + "zone.js" + ], + "tsConfig": "tsconfig.app.json", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "src/styles.css", + "./node_modules/@syncfusion/ej2-material-theme/styles/material.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "buildOptimizer": false, + "optimization": false, + "vendorChunk": true, + "extractLicenses": false, + "sourceMap": true, + "namedChunks": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "browserTarget": "myangularproject:build:production" + }, + "development": { + "browserTarget": "myangularproject:build:development" + } + }, + "defaultConfiguration": "development" + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "myangularproject:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "polyfills": [ + "zone.js", + "zone.js/testing" + ], + "tsConfig": "tsconfig.spec.json", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "src/styles.css", + "./node_modules/@syncfusion/ej2-material-theme/styles/material.css" + ], + "scripts": [] + } + } + } + } + } +} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..1c41385 --- /dev/null +++ b/package.json @@ -0,0 +1,42 @@ +{ + "name": "myangularproject", + "version": "0.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "ng test" + }, + "private": true, + "dependencies": { + "@angular/animations": "^16.0.0", + "@angular/common": "^16.0.0", + "@angular/compiler": "^16.0.0", + "@angular/core": "^16.0.0", + "@angular/forms": "^16.0.0", + "@angular/platform-browser": "^16.0.0", + "@angular/platform-browser-dynamic": "^16.0.0", + "@angular/router": "^16.0.0", + "@syncfusion/ej2-angular-buttons": "^22.2.9", + "@syncfusion/ej2-angular-diagrams": "^22.2.10", + "@syncfusion/ej2-angular-inputs": "^22.2.9", + "@syncfusion/ej2-material-theme": "*", + "rxjs": "~7.8.0", + "tslib": "^2.3.0", + "zone.js": "~0.13.0" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^16.0.4", + "@angular/cli": "~16.0.4", + "@angular/compiler-cli": "^16.0.0", + "@types/jasmine": "~4.3.0", + "jasmine-core": "~4.6.0", + "karma": "~6.4.0", + "karma-chrome-launcher": "~3.2.0", + "karma-coverage": "~2.2.0", + "karma-jasmine": "~5.1.0", + "karma-jasmine-html-reporter": "~2.0.0", + "typescript": "~5.0.2" + } +} \ No newline at end of file diff --git a/src/app/app.component.css b/src/app/app.component.css new file mode 100644 index 0000000..9fdc5c1 --- /dev/null +++ b/src/app/app.component.css @@ -0,0 +1,7 @@ +.e-btn{ + margin: 5px; +} + +.e-upload.e-control-wrapper{ + display: none; +} \ No newline at end of file diff --git a/src/app/app.component.html b/src/app/app.component.html new file mode 100644 index 0000000..8dacd11 --- /dev/null +++ b/src/app/app.component.html @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/app/app.component.spec.ts b/src/app/app.component.spec.ts new file mode 100644 index 0000000..f7dd36d --- /dev/null +++ b/src/app/app.component.spec.ts @@ -0,0 +1,27 @@ +import { TestBed } from '@angular/core/testing'; +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + beforeEach(() => TestBed.configureTestingModule({ + declarations: [AppComponent] + })); + + it('should create the app', () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app).toBeTruthy(); + }); + + it(`should have as title 'myangularproject'`, () => { + const fixture = TestBed.createComponent(AppComponent); + const app = fixture.componentInstance; + expect(app.title).toEqual('myangularproject'); + }); + + it('should render title', () => { + const fixture = TestBed.createComponent(AppComponent); + fixture.detectChanges(); + const compiled = fixture.nativeElement as HTMLElement; + expect(compiled.querySelector('.content span')?.textContent).toContain('myangularproject app is running!'); + }); +}); diff --git a/src/app/app.component.ts b/src/app/app.component.ts new file mode 100644 index 0000000..56cb04b --- /dev/null +++ b/src/app/app.component.ts @@ -0,0 +1,93 @@ +import { Component, ViewEncapsulation, ViewChild } from '@angular/core'; +import { ShapeStyleModel, FlowShapeModel, PointPortModel, DiagramComponent, PrintAndExport, Diagram, IExportOptions } from '@syncfusion/ej2-angular-diagrams'; +import { AsyncSettingsModel } from '@syncfusion/ej2-angular-inputs'; +Diagram.Inject(PrintAndExport); +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrls: ['app.component.css'], + encapsulation: ViewEncapsulation.None, +}) +export class AppComponent { + title = 'myangularproject'; + @ViewChild('diagram') diagramObj !: DiagramComponent; + public diagramData: any; + public terminator: FlowShapeModel = { type: 'Flow', shape: 'Terminator' }; + public data: FlowShapeModel = { type: 'Flow', shape: 'Data' }; + public process: FlowShapeModel = { type: 'Flow', shape: 'Process' }; + public decision: FlowShapeModel = { type: 'Flow', shape: 'Decision' }; + public basicStyle: ShapeStyleModel = { + fill: '#37909A', + strokeColor: '#37909A', + strokeWidth: 3, + }; + + public displacement: object = { x:10, y: 10} + public ports: PointPortModel[] = [ + { id:'port1', offset: {x:0.5, y:1} }, + { id:'port2', offset: {x:1, y:0.5} } + ] + + public asyncSettings: AsyncSettingsModel = { + saveUrl: 'https://aspnetmvc.syncfusion.com/services/api/uploadbox/Save' + }; + + public onSave(){ + // this.diagramData = this.diagramObj.saveDiagram(); + this.downlaod(this.diagramObj.saveDiagram()); + } + + public onPrint(){ + let printOptions: IExportOptions = {}; + printOptions.mode = 'Data'; + this.diagramObj.print(printOptions); + } + + public onExport(){ + let exportOptions: IExportOptions = {}; + exportOptions.format = 'PNG'; + exportOptions.mode = 'Download'; + this.diagramObj.exportDiagram(exportOptions); + } + + public onUploadSuccess(args: { [key: string]: Object }){ + let fileData: { [key: string]: Object } = args['file'] as { [key: string]: Object }; + let file: Blob = fileData['rawFile'] as Blob; + let reader = new FileReader(); + reader.readAsText(file); + reader.onloadend = this.loadDiagram.bind(this); + } + + public loadDiagram(event: ProgressEvent){ + let result = (event.target as FileReader).result; + if(result){ + this.diagramObj.loadDiagram(result.toString()); + } + } + + public onLoad(){ + // this.diagramObj.loadDiagram(this.diagramData); + const fileSelectWrap = document.getElementsByClassName('e-file-select-wrap')[0]; + if(fileSelectWrap){ + const button = fileSelectWrap.querySelector('button'); + if(button){ + button.click(); + } + } + } + + public downlaod(data: string){ + if((window.navigator as any).msSaveBlob){ + let blob: Blob = new Blob([data], { type: 'data:text/json;charset=utf-8,' }); + (window.navigator as any).msSaveOrOpenBlob(blob, 'Diagram.json'); + } else { + let dataStr: string = 'data:text/json;charset=utf-8,' + encodeURIComponent(data); + let a: HTMLAnchorElement = document.createElement('a'); + a.href = dataStr; + a.download = 'Diagram.json'; + document.body.appendChild(a); + a.click(); + a.remove(); + } + } +} diff --git a/src/app/app.module.ts b/src/app/app.module.ts new file mode 100644 index 0000000..3b1eb98 --- /dev/null +++ b/src/app/app.module.ts @@ -0,0 +1,22 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { AppComponent } from './app.component'; +import { DiagramModule } from '@syncfusion/ej2-angular-diagrams'; +import { ButtonModule } from '@syncfusion/ej2-angular-buttons'; +import { UploaderModule } from '@syncfusion/ej2-angular-inputs'; + +@NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, + DiagramModule, + ButtonModule, + UploaderModule + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/src/assets/images/Marker.png b/src/assets/images/Marker.png new file mode 100644 index 0000000000000000000000000000000000000000..4dda18a55653d2b6d62fc2e59d8f1dd0e6ce7469 GIT binary patch literal 2899 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 WcZ@i?LyX}70000 + + + + Myangularproject + + + + + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..f43f6ed --- /dev/null +++ b/src/main.ts @@ -0,0 +1,7 @@ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import {registerLicense} from '@syncfusion/ej2-base' +import { AppModule } from './app/app.module'; +registerLicense("Your license key"); + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); diff --git a/src/styles.css b/src/styles.css new file mode 100644 index 0000000..940369a --- /dev/null +++ b/src/styles.css @@ -0,0 +1,6 @@ +@import '../node_modules/@syncfusion/ej2-material-theme/styles/material.css'; +/* You can add global styles to this file, and also import other style files */ + +.btn{ + padding: 10px; +} \ No newline at end of file diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..374cc9d --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/app", + "types": [] + }, + "files": [ + "src/main.ts" + ], + "include": [ + "src/**/*.d.ts" + ] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..16e680a --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,34 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "resolveJsonModule": true, + "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "sourceMap": true, + "declaration": false, + "downlevelIteration": true, + "experimentalDecorators": true, + "moduleResolution": "node", + "importHelpers": true, + "target": "ES2022", + "module": "ES2022", + "useDefineForClassFields": false, + "lib": [ + "ES2022", + "dom" + ] + }, + "angularCompilerOptions": { + "enableI18nLegacyMessageIdFormat": false, + "strictInjectionParameters": true, + "strictInputAccessModifiers": true, + "strictTemplates": true + } +} diff --git a/tsconfig.spec.json b/tsconfig.spec.json new file mode 100644 index 0000000..be7e9da --- /dev/null +++ b/tsconfig.spec.json @@ -0,0 +1,14 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "outDir": "./out-tsc/spec", + "types": [ + "jasmine" + ] + }, + "include": [ + "src/**/*.spec.ts", + "src/**/*.d.ts" + ] +}