├── Src ├── Template.WebUI.Client │ ├── Shared │ │ ├── AccessDenied.razor │ │ ├── EmptyLayout.razor │ │ ├── TopBar.razor │ │ └── MainLayout.razor │ ├── wwwroot │ │ ├── appsettings.Development.json │ │ ├── favicon.ico │ │ ├── icon-512.png │ │ ├── fonts │ │ │ ├── BHoma.eot │ │ │ ├── BHoma.ttf │ │ │ ├── BHoma.woff │ │ │ ├── BHoma.woff2 │ │ │ ├── Aeonik-Bold.otf │ │ │ ├── Iran-Yekan.eot │ │ │ ├── Iran-Yekan.ttf │ │ │ ├── Iran-Yekan.woff │ │ │ ├── Aeonik-Light.otf │ │ │ ├── Aeonik-Medium.otf │ │ │ ├── Iran-Yekan.woff2 │ │ │ └── Aeonik-Regular.otf │ │ ├── appsettings.json │ │ ├── images │ │ │ ├── layout │ │ │ │ ├── 404.png │ │ │ │ ├── user.png │ │ │ │ ├── user-blue.png │ │ │ │ ├── ata-header-bg.jpg │ │ │ │ ├── ata_loading.png │ │ │ │ ├── ataairlines_main.png │ │ │ │ ├── ataairlines_white.png │ │ │ │ ├── logo-header-main.png │ │ │ │ ├── logo-header-white.png │ │ │ │ ├── home.svg │ │ │ │ ├── notifications-white.svg │ │ │ │ └── home-border.svg │ │ │ └── pages │ │ │ │ ├── login │ │ │ │ └── avatar.png │ │ │ │ ├── main │ │ │ │ └── ATA-logo.png │ │ │ │ └── workflow │ │ │ │ └── receive-reterive-workflow.jpeg │ │ ├── css │ │ │ ├── utils │ │ │ │ ├── _base.scss │ │ │ │ ├── _alertify-custom.scss │ │ │ │ └── _bit-custom.scss │ │ │ ├── pages │ │ │ │ ├── settings │ │ │ │ │ └── _roles-page.scss │ │ │ │ ├── food │ │ │ │ │ └── _tbz-food-menu-page.scss │ │ │ │ ├── dashboard │ │ │ │ │ └── _dashboard-page.scss │ │ │ │ └── report │ │ │ │ │ ├── _personnel-report-page.scss │ │ │ │ │ └── _report-statistical-page.scss │ │ │ ├── components │ │ │ │ ├── _Confirm.scss │ │ │ │ ├── _Loading.scss │ │ │ │ └── _Toast.scss │ │ │ ├── abstracts │ │ │ │ ├── _variables.scss │ │ │ │ ├── _functions.scss │ │ │ │ ├── _mixins.scss │ │ │ │ ├── _fonts.scss │ │ │ │ └── _responsive.scss │ │ │ └── site.scss │ │ ├── icons │ │ │ ├── dark_right_arrow.svg │ │ │ ├── pale_right_arrow.svg │ │ │ ├── arrow_down.svg │ │ │ ├── close.svg │ │ │ ├── toast │ │ │ │ ├── success-notif-icon.svg │ │ │ │ ├── error-notif-icon.svg │ │ │ │ ├── info-notif-icon.svg │ │ │ │ └── warning-notif-icon.svg │ │ │ ├── back.svg │ │ │ ├── close-white.svg │ │ │ ├── search.svg │ │ │ ├── close-menu.svg │ │ │ ├── report.svg │ │ │ ├── borrows_active.svg │ │ │ ├── borrows_inactive.svg │ │ │ ├── comment.svg │ │ │ ├── pen_gray.svg │ │ │ ├── pen_white.svg │ │ │ ├── folder-close.svg │ │ │ ├── home_active.svg │ │ │ ├── home_inactive.svg │ │ │ ├── request_active.svg │ │ │ ├── request_inactive.svg │ │ │ ├── dashboard_active.svg │ │ │ ├── dashboard_inactive.svg │ │ │ ├── samples_active.svg │ │ │ ├── samples_inactive.svg │ │ │ ├── curved_right_arrow.svg │ │ │ ├── role.svg │ │ │ ├── folder-open.svg │ │ │ ├── trash_gray.svg │ │ │ ├── trash_white.svg │ │ │ ├── add-circle.svg │ │ │ ├── logo_inverse.svg │ │ │ ├── customize.svg │ │ │ ├── logo_main.svg │ │ │ ├── import.svg │ │ │ ├── user.svg │ │ │ ├── export.svg │ │ │ └── my-foods.svg │ │ ├── manifest.json │ │ ├── service-worker.published.min.js │ │ ├── service-worker.js │ │ ├── service-worker.published.js │ │ └── ImageUrls.cs │ ├── compilerconfig.json │ ├── Contracts │ │ ├── IAppDataService.cs │ │ └── INotificationService.cs │ ├── Components │ │ ├── PageNotFound.razor │ │ ├── HeaderAddOrEdit.razor.cs │ │ ├── Confirm.razor │ │ ├── HeaderAddOrEdit.razor │ │ ├── Loading.razor │ │ ├── Confirm.razor.cs │ │ ├── Modal.razor.cs │ │ ├── Modal.razor │ │ ├── Toast.razor │ │ ├── TelerikComponents │ │ │ └── CustomDropDownListPopupSettings.cs │ │ ├── ConfirmDialog.razor.cs │ │ └── ConfirmDialog.razor │ ├── Enums │ │ ├── NotificationType.cs │ │ ├── OperationType.cs │ │ └── AlertifyPosition.cs │ ├── Models │ │ ├── HostClient.cs │ │ └── AppData.cs │ ├── ConfigureServices │ │ ├── BrokersInstaller.cs │ │ ├── TelerikInstaller.cs │ │ ├── ExcelWizardInstaller.cs │ │ ├── LoadingBarInstaller.cs │ │ ├── ClientAppSettingsInstaller.cs │ │ ├── ModalInstaller.cs │ │ ├── LocalStorageInstaller.cs │ │ ├── BitInstaller.cs │ │ ├── NotificationInstaller.cs │ │ ├── CacheInstaller.cs │ │ ├── HttpClientFactoryInstaller.cs │ │ ├── AutoRegisterDiInstaller.cs │ │ └── AuthInstaller.cs │ ├── compilerconfig.json.defaults │ ├── Extensions │ │ ├── NavigationManagerExtensions.cs │ │ ├── JsRuntimeExtensions.cs │ │ └── AuthStateTaskExtensions.cs │ ├── Implementations │ │ ├── AppDataService.cs │ │ └── NotificationService.cs │ ├── Properties │ │ └── launchSettings.json │ ├── App.razor │ ├── _Imports.razor │ ├── Pages │ │ ├── PageUrls.cs │ │ └── PageTitles.cs │ └── Program.cs ├── Template.WebUI.API │ ├── APIAssemblyEntryPoint.cs │ ├── IdentityServerCertificate.pfx │ ├── AppStartup.cs │ ├── appsettings.Production.json │ ├── appsettings.json │ ├── appsettings.Development.json │ ├── ConfigureServices │ │ ├── AppSettingsJsonInstaller.cs │ │ └── NamePatternRegisterInstaller.cs │ ├── Extensions │ │ ├── AppModuleExtensions.cs │ │ └── ATAExceptionToHttpErrorMapper.cs │ ├── Controllers │ │ └── Order │ │ │ └── OrderController.cs │ ├── ActionFilters │ │ ├── ATAExceptionHandlerFilterAttribute.cs │ │ └── ModelStateValidatorAttribute.cs │ ├── !app_offline.htm │ ├── Program.cs │ ├── web.config │ └── Properties │ │ └── launchSettings.json ├── Template.Application │ ├── ApplicationAssemblyEntryPoint.cs │ ├── Common │ │ ├── Mappings │ │ │ ├── MappingExtensions.cs │ │ │ └── OrderMapperProfile.cs │ │ ├── Contracts │ │ │ ├── IStringProvider.cs │ │ │ └── IInstaller.cs │ │ ├── Localization │ │ │ ├── Resources │ │ │ │ └── StringResourceType.cs │ │ │ ├── Attributes │ │ │ │ └── LocalizedRequiredAttribute.cs │ │ │ └── Extensions │ │ │ │ └── ValidationContextExtension.cs │ │ ├── PipelineBehaviours │ │ │ └── ValidationBehaviour.cs │ │ └── Implementations │ │ │ └── StringProvider.cs │ ├── Order │ │ ├── Queries │ │ │ ├── GetOrders │ │ │ │ └── GetOrdersQuery.cs │ │ │ └── GetUserLastOrder │ │ │ │ ├── GetUserLastOrderQuery.cs │ │ │ │ └── GetUserLastOrderQueryHandler.cs │ │ └── DTOs │ │ │ ├── GetOrdersQuery.cs │ │ │ └── OrderDto.cs │ ├── User │ │ └── Queries │ │ │ └── GetIdentityTokenById │ │ │ ├── GetIdentityTokenByIdQuery.cs │ │ │ ├── GetIdentityTokenByIdQueryHandler.cs │ │ │ └── GetIdentityTokenByIdQueryValidator.cs │ ├── ConfigureServices │ │ ├── Installers │ │ │ ├── AutoMapperInstaller.cs │ │ │ ├── FluentValidationInstaller.cs │ │ │ ├── MediatRInstaller.cs │ │ │ ├── AutoRegisterInstaller.cs │ │ │ └── LocalizationInstaller.cs │ │ └── ConfigureServicesExtension.cs │ ├── CurrentApp │ │ └── DTOs │ │ │ └── AppVersioningDto.cs │ └── Template.Application.csproj ├── Template.Infrastructure │ ├── Persistence │ │ ├── EF │ │ │ ├── DataSeeder.cs │ │ │ ├── Configuration │ │ │ │ ├── IdentityEFConfiguration.cs │ │ │ │ └── OrderEFConfiguration.cs │ │ │ ├── ATADbContext.cs │ │ │ └── Repository │ │ │ │ └── ATARepositoryReadOnly.cs │ │ └── DbObjects.cs │ ├── InfrastructureAssemblyEntryPoint.cs │ ├── Common │ │ └── Contracts │ │ │ └── IBitInstaller.cs │ ├── ConfigureServices │ │ ├── IdentityInstaller.cs │ │ ├── ATAInstaller.cs │ │ ├── LoggerInstaller.cs │ │ ├── ClientsInstaller.cs │ │ ├── NamePatternRegisterInstaller.cs │ │ └── DataAccessInstaller.cs │ ├── Identity │ │ └── IdentityClientsProvider.cs │ └── LogStore │ │ └── SeqLogStore.cs └── Template.Domain │ ├── Options │ ├── URLOptions.cs │ ├── ClientAppSettings.cs │ ├── ConnectionStringOptions.cs │ ├── AppSettings.cs │ ├── AuthOptions.cs │ └── ServerAppSettings.cs │ ├── Enums │ └── Order │ │ ├── ReferenceCity.cs │ │ ├── OrderOperation.cs │ │ └── OrderStatus.cs │ ├── Entities │ ├── ATAEntity.cs │ ├── Identity │ │ └── IdentityTokenEntity.cs │ └── Order │ │ └── OrderEntity.cs │ ├── GlobalUsings.cs │ ├── Shared │ ├── AppMetadata.cs │ ├── AppMessages.cs │ └── Claims.cs │ └── Template.Domain.csproj ├── .editorconfig ├── Tests ├── Domain.UnitTests │ ├── UnitTest1.cs │ └── Domain.UnitTests.csproj ├── Template.Domain.UnitTests │ ├── UnitTest1.cs │ └── Template.Domain.UnitTests.csproj ├── Template.Application.UnitTests │ ├── UnitTest1.cs │ └── Template.Application.UnitTests.csproj └── Template.Application.IntegrationTests │ ├── UnitTest1.cs │ └── Template.Application.IntegrationTests.csproj ├── BitConfig.json ├── Clean.bat ├── Directory.build.props ├── Architecture.txt ├── README.md └── azure-pipelines.yml /Src/Template.WebUI.Client/Shared/AccessDenied.razor: -------------------------------------------------------------------------------- 1 |

AccessDenied

-------------------------------------------------------------------------------- /Src/Template.WebUI.API/APIAssemblyEntryPoint.cs: -------------------------------------------------------------------------------- 1 | namespace Template.WebUI.API; 2 | 3 | public class APIAssemblyEntryPoint 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "ClientAppSettings": { 3 | "URLOptions": { 4 | 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.cs] 2 | 3 | # AsyncFixer03: Fire-and-forget async-void methods or delegates 4 | dotnet_diagnostic.AsyncFixer03.severity = suggestion 5 | -------------------------------------------------------------------------------- /Src/Template.Application/ApplicationAssemblyEntryPoint.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Application; 2 | 3 | public class ApplicationAssemblyEntryPoint 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /Src/Template.Infrastructure/Persistence/EF/DataSeeder.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Infrastructure.Persistence.EF; 2 | 3 | public static class DataSeeder 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/compilerconfig.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "outputFile": "wwwroot/css/site.css", 4 | "inputFile": "wwwroot/css/site.scss" 5 | } 6 | ] -------------------------------------------------------------------------------- /Src/Template.Domain/Options/URLOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Domain.Options; 2 | 3 | public class URLOptions 4 | { 5 | public string? AppURL { get; set; } 6 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Shared/EmptyLayout.razor: -------------------------------------------------------------------------------- 1 | @inherits LayoutComponentBase 2 | 3 |
4 |
5 | @Body 6 |
7 |
-------------------------------------------------------------------------------- /Src/Template.Application/Common/Mappings/MappingExtensions.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Application.Common.Mappings; 2 | 3 | public static class MappingExtensions 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /Src/Template.Infrastructure/InfrastructureAssemblyEntryPoint.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Infrastructure; 2 | 3 | public class InfrastructureAssemblyEntryPoint 4 | { 5 | 6 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icon-512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/icon-512.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/BHoma.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/BHoma.eot -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/BHoma.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/BHoma.ttf -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/BHoma.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/BHoma.woff -------------------------------------------------------------------------------- /Src/Template.Domain/Options/ClientAppSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Domain.Options; 2 | 3 | public class ClientAppSettings 4 | { 5 | public URLOptions? URLOptions { get; set; } 6 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.API/IdentityServerCertificate.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.API/IdentityServerCertificate.pfx -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ClientAppSettings": { 3 | "URLOptions": { 4 | "AppURL": "" //Set automatically in program.cs 5 | } 6 | } 7 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/BHoma.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/BHoma.woff2 -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/Aeonik-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/Aeonik-Bold.otf -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/Iran-Yekan.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/Iran-Yekan.eot -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/Iran-Yekan.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/Iran-Yekan.ttf -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/Iran-Yekan.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/Iran-Yekan.woff -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/404.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/layout/404.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/Aeonik-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/Aeonik-Light.otf -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/Aeonik-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/Aeonik-Medium.otf -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/Iran-Yekan.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/Iran-Yekan.woff2 -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/layout/user.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/fonts/Aeonik-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/fonts/Aeonik-Regular.otf -------------------------------------------------------------------------------- /Src/Template.Domain/Options/ConnectionStringOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Domain.Options; 2 | 3 | public class ConnectionStringOptions 4 | { 5 | public string? AppDbConnectionString { get; set; } 6 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Contracts/IAppDataService.cs: -------------------------------------------------------------------------------- 1 | namespace Template.WebUI.Client.Contracts; 2 | 3 | public interface IAppDataService 4 | { 5 | //Task> GetAllLocations(); 6 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/user-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/layout/user-blue.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/ata-header-bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/layout/ata-header-bg.jpg -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/ata_loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/layout/ata_loading.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/pages/login/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/pages/login/avatar.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/pages/main/ATA-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/pages/main/ATA-logo.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/utils/_base.scss: -------------------------------------------------------------------------------- 1 | @import '../abstracts/_variables.scss'; 2 | @import '../abstracts/_functions.scss'; 3 | @import '../abstracts/_responsive.scss'; 4 | @import '../abstracts/_mixins.scss'; -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/dark_right_arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/pale_right_arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/ataairlines_main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/layout/ataairlines_main.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/ataairlines_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/layout/ataairlines_white.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/logo-header-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/layout/logo-header-main.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/logo-header-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/layout/logo-header-white.png -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/PageNotFound.razor: -------------------------------------------------------------------------------- 1 |
2 | 3 |
-------------------------------------------------------------------------------- /Src/Template.Domain/Options/AppSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Domain.Options; 2 | 3 | public class AppSettings 4 | { 5 | public ServerAppSettings? Server { get; set; } 6 | 7 | public ClientAppSettings? Client { get; set; } 8 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/pages/settings/_roles-page.scss: -------------------------------------------------------------------------------- 1 | @import '../../utils/_base.scss'; 2 | 3 | .roles-page { 4 | 5 | .form-custom-wrapper { 6 | margin-bottom: rem(20px); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /Tests/Domain.UnitTests/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Domain.UnitTests 4 | { 5 | public class UnitTest1 6 | { 7 | [Fact] 8 | public void Test1() 9 | { 10 | 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/pages/workflow/receive-reterive-workflow.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/farshaddavoudi/BitWithCleanArchitectureTemplate/HEAD/Src/Template.WebUI.Client/wwwroot/images/pages/workflow/receive-reterive-workflow.jpeg -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/arrow_down.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Tests/Template.Domain.UnitTests/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Template.Domain.UnitTests 4 | { 5 | public class UnitTest1 6 | { 7 | [Fact] 8 | public void Test1() 9 | { 10 | 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Src/Template.Application/Common/Contracts/IStringProvider.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Application.Common.Contracts; 2 | 3 | public interface IStringProvider 4 | { 5 | string? Message(string messageStringsKey); 6 | 7 | string Exception(string exceptionStringsKey); 8 | } -------------------------------------------------------------------------------- /Src/Template.Application/Common/Localization/Resources/StringResourceType.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Application.Common.Localization.Resources 2 | { 3 | public enum StringResourceType 4 | { 5 | MessageStrings, 6 | 7 | ExceptionStrings 8 | } 9 | } -------------------------------------------------------------------------------- /Tests/Template.Application.UnitTests/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Template.Application.UnitTests 4 | { 5 | public class UnitTest1 6 | { 7 | [Fact] 8 | public void Test1() 9 | { 10 | 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Src/Template.Application/Common/Contracts/IInstaller.cs: -------------------------------------------------------------------------------- 1 | using Template.Domain.Options; 2 | 3 | namespace Template.Application.Common.Contracts; 4 | 5 | public interface IInstaller 6 | { 7 | void InstallServices(IServiceCollection services, AppSettings appSettings); 8 | } -------------------------------------------------------------------------------- /Src/Template.Application/Order/Queries/GetOrders/GetOrdersQuery.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | using Template.Application.Order.DTOs; 3 | 4 | namespace Template.Application.Order.Queries.GetOrders; 5 | 6 | public class GetOrdersQuery : IRequest> 7 | { 8 | 9 | } -------------------------------------------------------------------------------- /Src/Template.Application/Order/Queries/GetUserLastOrder/GetUserLastOrderQuery.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | using Template.Application.Order.DTOs; 3 | 4 | namespace Template.Application.Order.Queries.GetUserLastOrder; 5 | 6 | public record GetUserLastOrderQuery(int UserId) : IRequest; -------------------------------------------------------------------------------- /Tests/Template.Application.IntegrationTests/UnitTest1.cs: -------------------------------------------------------------------------------- 1 | using Xunit; 2 | 3 | namespace Template.Application.IntegrationTests 4 | { 5 | public class UnitTest1 6 | { 7 | [Fact] 8 | public void Test1() 9 | { 10 | 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Src/Template.Domain/Options/AuthOptions.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Domain.Options; 2 | 3 | public class AuthOptions 4 | { 5 | public string? MasterPassword { get; set; } 6 | 7 | public bool? EnableDirectLogin { get; set; } 8 | 9 | public bool? IsAppPublic { get; set; } 10 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Enums/NotificationType.cs: -------------------------------------------------------------------------------- 1 | namespace Template.WebUI.Client.Enums 2 | { 3 | public enum NotificationType 4 | { 5 | Success, 6 | 7 | Error, 8 | 9 | Message, 10 | 11 | Notify, 12 | 13 | Warning 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Src/Template.Domain/Enums/Order/ReferenceCity.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Template.Domain.Enums.Order; 4 | 5 | public enum ReferenceCity 6 | { 7 | [Display(Name = "تهران")] 8 | Tehran = 1, 9 | 10 | [Display(Name = "تبریز")] 11 | Tabriz = 2 12 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/pages/food/_tbz-food-menu-page.scss: -------------------------------------------------------------------------------- 1 | @import '../../utils/_base.scss'; 2 | 3 | .change-mode-wrapper { 4 | display: flex; 5 | margin-left: rem(19px); 6 | flex-direction: row-reverse; 7 | 8 | > button { 9 | width: rem(140px); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/HeaderAddOrEdit.razor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Template.WebUI.Client.Components 4 | { 5 | public partial class HeaderAddOrEdit 6 | { 7 | [Parameter] 8 | public RenderFragment ChildContent { get; set; } 9 | } 10 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/components/_Confirm.scss: -------------------------------------------------------------------------------- 1 | @import '../utils/_base.scss'; 2 | 3 | .confirm-component { 4 | 5 | .buttons-wrapper { 6 | text-align: left; 7 | margin-top: 2rem; 8 | } 9 | 10 | .confirm-button { 11 | margin-left: 0.6rem; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Src/Template.Domain/Options/ServerAppSettings.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Domain.Options; 2 | 3 | public class ServerAppSettings 4 | { 5 | public ConnectionStringOptions? ConnectionStringOptions { get; set; } 6 | 7 | public URLOptions? URLOptions { get; set; } 8 | 9 | public AuthOptions? AuthOptions { get; set; } 10 | } -------------------------------------------------------------------------------- /Src/Template.Domain/Entities/ATAEntity.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Model.Entities.Contracts; 2 | using Bit.Model.Contracts; 3 | 4 | namespace Template.Domain.Entities; 5 | 6 | public abstract class ATAEntity : IATAMiniEntity, IArchivableEntity 7 | { 8 | public int Id { get; set; } 9 | 10 | public bool IsArchived { get; set; } 11 | } -------------------------------------------------------------------------------- /Src/Template.Domain/GlobalUsings.cs: -------------------------------------------------------------------------------- 1 | //global using CleanArchitecture.Domain.Common; 2 | //global using CleanArchitecture.Domain.Entities; 3 | //global using CleanArchitecture.Domain.Enums; 4 | //global using CleanArchitecture.Domain.Events; 5 | //global using CleanArchitecture.Domain.Exceptions; 6 | //global using CleanArchitecture.Domain.ValueObjects; -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/home.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/notifications-white.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Src/Template.Application/User/Queries/GetIdentityTokenById/GetIdentityTokenByIdQuery.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Template.Domain.Entities.Identity; 4 | 5 | namespace Template.Application.DTOs; 6 | 7 | [ComplexType] 8 | public record GetIdentityTokenByIdQuery(int Id) : IRequest; -------------------------------------------------------------------------------- /Src/Template.WebUI.API/AppStartup.cs: -------------------------------------------------------------------------------- 1 | using Bit.Core.Contracts; 2 | using Bit.OData.Contracts; 3 | using Bit.Owin; 4 | using Template.WebUI.API; 5 | 6 | [assembly: ODataModule("TemplateRoute")] 7 | [assembly: AppModule(typeof(AppModules))] 8 | 9 | namespace Template.WebUI.API; 10 | 11 | public class AppStartup : AspNetCoreAppStartup 12 | { 13 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/images/layout/home-border.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Models/HostClient.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | 3 | namespace Template.WebUI.Client.Models 4 | { 5 | public class HostClient 6 | { 7 | public HttpClient Client { get; } 8 | 9 | public HostClient(HttpClient client) 10 | { 11 | Client = client; 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Src/Template.Domain/Enums/Order/OrderOperation.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Template.Domain.Enums.Order; 4 | 5 | public enum OrderOperation 6 | { 7 | [Display(Name = "ثبت")] 8 | Add = 0, 9 | 10 | [Display(Name = "ویرایش")] 11 | Update = 1, 12 | 13 | [Display(Name = "حذف")] 14 | Delete = 2 15 | } 16 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.Infrastructure/Common/Contracts/IBitInstaller.cs: -------------------------------------------------------------------------------- 1 | using Bit.Core.Contracts; 2 | using Template.Domain.Options; 3 | 4 | namespace Template.Infrastructure.Common.Contracts; 5 | 6 | public interface IBitInstaller 7 | { 8 | void InstallServices(IServiceCollection services, 9 | IDependencyManager dependencyManager, 10 | AppSettings appSettings); 11 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/Confirm.razor: -------------------------------------------------------------------------------- 1 |
2 | @ConfirmationMessage 3 |
4 | 5 |
6 | 7 |
8 | 9 | 10 | 11 |
12 | 13 |
-------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Shared/TopBar.razor: -------------------------------------------------------------------------------- 1 | 2 |
3 |
@PageName
4 |
@PageDescription
5 |
6 | 7 | @code 8 | { 9 | [Parameter] 10 | public string PageName { get; set; } 11 | 12 | [Parameter] 13 | public string PageDescription { get; set; } 14 | } 15 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/toast/success-notif-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "سامانه‌ی انتخاب غذای آتا", 3 | "short_name": "انتخاب غذای آتا", 4 | "start_url": "./", 5 | "display": "standalone", 6 | "background_color": "#ffffff", 7 | "theme_color": "#03173d", 8 | "icons": [ 9 | { 10 | "src": "icon-512.png", 11 | "type": "image/png", 12 | "sizes": "512x512" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Enums/OperationType.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Template.WebUI.Client.Enums; 4 | 5 | public enum OperationType 6 | { 7 | Nothing, 8 | 9 | [Display(Name = "افزودن")] 10 | Add, 11 | 12 | [Display(Name = "فیلتر")] 13 | Edit, 14 | 15 | [Display(Name = "فیلتر")] 16 | Filter, 17 | 18 | Custom1, 19 | 20 | Custom2 21 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/pages/dashboard/_dashboard-page.scss: -------------------------------------------------------------------------------- 1 | @import '../../utils/_base.scss'; 2 | 3 | .dashboard-page { 4 | 5 | .dashboard-grid-operation-wrapper { 6 | text-align: end; 7 | padding: rem(10px); 8 | background-color: $white-four; 9 | 10 | } 11 | 12 | .k-tabstrip-content, .k-tabstrip > .k-content { 13 | border : none; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/service-worker.published.min.js: -------------------------------------------------------------------------------- 1 | "use strict";self.assetsInclude=[/\.svg$/,/FabExMDL*/];self.assetsExclude=[/\.scp\.css$/,/bit\.blazorui\.cupertino\.min\.css$/,/bit\.blazorui\.cupertino\.css$/,/bit\.blazorui\.fluent\.min\.css$/,/bit\.blazorui\.fluent\.css$/,/bit\.blazorui\.material\.min\.css$/,/bit\.blazorui\.material\.css$/];self.defaultUrl="/";self.importScripts("_content/Bit.Tooling.Bswup/bit-bswup.sw.js"); -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/BrokersInstaller.cs: -------------------------------------------------------------------------------- 1 | using ATA.Broker.SSOSecurity; 2 | using Template.Application.Common.Contracts; 3 | using Template.Domain.Options; 4 | 5 | namespace Template.WebUI.Client.ConfigureServices; 6 | 7 | public class BrokersInstaller : IInstaller 8 | { 9 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 10 | { 11 | services.AddATASSOClient(); 12 | } 13 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/TelerikInstaller.cs: -------------------------------------------------------------------------------- 1 | using Template.Application.Common.Contracts; 2 | using Template.Domain.Options; 3 | 4 | namespace Template.WebUI.Client.ConfigureServices 5 | { 6 | public class TelerikInstaller : IInstaller 7 | { 8 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 9 | { 10 | services.AddTelerikBlazor(); 11 | } 12 | } 13 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/compilerconfig.json.defaults: -------------------------------------------------------------------------------- 1 | { 2 | "compilers": { 3 | "sass": { 4 | "autoPrefix": "", 5 | "loadPaths": [], 6 | "style": 0, 7 | "precision": 10, 8 | "quiet": true, 9 | "quietDeps": true, 10 | "sourceMap": false 11 | } 12 | }, 13 | "minifiers": { 14 | "css": { 15 | "enabled": true, 16 | "termSemicolons": true, 17 | "gzip": false 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/ExcelWizardInstaller.cs: -------------------------------------------------------------------------------- 1 | using ExcelWizard; 2 | using Template.Application.Common.Contracts; 3 | using Template.Domain.Options; 4 | 5 | namespace Template.WebUI.Client.ConfigureServices; 6 | 7 | public class ExcelWizardInstaller : IInstaller 8 | { 9 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 10 | { 11 | services.AddExcelWizardServices(true); 12 | } 13 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.API/appsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | // (Server)AppSettings 3 | "ServerAppSettings": { 4 | "ConnectionStringOptions": { 5 | 6 | }, 7 | 8 | "URLOptions": { 9 | "AppURL": "https://food.app.ataair.ir" 10 | }, 11 | 12 | "AuthOptions": { 13 | "MasterPassword": "fsrnfata!", 14 | "EnableDirectLogin": true, 15 | "IsAppPublic": true //Meaning it is available to all users 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/abstracts/_variables.scss: -------------------------------------------------------------------------------- 1 | /// Global Variables 2 | @import '_colors.scss'; 3 | 4 | // Colors 5 | $themeMainColor: $ATARed; // e.g. #403d7d 6 | $themeLightColor: $ATARed; // e.g. #6a679a 7 | $themeDarkColor: $ATADarkRed; // e.g. #2B2867 8 | $themeGridColor: $pale-chestnut; 9 | 10 | // Fonts 11 | $fontPrimary: aeonik-regular, iranyekan; 12 | $fontPrimaryLight: aeonik-light, iranyekan; 13 | $fontBHoma: bhoma, iranyekan; 14 | 15 | 16 | -------------------------------------------------------------------------------- /Src/Template.WebUI.API/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "Data": { 3 | "DbIsolationLevel": "ReadCommitted" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | }, 12 | "AllowedHosts": "*", 13 | "IdentityCertificatePassword": "P@ssw0rd", 14 | 15 | // (Server)AppSettings 16 | "ServerAppSettings": { 17 | 18 | 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/toast/error-notif-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Src/Template.Application/ConfigureServices/Installers/AutoMapperInstaller.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using Template.Application.Common.Contracts; 3 | using Template.Domain.Options; 4 | 5 | namespace Template.Application.ConfigureServices.Installers; 6 | 7 | public class AutoMapperInstaller : IInstaller 8 | { 9 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 10 | { 11 | services.AddAutoMapper(Assembly.GetExecutingAssembly()); 12 | } 13 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/toast/info-notif-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/utils/_alertify-custom.scss: -------------------------------------------------------------------------------- 1 | @import '_base.scss'; 2 | 3 | .alertify-notifier { 4 | border: 0; 5 | font-family: $fontPrimary; 6 | 7 | &.ajs-center { 8 | left: 62.5%; 9 | } 10 | 11 | .ajs-message { 12 | background-color: $themeMainColor; 13 | color: $white; 14 | text-shadow: -0.5px -0.5px 0 #232e3c; 15 | } 16 | } 17 | 18 | .validation-message { 19 | margin-top: rem(5px); 20 | color: $error-red; 21 | } 22 | -------------------------------------------------------------------------------- /BitConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "BitCodeGeneratorConfigs": { 3 | "BitCodeGeneratorMappings": [ 4 | { 5 | "GenerationType": "CSharpHttpClient", 6 | "Route": "Food", 7 | "DestinationFileName": "Bit\\ATA.Food.Model.Context", 8 | "SourceProjects": [ 9 | { 10 | "Name": "ATA.Food.Server.Api" 11 | } 12 | ], 13 | "DestinationProject": { 14 | "Name": "ATA.Food.Client.Web" 15 | } 16 | } 17 | ] 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/LoadingBarInstaller.cs: -------------------------------------------------------------------------------- 1 | using Template.Application.Common.Contracts; 2 | using Template.Domain.Options; 3 | using Toolbelt.Blazor.Extensions.DependencyInjection; 4 | 5 | namespace Template.WebUI.Client.ConfigureServices 6 | { 7 | public class LoadingBarInstaller : IInstaller 8 | { 9 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 10 | { 11 | services.AddLoadingBar(); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Src/Template.Application/Common/Mappings/OrderMapperProfile.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using Template.Application.Order.DTOs; 3 | using Template.Domain.Entities.Order; 4 | 5 | namespace Template.Application.Common.Mappings; 6 | 7 | public class OrderMapperProfile : Profile 8 | { 9 | public OrderMapperProfile() 10 | { 11 | CreateMap() 12 | .ForMember(dto => dto.OrderStatus, config => 13 | config.MapFrom(entity => (int)entity.OrderStatus)); 14 | } 15 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/ClientAppSettingsInstaller.cs: -------------------------------------------------------------------------------- 1 | using Template.Application.Common.Contracts; 2 | using Template.Domain.Options; 3 | 4 | namespace Template.WebUI.Client.ConfigureServices; 5 | 6 | public class ClientAppSettingsInstaller : IInstaller 7 | { 8 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 9 | { 10 | // Directly with injecting ClientAppSettings class 11 | services.AddSingleton(serviceProvider => appSettings); 12 | } 13 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/ModalInstaller.cs: -------------------------------------------------------------------------------- 1 | using Blazored.Modal; 2 | using Template.Application.Common.Contracts; 3 | using Template.Domain.Options; 4 | 5 | namespace Template.WebUI.Client.ConfigureServices 6 | { 7 | public class ModalInstaller : IInstaller 8 | { 9 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 10 | { 11 | // https://github.com/Blazored/Modal 12 | services.AddBlazoredModal(); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.API/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | // (Server)AppSettings 3 | "ServerAppSettings": { 4 | "ConnectionStringOptions": { 5 | //"AppDbConnectionString": "Data Source=.;Initial Catalog=ATACatering;Integrated Security=True;" 6 | }, 7 | 8 | "URLOptions": { 9 | "AppURL": "localhost:5001" 10 | }, 11 | 12 | "AuthOptions": { 13 | "MasterPassword": "ata!", 14 | "EnableDirectLogin": true, 15 | "IsAppPublic": true //Meaning it is available to all users 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Src/Template.Application/ConfigureServices/Installers/FluentValidationInstaller.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using System.Reflection; 3 | using Template.Application.Common.Contracts; 4 | using Template.Domain.Options; 5 | 6 | namespace Template.Application.ConfigureServices.Installers; 7 | 8 | public class FluentValidationInstaller : IInstaller 9 | { 10 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 11 | { 12 | services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly()); 13 | } 14 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/service-worker.js: -------------------------------------------------------------------------------- 1 | self.assetsInclude = [ 2 | /\.svg$/, 3 | /FabExMDL*/ 4 | ]; 5 | 6 | self.assetsExclude = [ 7 | /\.scp\.css$/, 8 | /bit\.blazorui\.cupertino\.min\.css$/, 9 | /bit\.blazorui\.cupertino\.css$/, 10 | /bit\.blazorui\.fluent\.min\.css$/, 11 | /bit\.blazorui\.fluent\.css$/, 12 | /bit\.blazorui\.material\.min\.css$/, 13 | /bit\.blazorui\.material\.css$/ 14 | ]; 15 | 16 | self.defaultUrl = "/"; 17 | 18 | self.importScripts('_content/Bit.Tooling.Bswup/bit-bswup.sw.js'); 19 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/LocalStorageInstaller.cs: -------------------------------------------------------------------------------- 1 | using Blazored.LocalStorage; 2 | using Template.Application.Common.Contracts; 3 | using Template.Domain.Options; 4 | 5 | 6 | namespace Template.WebUI.Client.ConfigureServices 7 | { 8 | public class LocalStorageInstaller : IInstaller 9 | { 10 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 11 | { 12 | // https://github.com/Blazored/LocalStorage 13 | services.AddBlazoredLocalStorage(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Src/Template.Domain/Shared/AppMetadata.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace Template.Domain.Shared; 4 | 5 | public static class AppMetadata 6 | { 7 | public static readonly string AppVersion = Assembly.GetExecutingAssembly().GetName().Version!.ToString(3); 8 | 9 | public static readonly string SSOAppName = "food"; 10 | 11 | public static readonly string PersianFullName = "سامانه‌ی انتخاب غذای آتا"; 12 | 13 | public static readonly string EnglishFullName = "ATA Food"; 14 | 15 | public static readonly string SolutionName = "ATA.Food"; 16 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/back.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Enums/AlertifyPosition.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Template.WebUI.Client.Enums; 4 | 5 | public enum AlertifyPosition 6 | { 7 | [Display(Name = "top-right")] 8 | TopRight, 9 | 10 | [Display(Name = "top-center")] 11 | TopCenter, 12 | 13 | [Display(Name = "top-left")] 14 | TopLeft, 15 | 16 | [Display(Name = "bottom-right")] 17 | BottomRight, 18 | 19 | [Display(Name = "bottom-center")] 20 | BottomCenter, 21 | 22 | [Display(Name = "bottom-left")] 23 | BottomLeft 24 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.API/ConfigureServices/AppSettingsJsonInstaller.cs: -------------------------------------------------------------------------------- 1 | using Bit.Core.Contracts; 2 | using Template.Domain.Options; 3 | using Template.Infrastructure.Common.Contracts; 4 | 5 | namespace Template.WebUI.API.ConfigureServices; 6 | 7 | public class AppSettingsJsonInstaller : IBitInstaller 8 | { 9 | public void InstallServices(IServiceCollection services, IDependencyManager dependencyManager, AppSettings appSettings) 10 | { 11 | // Register (Server)AppSettings as Singleton to easy use 12 | dependencyManager.RegisterInstance(appSettings); 13 | } 14 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/close-white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Src/Template.Infrastructure/ConfigureServices/IdentityInstaller.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Model.User.Contract; 2 | using Bit.Core.Contracts; 3 | using Template.Domain.Options; 4 | using Template.Infrastructure.Common.Contracts; 5 | using Template.Infrastructure.Identity; 6 | 7 | namespace Template.Infrastructure.ConfigureServices; 8 | 9 | public class IdentityInstaller : IBitInstaller 10 | { 11 | public void InstallServices(IServiceCollection services, IDependencyManager dependencyManager, AppSettings appSettings) 12 | { 13 | dependencyManager.Register(); 14 | } 15 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.API/Extensions/AppModuleExtensions.cs: -------------------------------------------------------------------------------- 1 | using Bit.Core.Contracts; 2 | using Template.WebUI.API.ActionFilters; 3 | 4 | namespace Template.WebUI.API.Extensions 5 | { 6 | public static class AppModuleExtensions 7 | { 8 | public static IDependencyManager RegisterModelStateValidator(this IDependencyManager dependencyManager) 9 | { 10 | dependencyManager.RegisterGlobalWebApiActionFiltersUsing(webApiConfig => 11 | webApiConfig.Filters.Add(new ModelStateValidatorAttribute())); 12 | 13 | return dependencyManager; 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/BitInstaller.cs: -------------------------------------------------------------------------------- 1 | using Bit.Http.Contracts; 2 | using Bit.Http.Implementations; 3 | using Template.Application.Common.Contracts; 4 | using Template.Domain.Options; 5 | 6 | namespace Template.WebUI.Client.ConfigureServices 7 | { 8 | public class BitInstaller : IInstaller 9 | { 10 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 11 | { 12 | services.AddScoped(); 13 | services.AddTransient(); 14 | } 15 | } 16 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/HeaderAddOrEdit.razor: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 5 |
6 | 7 |
8 | @AppMetadata.PersianFullName 9 |
10 | 11 |
12 |
13 | 14 |
15 |
@ChildContent
16 |
17 |
-------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/Loading.razor: -------------------------------------------------------------------------------- 1 | 2 | @**@ 3 | 4 |
5 |
6 |
7 |
8 | loader 9 |
10 |
11 | @*
Authorizing ...
*@ 12 |
13 |
14 |
-------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/abstracts/_functions.scss: -------------------------------------------------------------------------------- 1 | $html-font-size: 16px; 2 | 3 | /// stripUnit(10px) -> 10 4 | /// stripUnit(2em) -> 2 5 | /// stripUnit(3) -> 3 6 | @function stripUnit($value) { 7 | @if type-of($value) == 'number' and not unitless($value) { 8 | @return $value / ($value * 0 + 1); 9 | } 10 | @return $value; 11 | } 12 | 13 | /// Convert px to rem. 14 | @function rem($pxValue) { 15 | @return #{stripUnit($pxValue) / stripUnit($html-font-size)}rem; 16 | } 17 | 18 | /// Convert px to em. 19 | @function em($size, $base-font-size: 16px) { 20 | @return stripUnit($size) / stripUnit($base-font-size) * 1em; 21 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/NotificationInstaller.cs: -------------------------------------------------------------------------------- 1 | using Blazored.Toast; 2 | using Template.Application.Common.Contracts; 3 | using Template.Domain.Options; 4 | using Template.WebUI.Client.Contracts; 5 | using Template.WebUI.Client.Implementations; 6 | 7 | namespace Template.WebUI.Client.ConfigureServices; 8 | 9 | public class NotificationInstaller : IInstaller 10 | { 11 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 12 | { 13 | //https://github.com/Blazored/Toast 14 | services.AddBlazoredToast(); 15 | 16 | services.AddTransient(); 17 | } 18 | } -------------------------------------------------------------------------------- /Clean.bat: -------------------------------------------------------------------------------- 1 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S bin') DO RMDIR /S /Q "%%G" 2 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S obj') DO RMDIR /S /Q "%%G" 3 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S node_modules') DO RMDIR /S /Q "%%G" 4 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S Packages') DO RMDIR /S /Q "%%G" 5 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S .vs') DO RMDIR /S /Q "%%G" 6 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S TestResults') DO RMDIR /S /Q "%%G" 7 | FOR /F "tokens=*" %%G IN ('DIR /B /AD /S AppPackages') DO RMDIR /S /Q "%%G" 8 | DEL /Q /F /S "Resource.designer.cs" 9 | DEL /Q /F /S "*.csproj.user" 10 | DEL /Q /F /S "*.Model.Context.d.ts" 11 | DEL /Q /F /S "*.Model.Context.js" -------------------------------------------------------------------------------- /Src/Template.Application/Order/DTOs/GetOrdersQuery.cs: -------------------------------------------------------------------------------- 1 | using DNTPersianUtils.Core; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | 4 | namespace Template.Application.Order.DTOs; 5 | 6 | [ComplexType] 7 | public class GetOrdersQuery 8 | { 9 | public int? CityId { get; set; } //Null means user my-foods report 10 | 11 | public bool IsUserMyFoodsReport => CityId is null; 12 | 13 | public string? SearchTerm { get; set; } 14 | 15 | [ValidPersianDateTime(ErrorMessage = "فرمت تاریخ شمسی معتبر نیست")] 16 | public string? JalaliDate { get; set; } 17 | 18 | public IEnumerable? Locations { get; set; } 19 | 20 | public string? Unit { get; set; } 21 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Models/AppData.cs: -------------------------------------------------------------------------------- 1 | namespace Template.WebUI.Client.Models 2 | { 3 | public class AppData 4 | { 5 | //private List? _locations = new(); 6 | //public List Locations 7 | //{ 8 | // get => _locations ?? new List(); 9 | // set 10 | // { 11 | // _locations = value; 12 | // NotifyDataChanged(); 13 | // } 14 | //} 15 | 16 | public string? UserProfileImageUrl { get; set; } 17 | 18 | 19 | public event Action? OnChange; 20 | private void NotifyDataChanged() => OnChange?.Invoke(); 21 | } 22 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/CacheInstaller.cs: -------------------------------------------------------------------------------- 1 | using Template.Application.Common.Contracts; 2 | using Template.Domain.Options; 3 | using Template.WebUI.Client.Models; 4 | 5 | namespace Template.WebUI.Client.ConfigureServices 6 | { 7 | public class CacheInstaller : IInstaller 8 | { 9 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 10 | { 11 | // Singleton cash using by directly injecting AppData into a class 12 | var appCache = new AppData(); 13 | 14 | services.AddSingleton(sp => appCache); 15 | 16 | //services.AddTransient(); 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /Src/Template.Infrastructure/Persistence/EF/Configuration/IdentityEFConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Template.Domain.Entities.Identity; 4 | 5 | namespace Template.Infrastructure.Persistence.EF.Configuration; 6 | 7 | public class IdentityEFConfiguration : IEntityTypeConfiguration 8 | { 9 | public void Configure(EntityTypeBuilder builder) 10 | { 11 | // Table 12 | builder.ToTable("IdentityTokens"); 13 | 14 | builder.HasKey(t => t.Id); 15 | 16 | // Props 17 | builder.Property(b => b.ClientName).IsRequired().HasMaxLength(100); 18 | } 19 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/close-menu.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Src/Template.Domain/Entities/Identity/IdentityTokenEntity.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Domain.Entities.Identity; 2 | 3 | public class IdentityTokenEntity : ATAEntity 4 | { 5 | public new int Id { get; set; } 6 | 7 | public string? ClientName { get; set; } 8 | 9 | public DateTimeOffset ExpiresAt { get; set; } 10 | 11 | public DateTimeOffset CreatedAt { get; set; } 12 | 13 | public DateTimeOffset ModifiedAt { get; set; } 14 | 15 | public int UserId { get; set; } 16 | 17 | public string? IPAddress { get; set; } 18 | 19 | public string? DeviceName { get; set; } 20 | 21 | public override string ToString() 22 | { 23 | return $"{nameof(ClientName)}: {ClientName}, UserId: {UserId}"; 24 | } 25 | } -------------------------------------------------------------------------------- /Src/Template.Infrastructure/ConfigureServices/ATAInstaller.cs: -------------------------------------------------------------------------------- 1 | using ATA.Broker.CDN; 2 | using ATA.Broker.SSOSecurity; 3 | using ATA.Broker.Workflow; 4 | using ATABit.Data; 5 | using Bit.Core.Contracts; 6 | using Template.Domain.Options; 7 | using Template.Infrastructure.Common.Contracts; 8 | 9 | namespace Template.Infrastructure.ConfigureServices; 10 | 11 | public class ATAInstaller : IBitInstaller 12 | { 13 | public void InstallServices(IServiceCollection services, IDependencyManager dependencyManager, AppSettings appSettings) 14 | { 15 | services.AddATABitDataAccess(); 16 | 17 | services.AddATACDN(); 18 | 19 | services.AddATASSOClient(); 20 | 21 | services.AddATAWorkflowClient(); 22 | } 23 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Extensions/NavigationManagerExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Specialized; 2 | using System.Web; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Template.WebUI.Client.Extensions; 6 | 7 | public static class NavigationManagerExtensions 8 | { 9 | public static NameValueCollection GetQueryStrings(this NavigationManager navigationManager) 10 | { 11 | return HttpUtility.ParseQueryString(new Uri(navigationManager.Uri).Query); 12 | } 13 | 14 | // get single querystring value with specified key 15 | public static string GetQueryString(this NavigationManager navigationManager, string key) 16 | { 17 | return navigationManager.GetQueryStrings()[key]; 18 | } 19 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/service-worker.published.js: -------------------------------------------------------------------------------- 1 | self.assetsInclude = []; 2 | self.assetsExclude = [/\.scp\.css$/]; 3 | self.defaultUrl = '/'; 4 | self.prohibitedUrls = []; 5 | self.assetsUrl = '/service-worker-assets.js'; 6 | 7 | // more about SRI (Subresource Integrity) here: https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity 8 | // online tool to generate integrity hash: https://www.srihash.org/ or https://laysent.github.io/sri-hash-generator/ 9 | // using only js to generate hash: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest 10 | self.externalAssets = [ 11 | { 12 | "url": "/" 13 | }, 14 | ]; 15 | 16 | self.importScripts('_content/Bit.Tooling.Bswup/bit-bswup.sw.js'); -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/report.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/HttpClientFactoryInstaller.cs: -------------------------------------------------------------------------------- 1 | using Template.Application.Common.Contracts; 2 | using Template.Domain.Options; 3 | using Template.WebUI.Client.Implementations; 4 | using Template.WebUI.Client.Models; 5 | 6 | namespace Template.WebUI.Client.ConfigureServices 7 | { 8 | public class HttpClientFactoryInstaller : IInstaller 9 | { 10 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 11 | { 12 | #region Host client 13 | 14 | services.AddScoped(serviceProvider => serviceProvider.GetService()!.Client); 15 | 16 | services.AddScoped(); 17 | 18 | #endregion 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/Confirm.razor.cs: -------------------------------------------------------------------------------- 1 | using Blazored.Modal; 2 | using Blazored.Modal.Services; 3 | using Microsoft.AspNetCore.Components; 4 | 5 | namespace Template.WebUI.Client.Components 6 | { 7 | public partial class Confirm 8 | { 9 | [Parameter] 10 | public string ConfirmationMessage { get; set; } = "آیا مطمئن هستید؟"; 11 | 12 | [CascadingParameter] 13 | private BlazoredModalInstance ConfirmModal { get; set; } 14 | 15 | private async Task OnConfirm() 16 | { 17 | await ConfirmModal.CloseAsync(ModalResult.Ok(true)); 18 | } 19 | 20 | private async Task OnCancel() 21 | { 22 | await ConfirmModal.CancelAsync(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Src/Template.Application/ConfigureServices/Installers/MediatRInstaller.cs: -------------------------------------------------------------------------------- 1 | using MediatR; 2 | using System.Reflection; 3 | using Template.Application.Common.Contracts; 4 | using Template.Application.Common.PipelineBehaviours; 5 | using Template.Domain.Options; 6 | 7 | namespace Template.Application.ConfigureServices.Installers; 8 | 9 | public class MediatRInstaller : IInstaller 10 | { 11 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 12 | { 13 | services.AddMediatR(Assembly.GetExecutingAssembly()); 14 | 15 | // MediatR Pipelines (Behaviours) 16 | // Pipelines order matter! Execute from top to bottom 17 | services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehaviour<,>)); 18 | } 19 | } -------------------------------------------------------------------------------- /Src/Template.Application/CurrentApp/DTOs/AppVersioningDto.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Helper.Extensions; 2 | using System.ComponentModel.DataAnnotations; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | 5 | namespace Template.Application.DTOs; 6 | 7 | [ComplexType] 8 | public class AppVersioningDto 9 | { 10 | public string? Version { get; set; } 11 | public int VersionNo => Version!.Replace(".", "").ToInt(); 12 | 13 | public string? Date { get; set; } 14 | 15 | public List Changes { get; set; } = new(); 16 | } 17 | 18 | [ComplexType] 19 | public class VersionChange 20 | { 21 | [Required(ErrorMessage = "Version Change Title Is Required")] 22 | public string? Title { get; set; } 23 | 24 | public List Description { get; set; } = new(); 25 | } -------------------------------------------------------------------------------- /Src/Template.Infrastructure/ConfigureServices/LoggerInstaller.cs: -------------------------------------------------------------------------------- 1 | using Bit.Core.Contracts; 2 | using Bit.Owin.Implementations; 3 | using System.Reflection; 4 | using Template.Domain.Options; 5 | using Template.Infrastructure.Common.Contracts; 6 | using Template.Infrastructure.LogStore; 7 | 8 | namespace Template.Infrastructure.ConfigureServices; 9 | 10 | public class LoggerInstaller : IBitInstaller 11 | { 12 | public void InstallServices(IServiceCollection services, IDependencyManager dependencyManager, AppSettings appSettings) 13 | { 14 | dependencyManager.RegisterDefaultLogger(typeof(SeqLogStore).GetTypeInfo() 15 | #if DEBUG 16 | , typeof(DebugLogStore).GetTypeInfo() 17 | , typeof(ConsoleLogStore).GetTypeInfo() 18 | #endif 19 | ); 20 | } 21 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/borrows_active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/borrows_inactive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Src/Template.Domain/Shared/AppMessages.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Domain.Shared 2 | { 3 | public class AppMessages 4 | { 5 | public class Errors 6 | { 7 | public static string FoodIsDuplicate = "این غذا قبلا در سیستم ثبت شده است"; 8 | public static string FoodDeletionFailed = "مشکلی در حذف غذا وجود دارد"; 9 | public static string FoodUsedBefore = "از این غذا قبلا استفاده شده و امکان حذف آن وجود ندارد"; 10 | public static string FoodIdNotFound = "غذایی با این شناسه پیدا نشد"; 11 | } 12 | 13 | public class Success 14 | { 15 | public static string FoodAddedSuccessfully = "غذا با موفقیت ثبت شد"; 16 | public static string FoodDeletedSuccessfully = "غذا با موفقیت حذف شد"; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Src/Template.WebUI.API/Controllers/Order/OrderController.cs: -------------------------------------------------------------------------------- 1 | using Bit.OData.ODataControllers; 2 | using MediatR; 3 | using System.Web.Http; 4 | using Template.Application.Order.DTOs; 5 | using Template.Application.Order.Queries.GetUserLastOrder; 6 | 7 | namespace Template.WebUI.API.Controllers.Order; 8 | 9 | [AllowAnonymous] 10 | public class OrderController : DtoController 11 | { 12 | private readonly IMediator _mediator; 13 | 14 | public OrderController(IMediator mediator) 15 | { 16 | _mediator = mediator; 17 | } 18 | 19 | [Function] 20 | public async Task GetFirstOrder(int userId, CancellationToken cancellationToken) 21 | { 22 | var a = await _mediator.Send(new GetUserLastOrderQuery(userId), cancellationToken); 23 | 24 | return a; 25 | } 26 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/Modal.razor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | 3 | namespace Template.WebUI.Client.Components 4 | { 5 | public partial class Modal 6 | { 7 | [Parameter] 8 | public string Title { get; set; } 9 | 10 | [Parameter] 11 | public string Text { get; set; } 12 | 13 | [Parameter] 14 | public RenderFragment ChildContent { get; set; } 15 | 16 | public bool Visibility { get; set; } 17 | 18 | public void ToggleVisibility() 19 | { 20 | Visibility = !Visibility; 21 | } 22 | 23 | public void Show() 24 | { 25 | Visibility = true; 26 | } 27 | 28 | public void Hide() 29 | { 30 | Visibility = false; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Src/Template.Infrastructure/Persistence/DbObjects.cs: -------------------------------------------------------------------------------- 1 | namespace Template.Infrastructure.Persistence; 2 | 3 | public static class DbSchemas 4 | { 5 | public static readonly string ATA = nameof(ATA); 6 | public static readonly string ATAWorkflowDboSchema = "ATAWorkflow.dbo"; 7 | public static readonly string PardisWebDbDboSchema = "PardisWebDB.dbo"; 8 | } 9 | 10 | public static class DbViews 11 | { 12 | public static readonly string UsersView = nameof(UsersView); 13 | public static readonly string FoodMenu = nameof(FoodMenu); 14 | public static readonly string UserRolePairsView = nameof(UserRolePairsView); 15 | public static readonly string LocationView = nameof(LocationView); 16 | } 17 | 18 | public static class DbStoredProcedures 19 | { 20 | // public static readonly string SpName = nameof(SpName); 21 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/toast/warning-notif-icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Src/Template.WebUI.API/ActionFilters/ATAExceptionHandlerFilterAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | using System.Web.Http.Filters; 3 | using Bit.Owin.Contracts; 4 | using Bit.WebApi.ActionFilters; 5 | 6 | namespace Template.WebUI.API.ActionFilters; 7 | 8 | public class ATAExceptionHandlerFilterAttribute : ExceptionHandlerFilterAttribute 9 | { 10 | protected override HttpResponseMessage CreateErrorResponseMessage(HttpActionExecutedContext actionExecutedContext, IExceptionToHttpErrorMapper exceptionToHttpErrorMapper, Exception exception) 11 | { 12 | return new HttpResponseMessage 13 | { 14 | Content = new StringContent(exceptionToHttpErrorMapper.GetMessage(actionExecutedContext.Exception), Encoding.UTF8, "application/json"), 15 | StatusCode = exceptionToHttpErrorMapper.GetStatusCode(exception) 16 | }; 17 | } 18 | } -------------------------------------------------------------------------------- /Src/Template.Application/ConfigureServices/ConfigureServicesExtension.cs: -------------------------------------------------------------------------------- 1 | // ReSharper disable CheckNamespace 2 | 3 | using System.Reflection; 4 | using Template.Application.Common.Contracts; 5 | using Template.Domain.Options; 6 | 7 | namespace Microsoft.Extensions.DependencyInjection; 8 | 9 | public static class ConfigureServicesExtension 10 | { 11 | public static IServiceCollection AddApplicationServices(this IServiceCollection services, AppSettings appSettings) 12 | { 13 | var installers = Assembly.GetExecutingAssembly().GetExportedTypes() 14 | .Where(c => c.IsClass && !c.IsAbstract && c.IsPublic && typeof(IInstaller).IsAssignableFrom(c)) 15 | .Select(Activator.CreateInstance).Cast().ToList(); 16 | 17 | installers.ForEach(i => i.InstallServices(services, appSettings)); 18 | 19 | return services; 20 | } 21 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.API/!app_offline.htm: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 19 | 20 | 21 | 22 |
23 |

این سامانه در حال بروزرسانی است

24 |

لطفا چند دقیقه‌ی بعد مراجعه نمایید.

25 |
26 | 27 | -------------------------------------------------------------------------------- /Src/Template.Application/User/Queries/GetIdentityTokenById/GetIdentityTokenByIdQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Model.Data.Contracts; 2 | using MediatR; 3 | using Template.Domain.Entities.Identity; 4 | 5 | namespace Template.Application.DTOs; 6 | 7 | public class GetIdentityTokenByIdQueryHandler : IRequestHandler 8 | { 9 | private readonly IATARepository _identityTokenRepository; 10 | 11 | public GetIdentityTokenByIdQueryHandler(IATARepository identityTokenRepository) 12 | { 13 | _identityTokenRepository = identityTokenRepository; 14 | } 15 | 16 | public Task Handle(GetIdentityTokenByIdQuery request, CancellationToken cancellationToken) 17 | { 18 | return _identityTokenRepository.GetByIdAsync(request.Id, cancellationToken); 19 | } 20 | } -------------------------------------------------------------------------------- /Src/Template.Domain/Enums/Order/OrderStatus.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | 3 | namespace Template.Domain.Enums.Order; 4 | 5 | public enum OrderStatus 6 | { 7 | [Display(Name = "ثبت شده")] 8 | Confirmed = 0, 9 | 10 | [Display(Name = "حذف مستقیم توسط کاربر")] 11 | DeletedDirectlyByUser = 1, 12 | 13 | [Display(Name = "حذف بدلیل ویرایش غذا توسط کاربر")] 14 | DeletedBecauseOfFoodUpdateByUser = 2, 15 | 16 | [Display(Name = "حذف بدلیل تغییر برنامه غذایی")] 17 | DeletedBecauseOfGroupDeleteByCatering = 3, 18 | 19 | [Display(Name = "حذف بدلیل تغییر برنامه غذایی")] 20 | DeletedBecauseOfCalendarFoodChangeByCatering = 4 21 | } 22 | 23 | public static class OrderStatusExtensions 24 | { 25 | public static bool IsDelete(this OrderStatus orderStatus) 26 | { 27 | return orderStatus != OrderStatus.Confirmed; 28 | } 29 | } -------------------------------------------------------------------------------- /Src/Template.Application/Common/Localization/Attributes/LocalizedRequiredAttribute.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using ATA.Food.Shared.Localization.Resources.DataAnnotations; 3 | 4 | namespace Template.Application.Common.Localization.Attributes 5 | { 6 | public class LocalizedRequiredAttribute : RequiredAttribute 7 | { 8 | public LocalizedRequiredAttribute() 9 | { 10 | ErrorMessageResourceType = typeof(DataAnnotationStrings); 11 | ErrorMessageResourceName = nameof(DataAnnotationStrings.RequiredAttribute_ValidationError); 12 | } 13 | 14 | public LocalizedRequiredAttribute(string dataAnnotationStringsResourceKey) 15 | { 16 | ErrorMessageResourceType = typeof(DataAnnotationStrings); 17 | ErrorMessageResourceName = dataAnnotationStringsResourceKey; 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.API/Program.cs: -------------------------------------------------------------------------------- 1 | using Bit.Core; 2 | using Bit.Owin; 3 | using Bit.Owin.Implementations; 4 | 5 | namespace Template.WebUI.API; 6 | 7 | public class Program 8 | { 9 | public static Task Main(string[] args) 10 | { 11 | AssemblyContainer.Current.Init(); 12 | 13 | AssemblyContainer.Current.AddAppAssemblies(typeof(Program).Assembly); 14 | 15 | AspNetCoreAppEnvironmentsProvider.Current.Use(); 16 | 17 | return CreateHostBuilder(args) 18 | .Build() 19 | .RunAsync(); 20 | } 21 | 22 | public static IHostBuilder CreateHostBuilder(string[] args) => 23 | BitWebHost.CreateWebHost(args) 24 | .ConfigureWebHostDefaults(webHostBuilder => 25 | { 26 | #if Development 27 | webHostBuilder.UseUrls("http://*:5000/", "https://*:5001/"); 28 | #endif 29 | }); 30 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Implementations/AppDataService.cs: -------------------------------------------------------------------------------- 1 | using System.Net.Http; 2 | using Template.WebUI.Client.Contracts; 3 | using Template.WebUI.Client.Models; 4 | 5 | namespace Template.WebUI.Client.Implementations; 6 | 7 | public class AppDataService : IAppDataService 8 | { 9 | private AppData _appData; 10 | private HttpClient _httpClient; 11 | 12 | public AppDataService(AppData appData, HttpClient httpClient) 13 | { 14 | _appData = appData; 15 | _httpClient = httpClient; 16 | } 17 | 18 | //public async Task> GetAllLocations() 19 | //{ 20 | // List locations = new(); 21 | 22 | // if (_appData.Locations.Any() is false) 23 | // locations = await _httpClient.Location().GetAllLocations(); 24 | // else 25 | // locations = _appData.Locations; 26 | 27 | // return locations; 28 | //} 29 | } -------------------------------------------------------------------------------- /Src/Template.Infrastructure/Identity/IdentityClientsProvider.cs: -------------------------------------------------------------------------------- 1 | using Bit.IdentityServer.Contracts; 2 | using Bit.IdentityServer.Implementations; 3 | using Template.Domain.Shared; 4 | 5 | namespace Template.Infrastructure.Identity 6 | { 7 | public class IdentityClientsProvider : OAuthClientsProvider 8 | { 9 | public override IEnumerable GetClients() 10 | { 11 | return new[] 12 | { 13 | GetResourceOwnerFlowClient(new BitResourceOwnerFlowClient 14 | { 15 | ClientName = AppConstants.WebApp.ClientName, 16 | ClientId = AppConstants.WebApp.ClientId, 17 | Secret = AppConstants.WebApp.Secret, 18 | TokensLifetime = AppConstants.AuthToken.Lifetime, 19 | Enabled = true 20 | }) 21 | }; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/Modal.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Tests/Domain.UnitTests/Domain.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /Src/Template.WebUI.API/web.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Src/Template.Domain/Template.Domain.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | all 32 | runtime; build; native; contentfiles; analyzers 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/comment.svg: -------------------------------------------------------------------------------- 1 | chat-bubble -------------------------------------------------------------------------------- /Src/Template.Infrastructure/Persistence/EF/Configuration/OrderEFConfiguration.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore; 2 | using Microsoft.EntityFrameworkCore.Metadata.Builders; 3 | using Template.Domain.Entities.Order; 4 | using Template.Domain.Enums.Order; 5 | 6 | namespace Template.Infrastructure.Persistence.EF.Configuration; 7 | 8 | public class OrderEFConfiguration : IEntityTypeConfiguration 9 | { 10 | public void Configure(EntityTypeBuilder builder) 11 | { 12 | // Table 13 | builder.ToTable("FoodOrder", DbSchemas.ATA); 14 | 15 | builder.HasKey(b => b.Id); 16 | 17 | // Props 18 | builder.Property(b => b.Id).HasColumnType("bigint"); 19 | 20 | builder.Property(b => b.OrderStatus).HasDefaultValue(OrderStatus.Confirmed); 21 | 22 | builder.Property(b => b.GroupCalendarId).HasColumnType("bigint"); 23 | 24 | builder.Property(b => b.UserPersonnelCode).HasColumnName("EmployeeCode").HasColumnType("bigint"); 25 | 26 | builder.Property(b => b.UserFullName).HasMaxLength(20); 27 | } 28 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:65189", 7 | "sslPort": 44398 8 | } 9 | }, 10 | "profiles": { 11 | "Template.WebUI.Client": { 12 | "commandName": "Project", 13 | "dotnetRunMessages": true, 14 | "launchBrowser": true, 15 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 16 | "applicationUrl": "https://localhost:7298;http://localhost:5298", 17 | "environmentVariables": { 18 | "ASPNETCORE_ENVIRONMENT": "Development" 19 | } 20 | }, 21 | "IIS Express": { 22 | "commandName": "IISExpress", 23 | "launchBrowser": true, 24 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 25 | "environmentVariables": { 26 | "ASPNETCORE_ENVIRONMENT": "Development" 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/Toast.razor: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | 6 |
7 | @Message 8 |
9 |
10 | 11 | @code { 12 | [CascadingParameter] private BlazoredToast ToastInstance { get; set; } 13 | 14 | [Parameter] public NotificationType NotifType { get; set; } 15 | 16 | [Parameter] public string Message { get; set; } 17 | 18 | string _iconUrl; 19 | 20 | protected override void OnInitialized() 21 | { 22 | _iconUrl = NotifType switch 23 | { 24 | NotificationType.Success => IconUrls.SuccessToast, 25 | NotificationType.Error => IconUrls.ErrorToast, 26 | NotificationType.Warning => IconUrls.WarningToast, 27 | NotificationType.Notify => IconUrls.InfoToast, 28 | NotificationType.Message => IconUrls.InfoToast, 29 | _ => _iconUrl 30 | }; 31 | 32 | base.OnInitialized(); 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/ImageUrls.cs: -------------------------------------------------------------------------------- 1 | namespace Template.WebUI.Client.wwwroot; 2 | 3 | public static class ImageUrls 4 | { 5 | public static class Layout 6 | { 7 | public const string LogoHeaderWhite = "/images/layout/logo-header-white.png"; 8 | public const string LogoHeaderMain = "/images/layout/logo-header-main.png"; 9 | public const string AtaAirlinesLogoMain = "/images/layout/ataairlines_main.png"; 10 | public const string AtaAirlinesLogoWhite = "/images/layout/ataairlines_white.png"; 11 | public const string NotificationsWhite = "/images/layout/notifications-white.svg"; 12 | public const string ATALoading = "/images/layout/ata_loading.png"; 13 | public const string PageNotFound404 = "/images/layout/404.png"; 14 | } 15 | 16 | public static class Pages 17 | { 18 | public const string SelectFoodBanner = "/images/pages/food/desktop-banner.png"; 19 | public const string SelectFoodBannerMobile = "/images/pages/food/mobile-banner.png"; 20 | public const string SelectFoodSpoonAndFork = "/images/pages/food/spoon-fork.png"; 21 | } 22 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/pen_gray.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/pen_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/utils/_bit-custom.scss: -------------------------------------------------------------------------------- 1 | @import '_base.scss'; 2 | 3 | /*#region BitDropDown */ 4 | 5 | .bit-drp-fluent { 6 | font-family: $fontPrimary; 7 | 8 | .bit-drp-wrapper { 9 | .bit-drp-wrapper-txt { 10 | border: 1px solid $pinkish-grey; 11 | height: rem(40px); 12 | display: flex; 13 | align-items: center; 14 | } 15 | 16 | .bit-drp-wrapper-ic { 17 | top: rem(5px); 18 | } 19 | } 20 | 21 | .bit-drp-items-wrapper { 22 | .rtl & { 23 | left: unset !important; 24 | width: rem(460px); 25 | } 26 | 27 | .bit-chb-fluent { 28 | .bit-chb-txt { 29 | .rtl & { 30 | font-family: $fontPrimary; 31 | color: $dark; 32 | margin-right: 0.25rem; 33 | } 34 | } 35 | } 36 | } 37 | } 38 | 39 | /*#endregion BitDropDown*/ 40 | 41 | /*#region BitSpinner */ 42 | 43 | .bit-spn-fluent > div:first-child { 44 | border-top-color: $boulder; 45 | } 46 | /*#endregion BitSpinner*/ 47 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/abstracts/_mixins.scss: -------------------------------------------------------------------------------- 1 | @import '_variables.scss'; 2 | @import '_functions.scss'; 3 | @import '_responsive.scss'; 4 | 5 | // Global Mixins 6 | 7 | @mixin removeButtonDefaultStyle { 8 | border: none; 9 | outline: none; 10 | white-space: nowrap; 11 | text-decoration: none; 12 | font-family: 'aeonik-regular'; 13 | cursor: pointer; 14 | 15 | &:hover { 16 | text-decoration: none; 17 | } 18 | 19 | &:focus { 20 | outline: none; 21 | } 22 | } 23 | 24 | @mixin removeLinkDefaultStyle { 25 | cursor: pointer; 26 | 27 | &:hover { 28 | text-decoration: none; 29 | } 30 | } 31 | 32 | @mixin border($bcolor: $pinkish-grey) { 33 | border: rem(0.5px) solid $bcolor; 34 | border-radius: rem(2px); 35 | box-sizing: border-box; 36 | } 37 | 38 | @mixin defaultButtonStyle { 39 | @include removeButtonDefaultStyle; 40 | border-radius: 2px; 41 | font-size: rem(14px); 42 | font-family: $fontPrimary; 43 | height: rem(40px); 44 | line-height: 40px; 45 | display: flex; 46 | align-items: center; 47 | width: rem(140px); 48 | } 49 | 50 | -------------------------------------------------------------------------------- /Src/Template.WebUI.API/Extensions/ATAExceptionToHttpErrorMapper.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Server.Extensions; 2 | using ATABit.Shared.Exceptions; 3 | using Bit.Owin.Implementations; 4 | using Bit.Owin.Metadata; 5 | using System.Net; 6 | 7 | namespace Template.WebUI.API.Extensions 8 | { 9 | public class ATAExceptionToHttpErrorMapper : DefaultExceptionToHttpErrorMapper 10 | { 11 | public override HttpStatusCode GetStatusCode(Exception exp) 12 | { 13 | if (exp is ValidationException) 14 | return HttpStatusCode.BadRequest; 15 | 16 | //if (exp is InvalidTokenException) 17 | // return HttpStatusCode.BadRequest; 18 | 19 | return base.GetStatusCode(exp); 20 | } 21 | 22 | public override string GetMessage(Exception exp) 23 | { 24 | exp = UnWrapException(exp); 25 | 26 | string? messageToShow = BitMetadataBuilder.UnknownError; 27 | 28 | if (IsKnownError(exp)) 29 | { 30 | messageToShow = exp.GetModelErrorWrapper(); 31 | } 32 | 33 | return messageToShow ?? ""; 34 | } 35 | } 36 | } -------------------------------------------------------------------------------- /Src/Template.Application/Order/Queries/GetUserLastOrder/GetUserLastOrderQueryHandler.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Model.Data.Contracts; 2 | using AutoMapper; 3 | using AutoMapper.QueryableExtensions; 4 | using MediatR; 5 | using Microsoft.EntityFrameworkCore; 6 | using Template.Application.Order.DTOs; 7 | using Template.Domain.Entities.Order; 8 | 9 | namespace Template.Application.Order.Queries.GetUserLastOrder; 10 | 11 | public class GetUserLastOrderQueryHandler : IRequestHandler 12 | { 13 | private readonly IATARepository _orderRepository; 14 | private readonly IMapper _mapper; 15 | 16 | public GetUserLastOrderQueryHandler(IATARepository orderRepository, IMapper mapper) 17 | { 18 | _orderRepository = orderRepository; 19 | _mapper = mapper; 20 | } 21 | 22 | public Task Handle(GetUserLastOrderQuery request, CancellationToken cancellationToken) 23 | { 24 | return _orderRepository.GetAll() 25 | .Where(o => o.UserId == request.UserId) 26 | .ProjectTo(_mapper.ConfigurationProvider) 27 | .FirstOrDefaultAsync(cancellationToken); 28 | } 29 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/TelerikComponents/CustomDropDownListPopupSettings.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Microsoft.AspNetCore.Components; 3 | using Telerik.Blazor.Components; 4 | 5 | namespace ATA.Food.Client.Web.Components.TelerikComponents; 6 | 7 | public class CustomDropDownListPopupSettings : DropDownListPopupSettings 8 | { 9 | [Parameter] [Required] public bool HasDefaultText { get; set; } 10 | [Parameter] [Required] public int ItemsCount { get; set; } 11 | 12 | protected override Task OnParametersSetAsync() 13 | { 14 | Height = CalculatePopUpHeight(); 15 | Class = "form-dropdown-popup"; 16 | return base.OnParametersSetAsync(); 17 | } 18 | 19 | private string CalculatePopUpHeight() 20 | { 21 | int paddingHeight = HasDefaultText ? 47 : 20; 22 | int itemHeight = 40; 23 | int maxHeight = 210; 24 | 25 | int itemsHeight = (ItemsCount == 0 ? 1 : ItemsCount) * itemHeight; 26 | int popUpHeight = itemsHeight + paddingHeight; 27 | 28 | int height = popUpHeight > maxHeight ? maxHeight : popUpHeight; 29 | 30 | return $"{height}px"; 31 | } 32 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/folder-close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/home_active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/home_inactive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/App.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 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 | @code 33 | { 34 | protected override async Task OnInitializedAsync() 35 | { 36 | //await JsRuntime.InvokeVoidAsync("addSignature"); 37 | } 38 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/AutoRegisterDiInstaller.cs: -------------------------------------------------------------------------------- 1 | using NetCore.AutoRegisterDi; 2 | using System.Reflection; 3 | using Template.Application.Common.Contracts; 4 | using Template.Domain.Options; 5 | 6 | namespace Template.WebUI.Client.ConfigureServices 7 | { 8 | public class AutoRegisterDiInstaller : IInstaller 9 | { 10 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 11 | { 12 | var webAssembly = Assembly.GetExecutingAssembly(); 13 | var clientWebServiceAssembly = typeof(ClientAppSettings).Assembly; 14 | 15 | var assembliesToScan = new[] { webAssembly, clientWebServiceAssembly }; 16 | 17 | #region Generic Type Dependencies 18 | //services.AddScoped(typeof(IRepository<>), typeof(EfCoreRepositoryBase<,>)); 19 | #endregion 20 | 21 | 22 | #region Register DIs By Name 23 | services.RegisterAssemblyPublicNonGenericClasses(assembliesToScan) 24 | .Where(c => c.Name.EndsWith("Service")) 25 | .AsPublicImplementedInterfaces(ServiceLifetime.Scoped); 26 | #endregion 27 | 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /Src/Template.Application/User/Queries/GetIdentityTokenById/GetIdentityTokenByIdQueryValidator.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Model.Data.Contracts; 2 | using FluentValidation; 3 | using Template.Domain.Entities.Identity; 4 | 5 | namespace Template.Application.DTOs; 6 | 7 | public class GetIdentityTokenByIdQueryValidator : AbstractValidator 8 | { 9 | private readonly IATARepository _identityTokenRepository; 10 | 11 | public GetIdentityTokenByIdQueryValidator(IATARepository identityTokenRepository) 12 | { 13 | _identityTokenRepository = identityTokenRepository; 14 | 15 | //RuleFor(v => v.Title) 16 | // .NotEmpty().WithMessage("Title is required.") 17 | // .MaximumLength(200).WithMessage("Title must not exceed 200 characters.") 18 | // .MustAsync(BeUniqueTitle).WithMessage("The specified title already exists."); 19 | } 20 | 21 | public async Task BeUniqueTitle(string title, CancellationToken cancellationToken) 22 | { 23 | return await Task.FromResult(true); 24 | //return await _context.TodoLists 25 | // .AllAsync(l => l.Title != title, cancellationToken); 26 | } 27 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/request_active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/request_inactive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/_Imports.razor: -------------------------------------------------------------------------------- 1 | @using System.Net.Http 2 | @using System.Net.Http.Json 3 | @using Microsoft.AspNetCore.Components.Forms 4 | @using Microsoft.AspNetCore.Components.Routing 5 | @using Microsoft.AspNetCore.Components.Web 6 | @using Microsoft.AspNetCore.Components.Web.Virtualization 7 | @using Microsoft.AspNetCore.Components.WebAssembly.Http 8 | @using Microsoft.JSInterop 9 | @using Template.WebUI.Client 10 | @using Template.WebUI.Client.Shared 11 | 12 | @* Libs Usings *@ 13 | @using Bit_.View 14 | @using Blazored.Toast 15 | @using Blazored.Toast.Services 16 | @using Blazored.Modal 17 | @using Blazored.Modal.Services 18 | @using Telerik.Blazor 19 | @using Telerik.Blazor.Components 20 | @using Radzen 21 | @using Radzen.Blazor 22 | @using Blazor.PersianDatePicker 23 | @using Blazor.PersianDatePicker.Extensions 24 | @using ATABit.Helper; 25 | @using Bit.Client.Web.BlazorUI 26 | @using Microsoft.AspNetCore.Components.Authorization 27 | @using Blazored.Toast.Configuration 28 | 29 | @* Project Usings *@ 30 | @using Template.WebUI.Client.Components 31 | @using Template.Domain.Shared 32 | @using Template.WebUI.Client.wwwroot 33 | @using Template.WebUI.Client.Pages 34 | @using Template.WebUI.Client.Extensions 35 | @using Template.WebUI.Client.Enums -------------------------------------------------------------------------------- /Src/Template.Infrastructure/ConfigureServices/ClientsInstaller.cs: -------------------------------------------------------------------------------- 1 | using Bit.Core.Contracts; 2 | using Template.Domain.Options; 3 | using Template.Infrastructure.Common.Contracts; 4 | 5 | // ReSharper disable once ObjectCreationAsStatement 6 | 7 | namespace Template.Infrastructure.ConfigureServices; 8 | 9 | public class ClientsInstaller : IBitInstaller 10 | { 11 | public void InstallServices(IServiceCollection services, IDependencyManager dependencyManager, AppSettings appSettings) 12 | { 13 | //// SSO Client 14 | //services.AddHttpClient(client => 15 | //{ 16 | // client.BaseAddress = new Uri(serverAppSettings.URLOptions!.SSOClient!); 17 | //}); 18 | 19 | //// HR Client 20 | //services.AddHttpClient(client => 21 | //{ 22 | // string hrClientBaseUrl = AspNetCoreAppEnvironmentsProvider.Current.HostingEnvironment.IsDevelopment() 23 | // ? "https://dummy.com/" //Doesn't matter 24 | // : serverAppSettings.URLOptions!.HRClient!; 25 | 26 | // client.BaseAddress = new Uri(hrClientBaseUrl); 27 | // client.DefaultRequestHeaders.Add("api_key", serverAppSettings.HRClientOptions?.APIKey); 28 | //}); 29 | } 30 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/site.scss: -------------------------------------------------------------------------------- 1 | // Abstracts 2 | @import 'abstracts/_variables.scss'; 3 | @import 'abstracts/_responsive.scss'; 4 | @import 'abstracts/_fonts.scss'; 5 | 6 | // Vendors 7 | @import 'vendors/bootstrap/bootstrap-grid.min.css'; 8 | @import 'vendors/alertify/alertify.min.css'; 9 | 10 | // Utils 11 | @import 'utils/_helpers.scss'; 12 | @import 'utils/_radzen-custom.scss'; 13 | @import 'utils/_telerik-custom.scss'; 14 | @import 'utils/_bit-custom.scss'; 15 | @import 'utils/_alertify-custom.scss'; 16 | @import 'utils/_shared.scss'; 17 | 18 | // Layouts 19 | @import "layout/_header.scss"; 20 | @import "layout/_sidebar.scss"; 21 | @import "layout/_content.scss"; 22 | 23 | // Components 24 | @import 'components/_Confirm.scss'; 25 | @import 'components/_Loading.scss'; 26 | @import 'components/_Toast.scss'; 27 | 28 | // Pages 29 | @import 'pages/dashboard/_dashboard-page.scss'; 30 | @import 'pages/dashboard/_flowForm-page.scss'; 31 | @import 'pages/settings/_roles-page.scss'; 32 | @import 'pages/report/_report-statistical-page.scss'; 33 | @import 'pages/report/_personnel-report-page.scss'; 34 | @import 'pages/food/_tbz-food-menu-page.scss'; 35 | @import 'pages/food/_select-food-page.scss'; 36 | @import 'pages/calendar/_food-calendar-page.scss'; 37 | -------------------------------------------------------------------------------- /Src/Template.Infrastructure/ConfigureServices/NamePatternRegisterInstaller.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Bit.Core.Contracts; 3 | using System.Reflection; 4 | using Template.Domain.Options; 5 | using Template.Infrastructure.Common.Contracts; 6 | 7 | namespace Template.Infrastructure.ConfigureServices; 8 | 9 | /// 10 | /// Register Assembly Public NonAbstract Classes with PropertyInjection enabled 11 | /// 12 | public class NamePatternRegisterInstaller : IBitInstaller 13 | { 14 | public void InstallServices(IServiceCollection services, IDependencyManager dependencyManager, AppSettings appSettings) 15 | { 16 | dependencyManager 17 | .GetContainerBuilder() 18 | .RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) 19 | .PublicOnly() 20 | .Where(type => 21 | type.IsClass && 22 | !type.IsAbstract && 23 | (type.Name.EndsWith("Service") || type.Name.EndsWith("Repository")) && 24 | type.Name != "EntityService") 25 | .AsSelf() 26 | .As(t => t.BaseType!) 27 | .AsImplementedInterfaces() 28 | .PropertiesAutowired(PropertyWiringOptions.PreserveSetValues) 29 | .PreserveExistingDefaults(); 30 | } 31 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Pages/PageUrls.cs: -------------------------------------------------------------------------------- 1 | namespace Template.WebUI.Client.Pages; 2 | 3 | public static class PageUrls 4 | { 5 | public const string SelectFoodPage = "/"; 6 | 7 | public static string FlowFormsPage(int paramRequestId) => $"/flow-forms/{paramRequestId}"; 8 | public const string LogsPage = "/logs"; 9 | 10 | public const string ReportsRootPath = "/reports"; 11 | public const string MyFoodsReport = $"{ReportsRootPath}/personnel"; 12 | public static string PersonnelReportPage(string city) => $"{ReportsRootPath}/personnel/{city}"; 13 | public static string StatisticalReportPage(string city) => $"{ReportsRootPath}/statistical/{city}"; 14 | public static string GuestsReportPage(string city) => $"{ReportsRootPath}/guests/{city}"; 15 | 16 | public const string FoodManagementRootPath = "/foods"; 17 | public const string FoodMenuPage = $"{FoodManagementRootPath}/food-menu"; 18 | public static string FoodCalendarPage(string city) => $"{FoodManagementRootPath}/food-calendar/{city}"; 19 | 20 | public const string SettingsRootPath = "/settings"; 21 | public const string UsersPage = $"{SettingsRootPath}/users"; 22 | public const string RolesPage = $"{SettingsRootPath}/roles"; 23 | public const string WorkflowPage = $"{SettingsRootPath}/workflow"; 24 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.API/ConfigureServices/NamePatternRegisterInstaller.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using Bit.Core.Contracts; 3 | using Template.Domain.Options; 4 | using Template.Infrastructure.Common.Contracts; 5 | 6 | namespace Template.WebUI.API.ConfigureServices 7 | { 8 | /// 9 | /// Register Assembly Public NonAbstract Classes with PropertyInjection enabled 10 | /// 11 | public class NamePatternRegisterInstaller : IBitInstaller 12 | { 13 | public void InstallServices(IServiceCollection services, IDependencyManager dependencyManager, AppSettings appSettings) 14 | { 15 | dependencyManager 16 | .GetContainerBuilder() 17 | .RegisterAssemblyTypes(typeof(APIAssemblyEntryPoint).Assembly) 18 | .PublicOnly() 19 | .Where(type => 20 | type.IsClass && 21 | !type.IsAbstract && 22 | type.Name.EndsWith("Service") && 23 | type.Name != "EntityService") 24 | .AsSelf() 25 | .As(t => t.BaseType!) 26 | .AsImplementedInterfaces() 27 | .PropertiesAutowired(PropertyWiringOptions.PreserveSetValues) 28 | .PreserveExistingDefaults(); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.API/ActionFilters/ModelStateValidatorAttribute.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Server.Extensions; 2 | using ATABit.Shared; 3 | using ATABit.Shared.Exceptions; 4 | using Bit.Core.Contracts; 5 | using Microsoft.Owin; 6 | using System.Web.Http.Controllers; 7 | using System.Web.Http.Filters; 8 | using ILogger = Bit.Core.Contracts.ILogger; 9 | 10 | namespace Template.WebUI.API.ActionFilters 11 | { 12 | public class ModelStateValidatorAttribute : ActionFilterAttribute 13 | { 14 | public override void OnActionExecuting(HttpActionContext actionContext) 15 | { 16 | if (actionContext.ModelState is null) 17 | throw new ArgumentNullException(nameof(actionContext.ModelState)); 18 | 19 | if (actionContext.ModelState.IsValid | actionContext.Request.Method == HttpMethod.Get /*workaround*/) 20 | return; 21 | 22 | IDependencyResolver dependencyResolver = actionContext.Request.GetOwinContext().GetDependencyResolver(); 23 | var logger = dependencyResolver.Resolve(); 24 | 25 | ModelErrorWrapper modelErrorWrapper = actionContext.ModelState.GetModelErrors(); 26 | logger.AddLogData("ModelError", modelErrorWrapper); 27 | 28 | throw new ValidationException(modelErrorWrapper); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Directory.build.props: -------------------------------------------------------------------------------- 1 | 2 | 3 | Client 4 | 5 | $(DefineConstants);BlazorClient 6 | 7 | 8 | 9 | 1.0.0 10 | net6.0 11 | latest 12 | $(NoWarn);NU1701;1702;1591;NU1602;CS8609;CS8610;CS8619;CS8632 13 | enable 14 | 15 | 16 | 17 | portable 18 | true 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | all 33 | runtime; build; native; contentfiles; analyzers 34 | 35 | 36 | -------------------------------------------------------------------------------- /Src/Template.Application/Common/PipelineBehaviours/ValidationBehaviour.cs: -------------------------------------------------------------------------------- 1 | using FluentValidation; 2 | using MediatR; 3 | 4 | namespace Template.Application.Common.PipelineBehaviours; 5 | 6 | public class ValidationBehaviour : IPipelineBehavior 7 | where TRequest : IRequest 8 | { 9 | private readonly IEnumerable> _validators; 10 | 11 | public ValidationBehaviour(IEnumerable> validators) 12 | { 13 | _validators = validators; 14 | } 15 | 16 | public async Task Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate next) 17 | { 18 | if (_validators.Any()) 19 | { 20 | var context = new ValidationContext(request); 21 | 22 | var validationResults = await Task.WhenAll( 23 | _validators.Select(v => 24 | v.ValidateAsync(context, cancellationToken))); 25 | 26 | var failures = validationResults 27 | .Where(r => r.Errors.Any()) 28 | .SelectMany(r => r.Errors) 29 | .ToList(); 30 | 31 | if (failures.Any()) 32 | throw new ValidationException(failures); 33 | } 34 | 35 | return await next(); 36 | } 37 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/dashboard_active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Svg Vector Icons : http://www.onlinewebfonts.com/icon 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/dashboard_inactive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Svg Vector Icons : http://www.onlinewebfonts.com/icon 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/samples_active.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/samples_inactive.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/ConfigureServices/AuthInstaller.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Authorization; 2 | using Microsoft.AspNetCore.Components.Authorization; 3 | using Template.Application.Common.Contracts; 4 | using Template.Domain.Options; 5 | using Template.Domain.Shared; 6 | using Template.WebUI.Client.Implementations; 7 | 8 | namespace Template.WebUI.Client.ConfigureServices; 9 | 10 | public class AuthInstaller : IInstaller 11 | { 12 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 13 | { 14 | services.AddOptions(); 15 | 16 | services.AddAuthorizationCore(config => 17 | { 18 | var claims = Claims.GetAllAppClaims().ToList(); 19 | 20 | foreach (var claim in claims) 21 | { 22 | config.AddPolicy(claim, 23 | new AuthorizationPolicyBuilder() 24 | .RequireAuthenticatedUser() 25 | .RequireClaim(claim) 26 | .Build()); 27 | } 28 | } 29 | ); 30 | 31 | services.AddScoped(); 32 | 33 | services.AddTransient(serviceProvider => (AppAuthenticationStateProvider)serviceProvider.GetRequiredService()); 34 | } 35 | } -------------------------------------------------------------------------------- /Tests/Template.Domain.UnitTests/Template.Domain.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | all 30 | runtime; build; native; contentfiles; analyzers 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Tests/Template.Application.IntegrationTests/Template.Application.IntegrationTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | all 30 | runtime; build; native; contentfiles; analyzers 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /Src/Template.Application/ConfigureServices/Installers/AutoRegisterInstaller.cs: -------------------------------------------------------------------------------- 1 | using Autofac; 2 | using NetCore.AutoRegisterDi; 3 | using Template.Application.Common.Contracts; 4 | using Template.Domain.Options; 5 | 6 | namespace Template.Application.ConfigureServices.Installers; 7 | 8 | /// 9 | /// Register Assembly Public NonAbstract Classes 10 | /// 11 | public class AutoRegisterInstaller : IInstaller 12 | { 13 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 14 | { 15 | services.RegisterAssemblyPublicNonGenericClasses() 16 | .Where(c => c.Name.EndsWith("Service")) //optional 17 | // .IgnoreThisInterface() //optional 18 | .AsPublicImplementedInterfaces(); 19 | 20 | #region Scanning Multiple assemblies example 21 | 22 | //var assembliesToScan = new[] 23 | //{ 24 | // Assembly.GetExecutingAssembly(), 25 | // Assembly.GetAssembly(typeof(MyServiceInAssembly1)), 26 | // Assembly.GetAssembly(typeof(MyServiceInAssembly2)) 27 | //}; 28 | 29 | //services.RegisterAssemblyPublicNonGenericClasses(assembliesToScan) 30 | // .Where(c => c.Name.EndsWith("Service")) //optional 31 | // .IgnoreThisInterface() //optional 32 | // .AsPublicImplementedInterfaces(); 33 | 34 | #endregion 35 | } 36 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.API/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/launchsettings.json", 3 | "iisSettings": { 4 | "windowsAuthentication": false, 5 | "anonymousAuthentication": true, 6 | "iisExpress": { 7 | "applicationUrl": "http://localhost:21653", 8 | "sslPort": 44331 9 | } 10 | }, 11 | "profiles": { 12 | "IIS Express": { 13 | "commandName": "IISExpress", 14 | "launchBrowser": true, 15 | "environmentVariables": { 16 | "ASPNETCORE_ENVIRONMENT": "Development" 17 | } 18 | }, 19 | "Run (Dev)": { 20 | "commandName": "Project", 21 | "launchBrowser": true, 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | }, 25 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 26 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 27 | "dotnetRunMessages": "true" 28 | }, 29 | "Run (Prod)": { 30 | "commandName": "Project", 31 | "launchBrowser": true, 32 | "environmentVariables": { 33 | "ASPNETCORE_ENVIRONMENT": "Production" 34 | }, 35 | "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}", 36 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 37 | "dotnetRunMessages": "true" 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Tests/Template.Application.UnitTests/Template.Application.UnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | 7 | false 8 | 9 | 10 | 11 | 12 | 13 | 14 | runtime; build; native; contentfiles; analyzers; buildtransitive 15 | all 16 | 17 | 18 | runtime; build; native; contentfiles; analyzers; buildtransitive 19 | all 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | all 31 | runtime; build; native; contentfiles; analyzers 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /Src/Template.Application/ConfigureServices/Installers/LocalizationInstaller.cs: -------------------------------------------------------------------------------- 1 | using Template.Application.Common.Contracts; 2 | using Template.Domain.Options; 3 | 4 | namespace Template.Application.ConfigureServices.Installers; 5 | 6 | public class LocalizationInstaller : IInstaller 7 | { 8 | public void InstallServices(IServiceCollection services, AppSettings appSettings) 9 | { 10 | //services.AddLocalization(); 11 | 12 | //services.AddRequestLocalization(options => 13 | //{ 14 | // var supportedCultures = new[] 15 | // { 16 | // new CultureInfo("fa"), 17 | // new CultureInfo("en"), 18 | // }; 19 | 20 | // options.SupportedCultures = supportedCultures; 21 | // options.DefaultRequestCulture = new RequestCulture("fa"); 22 | // options.ApplyCurrentCultureToResponseHeaders = true; 23 | // options.SupportedUICultures = supportedCultures; 24 | // options.RequestCultureProviders = new List 25 | // { 26 | // new QueryStringRequestCultureProvider(), 27 | // new AcceptLanguageHeaderRequestCultureProvider() 28 | // // new CookieRequestCultureProvider() 29 | // }; 30 | //}); 31 | 32 | //dependencyManager.Register(); 33 | 34 | //services.AddSingleton, MvcConfigurationToProvideModelBindingMessage>(); 35 | } 36 | } -------------------------------------------------------------------------------- /Architecture.txt: -------------------------------------------------------------------------------- 1 | It is Clean Architechture, the one more aligned withJson Tylor and Nick Chapsas. 2 | 3 | Domain: 4 | - Things related to the domain (a little like DDD). No logic comes here. 5 | - This will contain all entities, enums, exceptions, interfaces, types and logic specific to the domain layer. 6 | - All Entities Properties has private set! Because only with class APIs they can change. 7 | 8 | Application: 9 | - Orchestrate the application. This layer contains all application logic. It is dependent on the domain layer, but has no dependencies on any other layer or project. This layer defines interfaces that are implemented by outside layers and DTOs. For example, if the application need to access a notification service, a new interface would be added to application and an implementation would be created within infrastructure. 10 | 11 | Infrastructure: 12 | - This layer contains classes for accessing external resources such as file systems, web services, smtp, and so on. These classes should be based on interfaces defined within the application layer. 13 | - All classes be internal because it do not have any effect on other projects, only in ConfigureServices have and it has its own method. 14 | 15 | WebUI: 16 | - This layer depends on both the Application and Infrastructure layers, however, the dependency on Infrastructure is only to support dependency injection. Therefore only Startup.cs should reference Infrastructure. 17 | - They depend to Infrastrucutre project only for Service registration and nothing else! 18 | -------------------------------------------------------------------------------- /Src/Template.Application/Common/Localization/Extensions/ValidationContextExtension.cs: -------------------------------------------------------------------------------- 1 | using System.ComponentModel.DataAnnotations; 2 | using Bit.Core.Exceptions; 3 | using Template.Application.Common.Contracts; 4 | 5 | namespace Template.Application.Common.Localization.Extensions 6 | { 7 | public static class ValidationContextExtension 8 | { 9 | public static IStringProvider GetStringProvider(this ValidationContext validationContext) 10 | { 11 | // Request originated from AspNetCore Controllers 12 | var stringsProvider = validationContext.GetService(typeof(IStringProvider)); 13 | 14 | if (stringsProvider is not null) 15 | return (IStringProvider)stringsProvider; 16 | 17 | // Below block should be uncomment in backend only projects. Blazor will use AspNetCore context and 18 | // will validate the dto in client-side, so no need to backend error message. 19 | 20 | #region Request originated from Bit Controllers 21 | 22 | //var context = DefaultDependencyManager.Current.Resolve().HttpContext; 23 | 24 | //validationContext.InitializeServiceProvider(type => context!.RequestServices.GetRequiredService(type)); 25 | 26 | //return validationContext.GetRequiredService(); 27 | 28 | #endregion 29 | 30 | throw new DomainLogicException("In Blazor applications, this error should not happen! See the above comments"); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/curved_right_arrow.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/components/_Loading.scss: -------------------------------------------------------------------------------- 1 | @import '../utils/_base.scss'; 2 | 3 | .ata-loading-component { 4 | 5 | #loader-wrappers { 6 | width: 100%; 7 | height: 100%; 8 | position: fixed; 9 | left: 0; 10 | top: 0; 11 | right: 0; 12 | bottom: 0; 13 | z-index: 9999; 14 | display: flex; 15 | align-items: center; 16 | flex-direction: column; 17 | justify-content: center; 18 | direction: ltr; 19 | } 20 | 21 | #loaders-body { 22 | width: 94px; 23 | height: 94px; 24 | background-size: 80%; 25 | border-radius: 50%; 26 | margin: 0 auto; 27 | z-index: 1; 28 | position: relative; 29 | display: flex; 30 | justify-content: center; 31 | align-items: center; 32 | 33 | img { 34 | position: absolute; 35 | left: 14px; 36 | } 37 | } 38 | 39 | #loaders { 40 | left: 0; 41 | top: 0; 42 | z-index: 1; 43 | border: 3px solid #b2b3b0; 44 | border-radius: 50%; 45 | border-top: 3px solid #a71c20; 46 | width: 68px; 47 | height: 68px; 48 | margin: -9px; 49 | -webkit-animation: spin 1s linear infinite; 50 | animation: spins 1s linear infinite; 51 | } 52 | 53 | @keyframes spins { 54 | 0% { 55 | transform: rotate(0deg); 56 | } 57 | 58 | 100% { 59 | transform: rotate(360deg); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Contracts/INotificationService.cs: -------------------------------------------------------------------------------- 1 | using Template.Domain.Shared; 2 | using Template.WebUI.Client.Enums; 3 | 4 | namespace Template.WebUI.Client.Contracts 5 | { 6 | public interface INotificationService 7 | { 8 | /// 9 | /// Show Alert Using AlertifyJS library 10 | /// 11 | /// Type of alert including success, error, warning, etc 12 | /// Message content 13 | /// Time (in seconds) to wait before the message is dismissed, a value of 0 means keep open till clicked. 14 | /// Sets a value indicating the position of the notifier instance. 15 | /// 16 | ValueTask AlertAsync(NotificationType notifType, string message, int waitSeconds = AppConstants.AlertDefaultTimeout, AlertifyPosition position = AlertifyPosition.TopCenter); 17 | 18 | /// 19 | /// Show Alert Using BlazoredToast library 20 | /// 21 | /// Type of alert including success, error, warning, etc 22 | /// Message content 23 | /// 24 | /// 25 | /// 26 | void Toast(NotificationType notifType, string message, int waitSeconds = 5, bool showProgressBar = true); 27 | 28 | ValueTask AlertGeneralError(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Src/Template.Infrastructure/Persistence/EF/ATADbContext.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Data.Extensions; 2 | using Bit.Data.EntityFrameworkCore.Implementations; 3 | using Microsoft.EntityFrameworkCore; 4 | using Template.Domain.Entities; 5 | 6 | namespace Template.Infrastructure.Persistence.EF; 7 | 8 | public class ATADbContext : EfCoreDbContextBase 9 | { 10 | public ATADbContext(DbContextOptions options) 11 | : base(options) 12 | { 13 | } 14 | 15 | protected override void OnModelCreating(ModelBuilder modelBuilder) 16 | { 17 | // Auto Register all Entities 18 | modelBuilder.RegisterDbSets(typeof(ATAEntity).Assembly); 19 | 20 | modelBuilder.UseJsonDbFunctions(); 21 | 22 | // Configure Views 23 | //modelBuilder.ConfigureDbView(DbViews.FoodMenu, DbSchemas.ATA, hasKey: true); 24 | 25 | base.OnModelCreating(modelBuilder); 26 | 27 | // Seed Base Data to Database 28 | //modelBuilder.SeedDefaultRoles(); 29 | 30 | // Ef Global Query Filters 31 | modelBuilder.RegisterIsArchivedGlobalQueryFilter(); 32 | //modelBuilder.Entity().HasQueryFilter(ur => ur.ApplicationName == AppMetadata.SSOAppName); 33 | 34 | modelBuilder.ConfigureDecimalPrecision(); 35 | 36 | // Restrict Delete (in Hard delete scenarios) 37 | // Ef default is Cascade 38 | modelBuilder.SetRestrictAsDefaultDeleteBehavior(); 39 | 40 | // Auto Register all Entity Configurations (Fluent-API) 41 | modelBuilder.ApplyConfigurations(typeof(ATADbContext).Assembly); 42 | } 43 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/role.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Svg Vector Icons : http://www.onlinewebfonts.com/icon 6 | 7 | -------------------------------------------------------------------------------- /Src/Template.Infrastructure/Persistence/EF/Repository/ATARepositoryReadOnly.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Model.Data.Contracts; 2 | using Bit.Data.EntityFrameworkCore.Implementations; 3 | using Bit.Model.Contracts; 4 | using Microsoft.EntityFrameworkCore; 5 | using System.Linq.Expressions; 6 | 7 | namespace Template.Infrastructure.Persistence.EF.Repository; 8 | 9 | public class ATARepositoryReadOnly : EfCoreRepository, IReadOnlyATARepository 10 | where TEntity : class, IEntity 11 | { 12 | public IQueryable GetAllWithoutQueryFilter() 13 | { 14 | return Set.IgnoreQueryFilters(); 15 | } 16 | 17 | public override IQueryable GetAll() 18 | { 19 | Expression>? getFilter = CreateGetFilter(); 20 | 21 | IQueryable queryable = base.GetAll(); 22 | 23 | if (getFilter != null) 24 | { 25 | queryable = queryable.Where(getFilter); 26 | } 27 | 28 | return queryable; 29 | } 30 | 31 | public override async Task> GetAllAsync(CancellationToken cancellationToken) 32 | { 33 | Expression>? getFilter = CreateGetFilter(); 34 | 35 | IQueryable queryable = await base.GetAllAsync(cancellationToken); 36 | 37 | if (getFilter != null) 38 | { 39 | queryable = queryable.Where(getFilter); 40 | } 41 | 42 | return queryable; 43 | } 44 | 45 | protected virtual Expression>? CreateGetFilter() 46 | { 47 | Expression>? criteria = null; 48 | 49 | return criteria; 50 | } 51 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/folder-open.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.Application/Template.Application.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net6.0 5 | enable 6 | enable 7 | 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 | all 35 | runtime; build; native; contentfiles; analyzers 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/trash_gray.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/trash_white.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Pages/PageTitles.cs: -------------------------------------------------------------------------------- 1 | using Template.Domain.Shared; 2 | 3 | namespace Template.WebUI.Client.Pages; 4 | 5 | public static class PageTitles 6 | { 7 | public static class HomePage 8 | { 9 | public static readonly string Title = AppMetadata.PersianFullName; 10 | } 11 | 12 | public static class LogsPage 13 | { 14 | public static readonly string Title = "Audit Logs"; 15 | } 16 | 17 | public static class PersonnelReportPage 18 | { 19 | public static readonly string ManagerialReportTitle = "گزارش غذای پرسنل"; 20 | public static readonly string PersonnelMyFoodTitle = "گزارش غذای من"; 21 | } 22 | 23 | public static class GuestReportPage 24 | { 25 | public static readonly string Title = "گزارش غذای مهمان"; 26 | } 27 | 28 | public static class StatisticalReportPage 29 | { 30 | public static readonly string Title = "گزارش آماری"; 31 | } 32 | 33 | public static class UsersPage 34 | { 35 | public static readonly string Title = "کاربران"; 36 | } 37 | 38 | public static class RolesPage 39 | { 40 | public static readonly string Title = "نقش‌ها"; 41 | } 42 | 43 | public static class SettingsPage 44 | { 45 | public static readonly string Title = "تنظیمات"; 46 | } 47 | 48 | public static class FoodMenuPage 49 | { 50 | public static readonly string Title = "تعریف غذا"; 51 | } 52 | 53 | public static class FoodCalendarPage 54 | { 55 | public static readonly string Title = "تعریف گروه و تقویم غذایی"; 56 | } 57 | 58 | public static class SelectFoodPage 59 | { 60 | public static readonly string Title = "انتخاب غذا آتا"; 61 | } 62 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/add-circle.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components.Web; 2 | using Microsoft.AspNetCore.Components.WebAssembly.Hosting; 3 | using Microsoft.Extensions.Configuration; 4 | using System.Reflection; 5 | using Template.Application.Common.Contracts; 6 | using Template.Domain.Options; 7 | using Template.WebUI.Client.Implementations; 8 | using Template.WebUI.Client.Models; 9 | using Toolbelt.Blazor.Extensions.DependencyInjection; 10 | 11 | namespace Template.WebUI.Client; 12 | 13 | public class Program 14 | { 15 | public static Task Main(string[] args) 16 | { 17 | var builder = WebAssemblyHostBuilder.CreateDefault(args); 18 | builder.RootComponents.Add("head::after"); 19 | 20 | var clientAppSettings = builder.Configuration.GetSection(nameof(ClientAppSettings)).Get(); 21 | clientAppSettings.URLOptions!.AppURL = builder.HostEnvironment.BaseAddress; 22 | 23 | // Host client 24 | builder.Services.AddHttpClient(httpClient => httpClient.BaseAddress = new Uri(builder.HostEnvironment.BaseAddress)) 25 | .AddHttpMessageHandler(); 26 | 27 | // Configure Dependencies with Service Installers 28 | var installers = new[] { Assembly.GetExecutingAssembly() }.SelectMany(a => a.GetExportedTypes()) 29 | .Where(c => c.IsClass && !c.IsAbstract && c.IsPublic && typeof(IInstaller).IsAssignableFrom(c)) 30 | .Select(Activator.CreateInstance).Cast().ToList(); 31 | installers.ForEach(i => i.InstallServices(builder.Services, new AppSettings { Client = clientAppSettings })); 32 | 33 | builder.UseLoadingBar(); 34 | 35 | return builder 36 | .Build() 37 | .RunAsync(); 38 | } 39 | } -------------------------------------------------------------------------------- /Src/Template.Infrastructure/LogStore/SeqLogStore.cs: -------------------------------------------------------------------------------- 1 | using Bit.Core.Contracts; 2 | using Bit.Core.Models; 3 | using Serilog; 4 | using Serilog.Context; 5 | using Serilog.Exceptions; 6 | using Template.Domain.Shared; 7 | 8 | namespace Template.Infrastructure.LogStore; 9 | 10 | public class SeqLogStore : ILogStore 11 | { 12 | public Task SaveLogAsync(LogEntry logEntry) 13 | { 14 | SaveLog(logEntry); 15 | 16 | return Task.CompletedTask; 17 | } 18 | 19 | public void SaveLog(LogEntry logEntry) 20 | { 21 | Log.Logger = new LoggerConfiguration() 22 | .Enrich.WithProperty("ApplicationName", AppMetadata.SolutionName) 23 | .Enrich.FromLogContext() 24 | .Enrich.WithExceptionDetails() 25 | .Enrich.WithMachineName() 26 | .Enrich.WithClientIp() 27 | .Enrich.WithClientAgent() 28 | .WriteTo.Seq("http://log.app.ataair.ir", apiKey: "iW1OLXzF01n3gSJ70qkR") 29 | .CreateLogger(); 30 | 31 | foreach (var prop in logEntry.GetType().GetProperties()) 32 | LogContext.PushProperty(prop.Name, prop.GetValue(logEntry)); 33 | 34 | var trackingCode = logEntry.LogData.SingleOrDefault(l => l.Key == "X-Correlation-ID")?.Value?.ToString(); 35 | 36 | if (!string.IsNullOrWhiteSpace(trackingCode)) 37 | LogContext.PushProperty("TrackingCode", trackingCode); 38 | 39 | string message = string.IsNullOrWhiteSpace(trackingCode) ? logEntry.Message : $"TrackingCode: {trackingCode}"; 40 | 41 | if (logEntry.Severity == LogSeverity.Fatal.ToString()) 42 | Log.Logger.Fatal(message); 43 | 44 | else 45 | Log.Logger.Error(message); 46 | } 47 | } 48 | 49 | public enum LogSeverity 50 | { 51 | Warning, 52 | Fatal 53 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Introduction 4 | Template project conducted by me! This project developed using ASP.NET Core as Backend and Blazor WebAssembly as Frontend and SQLServer as database. 5 | 6 | - Also the Bit framework has been used both in Backend and Frontend for easy and fast development of the project. 7 | - CQRS and MediatR with Clean Architercture. 8 | - Fluent Validation added. 9 | 10 | 11 | Bit Platform 12 | 13 | 14 | # Architecture 15 | It is Clean Architechture, the one more aligned withJson Tylor and Nick Chapsas. 16 | 17 | ### Domain: 18 | - Things related to the domain (a little like DDD). No logic comes here. 19 | - This will contain all entities, enums, exceptions, interfaces, types and logic specific to the domain layer. 20 | 21 | ### Application: 22 | - Orchestrate the application. This layer contains all application logic. It is dependent on the domain layer, but has no dependencies on any other layer or project. This layer defines interfaces that are implemented by outside layers and DTOs. For example, if the application need to access a notification service, a new interface would be added to application and an implementation would be created within infrastructure. 23 | 24 | ### Infrastructure: 25 | - This layer contains classes for accessing external resources such as file systems, web services, smtp, and so on. These classes should be based on interfaces defined within the application layer. 26 | 27 | ### WebUI: 28 | - This layer depends on both the Application and Infrastructure layers, however, the dependency on Infrastructure is only to support dependency injection. Therefore only Startup.cs should reference Infrastructure. 29 | - They depend to Infrastrucutre project only for Service registration and nothing else! 30 | 31 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Extensions/JsRuntimeExtensions.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.JSInterop; 2 | 3 | namespace Template.WebUI.Client.Extensions; 4 | 5 | public static class JsRuntimeExtensions 6 | { 7 | public static ValueTask AlertAsync(this IJSRuntime jsRuntime, string alertMessage) 8 | { 9 | return jsRuntime.InvokeVoidAsync("alert", alertMessage); 10 | } 11 | 12 | public static ValueTask SetCookieAsync(this IJSRuntime jsRuntime, string cookieName, string cookieValue, double expireMinutes = 525600) 13 | { 14 | return jsRuntime.InvokeVoidAsync("setCookie", cookieName, cookieValue, expireMinutes); 15 | } 16 | 17 | public static ValueTask GetCookieAsync(this IJSRuntime jsRuntime, string cookieName) 18 | { 19 | return jsRuntime.InvokeAsync("getCookie", cookieName); 20 | } 21 | 22 | public static ValueTask DeleteCookieAsync(this IJSRuntime jsRuntime, string cookieName) 23 | { 24 | return jsRuntime.InvokeAsync("deleteCookie", cookieName); 25 | } 26 | 27 | public static ValueTask OpenInNewTabAsync(this IJSRuntime jsRuntime, string url) 28 | { 29 | return jsRuntime.InvokeVoidAsync("open", url, "_blank"); 30 | } 31 | 32 | public static ValueTask ChangeAddressBarUrlAsync(this IJSRuntime jsRuntime, string newUrl) 33 | { 34 | return jsRuntime.InvokeVoidAsync("changeAddressBarUrl", newUrl); 35 | } 36 | 37 | public static ValueTask AddCSSClassByElementIdAsync(this IJSRuntime jsRuntime, string elementId, string className) 38 | { 39 | return jsRuntime.InvokeVoidAsync("addClassToElementById", elementId, className); 40 | } 41 | 42 | public static ValueTask SetFocusAsync(this IJSRuntime jsRuntime, string elementId) 43 | { 44 | return jsRuntime.InvokeVoidAsync("setFocus", elementId); 45 | } 46 | 47 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Shared/MainLayout.razor: -------------------------------------------------------------------------------- 1 | 2 | @inherits LayoutComponentBase 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 |
14 |
15 |
16 |
17 |
18 | 19 | @if (_showMenu) 20 | { 21 |
22 | 23 |
24 | } 25 | 26 |
27 | @Body 28 |
29 | 30 |
31 | 32 |
33 | 34 |
35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 |
44 | 45 | @code { 46 | 47 | bool _showMenu; 48 | 49 | [CascadingParameter] private Task AuthenticationStateTask { get; set; } 50 | 51 | protected override async Task OnInitializedAsync() 52 | { 53 | var authState = await AuthenticationStateTask; 54 | 55 | if (authState.User.Identity is null) 56 | return; 57 | 58 | if (authState.User.Identity.IsAuthenticated) 59 | { 60 | var userRoles = await AuthenticationStateTask.GetUserRoles(); 61 | 62 | _showMenu = userRoles.Count > 0; 63 | } 64 | 65 | await base.OnInitializedAsync(); 66 | } 67 | 68 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/abstracts/_fonts.scss: -------------------------------------------------------------------------------- 1 | /*#region Aeonik font*/ 2 | 3 | @font-face { 4 | font-family: 'aeonik-bold'; 5 | src: url("../../fonts/Aeonik-Bold.otf?v=uc2a313ce") format("truetype"); 6 | font-weight: normal; 7 | font-style: normal; 8 | font-display: block; 9 | } 10 | 11 | @font-face { 12 | font-family: 'aeonik-medium'; 13 | src: url("../../fonts/Aeonik-Medium.otf?v=uc2a313ce") format("truetype"); 14 | font-weight: normal; 15 | font-style: normal; 16 | font-display: block; 17 | } 18 | 19 | @font-face { 20 | font-family: 'aeonik-regular'; 21 | src: url("../../fonts/Aeonik-regular.otf?v=uc2a313ce") format("truetype"); 22 | font-weight: normal; 23 | font-style: normal; 24 | font-display: block; 25 | } 26 | 27 | @font-face { 28 | font-family: 'aeonik-light'; 29 | src: url("../../fonts/Aeonik-Light.otf?v=uc2a313ce") format("truetype"); 30 | font-weight: normal; 31 | font-style: normal; 32 | font-display: block; 33 | } 34 | 35 | /*#endregion*/ 36 | 37 | /*#region IranYekan font*/ 38 | 39 | @font-face { 40 | font-family: 'iranyekan'; 41 | src: url('../../fonts/Iran-Yekan.eot'); 42 | src: url('../../fonts/Iran-Yekan.eot?#iefix') format('embedded-opentype'),url('../../fonts/Iran-Yekan.woff') format('woff'),url('../../fonts/Iran-Yekan.ttf') format('truetype'),url('../../fonts/Iran-Yekan.svg#iran_sans') format('svg'); 43 | font-weight: normal; 44 | font-style: normal; 45 | } 46 | 47 | /*#endregion*/ 48 | 49 | /*#region BHoma font */ 50 | 51 | @font-face { 52 | font-family: 'bhoma'; 53 | src: url('../../fonts/BHoma.eot'); 54 | src: url('../../fonts/BHoma.eot?#iefix') format('embedded-opentype'), url('../../fonts/BHoma.woff2') format('woff2'), url('../../fonts/BHoma.woff') format('woff'), url('../../fonts/BHoma.ttf') format('truetype'); 55 | } 56 | 57 | /*#endregion */ -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/logo_inverse.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Src/Template.Domain/Shared/Claims.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using Bit.Core.Exceptions; 4 | 5 | // ReSharper disable InconsistentNaming 6 | 7 | namespace Template.Domain.Shared; 8 | 9 | public class DefaultRole 10 | { 11 | public string? Name { get; set; } 12 | 13 | public IEnumerable Claims { get; set; } = Array.Empty(); 14 | } 15 | 16 | public class DefaultRoles 17 | { 18 | public static DefaultRole Administrator => new() 19 | { 20 | Name = nameof(Administrator), 21 | Claims = Claims.GetAllAppClaims() 22 | }; 23 | } 24 | 25 | public static class Claims //* Do not change Claim values *// 26 | { 27 | public const string Settings_Permissions_View = nameof(Settings_Permissions_View); 28 | 29 | private static string[]? _claimNames; 30 | 31 | public static string GetClaimDisplayName(string claimType) 32 | { 33 | return claimType switch 34 | { 35 | Settings_Permissions_View => "مشاهده‌ی کاربران و نقش‌های سامانه", 36 | _ => throw new DomainLogicException("همه Claimها باید مقدار نمایشی داشته باشند.") 37 | }; 38 | } 39 | 40 | public static IEnumerable GetAllAppClaims() 41 | { 42 | return _claimNames ??= typeof(Claims) 43 | .GetFields(BindingFlags.Public | BindingFlags.Static) 44 | .Select(field => (string?)field.GetValue(null)) 45 | .ToArray(); 46 | } 47 | 48 | // Automatic Check for all Claims have DisplayName With Module Initializer 49 | [ModuleInitializer] 50 | public static void AutomaticCheckAllClaimsHaveDisplayName() 51 | { 52 | var allClaims = GetAllAppClaims(); 53 | 54 | foreach (var claim in allClaims) 55 | { 56 | GetClaimDisplayName(claim); //Throw error if no display is assigned for the Claim. 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/customize.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/logo_main.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | 7 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Src/Template.Application/Common/Implementations/StringProvider.cs: -------------------------------------------------------------------------------- 1 | using ATA.Food.Shared.Localization.Resources.ExceptionMessages; 2 | using ATA.Food.Shared.Localization.Resources.GeneralMessages; 3 | using Bit.Core.Exceptions; 4 | using Microsoft.Extensions.Localization; 5 | using Template.Application.Common.Contracts; 6 | using Template.Application.Common.Localization.Resources; 7 | 8 | namespace Template.Application.Common.Implementations; 9 | 10 | public class StringProvider : IStringProvider 11 | { 12 | public IStringLocalizer MessageStringsLocalizer { get; set; } = default!; //Property Injection 13 | public IStringLocalizer ExceptionStringsLocalizer { get; set; } = default!; //Property Injection 14 | 15 | /// 16 | /// Get value from MessageStrings resource 17 | /// 18 | /// Resource key 19 | /// 20 | public string? Message(string messageStringsKey) 21 | { 22 | return GetValueByKeyAndResource(messageStringsKey, StringResourceType.MessageStrings); 23 | } 24 | 25 | /// 26 | /// Get value from ExceptionStrings resource 27 | /// 28 | /// Resource key 29 | /// 30 | public string Exception(string exceptionStringsKey) 31 | { 32 | return GetValueByKeyAndResource(exceptionStringsKey, StringResourceType.ExceptionStrings) ?? string.Empty; 33 | } 34 | 35 | private string? GetValueByKeyAndResource(string key, StringResourceType stringResourceType) 36 | { 37 | if (stringResourceType == StringResourceType.MessageStrings) 38 | return MessageStringsLocalizer.GetString(key); 39 | 40 | if (stringResourceType == StringResourceType.ExceptionStrings) 41 | return ExceptionStringsLocalizer.GetString(key); 42 | 43 | throw new BadRequestException(); 44 | } 45 | 46 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/ConfirmDialog.razor.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Components; 2 | using System.ComponentModel.DataAnnotations; 3 | using Template.WebUI.Client.Contracts; 4 | 5 | namespace Template.WebUI.Client.Components; 6 | 7 | public partial class ConfirmDialog 8 | { 9 | // Props 10 | private bool _isLoading; 11 | private bool _isVisible; 12 | 13 | // DIs 14 | [Inject] public INotificationService NotificationService { get; set; } = default!; //Property Injection 15 | [Parameter] public string Title { get; set; } 16 | [Parameter, Required] public string Text { get; set; } 17 | //[Parameter] public string? SuccessMessage { get; set; } 18 | [Parameter] public RenderFragment ChildContent { get; set; } 19 | [Parameter] public EventCallback OnConfirm { get; set; } 20 | 21 | [Parameter] 22 | public bool IsVisible 23 | { 24 | get => _isVisible; 25 | set 26 | { 27 | if (value == _isVisible) return; 28 | _isVisible = value; 29 | 30 | _ = IsVisibleChanged.InvokeAsync(value); 31 | } 32 | } 33 | 34 | [Parameter] public EventCallback IsVisibleChanged { get; set; } 35 | 36 | public async Task OnActionConfirm() 37 | { 38 | if (_isLoading) return; 39 | 40 | _isLoading = true; 41 | try 42 | { 43 | await OnConfirm.InvokeAsync(); 44 | } 45 | finally 46 | { 47 | _isLoading = false; 48 | Hide(); 49 | } 50 | 51 | //ShowMessage(); //This method will call even the Confirm method throws error ;( 52 | } 53 | 54 | private void Hide() 55 | { 56 | IsVisible = false; 57 | } 58 | 59 | private void ShowMessage() 60 | { 61 | //if (string.IsNullOrEmpty(SuccessMessage) is false) 62 | //{ 63 | // NotificationService.AlertAsync(NotifType.Success, SuccessMessage); 64 | //} 65 | } 66 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/import.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.Application/Order/DTOs/OrderDto.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Helper.Extensions; 2 | using System.ComponentModel.DataAnnotations.Schema; 3 | using Template.Domain.Enums.Order; 4 | 5 | namespace Template.Application.Order.DTOs; 6 | 7 | [ComplexType] 8 | public record OrderDto 9 | { 10 | public int Id { get; set; } 11 | 12 | public int OrderStatus { get; set; } 13 | public string? OrderStatusDisplay => ((OrderStatus)OrderStatus).ToDisplayName(); 14 | 15 | public int CityId { get; set; } 16 | public string? CityDisplay => ((ReferenceCity)CityId).ToDisplayName(); 17 | 18 | public int GroupCalendarId { get; set; } 19 | 20 | public DateTime GroupCalendarDate { get; set; } //Flattening 21 | //public string GroupCalendarDateJalali => GroupCalendarDate.ToJalaliString(); 22 | // public string FoodDateDisplay => $"{GroupCalendarDateJalali} – {GroupCalendarDate.GetPersianWeekDayName()}"; 23 | 24 | public DateTime? DateTime { get; set; } 25 | 26 | public int? FoodMenuId { get; set; } 27 | public string? FoodMenuName { get; set; } //Flattening 28 | 29 | public int? TbzFoodMenuId { get; set; } 30 | public string? TbzFoodMenuName { get; set; } //Flattening 31 | 32 | public int UserPersonnelCode { get; set; } 33 | 34 | public string? UserFullName { get; set; } 35 | 36 | public string? UserWorkLocation { get; set; } 37 | 38 | public string? UserUnit { get; set; } 39 | 40 | public string? Location { get; set; } 41 | 42 | public bool IsActive { get; set; } = false; 43 | 44 | public int? CreatedBy { get; set; } 45 | 46 | public int? UpdatedBy { get; set; } 47 | 48 | //public DateTime? CreatedDate { get; set; } 49 | //public string RegisteredAtJalali => CreatedDate.ToJalaliString(false); 50 | 51 | public DateTime? UpdatedDate { get; set; } 52 | 53 | public bool IsHalfServing { get; set; } 54 | 55 | public bool IsArchived { get; set; } 56 | } -------------------------------------------------------------------------------- /Src/Template.Domain/Entities/Order/OrderEntity.cs: -------------------------------------------------------------------------------- 1 | using Template.Domain.Enums.Order; 2 | 3 | namespace Template.Domain.Entities.Order; 4 | 5 | public class OrderEntity : ATAEntity 6 | { 7 | public ReferenceCity CityId { get; private set; } 8 | 9 | public OrderStatus OrderStatus { get; private set; } 10 | 11 | public int GroupCalendarId { get; private set; } 12 | 13 | public int? UserId { get; private set; } 14 | 15 | public int UserPersonnelCode { get; private set; } 16 | 17 | public string? UserFullName { get; private set; } 18 | 19 | public string? Location { get; private set; } 20 | 21 | public bool IsActive { get; private set; } = false; 22 | 23 | public int? CreatedBy { get; private set; } 24 | 25 | public int? UpdatedBy { get; private set; } 26 | 27 | public DateTime? CreatedDate { get; private set; } 28 | 29 | public DateTime? UpdatedDate { get; private set; } 30 | 31 | public bool IsHalfServing { get; private set; } = false; 32 | 33 | // Nav Props 34 | 35 | // Constructors 36 | 37 | public OrderEntity() 38 | { 39 | // For EF 40 | } 41 | 42 | public OrderEntity(ReferenceCity cityId, OrderStatus orderStatus, int groupCalendarId, int? userId, int userPersonnelCode, string? userFullName, string? location, bool isActive, int? createdBy, int? updatedBy, DateTime? createdDate, DateTime? updatedDate, bool isHalfServing) 43 | { 44 | CityId = cityId; 45 | OrderStatus = orderStatus; 46 | GroupCalendarId = groupCalendarId; 47 | UserId = userId; 48 | UserPersonnelCode = userPersonnelCode; 49 | UserFullName = userFullName; 50 | Location = location; 51 | IsActive = isActive; 52 | CreatedBy = createdBy; 53 | UpdatedBy = updatedBy; 54 | CreatedDate = createdDate; 55 | UpdatedDate = updatedDate; 56 | IsHalfServing = isHalfServing; 57 | } 58 | 59 | // APIs 60 | public void ChangeOrderStatus(OrderStatus orderStatus) 61 | { 62 | OrderStatus = orderStatus; 63 | } 64 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/user.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Svg Vector Icons : http://www.onlinewebfonts.com/icon 6 | 7 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Components/ConfirmDialog.razor: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/export.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/components/_Toast.scss: -------------------------------------------------------------------------------- 1 | @import '../utils/_base.scss'; 2 | 3 | .toast-component { 4 | display: flex; 5 | align-items: center; 6 | padding: rem(9px) rem(15px); 7 | border-radius: 2px; 8 | 9 | &.Success { 10 | background-color: $success-notif-bg; 11 | border: 1px solid $success-notif-border; 12 | } 13 | 14 | &.Error { 15 | background-color: $error-notif-bg; 16 | border: 1px solid $error-notif-border; 17 | } 18 | 19 | &.Message { 20 | background-color: $info-notif-bg; 21 | border: 1px solid $info-notif-border; 22 | } 23 | 24 | &.Notify { 25 | background-color: $info-notif-bg; 26 | border: 1px solid $info-notif-border; 27 | } 28 | 29 | &.Warning { 30 | background-color: $warning-notif-bg; 31 | border: 1px solid $warning-notif-border; 32 | } 33 | 34 | .notif-type-icon-wrapper { 35 | margin-left: rem(18px); 36 | } 37 | 38 | .notif-message-wrapper { 39 | color: $black; 40 | margin-left: rem(16px); 41 | } 42 | } 43 | 44 | .blazored-toast-container { 45 | .blazored-toast-progressbar { 46 | height: rem(2px); 47 | 48 | span { 49 | height: rem(2px); 50 | background-color: #3f9a6f; 51 | left: 0; 52 | } 53 | } 54 | 55 | .Success + .blazored-toast-progressbar { 56 | span { 57 | background-color: $success-notif-border; 58 | } 59 | } 60 | 61 | .Error + .blazored-toast-progressbar { 62 | span { 63 | background-color: $error-notif-border; 64 | } 65 | } 66 | 67 | .Warning + .blazored-toast-progressbar { 68 | span { 69 | background-color: $warning-notif-border; 70 | } 71 | } 72 | 73 | .Notify + .blazored-toast-progressbar { 74 | span { 75 | background-color: $info-notif-border; 76 | } 77 | } 78 | 79 | .Message + .blazored-toast-progressbar { 80 | span { 81 | background-color: $info-notif-border; 82 | } 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/icons/my-foods.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Implementations/NotificationService.cs: -------------------------------------------------------------------------------- 1 | using Bit.Utils.Extensions; 2 | using Blazored.Toast; 3 | using Blazored.Toast.Services; 4 | using Microsoft.JSInterop; 5 | using Template.Domain.Shared; 6 | using Template.WebUI.Client.Components; 7 | using Template.WebUI.Client.Contracts; 8 | using Template.WebUI.Client.Enums; 9 | 10 | namespace Template.WebUI.Client.Implementations; 11 | 12 | public class NotificationService : INotificationService 13 | { 14 | private readonly IJSRuntime _jsRuntime; 15 | private readonly IToastService _toastService; 16 | 17 | public NotificationService(IJSRuntime jsRuntime, IToastService toastService) 18 | { 19 | _jsRuntime = jsRuntime; 20 | _toastService = toastService; 21 | } 22 | 23 | public async ValueTask AlertAsync(NotificationType notifType, string message, int waitSeconds = AppConstants.AlertDefaultTimeout, AlertifyPosition position = AlertifyPosition.TopCenter) 24 | { 25 | // Set position 26 | await _jsRuntime.InvokeVoidAsync("alertify.set", "notifier", "position", position.ToDisplayName()!); 27 | 28 | // Show alert 29 | string jsIdentifier = notifType switch 30 | { 31 | NotificationType.Success => "alertify.success", 32 | NotificationType.Error => "alertify.error", 33 | NotificationType.Message => "alertify.message", 34 | NotificationType.Notify => "alertify.notify", 35 | NotificationType.Warning => "alertify.warning", 36 | _ => throw new ArgumentOutOfRangeException(nameof(notifType), notifType, null) 37 | }; 38 | 39 | await _jsRuntime.InvokeVoidAsync(jsIdentifier, message, waitSeconds); 40 | } 41 | 42 | public void Toast(NotificationType notifType, string message, int waitSeconds = 5, bool showProgressBar = true) 43 | { 44 | // Toast Params 45 | var toastParameters = new ToastParameters(); 46 | // ReSharper disable once EntityNameCapturedOnly.Local 47 | Toast toastComponent; 48 | toastParameters.Add(nameof(toastComponent.Message), message); 49 | toastParameters.Add(nameof(toastComponent.NotifType), notifType); 50 | 51 | // Toast Settings 52 | var toastSettings = new ToastInstanceSettings(waitSeconds, showProgressBar); 53 | 54 | _toastService.ShowToast(toastParameters, toastSettings); 55 | } 56 | 57 | public ValueTask AlertGeneralError() 58 | { 59 | return AlertAsync(NotificationType.Error, "Some error happened"); 60 | } 61 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/pages/report/_personnel-report-page.scss: -------------------------------------------------------------------------------- 1 | @import '../../utils/_base.scss'; 2 | 3 | .personnel-report-page { 4 | 5 | @include lt-md { 6 | padding: 0 rem(15px); 7 | } 8 | 9 | .page-header-section { 10 | .page-header-wrapper { 11 | display: flex; 12 | 13 | @include lt-md { 14 | padding: rem(15px); 15 | display: flex; 16 | flex-direction: column; 17 | margin-top: rem(30px); 18 | text-align: center; 19 | } 20 | 21 | .back-to-select-food-link { 22 | color: $old-brick; 23 | font-weight: 700; 24 | } 25 | } 26 | } 27 | 28 | .filter-section { 29 | 30 | .filter-box { 31 | @include lt-xxl { 32 | margin-top: rem(15px); 33 | } 34 | } 35 | 36 | .food-date-filter { 37 | @include lt-md { 38 | margin-top: rem(15px); 39 | } 40 | } 41 | } 42 | 43 | .grid-section { 44 | .page-grid-wrapper { 45 | @include lt-md { 46 | margin-top: rem(40px); 47 | } 48 | } 49 | 50 | .orders-archive-status-container { 51 | display: flex; 52 | position: absolute; 53 | top: rem(18px); 54 | margin-right: rem(30px); 55 | z-index: 1; 56 | 57 | @include md { 58 | top: rem(22px); 59 | } 60 | 61 | @include lt-md { 62 | top: rem(-21px); 63 | } 64 | 65 | div { 66 | margin-left: rem(40px); 67 | padding: rem(10px) rem(5px); 68 | cursor: pointer; 69 | font-size: rem(14px); 70 | font-weight: normal; 71 | line-height: rem(20px); 72 | } 73 | 74 | .active { 75 | font-weight: bold; 76 | border-bottom: 4px solid $old-brick; 77 | border-radius: 1px; 78 | color: $old-brick; 79 | font-weight: bold; 80 | } 81 | } 82 | 83 | .deleted-order { 84 | background-color: $pale-red; 85 | 86 | &:hover { 87 | background-color: $pale-red-hover; 88 | } 89 | } 90 | } 91 | 92 | &.my-food-wrapper { 93 | padding: rem(110px) rem(40px) rem(40px) rem(40px); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/pages/report/_report-statistical-page.scss: -------------------------------------------------------------------------------- 1 | @import '../../utils/_base.scss'; 2 | 3 | .report-statistical-page { 4 | 5 | .container-table100 { 6 | margin: 0 auto; 7 | display: -webkit-box; 8 | display: -webkit-flex; 9 | display: -moz-box; 10 | display: -ms-flexbox; 11 | display: flex; 12 | flex-wrap: wrap; 13 | align-items: center; 14 | justify-content: center; 15 | padding: 33px 100px; 16 | 17 | .wrap-table100 { 18 | width: 100%; 19 | 20 | .table100 { 21 | width: 100%; 22 | position: relative; 23 | background-color: #fff; 24 | 25 | .table100-firstcol { 26 | background-color: #fff; 27 | position: absolute; 28 | z-index: 1000; 29 | width: 310px; 30 | top: 0; 31 | left: 0; 32 | 33 | table { 34 | background-color: transparent; 35 | 36 | tr { 37 | border-bottom: 1px solid #f2f2f2; 38 | 39 | th { 40 | font-family: $fontPrimary; 41 | font-size: 14px; 42 | color: #333; 43 | line-height: 1.4; 44 | text-transform: uppercase; 45 | padding-top: 21px; 46 | padding-bottom: 21px; 47 | text-align: left; 48 | } 49 | 50 | td { 51 | color: #666; 52 | font-family: $fontPrimary; 53 | font-size: 15px; 54 | line-height: 1.4; 55 | padding-top: 16px; 56 | padding-bottom: 16px; 57 | } 58 | 59 | .column1 { 60 | width: 100%; 61 | padding-left: 40px; 62 | } 63 | 64 | th, td { 65 | font-weight: unset; 66 | padding-right: 10px; 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - master 3 | 4 | variables: 5 | BuildConfiguration: 'Release' 6 | BuildPlatform: 'any cpu' 7 | PathToProjects: '**/ATA.Food.Server.Api.csproj' 8 | 9 | jobs: 10 | - job: Build 11 | displayName: Build Powered by YAML 12 | pool: 13 | name: Default 14 | steps: 15 | #task: Use .NET Core sdk 6.x 16 | - task: UseDotNet@2 17 | displayName: 'Use .NET Core sdk 6.x' 18 | inputs: 19 | version: 6.x 20 | 21 | #task: Use Node 6.x => Typscript build require it 22 | - task: NodeTool@0 23 | displayName: 'Use Node 6.x' 24 | 25 | #task: Restore 26 | - task: DotNetCoreCLI@2 27 | displayName: Restore 28 | inputs: 29 | command: restore 30 | projects: $(PathToProjects) 31 | vstsFeed: 'f5d0ca62-2bdf-417c-b55e-0f9a8acddc7a' 32 | 33 | #task: Powershell replace 'Client' with 'None' => In Directory.Build.props so the codes can be generated in client side without error 34 | - task: PowerShell@2 35 | displayName: Powershell replace 'Client' with 'None' 36 | inputs: 37 | targetType: 'inline' 38 | script: (Get-Content Directory.Build.props) -replace '>Client<' , '>None<' | Out-File Directory.Build.props 39 | 40 | #task: Build 41 | - task: DotNetCoreCLI@2 42 | displayName: Build 43 | inputs: 44 | command: 'build' 45 | projects: '$(PathToProjects)' 46 | arguments: '--configuration $(BuildConfiguration)' 47 | 48 | #task: Powershell replace 'None' to 'Client' => Now the codes are generated and everything is ready to full build of Bit Blazor application 49 | - task: PowerShell@2 50 | displayName: Powershell replace 'None' with 'Client' 51 | inputs: 52 | targetType: 'inline' 53 | script: (Get-Content Directory.Build.props) -replace '>None<' , '>Client<' | Out-File Directory.Build.props 54 | 55 | #task: Build 56 | - task: DotNetCoreCLI@2 57 | displayName: Build 58 | inputs: 59 | command: 'build' 60 | projects: '$(PathToProjects)' 61 | arguments: '--configuration $(BuildConfiguration)' 62 | 63 | #task: Publish 64 | - task: DotNetCoreCLI@2 65 | displayName: Publish 66 | inputs: 67 | command: publish 68 | publishWebProjects: false 69 | projects: $(PathToProjects) 70 | arguments: '--configuration $(BuildConfiguration) --output $(build.artifactstagingdirectory)' 71 | zipAfterPublish: True 72 | 73 | #task: Publish Artifact 74 | - task: PublishBuildArtifacts@1 75 | displayName: 'Publish Artifact' 76 | inputs: 77 | PathtoPublish: '$(build.artifactstagingdirectory)' 78 | condition: succeededOrFailed() 79 | -------------------------------------------------------------------------------- /Src/Template.Infrastructure/ConfigureServices/DataAccessInstaller.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Data; 2 | using ATABit.Data.Contracts; 3 | using ATABit.Data.Interceptors; 4 | using ATABit.Model.Data.Contracts; 5 | using Bit.Core.Contracts; 6 | using Bit.Data; 7 | using Bit.Data.Contracts; 8 | using Bit.Owin.Implementations; 9 | using Microsoft.Data.SqlClient; 10 | using Microsoft.EntityFrameworkCore; 11 | using Microsoft.Extensions.Hosting; 12 | using System.Data.Common; 13 | using System.Reflection; 14 | using Template.Domain.Options; 15 | using Template.Infrastructure.Common.Contracts; 16 | using Template.Infrastructure.Persistence.EF; 17 | using Template.Infrastructure.Persistence.EF.Repository; 18 | 19 | namespace Template.Infrastructure.ConfigureServices; 20 | 21 | public class DataAccessInstaller : IBitInstaller 22 | { 23 | public void InstallServices(IServiceCollection services, IDependencyManager dependencyManager, AppSettings appSettings) 24 | { 25 | services.AddATABitDataAccess(); 26 | 27 | dependencyManager.RegisterRepository(typeof(ATARepository<>).GetTypeInfo()); 28 | dependencyManager.RegisterRepository(typeof(ATARepositoryReadOnly<>).GetTypeInfo()); 29 | 30 | dependencyManager.RegisterGeneric(typeof(IATARepository<>).GetTypeInfo(), typeof(ATARepository<>).GetTypeInfo()); 31 | dependencyManager.RegisterGeneric(typeof(IReadOnlyATARepository<>).GetTypeInfo(), typeof(ATARepositoryReadOnly<>).GetTypeInfo()); 32 | 33 | dependencyManager.Register>(); 34 | 35 | dependencyManager.RegisterEfCoreDbContext((serviceProvider, optionsBuilder) => 36 | { 37 | var connectionString = appSettings.Server!.ConnectionStringOptions!.AppDbConnectionString!; 38 | 39 | DbConnection connection = serviceProvider.GetRequiredService().GetDbConnection(connectionString, rollbackOnScopeStatusFailure: true); 40 | 41 | optionsBuilder.UseSqlServer(connection, sqlServerOptions => 42 | { 43 | sqlServerOptions.CommandTimeout((int)TimeSpan.FromMinutes(1) 44 | .TotalSeconds); //Default is 30 seconds 45 | }); 46 | 47 | // Interceptors 48 | var entityAuditProvider = serviceProvider.GetRequiredService(); 49 | optionsBuilder.AddInterceptors(new AuditSaveChangesInterceptor(entityAuditProvider)); 50 | optionsBuilder.AddInterceptors(new FixSchemaInterceptor()); 51 | 52 | // Show Detailed Errors 53 | if (AspNetCoreAppEnvironmentsProvider.Current.HostingEnvironment.IsDevelopment()) 54 | optionsBuilder.EnableSensitiveDataLogging().EnableDetailedErrors(); 55 | }); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/wwwroot/css/abstracts/_responsive.scss: -------------------------------------------------------------------------------- 1 | @import '_functions.scss'; 2 | 3 | /// https://github.com/Necromancerx/media-queries-scss-mixins 4 | /// https://getbootstrap.com/docs/5.0/layout/breakpoints/ 5 | 6 | // media aliases and breakpoints 7 | $screen-sm-min: em(576.2px); 8 | $screen-md-min: em(768.2px); 9 | $screen-lg-min: em(992.2px); 10 | $screen-xl-min: em(1200.2px); 11 | $screen-xxl-min: em(1400.2px); 12 | 13 | $screen-xs-max: em(576px); 14 | $screen-sm-max: em(768px); 15 | $screen-md-max: em(992px); 16 | $screen-lg-max: em(1200px); 17 | $screen-xl-max: em(1400px); 18 | 19 | // media devices 20 | @mixin xs { 21 | @media screen and (max-width: #{$screen-xs-max}) { 22 | @content; 23 | } 24 | } 25 | 26 | @mixin sm { 27 | @media screen and (min-width: #{$screen-sm-min}) and (max-width: #{$screen-sm-max}) { 28 | @content; 29 | } 30 | } 31 | 32 | @mixin md { 33 | @media screen and (min-width: #{$screen-md-min}) and (max-width: #{$screen-md-max}) { 34 | @content; 35 | } 36 | } 37 | 38 | @mixin lg { 39 | @media screen and (min-width: #{$screen-lg-min}) and (max-width: #{$screen-lg-max}) { 40 | @content; 41 | } 42 | } 43 | 44 | @mixin xl { 45 | @media screen and (min-width: #{$screen-xl-min}) and (max-width: #{$screen-xl-max}) { 46 | @content; 47 | } 48 | } 49 | 50 | @mixin xxl { 51 | @media screen and (min-width: #{$screen-xxl-min}) { 52 | @content; 53 | } 54 | } 55 | 56 | // media lt queries 57 | @mixin lt-sm { 58 | @media screen and (max-width: #{$screen-sm-min}) { 59 | @content; 60 | } 61 | } 62 | 63 | @mixin lt-md { 64 | @media screen and (max-width: #{$screen-md-min}) { 65 | @content; 66 | } 67 | } 68 | 69 | @mixin lt-lg { 70 | @media screen and (max-width: #{$screen-lg-min}) { 71 | @content; 72 | } 73 | } 74 | 75 | @mixin lt-xl { 76 | @media screen and (max-width: #{$screen-xl-min}) { 77 | @content; 78 | } 79 | } 80 | 81 | @mixin lt-xxl { 82 | @media screen and (max-width: #{$screen-xxl-min}) { 83 | @content; 84 | } 85 | } 86 | 87 | // media gt queries 88 | @mixin gt-xs { 89 | @media screen and (min-width: #{$screen-xs-max}) { 90 | @content; 91 | } 92 | } 93 | 94 | @mixin gt-sm { 95 | @media screen and (min-width: #{$screen-sm-max}) { 96 | @content; 97 | } 98 | } 99 | 100 | @mixin gt-md { 101 | @media screen and (min-width: #{$screen-md-max}) { 102 | @content; 103 | } 104 | } 105 | 106 | @mixin gt-lg { 107 | @media screen and (min-width: #{$screen-lg-max}) { 108 | @content; 109 | } 110 | } 111 | 112 | @mixin gt-xl { 113 | @media screen and (min-width: #{$screen-xl-max}) { 114 | @content; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /Src/Template.WebUI.Client/Extensions/AuthStateTaskExtensions.cs: -------------------------------------------------------------------------------- 1 | using ATABit.Shared.Dto.Identity; 2 | using Microsoft.AspNetCore.Components.Authorization; 3 | using System.Security.Claims; 4 | 5 | namespace Template.WebUI.Client.Extensions 6 | { 7 | public static class AuthStateTaskExtensions 8 | { 9 | public static async Task IsAuthenticated(this Task authStateTask) 10 | { 11 | var authState = await authStateTask; 12 | 13 | return authState.User.Identity is not null; 14 | } 15 | 16 | public static async Task GetUserId(this Task authStateTask) 17 | { 18 | var authState = await authStateTask; 19 | 20 | return authState.User.Claims 21 | .Where(c => c.Type == ClaimTypes.NameIdentifier) 22 | .Select(c => c.Value) 23 | .FirstOrDefault(); 24 | } 25 | 26 | public static async Task GetUserFullName(this Task authStateTask) 27 | { 28 | var authState = await authStateTask; 29 | 30 | return authState.User.Claims 31 | .Where(c => c.Type == ClaimTypes.Name) 32 | .Select(c => c.Value) 33 | .FirstOrDefault(); 34 | } 35 | 36 | public static async Task GetPersonnelCode(this Task authStateTask) 37 | { 38 | var authState = await authStateTask; 39 | 40 | return authState.User.Claims 41 | .Where(c => c.Type.Equals(nameof(ATATokenClaims.PersonnelCode), StringComparison.OrdinalIgnoreCase)) 42 | .Select(c => c.Value) 43 | .FirstOrDefault(); 44 | } 45 | 46 | public static async Task GetIsMale(this Task authStateTask) 47 | { 48 | var authState = await authStateTask; 49 | 50 | var isMaleClaim = authState.User.Claims.Single(c => c.Type.Equals(nameof(ATATokenClaims.IsMale), StringComparison.OrdinalIgnoreCase)); 51 | 52 | return isMaleClaim.Value.Equals("true", StringComparison.OrdinalIgnoreCase); 53 | } 54 | 55 | public static async Task> GetUserRoles(this Task authStateTask) 56 | { 57 | var authState = await authStateTask; 58 | 59 | return authState.User.Claims 60 | .Where(c => c.Type == ClaimTypes.Role) 61 | .Select(c => c.Value) 62 | .ToList(); 63 | } 64 | 65 | public static async Task> GetUserClaims(this Task authStateTask) 66 | { 67 | var authState = await authStateTask; 68 | 69 | return authState.User.Claims 70 | .Select(c => c.Value) 71 | .ToList(); 72 | } 73 | } 74 | } --------------------------------------------------------------------------------