├── .gitignore ├── Candor.Sample.MvcWeb ├── App_Start │ ├── BundleConfig.cs │ ├── FilterConfig.cs │ ├── RouteConfig.cs │ └── WebApiConfig.cs ├── Candor.Sample.MvcWeb.csproj ├── Content │ ├── Site.css │ ├── bootstrap.css │ └── bootstrap.min.css ├── Controllers │ └── HomeController.cs ├── Global.asax ├── Global.asax.cs ├── Project_Readme.html ├── Properties │ └── AssemblyInfo.cs ├── Scripts │ ├── NgApp │ │ └── favicon.ico │ ├── _references.js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── jquery-1.10.2.intellisense.js │ ├── jquery-1.10.2.js │ ├── jquery-1.10.2.min.js │ ├── jquery-1.10.2.min.map │ ├── jquery.validate-vsdoc.js │ ├── jquery.validate.js │ ├── jquery.validate.min.js │ ├── jquery.validate.unobtrusive.js │ ├── jquery.validate.unobtrusive.min.js │ ├── modernizr-2.6.2.js │ ├── respond.js │ └── respond.min.js ├── Views │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ ├── Index.cshtml │ │ └── NgApp.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ └── _Layout.cshtml │ ├── Web.config │ └── _ViewStart.cshtml ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── favicon.ico ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff └── packages.config ├── Candor.Sample.sln ├── Candor.Sample ├── Candor.Sample.csproj ├── Location.cs ├── LocationProvider.cs ├── Mocks │ ├── MockLocationProvider.cs │ ├── MockPersonProvider.cs │ └── MockTripProvider.cs ├── Person.cs ├── PersonProvider.cs ├── Properties │ └── AssemblyInfo.cs ├── Trip.cs ├── TripCriteria.cs ├── TripProvider.cs └── packages.config ├── LICENSE ├── README.md ├── SampleAngular2Mvc ├── ApiControllers │ ├── LocationController.cs │ ├── PersonController.cs │ └── TripController.cs ├── App_Data │ ├── locations.json │ ├── people.json │ └── trips.json ├── App_Start │ ├── BundleConfig.cs │ ├── FilterConfig.cs │ ├── IdentityConfig.cs │ ├── ProviderBootstrapper.cs │ ├── RouteConfig.cs │ ├── Startup.Auth.cs │ └── WebApiConfig.cs ├── Content │ ├── Site.css │ ├── bootstrap.css │ └── bootstrap.min.css ├── Controllers │ ├── AccountController.cs │ ├── HomeController.cs │ └── ManageController.cs ├── Global.asax ├── Global.asax.cs ├── Models │ ├── AccountViewModels.cs │ ├── IdentityModels.cs │ ├── LocationModel.cs │ ├── ManageViewModels.cs │ ├── PersonModel.cs │ └── TripModel.cs ├── Project_Readme.html ├── Properties │ └── AssemblyInfo.cs ├── SampleAngular2Mvc.csproj ├── Scripts │ ├── _references.js │ ├── bootstrap.js │ ├── bootstrap.min.js │ ├── jquery-1.10.2.intellisense.js │ ├── jquery-1.10.2.js │ ├── jquery-1.10.2.min.js │ ├── jquery-1.10.2.min.map │ ├── jquery.validate-vsdoc.js │ ├── jquery.validate.js │ ├── jquery.validate.min.js │ ├── jquery.validate.unobtrusive.js │ ├── jquery.validate.unobtrusive.min.js │ ├── modernizr-2.6.2.js │ ├── respond.js │ ├── respond.min.js │ └── systemjs.config.js ├── Startup.cs ├── Views │ ├── Account │ │ ├── ConfirmEmail.cshtml │ │ ├── ExternalLoginConfirmation.cshtml │ │ ├── ExternalLoginFailure.cshtml │ │ ├── ForgotPassword.cshtml │ │ ├── ForgotPasswordConfirmation.cshtml │ │ ├── Login.cshtml │ │ ├── Register.cshtml │ │ ├── ResetPassword.cshtml │ │ ├── ResetPasswordConfirmation.cshtml │ │ ├── SendCode.cshtml │ │ ├── VerifyCode.cshtml │ │ └── _ExternalLoginsListPartial.cshtml │ ├── Home │ │ ├── About.cshtml │ │ ├── Contact.cshtml │ │ ├── Index.cshtml │ │ └── NgApp.cshtml │ ├── Manage │ │ ├── AddPhoneNumber.cshtml │ │ ├── ChangePassword.cshtml │ │ ├── Index.cshtml │ │ ├── ManageLogins.cshtml │ │ ├── SetPassword.cshtml │ │ └── VerifyPhoneNumber.cshtml │ ├── Shared │ │ ├── Error.cshtml │ │ ├── Lockout.cshtml │ │ ├── _Layout.cshtml │ │ ├── _LoginPartial.cshtml │ │ └── _NgLayout.cshtml │ ├── Web.config │ └── _ViewStart.cshtml ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── app │ ├── app-chrome │ │ ├── app-chrome.module.ts │ │ ├── app-chrome.scss │ │ ├── app-footer.component.ts │ │ ├── app-header.component.ts │ │ ├── app-header.template.html │ │ └── app-router-menu.service.ts │ ├── app-shared │ │ ├── app-shared.module.ts │ │ ├── app-shared.scss │ │ ├── datatable │ │ │ └── themes │ │ │ │ └── bootstrap.scss │ │ ├── generic-base.md │ │ ├── generic-detail.component.ts │ │ ├── generic-search-form.component.ts │ │ ├── generic-search-results.component.ts │ │ ├── generic-search.component.ts │ │ ├── generic.service.ts │ │ ├── tabset │ │ │ ├── tab.model.ts │ │ │ ├── tabset-generic-page.component.ts │ │ │ ├── tabset.component.html │ │ │ ├── tabset.component.scss │ │ │ └── tabset.component.ts │ │ └── type-cache.ts │ ├── app.component.ts │ ├── app.constants.ts │ ├── app.module.ts │ ├── app.scss │ ├── app.store.ts │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── location │ │ ├── detail │ │ │ ├── location-detail.component.html │ │ │ └── location-detail.component.ts │ │ ├── location-orchestrator.service.ts │ │ ├── location-routing.module.ts │ │ ├── location.component.html │ │ ├── location.component.scss │ │ ├── location.component.ts │ │ ├── location.model.ts │ │ ├── location.module.ts │ │ ├── location.service.ts │ │ ├── location.store.ts │ │ └── search │ │ │ ├── location-search-form.component.html │ │ │ ├── location-search-form.component.ts │ │ │ ├── location-search-results.component.html │ │ │ ├── location-search-results.component.ts │ │ │ ├── location-search.component.html │ │ │ └── location-search.component.ts │ ├── person │ │ ├── detail │ │ │ ├── person-detail.component.html │ │ │ └── person-detail.component.ts │ │ ├── person-orchestrator.service.ts │ │ ├── person-routing.module.ts │ │ ├── person.component.html │ │ ├── person.component.scss │ │ ├── person.component.ts │ │ ├── person.model.ts │ │ ├── person.module.ts │ │ ├── person.service.ts │ │ ├── person.store.ts │ │ └── search │ │ │ ├── person-search-form.component.html │ │ │ ├── person-search-form.component.ts │ │ │ ├── person-search-results.component.html │ │ │ ├── person-search-results.component.ts │ │ │ ├── person-search.component.html │ │ │ └── person-search.component.ts │ ├── trip │ │ ├── trip-orchestrator.service.ts │ │ ├── trip-routing.module.ts │ │ ├── trip.component.html │ │ ├── trip.component.scss │ │ ├── trip.component.ts │ │ ├── trip.model.ts │ │ ├── trip.module.ts │ │ └── trip.store.ts │ └── tsconfig.json ├── favicon.ico ├── fonts │ ├── glyphicons-halflings-regular.eot │ ├── glyphicons-halflings-regular.svg │ ├── glyphicons-halflings-regular.ttf │ └── glyphicons-halflings-regular.woff ├── gulpfile.js ├── package.json ├── packages.config └── typings.json ├── candor-sample-ng-cli ├── .angular-cli.json ├── .editorconfig ├── Properties │ └── AssemblyInfo.cs ├── README.md ├── Web.Debug.config ├── Web.Release.config ├── Web.config ├── candor-sample-ng-cli.csproj ├── e2e │ ├── app.e2e-spec.ts │ ├── app.po.ts │ └── tsconfig.e2e.json ├── karma.conf.js ├── package.json ├── packages.config ├── protractor.conf.js ├── src │ ├── app │ │ ├── app-common │ │ │ └── app-common.module.ts │ │ ├── app-routing.module.ts │ │ ├── app-toolbar │ │ │ ├── app-toolbar.service.spec.ts │ │ │ └── app-toolbar.service.ts │ │ ├── app.component.html │ │ ├── app.component.scss │ │ ├── app.component.spec.ts │ │ ├── app.component.ts │ │ ├── app.module.ts │ │ ├── app.theme.scss │ │ ├── location │ │ │ ├── location-page │ │ │ │ ├── location-page.component.html │ │ │ │ ├── location-page.component.scss │ │ │ │ └── location-page.component.ts │ │ │ ├── location-routing.module.ts │ │ │ └── location.module.ts │ │ ├── person │ │ │ ├── person-page │ │ │ │ ├── person-page.component.html │ │ │ │ ├── person-page.component.scss │ │ │ │ ├── person-page.component.spec.ts │ │ │ │ └── person-page.component.ts │ │ │ ├── person-routing.module.ts │ │ │ └── person.module.ts │ │ └── trip │ │ │ ├── trip-page │ │ │ ├── trip-page.component.html │ │ │ ├── trip-page.component.scss │ │ │ └── trip-page.component.ts │ │ │ ├── trip-routing.module.ts │ │ │ └── trip.module.ts │ ├── assets │ │ ├── .gitkeep │ │ └── logo.png │ ├── environments │ │ ├── environment.prod.ts │ │ └── environment.ts │ ├── favicon.ico │ ├── index.html │ ├── main.ts │ ├── polyfills.ts │ ├── styles.scss │ ├── test.ts │ ├── tsconfig.app.json │ ├── tsconfig.spec.json │ └── typings.d.ts ├── tsconfig.json ├── tslint.json └── yarn.lock └── tutorial-creation.md /Candor.Sample.MvcWeb/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace Candor.Sample.MvcWeb 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js", 24 | "~/Scripts/respond.js")); 25 | 26 | bundles.Add(new StyleBundle("~/Content/css").Include( 27 | "~/Content/bootstrap.css", 28 | "~/Content/site.css")); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace Candor.Sample.MvcWeb 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace Candor.Sample.MvcWeb 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapMvcAttributeRoutes(); 17 | 18 | routes.MapRoute( 19 | name: "Default", 20 | url: "{controller}/{action}/{id}", 21 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 22 | ); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | 6 | namespace Candor.Sample.MvcWeb 7 | { 8 | public static class WebApiConfig 9 | { 10 | public static void Register(HttpConfiguration config) 11 | { 12 | // Web API configuration and services 13 | 14 | // Web API routes 15 | config.MapHttpAttributeRoutes(); 16 | 17 | config.Routes.MapHttpRoute( 18 | name: "DefaultApi", 19 | routeTemplate: "api/{controller}/{id}", 20 | defaults: new { id = RouteParameter.Optional } 21 | ); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Set padding to keep content from hitting the edges */ 7 | .body-content { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | } 11 | 12 | /* Override the default bootstrap behavior where horizontal description lists 13 | will truncate terms that are too long to fit in the left column 14 | */ 15 | .dl-horizontal dt { 16 | white-space: normal; 17 | } 18 | 19 | /* Set width on the form input elements since they're 100% wide by default */ 20 | input, 21 | select, 22 | textarea { 23 | max-width: 280px; 24 | } 25 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | 7 | namespace Candor.Sample.MvcWeb.Controllers 8 | { 9 | [RoutePrefix("")] 10 | public class HomeController : Controller 11 | { 12 | [Route("")] 13 | public ActionResult Index() 14 | { 15 | return View("NgApp"); 16 | } 17 | [Route("trip")] 18 | [Route("location")] 19 | [Route("person")] 20 | public ActionResult AppBookmarkableRoutes() 21 | { 22 | return View("NgApp"); 23 | } 24 | 25 | [Route("about")] 26 | public ActionResult About() 27 | { 28 | ViewBag.Message = "Your application description page."; 29 | 30 | return View(); 31 | } 32 | 33 | [Route("contact")] 34 | public ActionResult Contact() 35 | { 36 | ViewBag.Message = "Your contact page."; 37 | 38 | return View(); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="Candor.Sample.MvcWeb.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Mvc; 7 | using System.Web.Optimization; 8 | using System.Web.Routing; 9 | 10 | namespace Candor.Sample.MvcWeb 11 | { 12 | public class MvcApplication : System.Web.HttpApplication 13 | { 14 | protected void Application_Start() 15 | { 16 | AreaRegistration.RegisterAllAreas(); 17 | GlobalConfiguration.Configure(WebApiConfig.Register); 18 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 19 | RouteConfig.RegisterRoutes(RouteTable.Routes); 20 | BundleConfig.RegisterBundles(BundleTable.Bundles); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Candor.Sample.MvcWeb")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Candor.Sample.MvcWeb")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a28311f7-7d17-4c37-8997-30f0c9ccbdd8")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Scripts/NgApp/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/Candor.Sample.MvcWeb/Scripts/NgApp/favicon.ico -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Scripts/_references.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/Candor.Sample.MvcWeb/Scripts/_references.js -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
-------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Home Page"; 3 | } 4 | 5 |
6 |

ASP.NET

7 |

ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.

8 |

Learn more »

9 |
10 | 11 |
12 |
13 |

Getting started

14 |

15 | ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that 16 | enables a clean separation of concerns and gives you full control over markup 17 | for enjoyable, agile development. 18 |

19 |

Learn more »

20 |
21 |
22 |

Get more libraries

23 |

NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.

24 |

Learn more »

25 |
26 |
27 |

Web Hosting

28 |

You can easily find a web hosting company that offers the right mix of features and price for your applications.

29 |

Learn more »

30 |
31 |
-------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Views/Home/NgApp.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = null; 3 | } 4 | 5 | 6 | 7 | 8 | CandorSampleNgCli 9 | 10 | 11 | 12 | 13 | 14 | 15 | Loading... 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Error 6 | 7 | 8 |
9 |

Error.

10 |

An error occurred while processing your request.

11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | @Styles.Render("~/Content/css") 8 | @Scripts.Render("~/bundles/modernizr") 9 | 10 | 11 | 30 |
31 | @RenderBody() 32 |
33 | 36 |
37 | 38 | @Scripts.Render("~/bundles/jquery") 39 | @Scripts.Render("~/bundles/bootstrap") 40 | @RenderSection("scripts", required: false) 41 | 42 | 43 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Views/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 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/Candor.Sample.MvcWeb/favicon.ico -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/Candor.Sample.MvcWeb/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/Candor.Sample.MvcWeb/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/Candor.Sample.MvcWeb/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /Candor.Sample.MvcWeb/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Candor.Sample.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 14 4 | VisualStudioVersion = 14.0.25420.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Candor.Sample", "Candor.Sample\Candor.Sample.csproj", "{B6CE5B66-BC1A-4C02-95F7-45739A2C7453}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Docs", "Docs", "{C8881E7E-B6CC-41D1-A5AE-4A318B9B740A}" 9 | ProjectSection(SolutionItems) = preProject 10 | README.md = README.md 11 | tutorial-creation.md = tutorial-creation.md 12 | EndProjectSection 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Candor.Sample.MvcWeb", "Candor.Sample.MvcWeb\Candor.Sample.MvcWeb.csproj", "{96129BD4-A14A-4AEE-810A-F33DAF68F57D}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "candor-sample-ng-cli", "candor-sample-ng-cli\candor-sample-ng-cli.csproj", "{B727EDB0-6520-4416-B7E7-253E4201D729}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleAngular2Mvc", "SampleAngular2Mvc\SampleAngular2Mvc.csproj", "{0A776B84-0632-4C95-A772-E96AA6619831}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release|Any CPU = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {B6CE5B66-BC1A-4C02-95F7-45739A2C7453}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {B6CE5B66-BC1A-4C02-95F7-45739A2C7453}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {B6CE5B66-BC1A-4C02-95F7-45739A2C7453}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {B6CE5B66-BC1A-4C02-95F7-45739A2C7453}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {96129BD4-A14A-4AEE-810A-F33DAF68F57D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {96129BD4-A14A-4AEE-810A-F33DAF68F57D}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {96129BD4-A14A-4AEE-810A-F33DAF68F57D}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {96129BD4-A14A-4AEE-810A-F33DAF68F57D}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {B727EDB0-6520-4416-B7E7-253E4201D729}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {B727EDB0-6520-4416-B7E7-253E4201D729}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {B727EDB0-6520-4416-B7E7-253E4201D729}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {B727EDB0-6520-4416-B7E7-253E4201D729}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {0A776B84-0632-4C95-A772-E96AA6619831}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {0A776B84-0632-4C95-A772-E96AA6619831}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {0A776B84-0632-4C95-A772-E96AA6619831}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {0A776B84-0632-4C95-A772-E96AA6619831}.Release|Any CPU.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | EndGlobal 47 | -------------------------------------------------------------------------------- /Candor.Sample/Location.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Candor.Sample 4 | { 5 | /// 6 | /// A location to be travelled to as part of a trip. 7 | /// 8 | /// 9 | /// For far away destinations you may want to use city names, 10 | /// while for close trips you may want to use specific address locations. 11 | /// 12 | public class Location 13 | { 14 | /// 15 | /// The system generated identity for this location. 16 | /// 17 | public string LocationId { get; set; } 18 | /// 19 | /// A user friendly name of the location or geographic area. 20 | /// 21 | public string Name { get; set; } 22 | /// 23 | /// The city name. 24 | /// 25 | public string City { get; set; } 26 | /// 27 | /// The locality region, such as a state in the USA. 28 | /// 29 | public string Region { get; set; } 30 | /// 31 | /// The latitude of the location, for distance calculations. 32 | /// 33 | public decimal Lat { get; set; } 34 | /// 35 | /// The longitude of the location, for distance calculations. 36 | /// 37 | public decimal Long { get; set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /Candor.Sample/LocationProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration.Provider; 4 | 5 | namespace Candor.Sample 6 | { 7 | public abstract class LocationProvider : ProviderBase 8 | { 9 | /// 10 | /// retrieve an existing location details by the identity. 11 | /// 12 | /// 13 | /// 14 | public abstract Location GetById(string locationId); 15 | /// 16 | /// Search for locations that partially match a term, such as for a search filter box. 17 | /// 18 | /// A full or partial match. 19 | /// 20 | public abstract IList Search(string term); 21 | /// 22 | /// Creates a new location. 23 | /// 24 | /// 25 | /// 26 | public abstract Location Save(Location item); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Candor.Sample/Person.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Candor.Sample 4 | { 5 | /// 6 | /// A user of the system that wants to join or host a trip. 7 | /// 8 | public class Person 9 | { 10 | /// 11 | /// The system generated identity for this person or user. 12 | /// 13 | public string PersonId { get; set; } 14 | /// 15 | /// The person's first name. 16 | /// 17 | public string FirstName { get; set; } 18 | /// 19 | /// The person's last name. 20 | /// 21 | public string LastName { get; set; } 22 | /// 23 | /// A number to contact the person in regards to any planned trips as driver or rider. 24 | /// 25 | public string ContactPhoneNumber { get; set; } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Candor.Sample/PersonProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration.Provider; 4 | 5 | namespace Candor.Sample 6 | { 7 | public abstract class PersonProvider : ProviderBase 8 | { 9 | /// 10 | /// retrieve an existing person details by the identity. 11 | /// 12 | /// 13 | /// 14 | public abstract Person GetById(string personId); 15 | /// 16 | /// Search for people that partially match a term, such as for a search filter box. 17 | /// 18 | /// A full or partial match. 19 | /// 20 | public abstract IList Search(string term); 21 | /// 22 | /// Creates a new person. 23 | /// 24 | /// 25 | /// 26 | public abstract Person Save(Person item); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Candor.Sample/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("Candor.Sample")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("Candor.Sample")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b6ce5b66-bc1a-4c02-95f7-45739a2c7453")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Candor.Sample/Trip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Candor.Sample 4 | { 5 | /// 6 | /// A single commitment to go from point A to B (and possibly back) 7 | /// 8 | public class Trip 9 | { 10 | /// 11 | /// The system generated unique identity of the trip. 12 | /// 13 | public string TripId { get; set; } 14 | /// 15 | /// The system identity of the departure location (and possibly return location). 16 | /// 17 | public string DepartureLocationId { get; set; } 18 | /// 19 | /// The system identity of the arrival location. 20 | /// 21 | public string ArrivalLocationId { get; set; } 22 | /// 23 | /// The person identity of the driver. 24 | /// 25 | public string DriverId { get; set; } 26 | /// 27 | /// The number of seat positions in the transport vehicle including the driver 28 | /// (including any applicable luggage required for the duration) 29 | /// 30 | public int SeatCount { get; set; } 31 | /// 32 | /// The date the trip will begin from the departure location to the arrival location. 33 | /// 34 | public DateTime DepartDate { get; set; } 35 | /// 36 | /// Specifies if this trip includes a specific planned return trip. 37 | /// 38 | public bool IncludesReturn { get; set; } 39 | /// 40 | /// The date the trip will begin from the arrival locaation back to the departure location, 41 | /// or leave as DateTime.MinValue for no return trip. 42 | /// 43 | public DateTime ReturnDate { get; set; } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Candor.Sample/TripCriteria.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Candor.Sample 4 | { 5 | public class TripCriteria 6 | { 7 | public string NearDepartureLocationId { get; set; } 8 | public string NearArrivalLocationId { get; set; } 9 | public int NearMiles { get; set; } 10 | 11 | public string DriverId { get; set; } 12 | public DateTime DepartureDate { get; set; } 13 | public DateTime ReturnDate { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Candor.Sample/TripProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Configuration.Provider; 4 | 5 | namespace Candor.Sample 6 | { 7 | public abstract class TripProvider : ProviderBase 8 | { 9 | /// 10 | /// retrieve an existing trip details by the identity. 11 | /// 12 | /// 13 | /// 14 | public abstract Trip GetById(string tripId); 15 | /// 16 | /// Search for trips that match supplied criteria. 17 | /// 18 | /// search parameters 19 | /// 20 | public abstract IList Search(TripCriteria criteria); 21 | /// 22 | /// Creates a new trip. 23 | /// 24 | /// 25 | /// 26 | public abstract Trip Save(Trip item); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Candor.Sample/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Michael Lang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/ApiControllers/LocationController.cs: -------------------------------------------------------------------------------- 1 | using Candor.Configuration.Provider; 2 | using Candor.Sample; 3 | using SampleAngular2Mvc.Models; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Web.Http; 7 | 8 | namespace SampleAngular2Mvc.ApiControllers 9 | { 10 | [RoutePrefix("api/location")] 11 | public class LocationController : ApiController 12 | { 13 | [Route("{id}")] 14 | public HttpResponseMessage Get(string id) 15 | { 16 | var item = ProviderResolver.Get.Provider.GetById(id); 17 | return Request.CreateResponse(HttpStatusCode.OK, item); 18 | } 19 | [HttpGet, HttpPost] 20 | [Route("search")] 21 | public HttpResponseMessage GetSearch(LocationCriteriaModel model) 22 | { 23 | var items = ProviderResolver.Get.Provider.Search(model.Term); 24 | return Request.CreateResponse(HttpStatusCode.OK, items); 25 | } 26 | [HttpPost] 27 | [Route("")] 28 | public HttpResponseMessage Post(LocationModel model) 29 | { 30 | if (model == null) 31 | return Request.CreateResponse(HttpStatusCode.BadRequest, new { message = "no location supplied" }); 32 | var updated = ProviderResolver.Get.Provider.Save(model); 33 | return Request.CreateResponse(HttpStatusCode.OK, updated); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/ApiControllers/PersonController.cs: -------------------------------------------------------------------------------- 1 | using Candor.Configuration.Provider; 2 | using Candor.Sample; 3 | using SampleAngular2Mvc.Models; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Web.Http; 7 | 8 | namespace SampleAngular2Mvc.ApiControllers 9 | { 10 | [RoutePrefix("api/person")] 11 | public class PersonController : ApiController 12 | { 13 | [Route("{id}")] 14 | public HttpResponseMessage Get(string id) 15 | { 16 | var item = ProviderResolver.Get.Provider.GetById(id); 17 | return Request.CreateResponse(HttpStatusCode.OK, item); 18 | } 19 | [HttpGet, HttpPost] 20 | [Route("search")] 21 | public HttpResponseMessage GetSearch(PersonCriteriaModel model) 22 | { 23 | var items = ProviderResolver.Get.Provider.Search(model.Term); 24 | return Request.CreateResponse(HttpStatusCode.OK, items); 25 | } 26 | [HttpPost] 27 | [Route("")] 28 | public HttpResponseMessage Post(PersonModel model) 29 | { 30 | if (model == null) 31 | return Request.CreateResponse(HttpStatusCode.BadRequest, new { message = "no person supplied" }); 32 | var updated = ProviderResolver.Get.Provider.Save(model); 33 | return Request.CreateResponse(HttpStatusCode.OK, updated); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/ApiControllers/TripController.cs: -------------------------------------------------------------------------------- 1 | using Candor.Configuration.Provider; 2 | using Candor.Sample; 3 | using SampleAngular2Mvc.Models; 4 | using System.Net; 5 | using System.Net.Http; 6 | using System.Web.Http; 7 | 8 | namespace SampleAngular2Mvc.ApiControllers 9 | { 10 | [RoutePrefix("api/trip")] 11 | public class TripController : ApiController 12 | { 13 | [Route("{id}")] 14 | public HttpResponseMessage Get(string id) 15 | { 16 | var item = ProviderResolver.Get.Provider.GetById(id); 17 | return Request.CreateResponse(HttpStatusCode.OK, item); 18 | } 19 | [HttpGet] 20 | [Route("search")] 21 | public HttpResponseMessage GetSearch(TripCriteria model) 22 | { 23 | var items = ProviderResolver.Get.Provider.Search(model); 24 | return Request.CreateResponse(HttpStatusCode.OK, items); 25 | } 26 | [HttpPost] 27 | [Route("")] 28 | public HttpResponseMessage Post(TripModel model) 29 | { 30 | if (model == null) 31 | return Request.CreateResponse(HttpStatusCode.BadRequest, new { message = "no trip supplied" }); 32 | var updated = ProviderResolver.Get.Provider.Save(model); 33 | return Request.CreateResponse(HttpStatusCode.OK, updated); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/App_Data/locations.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "locationId": "A01", 4 | "name": "Forest Park", 5 | "city": "St. Louis", 6 | "region": "Missouri", 7 | "lat": "38.633053", 8 | "long": "-90.285317" 9 | }, 10 | { 11 | "locationId": "A02", 12 | "name": "Cedar Point", 13 | "city": "Sandusky", 14 | "region": "Ohio", 15 | "lat": "41.477618", 16 | "long": "-82.680882" 17 | }, 18 | { 19 | "locationId": "A03", 20 | "name": "Key Largo Art Studio", 21 | "city": "Key Largo", 22 | "region": "Florida", 23 | "lat": "25.134086", 24 | "long": "-80.406083" 25 | } 26 | 27 | ] -------------------------------------------------------------------------------- /SampleAngular2Mvc/App_Data/people.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "personId": "A01", 4 | "firstName": "John", 5 | "lastName": "Smith", 6 | "contactPhoneNumber": "314-555-1234" 7 | }, 8 | { 9 | "personId": "A02", 10 | "firstName": "Michael", 11 | "lastName": "Jones", 12 | "contactPhoneNumber": "618-555-7362" 13 | }, 14 | { 15 | "personId": "A03", 16 | "firstName": "Harry", 17 | "lastName": "Denton", 18 | "contactPhoneNumber": "986-555-1192" 19 | }, 20 | { 21 | "personId": "A04", 22 | "firstName": "William", 23 | "lastName": "Wilson", 24 | "contactPhoneNumber": "208-555-8881" 25 | } 26 | ] -------------------------------------------------------------------------------- /SampleAngular2Mvc/App_Data/trips.json: -------------------------------------------------------------------------------- 1 | [ 2 | 3 | ] -------------------------------------------------------------------------------- /SampleAngular2Mvc/App_Start/BundleConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Optimization; 3 | 4 | namespace SampleAngular2Mvc 5 | { 6 | public class BundleConfig 7 | { 8 | // For more information on bundling, visit http://go.microsoft.com/fwlink/?LinkId=301862 9 | public static void RegisterBundles(BundleCollection bundles) 10 | { 11 | bundles.Add(new ScriptBundle("~/bundles/jquery").Include( 12 | "~/Scripts/jquery-{version}.js")); 13 | 14 | bundles.Add(new ScriptBundle("~/bundles/jqueryval").Include( 15 | "~/Scripts/jquery.validate*")); 16 | 17 | // Use the development version of Modernizr to develop with and learn from. Then, when you're 18 | // ready for production, use the build tool at http://modernizr.com to pick only the tests you need. 19 | bundles.Add(new ScriptBundle("~/bundles/modernizr").Include( 20 | "~/Scripts/modernizr-*")); 21 | 22 | bundles.Add(new ScriptBundle("~/bundles/bootstrap").Include( 23 | "~/Scripts/bootstrap.js", 24 | "~/Scripts/respond.js")); 25 | 26 | bundles.Add(new StyleBundle("~/Content/css").Include( 27 | "~/Content/bootstrap.css", 28 | "~/Content/site.css")); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/App_Start/FilterConfig.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using System.Web.Mvc; 3 | 4 | namespace SampleAngular2Mvc 5 | { 6 | public class FilterConfig 7 | { 8 | public static void RegisterGlobalFilters(GlobalFilterCollection filters) 9 | { 10 | filters.Add(new HandleErrorAttribute()); 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/App_Start/ProviderBootstrapper.cs: -------------------------------------------------------------------------------- 1 | using System.Web; 2 | using Candor.Configuration.Provider; 3 | using Candor.Sample; 4 | using Mocks = Candor.Sample.Mocks; 5 | 6 | [assembly: WebActivatorEx.PreApplicationStartMethod(typeof(SampleAngular2Mvc.App_Start.ProviderBootstrapper), "PreStartup")] 7 | [assembly: WebActivatorEx.PostApplicationStartMethod(typeof(SampleAngular2Mvc.App_Start.ProviderBootstrapper), "PostStartup")] 8 | 9 | namespace SampleAngular2Mvc.App_Start 10 | { 11 | public class ProviderBootstrapper 12 | { 13 | public static void PreStartup() 14 | { 15 | } 16 | public static void PostStartup() 17 | { 18 | InitProviders(); 19 | } 20 | 21 | private static void InitProviders() 22 | { 23 | ProviderResolver.Configure() 24 | .AppendActive(new Mocks.MockTripProvider() { JsonDataPath = HttpContext.Current.Server.MapPath("~/App_Data/trips.json") }); 25 | ProviderResolver.Configure() 26 | .AppendActive(new Mocks.MockPersonProvider() { JsonDataPath = HttpContext.Current.Server.MapPath("~/App_Data/people.json") }); 27 | ProviderResolver.Configure() 28 | .AppendActive(new Mocks.MockLocationProvider() { JsonDataPath = HttpContext.Current.Server.MapPath("~/App_Data/locations.json") }); 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/App_Start/RouteConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Mvc; 6 | using System.Web.Routing; 7 | 8 | namespace SampleAngular2Mvc 9 | { 10 | public class RouteConfig 11 | { 12 | public static void RegisterRoutes(RouteCollection routes) 13 | { 14 | routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 15 | 16 | routes.MapMvcAttributeRoutes(); 17 | 18 | routes.MapRoute( 19 | name: "Default", 20 | url: "{controller}/{action}/{id}", 21 | defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 22 | ); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/App_Start/WebApiConfig.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web.Http; 5 | 6 | namespace SampleAngular2Mvc 7 | { 8 | public static class WebApiConfig 9 | { 10 | public static void Register(HttpConfiguration config) 11 | { 12 | // Web API configuration and services 13 | 14 | // Web API routes 15 | config.MapHttpAttributeRoutes(); 16 | 17 | config.Routes.MapHttpRoute( 18 | name: "DefaultApi", 19 | routeTemplate: "api/{controller}/{id}", 20 | defaults: new { id = RouteParameter.Optional } 21 | ); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Content/Site.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 50px; 3 | padding-bottom: 20px; 4 | } 5 | 6 | /* Set padding to keep content from hitting the edges */ 7 | .body-content { 8 | padding-left: 15px; 9 | padding-right: 15px; 10 | } 11 | 12 | /* Override the default bootstrap behavior where horizontal description lists 13 | will truncate terms that are too long to fit in the left column 14 | */ 15 | .dl-horizontal dt { 16 | white-space: normal; 17 | } 18 | 19 | /* Set width on the form input elements since they're 100% wide by default */ 20 | input, 21 | select, 22 | textarea { 23 | max-width: 280px; 24 | } 25 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using System.Web.Mvc; 2 | 3 | namespace SampleAngular2Mvc.Controllers 4 | { 5 | [RoutePrefix("")] 6 | public class HomeController : Controller 7 | { 8 | [Route("")] 9 | public ActionResult Index() 10 | { 11 | return View("NgApp"); 12 | } 13 | [Route("trip")] 14 | [Route("location")] 15 | [Route("person")] 16 | public ActionResult AppBookmarkableRoutes() 17 | { 18 | return View("NgApp"); 19 | } 20 | 21 | [Route("about")] 22 | public ActionResult About() 23 | { 24 | ViewBag.Message = "Your application description page."; 25 | 26 | return View(); 27 | } 28 | 29 | [Route("contact")] 30 | public ActionResult Contact() 31 | { 32 | ViewBag.Message = "Your contact page."; 33 | 34 | return View(); 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/Global.asax: -------------------------------------------------------------------------------- 1 | <%@ Application Codebehind="Global.asax.cs" Inherits="SampleAngular2Mvc.MvcApplication" Language="C#" %> 2 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Global.asax.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Web; 5 | using System.Web.Http; 6 | using System.Web.Mvc; 7 | using System.Web.Optimization; 8 | using System.Web.Routing; 9 | 10 | namespace SampleAngular2Mvc 11 | { 12 | public class MvcApplication : System.Web.HttpApplication 13 | { 14 | protected void Application_Start() 15 | { 16 | AreaRegistration.RegisterAllAreas(); 17 | GlobalConfiguration.Configure(WebApiConfig.Register); 18 | FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 19 | RouteConfig.RegisterRoutes(RouteTable.Routes); 20 | BundleConfig.RegisterBundles(BundleTable.Bundles); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Models/IdentityModels.cs: -------------------------------------------------------------------------------- 1 | using System.Data.Entity; 2 | using System.Security.Claims; 3 | using System.Threading.Tasks; 4 | using Microsoft.AspNet.Identity; 5 | using Microsoft.AspNet.Identity.EntityFramework; 6 | 7 | namespace SampleAngular2Mvc.Models 8 | { 9 | // You can add profile data for the user by adding more properties to your ApplicationUser class, please visit http://go.microsoft.com/fwlink/?LinkID=317594 to learn more. 10 | public class ApplicationUser : IdentityUser 11 | { 12 | public async Task GenerateUserIdentityAsync(UserManager manager) 13 | { 14 | // Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType 15 | var userIdentity = await manager.CreateIdentityAsync(this, DefaultAuthenticationTypes.ApplicationCookie); 16 | // Add custom user claims here 17 | return userIdentity; 18 | } 19 | } 20 | 21 | public class ApplicationDbContext : IdentityDbContext 22 | { 23 | public ApplicationDbContext() 24 | : base("DefaultConnection", throwIfV1Schema: false) 25 | { 26 | } 27 | 28 | public static ApplicationDbContext Create() 29 | { 30 | return new ApplicationDbContext(); 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/Models/LocationModel.cs: -------------------------------------------------------------------------------- 1 | using Candor.Sample; 2 | 3 | namespace SampleAngular2Mvc.Models 4 | { 5 | /// 6 | /// Model returning a custom representation of a Location for display purposes. 7 | /// This may add formatted properties ready for consumption by javascript, 8 | /// such as formatting date objects or enum values to a good display representation. 9 | /// 10 | public class LocationModel : Location 11 | { 12 | } 13 | 14 | public class LocationCriteriaModel 15 | { 16 | public string Term { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/Models/ManageViewModels.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.ComponentModel.DataAnnotations; 3 | using Microsoft.AspNet.Identity; 4 | using Microsoft.Owin.Security; 5 | 6 | namespace SampleAngular2Mvc.Models 7 | { 8 | public class IndexViewModel 9 | { 10 | public bool HasPassword { get; set; } 11 | public IList Logins { get; set; } 12 | public string PhoneNumber { get; set; } 13 | public bool TwoFactor { get; set; } 14 | public bool BrowserRemembered { get; set; } 15 | } 16 | 17 | public class ManageLoginsViewModel 18 | { 19 | public IList CurrentLogins { get; set; } 20 | public IList OtherLogins { get; set; } 21 | } 22 | 23 | public class FactorViewModel 24 | { 25 | public string Purpose { get; set; } 26 | } 27 | 28 | public class SetPasswordViewModel 29 | { 30 | [Required] 31 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 32 | [DataType(DataType.Password)] 33 | [Display(Name = "New password")] 34 | public string NewPassword { get; set; } 35 | 36 | [DataType(DataType.Password)] 37 | [Display(Name = "Confirm new password")] 38 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 39 | public string ConfirmPassword { get; set; } 40 | } 41 | 42 | public class ChangePasswordViewModel 43 | { 44 | [Required] 45 | [DataType(DataType.Password)] 46 | [Display(Name = "Current password")] 47 | public string OldPassword { get; set; } 48 | 49 | [Required] 50 | [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] 51 | [DataType(DataType.Password)] 52 | [Display(Name = "New password")] 53 | public string NewPassword { get; set; } 54 | 55 | [DataType(DataType.Password)] 56 | [Display(Name = "Confirm new password")] 57 | [Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")] 58 | public string ConfirmPassword { get; set; } 59 | } 60 | 61 | public class AddPhoneNumberViewModel 62 | { 63 | [Required] 64 | [Phone] 65 | [Display(Name = "Phone Number")] 66 | public string Number { get; set; } 67 | } 68 | 69 | public class VerifyPhoneNumberViewModel 70 | { 71 | [Required] 72 | [Display(Name = "Code")] 73 | public string Code { get; set; } 74 | 75 | [Required] 76 | [Phone] 77 | [Display(Name = "Phone Number")] 78 | public string PhoneNumber { get; set; } 79 | } 80 | 81 | public class ConfigureTwoFactorViewModel 82 | { 83 | public string SelectedProvider { get; set; } 84 | public ICollection Providers { get; set; } 85 | } 86 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/Models/PersonModel.cs: -------------------------------------------------------------------------------- 1 | using Candor.Sample; 2 | 3 | namespace SampleAngular2Mvc.Models 4 | { 5 | /// 6 | /// Model returning a custom representation of a Person for display purposes. 7 | /// This may add formatted properties ready for consumption by javascript, 8 | /// such as formatting date objects or enum values to a good display representation. 9 | /// 10 | public class PersonModel : Person 11 | { 12 | } 13 | 14 | public class PersonCriteriaModel 15 | { 16 | public string Term { get; set; } 17 | } 18 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/Models/TripModel.cs: -------------------------------------------------------------------------------- 1 | using Candor.Sample; 2 | 3 | namespace SampleAngular2Mvc.Models 4 | { 5 | /// 6 | /// Model returning a custom representation of a Trip for display purposes. 7 | /// This may add formatted properties ready for consumption by javascript, 8 | /// such as formatting date objects or enum values to a good display representation. 9 | /// 10 | public class TripModel : Trip 11 | { 12 | //public Location DepartureLocation { get; set; } 13 | //public Location ArrivalLocation { get; set; } 14 | //public Person Driver { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("SampleAngular2Mvc")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("SampleAngular2Mvc")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b9dd2c8d-a8e8-41b0-8fc2-be88cdf0f61e")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Scripts/_references.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/SampleAngular2Mvc/Scripts/_references.js -------------------------------------------------------------------------------- /SampleAngular2Mvc/Scripts/systemjs.config.js: -------------------------------------------------------------------------------- 1 | /** 2 | * System configuration for Angular samples 3 | * Adjust as necessary for your application needs. 4 | */ 5 | (function (global) { 6 | System.config({ 7 | paths: { 8 | // paths serve as alias 9 | 'npm:': '/dist/libs/' 10 | }, 11 | // map tells the System loader where to look for things 12 | map: { 13 | app: '/dist/js', 14 | // angular bundles 15 | '@angular/core': 'npm:@angular/core/bundles/core.umd.js', 16 | '@angular/common': 'npm:@angular/common/bundles/common.umd.js', 17 | '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js', 18 | '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js', 19 | '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js', 20 | '@angular/http': 'npm:@angular/http/bundles/http.umd.js', 21 | '@angular/router': 'npm:@angular/router/bundles/router.umd.js', 22 | '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js', 23 | // other libraries 24 | 'rxjs': 'npm:rxjs', 25 | }, 26 | // packages tells the System loader how to load when no filename and/or no extension 27 | packages: { 28 | app: { 29 | defaultExtension: 'js' 30 | }, 31 | rxjs: { 32 | defaultExtension: 'js' 33 | } 34 | } 35 | }); 36 | })(this); -------------------------------------------------------------------------------- /SampleAngular2Mvc/Startup.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.Owin; 2 | using Owin; 3 | 4 | [assembly: OwinStartupAttribute(typeof(SampleAngular2Mvc.Startup))] 5 | namespace SampleAngular2Mvc 6 | { 7 | public partial class Startup 8 | { 9 | public void Configuration(IAppBuilder app) 10 | { 11 | ConfigureAuth(app); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/ConfirmEmail.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Confirm Email"; 3 | } 4 | 5 |

@ViewBag.Title.

6 |
7 |

8 | Thank you for confirming your email. Please @Html.ActionLink("Click here to Log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" }) 9 |

10 |
11 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/ExternalLoginConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.ExternalLoginConfirmationViewModel 2 | @{ 3 | ViewBag.Title = "Register"; 4 | } 5 |

@ViewBag.Title.

6 |

Associate your @ViewBag.LoginProvider account.

7 | 8 | @using (Html.BeginForm("ExternalLoginConfirmation", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 | 12 |

Association Form

13 |
14 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 15 |

16 | You've successfully authenticated with @ViewBag.LoginProvider. 17 | Please enter a user name for this site below and click the Register button to finish 18 | logging in. 19 |

20 |
21 | @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 22 |
23 | @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 24 | @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" }) 25 |
26 |
27 |
28 |
29 | 30 |
31 |
32 | } 33 | 34 | @section Scripts { 35 | @Scripts.Render("~/bundles/jqueryval") 36 | } 37 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/ExternalLoginFailure.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Login Failure"; 3 | } 4 | 5 |
6 |

@ViewBag.Title.

7 |

Unsuccessful login with service.

8 |
9 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/ForgotPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.ForgotPasswordViewModel 2 | @{ 3 | ViewBag.Title = "Forgot your password?"; 4 | } 5 | 6 |

@ViewBag.Title.

7 | 8 | @using (Html.BeginForm("ForgotPassword", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 |

Enter your email.

12 |
13 | @Html.ValidationSummary("", new { @class = "text-danger" }) 14 |
15 | @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 16 |
17 | @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 18 |
19 |
20 |
21 |
22 | 23 |
24 |
25 | } 26 | 27 | @section Scripts { 28 | @Scripts.Render("~/bundles/jqueryval") 29 | } 30 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/ForgotPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Forgot Password Confirmation"; 3 | } 4 | 5 |
6 |

@ViewBag.Title.

7 |
8 |
9 |

10 | Please check your email to reset your password. 11 |

12 |
13 | 14 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/Login.cshtml: -------------------------------------------------------------------------------- 1 | @using SampleAngular2Mvc.Models 2 | @model LoginViewModel 3 | @{ 4 | ViewBag.Title = "Log in"; 5 | } 6 | 7 |

@ViewBag.Title.

8 |
9 |
10 |
11 | @using (Html.BeginForm("Login", "Account", new { ReturnUrl = ViewBag.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 12 | { 13 | @Html.AntiForgeryToken() 14 |

Use a local account to log in.

15 |
16 | @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 17 |
18 | @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 19 |
20 | @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 21 | @Html.ValidationMessageFor(m => m.Email, "", new { @class = "text-danger" }) 22 |
23 |
24 |
25 | @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) 26 |
27 | @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) 28 | @Html.ValidationMessageFor(m => m.Password, "", new { @class = "text-danger" }) 29 |
30 |
31 |
32 |
33 |
34 | @Html.CheckBoxFor(m => m.RememberMe) 35 | @Html.LabelFor(m => m.RememberMe) 36 |
37 |
38 |
39 |
40 |
41 | 42 |
43 |
44 |

45 | @Html.ActionLink("Register as a new user", "Register") 46 |

47 | @* Enable this once you have account confirmation enabled for password reset functionality 48 |

49 | @Html.ActionLink("Forgot your password?", "ForgotPassword") 50 |

*@ 51 | } 52 |
53 |
54 |
55 |
56 | @Html.Partial("_ExternalLoginsListPartial", new ExternalLoginListViewModel { ReturnUrl = ViewBag.ReturnUrl }) 57 |
58 |
59 |
60 | 61 | @section Scripts { 62 | @Scripts.Render("~/bundles/jqueryval") 63 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/Register.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.RegisterViewModel 2 | @{ 3 | ViewBag.Title = "Register"; 4 | } 5 | 6 |

@ViewBag.Title.

7 | 8 | @using (Html.BeginForm("Register", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 |

Create a new account.

12 |
13 | @Html.ValidationSummary("", new { @class = "text-danger" }) 14 |
15 | @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 16 |
17 | @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 18 |
19 |
20 |
21 | @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) 22 |
23 | @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) 24 |
25 |
26 |
27 | @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" }) 28 |
29 | @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" }) 30 |
31 |
32 |
33 |
34 | 35 |
36 |
37 | } 38 | 39 | @section Scripts { 40 | @Scripts.Render("~/bundles/jqueryval") 41 | } 42 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/ResetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.ResetPasswordViewModel 2 | @{ 3 | ViewBag.Title = "Reset password"; 4 | } 5 | 6 |

@ViewBag.Title.

7 | 8 | @using (Html.BeginForm("ResetPassword", "Account", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 |

Reset your password.

12 |
13 | @Html.ValidationSummary("", new { @class = "text-danger" }) 14 | @Html.HiddenFor(model => model.Code) 15 |
16 | @Html.LabelFor(m => m.Email, new { @class = "col-md-2 control-label" }) 17 |
18 | @Html.TextBoxFor(m => m.Email, new { @class = "form-control" }) 19 |
20 |
21 |
22 | @Html.LabelFor(m => m.Password, new { @class = "col-md-2 control-label" }) 23 |
24 | @Html.PasswordFor(m => m.Password, new { @class = "form-control" }) 25 |
26 |
27 |
28 | @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" }) 29 |
30 | @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" }) 31 |
32 |
33 |
34 |
35 | 36 |
37 |
38 | } 39 | 40 | @section Scripts { 41 | @Scripts.Render("~/bundles/jqueryval") 42 | } 43 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/ResetPasswordConfirmation.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Reset password confirmation"; 3 | } 4 | 5 |
6 |

@ViewBag.Title.

7 |
8 |
9 |

10 | Your password has been reset. Please @Html.ActionLink("click here to log in", "Login", "Account", routeValues: null, htmlAttributes: new { id = "loginLink" }) 11 |

12 |
13 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/SendCode.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.SendCodeViewModel 2 | @{ 3 | ViewBag.Title = "Send"; 4 | } 5 | 6 |

@ViewBag.Title.

7 | 8 | @using (Html.BeginForm("SendCode", "Account", new { ReturnUrl = Model.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { 9 | @Html.AntiForgeryToken() 10 | @Html.Hidden("rememberMe", @Model.RememberMe) 11 |

Send verification code

12 |
13 |
14 |
15 | Select Two-Factor Authentication Provider: 16 | @Html.DropDownListFor(model => model.SelectedProvider, Model.Providers) 17 | 18 |
19 |
20 | } 21 | 22 | @section Scripts { 23 | @Scripts.Render("~/bundles/jqueryval") 24 | } 25 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/VerifyCode.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.VerifyCodeViewModel 2 | @{ 3 | ViewBag.Title = "Verify"; 4 | } 5 | 6 |

@ViewBag.Title.

7 | 8 | @using (Html.BeginForm("VerifyCode", "Account", new { ReturnUrl = Model.ReturnUrl }, FormMethod.Post, new { @class = "form-horizontal", role = "form" })) { 9 | @Html.AntiForgeryToken() 10 | @Html.Hidden("provider", @Model.Provider) 11 | @Html.Hidden("rememberMe", @Model.RememberMe) 12 |

Enter verification code

13 |
14 | @Html.ValidationSummary("", new { @class = "text-danger" }) 15 |
16 | @Html.LabelFor(m => m.Code, new { @class = "col-md-2 control-label" }) 17 |
18 | @Html.TextBoxFor(m => m.Code, new { @class = "form-control" }) 19 |
20 |
21 |
22 |
23 |
24 | @Html.CheckBoxFor(m => m.RememberBrowser) 25 | @Html.LabelFor(m => m.RememberBrowser) 26 |
27 |
28 |
29 |
30 |
31 | 32 |
33 |
34 | } 35 | 36 | @section Scripts { 37 | @Scripts.Render("~/bundles/jqueryval") 38 | } 39 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Account/_ExternalLoginsListPartial.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.ExternalLoginListViewModel 2 | @using Microsoft.Owin.Security 3 | 4 |

Use another service to log in.

5 |
6 | @{ 7 | var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes(); 8 | if (loginProviders.Count() == 0) { 9 |
10 |

11 | There are no external authentication services configured. See this article 12 | for details on setting up this ASP.NET application to support logging in via external services. 13 |

14 |
15 | } 16 | else { 17 | using (Html.BeginForm("ExternalLogin", "Account", new { ReturnUrl = Model.ReturnUrl })) { 18 | @Html.AntiForgeryToken() 19 |
20 |

21 | @foreach (AuthenticationDescription p in loginProviders) { 22 | 23 | } 24 |

25 |
26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Home/About.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "About"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |

Use this area to provide additional information.

8 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Home/Contact.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Contact"; 3 | } 4 |

@ViewBag.Title.

5 |

@ViewBag.Message

6 | 7 |
8 | One Microsoft Way
9 | Redmond, WA 98052-6399
10 | P: 11 | 425.555.0100 12 |
13 | 14 |
15 | Support: Support@example.com
16 | Marketing: Marketing@example.com 17 |
-------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Home Page"; 3 | } 4 | 5 |
6 |

ASP.NET

7 |

ASP.NET is a free web framework for building great Web sites and Web applications using HTML, CSS and JavaScript.

8 |

Learn more »

9 |
10 | 11 |
12 |
13 |

Getting started

14 |

15 | ASP.NET MVC gives you a powerful, patterns-based way to build dynamic websites that 16 | enables a clean separation of concerns and gives you full control over markup 17 | for enjoyable, agile development. 18 |

19 |

Learn more »

20 |
21 |
22 |

Get more libraries

23 |

NuGet is a free Visual Studio extension that makes it easy to add, remove, and update libraries and tools in Visual Studio projects.

24 |

Learn more »

25 |
26 |
27 |

Web Hosting

28 |

You can easily find a web hosting company that offers the right mix of features and price for your applications.

29 |

Learn more »

30 |
31 |
-------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Home/NgApp.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | ViewBag.Title = "Angular Demo App"; 3 | Layout = "~/Views/Shared/_NgLayout.cshtml"; 4 | } 5 | @section head{ 6 | 7 | 8 | 55 | } 56 | 57 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Manage/AddPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.AddPhoneNumberViewModel 2 | @{ 3 | ViewBag.Title = "Phone Number"; 4 | } 5 | 6 |

@ViewBag.Title.

7 | 8 | @using (Html.BeginForm("AddPhoneNumber", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 |

Add a phone number

12 |
13 | @Html.ValidationSummary("", new { @class = "text-danger" }) 14 |
15 | @Html.LabelFor(m => m.Number, new { @class = "col-md-2 control-label" }) 16 |
17 | @Html.TextBoxFor(m => m.Number, new { @class = "form-control" }) 18 |
19 |
20 |
21 |
22 | 23 |
24 |
25 | } 26 | 27 | @section Scripts { 28 | @Scripts.Render("~/bundles/jqueryval") 29 | } 30 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Manage/ChangePassword.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.ChangePasswordViewModel 2 | @{ 3 | ViewBag.Title = "Change Password"; 4 | } 5 | 6 |

@ViewBag.Title.

7 | 8 | @using (Html.BeginForm("ChangePassword", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 |

Change Password Form

12 |
13 | @Html.ValidationSummary("", new { @class = "text-danger" }) 14 |
15 | @Html.LabelFor(m => m.OldPassword, new { @class = "col-md-2 control-label" }) 16 |
17 | @Html.PasswordFor(m => m.OldPassword, new { @class = "form-control" }) 18 |
19 |
20 |
21 | @Html.LabelFor(m => m.NewPassword, new { @class = "col-md-2 control-label" }) 22 |
23 | @Html.PasswordFor(m => m.NewPassword, new { @class = "form-control" }) 24 |
25 |
26 |
27 | @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" }) 28 |
29 | @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" }) 30 |
31 |
32 |
33 |
34 | 35 |
36 |
37 | } 38 | @section Scripts { 39 | @Scripts.Render("~/bundles/jqueryval") 40 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Manage/ManageLogins.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.ManageLoginsViewModel 2 | @using Microsoft.Owin.Security 3 | @{ 4 | ViewBag.Title = "Manage your external logins"; 5 | } 6 | 7 |

@ViewBag.Title.

8 | 9 |

@ViewBag.StatusMessage

10 | @{ 11 | var loginProviders = Context.GetOwinContext().Authentication.GetExternalAuthenticationTypes(); 12 | if (loginProviders.Count() == 0) { 13 |
14 |

15 | There are no external authentication services configured. See this article 16 | for details on setting up this ASP.NET application to support logging in via external services. 17 |

18 |
19 | } 20 | else 21 | { 22 | if (Model.CurrentLogins.Count > 0) 23 | { 24 |

Registered Logins

25 | 26 | 27 | @foreach (var account in Model.CurrentLogins) 28 | { 29 | 30 | 31 | 49 | 50 | } 51 | 52 |
@account.LoginProvider 32 | @if (ViewBag.ShowRemoveButton) 33 | { 34 | using (Html.BeginForm("RemoveLogin", "Manage")) 35 | { 36 | @Html.AntiForgeryToken() 37 |
38 | @Html.Hidden("loginProvider", account.LoginProvider) 39 | @Html.Hidden("providerKey", account.ProviderKey) 40 | 41 |
42 | } 43 | } 44 | else 45 | { 46 | @:   47 | } 48 |
53 | } 54 | if (Model.OtherLogins.Count > 0) 55 | { 56 | using (Html.BeginForm("LinkLogin", "Manage")) 57 | { 58 | @Html.AntiForgeryToken() 59 |
60 |

61 | @foreach (AuthenticationDescription p in Model.OtherLogins) 62 | { 63 | 64 | } 65 |

66 |
67 | } 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Manage/SetPassword.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.SetPasswordViewModel 2 | @{ 3 | ViewBag.Title = "Create Password"; 4 | } 5 | 6 |

@ViewBag.Title.

7 |

8 | You do not have a local username/password for this site. Add a local 9 | account so you can log in without an external login. 10 |

11 | 12 | @using (Html.BeginForm("SetPassword", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 13 | { 14 | @Html.AntiForgeryToken() 15 | 16 |

Create Local Login

17 |
18 | @Html.ValidationSummary("", new { @class = "text-danger" }) 19 |
20 | @Html.LabelFor(m => m.NewPassword, new { @class = "col-md-2 control-label" }) 21 |
22 | @Html.PasswordFor(m => m.NewPassword, new { @class = "form-control" }) 23 |
24 |
25 |
26 | @Html.LabelFor(m => m.ConfirmPassword, new { @class = "col-md-2 control-label" }) 27 |
28 | @Html.PasswordFor(m => m.ConfirmPassword, new { @class = "form-control" }) 29 |
30 |
31 |
32 |
33 | 34 |
35 |
36 | } 37 | @section Scripts { 38 | @Scripts.Render("~/bundles/jqueryval") 39 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Manage/VerifyPhoneNumber.cshtml: -------------------------------------------------------------------------------- 1 | @model SampleAngular2Mvc.Models.VerifyPhoneNumberViewModel 2 | @{ 3 | ViewBag.Title = "Verify Phone Number"; 4 | } 5 | 6 |

@ViewBag.Title.

7 | 8 | @using (Html.BeginForm("VerifyPhoneNumber", "Manage", FormMethod.Post, new { @class = "form-horizontal", role = "form" })) 9 | { 10 | @Html.AntiForgeryToken() 11 | @Html.Hidden("phoneNumber", @Model.PhoneNumber) 12 |

Enter verification code

13 |
@ViewBag.Status
14 |
15 | @Html.ValidationSummary("", new { @class = "text-danger" }) 16 |
17 | @Html.LabelFor(m => m.Code, new { @class = "col-md-2 control-label" }) 18 |
19 | @Html.TextBoxFor(m => m.Code, new { @class = "form-control" }) 20 |
21 |
22 |
23 |
24 | 25 |
26 |
27 | } 28 | 29 | @section Scripts { 30 | @Scripts.Render("~/bundles/jqueryval") 31 | } 32 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model System.Web.Mvc.HandleErrorInfo 2 | 3 | @{ 4 | ViewBag.Title = "Error"; 5 | } 6 | 7 |

Error.

8 |

An error occurred while processing your request.

9 | 10 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Shared/Lockout.cshtml: -------------------------------------------------------------------------------- 1 | @model System.Web.Mvc.HandleErrorInfo 2 | 3 | @{ 4 | ViewBag.Title = "Locked Out"; 5 | } 6 | 7 |
8 |

Locked out.

9 |

This account has been locked out, please try again later.

10 |
11 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | @Styles.Render("~/Content/css") 8 | @Scripts.Render("~/bundles/modernizr") 9 | 10 | 11 | 12 | 32 |
33 | @RenderBody() 34 |
35 |
36 |

© @DateTime.Now.Year - My ASP.NET Application

37 |
38 |
39 | 40 | @Scripts.Render("~/bundles/jquery") 41 | @Scripts.Render("~/bundles/bootstrap") 42 | @RenderSection("scripts", required: false) 43 | 44 | 45 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNet.Identity 2 | @if (Request.IsAuthenticated) 3 | { 4 | using (Html.BeginForm("LogOff", "Account", FormMethod.Post, new { id = "logoutForm", @class = "navbar-right" })) 5 | { 6 | @Html.AntiForgeryToken() 7 | 8 | 14 | } 15 | } 16 | else 17 | { 18 | 22 | } 23 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/Shared/_NgLayout.cshtml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | @ViewBag.Title - My ASP.NET Application 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | @RenderSection("head", required: false) 18 | 19 | @Styles.Render("~/Content/css") 20 | @Scripts.Render("~/bundles/modernizr") 21 | 22 | 23 | @RenderBody() 24 | 25 | @Scripts.Render("~/bundles/jquery") 26 | @Scripts.Render("~/bundles/bootstrap") 27 | @RenderSection("scripts", required: false) 28 | 29 | 30 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/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 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "~/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Web.Debug.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/Web.Release.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-chrome/app-chrome.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { RouterModule } from '@angular/router'; 4 | import { AppHeaderComponent } from './app-header.component'; 5 | import { AppFooterComponent } from './app-footer.component'; 6 | import { AppRouterMenuService } from './app-router-menu.service'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | CommonModule, 11 | RouterModule 12 | ], 13 | exports: [RouterModule, AppHeaderComponent, AppFooterComponent], 14 | providers: [AppRouterMenuService], 15 | declarations: [AppHeaderComponent, AppFooterComponent] 16 | }) 17 | export class AppChromeModule { 18 | } 19 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-chrome/app-chrome.scss: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-chrome/app-footer.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-footer', 5 | template: ` 6 |
7 |
8 |
9 | © 2017 {{title}} 10 |
11 |
12 | Email Us 13 |
14 |
15 |
16 | ` 17 | }) 18 | export class AppFooterComponent { 19 | @Input() title: string = this.title; 20 | contactEmailAddress: string = 'support@example.com'; 21 | } 22 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-chrome/app-header.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | import { MenuItem, AppRouterMenuService } from './app-router-menu.service'; 3 | 4 | @Component({ 5 | selector: 'app-header', 6 | templateUrl: '/dist/js/app-chrome/app-header.template.html' 7 | }) 8 | export class AppHeaderComponent implements OnInit { 9 | @Input() title: string = this.title; 10 | menuItems: MenuItem[]; 11 | 12 | constructor(private headerService: AppRouterMenuService) {} 13 | 14 | ngOnInit() { 15 | this.menuItems = this.headerService.getMenuItems(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-chrome/app-header.template.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-chrome/app-router-menu.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | 4 | export class MenuItem { 5 | path: string; 6 | title: string; 7 | description?: string; 8 | } 9 | 10 | @Injectable() 11 | export class AppRouterMenuService { 12 | constructor(private router: Router) { } 13 | 14 | getMenuItems(): MenuItem[] { 15 | return this.router.config 16 | .filter(route => route.data && route.data['headerMenu']) 17 | .map(route => { 18 | if (!route.data['headerMenu'].title) { 19 | throw 'Missing title for header menu route ' + route.path; 20 | } 21 | return { 22 | path: route.path, 23 | title: route.data['headerMenu'].title, 24 | description: route.data['headerMenu'].description 25 | }; 26 | }); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/app-shared.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { RouterModule } from '@angular/router'; 4 | import { TabSetComponent } from './tabset/tabset.component'; 5 | import { NgxDatatableModule } from '@swimlane/ngx-datatable'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | RouterModule, 11 | NgxDatatableModule 12 | ], 13 | exports: [ 14 | RouterModule, 15 | TabSetComponent, 16 | NgxDatatableModule 17 | ], 18 | providers: [], 19 | declarations: [TabSetComponent] 20 | }) 21 | export class AppSharedModule { 22 | } 23 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/app-shared.scss: -------------------------------------------------------------------------------- 1 | @import "tabset/tabset.component.scss"; -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/generic-base.md: -------------------------------------------------------------------------------- 1 | ## Resusable base typescript classes using 'generics' 2 | 3 | Each of the application pages would have a similar boilerplate code for the component, with the view varying based on the data. 4 | Since much of the component code is boilerplate, we took advantage of now having generics in typescript to create a base 5 | class for each of these component types. Also, since the rest service to support these components is similar, a base class 6 | was created to handle the 80% + case of these services with extension points for customizations. 7 | 8 | Find an overview of generics in typescript here: 9 | https://www.typescriptlang.org/docs/handbook/generics.html 10 | 11 | ### Not intended for use with NgrxStore projects 12 | 13 | These classses were designed with the 'bucket brigade' application architecture where state is passes down and events emitted up. 14 | The main project was initially designed to use these and now uses NgrxStore instead. 15 | 16 | ### Overview of usage 17 | 18 | The base class generic types you could reuse on other projects include: 19 | 20 | 1. `GenericService` 21 | * `IGenericSearchService` 22 | - search(criteria: C): T[] function 23 | * `IGenericItemService` 24 | - get(id: string) function 25 | - save(item: T): T function 26 | 2. `GenericDetailComponent>` 27 | This is a base class for any general view of a single item. It contains the save() function usable from your derived 28 | component view. ngOnInit() and save() calls the injected S type service for the Http operation. 29 | 3. `GenericSearchFormComponent` 30 | Only contains emitters for search and criteria reset 31 | 4. `GenericSearchResultsComponent` 32 | Only responsible for receiving the results data via a binding and emitting when an item is clicked. 33 | 5. `GenericSearchComponent` 34 | Coordinates the seach form criteria and the results. 35 | It contains the controller logic to call the rest search service and pass the results down to the search results component. 36 | It also subscribes to a result click and passes the emit onto a parent component to decide what to do with it (such as open it in a new tab). 37 | 6. `TabsetGenericPageComponent` 38 | All the coordination required to have a tabbed interface 39 | * search as a static tab 40 | * each result clicked on opens in a new tab 41 | * a button to add a new tab for an item create 42 | * if duplicate result is clicked, the current open tab for it activates (no duplicate tabs for the same item) 43 | 44 | Most of the work to derive from these base components is in laying out your view. In your layout you can use any pipe you need for data formatting, 45 | general layout decisions, as well as deciding any sub views that open by adding additional event bindings not in the base classes. 46 | 47 | Your typescript can simple be a class definition that extends one of the generic classes above, or you can add additional features to your View 48 | that is not built into the base class. The generic classes are all loosely coupled such that you could pick and choose which ones you want to use, 49 | versus creating something more complex. 50 | 51 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/generic-detail.component.ts: -------------------------------------------------------------------------------- 1 | import { Input, Output, EventEmitter, OnInit } from '@angular/core'; 2 | import { Observable } from 'rxjs/Rx'; 3 | 4 | export interface IGenericItemService { 5 | get(itemId: string): Observable; 6 | save(item: T): Observable; 7 | } 8 | 9 | export class GenericDetailComponent> implements OnInit { 10 | @Input() public itemId: string; 11 | public loading: boolean = true; 12 | @Input() public item: T; 13 | @Output() itemSaved: EventEmitter = new EventEmitter(); 14 | 15 | constructor(private _itemService: S) { } 16 | 17 | public InitItem(): T { 18 | return null; 19 | } 20 | 21 | public ngOnInit(): void { 22 | this.loading = true; 23 | if (this.item) { 24 | return; // nothing to load. 25 | } 26 | 27 | if (this.itemId === '') { 28 | this.item = this.InitItem(); 29 | this.loading = false; 30 | } else { 31 | this._itemService 32 | .get(this.itemId) 33 | .subscribe((data: T) => { this.item = data; }, 34 | error => { console.log(error); this.item = this.InitItem(); }, 35 | () => { 36 | console.log('load item complete: ' + this.itemId); 37 | this.loading = false; 38 | }); 39 | } 40 | } 41 | 42 | public save(): void { 43 | this.loading = true; 44 | this._itemService 45 | .save(this.item) 46 | .subscribe((data: T) => { this.item = data; }, 47 | error => console.log(error), 48 | () => { 49 | console.log('save item update complete: ' + this.itemId); 50 | this.loading = false; 51 | this.itemSaved.emit(this.item); 52 | }); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/generic-search-form.component.ts: -------------------------------------------------------------------------------- 1 | import { Output, EventEmitter } from '@angular/core'; 2 | 3 | export class GenericSearchFormComponent { 4 | public criteria: C = null; 5 | @Output() resetFn: EventEmitter = new EventEmitter(); 6 | @Output() submitFn: EventEmitter = new EventEmitter(); 7 | 8 | constructor() { 9 | this.criteria = this.initCriteria(); 10 | } 11 | 12 | public initCriteria(): C { 13 | return null; 14 | } 15 | 16 | public reset(): void { 17 | this.criteria = this.initCriteria(); 18 | this.resetFn.emit(true); 19 | } 20 | 21 | public search(): void { 22 | this.submitFn.emit(this.criteria); 23 | } 24 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/generic-search-results.component.ts: -------------------------------------------------------------------------------- 1 | import { Input, Output, EventEmitter } from '@angular/core'; 2 | 3 | export class GenericSearchResultsComponent { 4 | @Input() public displayResults: T[]; 5 | @Output() onItemSelected: EventEmitter = new EventEmitter(); 6 | 7 | constructor() { } 8 | 9 | public resultCount(): number { 10 | return this.displayResults && this.displayResults.length ? this.displayResults.length : 0; 11 | } 12 | public itemSelected(item: T): void { 13 | console.log('item selected ' + item); 14 | this.onItemSelected.emit(item); 15 | } 16 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/generic-search.component.ts: -------------------------------------------------------------------------------- 1 | import { Output, EventEmitter } from '@angular/core'; 2 | import { Observable } from 'rxjs/Rx'; 3 | 4 | export interface IGenericSearchService { 5 | search(criteria: C): Observable; 6 | } 7 | 8 | export class GenericSearchComponent { 9 | public searching: boolean = false; 10 | public results: T[]; 11 | public hasResults: boolean = false; 12 | @Output() doOpen: EventEmitter = new EventEmitter(); 13 | 14 | constructor(private _searchService: IGenericSearchService) {} 15 | 16 | public criteriaReset(reset: boolean): void { 17 | this.searching = false; 18 | this.results = new Array(); 19 | } 20 | 21 | public criteriaSubmitted(criteria: C): void { 22 | this.searching = true; 23 | 24 | this._searchService 25 | .search(criteria) 26 | .subscribe((data: T[]) => { this.results = data; this.hasResults = data && data.length > 0; console.log(data); }, 27 | error => console.log(error), 28 | () => { 29 | console.log('search complete'); 30 | this.searching = false; 31 | }); 32 | } 33 | public itemSelected(item: T) { 34 | console.log('item selected ' + item); 35 | this.doOpen.emit(item); 36 | } 37 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/tabset/tab.model.ts: -------------------------------------------------------------------------------- 1 | export class Tab { 2 | id: string; 3 | active: boolean = false; 4 | closeable: boolean = true; 5 | title: string; 6 | template: string; 7 | icon: string; 8 | itemId: string; 9 | item: any; 10 | 11 | constructor() { } 12 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/tabset/tabset-generic-page.component.ts: -------------------------------------------------------------------------------- 1 | import { Tab } from './tab.model'; 2 | 3 | export class TabSetGenericPageComponent { 4 | nextNewId = 0; 5 | tabs: Tab[] = new Array(); 6 | 7 | constructor() { 8 | let tab = new Tab(); 9 | tab.id = 'tab-id-search'; 10 | tab.title = 'Search'; 11 | tab.template = 'search'; 12 | tab.active = true; 13 | tab.closeable = false; 14 | tab.itemId = ''; 15 | this.tabs.push(tab); 16 | } 17 | 18 | closeTab(tab: Tab) { // referenced in view binding 19 | // TODO: show a dialog if this tab has dirty data 20 | // ...close if user says its ok 21 | this.tabs = this.tabs.filter(t => t.id !== tab.id); 22 | if (tab.active && this.tabs.length > 0) { 23 | this.tabs[0].active = true; 24 | } 25 | } 26 | 27 | addTab(b: Boolean) { // referenced in view binding 28 | let tab = new Tab(); 29 | tab.id = 'tab-id-new-' + (++this.nextNewId); 30 | tab.title = this.getTitleOfNew() + (this.nextNewId > 1 ? ' (' + this.nextNewId + ')' : ''); 31 | tab.template = this.getTemplate(null); 32 | tab.active = false; 33 | tab.itemId = ''; 34 | this._openTab(tab); 35 | } 36 | 37 | openItem(item: T) { 38 | let tab = new Tab(); 39 | let uid = this.getUniqueId(item); 40 | if (uid === '') { 41 | console.log('Error: Derived controller must override getUniqueId(T) and return a value.'); 42 | } 43 | tab.id = 'tab-id-' + uid; 44 | tab.title = this.getTitle(item); 45 | tab.template = this.getTemplate(item); 46 | tab.active = false; 47 | tab.itemId = uid; 48 | tab.item = item; 49 | this._openTab(tab); 50 | } 51 | 52 | onItemSaved(item: T, tab: Tab) { 53 | tab.title = this.getTitle(item); 54 | let uid = this.getUniqueId(item); 55 | if (uid === '') { 56 | console.log('Error: Derived controller must override getUniqueId(T) and return a value.'); 57 | } 58 | tab.id = 'tab-id-' + uid; 59 | tab.itemId = uid; 60 | } 61 | 62 | _openTab(tab: Tab) { 63 | let exists = this.tabs.filter(x => tab.id.length > 0 && x.id === tab.id); 64 | if (exists.length === 0) { 65 | this.tabs.push(tab); 66 | } 67 | this.tabs.forEach(x => x.active = (x.id === tab.id)); 68 | } 69 | 70 | getUniqueId(item: T): string { 71 | return ''; 72 | } 73 | 74 | getTitle(item: T): string { 75 | return 'Untitled'; 76 | } 77 | 78 | getTitleOfNew(): string { 79 | return 'New Item'; 80 | } 81 | 82 | getTemplate(item: T | null): string { 83 | return 'item'; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/tabset/tabset.component.html: -------------------------------------------------------------------------------- 1 | 
2 | 14 |
15 | 16 |
17 |
-------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/tabset/tabset.component.scss: -------------------------------------------------------------------------------- 1 | app-tabset { 2 | .tab-content { 3 | .content { 4 | display: none; 5 | } 6 | 7 | .content.active { 8 | display: inherit; 9 | } 10 | } 11 | 12 | ul.nav-tabs { 13 | li.plus-tab { 14 | margin-left: 3px; 15 | margin-top: 5px; 16 | padding: 5px; 17 | } 18 | li.plus-tab:hover { 19 | background-color: #eee; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/tabset/tabset.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, Output, EventEmitter } from '@angular/core'; 2 | import { Tab } from './tab.model'; 3 | 4 | @Component({ 5 | selector: 'app-tabset', 6 | templateUrl: '/dist/js/app-shared/tabset/tabset.component.html' 7 | }) 8 | export class TabSetComponent { 9 | @Input() tabs: Tab[] = new Array(); 10 | @Input() showAddTabButton: boolean = false; 11 | @Output() onTabClosing: EventEmitter = new EventEmitter(); 12 | @Output() onTabAdd: EventEmitter = new EventEmitter(); 13 | @Output() onTabActivated: EventEmitter = new EventEmitter(); 14 | private activeTabId: string = ''; //private to help during transitions 15 | 16 | activateTab(tabId: string) { 17 | let match = this.tabs.filter(x => x.id === tabId); 18 | if (match.length > 0) { 19 | this.activeTabId = match[0].id; 20 | } 21 | this.tabs.forEach(x => x.active = (x.id === this.activeTabId)); 22 | this.onTabActivated.emit(tabId); 23 | } 24 | addingTab() { 25 | this.onTabAdd.emit(true); 26 | } 27 | closingTab(tabId: string) { 28 | let tab = this.tabs.filter(t => t.id === tabId); 29 | if (tab.length > 0) 30 | this.onTabClosing.emit(tab[0]); 31 | } 32 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app-shared/type-cache.ts: -------------------------------------------------------------------------------- 1 | import { Action } from '@ngrx/store'; 2 | /** 3 | * This function coerces a string into a string literal type. 4 | * Using tagged union types in TypeScript 2.0, this enables 5 | * powerful typechecking of our reducers. 6 | * 7 | * Since every action label passes through this function it 8 | * is a good place to ensure all of our action labels 9 | * are unique. 10 | */ 11 | let typeCache: { [label: string]: boolean } = {}; 12 | export function type(label: T | ''): T { 13 | if (typeCache[label]) { 14 | throw new Error(`Action type "${label}" is not unique"`); 15 | } 16 | 17 | typeCache[label] = true; 18 | 19 | return label; 20 | } 21 | 22 | /** 23 | * This function builds a state reducer to replace the typical switch/case pattern, 24 | * given an initial state and a list of classes with static type and reduce function. 25 | * @param initial The initial state for this reducer, called by store to initialize the state 26 | * @param actionClasses a list of classes (type names) implementing the required static reducer interface. 27 | */ 28 | export function buildReducer(initial: T, ...actionClasses: { type: string, reduce: (state: T, action: Action) => T }[]) { 29 | let handlers: { 30 | [key: string]: (state: T, action: Action) => T 31 | } = {}; 32 | actionClasses.forEach((ac) => { 33 | handlers[ac.type] = ac.reduce; 34 | }); 35 | return (state: T = initial, action: Action) => handlers[action.type] ? handlers[action.type](state, action) : state; 36 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | template: ` 6 | 7 |
8 | 9 |
10 | 11 |
12 | `, 13 | }) 14 | export class AppComponent { 15 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app.constants.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { IServiceConfiguration } from './app-shared/generic.service' 3 | 4 | @Injectable() 5 | export class Configuration implements IServiceConfiguration { 6 | public Server: string = "http://localhost:57673/"; 7 | public ApiUrl: string = "api/"; 8 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | import { NgModule } from '@angular/core'; 4 | import { FormsModule } from '@angular/forms'; 5 | import { HttpModule } from '@angular/http'; 6 | import { RouterModule } from '@angular/router'; 7 | import { StoreModule } from '@ngrx/store'; 8 | 9 | import { AppReducer } from './app.store'; 10 | import { AppComponent } from './app.component'; 11 | import { AppChromeModule } from './app-chrome/app-chrome.module'; 12 | import { LocationModule } from './location/location.module'; 13 | import { PersonModule } from './person/person.module'; 14 | import { TripModule } from './trip/trip.module'; 15 | 16 | @NgModule({ 17 | imports: [ 18 | BrowserModule, 19 | HttpModule, 20 | FormsModule, 21 | AppChromeModule, 22 | LocationModule, 23 | PersonModule, 24 | TripModule, 25 | StoreModule.provideStore(AppReducer), 26 | RouterModule.forRoot([{ 27 | path: '', redirectTo: '/person', pathMatch: 'full' 28 | }]) 29 | ], 30 | declarations: [ 31 | AppComponent 32 | ], 33 | exports: [RouterModule], //Don't export AppModule (this class), it causes '(SystemJS) Maximum call stack size exceeded' 34 | bootstrap: [AppComponent] 35 | }) 36 | export class AppModule { 37 | } 38 | 39 | const platform = platformBrowserDynamic(); 40 | platform.bootstrapModule(AppModule); -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app.scss: -------------------------------------------------------------------------------- 1 | @import "app-chrome/app-chrome.scss"; 2 | @import "app-shared/app-shared.scss"; 3 | @import "location/location.component.scss"; 4 | @import "person/person.component.scss"; 5 | @import "trip/trip.component.scss"; 6 | @import './app-shared/datatable/themes/bootstrap.scss'; -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/app.store.ts: -------------------------------------------------------------------------------- 1 | import { ActionReducer } from '@ngrx/store'; 2 | import { combineReducers } from '@ngrx/store'; 3 | import { storeFreeze } from 'ngrx-store-freeze'; 4 | import { compose } from "@ngrx/core"; 5 | import { environment } from './environments/environment'; 6 | import * as person from './person/person.store'; 7 | import * as location from './location/location.store'; 8 | import * as trip from './trip/trip.store'; 9 | 10 | export interface AppState { 11 | person: person.PersonState, 12 | location: location.LocationState, 13 | trip: trip.TripState 14 | } 15 | 16 | const reducers = { 17 | person: person.PersonReducer, 18 | location: location.LocationReducer, 19 | trip: trip.TripReducer 20 | } 21 | 22 | const developmentReducer: ActionReducer = compose(storeFreeze, combineReducers)(reducers); 23 | const productionReducer: ActionReducer = combineReducers(reducers); 24 | 25 | export function AppReducer(state: any, action: any) { 26 | if (environment.enableStoreFreeze && !environment.production) 27 | return developmentReducer(state, action); 28 | else 29 | return productionReducer(state, action); 30 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true, 3 | enableStoreFreeze: false 4 | }; 5 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | export const environment = { 3 | production: false, 4 | enableStoreFreeze: true 5 | }; 6 | //TODO: setup the production build process to replace environment with 'environment.prod.ts' 7 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/detail/location-detail.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | 13 |
14 |
15 | 19 |
20 |
21 | 25 |
26 |
27 |
28 |
29 | 33 |
34 |
35 | 39 |
40 | 41 |
42 |
43 |
44 | 47 |
48 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/detail/location-detail.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, Output, EventEmitter } from '@angular/core'; 2 | //import * as _ from 'lodash'; 3 | import { Location, LocationHolder } from '../location.model'; 4 | import { LocationService } from '../location.service'; 5 | 6 | @Component({ 7 | selector: 'location-detail', 8 | providers: [LocationService], 9 | templateUrl: '/dist/js/location/detail/location-detail.component.html', 10 | }) 11 | export class LocationDetailComponent { 12 | private _locationHolder: LocationHolder; 13 | get locationHolder() { return this._locationHolder; } 14 | @Input() set locationHolder(locationHolder: LocationHolder) { 15 | this._locationHolder = JSON.parse(JSON.stringify(locationHolder)) //_.cloneDeep(locationHolder); 16 | } 17 | @Output() saveClicked: EventEmitter = new EventEmitter(); 18 | 19 | get location() { 20 | return this._locationHolder.Location; 21 | } 22 | 23 | public save(): void { 24 | this.saveClicked.emit(this.locationHolder); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/location-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { LocationComponent } from './location.component'; 5 | 6 | const routes: Routes = [{ 7 | path: 'location', 8 | component: LocationComponent, 9 | data: { 10 | headerMenu: { 11 | title: 'Locations' 12 | } 13 | } 14 | }]; 15 | 16 | @NgModule({ 17 | imports: [RouterModule.forChild(routes)], 18 | exports: [RouterModule], 19 | providers: [] 20 | }) 21 | export class LocationRoutingModule { 22 | } 23 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/location.component.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 | 4 |
5 | 6 | 7 |
8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/location.component.scss: -------------------------------------------------------------------------------- 1 | app-location { 2 | 3 | 4 | 5 | } 6 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/location.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Observable } from 'rxjs/Rx'; 3 | import { Tab } from '../app-shared/tabset/tab.model'; 4 | import { Location, LocationHolder } from './location.model'; 5 | import { LocationOrchestratorService } from './location-orchestrator.service'; 6 | 7 | @Component({ 8 | selector: 'app-location', 9 | templateUrl: '/dist/js/location/location.component.html' 10 | }) 11 | export class LocationComponent { 12 | openItems$: Observable; 13 | tabs$: Observable; 14 | activeTabId$: Observable; 15 | 16 | constructor(private _itemService: LocationOrchestratorService) { 17 | this.activeTabId$ = _itemService.activeTabId; 18 | this.openItems$ = _itemService.openList; 19 | this.tabs$ = _itemService.tabs; 20 | } 21 | 22 | saveLocation(vh: LocationHolder) { 23 | this._itemService.save(vh); 24 | } 25 | 26 | closeTab(tab: Tab) { 27 | this._itemService.close(tab.id); 28 | } 29 | addTab(b: Boolean) { 30 | this._itemService.add(); 31 | } 32 | activateTab(id: string) { 33 | this._itemService.activate(id); 34 | } 35 | openItem(location: Location) { 36 | this._itemService.open(location); 37 | } 38 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/location.model.ts: -------------------------------------------------------------------------------- 1 | export class Location { 2 | public LocationId: string; 3 | public Name: string; 4 | public City: string; 5 | public Region: string; 6 | public Lat: number; 7 | public Long: number; 8 | } 9 | 10 | export class LocationHolder { 11 | public Location: Location; 12 | public PlaceholderId: string; 13 | public isNew: boolean; 14 | } 15 | 16 | export class LocationCriteria { 17 | public term?: string; 18 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/location.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { AppSharedModule } from '../app-shared/app-shared.module'; 5 | import { Configuration } from '../app.constants'; 6 | 7 | import { LocationComponent } from './location.component'; 8 | import { LocationRoutingModule } from './location-routing.module'; 9 | import { LocationSearchComponent } from './search/location-search.component'; 10 | import { LocationSearchResultsComponent } from './search/location-search-results.component'; 11 | import { LocationSearchFormComponent } from './search/location-search-form.component'; 12 | import { LocationDetailComponent } from './detail/location-detail.component'; 13 | import { LocationService } from './location.service'; 14 | import { LocationOrchestratorService } from './location-orchestrator.service'; 15 | 16 | @NgModule({ 17 | imports: [ 18 | CommonModule, 19 | FormsModule, 20 | LocationRoutingModule, 21 | AppSharedModule 22 | ], 23 | providers: [Configuration, LocationService, LocationOrchestratorService], 24 | exports: [LocationComponent, 25 | LocationSearchComponent, 26 | LocationSearchResultsComponent, 27 | LocationSearchFormComponent, 28 | LocationDetailComponent 29 | ], 30 | declarations: [LocationComponent, 31 | LocationSearchComponent, 32 | LocationSearchResultsComponent, 33 | LocationSearchFormComponent, 34 | LocationDetailComponent 35 | ] 36 | }) 37 | export class LocationModule { 38 | } 39 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/location.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response, Headers } from '@angular/http'; 3 | import { Observable } from 'rxjs/Rx'; 4 | import { Configuration } from '../app.constants'; 5 | import { GenericService } from '../app-shared/generic.service' 6 | import { Location, LocationCriteria } from './location.model'; 7 | 8 | @Injectable() 9 | export class LocationService extends GenericService { 10 | constructor(_http: Http, _configuration: Configuration) { 11 | super(_http, _configuration) 12 | } 13 | get endpoint(): string { 14 | return 'location'; 15 | } 16 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/search/location-search-form.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 7 |
8 | 9 | 10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/search/location-search-form.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, Output, EventEmitter, ViewChild, AfterViewInit } from '@angular/core'; 2 | import { LocationCriteria } from '../location.model'; 3 | import { NgForm } from '@angular/forms'; 4 | 5 | @Component({ 6 | selector: 'location-search-form', 7 | templateUrl: '/dist/js/location/search/location-search-form.component.html', 8 | }) 9 | export class LocationSearchFormComponent implements AfterViewInit { 10 | @Input() criteria: LocationCriteria; 11 | @Output() submitSearch: EventEmitter = new EventEmitter(); 12 | @Output() resetSearch: EventEmitter = new EventEmitter(); 13 | @Output() criteriaChange: EventEmitter = new EventEmitter(); 14 | @ViewChild('ngForm') ngForm: NgForm; 15 | 16 | ngAfterViewInit() { 17 | this.ngForm.form.valueChanges.subscribe(this.criteriaChange); 18 | } 19 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/search/location-search-results.component.html: -------------------------------------------------------------------------------- 1 |

Matching Locations

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
{{resultCount() + (resultCount() > 1 ? ' locations' : ' location')}}
NameCityRegion / StateLat/Long
{{p.Name}}{{p.City}}{{p.Region}}{{p.Lat}} / {{p.Long}}
21 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/search/location-search-results.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Location } from '../location.model'; 3 | import { GenericSearchResultsComponent } from '../../app-shared/generic-search-results.component' 4 | 5 | @Component({ 6 | selector: 'location-search-results', 7 | templateUrl: '/dist/js/location/search/location-search-results.component.html', 8 | }) 9 | export class LocationSearchResultsComponent extends GenericSearchResultsComponent { } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/search/location-search.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/location/search/location-search.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Output, EventEmitter } from '@angular/core'; 2 | import { Observable } from 'rxjs'; 3 | import '@ngrx/core/add/operator/select'; 4 | import { Location, LocationCriteria } from '../location.model'; 5 | import { LocationOrchestratorService } from '../location-orchestrator.service' 6 | import { SearchStatus } from '../location.store'; 7 | 8 | @Component({ 9 | selector: 'location-search', 10 | providers: [LocationOrchestratorService], 11 | templateUrl: '/dist/js/location/search/location-search.component.html' 12 | }) 13 | export class LocationSearchComponent { 14 | public searchStatus$: Observable; 15 | public criteria$: Observable; 16 | public hasResults$: Observable; 17 | public results$: Observable; 18 | @Output() doOpen: EventEmitter = new EventEmitter(); 19 | 20 | constructor(private _service: LocationOrchestratorService) { 21 | this.searchStatus$ = this._service.searchStatus; 22 | this.criteria$ = this._service.criteria; 23 | this.hasResults$ = this._service.hasResults; 24 | this.results$ = this._service.results; 25 | } 26 | 27 | public criteriaReset(reset: boolean): void { 28 | this._service.resetSearch(); 29 | } 30 | public criteriaChange(criteria: LocationCriteria): void { 31 | this._service.changeSearch(criteria); 32 | } 33 | public criteriaSubmitted(criteria: LocationCriteria): void { 34 | this._service.search(criteria); 35 | } 36 | public itemSelected(item: Location) { 37 | this.doOpen.emit(item); 38 | } 39 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/detail/person-detail.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | 15 |
16 |
17 | 22 |
23 |
24 |
25 |
26 | 31 |
32 |
33 |
34 |
35 |
36 | 37 |
38 |
39 |
40 |
41 |
42 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/detail/person-detail.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, Output, EventEmitter, ViewChild, AfterViewInit } from '@angular/core'; 2 | import { NgForm } from '@angular/forms'; 3 | //import * as _ from 'lodash'; 4 | import { Person, PersonHolder } from '../person.model'; 5 | import { PersonService } from '../person.service'; 6 | 7 | @Component({ 8 | selector: 'person-detail', 9 | providers: [PersonService], 10 | templateUrl: '/dist/js/person/detail/person-detail.component.html', 11 | }) 12 | export class PersonDetailComponent { 13 | @Input() personHolder: PersonHolder; 14 | @Output() saveClicked: EventEmitter = new EventEmitter(); 15 | 16 | get person() { 17 | return this.personHolder.Person; 18 | } 19 | 20 | save(person: Person) { 21 | let v = Object.assign({}, this.personHolder, { 22 | Person: Object.assign({}, this.personHolder.Person, person) 23 | }); 24 | this.saveClicked.emit(v); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/person-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { PersonComponent } from './person.component'; 5 | 6 | const routes: Routes = [{ 7 | path: 'person', 8 | component: PersonComponent, 9 | data: { 10 | headerMenu: { 11 | title: 'People' 12 | } 13 | } 14 | }]; 15 | 16 | @NgModule({ 17 | imports: [RouterModule.forChild(routes)], 18 | exports: [RouterModule], 19 | providers: [] 20 | }) 21 | export class PersonRoutingModule { 22 | } 23 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/person.component.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 | 4 |
5 | 6 | 7 |
8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/person.component.scss: -------------------------------------------------------------------------------- 1 | app-person{ 2 | 3 | 4 | 5 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/person.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Observable } from 'rxjs/Rx'; 3 | import { Tab } from '../app-shared/tabset/tab.model'; 4 | import { Person, PersonHolder } from './person.model'; 5 | import { PersonOrchestratorService } from './person-orchestrator.service'; 6 | 7 | @Component({ 8 | selector: 'app-person', 9 | templateUrl: '/dist/js/person/person.component.html' 10 | }) 11 | export class PersonComponent { 12 | openItems$: Observable; 13 | tabs$: Observable; 14 | activeTabId$: Observable; 15 | 16 | constructor(private _itemService: PersonOrchestratorService) { 17 | this.activeTabId$ = _itemService.activeTabId; 18 | this.openItems$ = _itemService.openList; 19 | this.tabs$ = _itemService.tabs; 20 | } 21 | 22 | savePerson(vh: PersonHolder) { 23 | this._itemService.save(vh); 24 | } 25 | 26 | closeTab(tab: Tab) { 27 | this._itemService.close(tab.id); 28 | } 29 | addTab(b: Boolean) { 30 | this._itemService.add(); 31 | } 32 | activateTab(id: string) { 33 | this._itemService.activate(id); 34 | } 35 | openItem(person: Person) { 36 | this._itemService.open(person); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/person.model.ts: -------------------------------------------------------------------------------- 1 | export class Person { 2 | public PersonId: string; 3 | public FirstName: string; 4 | public LastName: string; 5 | public ContactPhoneNumber: string; 6 | } 7 | 8 | export class PersonHolder { 9 | public Person: Person; 10 | public PlaceholderId: string; 11 | public isNew: boolean; 12 | } 13 | 14 | export class PersonCriteria { 15 | public term?: string; 16 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/person.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { AppSharedModule } from '../app-shared/app-shared.module'; 5 | import { Configuration } from '../app.constants'; 6 | 7 | import { PersonComponent } from './person.component'; 8 | import { PersonRoutingModule } from './person-routing.module'; 9 | import { PersonSearchComponent } from './search/person-search.component'; 10 | import { PersonSearchResultsComponent } from './search/person-search-results.component'; 11 | import { PersonSearchFormComponent } from './search/person-search-form.component'; 12 | import { PersonDetailComponent } from './detail/person-detail.component'; 13 | import { PersonService } from './person.service'; 14 | import { PersonOrchestratorService } from './person-orchestrator.service'; 15 | 16 | @NgModule({ 17 | imports: [ 18 | CommonModule, 19 | FormsModule, 20 | PersonRoutingModule, 21 | AppSharedModule 22 | ], 23 | providers: [Configuration, PersonService, PersonOrchestratorService], 24 | exports: [PersonComponent, 25 | PersonSearchComponent, 26 | PersonSearchResultsComponent, 27 | PersonSearchFormComponent, 28 | PersonDetailComponent 29 | ], 30 | declarations: [PersonComponent, 31 | PersonSearchComponent, 32 | PersonSearchResultsComponent, 33 | PersonSearchFormComponent, 34 | PersonDetailComponent 35 | ] 36 | }) 37 | export class PersonModule { 38 | } 39 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/person.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Http, Response, Headers } from '@angular/http'; 3 | import { Observable } from 'rxjs/Rx'; 4 | import { Configuration } from '../app.constants'; 5 | import { GenericService } from '../app-shared/generic.service' 6 | import { Person, PersonCriteria } from './person.model'; 7 | 8 | @Injectable() 9 | export class PersonService extends GenericService { 10 | constructor(_http: Http, _configuration: Configuration) { 11 | super(_http, _configuration) 12 | } 13 | get endpoint(): string { 14 | return 'person'; 15 | } 16 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/search/person-search-form.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 7 |
8 | 9 | 10 |
11 |
12 |
13 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/search/person-search-form.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Input, Output, EventEmitter, ViewChild, AfterViewInit } from '@angular/core'; 2 | import { PersonCriteria } from '../person.model'; 3 | import { NgForm } from '@angular/forms'; 4 | 5 | @Component({ 6 | selector: 'person-search-form', 7 | templateUrl: '/dist/js/person/search/person-search-form.component.html', 8 | }) 9 | export class PersonSearchFormComponent implements AfterViewInit { 10 | @Input() criteria: PersonCriteria; 11 | @Output() submitSearch: EventEmitter = new EventEmitter(); 12 | @Output() resetSearch: EventEmitter = new EventEmitter(); 13 | @Output() criteriaChange: EventEmitter = new EventEmitter(); 14 | @ViewChild('ngForm') ngForm: NgForm; 15 | 16 | ngAfterViewInit() { 17 | this.ngForm.form.valueChanges.debounceTime(50).subscribe(this.criteriaChange); 18 | } 19 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/search/person-search-results.component.html: -------------------------------------------------------------------------------- 1 |

Matching People

2 | 8 | 9 | 12 | 15 | 16 | 17 | 20 | 23 | 24 | 25 | 28 | 31 | 32 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/search/person-search-results.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Person } from '../person.model'; 3 | import { GenericSearchResultsComponent } from '../../app-shared/generic-search-results.component' 4 | 5 | @Component({ 6 | selector: 'person-search-results', 7 | templateUrl: '/dist/js/person/search/person-search-results.component.html', 8 | }) 9 | export class PersonSearchResultsComponent extends GenericSearchResultsComponent { } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/search/person-search.component.html: -------------------------------------------------------------------------------- 1 | 6 | 7 | 8 |
9 |
10 |
11 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/person/search/person-search.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, Output, EventEmitter } from '@angular/core'; 2 | import { Observable } from 'rxjs'; 3 | import '@ngrx/core/add/operator/select'; 4 | import { Person, PersonCriteria } from '../person.model'; 5 | import { PersonOrchestratorService } from '../person-orchestrator.service' 6 | import { SearchStatus } from '../person.store'; 7 | 8 | @Component({ 9 | selector: 'person-search', 10 | providers: [PersonOrchestratorService], 11 | templateUrl: '/dist/js/person/search/person-search.component.html' 12 | }) 13 | export class PersonSearchComponent { 14 | public searchStatus$: Observable; 15 | public criteria$: Observable; 16 | public hasResults$: Observable; 17 | public results$: Observable; 18 | @Output() doOpen: EventEmitter = new EventEmitter(); 19 | 20 | constructor(private _service: PersonOrchestratorService) { 21 | this.searchStatus$ = this._service.searchStatus; 22 | this.criteria$ = this._service.criteria; 23 | this.hasResults$ = this._service.hasResults; 24 | this.results$ = this._service.resultsCopy; 25 | } 26 | 27 | public criteriaReset(reset: boolean): void { 28 | this._service.resetSearch(); 29 | } 30 | public criteriaChange(criteria: PersonCriteria): void { 31 | this._service.changeSearch(criteria); 32 | } 33 | public criteriaSubmitted(criteria: PersonCriteria): void { 34 | this._service.search(criteria); 35 | } 36 | public itemSelected(item: Person) { 37 | this.doOpen.emit(item); 38 | } 39 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/trip/trip-orchestrator.service.ts: -------------------------------------------------------------------------------- 1 | //TODO: flesh this out, enhance with new combined observable of trip with the matching locations and people linked by id. 2 | // (assuming those people are loaded??) -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/trip/trip-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | import { TripComponent } from './trip.component'; 5 | 6 | const routes: Routes = [{ 7 | path: 'trip', 8 | component: TripComponent, 9 | data: { 10 | headerMenu: { 11 | title: 'Trips' 12 | } 13 | } 14 | }]; 15 | 16 | @NgModule({ 17 | imports: [RouterModule.forChild(routes)], 18 | exports: [RouterModule], 19 | providers: [] 20 | }) 21 | export class TripRoutingModule { 22 | } 23 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/trip/trip.component.html: -------------------------------------------------------------------------------- 1 | 
2 |
3 | 4 |
5 |

6 | tab body for {{t.id}} 7 |

8 |
9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/trip/trip.component.scss: -------------------------------------------------------------------------------- 1 | app-trip{ 2 | 3 | 4 | 5 | 6 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/trip/trip.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Observable } from 'rxjs/Rx'; 3 | import 'rxjs/rx'; 4 | import { Store } from '@ngrx/store'; 5 | import { Tab } from '../app-shared/tabset/tab.model'; 6 | import { Trip, TripHolder } from './trip.model'; 7 | //import { TripService } from './trip.service'; 8 | import { AppState } from '../app.store'; 9 | import { TripCloseAction, TripOpenAction, TripTabActivateAction } from './trip.store'; 10 | 11 | @Component({ 12 | selector: 'app-trip', 13 | templateUrl: '/dist/js/trip/trip.component.html' 14 | }) 15 | export class TripComponent { 16 | openItems$: Observable; 17 | tabs$: Observable; 18 | activeTabId$: Observable; 19 | searchTab: Tab; 20 | 21 | //TODO: create as a computed store service: 22 | // http://onehungrymind.com/handle-multiple-angular-2-models-ngrx-computed-observables/ 23 | constructor(private _store: Store /*, private _itemService: TripService*/) { 24 | this.searchTab = new Tab(); 25 | this.searchTab.id = 'tab-id-search'; 26 | this.searchTab.title = 'Search'; 27 | this.searchTab.template = 'search'; 28 | this.searchTab.active = true; 29 | this.searchTab.closeable = false; 30 | this.searchTab.itemId = ''; 31 | 32 | this.activeTabId$ = _store.select(x => x.trip.activeTabId); 33 | this.openItems$ = _store.select(x => x.trip.openList); 34 | this.tabs$ = this.openItems$ 35 | .combineLatest(this.activeTabId$) 36 | .map(([trips, activeId]) => { 37 | this.searchTab.active = activeId === this.searchTab.id || !activeId; 38 | return [this.searchTab].concat(trips.map(item => { 39 | let exists = item.Trip && item.Trip.TripId && item.Trip.TripId.length > 0; 40 | let t = new Tab(); 41 | t.id = item.PlaceholderId; 42 | t.title = exists ? item.Trip.DepartDate : 'Add Trip'; //TODO: what is a good title here?? 43 | t.template = 'item'; 44 | t.active = activeId === t.id; 45 | t.closeable = true; 46 | t.item = item; 47 | t.itemId = item.Trip.TripId; 48 | return t; 49 | })); 50 | }); 51 | } 52 | 53 | saveTrip(vh: TripHolder) { 54 | //TODO: on search impl: this._itemService.save(vh); 55 | } 56 | 57 | closeTab(tab: Tab) { 58 | this._store.dispatch(new TripCloseAction(tab.id)) 59 | } 60 | addTab(b: Boolean) { 61 | this._store.dispatch(new TripOpenAction(new Trip())); 62 | } 63 | activateTab(id: string) { 64 | this._store.dispatch(new TripTabActivateAction(id)); 65 | } 66 | openItem(trip: Trip) { 67 | this._store.dispatch(new TripOpenAction(trip)); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/trip/trip.model.ts: -------------------------------------------------------------------------------- 1 | export class Trip { 2 | public TripId: string; 3 | public DepartureLocationId: string; 4 | public ArrivalLocationId: string; 5 | public DriverId: string; 6 | public SeatCount: number; 7 | public DepartDate: string; //date 8 | public IncludesReturn: boolean; 9 | public ReturnDate: string; //date 10 | } 11 | 12 | export class TripHolder { 13 | public Trip: Trip; 14 | public PlaceholderId: string; 15 | public isNew: boolean; 16 | } 17 | 18 | export class TripCriteria { 19 | public NearDepartureLocationId: string; 20 | public NearArrivalLocationId: string; 21 | public NearMiles: number; 22 | public DriverId: string; 23 | public DepartureDate: string; //date 24 | public ReturnDate: string; //date 25 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/trip/trip.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { TripComponent } from './trip.component'; 4 | import { TripRoutingModule } from './trip-routing.module'; 5 | import { AppSharedModule } from '../app-shared/app-shared.module'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | TripRoutingModule, 11 | AppSharedModule 12 | ], 13 | declarations: [TripComponent] 14 | }) 15 | export class TripModule { 16 | } 17 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/app/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "emitDecoratorMetadata": true, 4 | "experimentalDecorators": true, 5 | "module": "commonjs", 6 | "noEmitOnError": true, 7 | "noImplicitAny": false, 8 | "outDir": "../dist/js", 9 | "removeComments": false, 10 | "sourceMap": true, 11 | "target": "es5", 12 | "moduleResolution": "node", 13 | "lib": ["dom", "es5", "es2015"] 14 | }, 15 | "exclude": [ 16 | "node_modules", 17 | "typings/index", 18 | "typings/index.d.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/SampleAngular2Mvc/favicon.ico -------------------------------------------------------------------------------- /SampleAngular2Mvc/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/SampleAngular2Mvc/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /SampleAngular2Mvc/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/SampleAngular2Mvc/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /SampleAngular2Mvc/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/SampleAngular2Mvc/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /SampleAngular2Mvc/gulpfile.js: -------------------------------------------------------------------------------- 1 | /// 2 | /* 3 | This file in the main entry point for defining Gulp tasks and using Gulp plugins. 4 | Click here to learn more. http://go.microsoft.com/fwlink/?LinkId=518007 5 | */ 6 | 7 | var ts = require('gulp-typescript'); 8 | var gulp = require('gulp'); 9 | var clean = require('gulp-clean'); 10 | var sass = require('gulp-sass'); 11 | 12 | /// RUN, DEPLOY tasks 13 | gulp.task('default', ['build', 'dist-libs', 'watch']); 14 | 15 | gulp.task('clean-libs', function () { 16 | return gulp.src('./dist/libs') 17 | .pipe(clean()); 18 | }); 19 | 20 | gulp.task("dist-libs", () => { 21 | gulp.src([ 22 | 'core-js/client/**', 23 | 'systemjs/dist/system.src.js', 24 | 'reflect-metadata/**', 25 | 'rxjs/**', 26 | 'zone.js/dist/**', 27 | '@angular/**', 28 | '@ngrx/**', 29 | 'deep-freeze-strict/**', 30 | 'ngrx-store-freeze/**', 31 | '@swimlane/ngx-datatable/release/**', 32 | 'tassign/**', 33 | 'lodash/**', 34 | 'jquery/dist/jquery.*js' 35 | ], { 36 | cwd: "node_modules/**" 37 | }) 38 | .pipe(gulp.dest('./dist/libs')); 39 | }); 40 | 41 | var tsProject = ts.createProject('app/tsconfig.json', { 42 | typescript: require('typescript') 43 | }); 44 | 45 | /// BUILD tasks 46 | gulp.task('build-ts', function (done) { 47 | //var tsResult = tsProject.src() 48 | var tsResult = gulp.src([ 49 | "./app/**/*.ts", 50 | "!./app/**/_*.ts" 51 | ]) 52 | .pipe(ts(tsProject), undefined, ts.reporter.fullReporter()); 53 | return tsResult.js.pipe(gulp.dest('./dist/js/')); 54 | }); 55 | gulp.task('build-sass', function () { 56 | gulp.src([ 57 | './app/**/*.scss', 58 | '!./app/**/_*.scss' 59 | ]) 60 | .pipe(sass()) 61 | .pipe(gulp.dest('./dist/css/')) 62 | }); 63 | gulp.task('build-html', function () { 64 | gulp.src("./app/**/*.html") 65 | .pipe(gulp.dest('./dist/js/')) 66 | }); 67 | gulp.task('build', ['build-ts', 'build-html', 'build-sass']); 68 | 69 | /// WATCH tasks 70 | gulp.task('watch-sass', function () { 71 | gulp.watch('./app/**/*.scss', ['build-sass']) 72 | }); 73 | gulp.task('watch-ts', ['build-ts'], function () { 74 | return gulp.watch('app/**/*.ts', ['build-ts']); 75 | }); 76 | gulp.task('watch', ['watch-ts', 'watch-sass']); 77 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "name": "asp.net", 4 | "private": true, 5 | "scripts": { 6 | "postinstall": "typings install", 7 | "typings": "typings" 8 | }, 9 | "dependencies": { 10 | "@angular/common": "2.2.1", 11 | "@angular/compiler": "2.2.1", 12 | "@angular/core": "2.2.1", 13 | "@angular/forms": "2.2.1", 14 | "@angular/http": "2.2.1", 15 | "@angular/platform-browser": "2.2.1", 16 | "@angular/platform-browser-dynamic": "2.2.1", 17 | "@angular/router": "3.2.1", 18 | "@ngrx/core": "^1.0.0", 19 | "@ngrx/db": "^2.0.0", 20 | "@ngrx/store": "^2.0.0", 21 | "@swimlane/ngx-datatable": "^6.3.0", 22 | "core-js": "^2.4.1", 23 | "reflect-metadata": "^0.1.9", 24 | "rxjs": "^5.0.3", 25 | "ngrx-store-freeze": "^0.1.9", 26 | "systemjs": "^0.20.0", 27 | "tassign": "1.0.0", 28 | "zone.js": "^0.7.6" 29 | }, 30 | "devDependencies": { 31 | "typescript": "2.1.5", 32 | "typings": "2.1.0", 33 | "gulp": "^3.9.1", 34 | "path": "^0.12.7", 35 | "gulp-clean": "^0.3.2", 36 | "gulp-concat": "^2.6.1", 37 | "gulp-typescript": "^3.1.4", 38 | "gulp-tsc": "^1.2.6", 39 | "gulp-sass": "^3.1.0" 40 | } 41 | } -------------------------------------------------------------------------------- /SampleAngular2Mvc/packages.config: -------------------------------------------------------------------------------- 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 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /SampleAngular2Mvc/typings.json: -------------------------------------------------------------------------------- 1 | { 2 | "globalDependencies": { 3 | "core-js": "registry:dt/core-js#0.0.0+20160725163759", 4 | "jasmine": "registry:dt/jasmine#2.2.0+20160621224255", 5 | "node": "registry:dt/node#6.0.0+20160909174046" 6 | } 7 | } -------------------------------------------------------------------------------- /candor-sample-ng-cli/.angular-cli.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "project": { 4 | "name": "candor-sample-ng-cli" 5 | }, 6 | "apps": [ 7 | { 8 | "root": "src", 9 | "outDir": "dist", 10 | "assets": [ 11 | "assets", 12 | "favicon.ico" 13 | ], 14 | "index": "index.html", 15 | "main": "main.ts", 16 | "polyfills": "polyfills.ts", 17 | "test": "test.ts", 18 | "tsconfig": "tsconfig.app.json", 19 | "testTsconfig": "tsconfig.spec.json", 20 | "prefix": "app", 21 | "styles": [ 22 | "styles.scss" 23 | ], 24 | "scripts": [], 25 | "environmentSource": "environments/environment.ts", 26 | "environments": { 27 | "dev": "environments/environment.ts", 28 | "prod": "environments/environment.prod.ts" 29 | } 30 | } 31 | ], 32 | "e2e": { 33 | "protractor": { 34 | "config": "./protractor.conf.js" 35 | } 36 | }, 37 | "lint": [ 38 | { 39 | "project": "src/tsconfig.app.json" 40 | }, 41 | { 42 | "project": "src/tsconfig.spec.json" 43 | }, 44 | { 45 | "project": "e2e/tsconfig.e2e.json" 46 | } 47 | ], 48 | "test": { 49 | "karma": { 50 | "config": "./karma.conf.js" 51 | } 52 | }, 53 | "defaults": { 54 | "styleExt": "scss", 55 | "component": {} 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("candor_sample_ng_cli")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("candor_sample_ng_cli")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("b727edb0-6520-4416-b7e7-253e4201d729")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Revision and Build Numbers 33 | // by using the '*' as shown below: 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] 36 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/README.md: -------------------------------------------------------------------------------- 1 | # CandorSampleNgCli 2 | 3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.0.0. 4 | 5 | ## Development server 6 | 7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. 8 | 9 | ## Code scaffolding 10 | 11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive/pipe/service/class/module`. 12 | 13 | ## Build 14 | 15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build. 16 | 17 | ## Running unit tests 18 | 19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). 20 | 21 | ## Running end-to-end tests 22 | 23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). 24 | Before running the tests make sure you are serving the app via `ng serve`. 25 | 26 | ## Further help 27 | 28 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). 29 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/Web.Debug.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 29 | 30 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/Web.Release.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 17 | 18 | 19 | 30 | 31 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/Web.config: -------------------------------------------------------------------------------- 1 |  2 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 16 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/e2e/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { CandorSampleNgCliPage } from './app.po'; 2 | 3 | describe('candor-sample-ng-cli App', () => { 4 | let page: CandorSampleNgCliPage; 5 | 6 | beforeEach(() => { 7 | page = new CandorSampleNgCliPage(); 8 | }); 9 | 10 | it('should display message saying app works', () => { 11 | page.navigateTo(); 12 | expect(page.getParagraphText()).toEqual('app works!'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/e2e/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, element, by } from 'protractor'; 2 | 3 | export class CandorSampleNgCliPage { 4 | navigateTo() { 5 | return browser.get('/'); 6 | } 7 | 8 | getParagraphText() { 9 | return element(by.css('app-root h1')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/e2e/tsconfig.e2e.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types":[ 8 | "jasmine", 9 | "node" 10 | ] 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/0.13/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular/cli'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular/cli/plugins/karma') 14 | ], 15 | client:{ 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | files: [ 19 | { pattern: './src/test.ts', watched: false } 20 | ], 21 | preprocessors: { 22 | './src/test.ts': ['@angular/cli'] 23 | }, 24 | mime: { 25 | 'text/x-typescript': ['ts','tsx'] 26 | }, 27 | coverageIstanbulReporter: { 28 | reports: [ 'html', 'lcovonly' ], 29 | fixWebpackSourcePaths: true 30 | }, 31 | angularCli: { 32 | environment: 'dev' 33 | }, 34 | reporters: config.angularCli && config.angularCli.codeCoverage 35 | ? ['progress', 'coverage-istanbul'] 36 | : ['progress', 'kjhtml'], 37 | port: 9876, 38 | colors: true, 39 | logLevel: config.LOG_INFO, 40 | autoWatch: true, 41 | browsers: ['Chrome'], 42 | singleRun: false 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "candor-sample-ng-cli", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "scripts": { 6 | "ng": "ng", 7 | "start": "ng serve", 8 | "build": "ng build", 9 | "test": "ng test", 10 | "lint": "ng lint", 11 | "e2e": "ng e2e", 12 | "copy": "xcopy \"dist\" \"..\\Candor.Sample.MvcWeb\\Scripts\\NgApp\" /i /s /r /y /c", 13 | "dist": "npm run build && npm run copy" 14 | }, 15 | "private": true, 16 | "dependencies": { 17 | "@angular/animations": "4.0.1", 18 | "@angular/common": "4.0.1", 19 | "@angular/compiler": "4.0.1", 20 | "@angular/core": "4.0.1", 21 | "@angular/flex-layout": "2.0.0-beta.8", 22 | "@angular/forms": "4.0.1", 23 | "@angular/http": "4.0.1", 24 | "@angular/material": "2.0.0-beta.3", 25 | "@angular/platform-browser": "4.0.1", 26 | "@angular/platform-browser-dynamic": "4.0.1", 27 | "@angular/router": "4.0.1", 28 | "@ngrx/core": "^1.2.0", 29 | "@ngrx/effects": "^2.0.2", 30 | "@ngrx/router-store": "^1.2.5", 31 | "@ngrx/store": "^2.2.1", 32 | "@ngrx/store-devtools": "^3.2.4", 33 | "core-js": "2.4.1", 34 | "hammerjs": "^2.0.8", 35 | "ngrx-store-freeze": "^0.1.9", 36 | "rxjs": "5.3.0", 37 | "zone.js": "0.8.5" 38 | }, 39 | "devDependencies": { 40 | "@angular/cli": "1.0.0", 41 | "@angular/compiler-cli": "4.0.1", 42 | "@angular/language-service": "4.0.1", 43 | "@types/jasmine": "2.5.47", 44 | "@types/node": "7.0.13", 45 | "codelyzer": "2.1.1", 46 | "jasmine-core": "2.5.2", 47 | "jasmine-spec-reporter": "4.0.0", 48 | "karma": "1.6.0", 49 | "karma-chrome-launcher": "2.0.0", 50 | "karma-cli": "1.0.1", 51 | "karma-jasmine": "1.1.0", 52 | "karma-jasmine-html-reporter": "0.2.2", 53 | "karma-coverage-istanbul-reporter": "1.2.0", 54 | "protractor": "5.1.1", 55 | "ts-node": "3.0.2", 56 | "tslint": "5.1.0", 57 | "typescript": "2.2.0" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // Protractor configuration file, see link for more information 2 | // https://github.com/angular/protractor/blob/master/lib/config.ts 3 | 4 | const { SpecReporter } = require('jasmine-spec-reporter'); 5 | 6 | exports.config = { 7 | allScriptsTimeout: 11000, 8 | specs: [ 9 | './e2e/**/*.e2e-spec.ts' 10 | ], 11 | capabilities: { 12 | 'browserName': 'chrome' 13 | }, 14 | directConnect: true, 15 | baseUrl: 'http://localhost:4200/', 16 | framework: 'jasmine', 17 | jasmineNodeOpts: { 18 | showColors: true, 19 | defaultTimeoutInterval: 30000, 20 | print: function() {} 21 | }, 22 | beforeLaunch: function() { 23 | require('ts-node').register({ 24 | project: 'e2e/tsconfig.e2e.json' 25 | }); 26 | }, 27 | onPrepare() { 28 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 29 | } 30 | }; 31 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/app-common/app-common.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { //only import the portions you will use to optimize build (MaterialModule to include all is deprecated) 4 | MdAutocompleteModule, 5 | MdCoreModule, 6 | MdButtonModule, 7 | MdButtonToggleModule, 8 | MdCardModule, 9 | MdCheckboxModule, 10 | MdIconModule, 11 | MdInputModule, 12 | MdListModule, 13 | MdMenuModule, 14 | MdProgressSpinnerModule, 15 | MdRadioModule, 16 | MdRippleModule, 17 | MdSelectModule, 18 | MdSidenavModule, 19 | MdSlideToggleModule, 20 | MdSnackBarModule, 21 | MdTabsModule, 22 | MdToolbarModule 23 | } from '@angular/material'; 24 | import { FlexLayoutModule } from '@angular/flex-layout'; 25 | 26 | @NgModule({ 27 | imports: [ 28 | CommonModule, 29 | MdAutocompleteModule, 30 | MdCoreModule, 31 | MdButtonModule, 32 | MdButtonToggleModule, 33 | MdCardModule, 34 | MdCheckboxModule, 35 | MdIconModule, 36 | MdInputModule, 37 | MdListModule, 38 | MdMenuModule, 39 | MdProgressSpinnerModule, 40 | MdRadioModule, 41 | MdRippleModule, 42 | MdSelectModule, 43 | MdSidenavModule, 44 | MdSlideToggleModule, 45 | MdSnackBarModule, 46 | MdToolbarModule, 47 | MdTabsModule, 48 | FlexLayoutModule 49 | ], 50 | declarations: [], 51 | exports: [ 52 | MdAutocompleteModule, 53 | MdCoreModule, 54 | MdButtonModule, 55 | MdButtonToggleModule, 56 | MdCardModule, 57 | MdCheckboxModule, 58 | MdIconModule, 59 | MdInputModule, 60 | MdListModule, 61 | MdMenuModule, 62 | MdProgressSpinnerModule, 63 | MdRadioModule, 64 | MdRippleModule, 65 | MdSelectModule, 66 | MdSidenavModule, 67 | MdSlideToggleModule, 68 | MdSnackBarModule, 69 | MdToolbarModule, 70 | MdTabsModule, 71 | FlexLayoutModule 72 | ] 73 | }) 74 | export class AppCommonModule { } 75 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | 4 | const routes: Routes = [{ 5 | path: '', 6 | redirectTo: '/trip', 7 | pathMatch: 'full' 8 | }]; 9 | 10 | @NgModule({ 11 | imports: [RouterModule.forRoot(routes)], 12 | exports: [RouterModule] 13 | }) 14 | export class AppRoutingModule { } 15 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/app-toolbar/app-toolbar.service.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, inject } from '@angular/core/testing'; 2 | 3 | import { AppToolbarService } from './app-toolbar.service'; 4 | 5 | describe('AppToolbarService', () => { 6 | beforeEach(() => { 7 | TestBed.configureTestingModule({ 8 | providers: [AppToolbarService] 9 | }); 10 | }); 11 | 12 | it('should ...', inject([AppToolbarService], (service: AppToolbarService) => { 13 | expect(service).toBeTruthy(); 14 | })); 15 | }); 16 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/app-toolbar/app-toolbar.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { Router, NavigationEnd, ActivatedRoute } from '@angular/router'; 3 | import { Title } from '@angular/platform-browser'; 4 | import { Observable } from 'rxjs/Observable'; 5 | import 'rxjs/add/operator/filter'; 6 | import 'rxjs/add/operator/map'; 7 | 8 | export class MenuItem { 9 | path: string; 10 | title: string; 11 | icon?: string; 12 | } 13 | 14 | @Injectable() 15 | export class AppToolbarService { 16 | activeMenuItem$: Observable; 17 | 18 | constructor(private router: Router, private titleService: Title) { 19 | this.activeMenuItem$ = this.router.events 20 | .filter(e => e instanceof NavigationEnd) 21 | .map(_ => this.router.routerState.root) 22 | .map(route => { 23 | let active = this.lastRouteWithMenuItem(route.root); 24 | this.titleService.setTitle(active.title); 25 | return active; 26 | }); 27 | } 28 | getMenuItems(): MenuItem[] { 29 | return this.router.config 30 | .filter(route => route.data && route.data.title) 31 | .map(route => { 32 | if (!route.data.title) { 33 | throw new Error('Missing title for toolbar menu route ' + route.path); 34 | } 35 | return { 36 | path: route.path, 37 | title: route.data.title, 38 | icon: route.data.icon 39 | }; 40 | }); 41 | } 42 | 43 | private lastRouteWithMenuItem(route: ActivatedRoute): MenuItem { 44 | let lastMenu = undefined; 45 | do { lastMenu = this.extractMenu(route) || lastMenu; } 46 | while ((route = route.firstChild)); 47 | return lastMenu; 48 | } 49 | private extractMenu(route: ActivatedRoute): MenuItem { 50 | let cfg = route.routeConfig; 51 | return cfg && cfg.data && cfg.data.title 52 | ? { path: cfg.path, title: cfg.data.title, icon: cfg.data.icon } 53 | : undefined 54 | } 55 | } 56 | 57 | 58 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | {{appName}} 6 | 7 | 8 | 14 | 15 | {{navItem.title}} 16 | 17 | 18 | 19 | 20 | 24 | 25 | {{(activeMenuItem$ | async)?.title}} 26 | 27 | 28 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/app.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/candor-sample-ng-cli/src/app/app.component.scss -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, async } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | 4 | import { AppComponent } from './app.component'; 5 | 6 | describe('AppComponent', () => { 7 | beforeEach(async(() => { 8 | TestBed.configureTestingModule({ 9 | imports: [ 10 | RouterTestingModule 11 | ], 12 | declarations: [ 13 | AppComponent 14 | ], 15 | }).compileComponents(); 16 | })); 17 | 18 | it('should create the app', async(() => { 19 | const fixture = TestBed.createComponent(AppComponent); 20 | const app = fixture.debugElement.componentInstance; 21 | expect(app).toBeTruthy(); 22 | })); 23 | 24 | it(`should have as title 'app works!'`, async(() => { 25 | const fixture = TestBed.createComponent(AppComponent); 26 | const app = fixture.debugElement.componentInstance; 27 | expect(app.title).toEqual('app works!'); 28 | })); 29 | 30 | it('should render title in a h1 tag', async(() => { 31 | const fixture = TestBed.createComponent(AppComponent); 32 | fixture.detectChanges(); 33 | const compiled = fixture.debugElement.nativeElement; 34 | expect(compiled.querySelector('h1').textContent).toContain('app works!'); 35 | })); 36 | }); 37 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | import { Observable } from 'rxjs/Observable'; 3 | import { AppToolbarService, MenuItem } from './app-toolbar/app-toolbar.service'; 4 | 5 | @Component({ 6 | selector: 'body', 7 | templateUrl: './app.component.html', 8 | styleUrls: ['./app.component.scss'] 9 | }) 10 | export class AppComponent { 11 | appName = 'Ride Finder'; 12 | isDarkTheme = false; 13 | mainMenuItems; 14 | activeMenuItem$: Observable; 15 | 16 | constructor(private toolbarService: AppToolbarService) { 17 | this.mainMenuItems = this.toolbarService.getMenuItems(); 18 | this.activeMenuItem$ = this.toolbarService.activeMenuItem$; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | import { FormsModule } from '@angular/forms'; 4 | import { HttpModule } from '@angular/http'; 5 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 6 | import { AppCommonModule } from './app-common/app-common.module'; 7 | 8 | import { RouterModule } from '@angular/router'; 9 | import { AppRoutingModule } from './app-routing.module'; 10 | import { AppComponent } from './app.component'; 11 | import { AppToolbarService } from './app-toolbar/app-toolbar.service'; 12 | import { TripModule } from './trip/trip.module'; 13 | import { TripRoutingModule } from './trip/trip-routing.module'; 14 | import { LocationModule } from './location/location.module'; 15 | import { LocationRoutingModule } from './location/location-routing.module'; 16 | import { PersonModule } from './person/person.module'; 17 | import { PersonRoutingModule } from './person/person-routing.module'; 18 | 19 | import 'hammerjs'; 20 | 21 | @NgModule({ 22 | declarations: [ 23 | AppComponent 24 | ], 25 | imports: [ 26 | BrowserModule, 27 | FormsModule, 28 | HttpModule, 29 | BrowserAnimationsModule, 30 | AppCommonModule, 31 | AppRoutingModule, 32 | TripModule, 33 | TripRoutingModule, 34 | LocationModule, 35 | LocationRoutingModule, 36 | PersonModule, 37 | PersonRoutingModule, 38 | RouterModule.forRoot([{ 39 | path: '', redirectTo: '/trip', pathMatch: 'full' 40 | }]) 41 | ], 42 | providers: [AppToolbarService], 43 | bootstrap: [AppComponent] 44 | }) 45 | export class AppModule { } 46 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/app.theme.scss: -------------------------------------------------------------------------------- 1 | @import '~@angular/material/theming'; 2 | 3 | @include mat-core(); 4 | $app-color-primary: mat-palette($mat-light-blue); 5 | $app-color-accent: mat-palette($mat-amber); 6 | $color-app-warn: mat-palette($mat-red); 7 | $app-theme: mat-light-theme($app-color-primary, $app-color-accent, $color-app-warn); 8 | 9 | @include angular-material-theme($app-theme); 10 | 11 | //To add another secondary theme: https://github.com/angular/material2/blob/master/guides/theming.md 12 | 13 | .dark-theme { 14 | $dark-primary: mat-palette($mat-indigo); 15 | $dark-accent: mat-palette($mat-brown); 16 | 17 | $dark-theme: mat-dark-theme($dark-primary, $dark-accent); 18 | 19 | @include angular-material-theme($dark-theme); 20 | } -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/location/location-page/location-page.component.html: -------------------------------------------------------------------------------- 1 |

2 | location-page works! 3 |

4 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/location/location-page/location-page.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/candor-sample-ng-cli/src/app/location/location-page/location-page.component.scss -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/location/location-page/location-page.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-location-page', 5 | templateUrl: './location-page.component.html', 6 | styleUrls: ['./location-page.component.scss'] 7 | }) 8 | export class LocationPageComponent { 9 | 10 | constructor() { } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/location/location-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { LocationPageComponent } from './location-page/location-page.component'; 4 | 5 | const routes: Routes = [{ 6 | path: 'location', 7 | component: LocationPageComponent, 8 | data: { 9 | title: 'Locations' 10 | } 11 | }]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule] 16 | }) 17 | export class LocationRoutingModule { } 18 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/location/location.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { LocationRoutingModule } from './location-routing.module'; 5 | import { LocationPageComponent } from './location-page/location-page.component'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | LocationRoutingModule 11 | ], 12 | declarations: [LocationPageComponent] 13 | }) 14 | export class LocationModule { } 15 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/person/person-page/person-page.component.html: -------------------------------------------------------------------------------- 1 |

2 | person-page works! 3 |

4 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/person/person-page/person-page.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/candor-sample-ng-cli/src/app/person/person-page/person-page.component.scss -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/person/person-page/person-page.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { PersonPageComponent } from './person-page.component'; 4 | 5 | describe('PersonPageComponent', () => { 6 | let component: PersonPageComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ PersonPageComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(PersonPageComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/person/person-page/person-page.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-person-page', 5 | templateUrl: './person-page.component.html', 6 | styleUrls: ['./person-page.component.scss'] 7 | }) 8 | export class PersonPageComponent implements OnInit { 9 | 10 | constructor() { } 11 | 12 | ngOnInit() { 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/person/person-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { PersonPageComponent } from './person-page/person-page.component'; 4 | 5 | const routes: Routes = [{ 6 | path: 'person', 7 | component: PersonPageComponent, 8 | data: { 9 | title: 'People' 10 | } 11 | }]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule] 16 | }) 17 | export class PersonRoutingModule { } 18 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/person/person.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | 4 | import { PersonRoutingModule } from './person-routing.module'; 5 | import { PersonPageComponent } from './person-page/person-page.component'; 6 | 7 | @NgModule({ 8 | imports: [ 9 | CommonModule, 10 | PersonRoutingModule 11 | ], 12 | declarations: [PersonPageComponent] 13 | }) 14 | export class PersonModule { } 15 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/trip/trip-page/trip-page.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | trip component works! 4 | 5 | 6 | 7 | aside 8 | 9 |
-------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/trip/trip-page/trip-page.component.scss: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/candor-sample-ng-cli/src/app/trip/trip-page/trip-page.component.scss -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/trip/trip-page/trip-page.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-trip-page', 5 | templateUrl: './trip-page.component.html', 6 | styleUrls: ['./trip-page.component.scss'] 7 | }) 8 | export class TripPageComponent { 9 | 10 | constructor() { } 11 | 12 | } 13 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/trip/trip-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { TripPageComponent } from './trip-page/trip-page.component'; 4 | 5 | const routes: Routes = [{ 6 | path: 'trip', 7 | component: TripPageComponent, 8 | data: { 9 | title: 'Trip Finder' 10 | } 11 | }]; 12 | 13 | @NgModule({ 14 | imports: [RouterModule.forChild(routes)], 15 | exports: [RouterModule] 16 | }) 17 | export class TripRoutingModule { } 18 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/app/trip/trip.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { CommonModule } from '@angular/common'; 3 | import { AppCommonModule } from '../app-common/app-common.module'; 4 | 5 | import { TripRoutingModule } from './trip-routing.module'; 6 | import { TripPageComponent } from './trip-page/trip-page.component'; 7 | 8 | @NgModule({ 9 | imports: [ 10 | CommonModule, 11 | AppCommonModule, 12 | TripRoutingModule 13 | ], 14 | declarations: [TripPageComponent], 15 | exports: [ 16 | TripPageComponent 17 | ] 18 | }) 19 | export class TripModule { } 20 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/candor-sample-ng-cli/src/assets/.gitkeep -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/candor-sample-ng-cli/src/assets/logo.png -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // The file contents for the current environment will overwrite these during build. 2 | // The build system defaults to the dev environment which uses `environment.ts`, but if you do 3 | // `ng build --env=prod` then `environment.prod.ts` will be used instead. 4 | // The list of which env maps to which file can be found in `.angular-cli.json`. 5 | 6 | export const environment = { 7 | production: false 8 | }; 9 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/michael-lang/sample-ng2-mvc/a6599df93e5aa4788f4c855929b37cb05c711dae/candor-sample-ng-cli/src/favicon.ico -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | CandorSampleNgCli 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | Loading... 14 | 15 | 16 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule); 12 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE9, IE10 and IE11 requires all of the following polyfills. **/ 22 | // import 'core-js/es6/symbol'; 23 | // import 'core-js/es6/object'; 24 | // import 'core-js/es6/function'; 25 | // import 'core-js/es6/parse-int'; 26 | // import 'core-js/es6/parse-float'; 27 | // import 'core-js/es6/number'; 28 | // import 'core-js/es6/math'; 29 | // import 'core-js/es6/string'; 30 | // import 'core-js/es6/date'; 31 | // import 'core-js/es6/array'; 32 | // import 'core-js/es6/regexp'; 33 | // import 'core-js/es6/map'; 34 | // import 'core-js/es6/set'; 35 | 36 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 37 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 38 | 39 | /** IE10 and IE11 requires the following to support `@angular/animation`. */ 40 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 41 | 42 | 43 | /** Evergreen browsers require these. **/ 44 | import 'core-js/es6/reflect'; 45 | import 'core-js/es7/reflect'; 46 | 47 | 48 | /** ALL Firefox browsers require the following to support `@angular/animation`. **/ 49 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 50 | 51 | 52 | 53 | /*************************************************************************************************** 54 | * Zone JS is required by Angular itself. 55 | */ 56 | import 'zone.js/dist/zone'; // Included with Angular CLI. 57 | 58 | 59 | 60 | /*************************************************************************************************** 61 | * APPLICATION IMPORTS 62 | */ 63 | 64 | /** 65 | * Date, currency, decimal and percent pipes. 66 | * Needed for: All but Chrome, Firefox, Edge, IE11 and Safari 10 67 | */ 68 | // import 'intl'; // Run `npm install --save intl`. 69 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/styles.scss: -------------------------------------------------------------------------------- 1 | @import 'app/app.theme'; 2 | 3 | html, body { 4 | display: flex; 5 | flex-direction: column; 6 | 7 | font-family: Roboto, Arial, sans-serif; 8 | margin: 0; 9 | height: 100%; 10 | } 11 | 12 | md-sidenav { 13 | width: 250px; 14 | } 15 | 16 | .content { 17 | padding: 12px; 18 | } -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/long-stack-trace-zone'; 4 | import 'zone.js/dist/proxy.js'; 5 | import 'zone.js/dist/sync-test'; 6 | import 'zone.js/dist/jasmine-patch'; 7 | import 'zone.js/dist/async-test'; 8 | import 'zone.js/dist/fake-async-test'; 9 | import { getTestBed } from '@angular/core/testing'; 10 | import { 11 | BrowserDynamicTestingModule, 12 | platformBrowserDynamicTesting 13 | } from '@angular/platform-browser-dynamic/testing'; 14 | 15 | // Unfortunately there's no typing for the `__karma__` variable. Just declare it as any. 16 | declare var __karma__: any; 17 | declare var require: any; 18 | 19 | // Prevent Karma from running prematurely. 20 | __karma__.loaded = function () {}; 21 | 22 | // First, initialize the Angular testing environment. 23 | getTestBed().initTestEnvironment( 24 | BrowserDynamicTestingModule, 25 | platformBrowserDynamicTesting() 26 | ); 27 | // Then we find all the tests. 28 | const context = require.context('./', true, /\.spec\.ts$/); 29 | // And load the modules. 30 | context.keys().map(context); 31 | // Finally, start Karma to run the tests. 32 | __karma__.start(); 33 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/app", 5 | "module": "es2015", 6 | "baseUrl": "", 7 | "types": [] 8 | }, 9 | "exclude": [ 10 | "test.ts", 11 | "**/*.spec.ts" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/spec", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "baseUrl": "", 8 | "types": [ 9 | "jasmine", 10 | "node" 11 | ] 12 | }, 13 | "files": [ 14 | "test.ts" 15 | ], 16 | "include": [ 17 | "**/*.spec.ts", 18 | "**/*.d.ts" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/src/typings.d.ts: -------------------------------------------------------------------------------- 1 | /* SystemJS module definition */ 2 | declare var module: NodeModule; 3 | interface NodeModule { 4 | id: string; 5 | } 6 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "outDir": "./dist/out-tsc", 5 | "baseUrl": "src", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "moduleResolution": "node", 9 | "emitDecoratorMetadata": true, 10 | "experimentalDecorators": true, 11 | "target": "es5", 12 | "typeRoots": [ 13 | "node_modules/@types" 14 | ], 15 | "lib": [ 16 | "es2016", 17 | "dom" 18 | ] 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /candor-sample-ng-cli/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rulesDirectory": [ 3 | "node_modules/codelyzer" 4 | ], 5 | "rules": { 6 | "callable-types": true, 7 | "class-name": true, 8 | "comment-format": [ 9 | true, 10 | "check-space" 11 | ], 12 | "curly": true, 13 | "eofline": true, 14 | "forin": true, 15 | "import-blacklist": [true, "rxjs"], 16 | "import-spacing": true, 17 | "indent": [ 18 | true, 19 | "spaces" 20 | ], 21 | "interface-over-type-literal": true, 22 | "label-position": true, 23 | "max-line-length": [ 24 | true, 25 | 140 26 | ], 27 | "member-access": false, 28 | "member-ordering": [ 29 | true, 30 | "static-before-instance", 31 | "variables-before-functions" 32 | ], 33 | "no-arg": true, 34 | "no-bitwise": true, 35 | "no-console": [ 36 | true, 37 | "debug", 38 | "info", 39 | "time", 40 | "timeEnd", 41 | "trace" 42 | ], 43 | "no-construct": true, 44 | "no-debugger": true, 45 | "no-duplicate-variable": true, 46 | "no-empty": false, 47 | "no-empty-interface": true, 48 | "no-eval": true, 49 | "no-inferrable-types": [true, "ignore-params"], 50 | "no-shadowed-variable": true, 51 | "no-string-literal": false, 52 | "no-string-throw": true, 53 | "no-switch-case-fall-through": true, 54 | "no-trailing-whitespace": true, 55 | "no-unused-expression": true, 56 | "no-use-before-declare": true, 57 | "no-var-keyword": true, 58 | "object-literal-sort-keys": false, 59 | "one-line": [ 60 | true, 61 | "check-open-brace", 62 | "check-catch", 63 | "check-else", 64 | "check-whitespace" 65 | ], 66 | "prefer-const": true, 67 | "quotemark": [ 68 | true, 69 | "single" 70 | ], 71 | "radix": true, 72 | "semicolon": [ 73 | "always" 74 | ], 75 | "triple-equals": [ 76 | true, 77 | "allow-null-check" 78 | ], 79 | "typedef-whitespace": [ 80 | true, 81 | { 82 | "call-signature": "nospace", 83 | "index-signature": "nospace", 84 | "parameter": "nospace", 85 | "property-declaration": "nospace", 86 | "variable-declaration": "nospace" 87 | } 88 | ], 89 | "typeof-compare": true, 90 | "unified-signatures": true, 91 | "variable-name": false, 92 | "whitespace": [ 93 | true, 94 | "check-branch", 95 | "check-decl", 96 | "check-operator", 97 | "check-separator", 98 | "check-type" 99 | ], 100 | 101 | "directive-selector": [true, "attribute", "app", "camelCase"], 102 | "component-selector": [true, "element", "app", "kebab-case"], 103 | "use-input-property-decorator": true, 104 | "use-output-property-decorator": true, 105 | "use-host-property-decorator": true, 106 | "no-input-rename": true, 107 | "no-output-rename": true, 108 | "use-life-cycle-interface": true, 109 | "use-pipe-transform-interface": true, 110 | "component-class-suffix": true, 111 | "directive-class-suffix": true, 112 | "no-access-missing-member": true, 113 | "templates-use-public": true, 114 | "invoke-injectable": true 115 | } 116 | } 117 | --------------------------------------------------------------------------------