@sintradigital/vustack v1.0.2
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:
Parameter | Description |
---|---|
title | Represents the main label of the menu item. |
subtitle | Represents a descriptive subtitle. |
icon | Specifies the icon in MDI format, such as mdi-information , mdi-account . |
enabled | Indicates whether the route should be included in the menu. |
order | Specifies 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
Component | Pagination | Editing | Filters |
---|---|---|---|
List View | Yes | To be tested | To be implemented |
Data Table | Yes | To be tested | Yes |
Record View Components
Component | Status |
---|---|
JsonFormCommonEditor | To be completed and integrated with the list components |
PropertyView | To be tested and integrated with the list components |
Data Adapters
Vuestack includes several data adapters for fetching data:
Data Adapter | Description |
---|---|
baseDataSource | Implements fake methods for data access. |
restDataSource | Implements the standard REST protocol, allowing the developer to define the necessary code for HTTP requests. |
apiStackDataSource | Implements 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
Parameter | Description |
---|---|
itemsPerPage | Number of items displayed per page by default. |
enabled | Pagination for the data grid cannot be disabled. |
Editing
Parameter | Description |
---|---|
enabled | If true , enables data editing (insert and update). |
component | Specifies the component to use for the entry/edit form. This can be any registered component or a path for dynamic loading. |
options | Properties that will be passed to the component. |
delete
Parameter | Description |
---|---|
enabled | If true , enables data deletion. |
component | Specifies the component to use for the entry/edit form. This can be any registered component or a path for dynamic loading. |
options | Properties that will be passed to the component. |
view
Parameter | Description |
---|---|
enabled | If true , enables data view. |
component | Specifies the component to use for the entry/edit form. This can be any registered component or a path for dynamic loading. |
options | Properties that will be passed to the component. |
Filters
Parameter | Description |
---|---|
enabled | If true , enables search filters. |
component | Specifies the component to use for the filters form. This can be any registered component or a path for dynamic loading. |
options | Properties 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:
Parameter | Description |
---|---|
sorted | true if the column is pre sortered |
asc | contains 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
Parameter | Description |
---|---|
key | it is the concatenation of type (item or header ) and the key of the column (eg. header.id oritem.id ) |
component | if 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 |
render | it is a javascript snippet with no return statement. the scope contains item,index, column, value when available. eg. value+'fdsfsf'+item.field |
text | contains 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:
Parameter | Description | Values |
---|---|---|
key | The name of the field | Any column field name |
order | The sorting direction | asc (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
- JSON Schema:
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
Method | Description |
---|---|
getPagedData | Returns a paginated list of data. |
getItem | Returns a single item based on the id . If the force parameter is false , it retrieves the item from local cache if available. |
insert | Provides functionality to insert new data. |
update | Provides functionality to update existing data. |
deleteItem | Provides functionality to delete data. |
Hooks by Implementation
restDataSource
Hook | Description |
---|---|
createListRequest | Creates a request for listing data. |
createInsertRequest | Creates a request for inserting data. |
createUpsertRequest | Creates a request for updating or inserting data (upsert). |
unpackGetListRequest | Unpacks the request for listing data. |
unpackGetRequest | Unpacks the request for retrieving a single item. |
unpackUpsertResponse | Unpacks the response from an upsert request. |
ApiStack
Variable | Description |
---|---|
Entity Name | The name of the entity being managed. |
URL | The 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:
Property | Description |
---|---|
componentName | Can be either the name of a loaded component or a dynamic path. |
options | Properties 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
Option | Description | Default Value | Example |
---|---|---|---|
envMap | Maps navigation URLs to specific environments. Supports regular expressions and expects HOST:PORT format. | N/A | {'localhost': 'local', 'prod.mysite.com': 'prod'} |
variablePrefix | Defines the prefix for environment variables based on the tool used (Vite, Webpack, Node, etc.). | VITE | Vite: VITE_TEST_VARIABLE , Webpack: WEBPACK_TEST_VARIABLE , Node: NODE_TEST_VARIABLE |
getVariables | A custom function to retrieve environment variables. Supports dynamic variables and external system fetches. | N/A | javascript 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 toVITE
, which would prefix all environment variables. - The
getVariables
function retrieves the environment variables dynamically usingprocess.env
.