├── .dockerignore
├── .gitattributes
├── .github
├── FUNDING.yml
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ ├── documenation-request.md
│ └── feature_request.md
└── workflows
│ └── dotnet.yml
├── .gitignore
├── .vscode
├── launch.json
└── tasks.json
├── BlazorHero.CleanArchitecture.sln
├── Features.md
├── LICENSE
├── README.md
├── docker-compose.dcproj
├── docker-compose.yml
└── src
├── Application
├── Application.csproj
├── Configurations
│ ├── AppConfiguration.cs
│ └── MailConfiguration.cs
├── Enums
│ ├── AuditType.cs
│ └── UploadType.cs
├── Exceptions
│ └── ApiException.cs
├── Extensions
│ ├── EnumExtensions.cs
│ ├── ExpressionExtensions.cs
│ ├── QueryableExtensions.cs
│ └── ServiceCollectionExtensions.cs
├── Features
│ ├── Brands
│ │ ├── Commands
│ │ │ ├── AddEdit
│ │ │ │ └── AddEditBrandCommand.cs
│ │ │ ├── Delete
│ │ │ │ └── DeleteBrandCommand.cs
│ │ │ └── Import
│ │ │ │ └── ImportBrandsCommand.cs
│ │ └── Queries
│ │ │ ├── Export
│ │ │ └── ExportBrandsQuery.cs
│ │ │ ├── GetAll
│ │ │ ├── GetAllBrandsQuery.cs
│ │ │ └── GetAllBrandsResponse.cs
│ │ │ └── GetById
│ │ │ ├── GetBrandByIdQuery.cs
│ │ │ └── GetBrandByIdResponse.cs
│ ├── Dashboards
│ │ └── Queries
│ │ │ └── GetData
│ │ │ ├── DashboardDataResponse.cs
│ │ │ └── GetDashboardDataQuery.cs
│ ├── DocumentTypes
│ │ ├── Commands
│ │ │ ├── AddEdit
│ │ │ │ └── AddEditDocumentTypeCommand.cs
│ │ │ └── Delete
│ │ │ │ └── DeleteDocumentTypeCommand.cs
│ │ └── Queries
│ │ │ ├── Export
│ │ │ └── ExportDocumentTypesQuery.cs
│ │ │ ├── GetAll
│ │ │ ├── GetAllDocumentTypesQuery.cs
│ │ │ └── GetAllDocumentTypesResponse.cs
│ │ │ └── GetById
│ │ │ ├── GetDocumentTypeByIdQuery.cs
│ │ │ └── GetDocumentTypeByIdResponse.cs
│ ├── Documents
│ │ ├── Commands
│ │ │ ├── AddEdit
│ │ │ │ └── AddEditDocumentCommand.cs
│ │ │ └── Delete
│ │ │ │ └── DeleteDocumentCommand.cs
│ │ └── Queries
│ │ │ ├── GetAll
│ │ │ ├── GetAllDocumentsQuery.cs
│ │ │ └── GetAllDocumentsResponse.cs
│ │ │ └── GetById
│ │ │ ├── GetDocumentByIdQuery.cs
│ │ │ └── GetDocumentByIdResponse.cs
│ ├── ExtendedAttributes
│ │ ├── Commands
│ │ │ ├── AddEdit
│ │ │ │ └── AddEditExtendedAttributeCommand.cs
│ │ │ └── Delete
│ │ │ │ └── DeleteExtendedAttributeCommand.cs
│ │ └── Queries
│ │ │ ├── Export
│ │ │ └── ExportExtendedAttributesQuery.cs
│ │ │ ├── GetAll
│ │ │ ├── GetAllExtendedAttributesQuery.cs
│ │ │ └── GetAllExtendedAttributesResponse.cs
│ │ │ ├── GetAllByEntityId
│ │ │ ├── GetAllExtendedAttributesByEntityIdQuery.cs
│ │ │ └── GetAllExtendedAttributesByEntityIdResponse.cs
│ │ │ └── GetById
│ │ │ ├── GetExtendedAttributeByIdQuery.cs
│ │ │ └── GetExtendedAttributeByIdResponse.cs
│ └── Products
│ │ ├── Commands
│ │ ├── AddEdit
│ │ │ └── AddEditProductCommand.cs
│ │ └── Delete
│ │ │ └── DeleteProductCommand.cs
│ │ └── Queries
│ │ ├── Export
│ │ └── ExportProductsQuery.cs
│ │ ├── GetAllPaged
│ │ ├── GetAllPagedProductsResponse.cs
│ │ └── GetAllProductsQuery.cs
│ │ └── GetProductImage
│ │ ├── GetProductImageQuery.cs
│ │ └── GetProductImageResponse.cs
├── Interfaces
│ ├── Chat
│ │ ├── IChatHistory.cs
│ │ └── IChatUser.cs
│ ├── Common
│ │ ├── IScopedService.cs
│ │ ├── IService.cs
│ │ └── ISingletonService.cs
│ ├── Repositories
│ │ ├── IBrandRepository.cs
│ │ ├── IDocumentRepository.cs
│ │ ├── IDocumentTypeRepository.cs
│ │ ├── IExtendedAttributeUnitOfWork.cs
│ │ ├── IProductRepository.cs
│ │ ├── IRepositoryAsync.cs
│ │ └── IUnitOfWork.cs
│ ├── Serialization
│ │ ├── Options
│ │ │ └── IJsonSerializerOptions.cs
│ │ ├── Serializers
│ │ │ └── IJsonSerializer.cs
│ │ └── Settings
│ │ │ └── IJsonSerializerSettings.cs
│ └── Services
│ │ ├── Account
│ │ └── IAccountService.cs
│ │ ├── IAuditService.cs
│ │ ├── IChatService.cs
│ │ ├── ICurrentUserService.cs
│ │ ├── IDatabaseSeeder.cs
│ │ ├── IDateTimeService.cs
│ │ ├── IExcelService.cs
│ │ ├── IMailService.cs
│ │ ├── IUploadService.cs
│ │ ├── Identity
│ │ ├── IRoleClaimService.cs
│ │ ├── IRoleService.cs
│ │ ├── ITokenService.cs
│ │ └── IUserService.cs
│ │ └── Storage
│ │ ├── ChangedEventArgs.cs
│ │ ├── ChangingEventArgs.cs
│ │ ├── IServerStorageService.cs
│ │ ├── ISyncServerStorageService.cs
│ │ └── Provider
│ │ └── IServerStorageProvider.cs
├── Mappings
│ ├── BrandProfile.cs
│ ├── DocumentProfile.cs
│ ├── DocumentTypeProfile.cs
│ ├── ExtendedAttributeProfile.cs
│ └── ProductProfile.cs
├── Models
│ └── Chat
│ │ ├── ChatHistory.cs
│ │ └── Message.cs
├── Requests
│ ├── Catalog
│ │ └── GetAllPagedProductsRequest.cs
│ ├── Documents
│ │ └── GetAllPagedDocumentsRequest.cs
│ ├── Identity
│ │ ├── ChangePasswordRequest.cs
│ │ ├── ForgotPasswordRequest.cs
│ │ ├── PermissionRequest.cs
│ │ ├── RefreshTokenRequest.cs
│ │ ├── RegisterRequest.cs
│ │ ├── ResetPasswordRequest.cs
│ │ ├── RoleClaimRequest.cs
│ │ ├── RoleRequest.cs
│ │ ├── ToggleUserStatusRequest.cs
│ │ ├── TokenRequest.cs
│ │ ├── UpdateProfilePictureRequest.cs
│ │ ├── UpdateProfileRequest.cs
│ │ └── UpdateUserRolesRequest.cs
│ ├── Mail
│ │ └── MailRequest.cs
│ ├── PagedRequest.cs
│ └── UploadRequest.cs
├── Resources
│ ├── Features
│ │ ├── Brands
│ │ │ ├── Commands
│ │ │ │ ├── AddEdit
│ │ │ │ │ ├── AddEditBrandCommandHandler.ar.resx
│ │ │ │ │ ├── AddEditBrandCommandHandler.en.resx
│ │ │ │ │ ├── AddEditBrandCommandHandler.es.resx
│ │ │ │ │ ├── AddEditBrandCommandHandler.fr.resx
│ │ │ │ │ ├── AddEditBrandCommandHandler.it.resx
│ │ │ │ │ ├── AddEditBrandCommandHandler.km.resx
│ │ │ │ │ ├── AddEditBrandCommandHandler.nl.resx
│ │ │ │ │ └── AddEditBrandCommandHandler.ru.resx
│ │ │ │ ├── Delete
│ │ │ │ │ ├── DeleteBrandCommandHandler.ar.resx
│ │ │ │ │ ├── DeleteBrandCommandHandler.de.nl.resx
│ │ │ │ │ ├── DeleteBrandCommandHandler.de.resx
│ │ │ │ │ ├── DeleteBrandCommandHandler.en.resx
│ │ │ │ │ ├── DeleteBrandCommandHandler.es.resx
│ │ │ │ │ ├── DeleteBrandCommandHandler.fr.resx
│ │ │ │ │ ├── DeleteBrandCommandHandler.id.resx
│ │ │ │ │ ├── DeleteBrandCommandHandler.it.resx
│ │ │ │ │ ├── DeleteBrandCommandHandler.km.resx
│ │ │ │ │ ├── DeleteBrandCommandHandler.ru.resx
│ │ │ │ │ └── DeleteBrandCommandHandler.sv.resx
│ │ │ │ └── Import
│ │ │ │ │ ├── ImportBrandsCommandHandler.ar.resx
│ │ │ │ │ ├── ImportBrandsCommandHandler.de.resx
│ │ │ │ │ ├── ImportBrandsCommandHandler.en.resx
│ │ │ │ │ ├── ImportBrandsCommandHandler.es.resx
│ │ │ │ │ ├── ImportBrandsCommandHandler.fr.resx
│ │ │ │ │ ├── ImportBrandsCommandHandler.id.resx
│ │ │ │ │ ├── ImportBrandsCommandHandler.it.resx
│ │ │ │ │ ├── ImportBrandsCommandHandler.km.resx
│ │ │ │ │ ├── ImportBrandsCommandHandler.nl.resx
│ │ │ │ │ ├── ImportBrandsCommandHandler.ru.resx
│ │ │ │ │ └── ImportBrandsCommandHandler.sv.resx
│ │ │ └── Queries
│ │ │ │ └── Export
│ │ │ │ ├── ExportBrandsQueryHandler.ar.resx
│ │ │ │ ├── ExportBrandsQueryHandler.en.resx
│ │ │ │ ├── ExportBrandsQueryHandler.es.resx
│ │ │ │ ├── ExportBrandsQueryHandler.fr.resx
│ │ │ │ ├── ExportBrandsQueryHandler.km.resx
│ │ │ │ ├── ExportBrandsQueryHandler.nl.resx
│ │ │ │ └── ExportBrandsQueryHandler.ru.resx
│ │ ├── Dashboards
│ │ │ └── Queries
│ │ │ │ └── GetData
│ │ │ │ ├── GetDashboardDataQueryHandler.ar.resx
│ │ │ │ ├── GetDashboardDataQueryHandler.en.resx
│ │ │ │ ├── GetDashboardDataQueryHandler.es.resx
│ │ │ │ ├── GetDashboardDataQueryHandler.fr.resx
│ │ │ │ ├── GetDashboardDataQueryHandler.it.resx
│ │ │ │ ├── GetDashboardDataQueryHandler.km.resx
│ │ │ │ ├── GetDashboardDataQueryHandler.nl.resx
│ │ │ │ └── GetDashboardDataQueryHandler.ru.resx
│ │ ├── DocumentTypes
│ │ │ ├── Commands
│ │ │ │ ├── AddEdit
│ │ │ │ │ ├── AddEditDocumentTypeCommandHandler.ar.resx
│ │ │ │ │ ├── AddEditDocumentTypeCommandHandler.en.nl.resx
│ │ │ │ │ ├── AddEditDocumentTypeCommandHandler.en.resx
│ │ │ │ │ ├── AddEditDocumentTypeCommandHandler.es.resx
│ │ │ │ │ ├── AddEditDocumentTypeCommandHandler.fr.resx
│ │ │ │ │ ├── AddEditDocumentTypeCommandHandler.km.resx
│ │ │ │ │ └── AddEditDocumentTypeCommandHandler.ru.resx
│ │ │ │ └── Delete
│ │ │ │ │ ├── DeleteDocumentTypeCommandHandler.ar.resx
│ │ │ │ │ ├── DeleteDocumentTypeCommandHandler.en.nl.resx
│ │ │ │ │ ├── DeleteDocumentTypeCommandHandler.en.resx
│ │ │ │ │ ├── DeleteDocumentTypeCommandHandler.es.resx
│ │ │ │ │ ├── DeleteDocumentTypeCommandHandler.fr.resx
│ │ │ │ │ ├── DeleteDocumentTypeCommandHandler.km.resx
│ │ │ │ │ └── DeleteDocumentTypeCommandHandler.ru.resx
│ │ │ └── Queries
│ │ │ │ └── Export
│ │ │ │ ├── ExportDocumentTypesQueryHandler.ar.resx
│ │ │ │ ├── ExportDocumentTypesQueryHandler.en.resx
│ │ │ │ ├── ExportDocumentTypesQueryHandler.es.resx
│ │ │ │ ├── ExportDocumentTypesQueryHandler.fr.resx
│ │ │ │ ├── ExportDocumentTypesQueryHandler.km.resx
│ │ │ │ ├── ExportDocumentTypesQueryHandler.nl.resx
│ │ │ │ └── ExportDocumentTypesQueryHandler.ru.resx
│ │ ├── Documents
│ │ │ └── Commands
│ │ │ │ ├── AddEdit
│ │ │ │ ├── AddEditDocumentCommandHandler.ar.resx
│ │ │ │ ├── AddEditDocumentCommandHandler.en.nl.resx
│ │ │ │ ├── AddEditDocumentCommandHandler.en.resx
│ │ │ │ ├── AddEditDocumentCommandHandler.es.resx
│ │ │ │ ├── AddEditDocumentCommandHandler.fr.resx
│ │ │ │ ├── AddEditDocumentCommandHandler.it.resx
│ │ │ │ ├── AddEditDocumentCommandHandler.km.resx
│ │ │ │ └── AddEditDocumentCommandHandler.ru.resx
│ │ │ │ └── Delete
│ │ │ │ ├── DeleteDocumentCommandHandler.ar.resx
│ │ │ │ ├── DeleteDocumentCommandHandler.en.nl.resx
│ │ │ │ ├── DeleteDocumentCommandHandler.en.resx
│ │ │ │ ├── DeleteDocumentCommandHandler.es.resx
│ │ │ │ ├── DeleteDocumentCommandHandler.fr.resx
│ │ │ │ ├── DeleteDocumentCommandHandler.it.resx
│ │ │ │ ├── DeleteDocumentCommandHandler.km.resx
│ │ │ │ └── DeleteDocumentCommandHandler.ru.resx
│ │ ├── ExtendedAttributes
│ │ │ ├── Commands
│ │ │ │ ├── AddEdit
│ │ │ │ │ ├── AddEditExtendedAttributeCommandLocalization.ar.resx
│ │ │ │ │ ├── AddEditExtendedAttributeCommandLocalization.de.nl.resx
│ │ │ │ │ ├── AddEditExtendedAttributeCommandLocalization.de.resx
│ │ │ │ │ ├── AddEditExtendedAttributeCommandLocalization.en.resx
│ │ │ │ │ ├── AddEditExtendedAttributeCommandLocalization.es.resx
│ │ │ │ │ ├── AddEditExtendedAttributeCommandLocalization.fr.resx
│ │ │ │ │ ├── AddEditExtendedAttributeCommandLocalization.id.resx
│ │ │ │ │ ├── AddEditExtendedAttributeCommandLocalization.it.resx
│ │ │ │ │ ├── AddEditExtendedAttributeCommandLocalization.km.resx
│ │ │ │ │ ├── AddEditExtendedAttributeCommandLocalization.ru.resx
│ │ │ │ │ └── AddEditExtendedAttributeCommandLocalization.sv.resx
│ │ │ │ └── Delete
│ │ │ │ │ ├── DeleteExtendedAttributeCommandLocalization.ar.resx
│ │ │ │ │ ├── DeleteExtendedAttributeCommandLocalization.de.nl.resx
│ │ │ │ │ ├── DeleteExtendedAttributeCommandLocalization.de.resx
│ │ │ │ │ ├── DeleteExtendedAttributeCommandLocalization.en.resx
│ │ │ │ │ ├── DeleteExtendedAttributeCommandLocalization.es.resx
│ │ │ │ │ ├── DeleteExtendedAttributeCommandLocalization.fr.resx
│ │ │ │ │ ├── DeleteExtendedAttributeCommandLocalization.id.resx
│ │ │ │ │ ├── DeleteExtendedAttributeCommandLocalization.it.resx
│ │ │ │ │ ├── DeleteExtendedAttributeCommandLocalization.km.resx
│ │ │ │ │ ├── DeleteExtendedAttributeCommandLocalization.ru.resx
│ │ │ │ │ └── DeleteExtendedAttributeCommandLocalization.sv.resx
│ │ │ └── Queries
│ │ │ │ └── Export
│ │ │ │ ├── ExportExtendedAttributesQueryLocalization.ar.resx
│ │ │ │ ├── ExportExtendedAttributesQueryLocalization.de.resx
│ │ │ │ ├── ExportExtendedAttributesQueryLocalization.en.resx
│ │ │ │ ├── ExportExtendedAttributesQueryLocalization.es.resx
│ │ │ │ ├── ExportExtendedAttributesQueryLocalization.fr.resx
│ │ │ │ ├── ExportExtendedAttributesQueryLocalization.id.resx
│ │ │ │ ├── ExportExtendedAttributesQueryLocalization.it.resx
│ │ │ │ ├── ExportExtendedAttributesQueryLocalization.km.resx
│ │ │ │ ├── ExportExtendedAttributesQueryLocalization.nl.resx
│ │ │ │ ├── ExportExtendedAttributesQueryLocalization.ru.resx
│ │ │ │ └── ExportExtendedAttributesQueryLocalization.sv.resx
│ │ └── Products
│ │ │ ├── Commands
│ │ │ ├── AddEdit
│ │ │ │ ├── AddEditProductCommandHandler.ar.resx
│ │ │ │ ├── AddEditProductCommandHandler.en.nl.resx
│ │ │ │ ├── AddEditProductCommandHandler.en.resx
│ │ │ │ ├── AddEditProductCommandHandler.es.resx
│ │ │ │ ├── AddEditProductCommandHandler.fr.resx
│ │ │ │ ├── AddEditProductCommandHandler.it.resx
│ │ │ │ ├── AddEditProductCommandHandler.km.resx
│ │ │ │ └── AddEditProductCommandHandler.ru.resx
│ │ │ └── Delete
│ │ │ │ ├── DeleteProductCommandHandler.ar.resx
│ │ │ │ ├── DeleteProductCommandHandler.de.nl.resx
│ │ │ │ ├── DeleteProductCommandHandler.de.resx
│ │ │ │ ├── DeleteProductCommandHandler.en.resx
│ │ │ │ ├── DeleteProductCommandHandler.es.resx
│ │ │ │ ├── DeleteProductCommandHandler.fr.resx
│ │ │ │ ├── DeleteProductCommandHandler.id.resx
│ │ │ │ ├── DeleteProductCommandHandler.it.resx
│ │ │ │ ├── DeleteProductCommandHandler.km.resx
│ │ │ │ ├── DeleteProductCommandHandler.ru.resx
│ │ │ │ └── DeleteProductCommandHandler.sv.resx
│ │ │ └── Queries
│ │ │ └── Export
│ │ │ ├── ExportProductsQueryHandler.ar.resx
│ │ │ ├── ExportProductsQueryHandler.en.resx
│ │ │ ├── ExportProductsQueryHandler.es.resx
│ │ │ ├── ExportProductsQueryHandler.fr.resx
│ │ │ ├── ExportProductsQueryHandler.it.resx
│ │ │ ├── ExportProductsQueryHandler.km.resx
│ │ │ ├── ExportProductsQueryHandler.nl.resx
│ │ │ └── ExportProductsQueryHandler.ru.resx
│ └── Validators
│ │ ├── Features
│ │ ├── Brands
│ │ │ └── Commands
│ │ │ │ └── AddEdit
│ │ │ │ ├── AddEditBrandCommandValidator.ar.resx
│ │ │ │ ├── AddEditBrandCommandValidator.de.resx
│ │ │ │ ├── AddEditBrandCommandValidator.en.resx
│ │ │ │ ├── AddEditBrandCommandValidator.es.resx
│ │ │ │ ├── AddEditBrandCommandValidator.fr.resx
│ │ │ │ ├── AddEditBrandCommandValidator.id.resx
│ │ │ │ ├── AddEditBrandCommandValidator.it.resx
│ │ │ │ ├── AddEditBrandCommandValidator.km.resx
│ │ │ │ ├── AddEditBrandCommandValidator.nl.resx
│ │ │ │ ├── AddEditBrandCommandValidator.ru.resx
│ │ │ │ └── AddEditBrandCommandValidator.sv.resx
│ │ ├── DocumentTypes
│ │ │ └── Commands
│ │ │ │ └── AddEdit
│ │ │ │ ├── AddEditDocumentTypeCommandValidator.ar.resx
│ │ │ │ ├── AddEditDocumentTypeCommandValidator.de.resx
│ │ │ │ ├── AddEditDocumentTypeCommandValidator.en.resx
│ │ │ │ ├── AddEditDocumentTypeCommandValidator.es.resx
│ │ │ │ ├── AddEditDocumentTypeCommandValidator.fr.resx
│ │ │ │ ├── AddEditDocumentTypeCommandValidator.id.resx
│ │ │ │ ├── AddEditDocumentTypeCommandValidator.it.resx
│ │ │ │ ├── AddEditDocumentTypeCommandValidator.km.resx
│ │ │ │ ├── AddEditDocumentTypeCommandValidator.nl.resx
│ │ │ │ ├── AddEditDocumentTypeCommandValidator.ru.resx
│ │ │ │ └── AddEditDocumentTypeCommandValidator.sv.resx
│ │ ├── Documents
│ │ │ └── Commands
│ │ │ │ └── AddEdit
│ │ │ │ ├── AddEditDocumentCommandValidator.ar.resx
│ │ │ │ ├── AddEditDocumentCommandValidator.de.resx
│ │ │ │ ├── AddEditDocumentCommandValidator.en.resx
│ │ │ │ ├── AddEditDocumentCommandValidator.es.resx
│ │ │ │ ├── AddEditDocumentCommandValidator.fr.resx
│ │ │ │ ├── AddEditDocumentCommandValidator.id.resx
│ │ │ │ ├── AddEditDocumentCommandValidator.it.resx
│ │ │ │ ├── AddEditDocumentCommandValidator.km.resx
│ │ │ │ ├── AddEditDocumentCommandValidator.nl.resx
│ │ │ │ ├── AddEditDocumentCommandValidator.ru.resx
│ │ │ │ └── AddEditDocumentCommandValidator.sv.resx
│ │ ├── ExtendedAttributes
│ │ │ └── Commands
│ │ │ │ └── AddEdit
│ │ │ │ ├── AddEditExtendedAttributeCommandValidatorLocalization.ar.resx
│ │ │ │ ├── AddEditExtendedAttributeCommandValidatorLocalization.de.resx
│ │ │ │ ├── AddEditExtendedAttributeCommandValidatorLocalization.en.resx
│ │ │ │ ├── AddEditExtendedAttributeCommandValidatorLocalization.es.resx
│ │ │ │ ├── AddEditExtendedAttributeCommandValidatorLocalization.fr.resx
│ │ │ │ ├── AddEditExtendedAttributeCommandValidatorLocalization.id.resx
│ │ │ │ ├── AddEditExtendedAttributeCommandValidatorLocalization.it.resx
│ │ │ │ ├── AddEditExtendedAttributeCommandValidatorLocalization.km.resx
│ │ │ │ ├── AddEditExtendedAttributeCommandValidatorLocalization.nl.resx
│ │ │ │ ├── AddEditExtendedAttributeCommandValidatorLocalization.ru.resx
│ │ │ │ └── AddEditExtendedAttributeCommandValidatorLocalization.sv.resx
│ │ └── Products
│ │ │ └── Commands
│ │ │ └── AddEdit
│ │ │ ├── AddEditProductCommandValidator.ar.resx
│ │ │ ├── AddEditProductCommandValidator.de.resx
│ │ │ ├── AddEditProductCommandValidator.en.resx
│ │ │ ├── AddEditProductCommandValidator.es.resx
│ │ │ ├── AddEditProductCommandValidator.fr.resx
│ │ │ ├── AddEditProductCommandValidator.id.resx
│ │ │ ├── AddEditProductCommandValidator.it.resx
│ │ │ ├── AddEditProductCommandValidator.km.resx
│ │ │ ├── AddEditProductCommandValidator.nl.resx
│ │ │ ├── AddEditProductCommandValidator.ru.resx
│ │ │ └── AddEditProductCommandValidator.sv.resx
│ │ └── Requests
│ │ └── Identity
│ │ ├── ChangePasswordRequestValidator.ar.resx
│ │ ├── ChangePasswordRequestValidator.de.resx
│ │ ├── ChangePasswordRequestValidator.en.resx
│ │ ├── ChangePasswordRequestValidator.es.resx
│ │ ├── ChangePasswordRequestValidator.fr.resx
│ │ ├── ChangePasswordRequestValidator.id.resx
│ │ ├── ChangePasswordRequestValidator.it.resx
│ │ ├── ChangePasswordRequestValidator.km.resx
│ │ ├── ChangePasswordRequestValidator.nl.resx
│ │ ├── ChangePasswordRequestValidator.ru.resx
│ │ ├── ChangePasswordRequestValidator.sv.resx
│ │ ├── ForgotPasswordRequestValidator.ar.resx
│ │ ├── ForgotPasswordRequestValidator.de.resx
│ │ ├── ForgotPasswordRequestValidator.en.resx
│ │ ├── ForgotPasswordRequestValidator.es.resx
│ │ ├── ForgotPasswordRequestValidator.fr.resx
│ │ ├── ForgotPasswordRequestValidator.id.resx
│ │ ├── ForgotPasswordRequestValidator.it.resx
│ │ ├── ForgotPasswordRequestValidator.km.resx
│ │ ├── ForgotPasswordRequestValidator.nl.resx
│ │ ├── ForgotPasswordRequestValidator.ru.resx
│ │ ├── ForgotPasswordRequestValidator.sv.resx
│ │ ├── RegisterRequestValidator.ar.resx
│ │ ├── RegisterRequestValidator.de.resx
│ │ ├── RegisterRequestValidator.en.resx
│ │ ├── RegisterRequestValidator.es.resx
│ │ ├── RegisterRequestValidator.fr.resx
│ │ ├── RegisterRequestValidator.id.resx
│ │ ├── RegisterRequestValidator.it.resx
│ │ ├── RegisterRequestValidator.km.resx
│ │ ├── RegisterRequestValidator.nl.resx
│ │ ├── RegisterRequestValidator.ru.resx
│ │ ├── RegisterRequestValidator.sv.resx
│ │ ├── ResetPasswordRequestValidator.ar.resx
│ │ ├── ResetPasswordRequestValidator.de.resx
│ │ ├── ResetPasswordRequestValidator.en.resx
│ │ ├── ResetPasswordRequestValidator.es.resx
│ │ ├── ResetPasswordRequestValidator.fr.resx
│ │ ├── ResetPasswordRequestValidator.id.resx
│ │ ├── ResetPasswordRequestValidator.it.resx
│ │ ├── ResetPasswordRequestValidator.km.resx
│ │ ├── ResetPasswordRequestValidator.nl.resx
│ │ ├── ResetPasswordRequestValidator.ru.resx
│ │ ├── ResetPasswordRequestValidator.sv.resx
│ │ ├── RoleRequestValidator.ar.resx
│ │ ├── RoleRequestValidator.de.resx
│ │ ├── RoleRequestValidator.en.resx
│ │ ├── RoleRequestValidator.es.resx
│ │ ├── RoleRequestValidator.fr.resx
│ │ ├── RoleRequestValidator.id.resx
│ │ ├── RoleRequestValidator.it.resx
│ │ ├── RoleRequestValidator.km.resx
│ │ ├── RoleRequestValidator.nl.resx
│ │ ├── RoleRequestValidator.ru.resx
│ │ ├── RoleRequestValidator.sv.resx
│ │ ├── TokenRequestValidator.ar.resx
│ │ ├── TokenRequestValidator.de.resx
│ │ ├── TokenRequestValidator.en.resx
│ │ ├── TokenRequestValidator.es.resx
│ │ ├── TokenRequestValidator.fr.resx
│ │ ├── TokenRequestValidator.id.resx
│ │ ├── TokenRequestValidator.it.resx
│ │ ├── TokenRequestValidator.km.resx
│ │ ├── TokenRequestValidator.nl.resx
│ │ ├── TokenRequestValidator.ru.resx
│ │ ├── TokenRequestValidator.sv.resx
│ │ ├── UpdateProfileRequestValidator.ar.resx
│ │ ├── UpdateProfileRequestValidator.de.resx
│ │ ├── UpdateProfileRequestValidator.en.resx
│ │ ├── UpdateProfileRequestValidator.es.resx
│ │ ├── UpdateProfileRequestValidator.fr.resx
│ │ ├── UpdateProfileRequestValidator.id.resx
│ │ ├── UpdateProfileRequestValidator.it.resx
│ │ ├── UpdateProfileRequestValidator.km.resx
│ │ ├── UpdateProfileRequestValidator.nl.resx
│ │ ├── UpdateProfileRequestValidator.ru.resx
│ │ └── UpdateProfileRequestValidator.sv.resx
├── Responses
│ ├── Audit
│ │ └── AuditResponse.cs
│ └── Identity
│ │ ├── ChatHistoryResponse.cs
│ │ ├── ChatUserResponse.cs
│ │ ├── GetAllRolesResponse.cs
│ │ ├── GetAllUsersResponse.cs
│ │ ├── PermissionResponse.cs
│ │ ├── RoleClaimResponse.cs
│ │ ├── RoleResponse.cs
│ │ ├── TokenResponse.cs
│ │ ├── UserResponse.cs
│ │ └── UserRolesResponse.cs
├── Serialization
│ ├── JsonConverters
│ │ └── TimespanJsonConverter.cs
│ ├── Options
│ │ └── SystemTextJsonOptions.cs
│ ├── Serializers
│ │ ├── NewtonSoftJsonSerializer.cs
│ │ └── SystemTextJsonSerializer.cs
│ └── Settings
│ │ └── NewtonsoftJsonSettings.cs
├── Specifications
│ ├── Base
│ │ ├── HeroSpecification.cs
│ │ └── ISpecification.cs
│ ├── Catalog
│ │ ├── BrandFilterSpecification.cs
│ │ └── ProductFilterSpecification.cs
│ ├── ExtendedAttribute
│ │ └── ExtendedAttributeFilterSpecification.cs
│ └── Misc
│ │ ├── DocumentFilterSpecification.cs
│ │ └── DocumentTypeFilterSpecification.cs
└── Validators
│ ├── Extensions
│ └── ValidatorExtensions.cs
│ ├── Features
│ ├── Brands
│ │ └── Commands
│ │ │ └── AddEdit
│ │ │ └── AddEditBrandCommandValidator.cs
│ ├── DocumentTypes
│ │ └── Commands
│ │ │ └── AddEdit
│ │ │ └── AddEditDocumentTypeCommandValidator.cs
│ ├── Documents
│ │ └── Commands
│ │ │ └── AddEdit
│ │ │ └── AddEditDocumentCommandValidator.cs
│ ├── ExtendedAttributes
│ │ └── Commands
│ │ │ └── AddEdit
│ │ │ ├── AddEditDocumentExtendedAttributeCommandValidator.cs
│ │ │ └── AddEditExtendedAttributeCommandValidator.cs
│ └── Products
│ │ └── Commands
│ │ └── AddEdit
│ │ └── AddEditProductCommandValidator.cs
│ ├── JsonValidator.cs
│ └── Requests
│ └── Identity
│ ├── ChangePasswordRequestValidator.cs
│ ├── ForgotPasswordRequestValidator.cs
│ ├── RegisterRequestValidator.cs
│ ├── ResetPasswordRequestValidator.cs
│ ├── RoleRequestValidator.cs
│ ├── TokenRequestValidator.cs
│ └── UpdateProfileRequestValidator.cs
├── Client.Infrastructure
├── Authentication
│ ├── AuthenticationHeaderHandler.cs
│ └── BlazorHeroStateProvider.cs
├── Client.Infrastructure.csproj
├── Extensions
│ └── ResultExtensions.cs
├── Managers
│ ├── Audit
│ │ ├── AuditManager.cs
│ │ └── IAuditManager.cs
│ ├── Catalog
│ │ ├── Brand
│ │ │ ├── BrandManager.cs
│ │ │ └── IBrandManager.cs
│ │ └── Product
│ │ │ ├── IProductManager.cs
│ │ │ └── ProductManager.cs
│ ├── Communication
│ │ ├── ChatManager.cs
│ │ └── IChatManager.cs
│ ├── Dashboard
│ │ ├── DashboardManager.cs
│ │ └── IDashboardManager.cs
│ ├── ExtendedAttribute
│ │ ├── ExtendedAttributeManager.cs
│ │ └── IExtendedAttributeManager.cs
│ ├── IManager.cs
│ ├── Identity
│ │ ├── Account
│ │ │ ├── AccountManager.cs
│ │ │ └── IAccountManager.cs
│ │ ├── Authentication
│ │ │ ├── AuthenticationManager.cs
│ │ │ └── IAuthenticationManager.cs
│ │ ├── RoleClaims
│ │ │ ├── IRoleClaimManager.cs
│ │ │ └── RoleClaimManager.cs
│ │ ├── Roles
│ │ │ ├── IRoleManager.cs
│ │ │ └── RoleManager.cs
│ │ └── Users
│ │ │ ├── IUserManager.cs
│ │ │ └── UserManager.cs
│ ├── Interceptors
│ │ ├── HttpInterceptorManager.cs
│ │ └── IHttpInterceptorManager.cs
│ ├── Misc
│ │ ├── Document
│ │ │ ├── DocumentManager.cs
│ │ │ └── IDocumentManager.cs
│ │ └── DocumentType
│ │ │ ├── DocumentTypeManager.cs
│ │ │ └── IDocumentTypeManager.cs
│ └── Preferences
│ │ ├── ClientPreferenceManager.cs
│ │ └── IClientPreferenceManager.cs
├── Mappings
│ └── RolesProfile.cs
├── Resources
│ └── Managers
│ │ ├── Identity
│ │ └── Authentication
│ │ │ ├── AuthenticationManager.ar.resx
│ │ │ ├── AuthenticationManager.en.resx
│ │ │ ├── AuthenticationManager.es.resx
│ │ │ ├── AuthenticationManager.fr.resx
│ │ │ ├── AuthenticationManager.km.resx
│ │ │ ├── AuthenticationManager.nl.resx
│ │ │ └── AuthenticationManager.ru.resx
│ │ ├── Interceptors
│ │ ├── HttpInterceptorManager.ar.resx
│ │ ├── HttpInterceptorManager.en.resx
│ │ ├── HttpInterceptorManager.es.resx
│ │ ├── HttpInterceptorManager.fr.resx
│ │ ├── HttpInterceptorManager.km.resx
│ │ ├── HttpInterceptorManager.nl.resx
│ │ └── HttpInterceptorManager.ru.resx
│ │ └── Preferences
│ │ ├── ClientPreferenceManager.ar.resx
│ │ ├── ClientPreferenceManager.en.resx
│ │ ├── ClientPreferenceManager.es.resx
│ │ ├── ClientPreferenceManager.fr.resx
│ │ ├── ClientPreferenceManager.km.resx
│ │ ├── ClientPreferenceManager.nl.resx
│ │ └── ClientPreferenceManager.ru.resx
├── Routes
│ ├── AccountEndpoints.cs
│ ├── AuditEndpoints.cs
│ ├── BrandsEndpoints.cs
│ ├── ChatEndpoints.cs
│ ├── DashboardEndpoints.cs
│ ├── DocumentTypesEndpoints.cs
│ ├── DocumentsEndpoints.cs
│ ├── ExtendedAttributesEndpoints.cs
│ ├── PreferencesEndpoints.cs
│ ├── ProductsEndpoints.cs
│ ├── RoleClaimsEndpoints.cs
│ ├── RolesEndpoints.cs
│ ├── TokenEndpoints.cs
│ └── UserEndpoints.cs
└── Settings
│ ├── BlazorHeroTheme.cs
│ └── ClientPreference.cs
├── Client
├── App.razor
├── Client.csproj
├── CustomIcons.cs
├── Extensions
│ ├── ClaimsPrincipalExtensions.cs
│ ├── HubExtensions.cs
│ └── WebAssemblyHostBuilderExtensions.cs
├── Models
│ ├── ChatMessage.cs
│ └── ChatUser.cs
├── Pages
│ ├── Authentication
│ │ ├── Login.razor
│ │ ├── Login.razor.cs
│ │ ├── Register.razor
│ │ └── Register.razor.cs
│ ├── Catalog
│ │ ├── AddEditBrandModal.razor
│ │ ├── AddEditBrandModal.razor.cs
│ │ ├── AddEditProductModal.razor
│ │ ├── AddEditProductModal.razor.cs
│ │ ├── Brands.razor
│ │ ├── Brands.razor.cs
│ │ ├── Products.razor
│ │ └── Products.razor.cs
│ ├── Communication
│ │ ├── Chat.razor
│ │ └── Chat.razor.cs
│ ├── Content
│ │ ├── Dashboard.razor
│ │ ├── Dashboard.razor.cs
│ │ └── Home.razor
│ ├── Identity
│ │ ├── Account.razor
│ │ ├── Forgot.razor
│ │ ├── Forgot.razor.cs
│ │ ├── Profile.razor
│ │ ├── Profile.razor.cs
│ │ ├── RegisterUserModal.razor
│ │ ├── RegisterUserModal.razor.cs
│ │ ├── Reset.razor
│ │ ├── Reset.razor.cs
│ │ ├── RoleModal.razor
│ │ ├── RoleModal.razor.cs
│ │ ├── RolePermissions.razor
│ │ ├── RolePermissions.razor.cs
│ │ ├── Roles.razor
│ │ ├── Roles.razor.cs
│ │ ├── Security.razor
│ │ ├── Security.razor.cs
│ │ ├── UserProfile.razor
│ │ ├── UserProfile.razor.cs
│ │ ├── UserRoles.razor
│ │ ├── UserRoles.razor.cs
│ │ ├── Users.razor
│ │ └── Users.razor.cs
│ ├── Misc
│ │ ├── AddEditDocumentModal.razor
│ │ ├── AddEditDocumentModal.razor.cs
│ │ ├── AddEditDocumentTypeModal.razor
│ │ ├── AddEditDocumentTypeModal.razor.cs
│ │ ├── DocumentStore.razor
│ │ ├── DocumentStore.razor.cs
│ │ ├── DocumentTypes.razor
│ │ ├── DocumentTypes.razor.cs
│ │ └── ExtendedAttribute
│ │ │ └── DocumentExtendedAttributes.razor
│ └── Utilities
│ │ ├── AuditTrails.razor
│ │ └── AuditTrails.razor.cs
├── Program.cs
├── Properties
│ └── launchSettings.json
├── Resources
│ ├── Pages
│ │ ├── Account
│ │ │ ├── Forgot.ar.resx
│ │ │ ├── Forgot.de.resx
│ │ │ ├── Forgot.en.resx
│ │ │ ├── Forgot.es.resx
│ │ │ ├── Forgot.fr.resx
│ │ │ ├── Forgot.id.resx
│ │ │ ├── Forgot.it.resx
│ │ │ ├── Forgot.km.resx
│ │ │ ├── Forgot.nl.resx
│ │ │ ├── Forgot.ru.resx
│ │ │ ├── Forgot.sv.resx
│ │ │ ├── Register.ar.resx
│ │ │ ├── Register.de.resx
│ │ │ ├── Register.en.resx
│ │ │ ├── Register.es.resx
│ │ │ ├── Register.fr.resx
│ │ │ ├── Register.id.resx
│ │ │ ├── Register.it.resx
│ │ │ ├── Register.km.resx
│ │ │ ├── Register.nl.resx
│ │ │ ├── Register.ru.resx
│ │ │ ├── Register.sv.resx
│ │ │ ├── Reset.ar.resx
│ │ │ ├── Reset.de.resx
│ │ │ ├── Reset.en.resx
│ │ │ ├── Reset.es.resx
│ │ │ ├── Reset.fr.resx
│ │ │ ├── Reset.id.resx
│ │ │ ├── Reset.it.resx
│ │ │ ├── Reset.km.resx
│ │ │ ├── Reset.nl.resx
│ │ │ ├── Reset.ru.resx
│ │ │ └── Reset.sv.resx
│ │ ├── Authentication
│ │ │ ├── Login.ar.resx
│ │ │ ├── Login.de.resx
│ │ │ ├── Login.en.resx
│ │ │ ├── Login.es.resx
│ │ │ ├── Login.fr.resx
│ │ │ ├── Login.id.resx
│ │ │ ├── Login.it.resx
│ │ │ ├── Login.km.resx
│ │ │ ├── Login.nl.resx
│ │ │ ├── Login.ru.resx
│ │ │ ├── Login.sv.resx
│ │ │ ├── Register.ar.resx
│ │ │ ├── Register.en.resx
│ │ │ ├── Register.es.resx
│ │ │ ├── Register.fr.resx
│ │ │ ├── Register.id.resx
│ │ │ ├── Register.it.resx
│ │ │ ├── Register.km.resx
│ │ │ ├── Register.nl.resx
│ │ │ ├── Register.ru.resx
│ │ │ └── Register.sv.resx
│ │ ├── Catalog
│ │ │ ├── AddEditBrandModal.ar.resx
│ │ │ ├── AddEditBrandModal.en.resx
│ │ │ ├── AddEditBrandModal.es.resx
│ │ │ ├── AddEditBrandModal.fr.resx
│ │ │ ├── AddEditBrandModal.id.resx
│ │ │ ├── AddEditBrandModal.it.resx
│ │ │ ├── AddEditBrandModal.km.resx
│ │ │ ├── AddEditBrandModal.nl.resx
│ │ │ ├── AddEditBrandModal.ru.resx
│ │ │ ├── AddEditProductModal.ar.resx
│ │ │ ├── AddEditProductModal.de.resx
│ │ │ ├── AddEditProductModal.en.resx
│ │ │ ├── AddEditProductModal.es.resx
│ │ │ ├── AddEditProductModal.fr.resx
│ │ │ ├── AddEditProductModal.id.resx
│ │ │ ├── AddEditProductModal.it.resx
│ │ │ ├── AddEditProductModal.km.resx
│ │ │ ├── AddEditProductModal.nl.resx
│ │ │ ├── AddEditProductModal.ru.resx
│ │ │ ├── AddEditProductModal.sv.resx
│ │ │ ├── Brands.ar.resx
│ │ │ ├── Brands.de.resx
│ │ │ ├── Brands.en.resx
│ │ │ ├── Brands.es.resx
│ │ │ ├── Brands.fr.resx
│ │ │ ├── Brands.id.resx
│ │ │ ├── Brands.it.resx
│ │ │ ├── Brands.km.resx
│ │ │ ├── Brands.nl.resx
│ │ │ ├── Brands.ru.resx
│ │ │ ├── Brands.sv.resx
│ │ │ ├── Products.ar.resx
│ │ │ ├── Products.de.resx
│ │ │ ├── Products.en.resx
│ │ │ ├── Products.es.resx
│ │ │ ├── Products.fr.resx
│ │ │ ├── Products.id.resx
│ │ │ ├── Products.it.resx
│ │ │ ├── Products.km.resx
│ │ │ ├── Products.nl.resx
│ │ │ ├── Products.ru.resx
│ │ │ └── Products.sv.resx
│ │ ├── Communication
│ │ │ ├── Chat.ar.resx
│ │ │ ├── Chat.en.resx
│ │ │ ├── Chat.es.resx
│ │ │ ├── Chat.fr.resx
│ │ │ ├── Chat.id.resx
│ │ │ ├── Chat.it.resx
│ │ │ ├── Chat.km.resx
│ │ │ ├── Chat.nl.resx
│ │ │ ├── Chat.ru.resx
│ │ │ └── Chat.sv.resx
│ │ ├── Content
│ │ │ ├── Dashboard.ar.resx
│ │ │ ├── Dashboard.en.resx
│ │ │ ├── Dashboard.es.resx
│ │ │ ├── Dashboard.fr.resx
│ │ │ ├── Dashboard.id.resx
│ │ │ ├── Dashboard.it.resx
│ │ │ ├── Dashboard.km.resx
│ │ │ ├── Dashboard.nl.resx
│ │ │ ├── Dashboard.ru.resx
│ │ │ ├── Dashboard.sv.resx
│ │ │ ├── Home.ar.resx
│ │ │ ├── Home.de.resx
│ │ │ ├── Home.en.resx
│ │ │ ├── Home.es.resx
│ │ │ ├── Home.fr.resx
│ │ │ ├── Home.id.resx
│ │ │ ├── Home.it.resx
│ │ │ ├── Home.km.resx
│ │ │ ├── Home.nl.resx
│ │ │ ├── Home.ru.resx
│ │ │ ├── Home.sv.resx
│ │ │ ├── Resources.ar.resx
│ │ │ ├── Resources.de.resx
│ │ │ ├── Resources.en.resx
│ │ │ ├── Resources.es.resx
│ │ │ ├── Resources.fr.resx
│ │ │ ├── Resources.id.resx
│ │ │ ├── Resources.it.resx
│ │ │ ├── Resources.km.resx
│ │ │ ├── Resources.nl.resx
│ │ │ ├── Resources.ru.resx
│ │ │ └── Resources.sv.resx
│ │ ├── Identity
│ │ │ ├── Account.ar.resx
│ │ │ ├── Account.de.resx
│ │ │ ├── Account.en.resx
│ │ │ ├── Account.es.resx
│ │ │ ├── Account.fr.resx
│ │ │ ├── Account.id.resx
│ │ │ ├── Account.it.resx
│ │ │ ├── Account.km.resx
│ │ │ ├── Account.nl.resx
│ │ │ ├── Account.ru.resx
│ │ │ ├── Account.sv.resx
│ │ │ ├── Forgot.ar.resx
│ │ │ ├── Forgot.en.resx
│ │ │ ├── Forgot.es.resx
│ │ │ ├── Forgot.fr.resx
│ │ │ ├── Forgot.id.resx
│ │ │ ├── Forgot.it.resx
│ │ │ ├── Forgot.km.resx
│ │ │ ├── Forgot.nl.resx
│ │ │ ├── Forgot.ru.resx
│ │ │ ├── Forgot.sv.resx
│ │ │ ├── Profile.ar.resx
│ │ │ ├── Profile.de.resx
│ │ │ ├── Profile.en.resx
│ │ │ ├── Profile.es.resx
│ │ │ ├── Profile.fr.resx
│ │ │ ├── Profile.id.resx
│ │ │ ├── Profile.it.resx
│ │ │ ├── Profile.km.resx
│ │ │ ├── Profile.nl.resx
│ │ │ ├── Profile.ru.resx
│ │ │ ├── Profile.sv.resx
│ │ │ ├── RegisterUserModal.ar.resx
│ │ │ ├── RegisterUserModal.de.resx
│ │ │ ├── RegisterUserModal.en.resx
│ │ │ ├── RegisterUserModal.es.resx
│ │ │ ├── RegisterUserModal.fr.resx
│ │ │ ├── RegisterUserModal.id.resx
│ │ │ ├── RegisterUserModal.it.resx
│ │ │ ├── RegisterUserModal.km.resx
│ │ │ ├── RegisterUserModal.nl.resx
│ │ │ ├── RegisterUserModal.ru.resx
│ │ │ ├── RegisterUserModal.sv.resx
│ │ │ ├── Reset.ar.resx
│ │ │ ├── Reset.de.resx
│ │ │ ├── Reset.en.resx
│ │ │ ├── Reset.es.resx
│ │ │ ├── Reset.fr.resx
│ │ │ ├── Reset.id.resx
│ │ │ ├── Reset.it.resx
│ │ │ ├── Reset.km.resx
│ │ │ ├── Reset.nl.resx
│ │ │ ├── Reset.ru.resx
│ │ │ ├── Reset.sv.resx
│ │ │ ├── RoleModal.ar.resx
│ │ │ ├── RoleModal.de.resx
│ │ │ ├── RoleModal.en.resx
│ │ │ ├── RoleModal.es.resx
│ │ │ ├── RoleModal.fr.resx
│ │ │ ├── RoleModal.id.resx
│ │ │ ├── RoleModal.it.resx
│ │ │ ├── RoleModal.km.resx
│ │ │ ├── RoleModal.nl.resx
│ │ │ ├── RoleModal.ru.resx
│ │ │ ├── RoleModal.sv.resx
│ │ │ ├── RolePermissions.ar.resx
│ │ │ ├── RolePermissions.en.resx
│ │ │ ├── RolePermissions.es.resx
│ │ │ ├── RolePermissions.fr.resx
│ │ │ ├── RolePermissions.id.resx
│ │ │ ├── RolePermissions.it.resx
│ │ │ ├── RolePermissions.km.resx
│ │ │ ├── RolePermissions.nl.resx
│ │ │ ├── RolePermissions.ru.resx
│ │ │ ├── RolePermissions.sv.resx
│ │ │ ├── Roles.ar.resx
│ │ │ ├── Roles.de.resx
│ │ │ ├── Roles.en.resx
│ │ │ ├── Roles.es.resx
│ │ │ ├── Roles.fr.resx
│ │ │ ├── Roles.id.resx
│ │ │ ├── Roles.it.resx
│ │ │ ├── Roles.km.resx
│ │ │ ├── Roles.nl.resx
│ │ │ ├── Roles.ru.resx
│ │ │ ├── Roles.sv.resx
│ │ │ ├── Security.ar.resx
│ │ │ ├── Security.de.resx
│ │ │ ├── Security.en.resx
│ │ │ ├── Security.es.resx
│ │ │ ├── Security.fr.resx
│ │ │ ├── Security.id.resx
│ │ │ ├── Security.it.resx
│ │ │ ├── Security.km.resx
│ │ │ ├── Security.nl.resx
│ │ │ ├── Security.ru.resx
│ │ │ ├── Security.sv.resx
│ │ │ ├── UserProfile.ar.resx
│ │ │ ├── UserProfile.de.resx
│ │ │ ├── UserProfile.en.resx
│ │ │ ├── UserProfile.es.resx
│ │ │ ├── UserProfile.fr.resx
│ │ │ ├── UserProfile.id.resx
│ │ │ ├── UserProfile.it.resx
│ │ │ ├── UserProfile.km.resx
│ │ │ ├── UserProfile.nl.resx
│ │ │ ├── UserProfile.ru.resx
│ │ │ ├── UserProfile.sv.resx
│ │ │ ├── UserRoles.ar.resx
│ │ │ ├── UserRoles.de.resx
│ │ │ ├── UserRoles.en.resx
│ │ │ ├── UserRoles.es.resx
│ │ │ ├── UserRoles.fr.resx
│ │ │ ├── UserRoles.id.resx
│ │ │ ├── UserRoles.it.resx
│ │ │ ├── UserRoles.km.resx
│ │ │ ├── UserRoles.nl.resx
│ │ │ ├── UserRoles.ru.resx
│ │ │ ├── UserRoles.sv.resx
│ │ │ ├── Users.ar.resx
│ │ │ ├── Users.de.resx
│ │ │ ├── Users.en.resx
│ │ │ ├── Users.es.resx
│ │ │ ├── Users.fr.resx
│ │ │ ├── Users.id.resx
│ │ │ ├── Users.it.resx
│ │ │ ├── Users.km.resx
│ │ │ ├── Users.nl.resx
│ │ │ ├── Users.ru.resx
│ │ │ └── Users.sv.resx
│ │ ├── Misc
│ │ │ ├── AddEditDocumentModal.ar.resx
│ │ │ ├── AddEditDocumentModal.en.resx
│ │ │ ├── AddEditDocumentModal.es.resx
│ │ │ ├── AddEditDocumentModal.fr.resx
│ │ │ ├── AddEditDocumentModal.id.resx
│ │ │ ├── AddEditDocumentModal.it.resx
│ │ │ ├── AddEditDocumentModal.km.resx
│ │ │ ├── AddEditDocumentModal.nl.resx
│ │ │ ├── AddEditDocumentModal.ru.resx
│ │ │ ├── AddEditDocumentModal.sv.resx
│ │ │ ├── AddEditDocumentTypeModal.ar.resx
│ │ │ ├── AddEditDocumentTypeModal.en.resx
│ │ │ ├── AddEditDocumentTypeModal.es.resx
│ │ │ ├── AddEditDocumentTypeModal.fr.resx
│ │ │ ├── AddEditDocumentTypeModal.km.resx
│ │ │ ├── AddEditDocumentTypeModal.nl.resx
│ │ │ ├── AddEditDocumentTypeModal.ru.resx
│ │ │ ├── DocumentStore.ar.resx
│ │ │ ├── DocumentStore.en.resx
│ │ │ ├── DocumentStore.es.resx
│ │ │ ├── DocumentStore.fr.resx
│ │ │ ├── DocumentStore.id.resx
│ │ │ ├── DocumentStore.it.resx
│ │ │ ├── DocumentStore.km.resx
│ │ │ ├── DocumentStore.nl.resx
│ │ │ ├── DocumentStore.ru.resx
│ │ │ ├── DocumentStore.sv.resx
│ │ │ ├── DocumentTypes.ar.resx
│ │ │ ├── DocumentTypes.en.resx
│ │ │ ├── DocumentTypes.es.resx
│ │ │ ├── DocumentTypes.fr.resx
│ │ │ ├── DocumentTypes.km.resx
│ │ │ ├── DocumentTypes.nl.resx
│ │ │ └── DocumentTypes.ru.resx
│ │ └── Utilities
│ │ │ ├── AuditTrails.ar.resx
│ │ │ ├── AuditTrails.en.resx
│ │ │ ├── AuditTrails.es.resx
│ │ │ ├── AuditTrails.fr.resx
│ │ │ ├── AuditTrails.it.resx
│ │ │ ├── AuditTrails.km.resx
│ │ │ ├── AuditTrails.nl.resx
│ │ │ ├── AuditTrails.ru.resx
│ │ │ └── AuditTrails.sv.resx
│ └── Shared
│ │ ├── Components
│ │ ├── AddEditExtendedAttributeModalLocalization.ar.resx
│ │ ├── AddEditExtendedAttributeModalLocalization.de.resx
│ │ ├── AddEditExtendedAttributeModalLocalization.en.resx
│ │ ├── AddEditExtendedAttributeModalLocalization.es.resx
│ │ ├── AddEditExtendedAttributeModalLocalization.fr.resx
│ │ ├── AddEditExtendedAttributeModalLocalization.id.resx
│ │ ├── AddEditExtendedAttributeModalLocalization.it.resx
│ │ ├── AddEditExtendedAttributeModalLocalization.km.resx
│ │ ├── AddEditExtendedAttributeModalLocalization.nl.resx
│ │ ├── AddEditExtendedAttributeModalLocalization.ru.resx
│ │ ├── AddEditExtendedAttributeModalLocalization.sv.resx
│ │ ├── ExtendedAttributesLocalization.ar.resx
│ │ ├── ExtendedAttributesLocalization.de.resx
│ │ ├── ExtendedAttributesLocalization.en.resx
│ │ ├── ExtendedAttributesLocalization.es.resx
│ │ ├── ExtendedAttributesLocalization.fr.resx
│ │ ├── ExtendedAttributesLocalization.id.resx
│ │ ├── ExtendedAttributesLocalization.it.resx
│ │ ├── ExtendedAttributesLocalization.km.resx
│ │ ├── ExtendedAttributesLocalization.nl.resx
│ │ ├── ExtendedAttributesLocalization.ru.resx
│ │ ├── ExtendedAttributesLocalization.sv.resx
│ │ ├── ImportExcelModal.ar.resx
│ │ ├── ImportExcelModal.de.resx
│ │ ├── ImportExcelModal.en.resx
│ │ ├── ImportExcelModal.es.resx
│ │ ├── ImportExcelModal.fr.resx
│ │ ├── ImportExcelModal.id.resx
│ │ ├── ImportExcelModal.it.resx
│ │ ├── ImportExcelModal.km.resx
│ │ ├── ImportExcelModal.nl.resx
│ │ ├── ImportExcelModal.ru.resx
│ │ ├── ImportExcelModal.sv.resx
│ │ ├── LanguageSelector.ar.resx
│ │ ├── LanguageSelector.de.resx
│ │ ├── LanguageSelector.en.resx
│ │ ├── LanguageSelector.es.resx
│ │ ├── LanguageSelector.fr.resx
│ │ ├── LanguageSelector.id.resx
│ │ ├── LanguageSelector.it.resx
│ │ ├── LanguageSelector.nl.resx
│ │ ├── LanguageSelector.ru.resx
│ │ ├── TablePager.ar.resx
│ │ ├── TablePager.en.resx
│ │ ├── TablePager.es.resx
│ │ ├── TablePager.fr.resx
│ │ ├── TablePager.id.resx
│ │ ├── TablePager.it.resx
│ │ ├── TablePager.km.resx
│ │ ├── TablePager.nl.resx
│ │ ├── TablePager.ru.resx
│ │ └── TablePager.sv.resx
│ │ ├── Dialogs
│ │ ├── DeleteConfirmation.en.resx
│ │ ├── DeleteConfirmation.es.resx
│ │ ├── DeleteConfirmation.fr.resx
│ │ ├── DeleteConfirmation.id.resx
│ │ ├── DeleteConfirmation.it.resx
│ │ ├── DeleteConfirmation.km.resx
│ │ ├── DeleteConfirmation.nl.resx
│ │ ├── DeleteConfirmation.ru.resx
│ │ ├── DeleteConfirmation.sv.resx
│ │ ├── Logout.en.resx
│ │ ├── Logout.es.resx
│ │ ├── Logout.fr.resx
│ │ ├── Logout.id.resx
│ │ ├── Logout.it.resx
│ │ ├── Logout.km.resx
│ │ ├── Logout.nl.resx
│ │ ├── Logout.ru.resx
│ │ ├── Logout.sv.resx
│ │ ├── DeleteConfirmation.ar.resx
│ │ └── Logout.ar.resx
│ │ ├── MainLayout.en.resx
│ │ ├── MainLayout.es.resx
│ │ ├── MainLayout.fr.resx
│ │ ├── MainLayout.id.resx
│ │ ├── MainLayout.it.resx
│ │ ├── MainLayout.km.resx
│ │ ├── MainLayout.nl.resx
│ │ ├── MainLayout.ru.resx
│ │ ├── MainLayout.sv.resx
│ │ ├── NavMenu.de.resx
│ │ ├── NavMenu.en.resx
│ │ ├── NavMenu.es.resx
│ │ ├── NavMenu.fr.resx
│ │ ├── NavMenu.id.resx
│ │ ├── NavMenu.it.resx
│ │ ├── NavMenu.km.resx
│ │ ├── NavMenu.nl.resx
│ │ ├── NavMenu.ru.resx
│ │ ├── NavMenu.sv.resx
│ │ ├── NotFoundLayout.de.resx
│ │ ├── NotFoundLayout.en.resx
│ │ ├── NotFoundLayout.es.resx
│ │ ├── NotFoundLayout.fr.resx
│ │ ├── NotFoundLayout.id.resx
│ │ ├── NotFoundLayout.it.resx
│ │ ├── NotFoundLayout.km.resx
│ │ ├── NotFoundLayout.nl.resx
│ │ ├── NotFoundLayout.ru.resx
│ │ ├── NotFoundLayout.sv.resx
│ │ ├── MainLayout.ar.resx
│ │ ├── NavMenu.ar.resx
│ │ └── NotFoundLayout.ar.resx
├── Shared
│ ├── Components
│ │ ├── AddEditExtendedAttributeModal.razor
│ │ ├── AddEditExtendedAttributeModal.razor.cs
│ │ ├── BlazorHeroLogo.razor
│ │ ├── ExtendedAttributes.razor
│ │ ├── ExtendedAttributes.razor.cs
│ │ ├── ExtendedAttributesBase.razor
│ │ ├── ExtendedAttributesBase.razor.cs
│ │ ├── HeroTitle.razor
│ │ ├── ImportExcelModal.razor
│ │ ├── ImportExcelModal.razor.cs
│ │ ├── LanguageSelector.razor
│ │ ├── TablePager.razor
│ │ ├── UserCard.razor
│ │ └── UserCard.razor.cs
│ ├── Dialogs
│ │ ├── DeleteConfirmation.razor
│ │ └── Logout.razor
│ ├── Error.razor
│ ├── MainBody.razor
│ ├── MainBody.razor.cs
│ ├── MainLayout.razor
│ ├── MainLayout.razor.cs
│ ├── NavMenu.razor
│ └── NotFoundLayout.razor
├── _Imports.razor
└── wwwroot
│ ├── css
│ └── loader.css
│ ├── favicon.ico
│ ├── index.html
│ ├── js
│ ├── file.js
│ ├── scroll.js
│ └── sounds.js
│ └── media
│ └── notification.mp3
├── Domain
├── Contracts
│ ├── AuditableEntity.cs
│ ├── AuditableEntityExtendedAttribute.cs
│ ├── AuditableEntityWithExtendedAttributes.cs
│ ├── IAuditableEntity.cs
│ ├── IEntity.cs
│ ├── IEntityAuditableExtendedAttribute.cs
│ ├── IEntityExtendedAttribute.cs
│ └── IEntityWithExtendedAttributes.cs
├── Domain.csproj
├── Entities
│ ├── Catalog
│ │ ├── Brand.cs
│ │ └── Product.cs
│ ├── ExtendedAttributes
│ │ └── DocumentExtendedAttribute.cs
│ └── Misc
│ │ ├── Document.cs
│ │ └── DocumentType.cs
└── Enums
│ └── EntityExtendedAttributeType.cs
├── Infrastructure.Shared
├── Infrastructure.Shared.csproj
└── Services
│ ├── SMTPMailService.cs
│ ├── SendGridMailService.cs
│ └── SystemDateTimeService.cs
├── Infrastructure
├── Configurations
│ └── EntityExtendedAttributeConfiguration.cs
├── Contexts
│ ├── AuditableContext.cs
│ └── BlazorHeroContext.cs
├── DatabaseSeeder.cs
├── Extensions
│ ├── ServiceCollectionExtensions.cs
│ └── ValueConversionExtensions.cs
├── Helpers
│ └── ClaimExtensions.cs
├── Infrastructure.csproj
├── Mappings
│ ├── AuditProfile.cs
│ ├── ChatHistoryProfile.cs
│ ├── RoleClaimProfile.cs
│ ├── RoleProfile.cs
│ └── UserProfile.cs
├── Migrations
│ ├── 20210413122110_initial.Designer.cs
│ ├── 20210413122110_initial.cs
│ ├── 20210526094834_AddBlazorHeroRole.Designer.cs
│ ├── 20210526094834_AddBlazorHeroRole.cs
│ ├── 20210528104232_AddBlazorHeroRoleClaim.Designer.cs
│ ├── 20210528104232_AddBlazorHeroRoleClaim.cs
│ ├── 20210613102039_AddDocumentTypeAndExtendedAttribute.Designer.cs
│ ├── 20210613102039_AddDocumentTypeAndExtendedAttribute.cs
│ └── BlazorHeroContextModelSnapshot.cs
├── Models
│ ├── Audit
│ │ ├── Audit.cs
│ │ └── AuditEntry.cs
│ └── Identity
│ │ ├── BlazorHeroRole.cs
│ │ ├── BlazorHeroRoleClaim.cs
│ │ └── BlazorHeroUser.cs
├── Repositories
│ ├── BrandRepository.cs
│ ├── DocumentRepository.cs
│ ├── DocumentTypeRepository.cs
│ ├── ExtendedAttributeUnitOfWork.cs
│ ├── ProductRepository.cs
│ ├── RepositoryAsync.cs
│ └── UnitOfWork.cs
├── Resources
│ ├── DatabaseSeeder.en.resx
│ ├── DatabaseSeeder.es.resx
│ ├── DatabaseSeeder.fr.resx
│ ├── DatabaseSeeder.it.resx
│ ├── DatabaseSeeder.km.resx
│ ├── DatabaseSeeder.nl.resx
│ ├── DatabaseSeeder.ru.resx
│ ├── Services
│ │ ├── AuditService.en.resx
│ │ ├── AuditService.es.resx
│ │ ├── AuditService.fr.resx
│ │ ├── AuditService.it.resx
│ │ ├── AuditService.km.resx
│ │ ├── AuditService.nl.resx
│ │ ├── AuditService.ru.resx
│ │ ├── ChatService.en.resx
│ │ ├── ChatService.es.resx
│ │ ├── ChatService.fr.resx
│ │ ├── ChatService.it.resx
│ │ ├── ChatService.km.resx
│ │ ├── ChatService.nl.resx
│ │ ├── ChatService.ru.resx
│ │ ├── ExcelService.en.resx
│ │ ├── ExcelService.es.resx
│ │ ├── ExcelService.fr.resx
│ │ ├── ExcelService.it.resx
│ │ ├── ExcelService.km.resx
│ │ ├── ExcelService.nl.resx
│ │ ├── ExcelService.ru.resx
│ │ ├── Identity
│ │ │ ├── AccountService.en.resx
│ │ │ ├── AccountService.es.resx
│ │ │ ├── AccountService.fr.resx
│ │ │ ├── AccountService.it.resx
│ │ │ ├── AccountService.km.resx
│ │ │ ├── AccountService.nl.resx
│ │ │ ├── AccountService.ru.resx
│ │ │ ├── IdentityService.en.resx
│ │ │ ├── IdentityService.es.resx
│ │ │ ├── IdentityService.fr.resx
│ │ │ ├── IdentityService.it.resx
│ │ │ ├── IdentityService.km.resx
│ │ │ ├── IdentityService.nl.resx
│ │ │ ├── IdentityService.ru.resx
│ │ │ ├── RoleClaimService.de.resx
│ │ │ ├── RoleClaimService.en.resx
│ │ │ ├── RoleClaimService.es.resx
│ │ │ ├── RoleClaimService.fr.resx
│ │ │ ├── RoleClaimService.id.resx
│ │ │ ├── RoleClaimService.it.resx
│ │ │ ├── RoleClaimService.km.resx
│ │ │ ├── RoleClaimService.nl.resx
│ │ │ ├── RoleClaimService.ru.resx
│ │ │ ├── RoleClaimService.sv.resx
│ │ │ ├── RoleService.en.resx
│ │ │ ├── RoleService.es.resx
│ │ │ ├── RoleService.fr.resx
│ │ │ ├── RoleService.it.resx
│ │ │ ├── RoleService.km.resx
│ │ │ ├── RoleService.nl.resx
│ │ │ ├── RoleService.ru.resx
│ │ │ ├── UserService.en.resx
│ │ │ ├── UserService.es.resx
│ │ │ ├── UserService.fr.resx
│ │ │ ├── UserService.it.resx
│ │ │ ├── UserService.km.resx
│ │ │ ├── UserService.nl.resx
│ │ │ ├── UserService.ru.resx
│ │ │ ├── AccountService.ar.resx
│ │ │ ├── IdentityService.ar.resx
│ │ │ ├── RoleClaimService.ar.resx
│ │ │ ├── RoleService.ar.resx
│ │ │ └── UserService.ar.resx
│ │ ├── AuditService.ar.resx
│ │ ├── ChatService.ar.resx
│ │ └── ExcelService.ar.resx
│ └── DatabaseSeeder.ar.resx
├── Services
│ ├── AuditService.cs
│ ├── ChatService.cs
│ ├── ExcelService.cs
│ ├── Identity
│ │ ├── AccountService.cs
│ │ ├── IdentityService.cs
│ │ ├── RoleClaimService.cs
│ │ ├── RoleService.cs
│ │ └── UserService.cs
│ ├── Storage
│ │ ├── Provider
│ │ │ └── ServerStorageProvider.cs
│ │ └── ServerStorageService.cs
│ └── UploadService.cs
└── Specifications
│ ├── AuditFilterSpecification.cs
│ └── UserFilterSpecification.cs
├── Server
├── Controllers
│ ├── BaseApiController.cs
│ ├── Communication
│ │ └── ChatsController.cs
│ ├── Identity
│ │ ├── AccountController.cs
│ │ ├── RoleClaimController.cs
│ │ ├── RoleController.cs
│ │ ├── TokenController.cs
│ │ └── UserController.cs
│ ├── Utilities
│ │ ├── AuditsController.cs
│ │ ├── ExtendedAttributes
│ │ │ ├── Base
│ │ │ │ └── ExtendedAttributesController.cs
│ │ │ └── Misc
│ │ │ │ └── DocumentExtendedAttributesController.cs
│ │ ├── Misc
│ │ │ ├── DocumentTypesController.cs
│ │ │ └── DocumentsController.cs
│ │ └── PreferencesController.cs
│ └── v1
│ │ ├── Catalog
│ │ ├── BrandsController.cs
│ │ └── ProductsController.cs
│ │ └── DashboardController.cs
├── Dockerfile
├── Extensions
│ ├── ApplicationBuilderExtensions.cs
│ ├── HostBuilderExtensions.cs
│ ├── MvcBuilderExtensions.cs
│ └── ServiceCollectionExtensions.cs
├── Files
│ └── Images
│ │ └── Products
│ │ └── demo.jpg
├── Filters
│ └── HangfireAuthorizationFilter.cs
├── Hubs
│ └── SignalRHub.cs
├── Localization
│ ├── ServerCommonResources.cs
│ └── ServerLocalizer.cs
├── Managers
│ └── Preferences
│ │ ├── IServerPreferenceManager.cs
│ │ └── ServerPreferenceManager.cs
├── Middlewares
│ ├── ErrorHandlerMiddleware.cs
│ └── RequestCultureMiddleware.cs
├── Program.cs
├── Properties
│ └── launchSettings.json
├── Resources
│ ├── Localization
│ │ ├── ServerCommonResources.en.resx
│ │ ├── ServerCommonResources.es.resx
│ │ ├── ServerCommonResources.fr.resx
│ │ ├── ServerCommonResources.it.resx
│ │ ├── ServerCommonResources.km.resx
│ │ ├── ServerCommonResources.nl.resx
│ │ ├── ServerCommonResources.ru.resx
│ │ └── ServerCommonResources.ar.resx
│ ├── Managers
│ │ ├── Preferences
│ │ │ ├── ServerPreferenceManager.en.resx
│ │ │ ├── ServerPreferenceManager.es.resx
│ │ │ ├── ServerPreferenceManager.fr.resx
│ │ │ ├── ServerPreferenceManager.it.resx
│ │ │ ├── ServerPreferenceManager.km.resx
│ │ │ ├── ServerPreferenceManager.nl.resx
│ │ │ ├── ServerPreferenceManager.ru.resx
│ │ │ └── ServerPreferenceManager.ar.resx
│ │ ├── Startup.en.resx
│ │ ├── Startup.es.resx
│ │ ├── Startup.fr.resx
│ │ ├── Startup.it.resx
│ │ ├── Startup.nl.resx
│ │ └── Startup.ar.resx
│ ├── Startup.en.resx
│ ├── Startup.es.resx
│ ├── Startup.fr.resx
│ ├── Startup.it.resx
│ ├── Startup.km.resx
│ ├── Startup.nl.resx
│ ├── Startup.ru.resx
│ └── Startup.ar.resx
├── Server.csproj
├── Services
│ └── CurrentUserService.cs
├── Settings
│ └── ServerPreference.cs
├── Startup.cs
├── appsettings.Development.json
└── appsettings.json
└── Shared
├── Constants
├── Application
│ └── ApplicationConstants.cs
├── Localization
│ ├── LanguageCode.cs
│ └── LocalizationConstants.cs
├── Permission
│ ├── ApplicationClaimType.cs
│ └── Permissions.cs
├── Role
│ └── RoleConstants.cs
├── Storage
│ └── StorageConstants.cs
└── User
│ └── UserConstants.cs
├── Managers
└── IPreferenceManager.cs
├── Models
└── User.cs
├── Settings
└── IPreference.cs
├── Shared.csproj
└── Wrapper
├── IResult.cs
├── PaginatedResult.cs
└── Result.cs
/.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
--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | custom: ['https://www.buymeacoffee.com/codewithmukesh']
4 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/documenation-request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Documenation Request
3 | about: Create a report to help us improve.
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe your documentation need**
11 | A clear and concise description of what the request is.
12 |
13 | **Requirement**
14 |
15 | 1. Documentation Title
16 | 2. What you need to achieve?
17 | 3. Current Blockers? etc
18 |
19 | **Expected behavior**
20 | A clear and concise description of what you expect.
21 |
22 | **Screenshots**
23 | If applicable, add screenshots to help explain your problem.
24 |
25 | **Desktop (please complete the following information):**
26 | - OS: [e.g. iOS]
27 | - Browser [e.g. chrome, safari]
28 | - Version [e.g. 22]
29 |
30 | **Smartphone (please complete the following information):**
31 | - Device: [e.g. iPhone6]
32 | - OS: [e.g. iOS8.1]
33 | - Browser [e.g. stock browser, safari]
34 | - Version [e.g. 22]
35 |
36 | **Additional context**
37 | Add any other context about the problem here.
38 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/dotnet.yml:
--------------------------------------------------------------------------------
1 | name: .NET
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 |
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v2
16 | - name: Setup .NET
17 | uses: actions/setup-dotnet@v1
18 | with:
19 | dotnet-version: 6.0.x
20 | - name: Restore dependencies
21 | run: dotnet restore
22 | working-directory: src/Server
23 | - name: Build
24 | run: dotnet build --no-restore
25 | working-directory: src/Server
26 |
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "0.2.0",
3 | "configurations": [
4 | {
5 | "name": "Launch and Debug Standalone Blazor WebAssembly App",
6 | "type": "blazorwasm",
7 | "request": "launch",
8 | "cwd": "${workspaceFolder}/src/Server"
9 | }
10 | ]
11 | }
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=733558
3 | // for the documentation about the tasks.json format
4 | "version": "2.0.0",
5 | "tasks": [
6 | {
7 | "label": "build",
8 | "command": "dotnet",
9 | "type": "shell",
10 | "args": [
11 | "build",
12 | "${workspaceFolder}/BlazorHero.CleanArchitecture.sln",
13 | // Ask dotnet build to generate full paths for file names.
14 | "/property:GenerateFullPaths=true",
15 | // Do not generate summary otherwise it leads to duplicate errors in Problems panel
16 | "/consoleloggerparameters:NoSummary"
17 | ],
18 | "group": "build",
19 | "presentation": {
20 | "reveal": "silent"
21 | },
22 | "problemMatcher": "$msCompile"
23 | }
24 | ]
25 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 blazorhero / codewithmukesh / Mukesh Murugan
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docker-compose.dcproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 2.1
5 | Linux
6 | 161b234c-6018-4ce5-86b2-0ea95a53982d
7 | LaunchBrowser
8 | {Scheme}://localhost:{ServicePort}
9 | server
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.4'
2 |
3 | services:
4 | blazorhero:
5 | image: ${DOCKER_REGISTRY-}blazorhero
6 | build:
7 | context: .
8 | dockerfile: src/Server/Dockerfile
9 | environment:
10 | - "ConnectionStrings__DefaultConnection=Server=db;Database=BlazorHero;User=sa;Password=Your_password123;MultipleActiveResultSets=true"
11 | - "ASPNETCORE_Kestrel__Certificates__Default__Password=securePassword123"
12 | - "ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx"
13 | volumes:
14 | - ~/.aspnet/https:/https:ro
15 | ports:
16 | - "5005:5005"
17 | - "5006:5006"
18 | depends_on:
19 | - db
20 | restart: on-failure
21 | container_name: blazorhero
22 |
23 | db:
24 | image: "mcr.microsoft.com/mssql/server"
25 | environment:
26 | - "SA_PASSWORD=Your_password123"
27 | - "ACCEPT_EULA=Y"
28 | container_name: mssql
--------------------------------------------------------------------------------
/src/Application/Application.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | BlazorHero.CleanArchitecture.Application
6 | BlazorHero.CleanArchitecture.Application
7 | latest
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/src/Application/Configurations/AppConfiguration.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Configurations
2 | {
3 | public class AppConfiguration
4 | {
5 | public string Secret { get; set; }
6 |
7 | public bool BehindSSLProxy { get; set; }
8 |
9 | public string ProxyIP { get; set; }
10 |
11 | public string ApplicationUrl { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Application/Configurations/MailConfiguration.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Configurations
2 | {
3 | public class MailConfiguration
4 | {
5 | public string From { get; set; }
6 | public string Host { get; set; }
7 | public int Port { get; set; }
8 | public string UserName { get; set; }
9 | public string Password { get; set; }
10 | public string DisplayName { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Application/Enums/AuditType.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Enums
2 | {
3 | public enum AuditType : byte
4 | {
5 | None = 0,
6 | Create = 1,
7 | Update = 2,
8 | Delete = 3
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Application/Enums/UploadType.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Enums
4 | {
5 | public enum UploadType : byte
6 | {
7 | [Description(@"Images\Products")]
8 | Product,
9 |
10 | [Description(@"Images\ProfilePictures")]
11 | ProfilePicture,
12 |
13 | [Description(@"Documents")]
14 | Document
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Application/Exceptions/ApiException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Globalization;
3 |
4 | namespace BlazorHero.CleanArchitecture.Application.Exceptions
5 | {
6 | public class ApiException : Exception
7 | {
8 | public ApiException() : base()
9 | {
10 | }
11 |
12 | public ApiException(string message) : base(message)
13 | {
14 | }
15 |
16 | public ApiException(string message, params object[] args)
17 | : base(string.Format(CultureInfo.CurrentCulture, message, args))
18 | {
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/Application/Extensions/EnumExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | namespace BlazorHero.CleanArchitecture.Application.Extensions
5 | {
6 | public static class EnumExtensions
7 | {
8 | public static string ToDescriptionString(this Enum val)
9 | {
10 | var attributes = (DescriptionAttribute[])val.GetType().GetField(val.ToString())?.GetCustomAttributes(typeof(DescriptionAttribute), false);
11 |
12 | return attributes?.Length > 0
13 | ? attributes[0].Description
14 | : val.ToString();
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Application/Extensions/ExpressionExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Extensions
7 | {
8 | public static class PredicateBuilder
9 | {
10 | public static Expression> And(this Expression> left, Expression> right)
11 | {
12 | ParameterExpression p = left.Parameters.First();
13 | SubstExpressionVisitor visitor = new SubstExpressionVisitor
14 | {
15 | Subst = {[right.Parameters.First()] = p}
16 | };
17 |
18 | Expression body = Expression.AndAlso(left.Body, visitor.Visit(right.Body));
19 | return Expression.Lambda>(body, p);
20 | }
21 |
22 | public static Expression> Or(this Expression> left, Expression> right)
23 | {
24 |
25 | ParameterExpression p = left.Parameters.First();
26 | SubstExpressionVisitor visitor = new SubstExpressionVisitor
27 | {
28 | Subst = {[right.Parameters.First()] = p}
29 | };
30 |
31 | Expression body = Expression.OrElse(left.Body, visitor.Visit(right.Body));
32 | return Expression.Lambda>(body, p);
33 | }
34 | }
35 |
36 | internal class SubstExpressionVisitor : ExpressionVisitor
37 | {
38 | public Dictionary Subst = new();
39 |
40 | protected override Expression VisitParameter(ParameterExpression node)
41 | {
42 | if (Subst.TryGetValue(node, out var newValue))
43 | {
44 | return newValue;
45 | }
46 | return node;
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/src/Application/Extensions/QueryableExtensions.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Exceptions;
2 | using BlazorHero.CleanArchitecture.Application.Specifications.Base;
3 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
4 | using Microsoft.EntityFrameworkCore;
5 | using System.Collections.Generic;
6 | using System.Linq;
7 | using System.Threading.Tasks;
8 | using BlazorHero.CleanArchitecture.Domain.Contracts;
9 |
10 | namespace BlazorHero.CleanArchitecture.Application.Extensions
11 | {
12 | public static class QueryableExtensions
13 | {
14 | public static async Task> ToPaginatedListAsync(this IQueryable source, int pageNumber, int pageSize) where T : class
15 | {
16 | if (source == null) throw new ApiException();
17 | pageNumber = pageNumber == 0 ? 1 : pageNumber;
18 | pageSize = pageSize == 0 ? 10 : pageSize;
19 | int count = await source.CountAsync();
20 | pageNumber = pageNumber <= 0 ? 1 : pageNumber;
21 | List items = await source.Skip((pageNumber - 1) * pageSize).Take(pageSize).ToListAsync();
22 | return PaginatedResult.Success(items, count, pageNumber, pageSize);
23 | }
24 |
25 | public static IQueryable Specify(this IQueryable query, ISpecification spec) where T : class, IEntity
26 | {
27 | var queryableResultWithIncludes = spec.Includes
28 | .Aggregate(query,
29 | (current, include) => current.Include(include));
30 | var secondaryResult = spec.IncludeStrings
31 | .Aggregate(queryableResultWithIncludes,
32 | (current, include) => current.Include(include));
33 | return secondaryResult.Where(spec.Criteria);
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/Application/Features/Brands/Queries/GetAll/GetAllBrandsQuery.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using BlazorHero.CleanArchitecture.Application.Interfaces.Repositories;
3 | using BlazorHero.CleanArchitecture.Domain.Entities.Catalog;
4 | using BlazorHero.CleanArchitecture.Shared.Constants.Application;
5 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
6 | using LazyCache;
7 | using MediatR;
8 | using System;
9 | using System.Collections.Generic;
10 | using System.Threading;
11 | using System.Threading.Tasks;
12 |
13 | namespace BlazorHero.CleanArchitecture.Application.Features.Brands.Queries.GetAll
14 | {
15 | public class GetAllBrandsQuery : IRequest>>
16 | {
17 | public GetAllBrandsQuery()
18 | {
19 | }
20 | }
21 |
22 | internal class GetAllBrandsCachedQueryHandler : IRequestHandler>>
23 | {
24 | private readonly IUnitOfWork _unitOfWork;
25 | private readonly IMapper _mapper;
26 | private readonly IAppCache _cache;
27 |
28 | public GetAllBrandsCachedQueryHandler(IUnitOfWork unitOfWork, IMapper mapper, IAppCache cache)
29 | {
30 | _unitOfWork = unitOfWork;
31 | _mapper = mapper;
32 | _cache = cache;
33 | }
34 |
35 | public async Task>> Handle(GetAllBrandsQuery request, CancellationToken cancellationToken)
36 | {
37 | Func>> getAllBrands = () => _unitOfWork.Repository().GetAllAsync();
38 | var brandList = await _cache.GetOrAddAsync(ApplicationConstants.Cache.GetAllBrandsCacheKey, getAllBrands);
39 | var mappedBrands = _mapper.Map>(brandList);
40 | return await Result>.SuccessAsync(mappedBrands);
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/src/Application/Features/Brands/Queries/GetAll/GetAllBrandsResponse.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Features.Brands.Queries.GetAll
2 | {
3 | public class GetAllBrandsResponse
4 | {
5 | public int Id { get; set; }
6 | public string Name { get; set; }
7 | public string Description { get; set; }
8 | public decimal Tax { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Application/Features/Brands/Queries/GetById/GetBrandByIdQuery.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using BlazorHero.CleanArchitecture.Application.Interfaces.Repositories;
3 | using BlazorHero.CleanArchitecture.Domain.Entities.Catalog;
4 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
5 | using MediatR;
6 | using System.Threading;
7 | using System.Threading.Tasks;
8 |
9 | namespace BlazorHero.CleanArchitecture.Application.Features.Brands.Queries.GetById
10 | {
11 | public class GetBrandByIdQuery : IRequest>
12 | {
13 | public int Id { get; set; }
14 | }
15 |
16 | internal class GetProductByIdQueryHandler : IRequestHandler>
17 | {
18 | private readonly IUnitOfWork _unitOfWork;
19 | private readonly IMapper _mapper;
20 |
21 | public GetProductByIdQueryHandler(IUnitOfWork unitOfWork, IMapper mapper)
22 | {
23 | _unitOfWork = unitOfWork;
24 | _mapper = mapper;
25 | }
26 |
27 | public async Task> Handle(GetBrandByIdQuery query, CancellationToken cancellationToken)
28 | {
29 | var brand = await _unitOfWork.Repository().GetByIdAsync(query.Id);
30 | var mappedBrand = _mapper.Map(brand);
31 | return await Result.SuccessAsync(mappedBrand);
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Application/Features/Brands/Queries/GetById/GetBrandByIdResponse.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Features.Brands.Queries.GetById
2 | {
3 | public class GetBrandByIdResponse
4 | {
5 | public int Id { get; set; }
6 | public string Name { get; set; }
7 | public decimal Tax { get; set; }
8 | public string Description { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Application/Features/Dashboards/Queries/GetData/DashboardDataResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Features.Dashboards.Queries.GetData
4 | {
5 | public class DashboardDataResponse
6 | {
7 | public int ProductCount { get; set; }
8 | public int BrandCount { get; set; }
9 | public int DocumentCount { get; set; }
10 | public int DocumentTypeCount { get; set; }
11 | public int DocumentExtendedAttributeCount { get; set; }
12 | public int UserCount { get; set; }
13 | public int RoleCount { get; set; }
14 | public List DataEnterBarChart { get; set; } = new();
15 | public Dictionary ProductByBrandTypePieChart { get; set; }
16 | }
17 |
18 | public class ChartSeries
19 | {
20 | public ChartSeries() { }
21 |
22 | public string Name { get; set; }
23 | public double[] Data { get; set; }
24 | }
25 |
26 | }
--------------------------------------------------------------------------------
/src/Application/Features/DocumentTypes/Queries/GetAll/GetAllDocumentTypesResponse.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Features.DocumentTypes.Queries.GetAll
2 | {
3 | public class GetAllDocumentTypesResponse
4 | {
5 | public int Id { get; set; }
6 | public string Name { get; set; }
7 | public string Description { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Application/Features/DocumentTypes/Queries/GetById/GetDocumentTypeByIdQuery.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 | using AutoMapper;
4 | using BlazorHero.CleanArchitecture.Application.Interfaces.Repositories;
5 | using BlazorHero.CleanArchitecture.Domain.Entities.Misc;
6 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
7 | using MediatR;
8 |
9 | namespace BlazorHero.CleanArchitecture.Application.Features.DocumentTypes.Queries.GetById
10 | {
11 | public class GetDocumentTypeByIdQuery : IRequest>
12 | {
13 | public int Id { get; set; }
14 | }
15 |
16 | internal class GetDocumentTypeByIdQueryHandler : IRequestHandler>
17 | {
18 | private readonly IUnitOfWork _unitOfWork;
19 | private readonly IMapper _mapper;
20 |
21 | public GetDocumentTypeByIdQueryHandler(IUnitOfWork unitOfWork, IMapper mapper)
22 | {
23 | _unitOfWork = unitOfWork;
24 | _mapper = mapper;
25 | }
26 |
27 | public async Task> Handle(GetDocumentTypeByIdQuery query, CancellationToken cancellationToken)
28 | {
29 | var documentType = await _unitOfWork.Repository().GetByIdAsync(query.Id);
30 | var mappedDocumentType = _mapper.Map(documentType);
31 | return await Result.SuccessAsync(mappedDocumentType);
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Application/Features/DocumentTypes/Queries/GetById/GetDocumentTypeByIdResponse.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Features.DocumentTypes.Queries.GetById
2 | {
3 | public class GetDocumentTypeByIdResponse
4 | {
5 | public int Id { get; set; }
6 | public string Name { get; set; }
7 | public string Description { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Application/Features/Documents/Queries/GetAll/GetAllDocumentsResponse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Features.Documents.Queries.GetAll
4 | {
5 | public class GetAllDocumentsResponse
6 | {
7 | public int Id { get; set; }
8 | public string Title { get; set; }
9 | public string Description { get; set; }
10 | public bool IsPublic { get; set; }
11 | public string CreatedBy { get; set; }
12 | public DateTime CreatedOn { get; set; }
13 | public string URL { get; set; }
14 | public string DocumentType { get; set; }
15 | public int DocumentTypeId { get; set; }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Application/Features/Documents/Queries/GetById/GetDocumentByIdQuery.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 | using System.Threading.Tasks;
3 | using AutoMapper;
4 | using BlazorHero.CleanArchitecture.Application.Interfaces.Repositories;
5 | using BlazorHero.CleanArchitecture.Domain.Entities.Misc;
6 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
7 | using MediatR;
8 |
9 | namespace BlazorHero.CleanArchitecture.Application.Features.Documents.Queries.GetById
10 | {
11 | public class GetDocumentByIdQuery : IRequest>
12 | {
13 | public int Id { get; set; }
14 | }
15 |
16 | internal class GetDocumentByIdQueryHandler : IRequestHandler>
17 | {
18 | private readonly IUnitOfWork _unitOfWork;
19 | private readonly IMapper _mapper;
20 |
21 | public GetDocumentByIdQueryHandler(IUnitOfWork unitOfWork, IMapper mapper)
22 | {
23 | _unitOfWork = unitOfWork;
24 | _mapper = mapper;
25 | }
26 |
27 | public async Task> Handle(GetDocumentByIdQuery query, CancellationToken cancellationToken)
28 | {
29 | var document = await _unitOfWork.Repository().GetByIdAsync(query.Id);
30 | var mappedDocument = _mapper.Map(document);
31 | return await Result.SuccessAsync(mappedDocument);
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Application/Features/Documents/Queries/GetById/GetDocumentByIdResponse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Features.Documents.Queries.GetById
4 | {
5 | public class GetDocumentByIdResponse
6 | {
7 | public int Id { get; set; }
8 | public string Title { get; set; }
9 | public string Description { get; set; }
10 | public bool IsPublic { get; set; }
11 | public string CreatedBy { get; set; }
12 | public DateTime CreatedOn { get; set; }
13 | public string URL { get; set; }
14 | public string DocumentType { get; set; }
15 | public int DocumentTypeId { get; set; }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Application/Features/Products/Commands/Delete/DeleteProductCommand.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Interfaces.Repositories;
2 | using BlazorHero.CleanArchitecture.Domain.Entities.Catalog;
3 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
4 | using MediatR;
5 | using System.Threading;
6 | using System.Threading.Tasks;
7 | using Microsoft.Extensions.Localization;
8 |
9 | namespace BlazorHero.CleanArchitecture.Application.Features.Products.Commands.Delete
10 | {
11 | public class DeleteProductCommand : IRequest>
12 | {
13 | public int Id { get; set; }
14 | }
15 |
16 | internal class DeleteProductCommandHandler : IRequestHandler>
17 | {
18 | private readonly IUnitOfWork _unitOfWork;
19 | private readonly IStringLocalizer _localizer;
20 |
21 | public DeleteProductCommandHandler(IUnitOfWork unitOfWork, IStringLocalizer localizer)
22 | {
23 | _unitOfWork = unitOfWork;
24 | _localizer = localizer;
25 | }
26 |
27 | public async Task> Handle(DeleteProductCommand command, CancellationToken cancellationToken)
28 | {
29 | var product = await _unitOfWork.Repository().GetByIdAsync(command.Id);
30 | if (product != null)
31 | {
32 | await _unitOfWork.Repository().DeleteAsync(product);
33 | await _unitOfWork.Commit(cancellationToken);
34 | return await Result.SuccessAsync(product.Id, _localizer["Product Deleted"]);
35 | }
36 | else
37 | {
38 | return await Result.FailAsync(_localizer["Product Not Found!"]);
39 | }
40 | }
41 | }
42 | }
--------------------------------------------------------------------------------
/src/Application/Features/Products/Queries/GetAllPaged/GetAllPagedProductsResponse.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Features.Products.Queries.GetAllPaged
2 | {
3 | public class GetAllPagedProductsResponse
4 | {
5 | public int Id { get; set; }
6 | public string Name { get; set; }
7 | public string Barcode { get; set; }
8 | public string Description { get; set; }
9 | public decimal Rate { get; set; }
10 | public string Brand { get; set; }
11 | public int BrandId { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Application/Features/Products/Queries/GetProductImage/GetProductImageQuery.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Interfaces.Repositories;
2 | using BlazorHero.CleanArchitecture.Domain.Entities.Catalog;
3 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
4 | using MediatR;
5 | using Microsoft.EntityFrameworkCore;
6 | using System.Linq;
7 | using System.Threading;
8 | using System.Threading.Tasks;
9 |
10 | namespace BlazorHero.CleanArchitecture.Application.Features.Products.Queries.GetProductImage
11 | {
12 | public class GetProductImageQuery : IRequest>
13 | {
14 | public int Id { get; set; }
15 |
16 | public GetProductImageQuery(int productId)
17 | {
18 | Id = productId;
19 | }
20 | }
21 |
22 | internal class GetProductImageQueryHandler : IRequestHandler>
23 | {
24 | private readonly IUnitOfWork _unitOfWork;
25 |
26 | public GetProductImageQueryHandler(IUnitOfWork unitOfWork)
27 | {
28 | _unitOfWork = unitOfWork;
29 | }
30 |
31 | public async Task> Handle(GetProductImageQuery request, CancellationToken cancellationToken)
32 | {
33 | var data = await _unitOfWork.Repository().Entities.Where(p => p.Id == request.Id).Select(a => a.ImageDataURL).FirstOrDefaultAsync(cancellationToken);
34 | return await Result.SuccessAsync(data: data);
35 | }
36 | }
37 | }
--------------------------------------------------------------------------------
/src/Application/Features/Products/Queries/GetProductImage/GetProductImageResponse.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Features.Products.Queries.GetProductImage
2 | {
3 | public class GetProductImageResponse
4 | {
5 | public string ImageDataURL { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Chat/IChatHistory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Chat
4 | {
5 | public interface IChatHistory where TUser : IChatUser
6 | {
7 | public long Id { get; set; }
8 | public string FromUserId { get; set; }
9 | public string ToUserId { get; set; }
10 | public string Message { get; set; }
11 | public DateTime CreatedDate { get; set; }
12 | public TUser FromUser { get; set; }
13 | public TUser ToUser { get; set; }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Chat/IChatUser.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations.Schema;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Chat
4 | {
5 | public interface IChatUser
6 | {
7 | public string FirstName { get; set; }
8 |
9 | public string LastName { get; set; }
10 |
11 | [Column(TypeName = "text")]
12 | public string ProfilePictureDataUrl { get; set; }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Common/IScopedService.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Common
2 | {
3 | public interface IScopedService
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Common/IService.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Common
2 | {
3 | public interface IService
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Common/ISingletonService.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Common
2 | {
3 | public interface ISingletonService
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Repositories/IBrandRepository.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Repositories
2 | {
3 | public interface IBrandRepository
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Repositories/IDocumentRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Repositories
4 | {
5 | public interface IDocumentRepository
6 | {
7 | Task IsDocumentTypeUsed(int documentTypeId);
8 |
9 | Task IsDocumentExtendedAttributeUsed(int documentExtendedAttributeId);
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Repositories/IDocumentTypeRepository.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Repositories
2 | {
3 | public interface IDocumentTypeRepository
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Repositories/IExtendedAttributeUnitOfWork.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Threading;
3 | using System.Threading.Tasks;
4 | using BlazorHero.CleanArchitecture.Domain.Contracts;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Repositories
7 | {
8 | public interface IExtendedAttributeUnitOfWork : IDisposable where TEntity : AuditableEntity
9 | {
10 | IRepositoryAsync Repository() where T : AuditableEntityExtendedAttribute;
11 |
12 | Task Commit(CancellationToken cancellationToken);
13 |
14 | Task CommitAndRemoveCache(CancellationToken cancellationToken, params string[] cacheKeys);
15 |
16 | Task Rollback();
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Repositories/IProductRepository.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Repositories
4 | {
5 | public interface IProductRepository
6 | {
7 | Task IsBrandUsed(int brandId);
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Repositories/IRepositoryAsync.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 | using System.Threading.Tasks;
4 | using BlazorHero.CleanArchitecture.Domain.Contracts;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Repositories
7 | {
8 | public interface IRepositoryAsync where T : class, IEntity
9 | {
10 | IQueryable Entities { get; }
11 |
12 | Task GetByIdAsync(TId id);
13 |
14 | Task> GetAllAsync();
15 |
16 | Task> GetPagedResponseAsync(int pageNumber, int pageSize);
17 |
18 | Task AddAsync(T entity);
19 |
20 | Task UpdateAsync(T entity);
21 |
22 | Task DeleteAsync(T entity);
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Repositories/IUnitOfWork.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Domain.Contracts;
2 | using System;
3 | using System.Threading;
4 | using System.Threading.Tasks;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Repositories
7 | {
8 | public interface IUnitOfWork : IDisposable
9 | {
10 | IRepositoryAsync Repository() where T : AuditableEntity;
11 |
12 | Task Commit(CancellationToken cancellationToken);
13 |
14 | Task CommitAndRemoveCache(CancellationToken cancellationToken, params string[] cacheKeys);
15 |
16 | Task Rollback();
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Serialization/Options/IJsonSerializerOptions.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Serialization.Options
4 | {
5 | public interface IJsonSerializerOptions
6 | {
7 | ///
8 | /// Options for .
9 | ///
10 | public JsonSerializerOptions JsonSerializerOptions { get; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Serialization/Serializers/IJsonSerializer.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Serialization.Serializers
2 | {
3 | public interface IJsonSerializer
4 | {
5 | string Serialize(T obj);
6 | T Deserialize(string text);
7 | }
8 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Serialization/Settings/IJsonSerializerSettings.cs:
--------------------------------------------------------------------------------
1 | using Newtonsoft.Json;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Serialization.Settings
4 | {
5 | public interface IJsonSerializerSettings
6 | {
7 | ///
8 | /// Settings for .
9 | ///
10 | public JsonSerializerSettings JsonSerializerSettings { get; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/Account/IAccountService.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Interfaces.Common;
2 | using BlazorHero.CleanArchitecture.Application.Requests.Identity;
3 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
4 | using System.Threading.Tasks;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services.Account
7 | {
8 | public interface IAccountService : IService
9 | {
10 | Task UpdateProfileAsync(UpdateProfileRequest model, string userId);
11 |
12 | Task ChangePasswordAsync(ChangePasswordRequest model, string userId);
13 |
14 | Task> GetProfilePictureAsync(string userId);
15 |
16 | Task> UpdateProfilePictureAsync(UpdateProfilePictureRequest request, string userId);
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/IAuditService.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Responses.Audit;
2 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services
7 | {
8 | public interface IAuditService
9 | {
10 | Task>> GetCurrentUserTrailsAsync(string userId);
11 |
12 | Task> ExportToExcelAsync(string userId, string searchString = "", bool searchInOldValues = false, bool searchInNewValues = false);
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/IChatService.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Responses.Identity;
2 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 | using BlazorHero.CleanArchitecture.Application.Interfaces.Chat;
6 | using BlazorHero.CleanArchitecture.Application.Models.Chat;
7 |
8 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services
9 | {
10 | public interface IChatService
11 | {
12 | Task>> GetChatUsersAsync(string userId);
13 |
14 | Task SaveMessageAsync(ChatHistory message);
15 |
16 | Task>> GetChatHistoryAsync(string userId, string contactId);
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/ICurrentUserService.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Interfaces.Common;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services
4 | {
5 | public interface ICurrentUserService : IService
6 | {
7 | string UserId { get; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/IDatabaseSeeder.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services
2 | {
3 | public interface IDatabaseSeeder
4 | {
5 | void Initialize();
6 | }
7 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/IDateTimeService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services
4 | {
5 | public interface IDateTimeService
6 | {
7 | DateTime NowUtc { get; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/IExcelService.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Data;
4 | using System.IO;
5 | using System.Threading.Tasks;
6 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
7 |
8 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services
9 | {
10 | public interface IExcelService
11 | {
12 | Task ExportAsync(IEnumerable data
13 | , Dictionary> mappers
14 | , string sheetName = "Sheet1");
15 |
16 | Task>> ImportAsync(Stream data
17 | , Dictionary> mappers
18 | , string sheetName = "Sheet1");
19 | }
20 |
21 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/IMailService.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Requests.Mail;
2 | using System.Threading.Tasks;
3 |
4 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services
5 | {
6 | public interface IMailService
7 | {
8 | Task SendAsync(MailRequest request);
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/IUploadService.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Requests;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services
4 | {
5 | public interface IUploadService
6 | {
7 | string UploadAsync(UploadRequest request);
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/Identity/IRoleClaimService.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading.Tasks;
3 | using BlazorHero.CleanArchitecture.Application.Interfaces.Common;
4 | using BlazorHero.CleanArchitecture.Application.Requests.Identity;
5 | using BlazorHero.CleanArchitecture.Application.Responses.Identity;
6 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
7 |
8 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services.Identity
9 | {
10 | public interface IRoleClaimService : IService
11 | {
12 | Task>> GetAllAsync();
13 |
14 | Task GetCountAsync();
15 |
16 | Task> GetByIdAsync(int id);
17 |
18 | Task>> GetAllByRoleIdAsync(string roleId);
19 |
20 | Task> SaveAsync(RoleClaimRequest request);
21 |
22 | Task> DeleteAsync(int id);
23 | }
24 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/Identity/IRoleService.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Interfaces.Common;
2 | using BlazorHero.CleanArchitecture.Application.Requests.Identity;
3 | using BlazorHero.CleanArchitecture.Application.Responses.Identity;
4 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
5 | using System.Collections.Generic;
6 | using System.Threading.Tasks;
7 |
8 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services.Identity
9 | {
10 | public interface IRoleService : IService
11 | {
12 | Task>> GetAllAsync();
13 |
14 | Task GetCountAsync();
15 |
16 | Task> GetByIdAsync(string id);
17 |
18 | Task> SaveAsync(RoleRequest request);
19 |
20 | Task> DeleteAsync(string id);
21 |
22 | Task> GetAllPermissionsAsync(string roleId);
23 |
24 | Task> UpdatePermissionsAsync(PermissionRequest request);
25 | }
26 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/Identity/ITokenService.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Interfaces.Common;
2 | using BlazorHero.CleanArchitecture.Application.Requests.Identity;
3 | using BlazorHero.CleanArchitecture.Application.Responses.Identity;
4 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
5 | using System.Threading.Tasks;
6 |
7 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services.Identity
8 | {
9 | public interface ITokenService : IService
10 | {
11 | Task> LoginAsync(TokenRequest model);
12 |
13 | Task> GetRefreshTokenAsync(RefreshTokenRequest model);
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/Identity/IUserService.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Interfaces.Common;
2 | using BlazorHero.CleanArchitecture.Application.Requests.Identity;
3 | using BlazorHero.CleanArchitecture.Application.Responses.Identity;
4 | using BlazorHero.CleanArchitecture.Shared.Wrapper;
5 | using System.Collections.Generic;
6 | using System.Threading.Tasks;
7 |
8 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services.Identity
9 | {
10 | public interface IUserService : IService
11 | {
12 | Task>> GetAllAsync();
13 |
14 | Task GetCountAsync();
15 |
16 | Task> GetAsync(string userId);
17 |
18 | Task RegisterAsync(RegisterRequest request, string origin);
19 |
20 | Task ToggleUserStatusAsync(ToggleUserStatusRequest request);
21 |
22 | Task> GetRolesAsync(string id);
23 |
24 | Task UpdateRolesAsync(UpdateUserRolesRequest request);
25 |
26 | Task> ConfirmEmailAsync(string userId, string code);
27 |
28 | Task ForgotPasswordAsync(ForgotPasswordRequest request, string origin);
29 |
30 | Task ResetPasswordAsync(ResetPasswordRequest request);
31 |
32 | Task ExportToExcelAsync(string searchString = "");
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/Storage/ChangedEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services.Storage
4 | {
5 | [ExcludeFromCodeCoverage]
6 | public class ChangedEventArgs
7 | {
8 | public string Key { get; set; }
9 | public object OldValue { get; set; }
10 | public object NewValue { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/Storage/ChangingEventArgs.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics.CodeAnalysis;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services.Storage
4 | {
5 | [ExcludeFromCodeCoverage]
6 | public class ChangingEventArgs : ChangedEventArgs
7 | {
8 | public bool Cancel { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Application/Interfaces/Services/Storage/Provider/IServerStorageProvider.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Interfaces.Services.Storage.Provider
4 | {
5 | public interface IStorageProvider
6 | {
7 | void Clear();
8 | ValueTask ClearAsync();
9 | bool ContainKey(string key);
10 | ValueTask ContainKeyAsync(string key);
11 | string GetItem(string key);
12 | ValueTask GetItemAsync(string key);
13 | string Key(int index);
14 | ValueTask KeyAsync(int index);
15 | int Length();
16 | ValueTask LengthAsync();
17 | void RemoveItem(string key);
18 | ValueTask RemoveItemAsync(string key);
19 | void SetItem(string key, string data);
20 | ValueTask SetItemAsync(string key, string data);
21 | }
22 | }
--------------------------------------------------------------------------------
/src/Application/Mappings/BrandProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using BlazorHero.CleanArchitecture.Application.Features.Brands.Commands.AddEdit;
3 | using BlazorHero.CleanArchitecture.Application.Features.Brands.Queries.GetAll;
4 | using BlazorHero.CleanArchitecture.Application.Features.Brands.Queries.GetById;
5 | using BlazorHero.CleanArchitecture.Domain.Entities.Catalog;
6 |
7 | namespace BlazorHero.CleanArchitecture.Application.Mappings
8 | {
9 | public class BrandProfile : Profile
10 | {
11 | public BrandProfile()
12 | {
13 | CreateMap().ReverseMap();
14 | CreateMap().ReverseMap();
15 | CreateMap().ReverseMap();
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Application/Mappings/DocumentProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using BlazorHero.CleanArchitecture.Application.Features.Documents.Commands.AddEdit;
3 | using BlazorHero.CleanArchitecture.Application.Features.Documents.Queries.GetById;
4 | using BlazorHero.CleanArchitecture.Domain.Entities.Misc;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Mappings
7 | {
8 | public class DocumentProfile : Profile
9 | {
10 | public DocumentProfile()
11 | {
12 | CreateMap().ReverseMap();
13 | CreateMap().ReverseMap();
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Application/Mappings/DocumentTypeProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using BlazorHero.CleanArchitecture.Application.Features.DocumentTypes.Commands.AddEdit;
3 | using BlazorHero.CleanArchitecture.Application.Features.DocumentTypes.Queries.GetAll;
4 | using BlazorHero.CleanArchitecture.Application.Features.DocumentTypes.Queries.GetById;
5 | using BlazorHero.CleanArchitecture.Domain.Entities.Misc;
6 |
7 | namespace BlazorHero.CleanArchitecture.Application.Mappings
8 | {
9 | public class DocumentTypeProfile : Profile
10 | {
11 | public DocumentTypeProfile()
12 | {
13 | CreateMap().ReverseMap();
14 | CreateMap().ReverseMap();
15 | CreateMap().ReverseMap();
16 | }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Application/Mappings/ExtendedAttributeProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using BlazorHero.CleanArchitecture.Application.Features.ExtendedAttributes.Commands.AddEdit;
3 | using BlazorHero.CleanArchitecture.Application.Features.ExtendedAttributes.Queries.GetAll;
4 | using BlazorHero.CleanArchitecture.Application.Features.ExtendedAttributes.Queries.GetAllByEntityId;
5 | using BlazorHero.CleanArchitecture.Application.Features.ExtendedAttributes.Queries.GetById;
6 | using BlazorHero.CleanArchitecture.Domain.Entities.ExtendedAttributes;
7 |
8 | namespace BlazorHero.CleanArchitecture.Application.Mappings
9 | {
10 | public class ExtendedAttributeProfile : Profile
11 | {
12 | public ExtendedAttributeProfile()
13 | {
14 | CreateMap(typeof(AddEditExtendedAttributeCommand<,,,>), typeof(DocumentExtendedAttribute))
15 | .ForMember(nameof(DocumentExtendedAttribute.Entity), opt => opt.Ignore())
16 | .ForMember(nameof(DocumentExtendedAttribute.CreatedBy), opt => opt.Ignore())
17 | .ForMember(nameof(DocumentExtendedAttribute.CreatedOn), opt => opt.Ignore())
18 | .ForMember(nameof(DocumentExtendedAttribute.LastModifiedBy), opt => opt.Ignore())
19 | .ForMember(nameof(DocumentExtendedAttribute.LastModifiedOn), opt => opt.Ignore());
20 |
21 | CreateMap(typeof(GetExtendedAttributeByIdResponse<,>), typeof(DocumentExtendedAttribute)).ReverseMap();
22 | CreateMap(typeof(GetAllExtendedAttributesResponse<,>), typeof(DocumentExtendedAttribute)).ReverseMap();
23 | CreateMap(typeof(GetAllExtendedAttributesByEntityIdResponse<,>), typeof(DocumentExtendedAttribute)).ReverseMap();
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/Application/Mappings/ProductProfile.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using BlazorHero.CleanArchitecture.Application.Features.Products.Commands.AddEdit;
3 | using BlazorHero.CleanArchitecture.Domain.Entities.Catalog;
4 |
5 | namespace BlazorHero.CleanArchitecture.Application.Mappings
6 | {
7 | public class ProductProfile : Profile
8 | {
9 | public ProductProfile()
10 | {
11 | CreateMap().ReverseMap();
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Application/Models/Chat/ChatHistory.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using BlazorHero.CleanArchitecture.Application.Interfaces.Chat;
3 |
4 | namespace BlazorHero.CleanArchitecture.Application.Models.Chat
5 | {
6 | public partial class ChatHistory : IChatHistory where TUser : IChatUser
7 | {
8 | public long Id { get; set; }
9 | public string FromUserId { get; set; }
10 | public string ToUserId { get; set; }
11 | public string Message { get; set; }
12 | public DateTime CreatedDate { get; set; }
13 | public virtual TUser FromUser { get; set; }
14 | public virtual TUser ToUser { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Application/Models/Chat/Message.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Models.Chat
2 | {
3 | public class Message
4 | {
5 | public string ToUserId { get; set; }
6 | public string FromUserId { get; set; }
7 | public string MessageText { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Catalog/GetAllPagedProductsRequest.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Requests.Catalog
2 | {
3 | public class GetAllPagedProductsRequest : PagedRequest
4 | {
5 | public string SearchString { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Documents/GetAllPagedDocumentsRequest.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Requests.Documents
2 | {
3 | public class GetAllPagedDocumentsRequest : PagedRequest
4 | {
5 | public string SearchString { get; set; }
6 | }
7 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/ChangePasswordRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
4 | {
5 | public class ChangePasswordRequest
6 | {
7 | [Required]
8 | public string Password { get; set; }
9 |
10 | [Required]
11 | public string NewPassword { get; set; }
12 |
13 | [Required]
14 | public string ConfirmNewPassword { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/ForgotPasswordRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
4 | {
5 | public class ForgotPasswordRequest
6 | {
7 | [Required]
8 | [EmailAddress]
9 | public string Email { get; set; }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/PermissionRequest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
4 | {
5 | public class PermissionRequest
6 | {
7 | public string RoleId { get; set; }
8 | public IList RoleClaims { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/RefreshTokenRequest.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
2 | {
3 | public class RefreshTokenRequest
4 | {
5 | public string Token { get; set; }
6 | public string RefreshToken { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/RegisterRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
4 | {
5 | public class RegisterRequest
6 | {
7 | [Required]
8 | public string FirstName { get; set; }
9 |
10 | [Required]
11 | public string LastName { get; set; }
12 |
13 | [Required]
14 | [EmailAddress]
15 | public string Email { get; set; }
16 |
17 | [Required]
18 | [MinLength(6)]
19 | public string UserName { get; set; }
20 |
21 | [Required]
22 | [MinLength(6)]
23 | public string Password { get; set; }
24 |
25 | [Required]
26 | [Compare(nameof(Password))]
27 | public string ConfirmPassword { get; set; }
28 |
29 | public string PhoneNumber { get; set; }
30 |
31 | public bool ActivateUser { get; set; } = false;
32 | public bool AutoConfirmEmail { get; set; } = false;
33 | }
34 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/ResetPasswordRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
4 | {
5 | public class ResetPasswordRequest
6 | {
7 | [Required]
8 | [EmailAddress]
9 | public string Email { get; set; }
10 | [Required]
11 | public string Password { get; set; }
12 | [Required]
13 | [Compare(nameof(Password))]
14 | public string ConfirmPassword { get; set; }
15 | [Required]
16 | public string Token { get; set; }
17 | }
18 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/RoleClaimRequest.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
2 | {
3 | public class RoleClaimRequest
4 | {
5 | public int Id { get; set; }
6 | public string RoleId { get; set; }
7 | public string Type { get; set; }
8 | public string Value { get; set; }
9 | public string Description { get; set; }
10 | public string Group { get; set; }
11 | public bool Selected { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/RoleRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
4 | {
5 | public class RoleRequest
6 | {
7 | public string Id { get; set; }
8 |
9 | [Required]
10 | public string Name { get; set; }
11 | public string Description { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/ToggleUserStatusRequest.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
2 | {
3 | public class ToggleUserStatusRequest
4 | {
5 | public bool ActivateUser { get; set; }
6 | public string UserId { get; set; }
7 | }
8 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/TokenRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
4 | {
5 | public class TokenRequest
6 | {
7 | [Required]
8 | public string Email { get; set; }
9 |
10 | [Required]
11 | public string Password { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/UpdateProfilePictureRequest.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
2 | {
3 | public class UpdateProfilePictureRequest : UploadRequest
4 | {
5 | }
6 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/UpdateProfileRequest.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
4 | {
5 | public class UpdateProfileRequest
6 | {
7 | [Required]
8 | public string FirstName { get; set; }
9 |
10 | [Required]
11 | public string LastName { get; set; }
12 |
13 | public string PhoneNumber { get; set; }
14 | public string Email { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Identity/UpdateUserRolesRequest.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Responses.Identity;
2 | using System.Collections.Generic;
3 |
4 | namespace BlazorHero.CleanArchitecture.Application.Requests.Identity
5 | {
6 | public class UpdateUserRolesRequest
7 | {
8 | public string UserId { get; set; }
9 | public IList UserRoles { get; set; }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Application/Requests/Mail/MailRequest.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Requests.Mail
2 | {
3 | public class MailRequest
4 | {
5 | public string To { get; set; }
6 | public string Subject { get; set; }
7 | public string Body { get; set; }
8 | public string From { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Application/Requests/PagedRequest.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Requests
2 | {
3 | public abstract class PagedRequest
4 | {
5 | public int PageSize { get; set; }
6 | public int PageNumber { get; set; }
7 |
8 | public string[] Orderby { get; set; }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Application/Requests/UploadRequest.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Enums;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Requests
4 | {
5 | public class UploadRequest
6 | {
7 | public string FileName { get; set; }
8 | public string Extension { get; set; }
9 | public UploadType UploadType { get; set; }
10 | public byte[] Data { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Audit/AuditResponse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Responses.Audit
4 | {
5 | public class AuditResponse
6 | {
7 | public int Id { get; set; }
8 | public string UserId { get; set; }
9 | public string Type { get; set; }
10 | public string TableName { get; set; }
11 | public DateTime DateTime { get; set; }
12 | public string OldValues { get; set; }
13 | public string NewValues { get; set; }
14 | public string AffectedColumns { get; set; }
15 | public string PrimaryKey { get; set; }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Identity/ChatHistoryResponse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Responses.Identity
4 | {
5 | public partial class ChatHistoryResponse
6 | {
7 | public long Id { get; set; }
8 | public string FromUserId { get; set; }
9 | public string FromUserImageURL { get; set; }
10 | public string FromUserFullName { get; set; }
11 | public string ToUserId { get; set; }
12 | public string ToUserImageURL { get; set; }
13 | public string ToUserFullName { get; set; }
14 | public string Message { get; set; }
15 | public DateTime CreatedDate { get; set; }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Identity/ChatUserResponse.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Models.Chat;
2 | using System.Collections.Generic;
3 | using BlazorHero.CleanArchitecture.Application.Interfaces.Chat;
4 |
5 | namespace BlazorHero.CleanArchitecture.Application.Responses.Identity
6 | {
7 | public class ChatUserResponse
8 | {
9 | public string Id { get; set; }
10 | public string UserName { get; set; }
11 | public string ProfilePictureDataUrl { get; set; }
12 | public string FirstName { get; set; }
13 | public string LastName { get; set; }
14 | public string EmailAddress { get; set; }
15 | public bool IsOnline { get; set; }
16 | public virtual ICollection> ChatHistoryFromUsers { get; set; }
17 | public virtual ICollection> ChatHistoryToUsers { get; set; }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Identity/GetAllRolesResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Responses.Identity
4 | {
5 | public class GetAllRolesResponse
6 | {
7 | public IEnumerable Roles { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Identity/GetAllUsersResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Responses.Identity
4 | {
5 | public class GetAllUsersResponse
6 | {
7 | public IEnumerable Users { get; set; }
8 | }
9 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Identity/PermissionResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Responses.Identity
4 | {
5 | public class PermissionResponse
6 | {
7 | public string RoleId { get; set; }
8 | public string RoleName { get; set; }
9 | public List RoleClaims { get; set; }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Identity/RoleClaimResponse.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Responses.Identity
2 | {
3 | public class RoleClaimResponse
4 | {
5 | public int Id { get; set; }
6 | public string RoleId { get; set; }
7 | public string Type { get; set; }
8 | public string Value { get; set; }
9 | public string Description { get; set; }
10 | public string Group { get; set; }
11 | public bool Selected { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Identity/RoleResponse.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel.DataAnnotations;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Responses.Identity
4 | {
5 | public class RoleResponse
6 | {
7 | public string Id { get; set; }
8 |
9 | [Required]
10 | public string Name { get; set; }
11 | public string Description { get; set; }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Identity/TokenResponse.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Responses.Identity
4 | {
5 | public class TokenResponse
6 | {
7 | public string Token { get; set; }
8 | public string RefreshToken { get; set; }
9 | public string UserImageURL { get; set; }
10 | public DateTime RefreshTokenExpiryTime { get; set; }
11 | }
12 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Identity/UserResponse.cs:
--------------------------------------------------------------------------------
1 | namespace BlazorHero.CleanArchitecture.Application.Responses.Identity
2 | {
3 | public class UserResponse
4 | {
5 | public string Id { get; set; }
6 | public string UserName { get; set; }
7 | public string FirstName { get; set; }
8 | public string LastName { get; set; }
9 | public string Email { get; set; }
10 | public bool IsActive { get; set; } = true;
11 | public bool EmailConfirmed { get; set; }
12 | public string PhoneNumber { get; set; }
13 | public string ProfilePictureDataUrl { get; set; }
14 | }
15 | }
--------------------------------------------------------------------------------
/src/Application/Responses/Identity/UserRolesResponse.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace BlazorHero.CleanArchitecture.Application.Responses.Identity
4 | {
5 | public class UserRolesResponse
6 | {
7 | public List UserRoles { get; set; } = new();
8 | }
9 |
10 | public class UserRoleModel
11 | {
12 | public string RoleName { get; set; }
13 | public string RoleDescription { get; set; }
14 | public bool Selected { get; set; }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Application/Serialization/JsonConverters/TimespanJsonConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text.Json;
3 | using System.Text.Json.Serialization;
4 | using System.Text.RegularExpressions;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Serialization.JsonConverters
7 | {
8 | ///
9 | /// The new Json.NET doesn't support Timespan at this time
10 | /// https://github.com/dotnet/corefx/issues/38641
11 | ///
12 | public class TimespanJsonConverter : JsonConverter
13 | {
14 | ///
15 | /// Format: Days.Hours:Minutes:Seconds:Milliseconds
16 | ///
17 | public const string TimeSpanFormatString = @"d\.hh\:mm\:ss\:FFF";
18 |
19 | public override TimeSpan Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
20 | {
21 | var s = reader.GetString();
22 | if (string.IsNullOrWhiteSpace(s))
23 | {
24 | return TimeSpan.Zero;
25 | }
26 |
27 | if (!TimeSpan.TryParseExact(s, TimeSpanFormatString, null, out var parsedTimeSpan))
28 | {
29 | throw new FormatException($"Input timespan is not in an expected format : expected {Regex.Unescape(TimeSpanFormatString)}. Please retrieve this key as a string and parse manually.");
30 | }
31 |
32 | return parsedTimeSpan;
33 | }
34 |
35 | public override void Write(Utf8JsonWriter writer, TimeSpan value, JsonSerializerOptions options)
36 | {
37 | var timespanFormatted = $"{value.ToString(TimeSpanFormatString)}";
38 | writer.WriteStringValue(timespanFormatted);
39 | }
40 | }
41 | }
--------------------------------------------------------------------------------
/src/Application/Serialization/Options/SystemTextJsonOptions.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 | using BlazorHero.CleanArchitecture.Application.Interfaces.Serialization.Options;
3 |
4 | namespace BlazorHero.CleanArchitecture.Application.Serialization.Options
5 | {
6 | public class SystemTextJsonOptions : IJsonSerializerOptions
7 | {
8 | public JsonSerializerOptions JsonSerializerOptions { get; } = new();
9 | }
10 | }
--------------------------------------------------------------------------------
/src/Application/Serialization/Serializers/NewtonSoftJsonSerializer.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Interfaces.Serialization.Serializers;
2 | using BlazorHero.CleanArchitecture.Application.Serialization.Settings;
3 | using Microsoft.Extensions.Options;
4 | using Newtonsoft.Json;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Serialization.Serializers
7 | {
8 | public class NewtonSoftJsonSerializer : IJsonSerializer
9 | {
10 | private readonly JsonSerializerSettings _settings;
11 |
12 | public NewtonSoftJsonSerializer(IOptions settings)
13 | {
14 | _settings = settings.Value.JsonSerializerSettings;
15 | }
16 |
17 | public T Deserialize(string text)
18 | => JsonConvert.DeserializeObject(text, _settings);
19 |
20 | public string Serialize(T obj)
21 | => JsonConvert.SerializeObject(obj, _settings);
22 | }
23 | }
--------------------------------------------------------------------------------
/src/Application/Serialization/Serializers/SystemTextJsonSerializer.cs:
--------------------------------------------------------------------------------
1 | using System.Text.Json;
2 | using BlazorHero.CleanArchitecture.Application.Interfaces.Serialization.Serializers;
3 | using BlazorHero.CleanArchitecture.Application.Serialization.Options;
4 | using Microsoft.Extensions.Options;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Serialization.Serializers
7 | {
8 | public class SystemTextJsonSerializer : IJsonSerializer
9 | {
10 | private readonly JsonSerializerOptions _options;
11 |
12 | public SystemTextJsonSerializer(IOptions options)
13 | {
14 | _options = options.Value.JsonSerializerOptions;
15 | }
16 |
17 | public T Deserialize(string data)
18 | => JsonSerializer.Deserialize(data, _options);
19 |
20 | public string Serialize(T data)
21 | => JsonSerializer.Serialize(data, _options);
22 | }
23 | }
--------------------------------------------------------------------------------
/src/Application/Serialization/Settings/NewtonsoftJsonSettings.cs:
--------------------------------------------------------------------------------
1 |
2 | using BlazorHero.CleanArchitecture.Application.Interfaces.Serialization.Settings;
3 | using Newtonsoft.Json;
4 |
5 | namespace BlazorHero.CleanArchitecture.Application.Serialization.Settings
6 | {
7 | public class NewtonsoftJsonSettings : IJsonSerializerSettings
8 | {
9 | public JsonSerializerSettings JsonSerializerSettings { get; } = new();
10 | }
11 | }
--------------------------------------------------------------------------------
/src/Application/Specifications/Base/HeroSpecification.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq.Expressions;
4 | using BlazorHero.CleanArchitecture.Application.Extensions;
5 | using BlazorHero.CleanArchitecture.Domain.Contracts;
6 |
7 | namespace BlazorHero.CleanArchitecture.Application.Specifications.Base
8 | {
9 | public abstract class HeroSpecification : ISpecification where T : class, IEntity
10 | {
11 | public Expression> Criteria { get; set; }
12 | public List>> Includes { get; } = new();
13 | public List IncludeStrings { get; } = new();
14 |
15 | protected virtual void AddInclude(Expression> includeExpression)
16 | {
17 | Includes.Add(includeExpression);
18 | }
19 |
20 | protected virtual void AddInclude(string includeString)
21 | {
22 | IncludeStrings.Add(includeString);
23 | }
24 |
25 | public Expression> And(Expression> query)
26 | {
27 | return Criteria = Criteria == null ? query : Criteria.And(query);
28 | }
29 |
30 | public Expression> Or(Expression> query)
31 | {
32 | return Criteria = Criteria == null ? query : Criteria.Or(query);
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/Application/Specifications/Base/ISpecification.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq.Expressions;
4 | using BlazorHero.CleanArchitecture.Domain.Contracts;
5 |
6 | namespace BlazorHero.CleanArchitecture.Application.Specifications.Base
7 | {
8 | public interface ISpecification where T : class, IEntity
9 | {
10 | Expression> Criteria { get; }
11 | List>> Includes { get; }
12 | List IncludeStrings { get; }
13 | Expression> And(Expression> query);
14 | Expression> Or(Expression> query);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/Application/Specifications/Catalog/BrandFilterSpecification.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Specifications.Base;
2 | using BlazorHero.CleanArchitecture.Domain.Entities.Catalog;
3 |
4 | namespace BlazorHero.CleanArchitecture.Application.Specifications.Catalog
5 | {
6 | public class BrandFilterSpecification : HeroSpecification
7 | {
8 | public BrandFilterSpecification(string searchString)
9 | {
10 | if (!string.IsNullOrEmpty(searchString))
11 | {
12 | Criteria = p => p.Name.Contains(searchString) || p.Description.Contains(searchString);
13 | }
14 | else
15 | {
16 | Criteria = p => true;
17 | }
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/Application/Specifications/Catalog/ProductFilterSpecification.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Specifications.Base;
2 | using BlazorHero.CleanArchitecture.Domain.Entities.Catalog;
3 |
4 | namespace BlazorHero.CleanArchitecture.Application.Specifications.Catalog
5 | {
6 | public class ProductFilterSpecification : HeroSpecification
7 | {
8 | public ProductFilterSpecification(string searchString)
9 | {
10 | Includes.Add(a => a.Brand);
11 | if (!string.IsNullOrEmpty(searchString))
12 | {
13 | Criteria = p => p.Barcode != null && (p.Name.Contains(searchString) || p.Description.Contains(searchString) || p.Barcode.Contains(searchString) || p.Brand.Name.Contains(searchString));
14 | }
15 | else
16 | {
17 | Criteria = p => p.Barcode != null;
18 | }
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/Application/Specifications/Misc/DocumentFilterSpecification.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Specifications.Base;
2 | using BlazorHero.CleanArchitecture.Domain.Entities.Misc;
3 |
4 | namespace BlazorHero.CleanArchitecture.Application.Specifications.Misc
5 | {
6 | public class DocumentFilterSpecification : HeroSpecification
7 | {
8 | public DocumentFilterSpecification(string searchString, string userId)
9 | {
10 | if (!string.IsNullOrEmpty(searchString))
11 | {
12 | Criteria = p => (p.Title.Contains(searchString) || p.Description.Contains(searchString)) && (p.IsPublic == true || (p.IsPublic == false && p.CreatedBy == userId));
13 | }
14 | else
15 | {
16 | Criteria = p => (p.IsPublic == true || (p.IsPublic == false && p.CreatedBy == userId));
17 | }
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Application/Specifications/Misc/DocumentTypeFilterSpecification.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Specifications.Base;
2 | using BlazorHero.CleanArchitecture.Domain.Entities.Misc;
3 |
4 | namespace BlazorHero.CleanArchitecture.Application.Specifications.Misc
5 | {
6 | public class DocumentTypeFilterSpecification : HeroSpecification
7 | {
8 | public DocumentTypeFilterSpecification(string searchString)
9 | {
10 | if (!string.IsNullOrEmpty(searchString))
11 | {
12 | Criteria = p => p.Name.Contains(searchString) || p.Description.Contains(searchString);
13 | }
14 | else
15 | {
16 | Criteria = p => true;
17 | }
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/Application/Validators/Extensions/ValidatorExtensions.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Interfaces.Serialization.Serializers;
2 | using FluentValidation;
3 | using FluentValidation.Validators;
4 |
5 | namespace BlazorHero.CleanArchitecture.Application.Validators.Extensions
6 | {
7 | public static class ValidatorExtensions
8 | {
9 | public static IRuleBuilderOptions MustBeJson(this IRuleBuilder ruleBuilder, IPropertyValidator validator) where T : class
10 | {
11 | return ruleBuilder.SetValidator(validator);
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Application/Validators/Features/Brands/Commands/AddEdit/AddEditBrandCommandValidator.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Features.Brands.Commands.AddEdit;
2 | using FluentValidation;
3 | using Microsoft.Extensions.Localization;
4 |
5 | namespace BlazorHero.CleanArchitecture.Application.Validators.Features.Brands.Commands.AddEdit
6 | {
7 | public class AddEditBrandCommandValidator : AbstractValidator
8 | {
9 | public AddEditBrandCommandValidator(IStringLocalizer localizer)
10 | {
11 | RuleFor(request => request.Name)
12 | .Must(x => !string.IsNullOrWhiteSpace(x)).WithMessage(x => localizer["Name is required!"]);
13 | RuleFor(request => request.Description)
14 | .Must(x => !string.IsNullOrWhiteSpace(x)).WithMessage(x => localizer["Description is required!"]);
15 | RuleFor(request => request.Tax)
16 | .GreaterThan(0).WithMessage(x => localizer["Tax must be greater than 0"]);
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/Application/Validators/Features/DocumentTypes/Commands/AddEdit/AddEditDocumentTypeCommandValidator.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Features.DocumentTypes.Commands.AddEdit;
2 | using FluentValidation;
3 | using Microsoft.Extensions.Localization;
4 |
5 | namespace BlazorHero.CleanArchitecture.Application.Validators.Features.DocumentTypes.Commands.AddEdit
6 | {
7 | public class AddEditDocumentTypeCommandValidator : AbstractValidator
8 | {
9 | public AddEditDocumentTypeCommandValidator(IStringLocalizer localizer)
10 | {
11 | RuleFor(request => request.Name)
12 | .Must(x => !string.IsNullOrWhiteSpace(x)).WithMessage(x => localizer["Name is required!"]);
13 | RuleFor(request => request.Description)
14 | .Must(x => !string.IsNullOrWhiteSpace(x)).WithMessage(x => localizer["Description is required!"]);
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/Application/Validators/Features/Documents/Commands/AddEdit/AddEditDocumentCommandValidator.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Features.Documents.Commands.AddEdit;
2 | using FluentValidation;
3 | using Microsoft.Extensions.Localization;
4 |
5 | namespace BlazorHero.CleanArchitecture.Application.Validators.Features.Documents.Commands.AddEdit
6 | {
7 | public class AddEditDocumentCommandValidator : AbstractValidator
8 | {
9 | public AddEditDocumentCommandValidator(IStringLocalizer localizer)
10 | {
11 | RuleFor(request => request.Title)
12 | .Must(x => !string.IsNullOrWhiteSpace(x)).WithMessage(x => localizer["Title is required!"]);
13 | RuleFor(request => request.Description)
14 | .Must(x => !string.IsNullOrWhiteSpace(x)).WithMessage(x => localizer["Description is required!"]);
15 | RuleFor(request => request.DocumentTypeId)
16 | .GreaterThan(0).WithMessage(x => localizer["Document Type is required!"]);
17 | RuleFor(request => request.URL)
18 | .Must(x => !string.IsNullOrWhiteSpace(x)).WithMessage(x => localizer["File is required!"]);
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/Application/Validators/Features/ExtendedAttributes/Commands/AddEdit/AddEditDocumentExtendedAttributeCommandValidator.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Domain.Entities.ExtendedAttributes;
2 | using BlazorHero.CleanArchitecture.Domain.Entities.Misc;
3 | using Microsoft.Extensions.Localization;
4 |
5 | namespace BlazorHero.CleanArchitecture.Application.Validators.Features.ExtendedAttributes.Commands.AddEdit
6 | {
7 | public class AddEditDocumentExtendedAttributeCommandValidator : AddEditExtendedAttributeCommandValidator
8 | {
9 | public AddEditDocumentExtendedAttributeCommandValidator(IStringLocalizer localizer) : base(localizer)
10 | {
11 | // you can override the validation rules here
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/src/Application/Validators/Features/Products/Commands/AddEdit/AddEditProductCommandValidator.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Features.Products.Commands.AddEdit;
2 | using FluentValidation;
3 | using Microsoft.Extensions.Localization;
4 |
5 | namespace BlazorHero.CleanArchitecture.Application.Validators.Features.Products.Commands.AddEdit
6 | {
7 | public class AddEditProductCommandValidator : AbstractValidator
8 | {
9 | public AddEditProductCommandValidator(IStringLocalizer localizer)
10 | {
11 | RuleFor(request => request.Name)
12 | .Must(x => !string.IsNullOrWhiteSpace(x)).WithMessage(x => localizer["Name is required!"]);
13 | RuleFor(request => request.Barcode)
14 | .Must(x => !string.IsNullOrWhiteSpace(x)).WithMessage(x => localizer["Barcode is required!"]);
15 | RuleFor(request => request.Description)
16 | .Must(x => !string.IsNullOrWhiteSpace(x)).WithMessage(x => localizer["Description is required!"]);
17 | RuleFor(request => request.BrandId)
18 | .GreaterThan(0).WithMessage(x => localizer["Brand is required!"]);
19 | RuleFor(request => request.Rate)
20 | .GreaterThan(0).WithMessage(x => localizer["Rate must be greater than 0"]);
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/src/Application/Validators/JsonValidator.cs:
--------------------------------------------------------------------------------
1 | using BlazorHero.CleanArchitecture.Application.Interfaces.Serialization.Serializers;
2 | using FluentValidation;
3 | using FluentValidation.Validators;
4 |
5 | namespace BlazorHero.CleanArchitecture.Application.Validators
6 | {
7 | public class JsonValidator : PropertyValidator
8 | {
9 | private readonly IJsonSerializer _jsonSerializer;
10 |
11 | public JsonValidator(IJsonSerializer jsonSerializer)
12 | {
13 | _jsonSerializer = jsonSerializer;
14 | }
15 |
16 | public override string Name => "JsonValidator";
17 |
18 | public override bool IsValid(ValidationContext context, string value)
19 | {
20 | var isJson = true;
21 | value = value.Trim();
22 | try
23 | {
24 | _jsonSerializer.Deserialize