1.0.2 • Published 8 months ago

@sintradigital/vustack v1.0.2

Weekly downloads
-
License
MIT
Repository
-
Last release
8 months ago

configuration

The Vustack project includes a plugins directory that contains various plugins to extend the application (e.g., http, uimessages). Each of these can be imported and used as Vue plugins within your application.

In addition to these plugins, Vustack provides a core module that includes global configurations. This core module should also be registered as a Vue plugin in your main entry file (main.js or main.ts). Below is an example of how to include it:

// main.js or main.ts

import Vustack from 'vustack';
app.use(Vustack, {
  "test": 243
});

Once included, you'll be able to access the Vustack instance via this.$vustack in any component. The oder plugins can be load similarly:

// main.js or main.ts

import { http } from 'vustack/plugins/http.js'
import { uimessages } from 'vustack/plugins/uimessages.js'
app.use(uimessages);
app.use(http);

routing menu

The setup provides a standard configuration for routing and menus. It operates using vue-router, where the necessary information for rendering the navigation menu is included within the route metadata.

The following parameters can be used in the route metadata:

ParameterDescription
titleRepresents the main label of the menu item.
subtitleRepresents a descriptive subtitle.
iconSpecifies the icon in MDI format, such as mdi-information, mdi-account.
enabledIndicates whether the route should be included in the menu.
orderSpecifies a number used to sort the menu items within the navigation tree.

Note

Currently, the menu component only supports a single-level menu. However, in the future, more complex views may be implemented, potentially including a path field in the metadata to build a hierarchical navigation tree.

A typical route is like this:

const _routes=[
    {
      path: '/',
      name: 'home',
      meta:{
        enabled: true,
        title: "Home",
        icon: "mdi-information",
        subtitle: "Subtitle",
        order:1
      },
      component: () => import('../views/HomeView.vue'),
    }
    //...
    ];

Vuesack Overview and components

Vuestack provides a set of data-driven components that can be extended through component inheritance. This design allows for the separation of data presentation from the data source.

Data List Components

ComponentPaginationEditingFilters
List ViewYesTo be testedTo be implemented
Data TableYesTo be testedYes

Record View Components

ComponentStatus
JsonFormCommonEditorTo be completed and integrated with the list components
PropertyViewTo be tested and integrated with the list components

Data Adapters

Vuestack includes several data adapters for fetching data:

Data AdapterDescription
baseDataSourceImplements fake methods for data access.
restDataSourceImplements the standard REST protocol, allowing the developer to define the necessary code for HTTP requests.
apiStackDataSourceImplements the ApiStack API protocol.

Component Composition

By composing these components, you can configure various combinations, such as instantiating a DataGrid with an ApiStack connection:

import restDataService from 'vustack/extensions/restDataService';
const _config={/* conf omitted */};

const _Base=restDataService("action",{
  axios:axios
});

const DataGrid=Vustack.compone(_Base,_DataGrid);

Similarly, you can define a new data source connector or extend an existing one. For example, here's a datasource with hardcoded data:

// Example of a datasource with hardcoded data

const _Base=restDataService("action",{
  axios:axios
});

const _Override={
    methods:{
        getPagedData: async function (page,itemsPerPage,_sortBy,filters) {
            return [{id:22, name:"my", value:"value"},
                {id:23, name:"my1", value:"value1"},
                {id:24, name:"my2", value:"value2"}
            ]
        }
    }
};

const DataSource=Vustack.compone(_Base,_Override);

Complete Example

Below is a complete example of including a data grid component:

// Complete example of a data grid component inclusion

<template>
  <DataGrid labelEdit="Action" title="Applications"  :config="config">
  </DataGrid>
</template>

<script >
import _DataGrid from "vustack/components/DataGrid.vue";
import restDataService from 'vustack/extensions/restDataService';
const _config={
  paging:{
    itemsPerPage:4,
  },
  editing:{
    enabled:true
  },
  filters: {
    enabled:true,
    options:{
      filtersDef:{
        fields:[{
          name:"myfield",
          label:"My field Id",
          component :"v-text-field"
        },
        //...
        }],
      }
    },
    component: "FilterForm"
  },
  headers: [
          { key: 'myfield', title: 'My field Id' },
          { key: 'myfield2', title: 'Field2' }
        ],
};

const _Base=restDataService("action",{
  axios:axios
});

const DataGrid=Vustack.compone(_Base,_DataGrid);

export default {
  name: "DataGridView",
  components: {
    DataGrid
  },
}
</script>

List View Component

The List View component displays paginated data from the data source. The presentation logic is entirely managed at the templating level. See the example below:

// Example of List View templating

<ListView labelEdit="Action" title="Applications" >
    <template v-slot:itemTitle="{ item }">
      {{item.first_name}} {{item.last_name}}
    </template>
    <template v-slot:itemSubTitle="{ item }">
      {{item.email}} ({{item.gebder}})
    </template>
  </ListView>

If the editing.enabled configuration parameter is set to true, action components for editing and deleting records, as well as a button for adding new entries, will be displayed. The editing form should also be implemented at the templating level within the "edit" slot.

// Example of List View templating with editing

<ListView labelEdit="Action" title="Applications" >
    //...
    <template v-slot:edit="{ editingItem }">
      XXX EDITING
    </template>
  </ListView>

Data Grid Component

The DataGrid component can be extended through both configuration and templating. The configuration object is comprehensive and includes the following sections:

  • paging: Settings for pagination.
  • editing: Settings for the data entry/editing form.
  • view: Settings for the data view form.
  • delete: Settings for the data deletion.
  • filters: Settings for the search filters form.
  • headers: Settings for the data columns.

Paging

ParameterDescription
itemsPerPageNumber of items displayed per page by default.
enabledPagination for the data grid cannot be disabled.

Editing

ParameterDescription
enabledIf true, enables data editing (insert and update).
componentSpecifies the component to use for the entry/edit form. This can be any registered component or a path for dynamic loading.
optionsProperties that will be passed to the component.

delete

ParameterDescription
enabledIf true, enables data deletion.
componentSpecifies the component to use for the entry/edit form. This can be any registered component or a path for dynamic loading.
optionsProperties that will be passed to the component.

view

ParameterDescription
enabledIf true, enables data view.
componentSpecifies the component to use for the entry/edit form. This can be any registered component or a path for dynamic loading.
optionsProperties that will be passed to the component.

Filters

ParameterDescription
enabledIf true, enables search filters.
componentSpecifies the component to use for the filters form. This can be any registered component or a path for dynamic loading.
optionsProperties that will be passed to the component.

Headers

The headers configuration is an array defining the standard columns of the native Vuetify table component. Refer to the official documentation for all available options.

In addition to the standard headers, for each header you can include these custom attributes:

ParameterDescription
sortedtrue if the column is pre sortered
asccontains a constant string value

Header Override

The headerOverrides array in the configuration allows column customization. Any column defined in the headers section can be overriden (you can use keys not present in the model, adding fully computed fields). There are three ways of extending a column:

  • use a constant value
  • use a render function
  • use a ready to be used component
ParameterDescription
keyit is the concatenation of type (item or header) and the key of the column (eg. header.id oritem.id)
componentif not empty print a component. This is an object with componentName and options fields available. Options properties are passed as props to the component. The value attribute allows to re-define the javacript expressoin for compute a custom column value, like in the render section
renderit is a javascript snippet with no return statement. the scope contains item,index, column, value when available. eg. value+'fdsfsf'+item.field
textcontains a constant string value

component,render, field are not mutually exclusive: the are rendered one above the other. Use only one at once if you need it.

Here a list of examples.

Constant value

{
  key: "item.id",
  text: "hello worlds"
}

Render Function

{
  key: "item.id",
  render: "value+' myconstant'"
}

Component

{
  key: "item.id",
  component: {
      componentName:"v-alert",
      options:{
        text:"prova",
        type:"success"
      },
    }
}

Javascript function

Javascript functions are allowed inside render and component.value elements. Both of them have the following prototype. The parameters availability depends on the context (item or header).

The expression:

"component": {
                "value":"value+' ssdfdsf'",
                "componentName": "SimpleText"
                
              }

is equivalent to:

function computeValue(item,index, column, value){
  return value+' ssdfdsf';
}

Default sorting

Ecco la descrizione con una tabella per i parametri:


Default Sort

The defaultSort section is an array that contains additional sorting conditions beyond those mapped directly onto the grid columns. These conditions are static and are applied before any dynamic conditions set by the data grid. This attribute allows you to enforce default sorting rules, including sorting by non-visible columns. If sorting is applied to a column already present, the values defined in defaultSort take precedence (i.e., the sorting cannot be modified by the user if specified here).

Parameters of defaultSort Elements:

ParameterDescriptionValues
keyThe name of the fieldAny column field name
orderThe sorting directionasc (ascending), desc (descending)

Example:

"defaultSort": [
  {
    "key": "routeShortName",
    "order": "asc"
  }
]

Full example

Below is a complete example of a configuration:

// Complete configuration example for DataGrid

{
  paging:{
    itemsPerPage:4,
  },
  editing:{
    enabled:true,
    component:'JsonFormCommonEditr',
    options:{
        settingsName:'accounts'
    }
  },
  filters: {
    enabled:true,
    options:{
      filtersDef:{
        fields:[
        {
          name:"campo1",
          label:"Campo 1",
          component :"v-text-field"
        },
        {
          name:"campo2",
          label:"Campo 2",
          component :"v-switch"
        },
        {
          name:"campo3",
          label:"Campo 3",
          component :"v-select",
          options:{
            items:[12,213,123,234]
          }
        }],
      }
    },
    component: "FilterForm"
  },
  headers: [
          {
            align: 'start',
            key: 'id',
            sortable: false,
            title: 'id',
          },
          { key: 'name', title: 'Name' },
          { key: 'code', title: 'Code' },
        ],
}

Moreover, you can override filters or edit component by changing the template via slots:

<template>
  <DataGrid labelEdit="Action" title="Applications"  :config="config">
     <template v-slot:edit="{ editingItem }">
       <!-- my implementation-->
    </template>
     <template v-slot:filters="{  }">
        <!-- my implementation-->
    </template>
  </DataGrid>
</template>

JsonFormCommonEditor Component

Overview

The JsonFormCommonEditor component implements a JSON form within a container that provides dual visualization modes: JSON (raw data) and form view. This dual-view feature is particularly useful for debugging or technical applications. The two views, hosted in separate tabs, are synchronized and accessible, allowing users to seamlessly switch between them. The dual-mode feature is enabled via the debug parameter.

Features

  • Dual view: JSON raw data and form, synchronized in real-time.
  • Debugging support: The dual-mode view, enabled by the debug parameter, helps in identifying and resolving issues efficiently.
  • Tab-based layout: JSON and form views are presented in separate, easy-to-navigate tabs.

Parameters

entity

  • The entity field defines the name of the form to be used. This name corresponds to the configuration files required to render the form.
  • For example, an entity value of "test" links to the following configuration files:
    • JSON Schema: /schemas/test.json
    • UI Schema: /schemas/test-ui.json

The JSON Schema defines the data structure, while the UI Schema follows the format used by the JSON Form library to describe the form's user interface.

Documentation

For full documentation, visit: the json form website and the UI plugin for vuetify

Demo and Materials

For a demo and additional resources, visit: Demo with examples

Example using dynamic component

Suppose to have the following data model:

{
  "date": "2022-06-15",
  "stringDate": "2022-06",
  "stringDateFull": "2022-06-15",
  "stringYear": "324"
}

The config for a dynamic component:

{
    "componentName": "JsonFormCommonEditor",
    "options":{
        "entity":"test",
        "debug":false
    }
}

The JSON Schema located at /schemas/test.json:

{
  "type": "object",
  "properties": {
    "date": {
      "type": "string",
      "format": "date"
    },
    "stringDate": {
      "type": "string"
    },
    "stringYear": {
      "type": "string"
    },
    "stringDateFull": {
      "type": "string"
    }
  }
}

The UI Schema located at /schemas/test-ui.json:

{
  "type": "Categorization",
  "elements": [
    {
      "type": "Category",
      "label": "Hide Actions",
      "elements": [
        {
          "type": "VerticalLayout",
          "elements": [
            {
              "type": "Group",
              "label": "Schema Based",
              "elements": [
                {
                  "type": "HorizontalLayout",
                  "elements": [
                    {
                      "type": "Control",
                      "scope": "#/properties/date",
                      "label": "Date",
                      "options": {
                        "dateFormat": "MM/DD/YYYY",
                        "dateSaveFormat": "YYYY-MM-DD"
                      }
                    }
                  ]
                }
              ]
            },
            //... omissis

note: the code abova can be inclueded in edit or view form of a datagrid or listview

Api service

The base interface for a DataSource component is as follows:

{
    getPagedData: async function (page, itemsPerPage, _sortBy, filters) {},
    getItem: async function (id, force) {},
    insert: async function (data) {},
    update: async function (data) {},
    deleteItem: async function (data) {},  
}

Functionality Overview

MethodDescription
getPagedDataReturns a paginated list of data.
getItemReturns a single item based on the id. If the force parameter is false, it retrieves the item from local cache if available.
insertProvides functionality to insert new data.
updateProvides functionality to update existing data.
deleteItemProvides functionality to delete data.

Hooks by Implementation

restDataSource

HookDescription
createListRequestCreates a request for listing data.
createInsertRequestCreates a request for inserting data.
createUpsertRequestCreates a request for updating or inserting data (upsert).
unpackGetListRequestUnpacks the request for listing data.
unpackGetRequestUnpacks the request for retrieving a single item.
unpackUpsertResponseUnpacks the response from an upsert request.

ApiStack

VariableDescription
Entity NameThe name of the entity being managed.
URLThe URL used for the API requests. If not specified, defaults to the base configuration.

Dynamic Loading

Vustack features an automatic configuration mechanism based on settings. In the standard configuration, files must be static assets exposed in the /settings directory of the compiled app. The file name acts as a key for the settings being referenced. For example, specifying "test" will refer to the file /settings/test.json.

This mechanism can be utilized in two levels of automation:

1. Reading Dynamic Parameters

Component configuration can be read dynamically at runtime through an optimized service. See the example below:

// Example of reading dynamic parameters

 let config=await this.vustack.services.getSettings(this.configName);

2. Adoption of Dynamic Components

When defining routing, it is sufficient to define the adoption of a dynamic component. In this case, there is no need to create specific Vue components; configuration alone is enough. See the example below:

// Example of including dynamic component
const _routes=[{
            path: '/dynamic',
            name: 'dynamic',
            meta:{},
            component: DynamicComponent,
            props:{
              configName:"test"
            }
          }
  ]

The configName parameter corresponds to the configuration file to be read. Within this file, the following properties will be present:

PropertyDescription
componentNameCan be either the name of a loaded component or a dynamic path.
optionsProperties to be passed to the component.

Below is a complete example demonstrating the loading of a DataGrid component:

// Complete example of loading a DataGrid component
{
  "componentName": "DataGrid",
  "extension":["restDataService"],
  "options": {
    "config": {
      "paging": {
        "itemsPerPage": 4
      },
      "editing": {
        "enabled": true
      },
      "filters": {
        "enabled": true,
        "options": {
          "filtersDef": {
            "fields": [
              {
                "name": "routeId",
                "label": "Route Id",
                "component": "v-text-field"
              },
              {
                "name": "campo1",
                "label": "Campo 1",
                "component": "v-text-field"
              },
              {
                "name": "campo2",
                "label": "Campo 2",
                "component": "v-switch"
              },
              {
                "name": "campo3",
                "label": "Campo 3",
                "component": "v-select",
                "options": {
                  "items": [
                    12,
                    213,
                    123,
                    234
                  ]
                }
              }
            ]
          }
        },
        "component": "FilterForm"
      },
      "headers": [
        {
          "align": "start",
          "key": "id",
          "sortable": false,
          "title": "id"
        },
        {
          "key": "routeId",
          "title": "Route id"
        },
        {
          "key": "routeLongName",
          "title": "Name"
        },
        {
          "key": "routeShortName",
          "title": "Code"
        }
      ]
    }
  }
}

Note: because the configuration object is read by http call, it must be a JSON object not a javascript object (so, you cannot use function and you must respect JSON rules).

Environments and deploy

Configuration

Vustack provides dynamic configuration management to facilitate flexible deployment environments for Single Page Applications (SPA). Due to the nature of SPA applications, all environment variables need to be embedded inside the application container at runtime. For example, environment variables might be:

  • VITE_TEST_VARIABLE1
  • VITE_PROD_VARIABLE

Where test and prod represent different environments.

The configuration of Vustack revolves around a few core options that allow for environment-specific behavior and dynamic retrieval of variables.

  • Always ensure that all required environment variables are available at build-time since SPAs require them to be embedded into the container.
  • Custom logic in getVariables allows for advanced configurations like fetching values from APIs or dynamically setting values based on conditions.

This configuration provides the flexibility needed to handle different environments and dynamic variable management for modern SPAs.

Configurable Options

OptionDescriptionDefault ValueExample
envMapMaps navigation URLs to specific environments. Supports regular expressions and expects HOST:PORT format.N/A{'localhost': 'local', 'prod.mysite.com': 'prod'}
variablePrefixDefines the prefix for environment variables based on the tool used (Vite, Webpack, Node, etc.).VITEVite: VITE_TEST_VARIABLE, Webpack: WEBPACK_TEST_VARIABLE, Node: NODE_TEST_VARIABLE
getVariablesA custom function to retrieve environment variables. Supports dynamic variables and external system fetches.N/Ajavascript getVariables: () => ({ VITE_API_URL: process.env.VITE_API_URL })

Example Configuration

Here is an example of how you can configure Vustack for a typical use case:

const vustackConfig = {
  ...
  envMap: {
    'localhost': 'local',
    'dev.mysite.com': 'dev',
    'prod.mysite.com': 'production',
  },
  variablePrefix: 'VITE',
  getVariables: () => {
    return {
      VITE_LOCAL_URL: "localhost/api",
      VITE_DEV_URL: "web.server/api",
    };
  }
};

In this example:

  • The envMap maps different URLs to specific environments.
  • The variablePrefix is set to VITE, which would prefix all environment variables.
  • The getVariables function retrieves the environment variables dynamically using process.env.