diff --git a/SystemKonkursow/4.2.1/angular/src/app/app-routing.module.ts b/SystemKonkursow/4.2.1/angular/src/app/app-routing.module.ts index 8245a31..5f5b874 100644 --- a/SystemKonkursow/4.2.1/angular/src/app/app-routing.module.ts +++ b/SystemKonkursow/4.2.1/angular/src/app/app-routing.module.ts @@ -10,6 +10,7 @@ import { RolesComponent } from 'app/roles/roles.component'; import { CategoriesListComponent } from '@app/categories-list/categories-list.component'; import { CompetitionsListComponent } from '@app/competitions-list/competitions-list.component'; import { CompetitionDetailComponent } from '@app/competition-detail/competition-detail.component'; +import { CompetitionCreateComponent } from '@app/competition-create/competition-create.component'; @NgModule({ imports: [ @@ -25,7 +26,8 @@ import { CompetitionDetailComponent } from '@app/competition-detail/competition- { path: 'about', component: AboutComponent }, { path: 'categories-list', component: CategoriesListComponent, canActivate: [AppRouteGuard] }, { path: 'categories-list/:id', component: CompetitionsListComponent, canActivate: [AppRouteGuard] }, - { path: 'competitions/:id', component: CompetitionDetailComponent, canActivate: [AppRouteGuard] } + { path: 'categories-list/:id/competitions/:id', component: CompetitionDetailComponent, canActivate: [AppRouteGuard] }, + { path: 'competition-create', component: CompetitionCreateComponent, data: { permission: 'Pages.Create.Competition' }, canActivate: [AppRouteGuard] }, ] } ]) diff --git a/SystemKonkursow/4.2.1/angular/src/app/app.module.ts b/SystemKonkursow/4.2.1/angular/src/app/app.module.ts index 291b192..70eb912 100644 --- a/SystemKonkursow/4.2.1/angular/src/app/app.module.ts +++ b/SystemKonkursow/4.2.1/angular/src/app/app.module.ts @@ -35,13 +35,18 @@ import { RightSideBarComponent } from '@app/layout/right-sidebar.component'; import { CategoriesListComponent } from '@app/categories-list/categories-list.component'; import { CompetitionsListComponent } from '@app/competitions-list/competitions-list.component'; import { CompetitionDetailComponent } from '@app/competition-detail/competition-detail.component'; +import { CompetitionCreateComponent } from '@app/competition-create/competition-create.component'; import { FilterClassesPipe } from '@app/pipe/filter-classes.pipe'; import { MatSelectModule, MatOptionModule, - MatFormFieldModule + MatFormFieldModule, + MatDatepickerModule, + MatNativeDateModule, + MatInputModule, + MatIconModule } from '@angular/material'; @NgModule({ @@ -67,6 +72,7 @@ import { CategoriesListComponent, CompetitionsListComponent, CompetitionDetailComponent, + CompetitionCreateComponent, FilterClassesPipe ], @@ -84,6 +90,10 @@ import { MatSelectModule, MatOptionModule, MatFormFieldModule, + MatDatepickerModule, + MatNativeDateModule, + MatInputModule, + MatIconModule ], providers: [ diff --git a/SystemKonkursow/4.2.1/angular/src/app/competition-create/competition-create.component.css b/SystemKonkursow/4.2.1/angular/src/app/competition-create/competition-create.component.css new file mode 100644 index 0000000..b7dce2f --- /dev/null +++ b/SystemKonkursow/4.2.1/angular/src/app/competition-create/competition-create.component.css @@ -0,0 +1,12 @@ +#create-competition-area { + overflow-x: hidden; +} + +.title { + color: cornflowerblue; + text-shadow: 1px 1px 1px #ab93ab; +} + +.element-size { + width: 500px; +} \ No newline at end of file diff --git a/SystemKonkursow/4.2.1/angular/src/app/competition-create/competition-create.component.html b/SystemKonkursow/4.2.1/angular/src/app/competition-create/competition-create.component.html new file mode 100644 index 0000000..45ee58e --- /dev/null +++ b/SystemKonkursow/4.2.1/angular/src/app/competition-create/competition-create.component.html @@ -0,0 +1,183 @@ +
+
+ +

Tworzenie konkursu

+ +
+
+
+ + + + Nazwa jest wymagana. + + + Przekroczono maksymalną długość nazwy, 100 znaków. + + +
+
+ +
+
+ + + + {{category.name}} + + + + Kategoria jest wymagana. + + +
+
+ +
+
+ + + + Opis jest wymagany. + + + Przekroczono maksymalną długość opisu, 1000 znaków. + + +
+
+ +
+
+ + + + Opis nagród jest wymagany. + + + Przekroczono maksymalną długość opisu nagród, 1000 znaków. + + +
+
+ +
+
+ + + + {{possibleClass.viewValue}} + + + + Minimalna klasa jest wymagana. + + +
+
+ +
+
+ + + + {{possibleClass.viewValue}} + + + + Maksymalna klasa jest wymagana. + + +
+
+ +
+
+ + + + + + Data rozpoczęcia konkursu jest nieprawidłowa. + + +
+
+ +
+
+ + + + + + Data zakończenia konkursu jest nieprawidłowa. + + +
+
+ +
+ +
+
+
+
\ No newline at end of file diff --git a/SystemKonkursow/4.2.1/angular/src/app/competition-create/competition-create.component.ts b/SystemKonkursow/4.2.1/angular/src/app/competition-create/competition-create.component.ts new file mode 100644 index 0000000..db84f0d --- /dev/null +++ b/SystemKonkursow/4.2.1/angular/src/app/competition-create/competition-create.component.ts @@ -0,0 +1,92 @@ +import { Component, OnInit, Injector, OnDestroy } from '@angular/core'; +import { appModuleAnimation } from '@shared/animations/routerTransition'; +import { CategoryServiceProxy, CategoryDto, CompetitionServiceProxy, CreateCompetitionDto } from '@shared/service-proxies/service-proxies'; +import { List } from 'lodash'; +import { AppComponentBase } from '@shared/app-component-base'; +import { Subscription } from 'rxjs/Rx'; +import { finalize } from 'rxjs/operators'; +import { Router } from '@angular/router'; +import * as moment from 'moment'; + +@Component({ + templateUrl: './competition-create.component.html', + styleUrls: ['./competition-create.component.css'], + animations: [appModuleAnimation()] +}) +export class CompetitionCreateComponent extends AppComponentBase implements OnInit, OnDestroy { + + public categoriesList: List = []; + public createCompetitionAreaId: string = 'create-competition-area'; + + public createCompetition: CreateCompetitionDto = null;; + + private categoryListSubscription: Subscription; + private createCompetitionSubscription: Subscription; + + public today: Date = new Date(); + + public possibleClasses = [ + {value: 1, viewValue: 'Klasa 1'}, + {value: 2, viewValue: 'Klasa 2'}, + {value: 3, viewValue: 'Klasa 3'}, + {value: 4, viewValue: 'Klasa 4'}, + {value: 5, viewValue: 'Klasa 5'}, + {value: 6, viewValue: 'Klasa 6'}, + {value: 7, viewValue: 'Klasa 7'}, + {value: 8, viewValue: 'Klasa 8'} + ]; + + constructor( + injector: Injector, + private _categoryService: CategoryServiceProxy, + private _competitionService: CompetitionServiceProxy, + private router: Router + ) { + super(injector); + } + + public ngOnInit() { + this.createCompetition = new CreateCompetitionDto(); + this.getCompetitionCategories(); + } + + public ngOnDestroy() { + if (this.categoryListSubscription) { + this.categoryListSubscription.unsubscribe(); + } + + if (this.createCompetitionSubscription) { + this.createCompetitionSubscription.unsubscribe(); + } + } + + private getCompetitionCategories(): void { + this.setBusy(this.createCompetitionAreaId); + + this.categoryListSubscription = this._categoryService.getAllCategories() + .pipe(finalize(() => { this.clearBusy(this.createCompetitionAreaId); })) + .subscribe((result: List) => { + this.categoriesList = result; + }); + } + + public saveCompetition(): void { + console.log('Save competition'); + console.log(this.createCompetition); + + this.createCompetition.startDate = moment(this.createCompetition.startDate, 'YYYY-MM-DD'); + this.createCompetition.endDate = moment(this.createCompetition.endDate, 'YYYY-MM-DD'); + + this.createCompetitionSubscription = this._competitionService.createCompetition(this.createCompetition) + .subscribe((result: number) => { + this.goToCategoriesList(); + this.notify.success(this.l('Zapisano pomyślnie')); + }); + + } + + public goToCategoriesList(): void { + const route: string = `app/categories-list`; + this.router.navigate([route]); + } +} \ No newline at end of file diff --git a/SystemKonkursow/4.2.1/angular/src/app/competitions-list/competitions-list.component.ts b/SystemKonkursow/4.2.1/angular/src/app/competitions-list/competitions-list.component.ts index 945b374..9465d0d 100644 --- a/SystemKonkursow/4.2.1/angular/src/app/competitions-list/competitions-list.component.ts +++ b/SystemKonkursow/4.2.1/angular/src/app/competitions-list/competitions-list.component.ts @@ -72,9 +72,9 @@ export class CompetitionsListComponent extends AppComponentBase implements OnIni } public goToDetail(competition: CompetitionDto): void { - //console.log(this.router.url); - //const route: string = this.router.url + `/${competition.id}`; - const route: string = `app/competitions/${competition.id}`; + console.log(this.router.url); + const route: string = this.router.url + `/competitions/${competition.id}`; + //const route: string = `app/competitions/${competition.id}`; this.router.navigate([route]); } diff --git a/SystemKonkursow/4.2.1/angular/src/app/layout/sidebar-nav.component.ts b/SystemKonkursow/4.2.1/angular/src/app/layout/sidebar-nav.component.ts index 7d2d594..1c30dc2 100644 --- a/SystemKonkursow/4.2.1/angular/src/app/layout/sidebar-nav.component.ts +++ b/SystemKonkursow/4.2.1/angular/src/app/layout/sidebar-nav.component.ts @@ -13,6 +13,7 @@ export class SideBarNavComponent extends AppComponentBase { new MenuItem(this.l("Strona domowa"), "", "home", "/app/home"), new MenuItem(this.l("Konkursy"), "", "list", "/app/categories-list"), + new MenuItem(this.l("Dodaj konkurs"), "Pages.Create.Competition", "add", "/app/competition-create"), new MenuItem(this.l("Tenants"), "Pages.Tenants", "business", "/app/tenants"), new MenuItem(this.l("Użytkownicy"), "Pages.Users", "people", "/app/users"), diff --git a/SystemKonkursow/4.2.1/angular/src/shared/service-proxies/service-proxies.ts b/SystemKonkursow/4.2.1/angular/src/shared/service-proxies/service-proxies.ts index a2c9dba..b0d7c2e 100644 --- a/SystemKonkursow/4.2.1/angular/src/shared/service-proxies/service-proxies.ts +++ b/SystemKonkursow/4.2.1/angular/src/shared/service-proxies/service-proxies.ts @@ -207,6 +207,74 @@ export class CategoryServiceProxy { } } +@Injectable() +export class CompetitionServiceProxy { + private http: HttpClient; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(@Inject(HttpClient) http: HttpClient, @Optional() @Inject(API_BASE_URL) baseUrl?: string) { + this.http = http; + this.baseUrl = baseUrl ? baseUrl : ""; + } + + /** + * @createCompetitionDto (optional) + * @return Success + */ + createCompetition(createCompetitionDto: CreateCompetitionDto | null | undefined): Observable { + let url_ = this.baseUrl + "/api/services/app/Competition/CreateCompetition"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(createCompetitionDto); + + let options_ : any = { + body: content_, + observe: "response", + responseType: "blob", + headers: new HttpHeaders({ + "Content-Type": "application/json", + "Accept": "application/json" + }) + }; + + return this.http.request("post", url_, options_).pipe(_observableMergeMap((response_ : any) => { + return this.processCreateCompetition(response_); + })).pipe(_observableCatch((response_: any) => { + if (response_ instanceof HttpResponseBase) { + try { + return this.processCreateCompetition(response_); + } catch (e) { + return >_observableThrow(e); + } + } else + return >_observableThrow(response_); + })); + } + + protected processCreateCompetition(response: HttpResponseBase): Observable { + const status = response.status; + const responseBlob = + response instanceof HttpResponse ? response.body : + (response).error instanceof Blob ? (response).error : undefined; + + let _headers: any = {}; if (response.headers) { for (let key of response.headers.keys()) { _headers[key] = response.headers.get(key); }}; + if (status === 200) { + return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => { + let result200: any = null; + let resultData200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver); + result200 = resultData200 !== undefined ? resultData200 : null; + return _observableOf(result200); + })); + } else if (status !== 200 && status !== 204) { + return blobToText(responseBlob).pipe(_observableMergeMap(_responseText => { + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + })); + } + return _observableOf(null); + } +} + @Injectable() export class CompetitionCategoryServiceProxy { private http: HttpClient; @@ -1959,6 +2027,85 @@ export interface ICategoryDto { id: number | undefined; } +export class CreateCompetitionDto implements ICreateCompetitionDto { + name: string | undefined; + startDate: moment.Moment | undefined; + endDate: moment.Moment | undefined; + description: string | undefined; + prize: string | undefined; + minClass: number | undefined; + maxClass: number | undefined; + categoriesId: number[] | undefined; + + constructor(data?: ICreateCompetitionDto) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(data?: any) { + if (data) { + this.name = data["name"]; + this.startDate = data["startDate"] ? moment(data["startDate"].toString()) : undefined; + this.endDate = data["endDate"] ? moment(data["endDate"].toString()) : undefined; + this.description = data["description"]; + this.prize = data["prize"]; + this.minClass = data["minClass"]; + this.maxClass = data["maxClass"]; + if (data["categoriesId"] && data["categoriesId"].constructor === Array) { + this.categoriesId = []; + for (let item of data["categoriesId"]) + this.categoriesId.push(item); + } + } + } + + static fromJS(data: any): CreateCompetitionDto { + data = typeof data === 'object' ? data : {}; + let result = new CreateCompetitionDto(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["name"] = this.name; + data["startDate"] = this.startDate ? this.startDate.toISOString() : undefined; + data["endDate"] = this.endDate ? this.endDate.toISOString() : undefined; + data["description"] = this.description; + data["prize"] = this.prize; + data["minClass"] = this.minClass; + data["maxClass"] = this.maxClass; + if (this.categoriesId && this.categoriesId.constructor === Array) { + data["categoriesId"] = []; + for (let item of this.categoriesId) + data["categoriesId"].push(item); + } + return data; + } + + clone(): CreateCompetitionDto { + const json = this.toJSON(); + let result = new CreateCompetitionDto(); + result.init(json); + return result; + } +} + +export interface ICreateCompetitionDto { + name: string | undefined; + startDate: moment.Moment | undefined; + endDate: moment.Moment | undefined; + description: string | undefined; + prize: string | undefined; + minClass: number | undefined; + maxClass: number | undefined; + categoriesId: number[] | undefined; +} + export class CompetitionDto implements ICompetitionDto { name: string | undefined; startDate: moment.Moment | undefined; diff --git a/SystemKonkursow/4.2.1/angular/src/shared/service-proxies/service-proxy.module.ts b/SystemKonkursow/4.2.1/angular/src/shared/service-proxies/service-proxy.module.ts index 22a58d9..5db6691 100644 --- a/SystemKonkursow/4.2.1/angular/src/shared/service-proxies/service-proxy.module.ts +++ b/SystemKonkursow/4.2.1/angular/src/shared/service-proxies/service-proxy.module.ts @@ -15,6 +15,7 @@ import * as ApiServiceProxies from './service-proxies'; ApiServiceProxies.ConfigurationServiceProxy, ApiServiceProxies.CategoryServiceProxy, ApiServiceProxies.CompetitionCategoryServiceProxy, + ApiServiceProxies.CompetitionServiceProxy, { provide: HTTP_INTERCEPTORS, useClass: AbpHttpInterceptor, multi: true } ] }) diff --git a/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Application/Competition/CompetitionCategory/CompetitionAppService.cs b/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Application/Competition/CompetitionCategory/CompetitionAppService.cs index eea9d11..9bf400f 100644 --- a/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Application/Competition/CompetitionCategory/CompetitionAppService.cs +++ b/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Application/Competition/CompetitionCategory/CompetitionAppService.cs @@ -27,6 +27,8 @@ namespace SystemKonkursow.Competition.CompetitionCategory var mappedCompetition = ObjectMapper.Map(createCompetitionDto); mappedCompetition.CreatorUserId = user.Id; + mappedCompetition.StartDate = DateHelper.GetLocalTime(createCompetitionDto.StartDate); + mappedCompetition.EndDate = DateHelper.GetLocalTime(createCompetitionDto.EndDate); var newCompetitionId = await _competitionRepository.InsertAndGetIdAsync(mappedCompetition); diff --git a/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Application/Competition/CompetitionCategory/Dto/CompetitionCategoryMapProfile.cs b/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Application/Competition/CompetitionCategory/Dto/CompetitionCategoryMapProfile.cs index cce62a4..f4d6c1c 100644 --- a/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Application/Competition/CompetitionCategory/Dto/CompetitionCategoryMapProfile.cs +++ b/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Application/Competition/CompetitionCategory/Dto/CompetitionCategoryMapProfile.cs @@ -7,6 +7,7 @@ namespace SystemKonkursow.Competition.CompetitionCategory.Dto public CompetitionCategoryMapProfile() { CreateMap() + .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.CompetitionId)) .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Competition.Name)) .ForMember(dest => dest.StartDate, opt => opt.MapFrom(src => src.Competition.StartDate)) .ForMember(dest => dest.EndDate, opt => opt.MapFrom(src => src.Competition.EndDate)) diff --git a/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Core/DateHelper.cs b/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Core/DateHelper.cs new file mode 100644 index 0000000..56e852a --- /dev/null +++ b/SystemKonkursow/4.2.1/aspnet-core/src/SystemKonkursow.Core/DateHelper.cs @@ -0,0 +1,13 @@ +using System; + +namespace SystemKonkursow +{ + public static class DateHelper + { + public static DateTime GetLocalTime(DateTime dateTime) + { + TimeZoneInfo timeZone = TimeZoneInfo.Local; + return TimeZoneInfo.ConvertTime(dateTime, timeZone); + } + } +}