1.0.6 • Published 5 years ago

winkit-cli-angular v1.0.6

Weekly downloads
1
License
MIT
Repository
-
Last release
5 years ago

Winkit Angular

IMPORTANT: Before starting a Winkit Angular project, make sure to read about the basics of Winkit CLI.

Contents

  1. Adding Winkit Angular plugin
  2. Getting help
  3. Quick start
  4. Server configuration
  5. Primary database key
  6. Winkit Angular commands
    1. Initializing a project
    2. Generating a model
    3. Generating a service
    4. Generating a detail
    5. Generating a list
    6. Updating a model
  7. Known issues
  8. What's next?

Adding Winkit Angular plugin

To add the Winkit Angular plugin to your project, run:

winkit add:plugin angular

Getting help

To get help on Winkit Angular commands run winkit angular --help

Quick start

Server configuration

Out-of-the-box Winkit Angular supports two server platforms - Strapi (visit website) and Firestore (visit website). Learn how to prepare your server for work with Winkit Angular:

Firestore

If you want to use Winkit with Firestore you must first configure your project in Firebase. Once the project is created, open /src/environments/environment.ts and update firebaseConfig with the project info. Do the same for /src/environments/environment.prod.ts with info for production environment.

Strapi

  1. install strapi globally

    npm install strapi@alpha -g
  2. Run the following command line in your terminal:

    strapi new strapi-winkit
  3. Go to your project and launch the server:

    cd strapi-winkit
    strapi start
  4. Create your first admin user

  5. Open strapi-winkit/plugins/users-permissions/models/User.settings.json

  6. Replace the content with the following:

    {
      "connection": "default",
      "info": {
        "name": "user",
        "description": ""
      },
      "attributes": {
        "username": {
          "type": "string",
          "minLength": 3,
          "unique": true,
          "configurable": false,
          "required": true
        },
        "email": {
          "type": "email",
          "minLength": 6,
          "configurable": false,
          "required": true
        },
        "password": {
          "type": "password",
          "minLength": 6,
          "configurable": false,
          "private": true
        },
        "confirmed": {
          "type": "boolean",
          "default": false,
          "configurable": false
        },
        "blocked": {
          "type": "boolean",
          "default": false,
          "configurable": false
        },
        "role": {
          "model": "role",
          "via": "users",
          "plugin": "users-permissions",
          "configurable": false
        },
        "userRole": {
          "default": "",
          "type": "string"
        },
        "firstName": {
          "default": "",
          "type": "string"
        },
        "lastName": {
          "default": "",
          "type": "string"
        },
        "description": {
          "default": "",
          "type": "string"
        },
        "telephone": {
          "default": "",
          "type": "string"
        },
        "profileImg": {
          "default": "",
          "type": "string"
        },
        "dateOfBirth": {
          "default": "",
          "type": "integer"
        },
        "registeredAt": {
          "default": "",
          "type": "integer"
        },
        "isMale": {
          "default": false,
          "type": "boolean"
        },
        "media": {
          "collection": "file",
          "via": "related",
          "plugin": "upload"
        }
      },
      "collectionName": "users-permissions_user"
    }
  7. Go to http://localhost:1337/admin/plugins/content-manager/user?source=users-permissions

  8. Open the admin detail and populate the userRole field with the value ADMIN then save.

  9. Now you can log into Winkit using these user credentials!

Primary database key

In your Winkit project you can either use the default primary database key or configure a custom primary database key.

The default key is 'id' (for the front-end) and '_id' (for the back-end). To use a different key provide it when prompted for the primary key upon initializing your project.

After initializing the project you can still change the primary key at any point in time by following these steps: 1. In the \<project folder>/winkit.conf.json file add or edit the primaryKey key by providing your value (minimum 2 characters). 2. Edit the \<project folder>/src/app/@core/models/Mappable.ts file by providing the name of your primaryKey as the first key of the Mappable interface; 3. Update all models in your project using the winkit angular update model ... command (more info);

Commands

winkit angular init|i \<projectName>

Initializes a new WDK Angular application in a new folder.

winkit angular init myproject

The application works right out of the box. Included are: authentication, password recovery, user CRUD, profile page, file upload, etc.

winkit angular generate|g model \<name>

Generate a new model and its associated server model, ready to be mapped.

NOTE: If you are using Strapi remember to also:

  • create the model on the server-side (ex. using the Strapi dashboard)
  • add the wid: string parameter for both models

(if you are using Firestore you don't have to do anything because everything will be managed by WDK Angular)

Let's explain with an example:

winkit angular generate model Foo

This command will generate the following file structure in the src/app/modules/ folder:

  • foo/
    • models/
      • Foo.ts
      • ServerFoo.ts
      • FooDataFactory.ts
    • foo.conf.json
    • foo.module.ts
    • foo.routing.ts

NOTE: The foo/ directory and the foo.conf.json, foo.module.ts and foo.routing.ts files are only generated if they don't exist yet.

1. src/app/modules/foo/models/Foo.ts
  • map(obj: ServerFoo): Foo : maps the model starting from its server model.

    Ex. const foo = new Foo().map(serverFoo);
  • mapReverse(): ServerFoo : maps the model starting from its server model.

    Ex. const serverFoo = foo.mapReverse();

2. src/app/modules/foo/models/ServerFoo.ts
  • static map(obj: Foo): ServerFoo : this method is called by the model mapReverse function.

    It returns a server model (in this case ServerFoo) with properties initialized using the logic provided in the private getMappedAttribute method (see below).

    Model properties which exist on the model only and don't exist on the server should have the existsOnModelOnly attribute in the \<model>.conf.json file set to true. This way they will not be initialized on the server model returned by the method.

    Learn more about model configuration

  • static mapReverse(serverObject: ServerUser): User : this method is called by the model map function.

    It returns a model (in this case Foo) with properties initialized using the logic provided in the private getReverseMappedAttribute method (see below).

    Model properties which exist on the model only and don't exist on the server should have the existsOnServerOnly attribute in the \<model>.conf.json file set to true. This way they will not be initialized on the model returned by the method.

  • private static getMappedAttribute(model: User, prop: ModelProperty): string : this method is used in the server model map function to compute the value of the server model attribute.

    The default logic is:

    typeof model[localName] !== 'undefined' ? model[localName] : defaultValue

    To provide your own logic, use the case clause which corresponds to the attribute.

  • private static getReverseMappedAttribute(serverObject: ServerUser, prop: ModelProperty): string : this method is called by the server model mapReverse function to compute the value of the model attribute.

    The default logic is:

    typeof serverObject[serverName] !== 'undefined' ? serverObject[serverName] : defaultValue

    To provide your own logic, use the case clause which corresponds to the attribute.

3. src/app/modules/foo/models/FooDataFactory.ts

File providing data used by the model's components. This file is updated by Winkit Angular based on the htmlConfig configuration in model properties.

4. src/app/modules/foo/foo.conf.json

The model configuration file. For more information on using the file, see the update model documentation.

5. src/app/modules/foo/foo.module.ts

The model module file - a standard Angular module which handles all the data and dependencies related to the model.

6. src/app/modules/foo/foo.routing.ts

The model routing file. It exports an object with 2 properties:

  • componentRoutes (required): an array of Angular type Routes
  • routeInfo (optional): an object of type RouteInfo

winkit angular generate|g service \<modelName>

Generate a new service for given model, so you'll be ready to implement CRUD that works with the server chosen in the initialization.

NOTE: If the associated model does not exist yet, it is generated together with all necessary files (for more info see generate model section), before the the service file is generated.

Let's explain with an example:

winkit angular generate|g service Foo

This command will generate the service and add it to the foo.module.ts:

src/app/modules/foo/service/foo.service.ts

on creation the service includes methods that allow you to:

  • Create model
  • Update model
  • Delete model
  • Get model by id
  • Get paginated list

winkit angular generate|g detail \<modelName>

Generate a new detail component for given model and implement its routing, so you'll be ready to display model info.

Let's explain with an example:

winkit angular generate|g detail Foo

This command will generate:

1. src/app/modules/foo/foo-detail/
  • foo-detail.component.ts
  • foo-detail.component.html
  • foo-detail.component.scss

This component implements the CRUD of the Model, including validation.

2. foo/:id route in src/app/modules/foo/foo.routing.ts

By default the generated route is accessible just by authenticated user with ADMIN role. Thanks to this route you can:

  • Create new instance of this model:
 localhost:5000/foo/new
  • Detail / Update the instance with given id, ex. #1:
 localhost:5000/foo/1

NOTE: The model info will be displayed in the detail component inside a <form> element. You can manage the form control elements inside the form by:

  • editing the <modelName>-detail.component.html file (make sure to add "skipUpdate": true to the property's config in \<model>.conf.json)
  • editing the <modelName>.conf.json configuration file and updating the model and detail (more info)
  • passing an array of type FormControlList as the 2nd argument in the <modelName>DataFactory.getFormControls() call in <modelName>-detail.component.ts (make sure to add "skipUpdate": true to the property's config in \<model>.conf.json). For example:

.../someModel-detail.component.ts

this.formControlList = ZdueDataFactory.getFormControls(this, [
  {name: 'sometext', type: FormControlType.TEXT}
]);

.../someModel.conf.json

"properties": [
    {"name": "someText", "skipUpdate": true},
    ...
]

winkit angular generate|g list \<modelName>

Generates a new list component for given model, implements its routing and adds the link to the sidebar, so the list is ready to be displayed, including pagination and filtering.

Let's explain with an example:

winkit angular generate|g list Foo

This command will generate:

1. src/app/modules/foo/foo-list/
  • foo-list.component.ts
  • foo-list.component.html
  • foo-list.component.scss

This component includes the paginated table list and the filter component.

2. foo-list route in src/app/modules/foo/foo.routing.ts

By default the generated route is accessible just by authenticated user with ADMIN role. Every element in the table includes a link to its detail page.

3. foo-list link in src/app/@core/sidebar/sidebar-routes.config.ts

By default the link is visible just to ADMIN users.

winkit angular update|u model \<name>

Updates a model based on the configuration in the \<name>.conf.json file.

(example configuration file)

The schema of the \<name>.conf.json configuration file is the following:

  • "properties" (Array<ModelProperty>): an array of ModelProperty objects.

IMPORTANT: To exclude a ModelProperty from being updated by Winkit (ex. because you want to something custom with it), set its skipUpdate property to true (see below for more info);

The structure of the ModelProperty object is the following:

  • name (string: required): the name of the model property;
  • serverName (string: optional): name of the corresponding server model property, if different from ModelProperty.name;
  • isOptional (boolean: optional): adds TypeScript's optional class marker to a property (more info);
  • type (string: optional): a string containing a typescript type (more info);
  • serverType (string: optional): name of the corresponding server model type, if different from ModelProperty.type;
  • value (any: optional): the default value assigned to the model on initialization. Setting this key results in ignoring the type and optional keys;
  • isManuallyUpdated (boolean: optional): setting this value to true results in the model property being skipped if it already exists and is initialized on the model, when the model is updated using winkit angular update|u .... It also results in the property not being added to the model detail. For info on rectifying this, see this section;
  • mapReverseName (string: optional): The name of the model property to which the server model property value should be assigned in the mapReverse method of the server model;
  • relationship (string: optional): Maps the value of the provided model property to the current property, e.g. the following configuration: {"name": "wid", "relationship": "id", ...} will result in mapping the value of the id property to the wid property in the model constructor and the server model map method;
  • mapReverseRelationship (string: optional): Maps the value of the provided server model property to the current property, e.g. the following configuration: {"name": "wid", "mapReverseRelationship": "_id", ...} will result in mapping the value of the _id property to the wid property in the server model mapReverse method;
  • existsOnModelOnly (boolean: optional): Excludes the model property from being initialized inside the Server\<Model>.map method;
  • existsOnServerOnly (boolean: optional): Excludes the model property from being initialized inside the Server\<Model>.mapReverse method;
  • htmlConfig (object: optional): An object containing configuration of a single form control element. Must be set for the form control element to be displayed in the detail component of a given model. For more information see Structure of the htmlConfig object section below;

NOTE: The primary key property settings are not affected by the \<name>.conf.json configuration.

STRUCTURE OF THE htmlConfig OBJECT

The structure of htmlConfig object mostly reflects attributes of an HTMLInputElement but also has some additional settings:

GENERAL

  • type (FormControlType | HTMLInputElement.type): a HTMLInputElement type or one of the special types listed in the FormControlType enum;
  • ngIf (boolean: optional): sets the value of the angular ngIf directive (more info) of the Form Element;
  • required (boolean: optional): sets the required attribute of the input element;
  • disabled (boolean: optional): sets the disabled attribute of the input element;
  • readonly (boolean: optional): sets the readonly attribute of the input element;
  • pattern (boolean: optional): sets the pattern attribute of the input element;
  • wrapperClass (string: optional): The class of the generated HTML element. Default value: col-sm-6 mb-3
  • innerWrapperClass (string: optional): The class of the <div> element that wraps the contents of the generated HTML element.
  • order (number | string: optional): Sets the CSS order property of the form element.
  • inputFeedbackText (string: optional): The text inside the <small> element, which is displayed when the value of the input is invalid. NOTE: Setting the inputFeedbackText attribute is the condition for displaying the <small> feedback element.
  • inputFeedbackExample (string: optional): The italicized text displayed in round brackets after inputFeedbackText inside the <small> element.

FORM ELEMENT TYPE: SELECT

  • options (Array<string | {name: string, value: any}>: required): The list of <option> elements that will be generated inside the <select> element.

FORM ELEMENT TYPE: MEDIA

  • allowedTypes (Array<MediaType>: required): Array of MediaType enum values.

FORM ELEMENT TYPE: TEXTAREA

  • rows (number: optional): sets the rows attribute of the <textarea> element. Default value: 6

IMPORTANT:

  • Inside htmlConfig you can use the that keyword to reference an external object. By default this object is the current model's detail component class (ex. FooDetailComponent). This is achieved by passing this as the 1st argument in the <modelName>DataFactory.getFormControls() call in <modelName>-detail.component.ts. To reference a different object pass it as the 1st argument instead of this.
  • To set a string literal as a value in htmlConfig wrap it in additional quotes, ex.: "'example string literal'"

Let's explain with an example:

src/app/modules/foo/foo.conf.json

{
  "properties": [
    {"name": "first", "optional": true},
    {"name": "second", "type": "{id: number, [key: string]: any, someKey: SomeClass[]}"},
    {"name": "third", "value": "['some string', 1.2]"},
    {"name": "fourth", "skipUpdate": true},
    {"name": "fifth", "type": "string", "htmlConfig": {
      "type": "FormControlType.SELECT", "required": true, "options": "that.fifthPropOptions"
    }}
  ]
}

With the above configuration, running this command:

winkit angular update|u model Foo

will result in the following property settings in Foo.ts and ServerFoo.ts models:

1. src/app/modules/foo/models/Foo.ts
...
id: string;
wid: string;
first?;
second: {id: number, [key: string]: any, someKey: SomeClass[]};
third = ['some string', 1.2];
fifth: string;
...
constructor()
constructor(id?: string,
            first?,
            second?: {id: number, [key: string]: any, someKey: SomeClass[]},
            third?: any,
            fifth?: string) {
    this.id = typeof id !== 'undefined' ? id : null;
    this.wid = typeof id !== 'undefined' ? id : null;
    this.first = typeof first !== 'undefined' ? first : null;
    this.second = typeof second !== 'undefined' ? second : null;
    this.third = typeof third !== 'undefined' ? third : ['some string', 1.2];
    this.fifth = typeof fifth !== 'undefined' ? fifth : null;
}
...
2. src/app/modules/foo/models/ServerFoo.ts
...
_id?: string;
wid?: string;
first?;
second: {id: number, [key: string]: any, someKey: SomeClass[]};
third: any = ['some string', 1.2];
fifth: string;
...
static map(obj: Zuno): ServerZuno {
    const o = {} as ServerZuno;
    o._id = typeof obj.id !== 'undefined' ? obj.id : null;
    o.wid = typeof obj.id !== 'undefined' ? obj.id : null;
    o.first = typeof obj.first !== 'undefined' ? obj.first : null;
    o.second = typeof obj.second !== 'undefined' ? obj.second : null;
    o.third = typeof obj.third !== 'undefined' ? obj.third : null;
    o.fifth = typeof obj.fifth !== 'undefined' ? obj.fifth : null;
    return o;
}
...
static mapReverse(serverObject: ServerZuno): Zuno {
    const o = {} as Zuno;
    o.id = typeof serverObject._id !== 'undefined' ? serverObject._id : null;
    o.wid = typeof serverObject._id !== 'undefined' ? serverObject._id : null;
    o.first = typeof serverObject.first !== 'undefined' ? serverObject.first : null;
    o.second = typeof serverObject.second !== 'undefined' ? serverObject.second : null;
    o.third = typeof serverObject.third !== 'undefined' ? serverObject.third : null;
    o.fifth = typeof serverObject.fifth !== 'undefined' ? serverObject.fifth : null;
    return o;
}
...
3. src/app/modules/foo/models/FooDataFactory.ts
...
static getFormControls = (that: any, customControlList: FormControlList = []): FormControlList => {
    const generatedFormControls: FormControlList = [
      {name: 'fifth', required: true, type: FormControlType.SELECT, options: that.fifthPropOptions}
    ];
...

Known issues

  • Strapi has been reported to not support Node.js >9 versions on certain versions of Windows. Link to issue
  • In Strapi 3.0.0-alpha.15 and 3.0.0-alpha.16 there is a bug causing update actions of User objects to fail. For possible solutions see this Strapi issue report
  • In Strapi 3.0.0-alpha.15 and 3.0.0-alpha.16 there is a bug causing create requests for non-User models to return a 404 error, even though instances of models are correctly created. See this Strapi issue report
  • In Firestore the filter feature is case sensitive and must match the whole value

What's next?

winkit angular update|u model \<modelName>

  • Add the generated parameter to the table header in the list component

winkit angular delete|d \<elementType> \<modelName>

This command will delete the model and all its associated files.

1.0.6

5 years ago

1.0.5

5 years ago

1.0.4

5 years ago

1.0.3

5 years ago

1.0.2

5 years ago