Happy coding!
16 |Type any login and password to enter.
35 | 36 |13 | 404 - Page not found 14 |
15 |
11 | Request ID: @ViewData["RequestId"]
12 |
17 | Swapping to Development environment will display more detailed information about the error that occurred. 18 |
19 |20 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 21 |
22 | -------------------------------------------------------------------------------- /RCB.JavaScript/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using RCB.JavaScript 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 3 | @addTagHelper *, Microsoft.AspNetCore.SpaServices 4 | -------------------------------------------------------------------------------- /RCB.JavaScript/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /RCB.JavaScript/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ "Serilog.Sinks.Console" ], 4 | "MinimumLevel": { 5 | "Default": "Debug", 6 | "Override": { 7 | "Microsoft.Hosting.Lifetime": "Information", 8 | "Microsoft.AspNetCore.Server.Kestrel": "Warning", 9 | "Microsoft.AspNetCore.Mvc.Razor.Compilation.DefaultViewCompiler": "Information", 10 | "Microsoft.AspNetCore.DataProtection": "Information", 11 | "Microsoft.AspNetCore.Mvc.ModelBinding": "Warning", 12 | "Microsoft.AspNetCore.Routing": "Information", 13 | "Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker": "Information", 14 | "Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware": "Information", 15 | "Microsoft.AspNetCore.Mvc.Infrastructure.SystemTextJsonResultExecutor": "Warning" 16 | } 17 | }, 18 | "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ], 19 | "WriteTo": [ 20 | { 21 | "Name": "Console", 22 | "Args": { 23 | "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console", 24 | "outputTemplate": "# [{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message}{NewLine}{Exception}" 25 | } 26 | }, 27 | { 28 | "Name": "File", 29 | "Args": { 30 | "path": "Logs\\log.log", 31 | "rollingInterval": "Day", 32 | "restrictedToMinimumLevel": "Error", 33 | "formatter": "Serilog.Formatting.Json.JsonFormatter" 34 | } 35 | } 36 | ] 37 | }, 38 | "AllowedHosts": "*" 39 | } -------------------------------------------------------------------------------- /RCB.JavaScript/appsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ "Serilog.Sinks.Console" ], 4 | "MinimumLevel": { 5 | "Default": "Information", 6 | "Override": { 7 | "System.Net.Http": "Warning", 8 | "Microsoft": "Error", 9 | "Microsoft.Hosting.Lifetime": "Information", 10 | "Serilog": "Error" 11 | } 12 | }, 13 | "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ], 14 | "WriteTo": [ 15 | { 16 | "Name": "Console", 17 | "Args": { 18 | "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console", 19 | "outputTemplate": "# [{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message}{NewLine}{Exception}" 20 | } 21 | }, 22 | { 23 | "Name": "File", 24 | "Args": { 25 | "path": "Logs\\log.json", 26 | "rollingInterval": "Day", 27 | "formatter": "Serilog.Formatting.Json.JsonFormatter" 28 | } 29 | } 30 | ] 31 | }, 32 | "AllowedHosts": "*" 33 | } -------------------------------------------------------------------------------- /RCB.JavaScript/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AppSettings": { 3 | }, 4 | "AllowedHosts": "*" 5 | } -------------------------------------------------------------------------------- /RCB.JavaScript/build.before.js: -------------------------------------------------------------------------------- 1 | var args = process.argv.slice(2); 2 | 3 | const modeTypes = { 4 | PRODUCTION: "PRODUCTION", 5 | DEVELOPMENT: "DEVELOPMENT", 6 | CLEAN: "CLEAN" 7 | }; 8 | 9 | var mode = modeTypes.DEVELOPMENT; 10 | 11 | // Note that those paths are mentioned in '.csproj' file in project building scenarios. 12 | var wwwrootDistDir = "wwwroot/dist"; 13 | var clientAppDistDir = "ClientApp/dist"; 14 | var productionBuildFileName = "production_build"; 15 | var productionBuildFilePath = wwwrootDistDir + "/" + productionBuildFileName; 16 | 17 | // Detect mode. 18 | args.forEach(arg => { 19 | var splitted = arg.toLowerCase().split("="); 20 | if (splitted.length < 2) { 21 | return; 22 | } 23 | var param = splitted[0].replace(/\-/g, ""); 24 | var value = splitted[1]; 25 | 26 | switch (param) { 27 | case "mode": 28 | mode = modeTypes.PRODUCTION.toLowerCase() === value ? modeTypes.PRODUCTION : modeTypes.DEVELOPMENT; 29 | } 30 | }); 31 | 32 | var fs = require("fs"); 33 | var fsAsync = fs.promises; 34 | var rimraf = require("rimraf"); 35 | 36 | const exists = (path) => { 37 | return fs.existsSync(path); 38 | }; 39 | 40 | const createEmptyFileAsync = async (filePath) => { 41 | let splitted = filePath.split("/"); 42 | 43 | if (splitted.length > 1) { 44 | // Create intermediate directories if necessary. 45 | 46 | var dirsToCreate = splitted.slice(0, splitted.length - 1); 47 | await fsAsync.mkdir(dirsToCreate.join("/"), { recursive: true }); 48 | } 49 | 50 | // Create empty file. 51 | fs.closeSync(fs.openSync(filePath, 'w')); 52 | }; 53 | 54 | /** 55 | * Clean up unnecessary files. 56 | * */ 57 | const cleanUpAsync = async () => { 58 | 59 | console.log("Deleting compiled scripts..."); 60 | 61 | await rimraf(wwwrootDistDir, (error) => { 62 | if (error) { 63 | console.log(error); 64 | } 65 | }); 66 | 67 | await rimraf(clientAppDistDir, (error) => { 68 | if (error) { 69 | console.log(error); 70 | } 71 | }); 72 | 73 | }; 74 | 75 | const startAsync = async () => { 76 | 77 | console.log("======= build.before.js mode: " + mode + " ======="); 78 | 79 | var doesProductionBuildFileExist = exists(productionBuildFilePath) 80 | 81 | var shouldClean = 82 | // Previous mode was "production". 83 | // So we need to clean up compiled scripts. 84 | doesProductionBuildFileExist || 85 | // Or we need to clean up after development mode 86 | // to remove those unnecessary files. 87 | mode == modeTypes.PRODUCTION || 88 | // Clean up only. 89 | mode == modeTypes.CLEAN; 90 | 91 | // Create indicator for next build operations. 92 | var shouldCreateProductionBuildFile = mode == modeTypes.PRODUCTION; 93 | 94 | if (shouldClean) { 95 | await cleanUpAsync(); 96 | } 97 | 98 | setTimeout(async () => { 99 | if (shouldCreateProductionBuildFile) { 100 | await createEmptyFileAsync(productionBuildFilePath); 101 | } 102 | }, 1000); 103 | }; 104 | 105 | startAsync(); -------------------------------------------------------------------------------- /RCB.JavaScript/download.js: -------------------------------------------------------------------------------- 1 | // This module allows you to download file using args --uri=[URI] --path=[FILEPATH] 2 | 3 | var args = process.argv.slice(2).map(arg => { 4 | 5 | var splitted = arg.toLowerCase().split("="); 6 | if (splitted.length < 2) { 7 | return; 8 | } 9 | 10 | var key = splitted[0].replace(/\-/g, ""); 11 | var value = splitted[1]; 12 | 13 | return { key, value }; 14 | }); 15 | 16 | var fs = require('fs'), 17 | request = require('request'); 18 | 19 | var download = function (uri, path) { 20 | 21 | request.head(uri, function (err, res, body) { 22 | 23 | var splitted = path.split("/"); 24 | 25 | var dirsToCreate = splitted.slice(0, splitted.length - 1); 26 | 27 | console.log(dirsToCreate.join("/")); 28 | 29 | fs.mkdir(dirsToCreate.join("/"), { recursive: true }, function () { }); 30 | 31 | console.log("Downloading file '" + uri + "' to path " + "'" + path + "'..."); 32 | 33 | request(uri) 34 | .pipe(fs.createWriteStream(path)) 35 | .on('close', function () { console.log("Download complete."); }); 36 | }); 37 | 38 | }; 39 | 40 | args.forEach((keyValuePair, index) => { 41 | switch (keyValuePair.key) { 42 | case "uri": 43 | var uri = keyValuePair.value; 44 | var path = args[index + 1].value; 45 | if (path) { 46 | if (!fs.existsSync(path)) { 47 | download(uri, path); 48 | } 49 | } 50 | break; 51 | } 52 | }); -------------------------------------------------------------------------------- /RCB.JavaScript/hosting.Production.json: -------------------------------------------------------------------------------- 1 | { "urls": "http://+:7000;https://+:7001" } -------------------------------------------------------------------------------- /RCB.JavaScript/jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "ClientApp", 4 | "target": "es5", 5 | "experimentalDecorators": true, 6 | "allowSyntheticDefaultImports": true, 7 | "paths": { 8 | "@Store/*": [ "./store/*" ], 9 | "@Core/*": [ "./core/*" ], 10 | "@Components/*": [ "./components/*" ], 11 | "@Images/*": [ "./images/*" ], 12 | "@Styles/*": [ "./styles/*" ], 13 | "@Pages/*": [ "./pages/*" ], 14 | "@Layouts/*": [ "./layouts/*" ], 15 | "@Services/*": [ "./services/*" ], 16 | "@Utils": [ "./utils.ts" ] 17 | } 18 | }, 19 | "exclude": [ 20 | "bin", 21 | "node_modules", 22 | "AspNet" 23 | ] 24 | } -------------------------------------------------------------------------------- /RCB.JavaScript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webapp", 3 | "private": true, 4 | "version": "0.0.0", 5 | "devDependencies": { 6 | "@babel/core": "7.9.6", 7 | "@babel/plugin-proposal-class-properties": "7.8.3", 8 | "@babel/plugin-proposal-decorators": "7.8.3", 9 | "@babel/plugin-proposal-optional-catch-binding": "7.8.3", 10 | "@babel/plugin-transform-runtime": "7.9.6", 11 | "@babel/preset-env": "7.9.6", 12 | "@babel/preset-react": "7.9.4", 13 | "@hot-loader/react-dom": "16.13.0", 14 | "aspnet-prerendering": "3.0.1", 15 | "aspnet-webpack-react": "4.0.0", 16 | "babel-loader": "8.1.0", 17 | "babel-plugin-import": "1.13.0", 18 | "case-sensitive-paths-webpack-plugin": "2.3.0", 19 | "css-loader": "3.5.3", 20 | "cssnano": "4.1.10", 21 | "file-loader": "6.0.0", 22 | "ignore-loader": "0.1.2", 23 | "mini-css-extract-plugin": "0.9.0", 24 | "node-noop": "1.0.0", 25 | "node-sass": "4.14.1", 26 | "optimize-css-assets-webpack-plugin": "5.0.3", 27 | "react-dev-utils": "10.2.1", 28 | "react-hot-loader": "4.12.21", 29 | "rimraf": "3.0.2", 30 | "sass-loader": "8.0.2", 31 | "style-loader": "1.2.1", 32 | "terser-webpack-plugin": "3.0.1", 33 | "url-loader": "4.1.0", 34 | "webpack": "4.43.0", 35 | "webpack-cli": "3.3.11", 36 | "webpack-dev-middleware": "3.7.2", 37 | "webpack-hot-middleware": "2.25.0", 38 | "webpack-merge": "4.2.2" 39 | }, 40 | "dependencies": { 41 | "@reduxjs/toolkit": "1.3.6", 42 | "aspnet-webpack": "3.0.0", 43 | "aspnet-webpack-react": "4.0.0", 44 | "awesome-debounce-promise": "2.1.0", 45 | "axios": "0.19.2", 46 | "bootstrap": "4.4.1", 47 | "connected-react-router": "6.8.0", 48 | "core-js": "^3.6.5", 49 | "custom-event-polyfill": "1.0.7", 50 | "domain-wait": "^1.3.0", 51 | "event-source-polyfill": "1.0.12", 52 | "formik": "2.1.4", 53 | "history": "4.10.1", 54 | "nval-tippy": "^1.0.40", 55 | "query-string": "6.12.1", 56 | "react": "16.13.1", 57 | "react-bootstrap": "1.0.1", 58 | "react-dom": "16.13.1", 59 | "react-helmet": "6.0.0", 60 | "react-paginating": "1.4.0", 61 | "react-redux": "7.2.0", 62 | "react-router": "5.1.2", 63 | "react-router-bootstrap": "0.25.0", 64 | "react-router-dom": "5.1.2", 65 | "react-toastify": "5.5.0", 66 | "redux": "4.0.5", 67 | "redux-thunk": "2.3.0", 68 | "sass": "1.26.5", 69 | "serialize-javascript": "^4.0.0" 70 | }, 71 | "scripts": { 72 | "postinstall": "node download.js --uri=https://github.com/sass/node-sass/releases/download/v4.14.1/linux-x64-72_binding.node --path=node_modules/node-sass/vendor/linux-x64-72/binding.node", 73 | "build:dev": "node build.before.js --mode=development && node ./node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js && node ./node_modules/webpack/bin/webpack.js --config webpack.config.js", 74 | "build:prod": "node build.before.js --mode=production && node ./node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js --env.prod=true && node ./node_modules/webpack/bin/webpack.js --config webpack.config.js --env.prod=true" 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /RCB.JavaScript/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickMaev/react-core-boilerplate/6f6e2eedd82dc8454bde543364557eb00413273e/RCB.JavaScript/wwwroot/favicon.ico -------------------------------------------------------------------------------- /RCB.TypeScript/.dockerignore: -------------------------------------------------------------------------------- 1 | [B|b]in 2 | [O|o]bj -------------------------------------------------------------------------------- /RCB.TypeScript/AppSettings.cs: -------------------------------------------------------------------------------- 1 | namespace RCB.TypeScript 2 | { 3 | public class AppSettings 4 | { 5 | public static AppSettings Default { get; } 6 | 7 | protected AppSettings() 8 | { 9 | } 10 | 11 | static AppSettings() 12 | { 13 | Default = new AppSettings(); 14 | } 15 | 16 | public bool IsDevelopment => Program.EnvironmentName == "Development"; 17 | } 18 | } -------------------------------------------------------------------------------- /RCB.TypeScript/ClientApp/boot-client.tsx: -------------------------------------------------------------------------------- 1 | // Import polyfills. 2 | import "core-js/stable"; 3 | import "custom-event-polyfill"; 4 | import "event-source-polyfill"; 5 | 6 | // Import global styles. 7 | import "bootstrap/dist/css/bootstrap.min.css"; 8 | import "@Styles/main.scss"; 9 | import "@Styles/loaders/queryLoader.scss"; 10 | import "react-toastify/dist/ReactToastify.css"; 11 | 12 | // Other imports. 13 | import * as React from "react"; 14 | import * as ReactDOM from "react-dom"; 15 | import configureStore from "@Store/configureStore"; 16 | import SessionManager, { IIsomorphicSessionData, ISsrSessionData } from "@Core/session"; 17 | import { AppContainer } from "react-hot-loader"; 18 | import { Provider } from "react-redux"; 19 | import { ConnectedRouter } from "connected-react-router"; 20 | import { createBrowserHistory } from "history"; 21 | import { isNode, showApplicationLoader, hideApplicationLoader } from "@Utils"; 22 | import * as RoutesModule from "./routes"; 23 | import { IApplicationState } from "@Store/index"; 24 | let routes = RoutesModule.routes; 25 | 26 | function setupSession() { 27 | if (!isNode()) { 28 | SessionManager.resetSession(); 29 | SessionManager.initSession({ 30 | isomorphic: window["session"] as IIsomorphicSessionData, 31 | ssr: {} as ISsrSessionData 32 | }); 33 | } 34 | }; 35 | 36 | function setupGlobalPlugins() { 37 | // Use this function to configure plugins on the client side. 38 | }; 39 | 40 | function setupEvents() { 41 | 42 | showApplicationLoader(); 43 | 44 | document.addEventListener("DOMContentLoaded", () => { 45 | hideApplicationLoader(); 46 | }); 47 | }; 48 | 49 | // Create browser history to use in the Redux store. 50 | const baseUrl = document.getElementsByTagName("base")[0].getAttribute("href")!; 51 | const history = createBrowserHistory({ basename: baseUrl }); 52 | 53 | // Get the application-wide store instance, prepopulating with state from the server where available. 54 | const initialState = (window as any).initialReduxState as IApplicationState; 55 | const store = configureStore(history, initialState); 56 | 57 | function renderApp() { 58 | // This code starts up the React app when it runs in a browser. 59 | // It sets up the routing configuration and injects the app into a DOM element. 60 | ReactDOM.hydrate( 61 |Happy coding!
19 |16 | 404 - Page not found 17 |
18 |
11 | Request ID: @ViewData["RequestId"]
12 |
17 | Swapping to Development environment will display more detailed information about the error that occurred. 18 |
19 |20 | Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application. 21 |
22 | -------------------------------------------------------------------------------- /RCB.TypeScript/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using RCB.TypeScript 2 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 3 | @addTagHelper *, Microsoft.AspNetCore.SpaServices 4 | -------------------------------------------------------------------------------- /RCB.TypeScript/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /RCB.TypeScript/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ "Serilog.Sinks.Console" ], 4 | "MinimumLevel": { 5 | "Default": "Debug", 6 | "Override": { 7 | "Microsoft.Hosting.Lifetime": "Information", 8 | "Microsoft.AspNetCore.Server.Kestrel": "Warning", 9 | "Microsoft.AspNetCore.Mvc.Razor.Compilation.DefaultViewCompiler": "Information", 10 | "Microsoft.AspNetCore.DataProtection": "Information", 11 | "Microsoft.AspNetCore.Mvc.ModelBinding": "Warning", 12 | "Microsoft.AspNetCore.Routing": "Information", 13 | "Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker": "Information", 14 | "Microsoft.AspNetCore.StaticFiles.StaticFileMiddleware": "Information", 15 | "Microsoft.AspNetCore.Mvc.Infrastructure.SystemTextJsonResultExecutor": "Warning" 16 | } 17 | }, 18 | "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ], 19 | "WriteTo": [ 20 | { 21 | "Name": "Console", 22 | "Args": { 23 | "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console", 24 | "outputTemplate": "# [{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message}{NewLine}{Exception}" 25 | } 26 | }, 27 | { 28 | "Name": "File", 29 | "Args": { 30 | "path": "Logs\\log.log", 31 | "rollingInterval": "Day", 32 | "restrictedToMinimumLevel": "Error", 33 | "formatter": "Serilog.Formatting.Json.JsonFormatter" 34 | } 35 | } 36 | ] 37 | }, 38 | "AllowedHosts": "*" 39 | } -------------------------------------------------------------------------------- /RCB.TypeScript/appsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "Serilog": { 3 | "Using": [ "Serilog.Sinks.Console" ], 4 | "MinimumLevel": { 5 | "Default": "Information", 6 | "Override": { 7 | "System.Net.Http": "Warning", 8 | "Microsoft": "Error", 9 | "Microsoft.Hosting.Lifetime": "Information", 10 | "Serilog": "Error" 11 | } 12 | }, 13 | "Enrich": [ "FromLogContext", "WithMachineName", "WithProcessId", "WithThreadId" ], 14 | "WriteTo": [ 15 | { 16 | "Name": "Console", 17 | "Args": { 18 | "theme": "Serilog.Sinks.SystemConsole.Themes.AnsiConsoleTheme::Code, Serilog.Sinks.Console", 19 | "outputTemplate": "# [{Timestamp:HH:mm:ss} {Level:u3}] [{SourceContext}] {Message}{NewLine}{Exception}" 20 | } 21 | }, 22 | { 23 | "Name": "File", 24 | "Args": { 25 | "path": "Logs\\log.json", 26 | "rollingInterval": "Day", 27 | "formatter": "Serilog.Formatting.Json.JsonFormatter" 28 | } 29 | } 30 | ] 31 | }, 32 | "AllowedHosts": "*" 33 | } -------------------------------------------------------------------------------- /RCB.TypeScript/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "AppSettings": { 3 | }, 4 | "AllowedHosts": "*" 5 | } -------------------------------------------------------------------------------- /RCB.TypeScript/build.before.js: -------------------------------------------------------------------------------- 1 | var args = process.argv.slice(2); 2 | 3 | const modeTypes = { 4 | PRODUCTION: "PRODUCTION", 5 | DEVELOPMENT: "DEVELOPMENT", 6 | CLEAN: "CLEAN" 7 | }; 8 | 9 | var mode = modeTypes.DEVELOPMENT; 10 | 11 | // Note that those paths are mentioned in '.csproj' file in project building scenarios. 12 | var wwwrootDistDir = "wwwroot/dist"; 13 | var clientAppDistDir = "ClientApp/dist"; 14 | var productionBuildFileName = "production_build"; 15 | var productionBuildFilePath = wwwrootDistDir + "/" + productionBuildFileName; 16 | 17 | // Detect mode. 18 | args.forEach(arg => { 19 | var splitted = arg.toLowerCase().split("="); 20 | if (splitted.length < 2) { 21 | return; 22 | } 23 | var param = splitted[0].replace(/\-/g, ""); 24 | var value = splitted[1]; 25 | 26 | switch (param) { 27 | case "mode": 28 | mode = modeTypes.PRODUCTION.toLowerCase() === value ? modeTypes.PRODUCTION : modeTypes.DEVELOPMENT; 29 | } 30 | }); 31 | 32 | var fs = require("fs"); 33 | var fsAsync = fs.promises; 34 | var rimraf = require("rimraf"); 35 | 36 | const exists = (path) => { 37 | return fs.existsSync(path); 38 | }; 39 | 40 | const createEmptyFileAsync = async (filePath) => { 41 | let splitted = filePath.split("/"); 42 | 43 | if (splitted.length > 1) { 44 | // Create intermediate directories if necessary. 45 | 46 | var dirsToCreate = splitted.slice(0, splitted.length - 1); 47 | await fsAsync.mkdir(dirsToCreate.join("/"), { recursive: true }); 48 | } 49 | 50 | // Create empty file. 51 | fs.closeSync(fs.openSync(filePath, 'w')); 52 | }; 53 | 54 | /** 55 | * Clean up unnecessary files. 56 | * */ 57 | const cleanUpAsync = async () => { 58 | 59 | console.log("Deleting compiled scripts..."); 60 | 61 | await rimraf(wwwrootDistDir, (error) => { 62 | if (error) { 63 | console.log(error); 64 | } 65 | }); 66 | 67 | await rimraf(clientAppDistDir, (error) => { 68 | if (error) { 69 | console.log(error); 70 | } 71 | }); 72 | 73 | }; 74 | 75 | const startAsync = async () => { 76 | 77 | console.log("======= build.before.js mode: " + mode + " ======="); 78 | 79 | var doesProductionBuildFileExist = exists(productionBuildFilePath) 80 | 81 | var shouldClean = 82 | // Previous mode was "production". 83 | // So we need to clean up compiled scripts. 84 | doesProductionBuildFileExist || 85 | // Or we need to clean up after development mode 86 | // to remove those unnecessary files. 87 | mode == modeTypes.PRODUCTION || 88 | // Clean up only. 89 | mode == modeTypes.CLEAN; 90 | 91 | // Create indicator for next build operations. 92 | var shouldCreateProductionBuildFile = mode == modeTypes.PRODUCTION; 93 | 94 | if (shouldClean) { 95 | await cleanUpAsync(); 96 | } 97 | 98 | setTimeout(async () => { 99 | if (shouldCreateProductionBuildFile) { 100 | await createEmptyFileAsync(productionBuildFilePath); 101 | } 102 | }, 1000); 103 | }; 104 | 105 | startAsync(); -------------------------------------------------------------------------------- /RCB.TypeScript/download.js: -------------------------------------------------------------------------------- 1 | // This module allows you to download file using args --uri=[URI] --path=[FILEPATH] 2 | 3 | var args = process.argv.slice(2).map(arg => { 4 | 5 | var splitted = arg.toLowerCase().split("="); 6 | if (splitted.length < 2) { 7 | return; 8 | } 9 | 10 | var key = splitted[0].replace(/\-/g, ""); 11 | var value = splitted[1]; 12 | 13 | return { key, value }; 14 | }); 15 | 16 | var fs = require('fs'), 17 | request = require('request'); 18 | 19 | var download = function (uri, path) { 20 | 21 | request.head(uri, function (err, res, body) { 22 | 23 | var splitted = path.split("/"); 24 | 25 | var dirsToCreate = splitted.slice(0, splitted.length - 1); 26 | 27 | console.log(dirsToCreate.join("/")); 28 | 29 | fs.mkdir(dirsToCreate.join("/"), { recursive: true }, function () { }); 30 | 31 | console.log("Downloading file '" + uri + "' to path " + "'" + path + "'..."); 32 | 33 | request(uri) 34 | .pipe(fs.createWriteStream(path)) 35 | .on('close', function () { console.log("Download complete."); }); 36 | }); 37 | 38 | }; 39 | 40 | args.forEach((keyValuePair, index) => { 41 | switch (keyValuePair.key) { 42 | case "uri": 43 | var uri = keyValuePair.value; 44 | var path = args[index + 1].value; 45 | if (path) { 46 | if (!fs.existsSync(path)) { 47 | download(uri, path); 48 | } 49 | } 50 | break; 51 | } 52 | }); -------------------------------------------------------------------------------- /RCB.TypeScript/hosting.Production.json: -------------------------------------------------------------------------------- 1 | { "urls": "https://+:7001;http://+:7000" } -------------------------------------------------------------------------------- /RCB.TypeScript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webapp", 3 | "private": true, 4 | "version": "0.0.0", 5 | "devDependencies": { 6 | "@babel/core": "7.9.6", 7 | "@hot-loader/react-dom": "16.13.0", 8 | "@types/history": "4.7.5", 9 | "@types/react": "16.9.34", 10 | "@types/react-dom": "16.9.7", 11 | "@types/react-helmet": "5.0.15", 12 | "@types/react-redux": "7.1.8", 13 | "@types/react-router": "5.1.7", 14 | "@types/react-router-dom": "5.1.5", 15 | "@types/webpack": "4.41.12", 16 | "@types/webpack-env": "1.15.2", 17 | "aspnet-prerendering": "3.0.1", 18 | "babel-loader": "8.1.0", 19 | "babel-plugin-import": "1.13.0", 20 | "case-sensitive-paths-webpack-plugin": "2.3.0", 21 | "css-loader": "3.5.3", 22 | "cssnano": "4.1.10", 23 | "file-loader": "6.0.0", 24 | "fork-ts-checker-webpack-plugin": "4.1.3", 25 | "ignore-loader": "0.1.2", 26 | "mini-css-extract-plugin": "0.9.0", 27 | "node-noop": "1.0.0", 28 | "node-sass": "4.14.1", 29 | "optimize-css-assets-webpack-plugin": "5.0.3", 30 | "react-dev-utils": "10.2.1", 31 | "react-hot-loader": "4.12.21", 32 | "rimraf": "3.0.2", 33 | "sass-loader": "8.0.2", 34 | "style-loader": "1.2.1", 35 | "terser-webpack-plugin": "3.0.1", 36 | "ts-loader": "7.0.3", 37 | "ts-nameof": "4.2.2", 38 | "ts-nameof-loader": "1.0.2", 39 | "typescript": "3.8.3", 40 | "url-loader": "4.1.0", 41 | "webpack": "4.43.0", 42 | "webpack-cli": "3.3.11", 43 | "webpack-dev-middleware": "3.7.2", 44 | "webpack-hot-middleware": "2.25.0", 45 | "webpack-merge": "4.2.2", 46 | "aspnet-webpack-react": "4.0.0" 47 | }, 48 | "dependencies": { 49 | "@reduxjs/toolkit": "1.3.6", 50 | "aspnet-webpack": "3.0.0", 51 | "awesome-debounce-promise": "2.1.0", 52 | "axios": "0.19.2", 53 | "bootstrap": "^4.4.1", 54 | "connected-react-router": "6.8.0", 55 | "core-js": "^3.6.5", 56 | "custom-event-polyfill": "1.0.7", 57 | "domain-wait": "^1.3.0", 58 | "event-source-polyfill": "1.0.12", 59 | "formik": "2.1.4", 60 | "history": "4.10.1", 61 | "nval-tippy": "^1.0.40", 62 | "query-string": "6.12.1", 63 | "react": "16.13.1", 64 | "react-bootstrap": "1.0.1", 65 | "react-dom": "16.13.1", 66 | "react-helmet": "6.0.0", 67 | "react-paginating": "1.4.0", 68 | "react-redux": "7.2.0", 69 | "react-router": "5.1.2", 70 | "react-router-bootstrap": "0.25.0", 71 | "react-router-dom": "5.1.2", 72 | "react-toastify": "5.5.0", 73 | "redux": "4.0.5", 74 | "redux-thunk": "2.3.0", 75 | "sass": "1.26.5", 76 | "serialize-javascript": "^4.0.0" 77 | }, 78 | "scripts": { 79 | "postinstall": "node download.js --uri=https://github.com/sass/node-sass/releases/download/v4.14.1/linux-x64-72_binding.node --path=node_modules/node-sass/vendor/linux-x64-72/binding.node", 80 | "build:dev": "node build.before.js --mode=development && node ./node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js && node ./node_modules/webpack/bin/webpack.js --config webpack.config.js", 81 | "build:prod": "node build.before.js --mode=production && node ./node_modules/webpack/bin/webpack.js --config webpack.config.vendor.js --env.prod=true && node ./node_modules/webpack/bin/webpack.js --config webpack.config.js --env.prod=true" 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /RCB.TypeScript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": "ClientApp", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "target": "es5", 7 | "jsx": "react", 8 | "sourceMap": true, 9 | "experimentalDecorators": true, 10 | "skipDefaultLibCheck": true, 11 | "strict": false, 12 | "noImplicitReturns": true, 13 | "allowUnusedLabels": false, 14 | "allowSyntheticDefaultImports": true, 15 | "noFallthroughCasesInSwitch": true, 16 | "lib": [ "es6", "dom" ], 17 | "types": [ "webpack-env" ], 18 | "paths": { 19 | "@Store/*": [ "./store/*" ], 20 | "@Core/*": [ "./core/*" ], 21 | "@Components/*": [ "./components/*" ], 22 | "@Images/*": [ "./images/*" ], 23 | "@Styles/*": [ "./styles/*" ], 24 | "@Models/*": [ "./models/*" ], 25 | "@Pages/*": [ "./pages/*" ], 26 | "@Layouts/*": [ "./layouts/*" ], 27 | "@Services/*": [ "./services/*" ], 28 | "@Utils": [ "./utils.ts" ] 29 | } 30 | }, 31 | "exclude": [ 32 | "bin", 33 | "node_modules", 34 | "AspNet" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /RCB.TypeScript/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickMaev/react-core-boilerplate/6f6e2eedd82dc8454bde543364557eb00413273e/RCB.TypeScript/wwwroot/favicon.ico -------------------------------------------------------------------------------- /RCB.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29709.97 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RCB.TypeScript", "RCB.TypeScript\RCB.TypeScript.csproj", "{4C50845F-9A28-4D5D-A23C-01876AD2931D}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RCB.JavaScript", "RCB.JavaScript\RCB.JavaScript.csproj", "{B0280670-40E0-411D-AFBF-0949269380BD}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {4C50845F-9A28-4D5D-A23C-01876AD2931D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {4C50845F-9A28-4D5D-A23C-01876AD2931D}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {4C50845F-9A28-4D5D-A23C-01876AD2931D}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {4C50845F-9A28-4D5D-A23C-01876AD2931D}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {B0280670-40E0-411D-AFBF-0949269380BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {B0280670-40E0-411D-AFBF-0949269380BD}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {B0280670-40E0-411D-AFBF-0949269380BD}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {B0280670-40E0-411D-AFBF-0949269380BD}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {C7D66D96-5A29-442E-882D-EC542D510714} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /TemplateIcon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NickMaev/react-core-boilerplate/6f6e2eedd82dc8454bde543364557eb00413273e/TemplateIcon.png -------------------------------------------------------------------------------- /azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | # ASP.NET Core (.NET Framework) 2 | # Build and test ASP.NET Core projects targeting the full .NET Framework. 3 | # Add steps that publish symbols, save build artifacts, and more: 4 | # https://docs.microsoft.com/azure/devops/pipelines/languages/dotnet-core 5 | 6 | trigger: 7 | - master 8 | 9 | pool: 10 | vmImage: 'windows-latest' 11 | 12 | variables: 13 | solution: '**/*.sln' 14 | buildPlatform: 'Any CPU' 15 | buildConfiguration: 'Release' 16 | 17 | steps: 18 | - task: NuGetToolInstaller@1 19 | 20 | - task: NuGetCommand@2 21 | inputs: 22 | restoreSolution: '$(solution)' 23 | 24 | - task: VSBuild@1 25 | inputs: 26 | solution: '$(solution)' 27 | msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:DesktopBuildPackageLocation="$(build.artifactStagingDirectory)\WebApp.zip" /p:DeployIisAppPath="Default Web Site"' 28 | platform: '$(buildPlatform)' 29 | configuration: '$(buildConfiguration)' 30 | 31 | - task: VSTest@2 32 | inputs: 33 | platform: '$(buildPlatform)' 34 | configuration: '$(buildConfiguration)' 35 | --------------------------------------------------------------------------------