├── .gitattributes ├── .github └── workflows │ ├── build-test-publish.yaml │ └── deploy-to-azure.yaml ├── .gitignore ├── .vscode └── launch.json ├── CNAME ├── DEVELOPER_DOCUMENTATION.md ├── LICENSE ├── README.md ├── USER_DOCUMENTATION.md ├── docs ├── .gitignore ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── _config.yml ├── back-end │ ├── adding-entities.md │ ├── database-providers │ │ ├── in-memory-provider.md │ │ ├── index.md │ │ ├── sql-server-provider.md │ │ └── sqlite-provider.md │ └── index.md ├── browser-app │ └── index.md ├── front-end │ └── index.md ├── getting-started.md ├── index.md └── web-api │ ├── adding-entities.md │ ├── index.md │ ├── sql-server-provider.md │ └── sqlite-provider.md ├── reports ├── 20241031.md ├── 20241106.md ├── 20241113.md ├── 20241204.md └── reports.md └── src ├── .dockerignore ├── LightNap.Core.Tests ├── LightNap.Core.Tests.csproj ├── Services │ ├── AdministratorServiceTests.cs │ ├── IdentityServiceTests.cs │ ├── ProfileServiceTests.cs │ ├── PublicServiceTests.cs │ └── UserServiceTests.cs └── Utilities │ ├── TestCookieManager.cs │ ├── TestHelper.cs │ └── TestUserContext.cs ├── LightNap.Core ├── Administrator │ ├── Dto │ │ ├── Request │ │ │ ├── SearchAdminUsersRequestDto.cs │ │ │ └── UpdateAdminUserDto.cs │ │ └── Response │ │ │ ├── AdminDeviceDto.cs │ │ │ └── AdminUserDto.cs │ ├── Interfaces │ │ └── IAdministratorService.cs │ ├── Models │ │ └── ApplicationUserSortBy.cs │ └── Services │ │ └── AdministratorService.cs ├── Api │ ├── OptionDto.cs │ ├── PagedResponseDto.cs │ ├── PaginationRequestDtoBase.cs │ └── UserFriendlyApiException.cs ├── ClassDesires │ ├── Dto │ │ ├── Request │ │ │ ├── CreateClassDesireDto.cs │ │ │ ├── SearchClassDesireDto.cs │ │ │ └── UpdateClassDesireDto.cs │ │ └── Response │ │ │ └── ClassDesireDto.cs │ ├── Extensions │ │ └── ClassDesireExtensions.cs │ ├── Interfaces │ │ └── IClassDesireService.cs │ └── Services │ │ └── ClassDesireService.cs ├── ClassInfos │ ├── Dto │ │ ├── Request │ │ │ ├── CreateClassInfoDto.cs │ │ │ ├── SearchClassInfoDto.cs │ │ │ └── UpdateClassInfoDto.cs │ │ └── Response │ │ │ ├── ClassInfoDto.cs │ │ │ └── ClassTimeDto.cs │ ├── Extensions │ │ ├── ClassInfoExtensions.cs │ │ └── ClassTimeExtensions.cs │ ├── Interfaces │ │ └── IClassInfoService.cs │ └── Services │ │ └── ClassInfoService.cs ├── ClassUsers │ ├── Dto │ │ ├── Request │ │ │ ├── CreateClassUserDto.cs │ │ │ ├── SearchClassUserDto.cs │ │ │ └── UpdateClassUserDto.cs │ │ └── Response │ │ │ └── ClassUserDto.cs │ ├── Extensions │ │ └── ClassUserExtensions.cs │ ├── Interfaces │ │ └── IClassUserService.cs │ └── Services │ │ └── ClassUserService.cs ├── Configuration │ ├── ApplicationSettings.cs │ └── Constants.cs ├── Data │ ├── ApplicationDbContext.cs │ ├── Converters │ │ ├── BrowserSettingsConverter.cs │ │ └── UtcValueConverter.cs │ └── Entities │ │ ├── ApplicationRole.cs │ │ ├── ApplicationRoles.cs │ │ ├── ApplicationUser.cs │ │ ├── ChatMessage.cs │ │ ├── ClassDesire.cs │ │ ├── ClassInfo.cs │ │ ├── ClassTime.cs │ │ ├── ClassUser.cs │ │ ├── RefreshToken.cs │ │ ├── TradeRequest.cs │ │ └── TradeRequestStatus.cs ├── Extensions │ ├── ApplicationRoleExtensions.cs │ ├── ApplicationServiceExtensions.cs │ ├── ApplicationUserExtensions.cs │ ├── IConfigurationExtensions.cs │ └── RefreshTokenExtensions.cs ├── Identity │ ├── Dto │ │ ├── Request │ │ │ ├── LoginRequestDto.cs │ │ │ ├── NewPasswordRequestDto.cs │ │ │ ├── RegisterRequestDto.cs │ │ │ ├── ResetPasswordRequestDto.cs │ │ │ └── VerifyCodeRequestDto.cs │ │ └── Response │ │ │ ├── LoginResultDto.cs │ │ │ └── RoleDto.cs │ ├── Interfaces │ │ └── IIdentityService.cs │ └── Services │ │ └── IdentityService.cs ├── Interfaces │ ├── ICookieManager.cs │ ├── IEmailService.cs │ ├── ITokenService.cs │ └── IUserContext.cs ├── LightNap.Core.csproj ├── Profile │ ├── Dto │ │ ├── Request │ │ │ ├── ChangePasswordRequestDto.cs │ │ │ └── UpdateProfileDto.cs │ │ └── Response │ │ │ ├── BrowserSettingsDto.cs │ │ │ ├── DeviceDto.cs │ │ │ └── ProfileDto.cs │ ├── Helpers │ │ └── BrowserSettingsMigration.cs │ ├── Interfaces │ │ └── IProfileService.cs │ └── Services │ │ └── ProfileService.cs ├── Public │ ├── Interfaces │ │ └── IPublicService.cs │ └── Services │ │ └── PublicService.cs ├── Services │ ├── LogToConsoleEmailService.cs │ ├── SmtpEmailService.cs │ └── TokenService.cs ├── TradeRequests │ ├── Dto │ │ ├── Request │ │ │ ├── CreateChatMessageDto.cs │ │ │ ├── CreateTradeRequestDto.cs │ │ │ ├── SearchTradeRequestDto.cs │ │ │ └── UpdateTradeRequestDto.cs │ │ └── Response │ │ │ ├── ChatMessageDto.cs │ │ │ └── TradeRequestDto.cs │ ├── Extensions │ │ ├── ChatMessageExtensions.cs │ │ └── TradeRequestExtensions.cs │ ├── Interfaces │ │ └── ITradeRequestService.cs │ └── Services │ │ └── TradeRequestService.cs └── User │ ├── Interfaces │ └── IUserService.cs │ └── Services │ └── UserService.cs ├── LightNap.DataProviders.SqlServer ├── Extensions │ └── ApplicationServiceExtensions.cs ├── LightNap.DataProviders.SqlServer.csproj └── Migrations │ ├── 20241024065346_InitialCreate.Designer.cs │ ├── 20241024065346_InitialCreate.cs │ ├── 20241209063223_AddCourseData.Designer.cs │ ├── 20241209063223_AddCourseData.cs │ └── ApplicationDbContextModelSnapshot.cs ├── LightNap.DataProviders.Sqlite ├── Extensions │ └── ApplicationServiceExtensions.cs ├── LightNap.DataProviders.Sqlite.csproj └── Migrations │ ├── 20241024065815_InitialCreate.Designer.cs │ ├── 20241024065815_InitialCreate.cs │ ├── 20241209063246_AddCourseData.Designer.cs │ ├── 20241209063246_AddCourseData.cs │ └── ApplicationDbContextModelSnapshot.cs ├── LightNap.MaintenanceService ├── Dockerfile ├── IMaintenanceTask.cs ├── LightNap.MaintenanceService.csproj ├── MainService.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Tasks │ ├── CountUsersMaintenanceTask.cs │ ├── PurgeExpiredRefreshTokensMaintenanceTask.cs │ └── SyncClassesTask.cs └── appsettings.json ├── LightNap.WebApi ├── Api │ ├── ApiResponseDto.cs │ └── ApiResponseType.cs ├── Configuration │ ├── AdministratorConfiguration.cs │ ├── Policies.cs │ └── Seeder.cs ├── Controllers │ ├── AdministratorController.cs │ ├── ClassDesiresController.cs │ ├── ClassInfosController.cs │ ├── ClassUsersController.cs │ ├── IdentityController.cs │ ├── ProfileController.cs │ ├── PublicController.cs │ ├── TradeRequestsController.cs │ └── UserController.cs ├── Dockerfile ├── Extensions │ ├── ApplicationServiceExtensions.cs │ └── ClaimsPrincipalExtensions.cs ├── LightNap.WebApi.csproj ├── LightNap.WebApi.http ├── Middleware │ └── ExceptionMiddleware.cs ├── Program.cs ├── Properties │ └── launchSettings.json ├── Services │ ├── WebCookieManager.cs │ └── WebUserContext.cs └── appsettings.json ├── LightNap.sln ├── Scaffolding ├── LightNap.Scaffolding.Tests │ ├── LightNap.Scaffolding.Tests.csproj │ ├── TemplateParametersTests.cs │ ├── TemplateProcessorTests.cs │ ├── TypeHelperTests.cs │ └── TypePropertyDetailsTests.cs ├── LightNap.Scaffolding.sln └── LightNap.Scaffolding │ ├── AssemblyManager │ ├── AssemblyManager.cs │ ├── IAssemblyManager.cs │ ├── TypeHelper.cs │ └── TypePropertyDetails.cs │ ├── LightNap.Scaffolding.csproj │ ├── Program.cs │ ├── ProjectManager │ ├── IProjectManager.cs │ ├── ProjectBuildResult.cs │ └── ProjectManager.cs │ ├── Properties │ └── launchSettings.json │ ├── ServiceRunner │ ├── ServiceParameters.cs │ └── ServiceRunner.cs │ ├── TemplateManager │ ├── ITemplateManager.cs │ ├── TemplateItem.cs │ ├── TemplateManager.cs │ ├── TemplateParameters.cs │ └── TemplateProcessor.cs │ └── Templates │ ├── Client │ ├── create-request.ts.txt │ ├── create.component.html.txt │ ├── create.component.ts.txt │ ├── data.service.ts.txt │ ├── edit.component.html.txt │ ├── edit.component.ts.txt │ ├── get.component.html.txt │ ├── get.component.ts.txt │ ├── index.component.html.txt │ ├── index.component.ts.txt │ ├── response.ts.txt │ ├── routes.ts.txt │ ├── search-request.ts.txt │ ├── service.ts.txt │ └── update-request.ts.txt │ └── Server │ ├── Controller.cs.txt │ ├── CreateDto.cs.txt │ ├── Dto.cs.txt │ ├── Extensions.cs.txt │ ├── Interface.cs.txt │ ├── SearchDto.cs.txt │ ├── Service.cs.txt │ └── UpdateDto.cs.txt ├── lightnap-ng ├── .editorconfig ├── .eslintrc.json ├── .gitignore ├── LICENSE.md ├── README.md ├── angular.json ├── karma.conf.js ├── package-lock.json ├── package.json ├── src │ ├── .prettierrc │ ├── app │ │ ├── admin │ │ │ ├── components │ │ │ │ └── pages │ │ │ │ │ ├── index │ │ │ │ │ ├── index.component.html │ │ │ │ │ └── index.component.ts │ │ │ │ │ ├── role │ │ │ │ │ ├── role.component.html │ │ │ │ │ └── role.component.ts │ │ │ │ │ ├── roles │ │ │ │ │ ├── roles.component.html │ │ │ │ │ └── roles.component.ts │ │ │ │ │ ├── routes.ts │ │ │ │ │ ├── user │ │ │ │ │ ├── user.component.html │ │ │ │ │ └── user.component.ts │ │ │ │ │ └── users │ │ │ │ │ ├── users.component.html │ │ │ │ │ └── users.component.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── admin-user-with-roles.ts │ │ │ │ ├── index.ts │ │ │ │ ├── request │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── search-admin-users-request.ts │ │ │ │ │ ├── search-admin-users-sort-by.ts │ │ │ │ │ └── update-admin-user-request.ts │ │ │ │ ├── response │ │ │ │ │ ├── admin-device.ts │ │ │ │ │ ├── admin-user.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── role.ts │ │ │ │ └── role-with-admin-users.ts │ │ │ └── services │ │ │ │ ├── admin.service.spec.ts │ │ │ │ ├── admin.service.ts │ │ │ │ └── data.service.ts │ │ ├── app.component.html │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── class-infos │ │ │ ├── components │ │ │ │ ├── controls │ │ │ │ │ └── class-info │ │ │ │ │ │ ├── class-info.component.html │ │ │ │ │ │ └── class-info.component.ts │ │ │ │ └── pages │ │ │ │ │ ├── class-desires │ │ │ │ │ ├── create │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ ├── edit │ │ │ │ │ │ ├── edit.component.html │ │ │ │ │ │ └── edit.component.ts │ │ │ │ │ ├── get │ │ │ │ │ │ ├── get.component.html │ │ │ │ │ │ └── get.component.ts │ │ │ │ │ ├── my-classes │ │ │ │ │ │ ├── my-classes.component.html │ │ │ │ │ │ └── my-classes.component.ts │ │ │ │ │ └── routes.ts │ │ │ │ │ ├── class-infos │ │ │ │ │ ├── create │ │ │ │ │ │ ├── create.component.html │ │ │ │ │ │ └── create.component.ts │ │ │ │ │ ├── edit │ │ │ │ │ │ ├── edit.component.html │ │ │ │ │ │ └── edit.component.ts │ │ │ │ │ ├── get │ │ │ │ │ │ ├── get.component.html │ │ │ │ │ │ └── get.component.ts │ │ │ │ │ ├── index │ │ │ │ │ │ ├── index.component.html │ │ │ │ │ │ └── index.component.ts │ │ │ │ │ └── routes.ts │ │ │ │ │ └── class-users │ │ │ │ │ ├── create │ │ │ │ │ ├── create.component.html │ │ │ │ │ └── create.component.ts │ │ │ │ │ ├── edit │ │ │ │ │ ├── edit.component.html │ │ │ │ │ └── edit.component.ts │ │ │ │ │ ├── get │ │ │ │ │ ├── get.component.html │ │ │ │ │ └── get.component.ts │ │ │ │ │ ├── my-classes │ │ │ │ │ ├── my-classes.component.html │ │ │ │ │ └── my-classes.component.ts │ │ │ │ │ └── routes.ts │ │ │ ├── helpers │ │ │ │ ├── class-info.helper.ts │ │ │ │ └── class-user.helper.ts │ │ │ ├── models │ │ │ │ ├── class-user-info.ts │ │ │ │ ├── request │ │ │ │ │ ├── create-class-desire-request.ts │ │ │ │ │ ├── create-class-info-request.ts │ │ │ │ │ ├── create-class-user-request.ts │ │ │ │ │ ├── search-class-desires-request.ts │ │ │ │ │ ├── search-class-infos-request.ts │ │ │ │ │ ├── search-class-users-request.ts │ │ │ │ │ ├── update-class-desire-request.ts │ │ │ │ │ ├── update-class-info-request.ts │ │ │ │ │ └── update-class-user-request.ts │ │ │ │ ├── response │ │ │ │ │ ├── class-desire.ts │ │ │ │ │ ├── class-info.ts │ │ │ │ │ └── class-user.ts │ │ │ │ └── user-classes.ts │ │ │ └── services │ │ │ │ ├── class-info.service.ts │ │ │ │ └── data.service.ts │ │ ├── core │ │ │ ├── components │ │ │ │ ├── controls │ │ │ │ │ ├── api-response │ │ │ │ │ │ ├── api-response.component.html │ │ │ │ │ │ └── api-response.component.ts │ │ │ │ │ ├── confirm-dialog │ │ │ │ │ │ ├── confirm-dialog.component.html │ │ │ │ │ │ └── confirm-dialog.component.ts │ │ │ │ │ ├── confirm-popup │ │ │ │ │ │ ├── confirm-popup.component.html │ │ │ │ │ │ └── confirm-popup.component.ts │ │ │ │ │ ├── dropdown-list-item │ │ │ │ │ │ ├── dropdown-list-item.component.html │ │ │ │ │ │ └── dropdown-list-item.component.ts │ │ │ │ │ ├── error-list │ │ │ │ │ │ ├── error-list.component.html │ │ │ │ │ │ └── error-list.component.ts │ │ │ │ │ └── index.ts │ │ │ │ └── index.ts │ │ │ ├── guards │ │ │ │ ├── admin.guard.ts │ │ │ │ ├── auth.guard.ts │ │ │ │ ├── can-deactivate.guard.ts │ │ │ │ └── can-deactivate.ts │ │ │ ├── helpers │ │ │ │ ├── form-helpers.ts │ │ │ │ ├── index.ts │ │ │ │ ├── injection-tokens.ts │ │ │ │ └── rxjs-helpers.ts │ │ │ ├── index.ts │ │ │ ├── interceptors │ │ │ │ ├── api-response-interceptor.spec.ts │ │ │ │ ├── api-response-interceptor.ts │ │ │ │ ├── token-interceptor.spec.ts │ │ │ │ └── token-interceptor.ts │ │ │ ├── models │ │ │ │ ├── api │ │ │ │ │ ├── api-response-type.ts │ │ │ │ │ ├── api-response.ts │ │ │ │ │ ├── empty-paged-response.ts │ │ │ │ │ ├── error-api-response.ts │ │ │ │ │ ├── http-error-api-response.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── option.ts │ │ │ │ │ ├── paged-response.ts │ │ │ │ │ ├── pagination-request.ts │ │ │ │ │ └── success-api-response.ts │ │ │ │ ├── block-ui-params.ts │ │ │ │ ├── button-severity.ts │ │ │ │ ├── extended-map.ts │ │ │ │ ├── index.ts │ │ │ │ ├── list-item-group.ts │ │ │ │ └── list-item.ts │ │ │ └── services │ │ │ │ ├── block-ui.service.spec.ts │ │ │ │ ├── block-ui.service.ts │ │ │ │ ├── index.ts │ │ │ │ ├── initialization.service.ts │ │ │ │ ├── timer.service.spec.ts │ │ │ │ ├── timer.service.ts │ │ │ │ ├── toast.service.spec.ts │ │ │ │ └── toast.service.ts │ │ ├── identity │ │ │ ├── components │ │ │ │ └── pages │ │ │ │ │ ├── login │ │ │ │ │ ├── login.component.html │ │ │ │ │ └── login.component.ts │ │ │ │ │ ├── new-password │ │ │ │ │ ├── new-password.component.html │ │ │ │ │ └── new-password.component.ts │ │ │ │ │ ├── register │ │ │ │ │ ├── register.component.html │ │ │ │ │ └── register.component.ts │ │ │ │ │ ├── reset-instructions-sent │ │ │ │ │ ├── reset-instructions-sent.component.html │ │ │ │ │ └── reset-instructions-sent.component.ts │ │ │ │ │ ├── reset-password │ │ │ │ │ ├── reset-password.component.html │ │ │ │ │ └── reset-password.component.ts │ │ │ │ │ ├── routes.ts │ │ │ │ │ └── verify-code │ │ │ │ │ ├── verify-code.component.html │ │ │ │ │ └── verify-code.component.ts │ │ │ ├── directives │ │ │ │ ├── hide-by-roles.directive.ts │ │ │ │ ├── hide-logged-in.directive.ts │ │ │ │ ├── index.ts │ │ │ │ ├── show-by-roles.directive.ts │ │ │ │ └── show-logged-in.directive.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── index.ts │ │ │ │ ├── request │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── login-request.ts │ │ │ │ │ ├── new-password-request.ts │ │ │ │ │ ├── register-request.ts │ │ │ │ │ ├── reset-password-request.ts │ │ │ │ │ └── verify-code-request.ts │ │ │ │ └── response │ │ │ │ │ ├── index.ts │ │ │ │ │ └── login-result.ts │ │ │ └── services │ │ │ │ ├── data.service.ts │ │ │ │ ├── identity.service.spec.ts │ │ │ │ ├── identity.service.ts │ │ │ │ └── index.ts │ │ ├── layout │ │ │ ├── components │ │ │ │ ├── controls │ │ │ │ │ ├── app-config │ │ │ │ │ │ ├── app-config.component.html │ │ │ │ │ │ └── app-config.component.ts │ │ │ │ │ ├── app-footer │ │ │ │ │ │ ├── app-footer.component.html │ │ │ │ │ │ └── app-footer.component.ts │ │ │ │ │ ├── app-menu-item │ │ │ │ │ │ ├── app-menu-item.component.html │ │ │ │ │ │ └── app-menu-item.component.ts │ │ │ │ │ ├── app-menu │ │ │ │ │ │ ├── app-menu.component.html │ │ │ │ │ │ └── app-menu.component.ts │ │ │ │ │ ├── app-sidebar │ │ │ │ │ │ ├── app-sidebar.component.html │ │ │ │ │ │ └── app-sidebar.component.ts │ │ │ │ │ └── app-top-bar │ │ │ │ │ │ ├── app-top-bar.component.html │ │ │ │ │ │ └── app-top-bar.component.ts │ │ │ │ └── layouts │ │ │ │ │ ├── app-layout │ │ │ │ │ ├── app-layout.component.html │ │ │ │ │ └── app-layout.component.ts │ │ │ │ │ └── focus-content-layout │ │ │ │ │ ├── focus-content-layout.component.html │ │ │ │ │ └── focus-content-layout.component.ts │ │ │ ├── models │ │ │ │ ├── layout-state.ts │ │ │ │ └── menu-change-event.ts │ │ │ └── services │ │ │ │ ├── layout.service.ts │ │ │ │ └── menu.service.ts │ │ ├── profile │ │ │ ├── components │ │ │ │ └── pages │ │ │ │ │ ├── change-password │ │ │ │ │ ├── change-password.component.html │ │ │ │ │ └── change-password.component.ts │ │ │ │ │ ├── devices │ │ │ │ │ ├── devices.component.html │ │ │ │ │ └── devices.component.ts │ │ │ │ │ ├── index │ │ │ │ │ ├── index.component.html │ │ │ │ │ └── index.component.ts │ │ │ │ │ └── routes.ts │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── index.ts │ │ │ │ ├── request │ │ │ │ │ ├── change-password-request.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── update-profile-request.ts │ │ │ │ ├── response │ │ │ │ │ ├── application-settings.ts │ │ │ │ │ ├── device.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ └── profile.ts │ │ │ │ └── settings │ │ │ │ │ ├── extended-settings.ts │ │ │ │ │ ├── features-settings.ts │ │ │ │ │ ├── index.ts │ │ │ │ │ ├── prefereces-settings.ts │ │ │ │ │ └── style-settings.ts │ │ │ └── services │ │ │ │ ├── data.service.ts │ │ │ │ ├── profile.service.spec.ts │ │ │ │ └── profile.service.ts │ │ ├── public │ │ │ ├── components │ │ │ │ ├── pages │ │ │ │ │ ├── index │ │ │ │ │ │ ├── index.component.html │ │ │ │ │ │ └── index.component.ts │ │ │ │ │ └── routes.ts │ │ │ │ └── support │ │ │ │ │ ├── access-denied │ │ │ │ │ ├── access-denied.component.html │ │ │ │ │ └── access-denied.component.ts │ │ │ │ │ ├── error │ │ │ │ │ ├── error.component.html │ │ │ │ │ └── error.component.ts │ │ │ │ │ ├── not-found │ │ │ │ │ ├── not-found.component.html │ │ │ │ │ └── not-found.component.ts │ │ │ │ │ ├── privacy-policy │ │ │ │ │ ├── privacy-policy.component.html │ │ │ │ │ └── privacy-policy.component.ts │ │ │ │ │ └── terms-and-conditions │ │ │ │ │ ├── terms-and-conditions.component.html │ │ │ │ │ └── terms-and-conditions.component.ts │ │ │ └── services │ │ │ │ ├── data.service.ts │ │ │ │ └── public.service.ts │ │ ├── routing │ │ │ ├── index.ts │ │ │ ├── models │ │ │ │ ├── app-route.ts │ │ │ │ ├── index.ts │ │ │ │ ├── route-alias.ts │ │ │ │ └── route-data.ts │ │ │ ├── pipes │ │ │ │ ├── index.ts │ │ │ │ └── route.pipe.ts │ │ │ ├── routes.ts │ │ │ └── services │ │ │ │ ├── index.ts │ │ │ │ ├── route-alias-service.spec.ts │ │ │ │ └── route-alias-service.ts │ │ ├── trade-requests │ │ │ ├── components │ │ │ │ ├── controls │ │ │ │ │ ├── trade-class-user-infos-display │ │ │ │ │ │ ├── trade-class-user-infos-display.component.html │ │ │ │ │ │ └── trade-class-user-infos-display.component.ts │ │ │ │ │ └── trade-request-chat │ │ │ │ │ │ ├── trade-request-chat.component.html │ │ │ │ │ │ └── trade-request-chat.component.ts │ │ │ │ └── pages │ │ │ │ │ ├── completed-swaps │ │ │ │ │ ├── completed-swaps.component.html │ │ │ │ │ └── completed-swaps.component.ts │ │ │ │ │ ├── create │ │ │ │ │ ├── create.component.html │ │ │ │ │ └── create.component.ts │ │ │ │ │ ├── edit │ │ │ │ │ ├── edit.component.html │ │ │ │ │ └── edit.component.ts │ │ │ │ │ ├── get │ │ │ │ │ ├── get.component.html │ │ │ │ │ └── get.component.ts │ │ │ │ │ ├── incoming-swaps │ │ │ │ │ ├── incoming-swaps.component.html │ │ │ │ │ └── incoming-swaps.component.ts │ │ │ │ │ ├── index │ │ │ │ │ ├── index.component.html │ │ │ │ │ └── index.component.ts │ │ │ │ │ ├── offer-swap │ │ │ │ │ ├── offer-swap.component.html │ │ │ │ │ └── offer-swap.component.ts │ │ │ │ │ ├── outgoing-swaps │ │ │ │ │ ├── outgoing-swaps.component.html │ │ │ │ │ └── outgoing-swaps.component.ts │ │ │ │ │ ├── routes.ts │ │ │ │ │ ├── view-incoming-swap │ │ │ │ │ ├── view-incoming-swap.component.html │ │ │ │ │ └── view-incoming-swap.component.ts │ │ │ │ │ └── view-outgoing-swap │ │ │ │ │ ├── view-outgoing-swap.component.html │ │ │ │ │ └── view-outgoing-swap.component.ts │ │ │ ├── helpers │ │ │ │ ├── chat-message.helper.ts │ │ │ │ └── trade-request.helper.ts │ │ │ ├── models │ │ │ │ ├── request │ │ │ │ │ ├── create-chat-message-request.ts │ │ │ │ │ ├── create-trade-request-request.ts │ │ │ │ │ ├── search-trade-requests-request.ts │ │ │ │ │ └── update-trade-request-request.ts │ │ │ │ ├── response │ │ │ │ │ ├── chat-message.ts │ │ │ │ │ └── trade-request.ts │ │ │ │ ├── trade-class-user-infos-display.ts │ │ │ │ └── trade-class-user-infos.ts │ │ │ └── services │ │ │ │ ├── data.service.ts │ │ │ │ └── trade-request.service.ts │ │ └── user │ │ │ ├── components │ │ │ └── pages │ │ │ │ ├── browse-swaps │ │ │ │ ├── browse-swaps.component.css │ │ │ │ ├── browse-swaps.component.html │ │ │ │ └── browse-swaps.component.ts │ │ │ │ ├── create-swap │ │ │ │ ├── create-swap.component.css │ │ │ │ ├── create-swap.component.html │ │ │ │ └── create-swap.component.ts │ │ │ │ ├── index │ │ │ │ ├── index.component.html │ │ │ │ └── index.component.ts │ │ │ │ ├── my-swaps │ │ │ │ ├── my-swap.component.html │ │ │ │ └── my-swap.component.ts │ │ │ │ └── routes.ts │ │ │ └── services │ │ │ ├── data.service.ts │ │ │ └── user.service.ts │ ├── assets │ │ ├── .gitkeep │ │ ├── images │ │ │ ├── access │ │ │ │ ├── asset-access.svg │ │ │ │ └── logo-orange.svg │ │ │ ├── error │ │ │ │ ├── asset-error.svg │ │ │ │ └── logo-error.svg │ │ │ └── notfound │ │ │ │ └── logo-blue.svg │ │ └── layout │ │ │ ├── images │ │ │ ├── logo-dark.png │ │ │ ├── logo-white.png │ │ │ └── themes │ │ │ │ ├── arya-blue.png │ │ │ │ ├── arya-green.png │ │ │ │ ├── arya-orange.png │ │ │ │ ├── arya-purple.png │ │ │ │ ├── bootstrap4-dark-blue.svg │ │ │ │ ├── bootstrap4-dark-purple.svg │ │ │ │ ├── bootstrap4-light-blue.svg │ │ │ │ ├── bootstrap4-light-purple.svg │ │ │ │ ├── fluent-light.png │ │ │ │ ├── lara-dark-blue.png │ │ │ │ ├── lara-dark-indigo.png │ │ │ │ ├── lara-dark-purple.png │ │ │ │ ├── lara-dark-teal.png │ │ │ │ ├── lara-light-blue.png │ │ │ │ ├── lara-light-indigo.png │ │ │ │ ├── lara-light-purple.png │ │ │ │ ├── lara-light-teal.png │ │ │ │ ├── luna-amber.png │ │ │ │ ├── luna-blue.png │ │ │ │ ├── luna-green.png │ │ │ │ ├── luna-pink.png │ │ │ │ ├── md-dark-deeppurple.svg │ │ │ │ ├── md-dark-indigo.svg │ │ │ │ ├── md-light-deeppurple.svg │ │ │ │ ├── md-light-indigo.svg │ │ │ │ ├── saga-blue.png │ │ │ │ ├── saga-green.png │ │ │ │ ├── saga-orange.png │ │ │ │ ├── saga-purple.png │ │ │ │ ├── tailwind-light.png │ │ │ │ ├── vela-blue.png │ │ │ │ ├── vela-green.png │ │ │ │ ├── vela-orange.png │ │ │ │ └── vela-purple.png │ │ │ └── styles │ │ │ ├── layout │ │ │ ├── _config.scss │ │ │ ├── _content.scss │ │ │ ├── _footer.scss │ │ │ ├── _main.scss │ │ │ ├── _menu.scss │ │ │ ├── _mixins.scss │ │ │ ├── _preloading.scss │ │ │ ├── _responsive.scss │ │ │ ├── _topbar.scss │ │ │ ├── _typography.scss │ │ │ ├── _utils.scss │ │ │ ├── _variables.scss │ │ │ ├── layout.css │ │ │ └── layout.scss │ │ │ └── theme │ │ │ ├── arya-blue │ │ │ └── theme.css │ │ │ ├── arya-green │ │ │ └── theme.css │ │ │ ├── arya-orange │ │ │ └── theme.css │ │ │ ├── arya-purple │ │ │ └── theme.css │ │ │ ├── bootstrap4-dark-blue │ │ │ └── theme.css │ │ │ ├── bootstrap4-dark-purple │ │ │ └── theme.css │ │ │ ├── bootstrap4-light-blue │ │ │ └── theme.css │ │ │ ├── bootstrap4-light-purple │ │ │ └── theme.css │ │ │ ├── fluent-light │ │ │ └── theme.css │ │ │ ├── lara-dark-blue │ │ │ ├── fonts │ │ │ │ └── Inter-roman.var.woff2 │ │ │ └── theme.css │ │ │ ├── lara-dark-indigo │ │ │ ├── fonts │ │ │ │ └── Inter-roman.var.woff2 │ │ │ └── theme.css │ │ │ ├── lara-dark-purple │ │ │ ├── fonts │ │ │ │ └── Inter-roman.var.woff2 │ │ │ └── theme.css │ │ │ ├── lara-dark-teal │ │ │ ├── fonts │ │ │ │ └── Inter-roman.var.woff2 │ │ │ └── theme.css │ │ │ ├── lara-light-blue │ │ │ ├── fonts │ │ │ │ └── Inter-roman.var.woff2 │ │ │ └── theme.css │ │ │ ├── lara-light-indigo │ │ │ ├── fonts │ │ │ │ └── Inter-roman.var.woff2 │ │ │ └── theme.css │ │ │ ├── lara-light-purple │ │ │ ├── fonts │ │ │ │ └── Inter-roman.var.woff2 │ │ │ └── theme.css │ │ │ ├── lara-light-teal │ │ │ ├── fonts │ │ │ │ └── Inter-roman.var.woff2 │ │ │ └── theme.css │ │ │ ├── md-dark-deeppurple │ │ │ ├── fonts │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-regular.woff │ │ │ │ └── roboto-v20-latin-ext_latin-regular.woff2 │ │ │ └── theme.css │ │ │ ├── md-dark-indigo │ │ │ ├── fonts │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-regular.woff │ │ │ │ └── roboto-v20-latin-ext_latin-regular.woff2 │ │ │ └── theme.css │ │ │ ├── md-light-deeppurple │ │ │ ├── fonts │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-regular.woff │ │ │ │ └── roboto-v20-latin-ext_latin-regular.woff2 │ │ │ └── theme.css │ │ │ ├── md-light-indigo │ │ │ ├── fonts │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-regular.woff │ │ │ │ └── roboto-v20-latin-ext_latin-regular.woff2 │ │ │ └── theme.css │ │ │ ├── mdc-dark-deeppurple │ │ │ ├── fonts │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-regular.woff │ │ │ │ └── roboto-v20-latin-ext_latin-regular.woff2 │ │ │ └── theme.css │ │ │ ├── mdc-dark-indigo │ │ │ ├── fonts │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-regular.woff │ │ │ │ └── roboto-v20-latin-ext_latin-regular.woff2 │ │ │ └── theme.css │ │ │ ├── mdc-light-deeppurple │ │ │ ├── fonts │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-regular.woff │ │ │ │ └── roboto-v20-latin-ext_latin-regular.woff2 │ │ │ └── theme.css │ │ │ ├── mdc-light-indigo │ │ │ ├── fonts │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-500.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff │ │ │ │ ├── roboto-v20-latin-ext_latin-700.woff2 │ │ │ │ ├── roboto-v20-latin-ext_latin-regular.woff │ │ │ │ └── roboto-v20-latin-ext_latin-regular.woff2 │ │ │ └── theme.css │ │ │ ├── saga-blue │ │ │ └── theme.css │ │ │ ├── saga-green │ │ │ └── theme.css │ │ │ ├── saga-orange │ │ │ └── theme.css │ │ │ ├── saga-purple │ │ │ └── theme.css │ │ │ ├── tailwind-light │ │ │ ├── fonts │ │ │ │ ├── Inter-Bold.woff │ │ │ │ ├── Inter-Bold.woff2 │ │ │ │ ├── Inter-Light.woff │ │ │ │ ├── Inter-Light.woff2 │ │ │ │ ├── Inter-Medium.woff │ │ │ │ ├── Inter-Medium.woff2 │ │ │ │ ├── Inter-Regular.woff │ │ │ │ ├── Inter-Regular.woff2 │ │ │ │ ├── Inter-SemiBold.woff │ │ │ │ └── Inter-SemiBold.woff2 │ │ │ └── theme.css │ │ │ ├── vela-blue │ │ │ └── theme.css │ │ │ ├── vela-green │ │ │ └── theme.css │ │ │ ├── vela-orange │ │ │ └── theme.css │ │ │ └── vela-purple │ │ │ └── theme.css │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── styles.scss │ └── test.ts ├── tsconfig.app.json ├── tsconfig.json └── tsconfig.spec.json └── package-lock.json /.gitattributes: -------------------------------------------------------------------------------- 1 | # Ignore CSS files 2 | *.css linguist-detectable=false 3 | 4 | # Ensure C# files are recognized 5 | *.cs linguist-language=C# 6 | 7 | # Ensure TypeScript files are recognized 8 | *.ts linguist-language=TypeScript 9 | -------------------------------------------------------------------------------- /.github/workflows/deploy-to-azure.yaml: -------------------------------------------------------------------------------- 1 | name: Deploy to Azure App Service 2 | 3 | on: 4 | workflow_run: 5 | workflows: "Build, Test, and Publish" 6 | types: 7 | - completed 8 | workflow_dispatch: 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | deploy: 15 | runs-on: ubuntu-latest 16 | 17 | steps: 18 | - uses: actions/checkout@v4 19 | 20 | - name: Download build artifacts 21 | uses: actions/download-artifact@v4 22 | with: 23 | name: build-artifacts 24 | path: ./build 25 | run-id: ${{ github.event.workflow_run.id }} 26 | github-token: ${{ secrets.GITHUB_TOKEN }} 27 | 28 | - name: Deploy to Azure Web App 29 | uses: azure/webapps-deploy@v2 30 | with: 31 | app-name: ${{ secrets.AZURE_APP_SERVICE_NAME }} 32 | slot-name: 'production' 33 | publish-profile: ${{ secrets.AZURE_WEBAPP_PUBLISH_PROFILE }} 34 | package: ./build 35 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | 8 | { 9 | "type": "msedge", 10 | "request": "launch", 11 | "name": "Launch Edge against localhost", 12 | "url": "http://localhost:4200", 13 | "webRoot": "${workspaceFolder}" 14 | }, 15 | { 16 | "type": "chrome", 17 | "request": "launch", 18 | "name": "Launch Chrome against localhost", 19 | "url": "http://localhost:4200", 20 | "webRoot": "${workspaceFolder}" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /CNAME: -------------------------------------------------------------------------------- 1 | lightnap.sharplogic.com -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | _site/ -------------------------------------------------------------------------------- /docs/Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | gem "jekyll", "~> 4.3.4" # installed by `gem jekyll` 4 | # gem "webrick" # required when using Ruby >= 3 and Jekyll <= 4.2.2 5 | 6 | gem "just-the-docs", "0.10.0" # pinned to the current release 7 | # gem "just-the-docs" # always download the latest release 8 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | title: LightNap 2 | description: LightNap (lightweight .NET Core/Angular/PrimeNG) is a full stack starter kit designed to provide a boost to Single Page Applications (SPA). 3 | theme: just-the-docs 4 | 5 | url: https://lightnap.sharplogic.com 6 | 7 | aux_links: 8 | Repository: https://github.com/SharpLogic/LightNap 9 | 10 | callouts: 11 | warning: 12 | title: Warning 13 | color: red 14 | note: 15 | title: Note 16 | color: blue 17 | important: 18 | title: Important 19 | color: yellow 20 | 21 | markdown: kramdown 22 | kramdown: 23 | input: GFM 24 | auto_ids: true 25 | toc_levels: 1..6 26 | entity_output: as_char 27 | smart_quotes: lsquo,rsquo,ldquo,rdquo 28 | enable_coderay: false -------------------------------------------------------------------------------- /docs/back-end/adding-entities.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Adding Entities" 3 | description: "A guide for extending the data model." 4 | layout: home 5 | parent: Back-End 6 | nav_order: 3 7 | --- 8 | 9 | LightNap makes use of Entity Framework (EF) for database access. The `ApplicationDbContext` and supporting entities are all kept in 10 | the `Data` folder of the `LightNap.Core` project. 11 | 12 | ## Extending EF Models 13 | 14 | Follow the common EF processes to ensure the changes are correctly integrated: 15 | 16 | 1. **Add New Entity Classes**: Create new classes in the `Data` folder that represent the new entities. 17 | 2. **Update DbContext**: Add `DbSet` properties to the `ApplicationDbContext` class for each new entity. 18 | 3. **Migrations**: Use EF Core migrations to update the database schema. Run `dotnet ef migrations add ` and `dotnet ef database update` to apply changes. 19 | 4. **Configure Relationships**: Define relationships and constraints using Fluent API or data annotations in your entity classes. 20 | 21 | By following these steps, you can effectively extend the data model to meet your application's requirements. 22 | -------------------------------------------------------------------------------- /docs/back-end/database-providers/in-memory-provider.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: In-Memory Provider 3 | layout: home 4 | parent: Database Providers 5 | nav_order: 3 6 | --- 7 | 8 | An in-memory database provider is included in the project to make it easier to develop and test the solution. Since the data itself is reset 9 | across sessions, it's not suitable for production use. 10 | 11 | ## Configuration 12 | 13 | To use the In-Memory Provider: 14 | 15 | - Set the `DatabaseProvider` setting to `InMemory`. 16 | -------------------------------------------------------------------------------- /docs/back-end/database-providers/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Database Providers 3 | description: Overview of database providers. 4 | parent: Back-End 5 | layout: home 6 | nav_order: 3 7 | --- 8 | 9 | -------------------------------------------------------------------------------- /docs/back-end/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Back-End 3 | description: Overview of back-end documentation for the LightNap project. 4 | layout: home 5 | nav_order: 3 6 | --- 7 | 8 | -------------------------------------------------------------------------------- /docs/browser-app/index.md: -------------------------------------------------------------------------------- 1 | # Index 2 | -------------------------------------------------------------------------------- /docs/front-end/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Front-End 3 | description: Overview of the front-end components and structure 4 | layout: home 5 | nav_order: 4 6 | --- 7 | 8 | Front end... 9 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Home 3 | layout: home 4 | nav_order: 1 5 | --- 6 | 7 | [Getting Started](getting-started) -------------------------------------------------------------------------------- /docs/web-api/adding-entities.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Adding Entities" 3 | description: "A guide for extending the data model." 4 | tags: ["data"] 5 | --- 6 | 7 | Add your own entities... 8 | -------------------------------------------------------------------------------- /docs/web-api/index.md: -------------------------------------------------------------------------------- 1 | # Index 2 | 3 | [Adding Data Entities](./adding-entities.md) 4 | 5 | [Using SQL Server](./sql-server-provider.md) 6 | 7 | [Using SQLite](./sqlite-provider.md) 8 | -------------------------------------------------------------------------------- /src/.dockerignore: -------------------------------------------------------------------------------- 1 | **/.classpath 2 | **/.dockerignore 3 | **/.env 4 | **/.git 5 | **/.gitignore 6 | **/.project 7 | **/.settings 8 | **/.toolstarget 9 | **/.vs 10 | **/.vscode 11 | **/*.*proj.user 12 | **/*.dbmdl 13 | **/*.jfm 14 | **/azds.yaml 15 | **/bin 16 | **/charts 17 | **/docker-compose* 18 | **/Dockerfile* 19 | **/node_modules 20 | **/npm-debug.log 21 | **/obj 22 | **/secrets.dev.yaml 23 | **/values.dev.yaml 24 | LICENSE 25 | README.md 26 | !**/.gitignore 27 | !.git/HEAD 28 | !.git/config 29 | !.git/packed-refs 30 | !.git/refs/heads/** -------------------------------------------------------------------------------- /src/LightNap.Core/Administrator/Dto/Request/SearchAdminUsersRequestDto.cs: -------------------------------------------------------------------------------- 1 | using LightNap.Core.Administrator.Models; 2 | using LightNap.Core.Api; 3 | using LightNap.Core.Identity; 4 | 5 | namespace LightNap.Core.Administrator.Dto.Request 6 | { 7 | /// 8 | /// Represents a request to search users. 9 | /// 10 | public class SearchAdminUsersRequestDto : PaginationRequestDtoBase 11 | { 12 | /// 13 | /// Gets or sets the email of the user. 14 | /// 15 | public string? Email { get; set; } 16 | 17 | /// 18 | /// Gets or sets the username of the user. 19 | /// 20 | public string? UserName { get; set; } 21 | 22 | /// 23 | /// Gets or sets the field to sort the users by. 24 | /// 25 | public ApplicationUserSortBy SortBy { get; set; } 26 | 27 | /// 28 | /// Reverses the default sort behavior of the SortBy field. 29 | /// 30 | public bool ReverseSort { get; set; } 31 | } 32 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Administrator/Dto/Request/UpdateAdminUserDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Administrator.Dto.Request 2 | { 3 | /// 4 | /// The data transfer object for updating a user. Update fields here when editable user fields change. 5 | /// 6 | public class UpdateAdminUserDto 7 | { 8 | // Add other fields from the user. 9 | } 10 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Administrator/Models/ApplicationUserSortBy.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Administrator.Models 2 | { 3 | /// 4 | /// Supported user sorting options. 5 | /// 6 | public enum ApplicationUserSortBy 7 | { 8 | Email, 9 | UserName, 10 | CreatedDate, 11 | LastModifiedDate 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/LightNap.Core/Api/OptionDto.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace LightNap.Core.Api 4 | { 5 | public class OptionDto 6 | { 7 | public required string DisplayName { get; set; } 8 | public required string Key { get; set; } 9 | public required string Description { get; set; } 10 | 11 | [SetsRequiredMembers] 12 | public OptionDto(string key, string displayName, string? description = null) 13 | { 14 | this.Description = description ?? string.Empty; 15 | this.DisplayName = displayName; 16 | this.Key = key; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/LightNap.Core/Api/PaginationRequestDtoBase.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace LightNap.Core.Api 4 | { 5 | /// 6 | /// Base class for pagination requests. 7 | /// 8 | public class PaginationRequestDtoBase 9 | { 10 | private const int _maxPageSize = 50; 11 | 12 | /// 13 | /// Gets or sets the page number. Must be greater than 0. 14 | /// 15 | /// The page number. 16 | [Range(1, int.MaxValue, ErrorMessage = "Page number must be greater than 0.")] 17 | public int PageNumber { get; set; } = 1; 18 | 19 | /// 20 | /// Gets or sets the page size. Must be between 1 and 50. 21 | /// 22 | /// The page size. 23 | [Range(1, PaginationRequestDtoBase._maxPageSize, ErrorMessage = "Page size must be between 1 and 50.")] 24 | public int PageSize { get; set; } = 10; 25 | } 26 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassDesires/Dto/Request/CreateClassDesireDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.ClassDesires.Request.Dto 2 | { 3 | public class CreateClassDesireDto 4 | { 5 | // TODO: Update which fields to include when creating this item. 6 | public required string ClassInfoId { get; set; } 7 | public string UserId { get; set; } 8 | } 9 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassDesires/Dto/Request/SearchClassDesireDto.cs: -------------------------------------------------------------------------------- 1 | using LightNap.Core.Api; 2 | 3 | namespace LightNap.Core.ClassDesires.Request.Dto 4 | { 5 | public class SearchClassDesiresDto : PaginationRequestDtoBase 6 | { 7 | // TODO: Update to reflect which fields to include for searches. 8 | public string? ClassInfoId { get; set; } 9 | public string? UserId { get; set; } 10 | public bool? IsActive { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/LightNap.Core/ClassDesires/Dto/Request/UpdateClassDesireDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.ClassDesires.Request.Dto 2 | { 3 | public class UpdateClassDesireDto 4 | { 5 | // TODO: Update which fields to include when updating this item. 6 | public bool IsActive { get; set; } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/LightNap.Core/ClassDesires/Dto/Response/ClassDesireDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.ClassDesires.Response.Dto 2 | { 3 | public class ClassDesireDto 4 | { 5 | // TODO: Finalize which fields to include when returning this item. 6 | public int Id { get; set; } 7 | public string ClassInfoId { get; set; } 8 | public string UserId { get; set; } 9 | public bool IsActive { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassDesires/Interfaces/IClassDesireService.cs: -------------------------------------------------------------------------------- 1 | using LightNap.Core.Api; 2 | using LightNap.Core.ClassDesires.Request.Dto; 3 | using LightNap.Core.ClassDesires.Response.Dto; 4 | 5 | namespace LightNap.Core.ClassDesires.Interfaces 6 | { 7 | public interface IClassDesireService 8 | { 9 | Task GetClassDesireAsync(int id); 10 | Task> SearchClassDesiresAsync(SearchClassDesiresDto dto); 11 | Task CreateClassDesireAsync(CreateClassDesireDto dto); 12 | Task UpdateClassDesireAsync(int id, UpdateClassDesireDto dto); 13 | Task> GetMyClassesAsync(); 14 | Task AddMeToClassAsync(string classId); 15 | Task RemoveMeFromClassAsync(string classId); 16 | Task DeleteClassDesireAsync(int id); 17 | } 18 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassInfos/Dto/Request/CreateClassInfoDto.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | using LightNap.Core.Data.Entities; 4 | 5 | namespace LightNap.Core.ClassInfos.Request.Dto 6 | { 7 | public class CreateClassInfoDto 8 | { 9 | // TODO: Update which fields to include when creating this item. 10 | public required string Id { get; set; } 11 | public required string Title { get; set; } 12 | public required string Description { get; set; } 13 | public required string Instructor { get; set; } 14 | public required string Notes { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassInfos/Dto/Request/SearchClassInfoDto.cs: -------------------------------------------------------------------------------- 1 | 2 | using LightNap.Core.Api; 3 | 4 | namespace LightNap.Core.ClassInfos.Request.Dto 5 | { 6 | public class SearchClassInfosDto : PaginationRequestDtoBase 7 | { 8 | // TODO: Update to reflect which fields to include for searches. 9 | public string? Id { get; set; } 10 | public string? Title { get; set; } 11 | public string? Instructor { get; set; } 12 | public string? ClassCode { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassInfos/Dto/Request/UpdateClassInfoDto.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | using LightNap.Core.Data.Entities; 4 | 5 | namespace LightNap.Core.ClassInfos.Request.Dto 6 | { 7 | public class UpdateClassInfoDto 8 | { 9 | // TODO: Update which fields to include when creating this item. 10 | public required string Title { get; set; } 11 | public required string Description { get; set; } 12 | public required string Instructor { get; set; } 13 | public required string Notes { get; set; } 14 | } 15 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassInfos/Dto/Response/ClassInfoDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.ClassInfos.Response.Dto 2 | { 3 | public class ClassInfoDto 4 | { 5 | // TODO: Finalize which fields to include when returning this item. 6 | public required string Id { get; set; } 7 | public required string Title { get; set; } 8 | public required string Description { get; set; } 9 | public required string Instructor { get; set; } 10 | public required string Notes { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/LightNap.Core/ClassInfos/Dto/Response/ClassTimeDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.ClassInfos.Response.Dto 2 | { 3 | public class ClassTimeDto 4 | { 5 | // TODO: Finalize which fields to include when returning this item. 6 | public int Id { get; set; } 7 | public int Day { get; set; } // M1,T2,W3,Th4,F5 8 | public int StartTime { get; set; } // 24 hr military time (0500) 9 | public int EndTime { get; set; } // 24 hr military time (0500) 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/LightNap.Core/ClassInfos/Extensions/ClassTimeExtensions.cs: -------------------------------------------------------------------------------- 1 | 2 | using LightNap.Core.Data.Entities; 3 | using LightNap.Core.ClassInfos.Request.Dto; 4 | using LightNap.Core.ClassInfos.Response.Dto; 5 | 6 | namespace LightNap.Core.ClassInfos.Extensions 7 | { 8 | public static class ClassTimeExtensions 9 | { 10 | public static ClassTimeDto ToDto(this ClassTime item) 11 | { 12 | // TODO: Update these fields to match the DTO. 13 | var dto = new ClassTimeDto 14 | { 15 | Id = item.Id, 16 | Day = item.Day, 17 | StartTime = item.StartTime, 18 | EndTime = item.EndTime 19 | }; 20 | return dto; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassInfos/Interfaces/IClassInfoService.cs: -------------------------------------------------------------------------------- 1 | 2 | using LightNap.Core.Api; 3 | using LightNap.Core.ClassInfos.Request.Dto; 4 | using LightNap.Core.ClassInfos.Response.Dto; 5 | 6 | namespace LightNap.Core.ClassInfos.Interfaces 7 | { 8 | public interface IClassInfoService 9 | { 10 | Task GetClassInfoAsync(string id); 11 | Task> SearchClassInfosAsync(SearchClassInfosDto dto); 12 | Task CreateClassInfoAsync(CreateClassInfoDto dto); 13 | Task UpdateClassInfoAsync(string id, UpdateClassInfoDto dto); 14 | Task DeleteClassInfoAsync(string id); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/LightNap.Core/ClassUsers/Dto/Request/CreateClassUserDto.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | namespace LightNap.Core.ClassUsers.Request.Dto 4 | { 5 | public class CreateClassUserDto 6 | { 7 | // TODO: Update which fields to include when creating this item. 8 | public required string ClassInfoId { get; set; } 9 | public required string UserId { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassUsers/Dto/Request/SearchClassUserDto.cs: -------------------------------------------------------------------------------- 1 | 2 | using LightNap.Core.Api; 3 | 4 | namespace LightNap.Core.ClassUsers.Request.Dto 5 | { 6 | public class SearchClassUsersDto : PaginationRequestDtoBase 7 | { 8 | // TODO: Update to reflect which fields to include for searches. 9 | public string? ClassInfoId { get; set; } 10 | public string? UserId { get; set; } 11 | public bool? IsActive { get; set; } 12 | 13 | } 14 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassUsers/Dto/Request/UpdateClassUserDto.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | namespace LightNap.Core.ClassUsers.Request.Dto 4 | { 5 | public class UpdateClassUserDto 6 | { 7 | // TODO: Update which fields to include when creating this item. 8 | public bool IsActive { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /src/LightNap.Core/ClassUsers/Dto/Response/ClassUserDto.cs: -------------------------------------------------------------------------------- 1 | 2 | 3 | namespace LightNap.Core.ClassUsers.Response.Dto 4 | { 5 | public class ClassUserDto 6 | { 7 | // TODO: Finalize which fields to include when returning this item. 8 | public int Id { get; set; } 9 | public string ClassInfoId { get; set; } 10 | public string UserId { get; set; } 11 | public bool IsActive { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/LightNap.Core/ClassUsers/Interfaces/IClassUserService.cs: -------------------------------------------------------------------------------- 1 | 2 | using LightNap.Core.Api; 3 | using LightNap.Core.ClassUsers.Request.Dto; 4 | using LightNap.Core.ClassUsers.Response.Dto; 5 | 6 | namespace LightNap.Core.ClassUsers.Interfaces 7 | { 8 | public interface IClassUserService 9 | { 10 | Task GetClassUserAsync(int id); 11 | Task> SearchClassUsersAsync(SearchClassUsersDto dto); 12 | Task CreateClassUserAsync(CreateClassUserDto dto); 13 | Task> GetMyClassesAsync(); 14 | Task AddMeToClassAsync(string classId); 15 | Task RemoveMeFromClassAsync(string classId); 16 | Task UpdateClassUserAsync(int id, UpdateClassUserDto dto); 17 | Task DeleteClassUserAsync(int id); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/LightNap.Core/Data/Converters/BrowserSettingsConverter.cs: -------------------------------------------------------------------------------- 1 | using LightNap.Core.Profile.Dto.Response; 2 | using LightNap.Core.Profile.Helpers; 3 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 4 | using System.Text.Json; 5 | 6 | namespace LightNap.Core.Data.Converters 7 | { 8 | internal class BrowserSettingsConverter : ValueConverter 9 | { 10 | public BrowserSettingsConverter() : base( 11 | settings => JsonSerializer.Serialize(settings, null as JsonSerializerOptions), 12 | json => BrowserSettingsMigration.Migrate(JsonSerializer.Deserialize(json, null as JsonSerializerOptions) ?? new BrowserSettingsDto())) 13 | { 14 | } 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/LightNap.Core/Data/Converters/UtcValueConverter.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 2 | 3 | namespace LightNap.Core.Data.Converters 4 | { 5 | /// 6 | /// Converts DateTime values to UTC DateTime values and vice versa. This ensures DateTimes going into EF are marked as UTC. 7 | /// 8 | public class UtcValueConverter : ValueConverter 9 | { 10 | /// 11 | /// Initializes a new instance of the class. 12 | /// 13 | public UtcValueConverter() : base(value => value, value => DateTime.SpecifyKind(value, DateTimeKind.Utc)) 14 | { 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Data/Entities/ApplicationRoles.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Data.Entities 2 | { 3 | /// 4 | /// Provides predefined application roles. 5 | /// 6 | public static class ApplicationRoles 7 | { 8 | /// 9 | /// Gets the administrator role with access to all administrative features. 10 | /// 11 | public static readonly ApplicationRole Administrator = new("Administrator", "Administrator", "Access to all administrative features"); 12 | 13 | /// 14 | /// Gets a read-only list of all predefined application roles. 15 | /// 16 | public static IReadOnlyList All => 17 | [ 18 | Administrator 19 | ]; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/LightNap.Core/Data/Entities/ChatMessage.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Data.Entities 2 | { 3 | public class ChatMessage 4 | { 5 | public int Id { get; set; } 6 | public TradeRequest? TradeRequest { get; set; } 7 | public int TradeRequestId { get; set; } 8 | public required string Content { get; set; } 9 | public ApplicationUser? SendingUser { get; set; } 10 | public required string SendingUserId { get; set; } 11 | public DateTimeOffset Timestamp { get; set; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/LightNap.Core/Data/Entities/ClassDesire.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Data.Entities 2 | { 3 | public class ClassDesire 4 | { 5 | public int Id { get; set; } 6 | public ClassInfo? ClassInfo { get; set; } 7 | public required string ClassInfoId { get; set; } 8 | public ApplicationUser? User { get; set; } 9 | public required string UserId { get; set; } 10 | public bool IsActive { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/LightNap.Core/Data/Entities/ClassInfo.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Data.Entities 2 | { 3 | public class ClassInfo 4 | { 5 | public required string Id { get; set; } 6 | public required string Title { get; set; } 7 | public required string Description { get; set; } 8 | public required string Instructor { get; set; } 9 | public required string Notes { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/LightNap.Core/Data/Entities/ClassTime.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Data.Entities 2 | { 3 | public class ClassTime 4 | { 5 | public int Id { get; set; } 6 | public ClassInfo? ClassInfo { get; set; } 7 | public required string ClassInfoId { get; set; } 8 | public int Day { get; set; } // M1,T2,W3,Th4,F5 9 | public int StartTime { get; set; } // 24 hr military time (0500) 10 | public int EndTime { get; set; } // 24 hr military time (0500) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/LightNap.Core/Data/Entities/ClassUser.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Data.Entities 2 | { 3 | public class ClassUser 4 | { 5 | public int Id { get; set; } 6 | public ClassInfo? ClassInfo { get; set; } 7 | public required string ClassInfoId { get; set; } 8 | public ApplicationUser? User { get; set; } 9 | public required string UserId { get; set; } 10 | public bool IsActive { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/LightNap.Core/Data/Entities/TradeRequest.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Data.Entities 2 | { 3 | public class TradeRequest 4 | { 5 | public int Id { get; set; } 6 | public ClassUser? RequestingClassUser { get; set; } 7 | public int RequestingClassUserId { get; set; } 8 | public ClassUser? TargetClassUser { get; set; } 9 | public int TargetClassUserId { get; set; } 10 | public required TradeRequestStatus Status { get; set; } 11 | public ICollection? ChatMessages { get; set; } 12 | public required string Notes { get; set; } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/LightNap.Core/Data/Entities/TradeRequestStatus.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Data.Entities 2 | { 3 | public enum TradeRequestStatus 4 | { 5 | Pending, 6 | Accepted, 7 | Rejected, 8 | Canceled 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/LightNap.Core/Extensions/IConfigurationExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Extensions.Configuration; 2 | 3 | namespace LightNap.Core.Extensions 4 | { 5 | /// 6 | /// Extension methods for . 7 | /// 8 | public static class IConfigurationExtensions 9 | { 10 | /// 11 | /// Gets the value of a required setting from the configuration. 12 | /// 13 | /// The configuration object. 14 | /// The key of the setting. 15 | /// The value of the setting. 16 | /// Thrown when the required setting is missing. 17 | public static string GetRequiredSetting(this IConfiguration configuration, string key) 18 | { 19 | return configuration[key] ?? throw new ArgumentException($"Required setting '{key}' is missing"); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Identity/Dto/Request/ResetPasswordRequestDto.cs: -------------------------------------------------------------------------------- 1 | using LightNap.Core.Configuration; 2 | using System.ComponentModel.DataAnnotations; 3 | 4 | namespace LightNap.Core.Identity.Dto.Request 5 | { 6 | /// 7 | /// Data transfer object for requesting a password reset. 8 | /// 9 | public class ResetPasswordRequestDto 10 | { 11 | /// 12 | /// Gets or sets the email address of the user. 13 | /// 14 | [EmailAddress] 15 | [Required] 16 | [StringLength(Constants.Dto.MaxEmailLength)] 17 | public required string Email { get; set; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/LightNap.Core/Identity/Dto/Response/LoginResultDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Identity.Dto.Response 2 | { 3 | /// 4 | /// Represents the result of a login operation. 5 | /// 6 | public class LoginResultDto 7 | { 8 | /// 9 | /// Gets or sets a value indicating whether two-factor authentication is required. 10 | /// 11 | public bool TwoFactorRequired { get; set; } 12 | 13 | /// 14 | /// Gets or sets the bearer token for the authenticated user. 15 | /// 16 | public string? BearerToken { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Identity/Dto/Response/RoleDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Identity.Dto.Response 2 | { 3 | /// 4 | /// Represents a role for the Application Role. 5 | /// 6 | public class RoleDto 7 | { 8 | /// 9 | /// Gets or sets the role name. 10 | /// 11 | public required string Name { get; set; } 12 | 13 | /// 14 | /// Gets or sets the role display name. 15 | /// 16 | public required string DisplayName { get; set; } 17 | 18 | /// 19 | /// Gets or sets the role description. 20 | /// 21 | public required string Description { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Interfaces/ICookieManager.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Interfaces 2 | { 3 | /// 4 | /// Provides methods to manage cookies. 5 | /// 6 | public interface ICookieManager 7 | { 8 | void SetCookie(string key, string value, bool isPersistent, DateTime expires); 9 | string? GetCookie(string key); 10 | void RemoveCookie(string key); 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Interfaces/ITokenService.cs: -------------------------------------------------------------------------------- 1 | using LightNap.Core.Data.Entities; 2 | 3 | namespace LightNap.Core.Interfaces 4 | { 5 | /// 6 | /// Represents a token service interface. 7 | /// 8 | public interface ITokenService 9 | { 10 | /// 11 | /// Generates an access token asynchronously for the specified user. 12 | /// 13 | /// The user for whom the access token is generated. 14 | /// The generated access token. 15 | Task GenerateAccessTokenAsync(ApplicationUser user); 16 | 17 | /// 18 | /// Generates a refresh token. 19 | /// 20 | /// The generated refresh token. 21 | string GenerateRefreshToken(); 22 | } 23 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Interfaces/IUserContext.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Interfaces 2 | { 3 | /// 4 | /// Provides methods to access content specific to a user request. 5 | /// 6 | public interface IUserContext 7 | { 8 | string GetUserId(); 9 | string? GetIpAddress(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Profile/Dto/Request/UpdateProfileDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Profile.Dto.Request 2 | { 3 | /// 4 | /// The data transfer object for updating a profile. Update fields here when editable profile fields change. 5 | /// 6 | public class UpdateProfileDto 7 | { 8 | // Add other fields from the user. 9 | } 10 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Profile/Dto/Response/DeviceDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Profile.Dto.Response 2 | { 3 | /// 4 | /// Data transfer object representing a device. 5 | /// 6 | public class DeviceDto 7 | { 8 | /// 9 | /// Gets or sets the unique identifier of the device. 10 | /// 11 | public required string Id { get; set; } 12 | 13 | /// 14 | /// Gets or sets the timestamp of the last time the device was seen. 15 | /// 16 | public long LastSeen { get; set; } 17 | 18 | /// 19 | /// Gets or sets the IP address of the device. 20 | /// 21 | public required string IpAddress { get; set; } 22 | 23 | /// 24 | /// Gets or sets additional details about the device. 25 | /// 26 | public required string Details { get; set; } 27 | } 28 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Profile/Dto/Response/ProfileDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Profile.Dto.Response 2 | { 3 | /// 4 | /// Data transfer object representing the logged-in user's profile. 5 | /// 6 | public class ProfileDto 7 | { 8 | /// 9 | /// Gets or sets the unique identifier of the user profile. 10 | /// 11 | public required string Id { get; set; } 12 | 13 | /// 14 | /// Gets or sets the email address of the user. 15 | /// 16 | public required string Email { get; set; } 17 | 18 | /// 19 | /// Gets or sets the username of the user. 20 | /// 21 | public required string UserName { get; set; } 22 | } 23 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Public/Interfaces/IPublicService.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.Public.Interfaces 2 | { 3 | /// 4 | /// Service for public data access. 5 | /// 6 | public interface IPublicService 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /src/LightNap.Core/Public/Services/PublicService.cs: -------------------------------------------------------------------------------- 1 | using LightNap.Core.Public.Interfaces; 2 | 3 | namespace LightNap.Core.Public.Services 4 | { 5 | /// 6 | /// Service for accessing public data. 7 | /// 8 | public class PublicService() : IPublicService 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/LightNap.Core/TradeRequests/Dto/Request/CreateChatMessageDto.cs: -------------------------------------------------------------------------------- 1 | 2 | using LightNap.Core.Data.Entities; 3 | 4 | namespace LightNap.Core.TradeRequests.Request.Dto 5 | { 6 | public class CreateChatMessageDto 7 | { 8 | // TODO: Update which fields to include when creating this item. 9 | public required string Content { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/LightNap.Core/TradeRequests/Dto/Request/CreateTradeRequestDto.cs: -------------------------------------------------------------------------------- 1 | 2 | using LightNap.Core.Data.Entities; 3 | 4 | namespace LightNap.Core.TradeRequests.Request.Dto 5 | { 6 | public class CreateTradeRequestDto 7 | { 8 | // TODO: Update which fields to include when creating this item. 9 | public int RequestingClassUserId { get; set; } 10 | public int TargetClassUserId { get; set; } 11 | public required string Notes { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/LightNap.Core/TradeRequests/Dto/Request/SearchTradeRequestDto.cs: -------------------------------------------------------------------------------- 1 | 2 | using LightNap.Core.Api; 3 | using LightNap.Core.Data.Entities; 4 | 5 | namespace LightNap.Core.TradeRequests.Request.Dto 6 | { 7 | public class SearchTradeRequestsDto : PaginationRequestDtoBase 8 | { 9 | // TODO: Update to reflect which fields to include for searches. 10 | public int? RequestingClassUserId { get; set; } 11 | public int? TargetClassUserId { get; set; } 12 | public TradeRequestStatus? Status { get; set; } 13 | public string? Notes { get; set; } 14 | 15 | } 16 | } -------------------------------------------------------------------------------- /src/LightNap.Core/TradeRequests/Dto/Request/UpdateTradeRequestDto.cs: -------------------------------------------------------------------------------- 1 | 2 | using LightNap.Core.Data.Entities; 3 | 4 | namespace LightNap.Core.TradeRequests.Request.Dto 5 | { 6 | public class UpdateTradeRequestDto 7 | { 8 | // TODO: Update which fields to include when creating this item. 9 | public required string Notes { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/LightNap.Core/TradeRequests/Dto/Response/ChatMessageDto.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.TradeRequests.Response.Dto 2 | { 3 | public class ChatMessageDto 4 | { 5 | // TODO: Finalize which fields to include when returning this item. 6 | public int Id { get; set; } 7 | public required string Content { get; set; } 8 | public required string SendingUserId { get; set; } 9 | public DateTimeOffset Timestamp { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/LightNap.Core/TradeRequests/Dto/Response/TradeRequestDto.cs: -------------------------------------------------------------------------------- 1 | 2 | using LightNap.Core.Data.Entities; 3 | 4 | namespace LightNap.Core.TradeRequests.Response.Dto 5 | { 6 | public class TradeRequestDto 7 | { 8 | // TODO: Finalize which fields to include when returning this item. 9 | public int Id { get; set; } 10 | public int RequestingClassUserId { get; set; } 11 | public int TargetClassUserId { get; set; } 12 | public TradeRequestStatus Status { get; set; } 13 | public required string Notes { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/LightNap.Core/User/Interfaces/IUserService.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Core.User.Interfaces 2 | { 3 | /// 4 | /// Service for logged-in business functionality. 5 | /// 6 | public interface IUserService 7 | { 8 | } 9 | } -------------------------------------------------------------------------------- /src/LightNap.Core/User/Services/UserService.cs: -------------------------------------------------------------------------------- 1 | using LightNap.Core.User.Interfaces; 2 | 3 | namespace LightNap.Core.User.Services 4 | { 5 | /// 6 | /// Service for logged-in business functionality. 7 | /// 8 | public class UserService() : IUserService 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/LightNap.DataProviders.SqlServer/LightNap.DataProviders.SqlServer.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/LightNap.DataProviders.Sqlite/LightNap.DataProviders.Sqlite.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/LightNap.MaintenanceService/IMaintenanceTask.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.MaintenanceService 2 | { 3 | /// 4 | /// Represents a maintenance task that can be run. 5 | /// 6 | internal interface IMaintenanceTask 7 | { 8 | /// 9 | /// Gets the name of the maintenance task. 10 | /// 11 | string Name { get; } 12 | 13 | /// 14 | /// Runs the maintenance task asynchronously. 15 | /// 16 | /// A task that represents the asynchronous operation. 17 | Task RunAsync(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/LightNap.MaintenanceService/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "LightNap.MaintenanceService": { 4 | "commandName": "Project" 5 | }, 6 | "Container (Dockerfile)": { 7 | "commandName": "Docker" 8 | } 9 | } 10 | } -------------------------------------------------------------------------------- /src/LightNap.MaintenanceService/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft.AspNetCore": "Warning" 6 | } 7 | }, 8 | "AllowedHosts": "*", 9 | "ConnectionStrings": { 10 | "DefaultConnection": "Data Source=..\\..\\..\\..\\LightNap.WebApi\\LightNap.db" 11 | //"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=LightNap;Trusted_Connection=True;MultipleActiveResultSets=true" 12 | }, 13 | "DatabaseProvider": "Sqlite" // "SqlServer" or "Sqlite" 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/LightNap.WebApi/Api/ApiResponseType.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.WebApi.Api 2 | { 3 | /// 4 | /// Represents the response types for an API. 5 | /// 6 | public enum ApiResponseType 7 | { 8 | /// 9 | /// The API call was successful. 10 | /// 11 | Success, 12 | 13 | /// 14 | /// An error occurred during the API call. User-friendly error messages are available in the property. 15 | /// 16 | Error, 17 | 18 | /// 19 | /// An unexpected error occurred during the API call. 20 | /// 21 | UnexpectedError 22 | } 23 | } -------------------------------------------------------------------------------- /src/LightNap.WebApi/Configuration/AdministratorConfiguration.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.WebApi.Configuration 2 | { 3 | /// 4 | /// Represents the configuration for an administrator. 5 | /// 6 | public class AdministratorConfiguration 7 | { 8 | /// 9 | /// Gets or sets the email of the administrator. This field is required. 10 | /// 11 | public required string Email { get; set; } 12 | 13 | /// 14 | /// Gets or sets the username of the administrator. This field is required. 15 | /// 16 | public required string UserName { get; set; } 17 | 18 | /// 19 | /// Gets or sets the password of the administrator. This field is optional. 20 | /// 21 | public string? Password { get; set; } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/LightNap.WebApi/Configuration/Policies.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.WebApi.Configuration 2 | { 3 | /// 4 | /// Contains the policy names used in the application. 5 | /// 6 | public static class Policies 7 | { 8 | /// 9 | /// Policy name for requiring administrator role. 10 | /// 11 | public const string RequireAdministratorRole = "RequireAdministratorRole"; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/LightNap.WebApi/Controllers/PublicController.cs: -------------------------------------------------------------------------------- 1 | using LightNap.Core.Public.Interfaces; 2 | using Microsoft.AspNetCore.Mvc; 3 | 4 | namespace LightNap.WebApi.Controllers 5 | { 6 | /// 7 | /// Controller for handling publicly accessible data. 8 | /// 9 | [ApiController] 10 | [Route("api/[controller]")] 11 | public class PublicController( 12 | // Suppress CS9113 warning for unused parameter 'publicService'. Remove this if actually using the parameter. 13 | #pragma warning disable CS9113 14 | IPublicService publicService 15 | #pragma warning restore CS9113 16 | ) : ControllerBase 17 | { 18 | // Add Web API methods for data that is publicly accessible (user doesn't need to be logged in). 19 | } 20 | } -------------------------------------------------------------------------------- /src/LightNap.WebApi/Controllers/UserController.cs: -------------------------------------------------------------------------------- 1 | using LightNap.Core.User.Interfaces; 2 | using Microsoft.AspNetCore.Authorization; 3 | using Microsoft.AspNetCore.Mvc; 4 | 5 | namespace LightNap.WebApi.Controllers 6 | { 7 | /// 8 | /// Service for logged-in business functionality. 9 | /// 10 | [ApiController] 11 | [Authorize] 12 | [Route("api/[controller]")] 13 | public class UserController( 14 | // Suppress CS9113 warning for unused parameter 'publicService'. Remove this if actually using the parameter. 15 | #pragma warning disable CS9113 16 | IUserService userService 17 | #pragma warning restore CS9113 18 | ) : ControllerBase 19 | { 20 | // Add Web API methods for business data and functionality accessible to a logged in user. 21 | } 22 | } -------------------------------------------------------------------------------- /src/LightNap.WebApi/Extensions/ClaimsPrincipalExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Security.Claims; 2 | 3 | namespace LightNap.WebApi.Extensions 4 | { 5 | /// 6 | /// Extension methods for ClaimsPrincipal. 7 | /// 8 | public static class ClaimsPrincipalExtensions 9 | { 10 | /// 11 | /// Gets the user ID from the ClaimsPrincipal. 12 | /// 13 | /// The ClaimsPrincipal instance. 14 | /// The user ID. 15 | /// Thrown when the JWT does not include the required ID claim. 16 | public static string GetUserId(this ClaimsPrincipal user) 17 | { 18 | return user.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? throw new Exception("JWT did not include required ID claim"); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding.Tests/LightNap.Scaffolding.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net8.0 5 | enable 6 | enable 7 | 8 | false 9 | true 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/AssemblyManager/IAssemblyManager.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Scaffolding.AssemblyManager 2 | { 3 | /// 4 | /// Interface for managing assembly operations. 5 | /// 6 | public interface IAssemblyManager 7 | { 8 | /// 9 | /// Gets the path of the currently executing assembly. 10 | /// 11 | /// The executing assembly path as a string. 12 | string GetExecutingPath(); 13 | 14 | /// 15 | /// Loads a type from a specified assembly. 16 | /// 17 | /// The path to the assembly file. 18 | /// The name of the class to load. 19 | /// The loaded type, or null if the type cannot be found. 20 | Type? LoadType(string assemblyPath, string className); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/ProjectManager/IProjectManager.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Scaffolding.ProjectManager 2 | { 3 | /// 4 | /// Interface for managing project operations. 5 | /// 6 | public interface IProjectManager 7 | { 8 | /// 9 | /// Builds the project at the specified path. 10 | /// 11 | /// The path to the project to build. 12 | /// A containing the result of the build operation. 13 | ProjectBuildResult BuildProject(string projectPath); 14 | 15 | /// 16 | /// Adds a file to the project at the specified path. 17 | /// 18 | /// The path to the project. 19 | /// The path to the file to add. 20 | void AddFileToProject(string projectPath, string filePath); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/ProjectManager/ProjectBuildResult.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Scaffolding.ProjectManager 2 | { 3 | /// 4 | /// Represents the result of a project build. 5 | /// 6 | public class ProjectBuildResult 7 | { 8 | /// 9 | /// The path to the output assembly. 10 | /// 11 | public string? OutputAssemblyPath { get; set; } 12 | 13 | /// 14 | /// True if successful. 15 | /// 16 | public bool Success { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "profiles": { 3 | "LightNap.Scaffolding": { 4 | "commandName": "Project", 5 | "commandLineArgs": "ClassDetails --src-path \"../../../../..\"" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/TemplateManager/ITemplateManager.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Scaffolding.TemplateManager 2 | { 3 | /// 4 | /// Interface for managing templates. 5 | /// 6 | public interface ITemplateManager 7 | { 8 | /// 9 | /// Processes the specified template with the given parameters. 10 | /// 11 | /// The template item to process. 12 | /// The parameters to use for processing the template. 13 | void ProcessTemplate(TemplateItem templateItem, TemplateParameters templateParameters); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/TemplateManager/TemplateItem.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics.CodeAnalysis; 2 | 3 | namespace LightNap.Scaffolding.TemplateManager 4 | { 5 | /// 6 | /// Represents a template item with a template file, output file, and an optional project path. 7 | /// 8 | [method: SetsRequiredMembers] 9 | public class TemplateItem(string templateFile, string outputFile, string? addToProjectPath = null) 10 | { 11 | /// 12 | /// Gets or sets the template file path. 13 | /// 14 | public required string TemplateFile { get; set; } = templateFile; 15 | 16 | /// 17 | /// Gets or sets the output file path. 18 | /// 19 | public required string OutputFile { get; set; } = outputFile; 20 | 21 | /// 22 | /// Gets or sets the optional project path to add the output file to. 23 | /// 24 | public string? AddToProjectPath { get; set; } = addToProjectPath; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/TemplateManager/TemplateManager.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Scaffolding.TemplateManager 2 | { 3 | /// 4 | /// Manages the processing of templates. 5 | /// 6 | public class TemplateManager : ITemplateManager 7 | { 8 | /// 9 | /// Processes the specified template with the given parameters. 10 | /// 11 | /// The template item to process. 12 | /// The parameters to use for processing the template. 13 | public void ProcessTemplate(TemplateItem template, TemplateParameters templateParameters) 14 | { 15 | string templateContent = File.ReadAllText(template.TemplateFile); 16 | string content = TemplateProcessor.ProcessTemplate(templateContent, templateParameters); 17 | Directory.CreateDirectory(Path.GetDirectoryName(template.OutputFile)!); 18 | File.WriteAllText(template.OutputFile, content); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/TemplateManager/TemplateProcessor.cs: -------------------------------------------------------------------------------- 1 | namespace LightNap.Scaffolding.TemplateManager 2 | { 3 | /// 4 | /// Provides methods to process templates with specified parameters. 5 | /// 6 | public static class TemplateProcessor 7 | { 8 | /// 9 | /// Processes the template content by replacing placeholders with specified values. 10 | /// 11 | /// The content of the template to process. 12 | /// The parameters containing the replacements. 13 | /// The processed template content. 14 | public static string ProcessTemplate(string templateContent, TemplateParameters templateParameters) 15 | { 16 | foreach (var replacement in templateParameters.Replacements) 17 | { 18 | templateContent = templateContent.Replace($"<#= {replacement.Key} #>", replacement.Value); 19 | } 20 | return templateContent; 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Client/create-request.ts.txt: -------------------------------------------------------------------------------- 1 | export interface Create<#= PascalName #>Request { 2 | // TODO: Update these fields to match the server's Create<#= PascalName #>Dto. 3 | <#= ClientPropertiesList #> 4 | } 5 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Client/create.component.html.txt: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 |
13 |
14 |
-------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Client/get.component.html.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | > 4 |
5 | 6 | 7 |
8 |
{{ <#= CamelName #> | json }}
9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Client/index.component.html.txt: -------------------------------------------------------------------------------- 1 | 2 | 3 | > 4 |
5 | 6 |
7 |
    8 | @for(<#= CamelName #> of <#= CamelNamePlural #>.data; track $index) { 9 |
  • 10 | {{ <#= CamelName #> | json }} 11 |
  • 12 | } @empty { 13 |
  • There are no items yet
  • 14 | } 15 |
16 |
17 |
18 |
19 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Client/index.component.ts.txt: -------------------------------------------------------------------------------- 1 | import { CommonModule } from "@angular/common"; 2 | import { Component, inject } from "@angular/core"; 3 | import { RouterModule } from "@angular/router"; 4 | import { ApiResponseComponent } from "@core"; 5 | import { ButtonModule } from "primeng/button"; 6 | import { CardModule } from "primeng/card"; 7 | import { <#= PascalName #>Service } from "src/app/<#= KebabNamePlural #>/services/<#= KebabName #>.service"; 8 | 9 | @Component({ 10 | standalone: true, 11 | templateUrl: "./index.component.html", 12 | imports: [CommonModule, CardModule, ApiResponseComponent, RouterModule, ButtonModule], 13 | }) 14 | export class IndexComponent { 15 | #<#= CamelName #>Service = inject(<#= PascalName #>Service); 16 | <#= CamelNamePlural #>$ = this.#<#= CamelName #>Service.search<#= PascalNamePlural #>({ pageNumber: 1, pageSize: 10 }); 17 | } 18 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Client/response.ts.txt: -------------------------------------------------------------------------------- 1 | export interface <#= PascalName #> { 2 | // TODO: Update these fields to match the server's <#= PascalName #>Dto. 3 | id: <#= ClientIdType #>; 4 | <#= ClientPropertiesList #> 5 | } 6 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Client/routes.ts.txt: -------------------------------------------------------------------------------- 1 | import { AppRoute } from "@routing"; 2 | 3 | // TODO: Add this route list to app/routing/routes.ts. 4 | // 5 | // At the top of the file, import the routes: 6 | // 7 | // import { Routes as <#= PascalName #>Routes } from "../<#= KebabNamePlural #>/components/pages/routes"; 8 | // 9 | // Then add the routes to the list: 10 | // 11 | // { path: "<#= KebabNamePlural #>", children: <#= PascalName #>Routes } 12 | // 13 | export const Routes: AppRoute[] = [ 14 | { path: "", loadComponent: () => import("./index/index.component").then(m => m.IndexComponent) }, 15 | { path: "create", loadComponent: () => import("./create/create.component").then(m => m.CreateComponent) }, 16 | { path: ":id", loadComponent: () => import("./get/get.component").then(m => m.GetComponent) }, 17 | { path: ":id/edit", loadComponent: () => import("./edit/edit.component").then(m => m.EditComponent) }, 18 | ]; 19 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Client/search-request.ts.txt: -------------------------------------------------------------------------------- 1 | import { PaginationRequest } from "@core"; 2 | export interface Search<#= PascalNamePlural #>Request extends PaginationRequest { 3 | <#= ClientOptionalPropertiesList #> 4 | } 5 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Client/update-request.ts.txt: -------------------------------------------------------------------------------- 1 | export interface Update<#= PascalName #>Request { 2 | // TODO: Update these fields to match the server's Update<#= PascalName #>Dto. 3 | <#= ClientPropertiesList #> 4 | } -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Server/CreateDto.cs.txt: -------------------------------------------------------------------------------- 1 | namespace <#= CoreNamespace #>.<#= NameForNamespace #>.Request.Dto 2 | { 3 | public class Create<#= PascalName #>Dto 4 | { 5 | // TODO: Update which fields to include when creating this item. 6 | <#= ServerPropertiesList #> 7 | } 8 | } -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Server/Dto.cs.txt: -------------------------------------------------------------------------------- 1 | namespace <#= CoreNamespace #>.<#= NameForNamespace #>.Response.Dto 2 | { 3 | public class <#= PascalName #>Dto 4 | { 5 | // TODO: Finalize which fields to include when returning this item. 6 | public <#= ServerIdType #> Id { get; set; } 7 | <#= ServerPropertiesList #> 8 | } 9 | } -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Server/Interface.cs.txt: -------------------------------------------------------------------------------- 1 | using <#= CoreNamespace #>.Api; 2 | using <#= CoreNamespace #>.<#= NameForNamespace #>.Request.Dto; 3 | using <#= CoreNamespace #>.<#= NameForNamespace #>.Response.Dto; 4 | 5 | namespace <#= CoreNamespace #>.<#= NameForNamespace #>.Interfaces 6 | { 7 | public interface I<#= PascalName #>Service 8 | { 9 | TaskDto>> Get<#= PascalName #>Async(<#= ServerIdType #> id); 10 | TaskDto>>> Search<#= PascalNamePlural #>Async(Search<#= PascalNamePlural #>Dto dto); 11 | TaskDto>> Create<#= PascalName #>Async(Create<#= PascalName #>Dto dto); 12 | TaskDto>> Update<#= PascalName #>Async(<#= ServerIdType #> id, Update<#= PascalName #>Dto dto); 13 | Task> Delete<#= PascalName #>Async(<#= ServerIdType #> id); 14 | } 15 | } -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Server/SearchDto.cs.txt: -------------------------------------------------------------------------------- 1 | using <#= CoreNamespace #>.Api; 2 | 3 | namespace <#= CoreNamespace #>.<#= NameForNamespace #>.Request.Dto 4 | { 5 | public class Search<#= PascalNamePlural #>Dto : PaginationRequestDtoBase 6 | { 7 | // TODO: Update to reflect which fields to include for searches. 8 | <#= ServerOptionalPropertiesList #> 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/Scaffolding/LightNap.Scaffolding/Templates/Server/UpdateDto.cs.txt: -------------------------------------------------------------------------------- 1 | namespace <#= CoreNamespace #>.<#= NameForNamespace #>.Request.Dto 2 | { 3 | public class Update<#= PascalName #>Dto 4 | { 5 | // TODO: Update which fields to include when updating this item. 6 | <#= ServerPropertiesList #> 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 4 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /src/lightnap-ng/.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # Compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | /bazel-out 8 | 9 | # Node 10 | /node_modules 11 | npm-debug.log 12 | yarn-error.log 13 | 14 | # IDEs and editors 15 | .idea/ 16 | .project 17 | .classpath 18 | .c9/ 19 | *.launch 20 | .settings/ 21 | *.sublime-workspace 22 | 23 | # Visual Studio Code 24 | .vscode 25 | .vscode/* 26 | .history/* 27 | 28 | # Miscellaneous 29 | /.angular/cache 30 | .sass-cache/ 31 | /connect.lock 32 | /coverage 33 | /libpeerconnection.log 34 | testem.log 35 | /typings 36 | 37 | # System files 38 | .DS_Store 39 | Thumbs.db 40 | 41 | -------------------------------------------------------------------------------- /src/lightnap-ng/README.md: -------------------------------------------------------------------------------- 1 | # HuskySwap Angular Front-End 2 | 3 | This project is based on PrimeTek's [Sakai](https://github.com/primefaces/sakai-ng) template. 4 | Please see its repo for more details and ideas on how to use PrimeNG. 5 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": true, 4 | "htmlWhitespaceSensitivity": "css", 5 | "insertPragma": false, 6 | "jsxBracketSameLine": false, 7 | "jsxSingleQuote": false, 8 | "printWidth": 150, 9 | "proseWrap": "preserve", 10 | "quoteProps": "consistent", 11 | "requirePragma": false, 12 | "semi": true, 13 | "singleQuote": false, 14 | "tabWidth": 2, 15 | "trailingComma": "es5", 16 | "useTabs": false 17 | } 18 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/components/pages/index/index.component.html: -------------------------------------------------------------------------------- 1 | 2 |

This is the home page for the administration part of your app.

3 |
4 | 5 | 6 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/components/pages/index/index.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { CardModule } from 'primeng/card'; 3 | 4 | @Component({ 5 | standalone: true, 6 | templateUrl: './index.component.html', 7 | imports: [CardModule] 8 | }) 9 | export class IndexComponent { 10 | } 11 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/components/pages/roles/roles.component.ts: -------------------------------------------------------------------------------- 1 | import { AdminService } from "@admin/services/admin.service"; 2 | import { CommonModule } from "@angular/common"; 3 | import { Component, inject } from "@angular/core"; 4 | import { RouterLink } from "@angular/router"; 5 | import { ApiResponseComponent } from "@core/components/controls/api-response/api-response.component"; 6 | import { RoutePipe } from "@routing"; 7 | import { CardModule } from "primeng/card"; 8 | import { TableModule } from "primeng/table"; 9 | 10 | @Component({ 11 | standalone: true, 12 | templateUrl: "./roles.component.html", 13 | imports: [CommonModule, CardModule, RouterLink, RoutePipe, ApiResponseComponent, TableModule], 14 | }) 15 | export class RolesComponent { 16 | readonly #adminService = inject(AdminService); 17 | 18 | readonly roles$ = this.#adminService.getRoles(); 19 | } 20 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/components/pages/routes.ts: -------------------------------------------------------------------------------- 1 | import { AppRoute } from "@routing"; 2 | 3 | export const Routes: AppRoute[] = [ 4 | { path: "", data: { alias: "admin-home" }, loadComponent: () => import("./index/index.component").then(m => m.IndexComponent) }, 5 | { path: "users", data: { alias: "admin-users" }, loadComponent: () => import("./users/users.component").then(m => m.UsersComponent) }, 6 | { path: "users/:userId", data: { alias: "admin-user" }, loadComponent: () => import("./user/user.component").then(m => m.UserComponent) }, 7 | { path: "roles", data: { alias: "admin-roles" }, loadComponent: () => import("./roles/roles.component").then(m => m.RolesComponent) }, 8 | { path: "roles/:role", data: { alias: "admin-role" }, loadComponent: () => import("./role/role.component").then(m => m.RoleComponent) }, 9 | ]; 10 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./models"; 2 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/admin-user-with-roles.ts: -------------------------------------------------------------------------------- 1 | import { AdminUser, Role } from "./response"; 2 | 3 | /** 4 | * Interface representing a user with full details including roles for an administrative context. 5 | */ 6 | export interface AdminUserWithRoles { 7 | /** 8 | * The timestamp when the user was last modified. 9 | * @type {AdminUser} 10 | */ 11 | user: AdminUser; 12 | 13 | /** 14 | * The timestamp when the user was created. 15 | * @type {Array} 16 | */ 17 | roles: Array; 18 | } 19 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./admin-user-with-roles"; 2 | export * from "./request"; 3 | export * from "./response"; 4 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/request/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./search-admin-users-request"; 2 | export * from "./search-admin-users-sort-by"; 3 | export * from "./update-admin-user-request"; 4 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/request/search-admin-users-request.ts: -------------------------------------------------------------------------------- 1 | import { PaginationRequest } from "@core"; 2 | import { SearchAdminUsersSortBy } from "./search-admin-users-sort-by"; 3 | 4 | /** 5 | * Interface representing a request to search for admin users. 6 | * Extends the PaginationRequest interface to include pagination properties. 7 | */ 8 | export interface SearchAdminUsersRequest extends PaginationRequest { 9 | /** 10 | * The email address substring to search for. 11 | * @type {string} 12 | */ 13 | email?: string; 14 | 15 | /** 16 | * The username substring to search for. 17 | * @type {string} 18 | */ 19 | userName?: string; 20 | 21 | /** 22 | * The field to sort the results by. 23 | * @type {SearchAdminUsersSortBy} 24 | */ 25 | sortBy: SearchAdminUsersSortBy; 26 | 27 | /** 28 | * Whether to reverse the sort order. 29 | * @type {boolean} 30 | */ 31 | reverseSort: boolean; 32 | } 33 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/request/search-admin-users-sort-by.ts: -------------------------------------------------------------------------------- 1 | export type SearchAdminUsersSortBy = "email" | "userName" | "createdDate" | "lastModifiedDate"; 2 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/request/update-admin-user-request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a request to update a user. 3 | */ 4 | export interface UpdateAdminUserRequest {} 5 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/response/admin-device.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface representing an admin device. 3 | */ 4 | export interface AdminDevice { 5 | /** 6 | * The unique identifier for the device. 7 | * @type {string} 8 | */ 9 | id: string; 10 | 11 | /** 12 | * The timestamp of the last time the device was seen. 13 | * @type {number} 14 | */ 15 | lastSeen: number; 16 | 17 | /** 18 | * The IP address from the last time the device was seen. 19 | * @type {string} 20 | */ 21 | ipAddress: string; 22 | 23 | /** 24 | * Device details, such as the browser agent, so it can be more easily identified by the user. 25 | * @type {string} 26 | */ 27 | details: string; 28 | 29 | /** 30 | * The timestamp when the device expires. 31 | * @type {number} 32 | */ 33 | expires: number; 34 | 35 | /** 36 | * The user associated with the device. 37 | * @type {string} 38 | */ 39 | userId: string; 40 | } 41 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/response/admin-user.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface representing a user with full details for an administrative context. 3 | */ 4 | export interface AdminUser { 5 | /** 6 | * The unique identifier for the user. 7 | * @type {string} 8 | */ 9 | id: string; 10 | 11 | /** 12 | * The email address of the user. 13 | * @type {string} 14 | */ 15 | email: string; 16 | 17 | /** 18 | * The username of the user. 19 | * @type {string} 20 | */ 21 | userName: string; 22 | 23 | /** 24 | * The timestamp when the user was last modified. 25 | * @type {number} 26 | */ 27 | lastModifiedDate: number; 28 | 29 | /** 30 | * The timestamp when the user was created. 31 | * @type {number} 32 | */ 33 | createdDate: number; 34 | 35 | /** 36 | * The timestamp when the user lockout ends. If the user is not locked out, this value is undefined. 37 | * @type {number} 38 | */ 39 | lockoutEnd: number; 40 | } 41 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/response/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./admin-device"; 2 | export * from "./admin-user"; 3 | export * from "./role"; 4 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/response/role.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a role within the application. 3 | */ 4 | export interface Role { 5 | /** 6 | * The name of the role. 7 | */ 8 | name: string; 9 | 10 | /** 11 | * The display name of the role. 12 | */ 13 | displayName: string; 14 | 15 | /** 16 | * A brief description of the role. 17 | */ 18 | description: string; 19 | } 20 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/admin/models/role-with-admin-users.ts: -------------------------------------------------------------------------------- 1 | import { AdminUser, Role } from "./response"; 2 | 3 | export interface RoleWithAdminUsers { 4 | role: Role; 5 | users: Array; 6 | } 7 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |
6 | 7 | {{blockUiMessage}} 8 |
9 |
10 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/controls/class-info/class-info.component.html: -------------------------------------------------------------------------------- 1 |
2 |

{{ classInfo().title }}

3 | {{ classInfo().description }} 4 | {{ classInfo().instructor }} 5 | {{ classInfo().id }} 6 | {{ classInfo().notes }} 7 |
-------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/controls/class-info/class-info.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from "@angular/common"; 2 | import { Component, input } from "@angular/core"; 3 | import { RouterLink } from "@angular/router"; 4 | import { ButtonModule } from "primeng/button"; 5 | import { ClassInfo } from "src/app/class-infos/models/response/class-info"; 6 | 7 | @Component({ 8 | standalone: true, 9 | templateUrl: "./class-info.component.html", 10 | selector: "class-info", 11 | imports: [CommonModule, RouterLink, ButtonModule], 12 | }) 13 | export class ClassInfoComponent { 14 | readonly classInfo = input(undefined); 15 | } 16 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/pages/class-desires/create/create.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 |
5 | 6 |
7 |
8 | 9 | 10 | 11 | 12 |
13 |
14 |
-------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/pages/class-desires/get/get.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 | 7 |
8 |
{{ classDesire | json }}
9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/pages/class-desires/get/get.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from "@angular/common"; 2 | import { Component, inject, Input, OnInit } from "@angular/core"; 3 | import { RouterLink } from "@angular/router"; 4 | import { ApiResponse, ApiResponseComponent } from "@core"; 5 | import { ButtonModule } from "primeng/button"; 6 | import { CardModule } from "primeng/card"; 7 | import { Observable } from "rxjs"; 8 | import { ClassDesire } from "src/app/class-infos/models/response/class-desire"; 9 | import { ClassInfoService } from "src/app/class-infos/services/class-info.service"; 10 | 11 | @Component({ 12 | standalone: true, 13 | templateUrl: "./get.component.html", 14 | imports: [CommonModule, CardModule, RouterLink, ApiResponseComponent, ButtonModule], 15 | }) 16 | export class GetComponent implements OnInit { 17 | #classInfoService = inject(ClassInfoService); 18 | errors = new Array(); 19 | 20 | @Input() id: number; 21 | classDesire$ = new Observable(); 22 | 23 | ngOnInit() { 24 | this.classDesire$ = this.#classInfoService.getClassDesire(this.id); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/pages/class-desires/my-classes/my-classes.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | @for(classInfo of classInfos; track $index) { 6 | 7 | 8 | 9 | } 10 | @empty { 11 |

No classes in your wishlist

12 | } 13 | 14 |
15 |
16 |
-------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/pages/class-desires/routes.ts: -------------------------------------------------------------------------------- 1 | import { AppRoute } from "@routing"; 2 | 3 | // TODO: Add this route list to app/routing/routes.ts. 4 | // 5 | // At the top of the file, import the routes: 6 | // 7 | // import { Routes as ClassDesireRoutes } from "../class-desires/components/pages/routes"; 8 | // 9 | // Then add the routes to the list: 10 | // 11 | // { path: "class-desires", children: ClassDesireRoutes } 12 | // 13 | export const Routes: AppRoute[] = [ 14 | { path: "create", loadComponent: () => import("./create/create.component").then(m => m.CreateComponent) }, 15 | { path: "my-classes", data: {alias: "wishlist"}, loadComponent: () => import("./my-classes/my-classes.component").then(m => m.MyClassesComponent)}, 16 | { path: ":id", loadComponent: () => import("./get/get.component").then(m => m.GetComponent) }, 17 | { path: ":id/edit", loadComponent: () => import("./edit/edit.component").then(m => m.EditComponent) }, 18 | ]; 19 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/pages/class-infos/routes.ts: -------------------------------------------------------------------------------- 1 | 2 | import { adminGuard } from "@core/guards/admin.guard"; 3 | import { AppRoute } from "@routing"; 4 | 5 | // TODO: Add this route list to app/routing/routes.ts. 6 | // 7 | // At the top of the file, import the routes: 8 | // 9 | // import { Routes as ClassInfoRoutes } from "../class-infos/components/pages/routes"; 10 | // 11 | // Then add the routes to the list: 12 | // 13 | // { path: "class-infos", children: ClassInfoRoutes } 14 | // 15 | export const Routes: AppRoute[] = [ 16 | { path: "", data: {alias: "class-infos"}, loadComponent: () => import("./index/index.component").then(m => m.IndexComponent) }, 17 | { path: "create", canActivate: [adminGuard], loadComponent: () => import("./create/create.component").then(m => m.CreateComponent) }, 18 | { path: ":id", data: {alias: "class-info"}, loadComponent: () => import("./get/get.component").then(m => m.GetComponent) }, 19 | { path: ":id/edit", loadComponent: () => import("./edit/edit.component").then(m => m.EditComponent) }, 20 | ]; 21 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/pages/class-users/create/create.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 |
6 | 7 |
8 |
9 |
10 | 11 | 12 |
13 |
14 | 15 |
16 | 17 | 18 | 19 |
20 |
21 |
22 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/pages/class-users/get/get.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from "@angular/common"; 2 | import { Component, inject, input, OnInit } from "@angular/core"; 3 | import { RouterLink } from "@angular/router"; 4 | import { ApiResponseComponent } from "@core"; 5 | import { ButtonModule } from "primeng/button"; 6 | import { CardModule } from "primeng/card"; 7 | import { Observable } from "rxjs"; 8 | import { ClassUser } from "src/app/class-infos/models/response/class-user"; 9 | import { ClassInfoService } from "src/app/class-infos/services/class-info.service"; 10 | 11 | @Component({ 12 | standalone: true, 13 | templateUrl: "./get.component.html", 14 | imports: [CommonModule, CardModule, RouterLink, ApiResponseComponent, ButtonModule], 15 | }) 16 | export class GetComponent implements OnInit { 17 | #classInfoService = inject(ClassInfoService); 18 | errors = new Array(); 19 | 20 | readonly id = input(undefined); 21 | classUser$?: Observable; 22 | 23 | ngOnInit() { 24 | this.classUser$ = this.#classInfoService.getClassUser(this.id()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/pages/class-users/my-classes/my-classes.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | @for(classUserInfo of classInfos; track $index) { 6 | 7 | 8 | 9 | } @empty { 10 |

You don't have any classes!

11 | } 12 | 13 |
14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/components/pages/class-users/routes.ts: -------------------------------------------------------------------------------- 1 | 2 | import { AppRoute } from "@routing"; 3 | 4 | // TODO: Add this route list to app/routing/routes.ts. 5 | // 6 | // At the top of the file, import the routes: 7 | // 8 | // import { Routes as ClassUserRoutes } from "../class-users/components/pages/routes"; 9 | // 10 | // Then add the routes to the list: 11 | // 12 | // { path: "class-users", children: ClassUserRoutes } 13 | // 14 | export const Routes: AppRoute[] = [ 15 | { path: "create", loadComponent: () => import("./create/create.component").then(m => m.CreateComponent) }, 16 | { path: "my-classes", data: {alias: "my-classes"}, loadComponent: () => import("./my-classes/my-classes.component").then(m => m.MyClassesComponent) }, 17 | { path: ":id", loadComponent: () => import("./get/get.component").then(m => m.GetComponent) }, 18 | { path: ":id/edit", loadComponent: () => import("./edit/edit.component").then(m => m.EditComponent) }, 19 | ]; 20 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/helpers/class-info.helper.ts: -------------------------------------------------------------------------------- 1 | 2 | import { ClassInfo } from "../models/response/class-info"; 3 | 4 | export class ClassInfoHelper { 5 | static rehydrate(classInfo: ClassInfo) { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/helpers/class-user.helper.ts: -------------------------------------------------------------------------------- 1 | 2 | import { ClassUser } from "../models/response/class-user"; 3 | 4 | export class ClassUserHelper { 5 | static rehydrate(classUser: ClassUser) { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/class-user-info.ts: -------------------------------------------------------------------------------- 1 | import { ClassInfo } from "src/app/class-infos/models/response/class-info"; 2 | import { ClassUser } from "./response/class-user"; 3 | 4 | export interface ClassUserInfo { 5 | // TODO: Update these fields to match the server's ClassUserDto. 6 | classUser: ClassUser; 7 | classInfo: ClassInfo; 8 | } 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/request/create-class-desire-request.ts: -------------------------------------------------------------------------------- 1 | export interface CreateClassDesireRequest { 2 | // TODO: Update these fields to match the server's CreateClassDesireDto. 3 | classInfoId: string; 4 | userId: string; 5 | isActive: string; 6 | } 7 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/request/create-class-info-request.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface CreateClassInfoRequest { 3 | // TODO: Update these fields to match the server's CreateClassInfoDto. 4 | id: string; 5 | title: string; 6 | description: string; 7 | instructor: string; 8 | notes: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/request/create-class-user-request.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface CreateClassUserRequest { 3 | // TODO: Update these fields to match the server's CreateClassUserDto. 4 | classInfoId: string; 5 | isActive: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/request/search-class-desires-request.ts: -------------------------------------------------------------------------------- 1 | import { PaginationRequest } from "@core"; 2 | export interface SearchClassDesiresRequest extends PaginationRequest { 3 | classInfoId?: string; 4 | userId?: string; 5 | isActive?: boolean; 6 | } 7 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/request/search-class-infos-request.ts: -------------------------------------------------------------------------------- 1 | 2 | import { PaginationRequest } from "@core"; 3 | export interface SearchClassInfosRequest extends PaginationRequest { 4 | // TODO: Update these fields to match the server's SearchClassInfoDto. 5 | id?: string; 6 | title?: string; 7 | description?: string; 8 | instructor?: string; 9 | notes?: string; 10 | } 11 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/request/search-class-users-request.ts: -------------------------------------------------------------------------------- 1 | 2 | import { PaginationRequest } from "@core"; 3 | export interface SearchClassUsersRequest extends PaginationRequest { 4 | // TODO: Update these fields to match the server's SearchClassUserDto. 5 | classInfoId?: string; 6 | userId?: string; 7 | isActive?: boolean; 8 | } 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/request/update-class-desire-request.ts: -------------------------------------------------------------------------------- 1 | export interface UpdateClassDesireRequest { 2 | // TODO: Update these fields to match the server's UpdateClassDesireDto. 3 | classInfoId: string; 4 | userId: string; 5 | isActive: string; 6 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/request/update-class-info-request.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface UpdateClassInfoRequest { 3 | // TODO: Update these fields to match the server's UpdateClassInfoDto. 4 | title: string; 5 | description: string; 6 | instructor: string; 7 | notes: string; 8 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/request/update-class-user-request.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface UpdateClassUserRequest { 3 | // TODO: Update these fields to match the server's UpdateClassUserDto. 4 | classInfoId: string; 5 | isActive: boolean; 6 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/response/class-desire.ts: -------------------------------------------------------------------------------- 1 | export interface ClassDesire { 2 | // TODO: Update these fields to match the server's ClassDesireDto. 3 | id: number; 4 | classInfoId: string; 5 | userId: string; 6 | isActive: boolean; 7 | } 8 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/response/class-info.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface ClassInfo { 3 | // TODO: Update these fields to match the server's ClassInfoDto. 4 | id: string; 5 | title: string; 6 | description: string; 7 | instructor: string; 8 | notes: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/response/class-user.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface ClassUser { 3 | // TODO: Update these fields to match the server's ClassUserDto. 4 | id: number; 5 | classInfoId: string; 6 | userId: string; 7 | isActive: boolean; 8 | } 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/class-infos/models/user-classes.ts: -------------------------------------------------------------------------------- 1 | import { ClassUserInfo } from "src/app/class-infos/models/class-user-info"; 2 | 3 | export interface UserClasses { 4 | // TODO: Update these fields to match the server's ClassUserDto. 5 | classUserInfos: Array; 6 | userId: string; 7 | } 8 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/controls/api-response/api-response.component.html: -------------------------------------------------------------------------------- 1 | @if(internalApiResponse$ | async; as response) { @if (response.result; as result) { 2 | 3 | } @else { 4 | 5 | } } @else { 6 | 7 | } 8 | 9 | 10 |

{{ errorMessage() }}

11 | 12 |
13 | 14 | 15 | 16 |

{{ loadingMessage() }}

17 |
18 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/controls/confirm-dialog/confirm-dialog.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/controls/confirm-dialog/confirm-dialog.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, Input, TemplateRef } from "@angular/core"; 2 | import { ButtonSeverity } from "@core/models"; 3 | import { PrimeIcons } from "primeng/api"; 4 | import { ButtonModule } from "primeng/button"; 5 | import { ConfirmDialogModule } from "primeng/confirmdialog"; 6 | 7 | @Component({ 8 | standalone: true, 9 | selector: "confirm-dialog", 10 | templateUrl: "./confirm-dialog.component.html", 11 | imports: [ConfirmDialogModule, ButtonModule], 12 | }) 13 | export class ConfirmDialogComponent { 14 | @Input() confirmText = "Confirm"; 15 | @Input() confirmSeverity: ButtonSeverity = "danger"; 16 | @Input() confirmIcon = PrimeIcons.TRASH; 17 | @Input() rejectText = "Cancel"; 18 | @Input() rejectSeverity: ButtonSeverity = "secondary"; 19 | @Input() rejectIcon = PrimeIcons.UNDO; 20 | @Input() key = ""; 21 | @Input() appendTo?: HTMLElement | ElementRef | TemplateRef | string | null | undefined | any; 22 | } 23 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/controls/confirm-popup/confirm-popup.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | {{ message.message }} 5 |
6 | 7 | 8 |
9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/controls/confirm-popup/confirm-popup.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from "@angular/core"; 2 | import { ButtonSeverity } from "@core/models"; 3 | import { PrimeIcons } from "primeng/api"; 4 | import { ButtonModule } from "primeng/button"; 5 | import { ConfirmPopupModule } from "primeng/confirmpopup"; 6 | 7 | @Component({ 8 | standalone: true, 9 | selector: "confirm-popup", 10 | templateUrl: "./confirm-popup.component.html", 11 | imports: [ConfirmPopupModule, ButtonModule], 12 | }) 13 | export class ConfirmPopupComponent { 14 | @Input() confirmText = "Confirm"; 15 | @Input() confirmSeverity: ButtonSeverity = "danger"; 16 | @Input() confirmIcon = PrimeIcons.TRASH; 17 | @Input() rejectText = "Cancel"; 18 | @Input() rejectSeverity: ButtonSeverity = "secondary"; 19 | @Input() rejectIcon = PrimeIcons.UNDO; 20 | @Input() key = ""; 21 | } 22 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/controls/dropdown-list-item/dropdown-list-item.component.html: -------------------------------------------------------------------------------- 1 |
2 | {{ label }} 3 | @if (description) { 4 |

5 | {{ description }} 6 |

7 | } 8 |
9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/controls/dropdown-list-item/dropdown-list-item.component.ts: -------------------------------------------------------------------------------- 1 | 2 | import { Component, Input } from "@angular/core"; 3 | import { ListItem } from "@core"; 4 | 5 | @Component({ 6 | selector: 'dropdown-list-item', 7 | templateUrl: './dropdown-list-item.component.html', 8 | imports: [], 9 | standalone: true, 10 | }) 11 | export class DropdownListItemComponent { 12 | @Input() label = ""; 13 | @Input() description?: string; 14 | 15 | @Input() set listItem(value: ListItem) { 16 | this.label = value.label; 17 | this.description = value.description; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/controls/error-list/error-list.component.html: -------------------------------------------------------------------------------- 1 | @if (errorList.length) { 2 |
    3 | @for (error of errorList; track $index) { 4 |
  • {{ error }}
  • 5 | } 6 |
7 | } 8 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/controls/error-list/error-list.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from "@angular/common"; 2 | import { Component, Input, OnChanges, SimpleChanges } from "@angular/core"; 3 | import { ApiResponse } from "@core"; 4 | 5 | @Component({ 6 | selector: "error-list", 7 | standalone: true, 8 | templateUrl: "./error-list.component.html", 9 | imports: [CommonModule], 10 | }) 11 | export class ErrorListComponent implements OnChanges { 12 | @Input() error?: string; 13 | @Input() errors?: Array; 14 | @Input() apiResponse?: ApiResponse; 15 | 16 | errorList = new Array(); 17 | 18 | ngOnChanges(changes: SimpleChanges): void { 19 | if (this.error) { 20 | this.errorList = [this.error]; 21 | } else if (this.errors?.length) { 22 | this.errorList = [...this.errors]; 23 | } else if (this.apiResponse?.errorMessages?.length) { 24 | this.errorList = [...this.apiResponse.errorMessages]; 25 | } else { 26 | this.errorList = []; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/controls/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./api-response/api-response.component"; 2 | export * from "./confirm-dialog/confirm-dialog.component"; 3 | export * from "./confirm-popup/confirm-popup.component"; 4 | export * from "./dropdown-list-item/dropdown-list-item.component"; 5 | export * from "./error-list/error-list.component"; 6 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./controls"; 2 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/guards/admin.guard.ts: -------------------------------------------------------------------------------- 1 | import { inject } from "@angular/core"; 2 | import { ActivatedRouteSnapshot, createUrlTreeFromSnapshot } from "@angular/router"; 3 | import { IdentityService } from "src/app/identity/services/identity.service"; 4 | import { map, take } from "rxjs"; 5 | import { RouteAliasService } from "@routing"; 6 | 7 | export const adminGuard = (next: ActivatedRouteSnapshot) => { 8 | const authenticationService = inject(IdentityService); 9 | const routeAliasService = inject(RouteAliasService); 10 | 11 | return authenticationService 12 | .watchLoggedInToRole$("Administrator") 13 | .pipe(take(1), map(isAdmin => (isAdmin ? true : createUrlTreeFromSnapshot(next, routeAliasService.getRoute("access-denied"))))); 14 | }; 15 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/guards/auth.guard.ts: -------------------------------------------------------------------------------- 1 | import { inject } from "@angular/core"; 2 | import { ActivatedRouteSnapshot, createUrlTreeFromSnapshot, RouterStateSnapshot } from "@angular/router"; 3 | import { RouteAliasService } from "@routing"; 4 | import { map, take } from "rxjs"; 5 | import { IdentityService } from "src/app/identity/services/identity.service"; 6 | 7 | export const authGuard = (next: ActivatedRouteSnapshot, state: RouterStateSnapshot) => { 8 | const routeAliasService = inject(RouteAliasService); 9 | const identityService = inject(IdentityService); 10 | 11 | return identityService 12 | .watchLoggedIn$() 13 | .pipe( 14 | take(1), 15 | map(isLoggedIn => { 16 | if (isLoggedIn) return true; 17 | identityService.redirectUrl = state.url; 18 | return createUrlTreeFromSnapshot(next, routeAliasService.getRoute("login")); 19 | }) 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/guards/can-deactivate.guard.ts: -------------------------------------------------------------------------------- 1 | import { CanDeactivateFn } from "@angular/router"; 2 | import { OnCanDeactivate } from "./can-deactivate"; 3 | 4 | export const canDeactivateGuard: CanDeactivateFn = (component: OnCanDeactivate) => { 5 | if (!component.canDeactivate) { 6 | return true; 7 | } 8 | 9 | return component.canDeactivate(); 10 | } 11 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/guards/can-deactivate.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from "rxjs"; 2 | 3 | export interface OnCanDeactivate { 4 | canDeactivate(): Observable | boolean; 5 | } 6 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/helpers/form-helpers.ts: -------------------------------------------------------------------------------- 1 | import { FormGroup } from "@angular/forms"; 2 | 3 | /** 4 | * Validator function to check if two password fields match. 5 | * 6 | * @param firstPasswordName - The name of the first password form control. 7 | * @param secondPasswordName - The name of the second password form control. 8 | * @returns A validator function that takes a FormGroup and returns an error object if the passwords do not match, or null if they do. 9 | */ 10 | export function confirmPasswordValidator(firstPasswordName: string, secondPasswordName: string) { 11 | return (form: FormGroup) => { 12 | const newPassword = form.get(firstPasswordName); 13 | const confirmPassword = form.get(secondPasswordName); 14 | 15 | if (newPassword.value !== confirmPassword.value) { 16 | return { passwordsDoNotMatch: true }; 17 | } 18 | 19 | return null; 20 | }; 21 | } 22 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/helpers/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./form-helpers"; 2 | export * from "./injection-tokens"; 3 | export * from "./rxjs-helpers"; 4 | 5 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/helpers/injection-tokens.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from "@angular/core"; 2 | 3 | /** 4 | * Injection token for the root URL of the API. 5 | * 6 | * This token can be used to inject the root URL of the API into Angular services or components. 7 | * 8 | * @example 9 | * ```typescript 10 | * constructor(@Inject(API_URL_ROOT) private apiUrlRoot: string) {} 11 | * ``` 12 | */ 13 | export const API_URL_ROOT = new InjectionToken('API_URL_ROOT'); 14 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/helpers/rxjs-helpers.ts: -------------------------------------------------------------------------------- 1 | import { distinctUntilChanged, Observable } from "rxjs"; 2 | 3 | /** 4 | * RxJS operator that filters out items emitted by the source Observable that are the same as the previous item when stringified. 5 | * 6 | * @template T The type of items emitted by the source Observable. 7 | * @returns A function that returns an Observable that emits items from the source Observable only when the serialized JSON representation of the current item is different from the serialized JSON representation of the previous item. 8 | */ 9 | export function distinctUntilJsonChanged() { 10 | return (source$: Observable) => 11 | source$.pipe(distinctUntilChanged((original, incoming) => JSON.stringify(original) === JSON.stringify(incoming))); 12 | } 13 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./components"; 2 | export * from "./helpers"; 3 | export * from "./models"; 4 | export * from "./services"; 5 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/api/api-response-type.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the type of response received from an API call. 3 | */ 4 | export type ApiResponseType = 5 | /** 6 | * Indicates that the API call was successful. 7 | */ 8 | "Success" 9 | /** 10 | * Indicates that the API call encountered an expected error with user-friendly error messages. 11 | */ 12 | | "Error" 13 | /** 14 | * Indicates that the API call encountered an unexpected error. 15 | */ 16 | | "UnexpectedError"; 17 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/api/api-response.ts: -------------------------------------------------------------------------------- 1 | import { ApiResponseType } from "./api-response-type"; 2 | 3 | /** 4 | * Represents a generic API response. 5 | * 6 | * @template T - The type of the result. 7 | */ 8 | export interface ApiResponse { 9 | /** 10 | * The result of the API call. 11 | */ 12 | result?: T; 13 | 14 | /** 15 | * The type of the API response. 16 | */ 17 | type: ApiResponseType; 18 | 19 | /** 20 | * An array of error messages, if any. 21 | */ 22 | errorMessages?: Array; 23 | } 24 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/api/empty-paged-response.ts: -------------------------------------------------------------------------------- 1 | import { PagedResponse } from "./paged-response"; 2 | 3 | /** 4 | * Represents an empty paged response. This is useful when a component requires an initial response to kickstart. 5 | * 6 | * @template T - The type of the data items. 7 | */ 8 | export class EmptyPagedResponse implements PagedResponse { 9 | /** 10 | * The data items in the response. 11 | * 12 | * @type {T[]} 13 | */ 14 | data = []; 15 | 16 | /** 17 | * The current page number. 18 | * 19 | * @type {number} 20 | */ 21 | pageNumber = 1; 22 | 23 | /** 24 | * The number of items per page. 25 | * 26 | * @type {number} 27 | */ 28 | pageSize = 0; 29 | 30 | /** 31 | * The total number of items. 32 | * 33 | * @type {number} 34 | */ 35 | totalCount = 0; 36 | 37 | /** 38 | * The total number of pages. 39 | * 40 | * @type {number} 41 | */ 42 | totalPages = 0; 43 | } 44 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/api/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./api-response"; 2 | export * from "./api-response-type"; 3 | export * from "./empty-paged-response"; 4 | export * from "./error-api-response"; 5 | export * from "./http-error-api-response"; 6 | export * from "./option"; 7 | export * from "./paged-response"; 8 | export * from "./pagination-request"; 9 | export * from "./success-api-response"; 10 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/api/option.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents an option with a key, display name, and description. 3 | */ 4 | export interface Option { 5 | /** 6 | * The unique key for the option. 7 | */ 8 | key: string; 9 | 10 | /** 11 | * The display name of the option. 12 | */ 13 | displayName: string; 14 | 15 | /** 16 | * A brief description of the option. 17 | */ 18 | description: string; 19 | } 20 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/api/paged-response.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a paginated response from an API. 3 | * 4 | * @template T - The type of the items in the paginated response. 5 | */ 6 | export interface PagedResponse { 7 | /** 8 | * The array of items for the current page. 9 | */ 10 | data: Array; 11 | 12 | /** 13 | * The current page number. 14 | */ 15 | pageNumber: number; 16 | 17 | /** 18 | * The number of items per page. 19 | */ 20 | pageSize: number; 21 | 22 | /** 23 | * The total number of items across all pages. 24 | */ 25 | totalCount: number; 26 | 27 | /** 28 | * The total number of pages. 29 | */ 30 | totalPages: number; 31 | } 32 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/api/pagination-request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a request for paginated data. 3 | */ 4 | export interface PaginationRequest { 5 | /** 6 | * The page number to retrieve. 7 | * @remarks 8 | * This is an optional parameter. If not provided, a default value may be used. 9 | */ 10 | pageNumber?: number; 11 | 12 | /** 13 | * The number of items per page. 14 | * @remarks 15 | * This is an optional parameter. If not provided, a default value may be used. 16 | */ 17 | pageSize?: number; 18 | } 19 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/api/success-api-response.ts: -------------------------------------------------------------------------------- 1 | import { ApiResponse } from "./api-response"; 2 | import { ApiResponseType } from "./api-response-type"; 3 | 4 | /** 5 | * Represents a successful API response. This is useful when a method needs to return a successful API response, 6 | * such as when the final result of an operation is not the result of the API call itself. 7 | * @template T - The type of the result. 8 | */ 9 | export class SuccessApiResponse implements ApiResponse { 10 | /** 11 | * The type of the API response. 12 | * @default "Success" 13 | */ 14 | type: ApiResponseType = "Success"; 15 | 16 | /** 17 | * An array of error messages. This will be empty for a successful response. 18 | * @default [] 19 | */ 20 | errorMessages = []; 21 | 22 | /** 23 | * Indicates whether the API call succeeded. 24 | * @default true 25 | */ 26 | succeeded = true; 27 | 28 | /** 29 | * Creates an instance of SuccessApiResponse. 30 | * @param result - The result of the API call. 31 | */ 32 | constructor(public result: T) {} 33 | } 34 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/block-ui-params.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Parameters for the BlockUiService.blockUi method. 3 | */ 4 | export interface BlockUiParams { 5 | /** 6 | * Optional message to be displayed in the UI block. 7 | */ 8 | message?: string; 9 | 10 | /** 11 | * Optional CSS class for the icon to be displayed in the UI block. 12 | */ 13 | iconClass?: string; 14 | } 15 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/button-severity.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the severity levels for a button for use with PrimeNG. 3 | */ 4 | export type ButtonSeverity = 'success' | 'info' | 'warning' | 'danger' | 'help' | 'primary' | 'secondary' | 'contrast' | null | undefined; 5 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./api"; 2 | export * from "./block-ui-params"; 3 | export * from "./button-severity"; 4 | export * from "./extended-map"; 5 | export * from "./list-item"; 6 | export * from "./list-item-group"; 7 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/list-item-group.ts: -------------------------------------------------------------------------------- 1 | import { ListItem } from "./list-item"; 2 | 3 | /** 4 | * Represents a group of list items with a label. This helps with PrimeNG collection controls using groups. 5 | * 6 | * @template T - The type of the items in the list. 7 | */ 8 | export class ListItemGroup { 9 | /** 10 | * Creates an instance of ListItemGroup. 11 | * 12 | * @param label - The label for the group of list items. 13 | * @param listItems - An array of list items of type T. 14 | */ 15 | constructor( 16 | public label: string, 17 | public listItems: Array> 18 | ) {} 19 | } 20 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/models/list-item.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents an item in a list to make it easier to work with PrimeNG collection controls. 3 | * 4 | * @template T - The type of the value. 5 | */ 6 | export class ListItem { 7 | /** 8 | * Creates an instance of ListItem. 9 | * 10 | * @param value - The value of the list item. 11 | * @param label - The label of the list item. 12 | * @param description - An optional description of the list item. 13 | */ 14 | constructor(public value: T, public label: string, public description?: string) {} 15 | } 16 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/services/block-ui.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { BlockUiService } from './block-ui.service'; 3 | import { BlockUiParams } from '@core/models'; 4 | 5 | describe('BlockUiService', () => { 6 | let service: BlockUiService; 7 | 8 | beforeEach(() => { 9 | TestBed.configureTestingModule({}); 10 | service = TestBed.inject(BlockUiService); 11 | }); 12 | 13 | it('should be created', () => { 14 | expect(service).toBeTruthy(); 15 | }); 16 | 17 | it('should emit show event with correct parameters', (done) => { 18 | const blockUiParams: BlockUiParams = { message: 'Loading...' }; 19 | service.onShow$.subscribe((params) => { 20 | expect(params).toEqual(blockUiParams); 21 | done(); 22 | }); 23 | service.show(blockUiParams); 24 | }); 25 | 26 | it('should emit hide event', (done) => { 27 | service.onHide$.subscribe(() => { 28 | expect(true).toBeTrue(); 29 | done(); 30 | }); 31 | service.hide(); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/services/block-ui.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { BlockUiParams } from "@core/models"; 3 | import { Subject } from "rxjs"; 4 | 5 | @Injectable({ 6 | providedIn: "root", 7 | }) 8 | export class BlockUiService { 9 | #showEmitter = new Subject(); 10 | #hideEmitter = new Subject(); 11 | 12 | onShow$ = this.#showEmitter.asObservable(); 13 | onHide$ = this.#hideEmitter.asObservable(); 14 | 15 | show(blockUiParams: BlockUiParams) { 16 | this.#showEmitter.next(blockUiParams); 17 | } 18 | 19 | hide() { 20 | this.#hideEmitter.next(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./block-ui.service"; 2 | export * from "./timer.service"; 3 | export * from "./toast.service"; 4 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/services/initialization.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from "@angular/core"; 2 | import { ReplaySubject } from "rxjs"; 3 | 4 | @Injectable({ 5 | providedIn: "root", 6 | }) 7 | export class InitializationService { 8 | #initializedSubject$ = new ReplaySubject(1); 9 | initialized$ = this.#initializedSubject$.asObservable(); 10 | 11 | initialize() { 12 | this.#initializedSubject$.next(true); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/services/timer.service.ts: -------------------------------------------------------------------------------- 1 | import { DestroyRef, inject, Injectable } from "@angular/core"; 2 | import { takeUntilDestroyed } from "@angular/core/rxjs-interop"; 3 | import { interval, Observable, Subject } from "rxjs"; 4 | 5 | @Injectable({ 6 | providedIn: "root", 7 | }) 8 | export class TimerService { 9 | #destroyRef = inject(DestroyRef); 10 | #timers: { [index: number]: { subject: Subject, observable$: Observable} } = {}; 11 | 12 | watchTimer$(milliseconds: number) { 13 | if (milliseconds < 0) { 14 | throw new Error(`Intervals must be positive: '${milliseconds}' not valid`); 15 | } 16 | 17 | if (!this.#timers[milliseconds]) { 18 | const subject = new Subject(); 19 | this.#timers[milliseconds] = { subject, observable$: subject.asObservable() }; 20 | 21 | interval(milliseconds).pipe(takeUntilDestroyed(this.#destroyRef)).subscribe({ 22 | next: () => this.#timers[milliseconds].subject.next(milliseconds), 23 | }); 24 | } 25 | return this.#timers[milliseconds].observable$; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/core/services/toast.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, inject } from "@angular/core"; 2 | import { MessageService } from "primeng/api"; 3 | 4 | @Injectable({ 5 | providedIn: "root", 6 | }) 7 | export class ToastService { 8 | #messageService = inject(MessageService); 9 | 10 | show(message: string, title: string, severity: string, key: string) { 11 | this.#messageService.add({ 12 | key: key, 13 | detail: message, 14 | severity: severity, 15 | summary: title, 16 | }); 17 | } 18 | 19 | success(message: string, title: string = "Success") { 20 | this.show(message, title, "success", "global"); 21 | } 22 | 23 | info(message: string, title: string = "Info") { 24 | this.show(message, title, "info", "global"); 25 | } 26 | 27 | error(message: string, title: string = "Error") { 28 | this.show(message, title, "error", "global"); 29 | } 30 | 31 | warn(message: string, title: string = "Warning") { 32 | this.show(message, title, "warn", "global"); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/components/pages/reset-instructions-sent/reset-instructions-sent.component.html: -------------------------------------------------------------------------------- 1 | 2 | Check Your Inbox 3 | Password reset instructions have been sent to your email 4 | 5 |
6 | 10 |
11 |
12 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/components/pages/reset-instructions-sent/reset-instructions-sent.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from "@angular/core"; 2 | import { RouterModule } from "@angular/router"; 3 | import { FocusContentLayout } from "@layout/components/layouts/focus-content-layout/focus-content-layout.component"; 4 | import { RoutePipe } from "@routing"; 5 | 6 | @Component({ 7 | standalone: true, 8 | templateUrl: "./reset-instructions-sent.component.html", 9 | imports: [RouterModule, RoutePipe, FocusContentLayout], 10 | }) 11 | export class ResetInstructionsSentComponent {} 12 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/components/pages/reset-password/reset-password.component.html: -------------------------------------------------------------------------------- 1 | 2 | Forgot Password? 3 | Enter your email to reset your password 4 | 5 |
6 |
7 | 8 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | Return to login 24 |
25 | 26 |
27 |
28 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/directives/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./hide-by-roles.directive"; 2 | export * from "./hide-logged-in.directive"; 3 | export * from "./show-by-roles.directive"; 4 | export * from "./show-logged-in.directive"; 5 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./models"; 2 | export * from "./directives"; 3 | export * from "./services"; 4 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./request"; 2 | export * from "./response"; 3 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/models/request/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./login-request"; 2 | export * from "./new-password-request"; 3 | export * from "./register-request"; 4 | export * from "./reset-password-request"; 5 | export * from "./verify-code-request"; 6 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/models/request/login-request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a request to log in to the application. 3 | */ 4 | export interface LoginRequest { 5 | /** 6 | * The email address of the user attempting to log in. 7 | */ 8 | email: string; 9 | 10 | /** 11 | * The password of the user attempting to log in. 12 | */ 13 | password: string; 14 | 15 | /** 16 | * Indicates whether the user should be remembered on the device. 17 | */ 18 | rememberMe: boolean; 19 | 20 | /** 21 | * Details about the device from which the login request is made, such as the user agent, 22 | * so that the user can recognize it later on if they want to revoke the associated token. 23 | */ 24 | deviceDetails: string; 25 | } 26 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/models/request/new-password-request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a request to set a new password after receiving a reset link. 3 | */ 4 | export interface NewPasswordRequest { 5 | /** 6 | * The email address associated with the account. 7 | */ 8 | email: string; 9 | 10 | /** 11 | * The new password to be set. 12 | */ 13 | password: string; 14 | 15 | /** 16 | * The token used to authorize the password change. 17 | */ 18 | token: string; 19 | 20 | /** 21 | * Indicates whether the user should be remembered on the device. 22 | */ 23 | rememberMe: boolean; 24 | 25 | /** 26 | * Details about the device making the request. 27 | */ 28 | deviceDetails: string; 29 | } 30 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/models/request/register-request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a request to register a new user. 3 | */ 4 | export interface RegisterRequest { 5 | /** 6 | * The username of the user. 7 | */ 8 | userName: string; 9 | 10 | /** 11 | * The email address of the user. 12 | */ 13 | email: string; 14 | 15 | /** 16 | * The password chosen by the user. 17 | */ 18 | password: string; 19 | 20 | /** 21 | * The confirmation of the password. 22 | */ 23 | confirmPassword: string; 24 | 25 | /** 26 | * Indicates whether the user should be remembered on the device. 27 | */ 28 | rememberMe: boolean; 29 | 30 | /** 31 | * Details about the device being used for registration. 32 | */ 33 | deviceDetails: string; 34 | } 35 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/models/request/reset-password-request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a request to reset a user's password. 3 | */ 4 | export interface ResetPasswordRequest { 5 | /** 6 | * The email address associated with the user's account. 7 | */ 8 | email: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/models/request/verify-code-request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a request to verify a two-factor code. 3 | */ 4 | export interface VerifyCodeRequest { 5 | /** 6 | * The email address associated with the verification request. 7 | */ 8 | email: string; 9 | 10 | /** 11 | * The verification code to be validated. 12 | */ 13 | code: string; 14 | 15 | /** 16 | * Indicates whether the user should be remembered on the device. 17 | */ 18 | rememberMe: boolean; 19 | 20 | /** 21 | * Details about the device from which the request is made. 22 | */ 23 | deviceDetails: string; 24 | } 25 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/models/response/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./login-result"; 2 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/models/response/login-result.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the result of a login attempt. 3 | */ 4 | export interface LoginResult { 5 | /** 6 | * Indicates whether two-factor authentication is required. Otherwise there will be a bearerToken. 7 | */ 8 | twoFactorRequired: boolean; 9 | 10 | /** 11 | * The bearer token received upon successful login, if two-factor authentication is not required. 12 | */ 13 | bearerToken?: string; 14 | } 15 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/identity/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./identity.service"; 2 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/components/controls/app-footer/app-footer.component.html: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/components/controls/app-footer/app-footer.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from '@angular/core'; 2 | import { LayoutService } from 'src/app/layout/services/layout.service'; 3 | 4 | @Component({ 5 | selector: 'app-footer', 6 | standalone: true, 7 | templateUrl: './app-footer.component.html' 8 | }) 9 | export class AppFooterComponent { 10 | layoutService = inject(LayoutService); 11 | } 12 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/components/controls/app-menu/app-menu.component.html: -------------------------------------------------------------------------------- 1 |
    2 | @for (item of menuItems$ | async; track item; let i = $index) { 3 | @if (!item.separator) { 4 |
  • 5 | } 6 | @if (item.separator) { 7 | 8 | } 9 | } 10 |
11 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/components/controls/app-menu/app-menu.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from "@angular/core"; 2 | import { LayoutService } from "src/app/layout/services/layout.service"; 3 | import { MenuService } from "src/app/layout/services/menu.service"; 4 | import { AppMenuItemComponent } from "../app-menu-item/app-menu-item.component"; 5 | import { CommonModule } from "@angular/common"; 6 | 7 | @Component({ 8 | selector: "app-menu", 9 | standalone: true, 10 | templateUrl: "./app-menu.component.html", 11 | imports: [CommonModule, AppMenuItemComponent], 12 | }) 13 | export class AppMenuComponent { 14 | layoutService = inject(LayoutService); 15 | #menuService = inject(MenuService); 16 | 17 | menuItems$ = this.#menuService.watchMenuItems$(); 18 | } 19 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/components/controls/app-sidebar/app-sidebar.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/components/controls/app-sidebar/app-sidebar.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, inject } from '@angular/core'; 2 | import { AppMenuComponent } from '../app-menu/app-menu.component'; 3 | import { LayoutService } from 'src/app/layout/services/layout.service'; 4 | 5 | @Component({ 6 | selector: 'app-sidebar', 7 | standalone: true, 8 | templateUrl: './app-sidebar.component.html', 9 | imports: [AppMenuComponent] 10 | }) 11 | export class AppSidebarComponent { 12 | layoutService = inject(LayoutService); 13 | el = inject(ElementRef); 14 | } 15 | 16 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/components/controls/app-top-bar/app-top-bar.component.html: -------------------------------------------------------------------------------- 1 |
2 | 6 | 7 | 10 | 11 | 14 | 15 |
16 | 20 |
21 |
22 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/components/controls/app-top-bar/app-top-bar.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ElementRef, inject, ViewChild } from '@angular/core'; 2 | import { MenuItem } from 'primeng/api'; 3 | import { CommonModule } from '@angular/common'; 4 | import { RouterModule } from '@angular/router'; 5 | import { ButtonModule } from 'primeng/button'; 6 | import { RippleModule } from 'primeng/ripple'; 7 | import { RoutePipe } from '@routing'; 8 | import { LayoutService } from 'src/app/layout/services/layout.service'; 9 | 10 | @Component({ 11 | selector: 'app-topbar', 12 | standalone: true, 13 | templateUrl: './app-top-bar.component.html', 14 | imports: [CommonModule, RouterModule, ButtonModule, RippleModule, RoutePipe] 15 | }) 16 | export class AppTopBarComponent { 17 | layoutService = inject(LayoutService); 18 | 19 | items!: MenuItem[]; 20 | 21 | @ViewChild('menubutton') menuButton!: ElementRef; 22 | 23 | @ViewChild('topbarmenubutton') topbarMenuButton!: ElementRef; 24 | 25 | @ViewChild('topbarmenu') menu!: ElementRef; 26 | } 27 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/components/layouts/app-layout/app-layout.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 | 5 |
6 |
7 |
8 | 9 |
10 | 11 |
12 | 13 |
14 |
15 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/components/layouts/focus-content-layout/focus-content-layout.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from '@angular/common'; 2 | import { Component, inject } from '@angular/core'; 3 | import { LayoutService } from 'src/app/layout/services/layout.service'; 4 | 5 | @Component({ 6 | selector: 'focus-content-layout', 7 | standalone: true, 8 | templateUrl: './focus-content-layout.component.html', 9 | imports: [CommonModule] 10 | }) 11 | export class FocusContentLayout { 12 | layoutService = inject(LayoutService); 13 | } 14 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/models/layout-state.ts: -------------------------------------------------------------------------------- 1 | export interface LayoutState { 2 | staticMenuDesktopInactive: boolean; 3 | overlayMenuActive: boolean; 4 | profileSidebarVisible: boolean; 5 | configSidebarVisible: boolean; 6 | staticMenuMobileActive: boolean; 7 | menuHoverActive: boolean; 8 | } 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/layout/models/menu-change-event.ts: -------------------------------------------------------------------------------- 1 | export interface MenuChangeEvent { 2 | key: string; 3 | routeEvent?: boolean; 4 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/components/pages/routes.ts: -------------------------------------------------------------------------------- 1 | import { AppRoute } from "@routing"; 2 | 3 | export const Routes: AppRoute[] = [ 4 | { path: "", data: { alias: "profile" }, loadComponent: () => import("./index/index.component").then(m => m.IndexComponent) }, 5 | { path: "devices", data: { alias: "devices" }, loadComponent: () => import("./devices/devices.component").then(m => m.DevicesComponent) }, 6 | { 7 | path: "change-password", 8 | data: { alias: "change-password" }, 9 | loadComponent: () => import("./change-password/change-password.component").then(m => m.ChangePasswordComponent), 10 | }, 11 | ]; 12 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./models"; 2 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./request"; 2 | export * from "./response"; 3 | export * from "./settings"; 4 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/request/change-password-request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a request to change a user's password. 3 | */ 4 | export interface ChangePasswordRequest { 5 | /** 6 | * The user's current password. 7 | */ 8 | currentPassword: string; 9 | 10 | /** 11 | * The new password that the user wants to set. 12 | */ 13 | newPassword: string; 14 | 15 | /** 16 | * Confirmation of the new password to ensure it was entered correctly. 17 | */ 18 | confirmNewPassword: string; 19 | } 20 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/request/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./change-password-request"; 2 | export * from "./update-profile-request"; 3 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/request/update-profile-request.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a request to update a user's profile. 3 | */ 4 | export interface UpdateProfileRequest { 5 | } 6 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/response/application-settings.ts: -------------------------------------------------------------------------------- 1 | import { ExtendedSettings, FeaturesSettings, PreferencesSettings } from "../settings"; 2 | import { StyleSettings } from "../settings/style-settings"; 3 | 4 | /** 5 | * Represents the settings configuration for this app. 6 | */ 7 | export interface ApplicationSettings { 8 | /** 9 | * Extended settings for the app not covered by other settings. 10 | */ 11 | extended: ExtendedSettings; 12 | 13 | /** 14 | * Feature-specific settings for the app. 15 | */ 16 | features: FeaturesSettings; 17 | 18 | /** 19 | * User preferences settings for the app. 20 | */ 21 | preferences: PreferencesSettings; 22 | 23 | /** 24 | * Style-related settings for the app. 25 | */ 26 | style: StyleSettings; 27 | } 28 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/response/device.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Interface representing a device. 3 | */ 4 | export interface Device { 5 | /** 6 | * The unique identifier for the device. 7 | * @type {string} 8 | */ 9 | id: string; 10 | 11 | /** 12 | * The timestamp of the last time the device was seen. 13 | * @type {number} 14 | */ 15 | lastSeen: number; 16 | 17 | /** 18 | * The IP address from the last time the device was seen. 19 | * @type {string} 20 | */ 21 | ipAddress: string; 22 | 23 | /** 24 | * Device details, such as the browser agent, so it can be more easily identified by the user. 25 | * @type {string} 26 | */ 27 | details: string; 28 | } 29 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/response/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./application-settings"; 2 | export * from "./device"; 3 | export * from "./profile"; 4 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/response/profile.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents a user profile. 3 | */ 4 | export interface Profile { 5 | /** 6 | * The unique identifier of the profile. 7 | */ 8 | id: string; 9 | 10 | /** 11 | * The email address associated with the profile. 12 | */ 13 | email: string; 14 | 15 | /** 16 | * The username of the profile. 17 | */ 18 | userName: string; 19 | } 20 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/settings/extended-settings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the extended settings not covered by other settings. 3 | */ 4 | export interface ExtendedSettings { 5 | } 6 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/settings/features-settings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the settings related to features in the application. 3 | */ 4 | export interface FeaturesSettings { 5 | } 6 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/settings/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./extended-settings"; 2 | export * from "./features-settings"; 3 | export * from "./prefereces-settings"; 4 | export * from "./style-settings"; 5 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/settings/prefereces-settings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the settings related to user preferences. 3 | */ 4 | export interface PreferencesSettings { 5 | } 6 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/profile/models/settings/style-settings.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Represents the style settings for the application. 3 | */ 4 | export interface StyleSettings { 5 | /** 6 | * The scale factor for the UI elements. 7 | */ 8 | scale: number; 9 | 10 | /** 11 | * The mode of the menu. 12 | */ 13 | menuMode: string; 14 | 15 | /** 16 | * The style of the input elements. 17 | */ 18 | inputStyle: string; 19 | 20 | /** 21 | * Indicates whether ripple effect is enabled. 22 | */ 23 | ripple: boolean; 24 | 25 | /** 26 | * The theme of the application. 27 | */ 28 | theme: string; 29 | 30 | /** 31 | * The color scheme of the application. 32 | */ 33 | colorScheme: string; 34 | } 35 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/public/components/support/error/error.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from '@angular/core'; 2 | import { RouterLink } from '@angular/router'; 3 | import { RoutePipe } from '@routing'; 4 | import { LayoutService } from 'src/app/layout/services/layout.service'; 5 | 6 | @Component({ 7 | standalone: true, 8 | templateUrl: './error.component.html', 9 | imports: [RouterLink, RoutePipe] 10 | }) 11 | export class ErrorComponent { 12 | layoutService = inject(LayoutService); 13 | } 14 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/public/components/support/not-found/not-found.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from '@angular/core'; 2 | import { RouterModule } from '@angular/router'; 3 | import { LayoutService } from 'src/app/layout/services/layout.service'; 4 | 5 | @Component({ 6 | standalone: true, 7 | templateUrl: './not-found.component.html', 8 | imports: [RouterModule] 9 | }) 10 | export class NotFoundComponent { 11 | layoutService = inject(LayoutService); 12 | } 13 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/public/components/support/privacy-policy/privacy-policy.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from '@angular/core'; 2 | import { RouterModule } from '@angular/router'; 3 | import { LayoutService } from 'src/app/layout/services/layout.service'; 4 | 5 | @Component({ 6 | standalone: true, 7 | templateUrl: './privacy-policy.component.html', 8 | imports: [RouterModule] 9 | }) 10 | export class PrivacyPolicyComponent { 11 | layoutService = inject(LayoutService); 12 | } 13 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/public/components/support/terms-and-conditions/terms-and-conditions.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, inject } from '@angular/core'; 2 | import { RouterModule } from '@angular/router'; 3 | import { LayoutService } from 'src/app/layout/services/layout.service'; 4 | 5 | @Component({ 6 | standalone: true, 7 | templateUrl: './terms-and-conditions.component.html', 8 | imports: [RouterModule] 9 | }) 10 | export class TermsAndConditionsComponent { 11 | layoutService = inject(LayoutService); 12 | } 13 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/public/services/data.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from "@angular/common/http"; 2 | import { Injectable, inject } from "@angular/core"; 3 | import { API_URL_ROOT } from "@core"; 4 | 5 | @Injectable({ 6 | providedIn: "root", 7 | }) 8 | export class DataService { 9 | #http = inject(HttpClient); 10 | #apiUrlRoot = `${inject(API_URL_ROOT)}public/`; 11 | } 12 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/public/services/public.service.ts: -------------------------------------------------------------------------------- 1 | import { inject, Injectable } from "@angular/core"; 2 | import { DataService } from "./data.service"; 3 | 4 | @Injectable({ 5 | providedIn: "root", 6 | }) 7 | export class PublicService { 8 | #dataService = inject(DataService); 9 | } 10 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/routing/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./models"; 2 | export * from "./pipes"; 3 | export * from "./services"; 4 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/routing/models/app-route.ts: -------------------------------------------------------------------------------- 1 | import { Route } from "@angular/router"; 2 | import { RouteData } from "./route-data"; 3 | 4 | /** 5 | * Represents an application route that extends the Angular `Route` interface. 6 | */ 7 | export interface AppRoute extends Route { 8 | /** 9 | * An optional array of child routes, each of which is also an `AppRoute`. 10 | */ 11 | children?: Array; 12 | 13 | /** 14 | * Optional custom data associated with the route. 15 | */ 16 | data?: RouteData; 17 | } 18 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/routing/models/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./app-route"; 2 | export * from "./route-alias"; 3 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/routing/models/route-data.ts: -------------------------------------------------------------------------------- 1 | import { RouteAlias } from "./route-alias"; 2 | 3 | /** 4 | * Represents the data associated with a route. 5 | */ 6 | export interface RouteData { 7 | /** 8 | * An optional alias for the route. This alias is a shorthand that can be used to generate routes 9 | * and for the RoutePipe for cleaner binding in templates. 10 | */ 11 | alias?: RouteAlias; 12 | 13 | /** 14 | * An optional breadcrumb label for the route. 15 | */ 16 | breadcrumb?: string; 17 | } 18 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/routing/pipes/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./route.pipe"; 2 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/routing/pipes/route.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform, inject } from "@angular/core"; 2 | import { RouteAliasService } from "@routing/services/route-alias-service"; 3 | import { RouteAlias } from "@routing/models/route-alias"; 4 | 5 | @Pipe({ 6 | name: "route", 7 | standalone: true, 8 | }) 9 | /** 10 | * A pipe that transforms a given `RouteAlias` into route data that can be bound to [routerLink] in templates. 11 | */ 12 | export class RoutePipe implements PipeTransform { 13 | #routeAliasService = inject(RouteAliasService); 14 | 15 | /** 16 | * Transforms the provided `RouteAlias` into a route string. 17 | * 18 | * @param view - The `RouteAlias` to be transformed. 19 | * @param value - Optional additional value to be used in the transformation. 20 | * @returns The route string corresponding to the provided `RouteAlias`. 21 | */ 22 | transform(view: RouteAlias, value?: any) { 23 | return this.#routeAliasService.getRoute(view, value); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/routing/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./route-alias-service"; 2 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/components/controls/trade-class-user-infos-display/trade-class-user-infos-display.component.ts: -------------------------------------------------------------------------------- 1 | import { CommonModule } from "@angular/common"; 2 | import { Component, input } from "@angular/core"; 3 | import { RouterLink } from "@angular/router"; 4 | import { ButtonModule } from "primeng/button"; 5 | import { TradeClassUserInfosDisplay } from "src/app/trade-requests/models/trade-class-user-infos-display"; 6 | import { ClassInfoComponent } from "../../../../class-infos/components/controls/class-info/class-info.component"; 7 | import { RoutePipe } from "../../../../routing/pipes/route.pipe"; 8 | 9 | @Component({ 10 | standalone: true, 11 | templateUrl: "./trade-class-user-infos-display.component.html", 12 | selector: "trade-class-user-infos-display", 13 | imports: [CommonModule, RouterLink, ButtonModule, ClassInfoComponent, RoutePipe], 14 | }) 15 | export class TradeClassUserInfosDisplayComponent { 16 | readonly tradeClassUserInfosDisplay = input(undefined); 17 | } 18 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/components/pages/completed-swaps/completed-swaps.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | @for(tradeClassUserInfo of tradeClassUserInfos; track $index) { 6 | 7 | } @empty { 8 |

You haven't complete any swaps!

9 | } 10 | 11 |
12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/components/pages/incoming-swaps/incoming-swaps.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | @for(tradeClassUserInfo of tradeClassUserInfos; track $index) { 6 | 7 | 8 | 9 | } @empty { 10 |

You don't have any incoming swaps!

11 | } 12 | 13 |
14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/components/pages/outgoing-swaps/outgoing-swaps.component.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | @for(tradeClassUserInfo of tradeClassUserInfos; track $index) { 6 | 7 | 8 | 9 | } @empty { 10 |

You don't have any outgoing swaps!

11 | } 12 | 13 |
14 |
15 |
16 |
17 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/helpers/chat-message.helper.ts: -------------------------------------------------------------------------------- 1 | 2 | import { ChatMessage } from "../models/response/chat-message"; 3 | 4 | export class ChatMessageHelper { 5 | static rehydrate(chatMessage: ChatMessage) { 6 | if (chatMessage.timestamp) { 7 | chatMessage.timestamp = new Date(chatMessage.timestamp); 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/helpers/trade-request.helper.ts: -------------------------------------------------------------------------------- 1 | 2 | import { TradeRequest } from "../models/response/trade-request"; 3 | 4 | export class TradeRequestHelper { 5 | static rehydrate(tradeRequest: TradeRequest) { 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/models/request/create-chat-message-request.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface CreateChatMessageRequest { 3 | // TODO: Update these fields to match the server's CreateTradeRequestDto. 4 | content: string; 5 | } 6 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/models/request/create-trade-request-request.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface CreateTradeRequestRequest { 3 | // TODO: Update these fields to match the server's CreateTradeRequestDto. 4 | requestingClassUserId: number; 5 | targetClassUserId: number; 6 | notes: string; 7 | } 8 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/models/request/search-trade-requests-request.ts: -------------------------------------------------------------------------------- 1 | 2 | import { PaginationRequest } from "@core"; 3 | export interface SearchTradeRequestsRequest extends PaginationRequest { 4 | // TODO: Update these fields to match the server's SearchTradeRequestDto. 5 | requestingClassUserId?: number; 6 | targetClassUserId?: number; 7 | status?: string; 8 | notes?: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/models/request/update-trade-request-request.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface UpdateTradeRequestRequest { 3 | // TODO: Update these fields to match the server's UpdateTradeRequestDto. 4 | notes: string; 5 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/models/response/chat-message.ts: -------------------------------------------------------------------------------- 1 | export interface ChatMessage { 2 | // TODO: Update these fields to match the server's CreateTradeRequestDto. 3 | id: number; 4 | content: string; 5 | sendingUserId: string; 6 | timestamp: Date; 7 | } 8 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/models/response/trade-request.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface TradeRequest { 3 | // TODO: Update these fields to match the server's TradeRequestDto. 4 | id: number; 5 | requestingClassUserId: number; 6 | targetClassUserId: number; 7 | status: string; 8 | notes: string; 9 | } 10 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/models/trade-class-user-infos-display.ts: -------------------------------------------------------------------------------- 1 | import { TradeClassUserInfos } from "./trade-class-user-infos"; 2 | 3 | export interface TradeClassUserInfosDisplay { 4 | tradeClassUserInfos: TradeClassUserInfos; 5 | flip: boolean; 6 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/trade-requests/models/trade-class-user-infos.ts: -------------------------------------------------------------------------------- 1 | import { ClassUserInfo } from "src/app/class-infos/models/class-user-info"; 2 | 3 | export interface TradeClassUserInfos { 4 | // TODO: Update these fields to match the server's TradeRequestDto. 5 | id: number; 6 | requestingClassUser: ClassUserInfo; 7 | targetClassUser: ClassUserInfo; 8 | status: string; 9 | notes: string; 10 | } 11 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/user/components/pages/browse-swaps/browse-swaps.component.css: -------------------------------------------------------------------------------- 1 | .offers-list { 2 | max-width: 600px; 3 | margin: 20px auto; 4 | padding: 10px; 5 | border: 1px solid #ddd; 6 | border-radius: 8px; 7 | background-color: #f9f9f9; 8 | } 9 | 10 | .offer-item { 11 | padding: 20px; 12 | border-bottom: 1px solid #ddd; 13 | margin-bottom: 20px; 14 | } 15 | 16 | .offer-item p { 17 | margin: 5px 0; 18 | } 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/user/components/pages/browse-swaps/browse-swaps.component.html: -------------------------------------------------------------------------------- 1 | Incoming Offers 2 | 3 |
4 |
5 | 6 |

Wanted Class: {{ offer.wantedClass }}

7 |

Offered Class: {{ offer.offeredClass }}

8 | 9 | 10 |
11 |
12 |
13 | 14 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/user/components/pages/create-swap/create-swap.component.css: -------------------------------------------------------------------------------- 1 | form { 2 | display: flex; 3 | flex-direction: column; 4 | } 5 | 6 | .form-group { 7 | margin-bottom: 1rem; /* Adds space between each form group */ 8 | } 9 | 10 | label { 11 | font-weight: bold; 12 | } 13 | 14 | p-dropdown { 15 | width: 100%; 16 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/user/components/pages/my-swaps/my-swap.component.html: -------------------------------------------------------------------------------- 1 | 2 |

List of my swaps!

3 |
-------------------------------------------------------------------------------- /src/lightnap-ng/src/app/user/components/pages/my-swaps/my-swap.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { CardModule } from 'primeng/card'; 3 | 4 | @Component({ 5 | selector: 'app-my-swap', 6 | standalone: true, 7 | templateUrl: './my-swap.component.html', 8 | imports: [CardModule] 9 | }) 10 | export class MySwapsComponent { 11 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/user/components/pages/routes.ts: -------------------------------------------------------------------------------- 1 | import { AppRoute } from "@routing"; 2 | 3 | export const Routes: AppRoute[] = [ 4 | { path: "", data: { alias: "user-home" }, loadComponent: () => import("./index/index.component").then(m => m.IndexComponent) }, 5 | { path: "create-swap", data: { alias: "create-swap" }, loadComponent: () => import("./create-swap/create-swap.component").then(m => m.CreateSwapComponent) }, 6 | { path: "my-swaps", data: { alias: "my-swaps" }, loadComponent: () => import("./my-swaps/my-swap.component").then(m => m.MySwapsComponent) }, 7 | { path: "browse-swaps", data: { alias: "browse-swaps" }, loadComponent: () => import("./browse-swaps/browse-swaps.component").then(m => m.BrowseSwapsComponent) }, 8 | ]; 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/user/services/data.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from "@angular/common/http"; 2 | import { Injectable, inject } from "@angular/core"; 3 | import { API_URL_ROOT } from "@core"; 4 | 5 | @Injectable({ 6 | providedIn: "root", 7 | }) 8 | export class DataService { 9 | #http = inject(HttpClient); 10 | #apiUrlRoot = `${inject(API_URL_ROOT)}service/`; 11 | } 12 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/app/user/services/user.service.ts: -------------------------------------------------------------------------------- 1 | import { inject, Injectable } from "@angular/core"; 2 | import { DataService } from "./data.service"; 3 | 4 | @Injectable({ 5 | providedIn: "root", 6 | }) 7 | export class UserService { 8 | #dataService = inject(DataService); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/logo-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/logo-dark.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/logo-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/logo-white.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/arya-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/arya-blue.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/arya-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/arya-green.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/arya-orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/arya-orange.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/arya-purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/arya-purple.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/fluent-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/fluent-light.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/lara-dark-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/lara-dark-blue.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/lara-dark-indigo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/lara-dark-indigo.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/lara-dark-purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/lara-dark-purple.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/lara-dark-teal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/lara-dark-teal.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/lara-light-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/lara-light-blue.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/lara-light-indigo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/lara-light-indigo.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/lara-light-purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/lara-light-purple.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/lara-light-teal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/lara-light-teal.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/luna-amber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/luna-amber.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/luna-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/luna-blue.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/luna-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/luna-green.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/luna-pink.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/luna-pink.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/md-dark-deeppurple.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/md-dark-indigo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/md-light-deeppurple.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/md-light-indigo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 2 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/saga-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/saga-blue.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/saga-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/saga-green.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/saga-orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/saga-orange.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/saga-purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/saga-purple.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/tailwind-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/tailwind-light.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/vela-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/vela-blue.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/vela-green.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/vela-green.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/vela-orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/vela-orange.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/images/themes/vela-purple.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/images/themes/vela-purple.png -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/layout/_content.scss: -------------------------------------------------------------------------------- 1 | .layout-main-container { 2 | display: flex; 3 | flex-direction: column; 4 | min-height: 100vh; 5 | justify-content: space-between; 6 | padding: 7rem 2rem 2rem 4rem; 7 | transition: margin-left $transitionDuration; 8 | } 9 | 10 | .layout-main { 11 | flex: 1 1 auto; 12 | } 13 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/layout/_footer.scss: -------------------------------------------------------------------------------- 1 | .layout-footer { 2 | transition: margin-left $transitionDuration; 3 | display: flex; 4 | align-items: center; 5 | justify-content: center; 6 | padding-top: 1rem; 7 | border-top: 1px solid var(--surface-border); 8 | } 9 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/layout/_main.scss: -------------------------------------------------------------------------------- 1 | * { 2 | box-sizing: border-box; 3 | } 4 | 5 | html { 6 | height: 100%; 7 | font-size: $scale; 8 | } 9 | 10 | body { 11 | font-family: var(--font-family); 12 | color: var(--text-color); 13 | background-color: var(--surface-ground); 14 | margin: 0; 15 | padding: 0; 16 | min-height: 100%; 17 | -webkit-font-smoothing: antialiased; 18 | -moz-osx-font-smoothing: grayscale; 19 | } 20 | 21 | a { 22 | text-decoration: none; 23 | color: var(--primary-color); 24 | } 25 | 26 | .layout-wrapper { 27 | min-height: 100vh; 28 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/layout/_mixins.scss: -------------------------------------------------------------------------------- 1 | @mixin focused() { 2 | outline: 0 none; 3 | outline-offset: 0; 4 | transition: box-shadow .2s; 5 | box-shadow: var(--focus-ring); 6 | } 7 | 8 | @mixin focused-inset() { 9 | outline: 0 none; 10 | outline-offset: 0; 11 | transition: box-shadow .2s; 12 | box-shadow: inset var(--focus-ring); 13 | } 14 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/layout/_preloading.scss: -------------------------------------------------------------------------------- 1 | .preloader { 2 | position: fixed; 3 | z-index: 999999; 4 | background: #edf1f5; 5 | width: 100%; 6 | height: 100%; 7 | } 8 | .preloader-content { 9 | border: 0 solid transparent; 10 | border-radius: 50%; 11 | width: 150px; 12 | height: 150px; 13 | position: absolute; 14 | top: calc(50vh - 75px); 15 | left: calc(50vw - 75px); 16 | } 17 | 18 | .preloader-content:before, .preloader-content:after{ 19 | content: ''; 20 | border: 1em solid var(--primary-color); 21 | border-radius: 50%; 22 | width: inherit; 23 | height: inherit; 24 | position: absolute; 25 | top: 0; 26 | left: 0; 27 | animation: loader 2s linear infinite; 28 | opacity: 0; 29 | } 30 | 31 | .preloader-content:before{ 32 | animation-delay: 0.5s; 33 | } 34 | 35 | @keyframes loader{ 36 | 0%{ 37 | transform: scale(0); 38 | opacity: 0; 39 | } 40 | 50%{ 41 | opacity: 1; 42 | } 43 | 100%{ 44 | transform: scale(1); 45 | opacity: 0; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/layout/_utils.scss: -------------------------------------------------------------------------------- 1 | .card { 2 | background: var(--surface-card); 3 | border: 1px solid var(--surface-border); 4 | padding: 2rem; 5 | margin-bottom: 2rem; 6 | box-shadow: var(--card-shadow); 7 | border-radius: $borderRadius; 8 | 9 | &:last-child { 10 | margin-bottom: 0; 11 | } 12 | } 13 | 14 | .p-toast { 15 | &.p-toast-top-right, 16 | &.p-toast-top-left, 17 | &.p-toast-top-center { 18 | top: 100px; 19 | } 20 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/layout/_variables.scss: -------------------------------------------------------------------------------- 1 | /* General */ 2 | $scale:14px; /* main font size */ 3 | $borderRadius:12px; /* border radius of layout element e.g. card, sidebar */ 4 | $transitionDuration:.2s; /* transition duration of layout elements e.g. sidebar, overlay menus */ 5 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/layout/layout.scss: -------------------------------------------------------------------------------- 1 | @import './_variables'; 2 | @import "./_mixins"; 3 | @import "./_preloading"; 4 | @import "./_main"; 5 | @import "./_topbar"; 6 | @import "./_menu"; 7 | @import "./_config"; 8 | @import "./_content"; 9 | @import "./_footer"; 10 | @import "./_responsive"; 11 | @import "./_utils"; 12 | @import "./_typography"; -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/lara-dark-blue/fonts/Inter-roman.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/lara-dark-blue/fonts/Inter-roman.var.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/lara-dark-indigo/fonts/Inter-roman.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/lara-dark-indigo/fonts/Inter-roman.var.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/lara-dark-purple/fonts/Inter-roman.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/lara-dark-purple/fonts/Inter-roman.var.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/lara-dark-teal/fonts/Inter-roman.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/lara-dark-teal/fonts/Inter-roman.var.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/lara-light-blue/fonts/Inter-roman.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/lara-light-blue/fonts/Inter-roman.var.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/lara-light-indigo/fonts/Inter-roman.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/lara-light-indigo/fonts/Inter-roman.var.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/lara-light-purple/fonts/Inter-roman.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/lara-light-purple/fonts/Inter-roman.var.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/lara-light-teal/fonts/Inter-roman.var.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/lara-light-teal/fonts/Inter-roman.var.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-500.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-500.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-700.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-700.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-dark-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-500.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-500.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-700.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-700.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/md-light-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-500.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-500.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-700.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-700.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-dark-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-500.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-700.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-deeppurple/fonts/roboto-v20-latin-ext_latin-regular.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-500.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-500.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-500.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-500.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-700.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-700.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-700.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-700.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/mdc-light-indigo/fonts/roboto-v20-latin-ext_latin-regular.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Bold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Bold.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Bold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Bold.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Light.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Light.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Light.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Light.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Medium.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Medium.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Medium.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Medium.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Regular.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-Regular.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-SemiBold.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-SemiBold.woff -------------------------------------------------------------------------------- /src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-SemiBold.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/assets/layout/styles/theme/tailwind-light/fonts/Inter-SemiBold.woff2 -------------------------------------------------------------------------------- /src/lightnap-ng/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | apiUrlRoot: "/api/" 4 | }; 5 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false, 7 | apiUrlRoot: "https://localhost:7266/api/" 8 | }; 9 | 10 | /* 11 | * For easier debugging in development mode, you can import the following file 12 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 13 | * 14 | * This import should be commented out in production mode because it will have a negative impact 15 | * on performance if an error is thrown. 16 | */ 17 | // import 'zone.js/plugins/zone-error'; // Included with Angular CLI. 18 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JDKaim/HuskySwap/d1c4f447db8a57adc8ff61e16d3b24cb57a93b69/src/lightnap-ng/src/favicon.ico -------------------------------------------------------------------------------- /src/lightnap-ng/src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | HuskySwap 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /src/lightnap-ng/src/styles.scss: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | $gutter: 1rem; //for primeflex grid system 4 | @import "assets/layout/styles/layout/layout.scss"; 5 | 6 | /* PrimeNG */ 7 | @import "../node_modules/primeng/resources/primeng.min.css"; 8 | @import "../node_modules/primeflex/primeflex.scss"; 9 | @import "../node_modules/primeicons/primeicons.css"; 10 | 11 | body { 12 | background-color: #4b2e83; 13 | } -------------------------------------------------------------------------------- /src/lightnap-ng/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: { 11 | context(path: string, deep?: boolean, filter?: RegExp): { 12 | (id: string): T; 13 | keys(): string[]; 14 | }; 15 | }; 16 | 17 | // First, initialize the Angular testing environment. 18 | getTestBed().initTestEnvironment( 19 | BrowserDynamicTestingModule, 20 | platformBrowserDynamicTesting(), 21 | ); 22 | 23 | // Then we find all the tests. 24 | const context = require.context('./', true, /\.spec\.ts$/); 25 | // And load the modules. 26 | context.keys().map(context); 27 | -------------------------------------------------------------------------------- /src/lightnap-ng/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.d.ts" 13 | ] 14 | } 15 | -------------------------------------------------------------------------------- /src/lightnap-ng/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts" 12 | ], 13 | "include": [ 14 | "src/**/*.spec.ts", 15 | "src/**/*.d.ts" 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /src/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "src", 3 | "lockfileVersion": 3, 4 | "requires": true, 5 | "packages": {} 6 | } 7 | --------------------------------------------------------------------------------