1.0.3 • Published 1 year ago

thematrix-entities v1.0.3

Weekly downloads
-
License
ISC
Repository
-
Last release
1 year ago

TheMatrix-Entities

Lightweight JavaScript Client Processing Library

Installation

Install with npm

  npm install thematrix-entities

Usage/Examples

  1. Initialize Entities Object
    let _baseUsers = [
      {
        id: 1,
        name: "user1",
        role_id: 1,
        role_name: "admin",
        country_id: 1,
        country_name: "Country 1",
        hourly_rate: 50,
        hours: 180
      },
      {
        id: 2,
        name: "user2",
        role_id: 2,
        role_name: "operator",
        country_id: 1,
        country_name: "Country 1",
        hourly_rate: 30,
        hours: 120
      }
    ];
    let eUsers=new Entities({
      list: _baseUsers,
      key: "id", //add new custom key if id is not unique
      init: function () {
        //called on each object once when adding to list
        this.icon = this._isAdmin()?<FaUserCircle />:<FaUser />; //jsx if supported by primary framework
        this.salary=0; //initialize any custom field
      },
      calculateSalary: function () {
          //custom function, need to be called with "_" prefix as eUsers._master[1]._callcuateSalary();
        this.salary = "$ " + Entities._u._formatComma(this.hourly_rate * this.hours, 2);
      },
      isAdmin: function () {
        //custom function, need to be called with "_" prefix as eUsers._master[1]._isAdmin();
        return this.role_id === 1;
      }
    });
  1. Entities-Object is made up of Entity objects indexed by key. Entity objects can be accessed under "_master" branch of Entities object.
console.log(eUsers._master[1]._isAdmin());
  1. Entities can be updated with _refresh(NEW_LIST) method.
eUsers._refresh([
    {},{},..
]);
//will call init method
  1. Entities can be appended with _append(NEXT_DATA) method.
eUsers._append([
    {},{},..
]);
//will call init method for new entries
  1. Branches list supplied to an Entities objects are assigned as "master" branch with branch key "_master". Other branches can be folked or filtered with _folk() method and _where() method.

5.1 Folking as new branch (not cloned)

eUsers._folk('to_branch','from_branch');

5.2 Folking as new branch by _where() method (not cloned)

//args:rules object or function array, source branch (default branch master=""), key column for new branch, new branch name 
eUsers._where({role_id:1},"","id","admins"); //listing only admin users as "admins" branch.

//with function array for advanced rules
eUsers._where([
    function(me){
        return me.role_id==1;
    }
],"","id","admins"); //listing only admin users as "admins" branch with advanced filtering.
  1. Creating JSON object/string
let json=eUsers._toJson();  
//with full arguments   
//args: branch, rules, is_javascript_object, pre_object + post_object, sortby  
let json=eUser._toJson('',[],true,null,'name') 
  1. Get a field value by other field's value
//args: by field, by field's value, field to get, source branch (default master="") 
let current_role_id=eUsers._getBy('id',1,'role_id',''); //get role_id where id=1
  1. Entities can be casted into an other model (with same columns, need to merge with _getColumnData() method.
//rules object or function array, unique key, source branch (default master="")
let roles=eUsers._model({},'role_id','');
//e.g. role model extracted with unique role_id
  1. Extracting sub model

7.1 Extracting a column data as sub model (with specified target fields)

//args: options object, source branch (default master=""), rules object or function array
let roles=eUsers._getColumnData(
        {
          columns: [
            ["role_id", "value"],
            ["role_name", "label"]
          ],
          mode: "unique", //remove duplicates
          orderBy: "label" //sort by sub-model-field
          topping:{role_id:-1,role_name:"No Role"}, //inject first custom item
          rottenEgg:{role_id:0,rolel_name:"Add New Role"} //append last custom item.
        },
        "", //source branch (default master="")
        {} //AND - rules, {column1:"value1",colum2:"value2"}
      );

7.2 Casting columns' data as sub model by custom rules

//args: options object, source branch (default master=""), rules object or function array   
let roles=eUsers._getColumnData(
        {
          columns: [
            ["role_id", "value"],
            ["role_name", "label"]
          ],
          mode: "unique", //remove duplicates
          orderBy: "label" //sort by sub-model-field
          topping:{role_id:-1,role_name:"No Role"}, //inject first custom item
          rottenEgg:{role_id:0,rolel_name:"Add New Role"} //append last custom item.
        },
        "", //source branch "" or "_mmaster" for default
        [
            function(me){
                return me.country_id=1;
            },
            function(me){
                return me.id>2;
            },
        ] //AND - rules
      );

Sample: https://codesandbox.io/s/crazy-pascal-jv4vl

import "./styles.css";
import React, { useState, useEffect } from "react";
import { Entity, Entities } from "thematrix-entities";
import Select from "react-select";
import { FaUser, FaUserCircle } from "react-icons/fa";
import SimpleTableComponent from "reactjs-simple-table";

export default function App() {
  const defC = []; //defC={value:0,label:'Select Countries'};
  const defR = { value: 0, label: "Select Role" };
  const defU = { value: 0, label: "Select User" };

  const [eUsers, setEUsers] = useState(
    new Entities({
      list: [],
      key: "id", //add new key if id is not unique
      init: function () {
        //called on each object once when adding to list
        this.icon = this._isAdmin()?<FaUserCircle />:<FaUser />;
        this.salary=0; //initialize any custom field
      },
      calculateSalary: function () {
        this.salary = "$ " + Entities._u._formatComma(this.hourly_rate * this.hours, 2);
      },
      isAdmin: function () {
        //custom function, need to be called with _ prefix
        // eUser._master[1]._isAdmin()
        return this.role_id === 1;
      }
    })
  );
  const [countries, setCountries] = useState([]);
  const [roles, setRoles] = useState([]);
  const [users, setUsers] = useState([]);
  const [tableUserData, setTableUserData] = useState([]);
  const [selCountries, setSelCountries] = useState(defC);
  const [selRoles, setSelRoles] = useState(defR);
  const [selUsers, setSelUsers] = useState(defU);
  const [loading, setLoading] = useState(true);
  const columns = [
    { field: "icon", headerName: "#" },
    { field: "name", headerName: "Name" },
    { field: "role_name", headerName: "Role" },
    { field: "country_name", headerName: "Country" },
    { field: "salary", headerName: "Salary" }
  ];
  
  const getSelectedArray = (sel) => {
    let _vals = [];
    if (!sel) return _vals;
    for (let i in sel) {
      _vals.push(sel[i].value);
    }
    return _vals;
  };

  useEffect(() => {
    //load data
    let _baseUsers = [
      {
        id: 1,
        name: "user1",
        role_id: 1,
        role_name: "admin",
        country_id: 1,
        country_name: "Country 1",
        hourly_rate: 50,
        hours: 180
      },
      {
        id: 2,
        name: "user2",
        role_id: 2,
        role_name: "operator",
        country_id: 1,
        country_name: "Country 1",
        hourly_rate: 30,
        hours: 120
      },
      {
        id: 3,
        name: "user3",
        role_id: 3,
        role_name: "user",
        country_id: 2,
        country_name: "Country 2",
        hourly_rate: 20,
        hours: 100
      },
      {
        id: 4,
        name: "user4",
        role_id: 3,
        role_name: "user",
        country_id: 3,
        country_name: "Country 3",
        hourly_rate: 20,
        hours: 75
      }
    ];

    eUsers._refresh(_baseUsers);
    //call calculateSalary method on each entity in list
    eUsers._calculateSalary(); 
    //can access filed of inner object by key under master branch
    //console.log(eUsers._master[1].salary);
    setEUsers({ ...eUsers });
  }, []);

  useEffect(() => {
    setCountries(
      eUsers._getColumnData(
        {
          columns: [
            ["country_id", "value"],
            ["country_name", "label"]
          ],
          mode: "unique",
          orderBy: "label"
          // topping:defC
        },
        "",
        {}
      )
    );
  }, [eUsers]);

  useEffect(() => {
   // console.log(selCountries);
    let _rule = []; //(selCountries.value===0)?[]:{country_id:selCountries.value};
    if (selCountries.length > 0) {
      let _cts = getSelectedArray(selCountries);
      _rule.push(function (me) {
        return _cts.includes(me.country_id);
      });
    }
    setRoles(
      eUsers._getColumnData(
        {
          columns: [
            ["role_id", "value"],
            ["role_name", "label"]
          ],
          mode: "unique",
          orderBy: "label",
          topping: defR
        },
        "",
        _rule
      )
    );
    setSelRoles(defR);
    setSelUsers(defU);
  }, [selCountries]);
  useEffect(() => {
    // let _rule=(selRoles.value===0)?[]:{role_id:selRoles.value};
    let _rule = [];

    if (selRoles.value > 0) {
      _rule.push(function (me) {
        return me.role_id == selRoles.value;
      });
    }
    if (selCountries.length > 0) {
      let _cts = getSelectedArray(selCountries);
      _rule.push(function (me) {
        return _cts.includes(me.country_id);
      });
    }

    //alert(_rule);
    setUsers(
      eUsers._getColumnData(
        {
          columns: [
            ["id", "value"],
            ["name", "label"]
          ],
          mode: "unique",
          orderBy: "label",
          topping: defU
        },
        "",
        _rule
      )
    );
    setSelUsers(defU);
  }, [selRoles]);
  useEffect(() => {
    let _rules = [];
    if (selCountries.length > 0) {
     // console.log(selCountries);
      let _cts = getSelectedArray(selCountries);
      _rules.push(function (me) {
        return _cts.includes(me.country_id);
      });
    }
    if (selRoles.value > 0) {
      _rules.push(function (me) {
        return me.role_id === selRoles.value;
      });
    }
   // console.log("rule", _rules);
    if (selUsers.value > 0) {
      _rules.push(function (me) {
        return me.id === selUsers.value;
      });
    }
    
    setLoading(true);
    //fillter data
    //approach 1: filter into a branch and convert json
    // eUsers._where(_rules, "filter", "id", "");
    // console.log('brs',eUsers._branches);
    //setTableUserData(eUsers._toJson('filter');

    //approach 2: convert json with filtering rule
    //first argument source branch
    setTableUserData(eUsers._toJson("", _rules));
  }, [selUsers]);
  useEffect(() => {
    setTimeout(function () {
      setLoading(false);
    }, 20);
  }, [tableUserData]);
  return (
    <>
      <Select
        id="countries_select"
        isMulti
        isSearchable
        name="country"
        value={selCountries}
        options={countries}
        onChange={(sel) => {
          setSelCountries(sel);
        }}
      />
      <Select
        id="roles_select"
        isSearchable
        name="role"
        options={roles}
        value={selRoles}
        onChange={(sel) => {
          setSelRoles(sel);
        }}
      />
      <Select
        id="users_select"
        isSearchable
        name="user"
        value={selUsers}
        options={users}
        onChange={(sel) => {
          setSelUsers(sel);
        }}
      />

      {loading ? (
        <></>
      ) : (
        <>
          <SimpleTableComponent columns={columns} list={tableUserData} />
        </>
      )}
    </>
  );
}