1.0.0 • Published 7 years ago

siipi-erp v1.0.0

Weekly downloads
5
License
-
Repository
-
Last release
7 years ago

Logitus:

  • Luo SiipiERPLog tietokanta
  • Aja alla oleva skripti kyseiseen kantaan

CREATE TABLE SiipiUILog (

Id int IDENTITY(1,1) NOT NULL, Message nvarchar(max) NULL, MessageTemplate nvarchar(max) NULL, Level nvarchar(128) NULL, TimeStamp datetimeoffset(7) NOT NULL, Exception nvarchar(max) NULL, Properties xml NULL, LogEvent nvarchar(max) NULL

CONSTRAINT PK_SiipiUILog PRIMARY KEY CLUSTERED (Id ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY

) ON PRIMARY;

  • Angular 4.0.0 :

    • Featuring Server-side rendering (Platform-Server (basically Angular Universal, but moved into Angular Core) - Faster initial paints, SEO (Search-engine optimization w Title/Meta/Link tags), social media link-previews, etc
    • i18n internationalization support (via/ ngx-translate)
    • Baked in best-practices (follows Angular style guide)
    • Bootstrap4 (with ngx-bootstrap) - (can be rendered on the server!)
      • Bootstrap using SCSS / SASS for easy theming / styling!
  • Webpack build system (Webpack 2)

    • HMR : Hot Module Reloading/Replacement
    • Production builds
  • Testing frameworks

    • Unit testing with Karma/Jasmine
  • Productivity

    • Typescript 2
    • Codelyzer (for Real-time static code analysis)
      • VSCode & Atom provide real-time analysis out of the box.
      • NOTE: Does not fully work with Visual Studio yet. (Even with VS2017 and .NET core 1.0)
  • ASP.NET Core 1.1

    • Integration with NodeJS to provide pre-rendering, as well as any other Node module asset you want to use.

Getting Started?

Make sure you have at least Node 6.x or higher (w/ npm 3+) installed!

Visual Studio 2017

Make sure you have .NET Core 1.0+ installed and/or VS2017. VS2017 will automatically install all the neccessary npm & .NET dependencies when you open the project.

Simply push F5 to start debugging !

Visual Studio Code

Note: Make sure you have the C# extension & .NET Core Debugger installed.

The project comes with the configured Launch.json files to let you just push F5 to start the project.

# cd into the directory you cloned the project into
npm install && npm run build:dev && dotnet restore
# or yarn install

If you're running the project from command line with dotnet run make sure you set your environment variables to Development (otherwise things like HMR won't work).

# on Windows:
set ASPNETCORE_ENVIRONMENT=Development
# on Mac/Linux
export ASPNETCORE_ENVIRONMENT=Development 

Upcoming Features:

  • Update to use npm ngAspnetCoreEngine (still need to tweak a few things there)
  • Potractor e2e testing
  • Add Redux back in (maybe?)
  • Add Azure application insights module (or at least demo how to use it)
  • Add i18n support
  • DONE - Fix old README to match new project
  • Add AoT compilation
  • Add Bootstrap with SCSS
  • Add REST API CRUD Demo


Deployment

Dotnet publish

Using dotnet publish, when it's finished place the generated folder onto your server and use IIS to fire everything up.

Application Structure:

Note: This application has WebAPI (our REST API) setup inside the same project, but of course all of this could be abstracted out into a completely separate project('s) ideally. .NET Core things are all done in the same project for simplicity's sake.

Root level files

Here we have the usual suspects found at the root level.

Front-end oriented files:

  • package.json - NPM project dependencies & scripts
  • .tsconfig - TypeScript configuration (here we setup PATHs as well)
  • webpack - configuration files (modular bundling + so much more)
  • karma - configuration files (unit testing)
  • protractor - config files (e2e testing)
  • tslint - TypeScript code linting rules

/Client/ - Everything Angular

Let's take a look at how this is structured so we can make some sense of it all!

With Angular Universal, we need to split our applicatoin logic per platform so if we look inside this folder, you'll see the 2 root files, that branch the entire logic for browser & server respectively.

  • Main.Browser.ts - This file starts up the entire Angular application for the Client/browser platform.

Here we setup a few things, client Angular bootstrapping.

You'll barely need to touch this file, but something to note, this is the file where you would import libraries that you only want being used in the Browser. (Just know that you'd have to provide a mock implementation for the Server when doing that).

  • Main-Server.ts - This file is where Angular platform-server serializes the Angular application itself on the .NET server within a very quick Node process, and renders it a string. This is what causes that initial fast paint of the entire application to the Browser, and helps us get all our SEO goodness :sparkles:

Notice the folder structure here in ./Client/ :

+ /Client/

+   /app/
    App NgModule - our Root NgModule (you'll insert Components/etc here most often)
    AppComponent / App Routes / global css styles

    * Notice that we have 2 dividing NgModules:
        browser-app.module & server-app.module
    You'll almost always be using the common app.module, but these 2 are used to split up platform logic
    for situations where you need to use Dependency Injection / etc, between platforms.

Note: You could use whatever folder conventions you'd like, I prefer to split up things in terms of whether they are re-usable 
     "components" or routeable / page-like components that group together and organize entire sections.
++ > ++ > /components/ 
          Here are all the regular Components that aren't "Pages" or container Components

++ > ++ > /containers/
          These are the routeable or "Page / Container" Components, sometimes known as "Dumb" Components

++ > ++ > /shared/
          Here we put all shared Services / Directives / Pipes etc

When adding new features/components/etc to your application you'll be commonly adding things to the Root NgModule (located in /Client/app/app.module.ts), but why are there two other NgModules in this folder?

This is because we want to split our logic per Platform, but notice they both share the Common NgModule named app.module.ts. When adding most things to your application, this is the only place you'll have to add in your new Component / Directive / Pipe / etc. You'll only occassional need to manually add in the Platform specific things to either browser-app.module || server-app.module.

To illustrate this point with an example, you can see how we're using Dependency Injection to inject a StorageService that is different for the Browser & Server.

// For the Browser (browser-app.module)
{ provide: StorageService, useClass: BrowserStorage }

// For the Server (server-app.module)
{ provide: StorageService, useClass: ServerStorage }

Just remember, you'll usually only need to worry about app.module.ts, as that's where you'll be adding most of your applications new aspects!

/Server/ - Our REST API (WebApi) - MVC Controller

As we pointed out, these are here for simplicities sake, and realistically you may want separate projects for all your microservices / REST API projects / etc.

We're utilizing MVC within this application, but we only need & have ONE Controller, named HomeController. This is where our entire Angular application gets serialized into a String, sent to the Browser, along with all the assets it needs to then bootstrap on the client-side, and become a full-blown SPA afterwards.


The short-version is that we invoke that Node process, passing in our Request object & invoke the boot-server file, and we get back a nice object that we pass into .NETs ViewData object, and sprinkle through out our Views/Shared/_Layout.cshtml and /Views/Home/index.cshtml files!

A more detailed explanation can be found here: TODO-add-link * You can read a more detailed explanation here

// Prerender / Serialize application (with Universal)
var prerenderResult = await Prerenderer.RenderToString(
    /* all of our parameters / options / boot-server file / customData object goes here */
);

ViewData["SpaHtml"] = prerenderResult.Html;
ViewData["Title"] = prerenderResult.Globals["title"];
ViewData["Styles"] = prerenderResult.Globals["styles"];
ViewData["Meta"] = prerenderResult.Globals["meta"];
ViewData["Links"] = prerenderResult.Globals["links"];

return View(); // let's render the MVC View

Take a look at the _Layout.cshtml file for example, notice how we let .NET handle and inject all our SEO magic (that we extracted from Angular itself) !

<!DOCTYPE html>
<html>
    <head>
        <base href="/" />
        <!-- Title will be the one you set in your Angular application -->
        <title>@ViewData["Title"] - AspNET.Core Angular 4.0.0 (+) Universal starter</title>

        <meta charset="utf-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        @Html.Raw(ViewData["Meta"]) <!-- <meta /> tags -->
        @Html.Raw(ViewData["Links"]) <!-- <link /> tags -->
        
        <link rel="stylesheet" href="~/dist/vendor.css" asp-append-version="true" />

        @Html.Raw(ViewData["Styles"]) <!-- <style /> tags -->

    </head>
    ... etc ...

Our Views/Home/index.cshtml simply renders the application and serves the bundled webpack files in it.

@Html.Raw(ViewData["SpaHtml"])

<script src="~/dist/vendor.js" asp-append-version="true"></script>
@section scripts {
    <script src="~/dist/main-client.js" asp-append-version="true"></script>
}

What happens after the App gets server rendered?

Well now, your Client-side Angular will take over, and you'll have a fully functioning SPA. (But we gained all these great SEO benefits of being server-rendered) !

:sparkles:



Universal "Gotchas"

When building Universal components in Angular 2 there are a few things to keep in mind.

  • window, document, navigator, and other browser types - do not exist on the server - so using them, or any library that uses them (jQuery for example) will not work. You do have some options, if you truly need some of this functionality:
    • If you need to use them, consider limiting them to only your client and wrapping them situationally. You can use the Object injected using the PLATFORM_ID token to check whether the current platform is browser or server.

       import { PLATFORM_ID } from '@angular/core';
       import { isPlatformBrowser, isPlatformServer } from '@angular/common';
       
       constructor(@Inject(PLATFORM_ID) private platformId: Object) { ... }
       
       ngOnInit() {
         if (isPlatformBrowser(this.platformId)) {
            // Client only code.
            ...
         }
         if (isPlatformServer(this.platformId)) {
           // Server only code.
           ...
         }
       }
    • Try to limit or avoid using setTimeout. It will slow down the server-side rendering process. Make sure to remove them ngOnDestroy in Components.

    • Also for RxJs timeouts, make sure to cancel their stream on success, for they can slow down rendering as well.
  • Don't manipulate the nativeElement directly. Use the Renderer2. We do this to ensure that in any environment we're able to change our view.
constructor(element: ElementRef, renderer: Renderer) {
  renderer.setElementStyle(element.nativeElement, 'font-size', 'x-large');
}
  • The application runs XHR requests on the server & once again on the Client-side (when the application bootstraps)
    • Use a cache that's transferred from server to client (TODO: Point to the example)
  • Know the difference between attributes and properties in relation to the DOM.
  • Keep your directives stateless as much as possible. For stateful directives, you may need to provide an attribute that reflects the corresponding property with an initial string value such as url in img tag. For our native element the src attribute is reflected as the src property of the element type HTMLImageElement.


FAQ - Also check out the FAQ Issues label

How can I disable Universal / SSR (Server-side rendering)?

Simply comment out the logic within HomeController, and replace @Html.Raw(ViewData["SpaHtml"]) with just your applications root AppComponent tag ("app" in our case): <app></app>.

You could also remove any isPlatformBrowser/etc logic, and delete the boot-server, browser-app.module & server-app.module files, just make sure your boot-client file points to app.module.

How do I have code run only in the Browser?

Check the Universal Gotchas on how to use isPlatformBrowser().

How do I Material2 with this repo?

You'll either want to remove SSR for now, or wait as support should be coming to handle Universal/platform-server rendering.

How can I use jQuery and/or some jQuery plugins with Angular Universal?

Note: If at all possible, try to avoid using jQuery or libraries dependent on it, as there are better, more abstract ways of dealing with the DOM in Angular (2+) such as using the Renderer, etc.

Yes, of course but there are a few things you need to setup before doing this. First, make sure jQuery is included in webpack vendor file, and that you have a webpack Plugin setup for it. new webpack.ProvidePlugin({ $: 'jquery', jQuery: 'jquery' })

Now, make sure any "plugins" etc that you have, are only included in your main.browser.ts file. (ie: import 'slick-carousel';) In a Component you want to use jQuery, make sure to import it near the top like so:

import * as $ from 'jquery';

Always make sure to wrap anything jQuery oriented in Angular's isPlatformBrowser() conditional!

How can I support IE9 through IE11?

To support IE9 through IE11 open the polyfills.ts file in the polyfills folder and uncomment out the 'import polyfills' as needed.