diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Controllers/OrdersController.cs b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Controllers/OrdersController.cs new file mode 100644 index 0000000..f4987f1 --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Controllers/OrdersController.cs @@ -0,0 +1,93 @@ +using Microsoft.AspNetCore.Mvc; +using RemoteSaveAdaptor.Server.Models; + +namespace RemoteSaveAdaptor.Server.Controllers +{ + [ApiController] + public class OrdersController : Controller + { + [HttpPost] + [Route("api/[controller]")] + public object Post() + { + // Retrieve data from the data source (e.g., database) + IQueryable DataSource = GetOrderData().AsQueryable(); + + // Get the total records count + int totalRecordsCount = DataSource.Count(); + + // Return data based on the request + return new { result = DataSource, count = totalRecordsCount }; + } + + [HttpGet] + [Route("api/[controller]")] + public List GetOrderData() + { + var data = OrdersDetails.GetAllRecords().ToList(); + return data; + } + + [HttpPost] + [Route("api/Orders/Insert")] + public ActionResult Insert([FromBody] CRUDModel newRecord) + { + if (newRecord.value !=null) + { + OrdersDetails.GetAllRecords().Insert(0, newRecord.value); + } + + return Json(newRecord.value); + } + + [HttpPost] + [Route("api/Orders/Update")] + public object Update([FromBody] CRUDModel updatedRecord) + { + var updatedOrder = updatedRecord.value; + if (updatedOrder != null) + { + var data = OrdersDetails.GetAllRecords().FirstOrDefault(or => or.OrderID == updatedOrder.OrderID); + if (data != null) + { + // Update the existing record + data.OrderID = updatedOrder.OrderID; + data.CustomerID = updatedOrder.CustomerID; + data.Freight = updatedOrder.Freight; + data.ShipCity = updatedOrder.ShipCity; + data.ShipCountry = updatedOrder.ShipCountry; + data.Verified = updatedOrder.Verified; + + // Update other properties similarly + } + } + return updatedRecord; + } + + [HttpPost] + [Route("api/Orders/Remove")] + public object Remove([FromBody] CRUDModel deletedRecord) + { + int orderId = int.Parse(deletedRecord.key.ToString()); // get key value from the deletedRecord + var data = OrdersDetails.GetAllRecords().FirstOrDefault(orderData => orderData.OrderID == orderId); + if (data != null) + { + // Remove the record from the data collection + OrdersDetails.GetAllRecords().Remove(data); + } + return deletedRecord; + } + + public class CRUDModel where T : class + { + public string? action { get; set; } + public string? keyColumn { get; set; } + public object? key { get; set; } + public T? value { get; set; } + public List? added { get; set; } + public List? changed { get; set; } + public List? deleted { get; set; } + public IDictionary? @params { get; set; } + } + } +} diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Controllers/WeatherForecastController.cs b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Controllers/WeatherForecastController.cs new file mode 100644 index 0000000..7fb5936 --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Controllers/WeatherForecastController.cs @@ -0,0 +1,33 @@ +using Microsoft.AspNetCore.Mvc; + +namespace RemoteSaveAdaptor.Server.Controllers +{ + [ApiController] + [Route("[controller]")] + public class WeatherForecastController : ControllerBase + { + private static readonly string[] Summaries = new[] + { + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" + }; + + private readonly ILogger _logger; + + public WeatherForecastController(ILogger logger) + { + _logger = logger; + } + + [HttpGet(Name = "GetWeatherForecast")] + public IEnumerable Get() + { + return Enumerable.Range(1, 5).Select(index => new WeatherForecast + { + Date = DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + TemperatureC = Random.Shared.Next(-20, 55), + Summary = Summaries[Random.Shared.Next(Summaries.Length)] + }) + .ToArray(); + } + } +} diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Models/OrdersDetails.cs b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Models/OrdersDetails.cs new file mode 100644 index 0000000..dcedad9 --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Models/OrdersDetails.cs @@ -0,0 +1,57 @@ +using System.ComponentModel.DataAnnotations; + +namespace RemoteSaveAdaptor.Server.Models +{ + public class OrdersDetails + { + public static List order = new List(); + public OrdersDetails() + { + + } + public OrdersDetails(int OrderID, string CustomerId, int EmployeeId, double Freight, bool Verified, DateTime OrderDate, string ShipCity, string ShipName, string ShipCountry, DateTime ShippedDate, string ShipAddress) + { + this.OrderID = OrderID; + this.CustomerID = CustomerId; + this.EmployeeID = EmployeeId; + this.Freight = Freight; + this.ShipCity = ShipCity; + this.Verified = Verified; + this.OrderDate = OrderDate; + this.ShipName = ShipName; + this.ShipCountry = ShipCountry; + this.ShippedDate = ShippedDate; + this.ShipAddress = ShipAddress; + } + + public static List GetAllRecords() + { + if (order.Count() == 0) + { + int code = 10000; + for (int i = 1; i <= 2000; i++) + { + order.Add(new OrdersDetails(code + 1, "ALFKI", i + 0, 2.3 * i, false, new DateTime(1991, 05, 15), "Berlin", "Simons bistro", "Denmark", new DateTime(1996, 7, 16), "Kirchgasse 6")); + order.Add(new OrdersDetails(code + 2, "ANATR", i + 2, 3.3 * i, true, new DateTime(1990, 04, 04), "Madrid", "Queen Cozinha", "Brazil", new DateTime(1996, 9, 11), "Avda. Azteca 123")); + order.Add(new OrdersDetails(code + 3, "ANTON", i + 1, 4.3 * i, true, new DateTime(1957, 11, 30), "Cholchester", "Frankenversand", "Germany", new DateTime(1996, 10, 7), "Carrera 52 con Ave. Bolívar #65-98 Llano Largo")); + order.Add(new OrdersDetails(code + 4, "BLONP", i + 3, 5.3 * i, false, new DateTime(1930, 10, 22), "Marseille", "Ernst Handel", "Austria", new DateTime(1996, 12, 30), "Magazinweg 7")); + order.Add(new OrdersDetails(code + 5, "BOLID", i + 4, 6.3 * i, true, new DateTime(1953, 02, 18), "Tsawassen", "Hanari Carnes", "Switzerland", new DateTime(1997, 12, 3), "1029 - 12th Ave. S.")); + code += 5; + } + } + return order; + } + [Key] + public int OrderID { get; set; } + public string? CustomerID { get; set; } + public int? EmployeeID { get; set; } + public double? Freight { get; set; } + public string? ShipCity { get; set; } + public bool? Verified { get; set; } + public DateTime? OrderDate { get; set; } + public string? ShipName { get; set; } + public string? ShipCountry { get; set; } + public DateTime? ShippedDate { get; set; } + public string? ShipAddress { get; set; } + } +} diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Program.cs b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Program.cs new file mode 100644 index 0000000..5b0230b --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Program.cs @@ -0,0 +1,36 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. + +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(builder => + { + builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader(); + }); +}); +var app = builder.Build(); +app.UseCors(); +app.UseDefaultFiles(); +app.UseStaticFiles(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.MapFallbackToFile("/index.html"); + +app.Run(); diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Properties/launchSettings.json b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Properties/launchSettings.json new file mode 100644 index 0000000..c1fbf7f --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/Properties/launchSettings.json @@ -0,0 +1,45 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:17668", + "sslPort": 44357 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5218", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7010;http://localhost:5218", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development", + "ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.SpaProxy" + } + } + } +} + diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/RemoteSaveAdaptor.Server.csproj b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/RemoteSaveAdaptor.Server.csproj new file mode 100644 index 0000000..22075e1 --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/RemoteSaveAdaptor.Server.csproj @@ -0,0 +1,25 @@ + + + + net8.0 + enable + enable + ..\remotesaveadaptor.client + npm start + https://localhost:4200 + + + + + 8.*-* + + + + + + + false + + + + diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/RemoteSaveAdaptor.Server.csproj.user b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/RemoteSaveAdaptor.Server.csproj.user new file mode 100644 index 0000000..2c8f5c1 --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/RemoteSaveAdaptor.Server.csproj.user @@ -0,0 +1,8 @@ + + + + https + ApiControllerEmptyScaffolder + root/Common/Api + + \ No newline at end of file diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/RemoteSaveAdaptor.Server.http b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/RemoteSaveAdaptor.Server.http new file mode 100644 index 0000000..c35fed9 --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/RemoteSaveAdaptor.Server.http @@ -0,0 +1,6 @@ +@RemoteSaveAdaptor.Server_HostAddress = http://localhost:5218 + +GET {{RemoteSaveAdaptor.Server_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/WeatherForecast.cs b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/WeatherForecast.cs new file mode 100644 index 0000000..4b6bcde --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/WeatherForecast.cs @@ -0,0 +1,13 @@ +namespace RemoteSaveAdaptor.Server +{ + public class WeatherForecast + { + public DateOnly Date { get; set; } + + public int TemperatureC { get; set; } + + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); + + public string? Summary { get; set; } + } +} diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/appsettings.Development.json b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/appsettings.json b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.Server/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/RemoteSaveAdaptor/RemoteSaveAdaptor.sln b/RemoteSaveAdaptor/RemoteSaveAdaptor.sln new file mode 100644 index 0000000..02a2132 --- /dev/null +++ b/RemoteSaveAdaptor/RemoteSaveAdaptor.sln @@ -0,0 +1,33 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.9.34728.123 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RemoteSaveAdaptor.Server", "RemoteSaveAdaptor.Server\RemoteSaveAdaptor.Server.csproj", "{03248ABA-27D2-470C-9FE2-6AF2F2F56A96}" +EndProject +Project("{54A90642-561A-4BB1-A94E-469ADEE60C69}") = "remotesaveadaptor.client", "remotesaveadaptor.client\remotesaveadaptor.client.esproj", "{F593DC32-452A-4342-9CBB-7C336F34F494}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {03248ABA-27D2-470C-9FE2-6AF2F2F56A96}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {03248ABA-27D2-470C-9FE2-6AF2F2F56A96}.Debug|Any CPU.Build.0 = Debug|Any CPU + {03248ABA-27D2-470C-9FE2-6AF2F2F56A96}.Release|Any CPU.ActiveCfg = Release|Any CPU + {03248ABA-27D2-470C-9FE2-6AF2F2F56A96}.Release|Any CPU.Build.0 = Release|Any CPU + {F593DC32-452A-4342-9CBB-7C336F34F494}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F593DC32-452A-4342-9CBB-7C336F34F494}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F593DC32-452A-4342-9CBB-7C336F34F494}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {F593DC32-452A-4342-9CBB-7C336F34F494}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F593DC32-452A-4342-9CBB-7C336F34F494}.Release|Any CPU.Build.0 = Release|Any CPU + {F593DC32-452A-4342-9CBB-7C336F34F494}.Release|Any CPU.Deploy.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C339D384-F8A0-4882-B45A-DAED514717FC} + EndGlobalSection +EndGlobal diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/.editorconfig b/RemoteSaveAdaptor/remotesaveadaptor.client/.editorconfig new file mode 100644 index 0000000..59d9a3a --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/.editorconfig @@ -0,0 +1,16 @@ +# Editor configuration, see https://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.ts] +quote_type = single + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/.gitignore b/RemoteSaveAdaptor/remotesaveadaptor.client/.gitignore new file mode 100644 index 0000000..0711527 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/.gitignore @@ -0,0 +1,42 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# Compiled output +/dist +/tmp +/out-tsc +/bazel-out + +# Node +/node_modules +npm-debug.log +yarn-error.log + +# IDEs and editors +.idea/ +.project +.classpath +.c9/ +*.launch +.settings/ +*.sublime-workspace + +# Visual Studio Code +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +.history/* + +# Miscellaneous +/.angular/cache +.sass-cache/ +/connect.lock +/coverage +/libpeerconnection.log +testem.log +/typings + +# System files +.DS_Store +Thumbs.db diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/README.md b/RemoteSaveAdaptor/remotesaveadaptor.client/README.md new file mode 100644 index 0000000..2976579 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/README.md @@ -0,0 +1,27 @@ +# RemotesaveadaptorClient + +This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.2.3. + +## Development server + +Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files. + +## Code scaffolding + +Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. + +## Build + +Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. + +## Running unit tests + +Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Running end-to-end tests + +Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities. + +## Further help + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page. diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/angular.json b/RemoteSaveAdaptor/remotesaveadaptor.client/angular.json new file mode 100644 index 0000000..b85ba2e --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/angular.json @@ -0,0 +1,109 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "remotesaveadaptor.client": { + "projectType": "application", + "schematics": { + "@schematics/angular:component": { + "standalone": false + }, + "@schematics/angular:directive": { + "standalone": false + }, + "@schematics/angular:pipe": { + "standalone": false + } + }, + "root": "", + "sourceRoot": "src", + "prefix": "app", + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:application", + "options": { + "outputPath": "dist/remotesaveadaptor.client", + "index": "src/index.html", + "browser": "src/main.ts", + "polyfills": [ + "zone.js" + ], + "tsConfig": "tsconfig.app.json", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "src/styles.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "budgets": [ + { + "type": "initial", + "maximumWarning": "500kb", + "maximumError": "1mb" + }, + { + "type": "anyComponentStyle", + "maximumWarning": "2kb", + "maximumError": "4kb" + } + ], + "outputHashing": "all" + }, + "development": { + "optimization": false, + "extractLicenses": false, + "sourceMap": true + } + }, + "defaultConfiguration": "production" + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "configurations": { + "production": { + "buildTarget": "remotesaveadaptor.client:build:production" + }, + "development": { + "buildTarget": "remotesaveadaptor.client:build:development" + } + }, + "defaultConfiguration": "development", + "options": { + "proxyConfig": "src/proxy.conf.js" + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "buildTarget": "remotesaveadaptor.client: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" + ], + "scripts": [], + "karmaConfig": "karma.conf.js" + } + } + } + } + } +} \ No newline at end of file diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/aspnetcore-https.js b/RemoteSaveAdaptor/remotesaveadaptor.client/aspnetcore-https.js new file mode 100644 index 0000000..764331a --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/aspnetcore-https.js @@ -0,0 +1,33 @@ +// This script sets up HTTPS for the application using the ASP.NET Core HTTPS certificate +const fs = require('fs'); +const spawn = require('child_process').spawn; +const path = require('path'); + +const baseFolder = + process.env.APPDATA !== undefined && process.env.APPDATA !== '' + ? `${process.env.APPDATA}/ASP.NET/https` + : `${process.env.HOME}/.aspnet/https`; + +const certificateArg = process.argv.map(arg => arg.match(/--name=(?.+)/i)).filter(Boolean)[0]; +const certificateName = certificateArg ? certificateArg.groups.value : process.env.npm_package_name; + +if (!certificateName) { + console.error('Invalid certificate name. Run this script in the context of an npm/yarn script or pass --name=<> explicitly.') + process.exit(-1); +} + +const certFilePath = path.join(baseFolder, `${certificateName}.pem`); +const keyFilePath = path.join(baseFolder, `${certificateName}.key`); + +if (!fs.existsSync(certFilePath) || !fs.existsSync(keyFilePath)) { + spawn('dotnet', [ + 'dev-certs', + 'https', + '--export-path', + certFilePath, + '--format', + 'Pem', + '--no-password', + ], { stdio: 'inherit', }) + .on('exit', (code) => process.exit(code)); +} \ No newline at end of file diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/karma.conf.js b/RemoteSaveAdaptor/remotesaveadaptor.client/karma.conf.js new file mode 100644 index 0000000..efe6efe --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/karma.conf.js @@ -0,0 +1,44 @@ +module.exports = function (config) { + config.set({ + basePath: '', + frameworks: ['jasmine', '@angular-devkit/build-angular'], + plugins: [ + require('karma-jasmine'), + require('karma-chrome-launcher'), + require('karma-jasmine-html-reporter'), + require('karma-coverage'), + require('@angular-devkit/build-angular/plugins/karma') + ], + client: { + jasmine: { + // you can add configuration options for Jasmine here + // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html + // for example, you can disable the random execution with `random: false` + // or set a specific seed with `seed: 4321` + }, + clearContext: false // leave Jasmine Spec Runner output visible in browser + }, + jasmineHtmlReporter: { + suppressAll: true // removes the duplicated traces + }, + coverageReporter: { + dir: require('path').join(__dirname, './coverage/'), + subdir: '.', + reporters: [ + { type: 'html' }, + { type: 'text-summary' } + ] + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false, + restartOnFileChange: true, + listenAddress: 'localhost', + hostname: 'localhost' + }); +}; + diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/nuget.config b/RemoteSaveAdaptor/remotesaveadaptor.client/nuget.config new file mode 100644 index 0000000..6548586 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/nuget.config @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/package.json b/RemoteSaveAdaptor/remotesaveadaptor.client/package.json new file mode 100644 index 0000000..88af598 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/package.json @@ -0,0 +1,45 @@ +{ + "name": "remotesaveadaptor.client", + "version": "0.0.0", + "scripts": { + "ng": "ng", + "start": "run-script-os", + "build": "ng build", + "watch": "ng build --watch --configuration development", + "test": "ng test", + "prestart": "node aspnetcore-https", + "start:windows": "ng serve --ssl --ssl-cert \"%APPDATA%\\ASP.NET\\https\\%npm_package_name%.pem\" --ssl-key \"%APPDATA%\\ASP.NET\\https\\%npm_package_name%.key\" --host=127.0.0.1", + "start:default": "ng serve --ssl --ssl-cert \"$HOME/.aspnet/https/${npm_package_name}.pem\" --ssl-key \"$HOME/.aspnet/https/${npm_package_name}.key\" --host=127.0.0.1" + }, + "private": true, + "dependencies": { + "@angular/animations": "^17.2.0", + "@angular/common": "^17.2.0", + "@angular/compiler": "^17.2.0", + "@angular/core": "^17.2.0", + "@angular/forms": "^17.2.0", + "@angular/platform-browser": "^17.2.0", + "@angular/platform-browser-dynamic": "^17.2.0", + "@angular/router": "^17.2.0", + "@syncfusion/ej2-angular-grids": "^25.2.3", + "@syncfusion/ej2-data": "^25.2.3", + "jest-editor-support": "*", + "run-script-os": "*", + "rxjs": "~7.8.0", + "tslib": "^2.3.0", + "zone.js": "~0.14.3" + }, + "devDependencies": { + "@angular-devkit/build-angular": "^17.2.3", + "@angular/cli": "^17.2.3", + "@angular/compiler-cli": "^17.2.0", + "@types/jasmine": "~5.1.0", + "jasmine-core": "~5.1.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.1.0", + "typescript": "~5.3.2" + } +} diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/remotesaveadaptor.client.esproj b/RemoteSaveAdaptor/remotesaveadaptor.client/remotesaveadaptor.client.esproj new file mode 100644 index 0000000..1f69182 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/remotesaveadaptor.client.esproj @@ -0,0 +1,10 @@ + + + npm start + Jasmine + + false + + $(MSBuildProjectDirectory)\dist\remotesaveadaptor.client\ + + \ No newline at end of file diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app-routing.module.ts b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app-routing.module.ts new file mode 100644 index 0000000..0297262 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app-routing.module.ts @@ -0,0 +1,10 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +const routes: Routes = []; + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] +}) +export class AppRoutingModule { } diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.css b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.css new file mode 100644 index 0000000..7a99c93 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.css @@ -0,0 +1,22 @@ +:host { + max-width: 1280px; + padding: 2rem; + text-align: center; +} + +tr:nth-child(even) { + background: #F2F2F2; +} + +tr:nth-child(odd) { + background: #FFF; +} + +th, td { + padding-left: 1rem; + padding-right: 1rem; +} + +table { + margin: 0 auto; +} diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.html b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.html new file mode 100644 index 0000000..4f4058c --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.html @@ -0,0 +1,24 @@ +

Weather forecast

+ +

This component demonstrates fetching data from the server.

+ +

Loading... Please refresh once the ASP.NET backend has started. See https://aka.ms/jspsintegrationangular for more details.

+ + + + + + + + + + + + + + + + + + +
DateTemp. (C)Temp. (F)Summary
{{ forecast.date }}{{ forecast.temperatureC }}{{ forecast.temperatureF }}{{ forecast.summary }}
diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.spec.ts b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.spec.ts new file mode 100644 index 0000000..64dc497 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.spec.ts @@ -0,0 +1,45 @@ +import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { AppComponent } from './app.component'; + +describe('AppComponent', () => { + let component: AppComponent; + let fixture: ComponentFixture; + let httpMock: HttpTestingController; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [AppComponent], + imports: [HttpClientTestingModule] + }).compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(AppComponent); + component = fixture.componentInstance; + httpMock = TestBed.inject(HttpTestingController); + }); + + afterEach(() => { + httpMock.verify(); + }); + + it('should create the app', () => { + expect(component).toBeTruthy(); + }); + + it('should retrieve weather forecasts from the server', () => { + const mockForecasts = [ + { date: '2021-10-01', temperatureC: 20, temperatureF: 68, summary: 'Mild' }, + { date: '2021-10-02', temperatureC: 25, temperatureF: 77, summary: 'Warm' } + ]; + + component.ngOnInit(); + + const req = httpMock.expectOne('/weatherforecast'); + expect(req.request.method).toEqual('GET'); + req.flush(mockForecasts); + + expect(component.forecasts).toEqual(mockForecasts); + }); +}); \ No newline at end of file diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.ts b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.ts new file mode 100644 index 0000000..38888f2 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.component.ts @@ -0,0 +1,53 @@ +import { Component, OnInit } from '@angular/core'; + +import { DataManager, RemoteSaveAdaptor } from '@syncfusion/ej2-data'; +import { EditSettingsModel, ToolbarItems } from '@syncfusion/ej2-angular-grids'; +import { HttpClient } from '@angular/common/http'; + + +const serviceUrl = 'https://localhost:7010/api/orders'; + +@Component({ + selector: 'app-root', + template: ` + + + + + + + + + + `, + providers: [] +}) +export class AppComponent implements OnInit { + + public data?: DataManager; + constructor(private http: HttpClient) { } + public editSettings: EditSettingsModel = { + allowEditing: true, + allowAdding: true, + allowDeleting: true, + newRowPosition: 'Top' + }; + + public toolbar: ToolbarItems[] = ['Add', 'Edit', 'Delete', 'Update', 'Cancel', 'Search']; + + ngOnInit(): void { + + this.http.get<[]>(serviceUrl) + .pipe() + .subscribe((value: any) => { + this.data = new DataManager({ + json: value, + insertUrl: serviceUrl + "/Insert", + updateUrl: serviceUrl + "/Update", + removeUrl: serviceUrl + "/Remove", + adaptor: new RemoteSaveAdaptor(), + }); + }); + } + title = 'RemoteSaveAdaptor.client'; +} diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.module.ts b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.module.ts new file mode 100644 index 0000000..8214432 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/src/app/app.module.ts @@ -0,0 +1,21 @@ +import { HttpClientModule } from '@angular/common/http'; +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; + +import { AppRoutingModule } from './app-routing.module'; +import { AppComponent } from './app.component'; +import { EditService, FilterService, GridModule, PageService, SortService, ToolbarService } from '@syncfusion/ej2-angular-grids'; + +@NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, HttpClientModule, + AppRoutingModule, + GridModule + ], + providers: [EditService, FilterService, SortService, PageService, ToolbarService], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/assets/.gitkeep b/RemoteSaveAdaptor/remotesaveadaptor.client/src/assets/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/favicon.ico b/RemoteSaveAdaptor/remotesaveadaptor.client/src/favicon.ico new file mode 100644 index 0000000..57614f9 Binary files /dev/null and b/RemoteSaveAdaptor/remotesaveadaptor.client/src/favicon.ico differ diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/index.html b/RemoteSaveAdaptor/remotesaveadaptor.client/src/index.html new file mode 100644 index 0000000..27804cf --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/src/index.html @@ -0,0 +1,13 @@ + + + + + RemotesaveadaptorClient + + + + + + + + diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/main.ts b/RemoteSaveAdaptor/remotesaveadaptor.client/src/main.ts new file mode 100644 index 0000000..c58dc05 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/src/main.ts @@ -0,0 +1,7 @@ +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; + + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.error(err)); diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/proxy.conf.js b/RemoteSaveAdaptor/remotesaveadaptor.client/src/proxy.conf.js new file mode 100644 index 0000000..9910722 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/src/proxy.conf.js @@ -0,0 +1,16 @@ +const { env } = require('process'); + +const target = env.ASPNETCORE_HTTPS_PORT ? `https://localhost:${env.ASPNETCORE_HTTPS_PORT}` : + env.ASPNETCORE_URLS ? env.ASPNETCORE_URLS.split(';')[0] : 'https://localhost:7010'; + +const PROXY_CONFIG = [ + { + context: [ + "/weatherforecast", + ], + target, + secure: false + } +] + +module.exports = PROXY_CONFIG; diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/src/styles.css b/RemoteSaveAdaptor/remotesaveadaptor.client/src/styles.css new file mode 100644 index 0000000..756c128 --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/src/styles.css @@ -0,0 +1,11 @@ + +/* You can add global styles to this file, and also import other style files */ +@import '../node_modules/@syncfusion/ej2-base/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-buttons/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-calendars/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-dropdowns/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-inputs/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-navigations/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-popups/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-splitbuttons/styles/material.css'; +@import '../node_modules/@syncfusion/ej2-angular-grids/styles/material.css'; diff --git a/RemoteSaveAdaptor/remotesaveadaptor.client/tsconfig.app.json b/RemoteSaveAdaptor/remotesaveadaptor.client/tsconfig.app.json new file mode 100644 index 0000000..374cc9d --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/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/RemoteSaveAdaptor/remotesaveadaptor.client/tsconfig.json b/RemoteSaveAdaptor/remotesaveadaptor.client/tsconfig.json new file mode 100644 index 0000000..f37b67f --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/tsconfig.json @@ -0,0 +1,33 @@ +/* To learn more about this file see: https://angular.io/config/tsconfig. */ +{ + "compileOnSave": false, + "compilerOptions": { + "outDir": "./dist/out-tsc", + "forceConsistentCasingInFileNames": true, + "strict": true, + "noImplicitOverride": true, + "noPropertyAccessFromIndexSignature": true, + "noImplicitReturns": true, + "noFallthroughCasesInSwitch": true, + "skipLibCheck": true, + "esModuleInterop": true, + "sourceMap": true, + "declaration": false, + "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/RemoteSaveAdaptor/remotesaveadaptor.client/tsconfig.spec.json b/RemoteSaveAdaptor/remotesaveadaptor.client/tsconfig.spec.json new file mode 100644 index 0000000..be7e9da --- /dev/null +++ b/RemoteSaveAdaptor/remotesaveadaptor.client/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" + ] +}