Angular implementation

Versionsfehler
This commit is contained in:
marcusferl@weifer.de 2022-06-23 12:54:54 +02:00
parent ec0a463b9b
commit 40cfa5ff97
21 changed files with 141 additions and 241 deletions

View File

@ -22,7 +22,6 @@
"tsConfig": "src/tsconfig.app.json", "tsConfig": "src/tsconfig.app.json",
"assets": ["src/assets"], "assets": ["src/assets"],
"styles": [ "styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css",
"src/styles.css" "src/styles.css"
], ],
"scripts": [] "scripts": []

View File

@ -23,12 +23,9 @@
"@angular/router": "8.2.12", "@angular/router": "8.2.12",
"@nguniversal/module-map-ngfactory-loader": "8.1.1", "@nguniversal/module-map-ngfactory-loader": "8.1.1",
"aspnet-prerendering": "^3.0.1", "aspnet-prerendering": "^3.0.1",
"bootstrap": "^4.6.0",
"core-js": "^3.8.3", "core-js": "^3.8.3",
"jquery": "^3.6.0",
"node-sass": "^5.0.0", "node-sass": "^5.0.0",
"oidc-client": "^1.11.5", "oidc-client": "^1.11.5",
"popper.js": "^1.16.0",
"protractor": "~5.4.2", "protractor": "~5.4.2",
"rxjs": "^6.6.3", "rxjs": "^6.6.3",
"ts-node": "~8.4.1", "ts-node": "~8.4.1",

View File

@ -7,16 +7,14 @@ import { RouterModule } from '@angular/router';
import { AppComponent } from './app.component'; import { AppComponent } from './app.component';
import { NavMenuComponent } from './nav-menu/nav-menu.component'; import { NavMenuComponent } from './nav-menu/nav-menu.component';
import { HomeComponent } from './home/home.component'; import { HomeComponent } from './home/home.component';
import { CounterComponent } from './counter/counter.component';
import { FetchDataComponent } from './fetch-data/fetch-data.component';
@NgModule({ @NgModule({
declarations: [ declarations: [
AppComponent, AppComponent,
NavMenuComponent, NavMenuComponent,
HomeComponent, HomeComponent,
CounterComponent,
FetchDataComponent
], ],
imports: [ imports: [
BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }), BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
@ -24,8 +22,6 @@ import { FetchDataComponent } from './fetch-data/fetch-data.component';
FormsModule, FormsModule,
RouterModule.forRoot([ RouterModule.forRoot([
{ path: '', component: HomeComponent, pathMatch: 'full' }, { path: '', component: HomeComponent, pathMatch: 'full' },
{ path: 'counter', component: CounterComponent },
{ path: 'fetch-data', component: FetchDataComponent },
]) ])
], ],
providers: [], providers: [],

View File

@ -1,7 +0,0 @@
<h1>Counter</h1>
<p>This is a simple example of an Angular component.</p>
<p aria-live="polite">Current count: <strong>{{ currentCount }}</strong></p>
<button class="btn btn-primary" (click)="incrementCounter()">Increment</button>

View File

@ -1,36 +0,0 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CounterComponent } from './counter.component';
describe('CounterComponent', () => {
let component: CounterComponent;
let fixture: ComponentFixture<CounterComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ CounterComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CounterComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should display a title', async(() => {
const titleText = fixture.nativeElement.querySelector('h1').textContent;
expect(titleText).toEqual('Counter');
}));
it('should start with count 0, then increments by 1 when clicked', async(() => {
const countElement = fixture.nativeElement.querySelector('strong');
expect(countElement.textContent).toEqual('0');
const incrementButton = fixture.nativeElement.querySelector('button');
incrementButton.click();
fixture.detectChanges();
expect(countElement.textContent).toEqual('1');
}));
});

View File

@ -1,13 +0,0 @@
import { Component } from '@angular/core';
@Component({
selector: 'app-counter-component',
templateUrl: './counter.component.html'
})
export class CounterComponent {
public currentCount = 0;
public incrementCounter() {
this.currentCount++;
}
}

View File

@ -1,24 +0,0 @@
<h1 id="tableLabel">Weather forecast</h1>
<p>This component demonstrates fetching data from the server.</p>
<p *ngIf="!forecasts"><em>Loading...</em></p>
<table class='table table-striped' aria-labelledby="tableLabel" *ngIf="forecasts">
<thead>
<tr>
<th>Date</th>
<th>Temp. (C)</th>
<th>Temp. (F)</th>
<th>Summary</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let forecast of forecasts">
<td>{{ forecast.date }}</td>
<td>{{ forecast.temperatureC }}</td>
<td>{{ forecast.temperatureF }}</td>
<td>{{ forecast.summary }}</td>
</tr>
</tbody>
</table>

View File

@ -1,23 +0,0 @@
import { Component, Inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Component({
selector: 'app-fetch-data',
templateUrl: './fetch-data.component.html'
})
export class FetchDataComponent {
public forecasts: WeatherForecast[];
constructor(http: HttpClient, @Inject('BASE_URL') baseUrl: string) {
http.get<WeatherForecast[]>(baseUrl + 'weatherforecast').subscribe(result => {
this.forecasts = result;
}, error => console.error(error));
}
}
interface WeatherForecast {
date: string;
temperatureC: number;
temperatureF: number;
summary: string;
}

View File

@ -1,14 +1 @@
<h1>Hello, world!</h1> <h1>DaRestaurante</h1>
<p>Welcome to your new single-page application, built with:</p>
<ul>
<li><a href='https://get.asp.net/'>ASP.NET Core</a> and <a href='https://msdn.microsoft.com/en-us/library/67ef8sbd.aspx'>C#</a> for cross-platform server-side code</li>
<li><a href='https://angular.io/'>Angular</a> and <a href='http://www.typescriptlang.org/'>TypeScript</a> for client-side code</li>
<li><a href='http://getbootstrap.com/'>Bootstrap</a> for layout and styling</li>
</ul>
<p>To help you get started, we've also set up:</p>
<ul>
<li><strong>Client-side navigation</strong>. For example, click <em>Counter</em> then <em>Back</em> to return here.</li>
<li><strong>Angular CLI integration</strong>. In development mode, there's no need to run <code>ng serve</code>. It runs in the background automatically, so your client-side resources are dynamically built on demand and the page refreshes when you modify any file.</li>
<li><strong>Efficient production builds</strong>. In production mode, development-time features are disabled, and your <code>dotnet publish</code> configuration automatically invokes <code>ng build</code> to produce minified, ahead-of-time compiled JavaScript files.</li>
</ul>
<p>The <code>ClientApp</code> subdirectory is a standard Angular CLI application. If you open a command prompt in that directory, you can run any <code>ng</code> command (e.g., <code>ng test</code>), or use <code>npm</code> to install extra packages into it.</p>

View File

@ -1,18 +0,0 @@
a.navbar-brand {
white-space: normal;
text-align: center;
word-break: break-all;
}
html {
font-size: 14px;
}
@media (min-width: 768px) {
html {
font-size: 16px;
}
}
.box-shadow {
box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05);
}

View File

@ -1,44 +1 @@
<header> <div>Menü</div>
<nav
class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3"
>
<div class="container">
<a class="navbar-brand" [routerLink]="['/']">Aps_Single_Page_Anwendung</a>
<button
class="navbar-toggler"
type="button"
data-toggle="collapse"
data-target=".navbar-collapse"
aria-label="Toggle navigation"
[attr.aria-expanded]="isExpanded"
(click)="toggle()"
>
<span class="navbar-toggler-icon"></span>
</button>
<div
class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse"
[ngClass]="{ show: isExpanded }"
>
<ul class="navbar-nav flex-grow">
<li
class="nav-item"
[routerLinkActive]="['link-active']"
[routerLinkActiveOptions]="{ exact: true }"
>
<a class="nav-link text-dark" [routerLink]="['/']">Home</a>
</li>
<li class="nav-item" [routerLinkActive]="['link-active']">
<a class="nav-link text-dark" [routerLink]="['/counter']"
>Counter</a
>
</li>
<li class="nav-item" [routerLinkActive]="['link-active']">
<a class="nav-link text-dark" [routerLink]="['/fetch-data']"
>Fetch data</a
>
</li>
</ul>
</div>
</div>
</nav>
</header>

View File

@ -1,16 +0,0 @@
/* You can add global styles to this file, and also import other style files */
/* Provide sufficient contrast against white background */
a {
color: #0366d6;
}
code {
color: #e01a76;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}

View File

@ -9,7 +9,7 @@ using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
namespace Single_Page_Anwendung.Migrations namespace Single_Page_Anwendung.Migrations
{ {
[DbContext(typeof(FutterContext))] [DbContext(typeof(FutterContext))]
[Migration("20220607122417_InitialCreate")] [Migration("20220610054518_InitialCreate")]
partial class InitialCreate partial class InitialCreate
{ {
protected override void BuildTargetModel(ModelBuilder modelBuilder) protected override void BuildTargetModel(ModelBuilder modelBuilder)

View File

@ -1,4 +1,5 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
namespace Aps_Single_Page_Anwendung.Models namespace Aps_Single_Page_Anwendung.Models
{ {
@ -17,6 +18,8 @@ namespace Aps_Single_Page_Anwendung.Models
public double Preis { get; set; } public double Preis { get; set; }
public int KategorieId { get; set; } public int KategorieId { get; set; }
[JsonIgnore]
public Kategorie Kategorie { get; set; } public Kategorie Kategorie { get; set; }
} }
} }

View File

@ -0,0 +1,54 @@
using Aps_Single_Page_Anwendung.Models;
using Aps_Single_Page_Anwendung.Repositories;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
namespace Single_Page_Anwendung.Repositories
{
public class EfKategorieRepository : IKategorieRepository
{
private readonly FutterContext _futterContext;
public EfKategorieRepository(FutterContext futterContext)
{
_futterContext = futterContext;
}
public Kategorie CreateKategorie(Kategorie kategorie)
{
_futterContext.Kategorien.Add(kategorie);
_futterContext.SaveChanges();
return kategorie;
}
public void DeleteKategorie(int id)
{
var kategorie = _futterContext.Kategorien.Find(id);
_futterContext.Kategorien.Remove(kategorie);
_futterContext.SaveChanges();
}
public Kategorie GetKategorieByID(int id)
{
var kategorie = _futterContext.Kategorien.Find(id);
return kategorie;
}
public IEnumerable<Kategorie> GetKategorien()
{
var kategorie = _futterContext.Kategorien.AsNoTracking().Include(x => x.Speisen).ToList();
return kategorie;
}
public Kategorie UpdateKategorie(Kategorie kategorie)
{
var kategorieToUpdate = _futterContext.Kategorien.Find(kategorie.Id);
kategorieToUpdate.Name = kategorie.Name;
kategorieToUpdate.Beschreibung = kategorie.Beschreibung;
_futterContext.SaveChanges();
return kategorieToUpdate;
}
}
}

View File

@ -0,0 +1,54 @@
using Aps_Single_Page_Anwendung.Models;
using Aps_Single_Page_Anwendung.Repositories;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
namespace Single_Page_Anwendung.Repositories
{
public class EfSpeisenRepository : ISpeiseRepository
{
private readonly FutterContext _futterContext;
public EfSpeisenRepository(FutterContext futterContext)
{
_futterContext = futterContext;
}
public Speise CreateSpeise(Speise speise)
{
_futterContext.Speisen.Add(speise);
_futterContext.SaveChanges();
return speise;
}
public void DeleteSpeise(int id)
{
var speise = _futterContext.Speisen.Find(id);
_futterContext.Speisen.Remove(speise);
_futterContext.SaveChanges();
}
public Speise GetSpeiseById(int id)
{
var speise = _futterContext.Speisen.Find(id);
return speise;
}
public IEnumerable<Speise> GetSpeisen()
{
var speisen = _futterContext.Speisen.AsNoTracking().ToList();
return speisen;
}
public Speise UpdateSpeise(Speise speise)
{
var speiseToUpdate = _futterContext.Speisen.Find(speise.Id);
speiseToUpdate.Name = speise.Name;
speiseToUpdate.Preis = speise.Preis;
speiseToUpdate.Beschreibung = speise.Beschreibung;
speiseToUpdate.KategorieId = speise.KategorieId;
_futterContext.SaveChanges();
return speise;
}
}
}

View File

@ -29,6 +29,10 @@
<None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" /> <None Include="$(SpaRoot)**" Exclude="$(SpaRoot)node_modules\**" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Migrations\" />
</ItemGroup>
<Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') "> <Target Name="DebugEnsureNodeEnv" BeforeTargets="Build" Condition=" '$(Configuration)' == 'Debug' And !Exists('$(SpaRoot)node_modules') ">
<!-- Ensure Node.js is installed --> <!-- Ensure Node.js is installed -->
<Exec Command="node --version" ContinueOnError="true"> <Exec Command="node --version" ContinueOnError="true">

View File

@ -8,6 +8,7 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Single_Page_Anwendung.Repositories;
namespace Aps_Single_Page_Anwendung namespace Aps_Single_Page_Anwendung
{ {
@ -29,8 +30,8 @@ namespace Aps_Single_Page_Anwendung
services.AddControllersWithViews(); services.AddControllersWithViews();
// Sorgt dafür, das jedesmal wenn ein ISpeiseRep angefragt wird, wird ein FileSpeiseRep zurückgegeben // Sorgt dafür, das jedesmal wenn ein ISpeiseRep angefragt wird, wird ein FileSpeiseRep zurückgegeben
services.AddScoped<ISpeiseRepository, FileSpeiseRepository>(); services.AddScoped<ISpeiseRepository, EfSpeisenRepository>();
services.AddScoped<IKategorieRepository, FileKategorieRepository>(); services.AddScoped<IKategorieRepository, EfKategorieRepository>();
// In production, the Angular files will be served from this directory // In production, the Angular files will be served from this directory

View File

@ -1,15 +0,0 @@
using System;
namespace Aps_Single_Page_Anwendung
{
public class WeatherForecast
{
public DateTime Date { get; set; }
public int TemperatureC { get; set; }
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
public string Summary { get; set; }
}
}

View File

@ -1,31 +1,31 @@
[{ [{
"id": 1, "Id": 1,
"name": "Salate", "Name": "Salate",
"beschreibung": "Fröhlich bunte Salate" "Beschreibung": "Fröhlich bunte Salate"
}, },
{ {
"id": 2, "Id": 2,
"name": "Suppen", "Name": "Suppen",
"beschreibung": "Cremige Suppen" "Beschreibung": "Cremige Suppen"
}, },
{ {
"id": 3, "Id": 3,
"name": "Vorspeißen", "Name": "Vorspeißen",
"beschreibung": "Kleine Portionen" "Beschreibung": "Kleine Portionen"
}, },
{ {
"id": 4, "Id": 4,
"name": "Hauptgerichte", "Name": "Hauptgerichte",
"beschreibung": "Eine vielfalt aus verschiedenen Gerichten" "Beschreibung": "Eine vielfalt aus verschiedenen Gerichten"
}, },
{ {
"id": 5, "Id": 5,
"name": "Nachspeißen", "Name": "Nachspeißen",
"beschreibung": "Leckere süße Desserts" "Beschreibung": "Leckere süße Desserts"
}, },
{ {
"id": 6, "Id": 6,
"name": "Getränke", "Name": "Getränke",
"beschreibung": "Eine große Auswahl an Getränkeetränken" "Beschreibung": "Eine große Auswahl an Getränkeetränken"
} }
] ]