pro-web
v18.9.3
Published
A web-based version of ITrack Pro
Downloads
73
Readme
Pro Web
A modern web-based version of ITrack Pro.
Moved from SVN to GitHub at SVN revision 32416
Getting started for development
- clone repo
- make sure you have node version 20+ installed
- make sure you are logged into an npm account(
npm login
) that has access to the @isoftdata npm organization. If you don't have access, ask another ISoft developer for an invite. - Run
npm i
in the clonedpro-web
directory - create a
config.json
file (seeconfig.template.json
) - build the server with
npm run build-server-watch
- start the server for dev by running
npm run startdev
. This will also build and serve the client.- By default, this will look for a
config.json
file. If you want to user another file, runnpm run startdev <theFileName>
- By default, this will look for a
- open your browser to localhost on the port specified in the config.json file's
webport
property.
Instead of running
build-server-watch
andstartdev
manually, you can run the "Server: Dev" debug configuration
Yup Schema Validation
Yup is used for schema validation, custom methods have been added to make handling dates and other data types easier. To access these on the server, you should require tools/yup-helper
instead of yup
. This will give you access to all the features of yup, plus the added custom methods, which are detailed below.
yup.mixed().dateNowOnInsert(primaryKeyName)
If the named primary key is truthy (i.e., when inserting a new row), it will strip off this property. Otherwise (i.e. updating an existing row), it will replace the property's value with the current date and time according to the database. This will also work fine if you already pass db.NOW
on the property, since it matches the shape enforced by this function.
yup.mixed().dateNow()
Replaces the current value with the current date and time according to the database.
yup.boolean().enumBool()
Coerces a string ('True'
or 'False'
), native JS boolean, or other value(truthyness test) to a string with the value of either "True" or "False".
yup.number().precision(integer)
Evaluates whether the current value has at most the specified number of digits.
yup.string().ensureValidIsoDate()
Evaluates whether the current value is a valid string representation of an ISO date
yup.string().isValidJSON()
Evaluates whether the current value is valid JSON by parsing it.
printValueAndType
Prints the value and type of the current value without mutating it. Used for debugging.
Error logging and handling
Logging errors in mediator requests
Whenever you make a mediator request to emitToServer
or noAuthEmitToServer
, any errors thrown by the server will implicitly be caught, logged, and an alert will be shown to the user. If you want to override the default behavior, you can optionally pass a third parameter in your mediator request, an object with the properties shown below.
logOptions properties
Property | Type | Description | Default
---- | ---- | ----------- | ----
message | string | The message that will be shown to the user. If truthy, is used instead of the default, unless the error is a Yup ValidationError
| Depends on the error
context | any | Anything you want logged alongside the error to give more context, such as a state or endpoint name. | ''
doNotAlert | boolean | If truthy, the user will not be alerted to the error, but it will still be logged. Useful for if you show errors to the user some other way. | false |
Example
const auth = await mediator.call('noAuthEmitToServer', 'authenticate', {
userName,
passphrase,
storeId,
}, { doNotAlert: true, message: '', context: 'login' })
Logging errors elsewhere in client code
If you want to log errors outside of mediator requests, you can do so with the logAndAlert
function, which is included in the context
object passed to every state.
Function arguments
Argument | Type | Description | Default
---- | ---- | ----------- | ----
err | Error | A JS error. If absent, nothing will be logged or alerted. | undefined
mediator | Object | The mediator. Used to call showMessage
to show alerts. If absent, uses vanilla JS alerts. | undefined
message | string | The message that will be shown to the user and logged with the error. If truthy, is used instead of the default, unless the error is a Yup ValidationError
| Depends on the error
context | any | Anything you want logged alongside the error to give more context, such as a state or endpoint name. | ''
showMessageOptions | Object | Any options you want to pass to showMessage
. If this is explicitly false, the alert will not be shown. | {}
Example
try {
// Something that can throw an error
} catch (err) {
logAndAlert(
err,
mediator,
'This will be shown to the user and logged with the error. It should be a string',
'This will be logged alongside the error. It can be of any type.',
{
type: 'danger', // Bootstrap alert class
time: 3000, // Milliseconds before the alert dismisses itself
dismissable: true // Whether to allow the user to dismiss the alert
})
}
Retrieving the error log
The error log is stored in the localStorage variable errorLog
. You can view it from the web browser's console. At the top level, it is an object whose keys are the userAccountId
of the logged in user when the error was logged. Each of these properties is an array of objects, representing any errors that were logged, sorted by age, newest first. Only 100 logs will be stored per user, then the oldest will be removed whenever a new error is inserted.
There is also a function, getErrorLog
, that retrieves this object from localStorage.
Reporting/Charting
Pro web has a set of three database tables and views where reports, charts, and their associations are defined: wa_dashboard_report
, wa_dashboard_chart
, and wa_dashboard_report_chart
. Reports are a collection of various charts. Reports have parameters and charts can use said parameters. Currently Charts are rendered using Google Charts.
Defining a Report
Inside of Pro web, reports can be created on the Configuration > Dashboard screen. This includes the report name, the charts contained within it, who it is shared with, and the default value of any parameters. Currently it is not possible to add or remove parameters for reports within Pro web, because all charts require the date range parameter, and support no others.
Report Database Row - wa_dashboard_report
Property | Type | Description
---- | ---- | -----------
dashboard_report_id | Unsigned integer
| Required - Primary key. Auto incremented.
report_name | String
| Required - a unique name for the report.
report_title | String
| When rendered, this title will be displayed at the top of the card. If omitted, name
will be used.
json | Text
| Parsed into JSON on the server, this field contains JSON for an array of parameter objects, the format of which is detailed below.
share_type | Enum
| Controls access to reports within Pro web. Possible values include: everyone
, group
, store
, and user
. Defaults to everyone
.
share_id | Unsigned integer
| Used in conjunction with share_type
to control access to reports. When share_type
is 'everyone', this field is null. Otherwise, it contains the id of the user, group, or store to share the report with. Defaults to NULL
.
owner_id | Unsigned integer
| The user_account_id
of the user who created the report within Pro web. This user will always have access to the given report, regardless of its sharing settings, and will be shown as the report owner on the configuration screen. Defaults to NULL
, which designates it as a default report.
Parameter Object
Property | Type | Description
---- | ---- | -----------
name | String
| Required - a unique name for the parameter. This name is also used to reference param in a query.
title | String
| This is used to label the parameter for the user.
type | String
| Can be one of dateRange
, date
, or selection
. See the tables below for parameter-type-specific properties
dateRange
Type Properties
In the UI, the user will see a dropdown with the possible date range values(see
default
description below).
Property | Type | Description
---- | ---- | -----------
default | String
| One of the following values: 'Today'
, 'Yesterday'
, 'Last 7 Days'
, 'Last 30 Days'
, 'Last 90 Days'
, 'Last 365 Days'
, 'This Week'
, 'This Month'
, 'This Quarter'
, 'This Year'
, 'Previous Week'
, 'Previous Month'
, 'Previous Quarter'
, or 'Previous Year'
. If the default
property is omitted or falsy, 'Last 30 Days'
will be used.
date
Type Properties
In the UI, the user will see a dropdown with a date picker.
Property | Type | Description
---- | ---- | -----------
default | String
| Can be an ISO 8601 date string(eg. '2021-01-13'
). If the default
property is omitted or falsy, the today's date will be used.
selection
Type properties
In the UI, the user will see a dropdown with the
optionList
values(if any) and the values returned from theoptionListQuery
(if any).
Property | Type | Description
---- | ---- | -----------
default | String
| The id
of the option you'd like to be selected by default
optionList | Object
| Each object should have an id
, and name
. id
is the value that will be given to you at query time and name
is what will be displayed in the dropdown to the user.
optionListQuery | String
| A query that selects 2 columns id
and name
. The results of this query will be merged with optionList
and put in the dropdown for the user.
Example
'dashboard_report_id' | 'report_name' | 'report_title' | 'json' | 'share_type' | 'share_id' | 'owner_id'
-- | ---- | ---- | ------- | -- | -- | --
1 | report_overview | Overview | {"parameters": [{"name": "date_range", "type": "dateRange", "title": "Date Range", "default": "This Year"}]}
| everyone | NULL
| NULL
2 | shared_report | Shared Report | {"parameters":[{"name":"date_range","type":"dateRange","title":"Date Range","default":"This Month"}]}
| user | 1 | 2
Defining a Chart
Currently, charts cannot be defined within Pro web, and must be created in the database view wa_dashboard_chart
. Currently, 19 charts are defined, but some are set to not show as options in the user interface.
Chart Database Row - wa_dashboard_chart
Property | Type | Description
---- | ---- | -----------
chart_id | Unsigned integer
| Required - primary key. Auto incremented.
chart_name | String
| Required - a unique name for the chart
chart_title | String
| When rendered, this title will be displayed at the top of the card. If omitted, name
will be used.
supertype | Enum
| Required - designates how the chart should be loaded. Options include google
, table
, and embed
. Defaults to google
.
json | Text
| Parsed to JSON on the server. Contains several properties: query
(string, required), chartWrapper
(object, required for Google charts), multiSeries
(object, required for multi-series charts), formatting
(object).
show_chart | Bit
| Required - whether or not to show a chart in the UI. Defaults to 1
.
MultiSeries Object
Property | Type | Description
---- | ---- | -----------
groupXAxisBy | String
| Required - The name of the query column that determines the X axis of the chart.
series | String
| Required - The name of the query column that determines which series a query row corresponds to.
value | String
| Required - The namem of the query column that contains the value for that data point.
tooltip | String
| The name of the (optional) query column that contains a custom plaintext tooltip, which replaces the default Google Charts tooltip. Does not work for Tree Map type charts, which have special tooltip requirements.
Formatting Object
An object whose property names are the columns in the query to be formatted. Currently only currency formatting is supported.
Property | Type | Description
---- | ---- | ---------
type | String
| The name of a Google Charts Formatter.
format | String
| The name of a formatter template, defined in charts.json
.
JSON Example
{
"chartWrapper": {
"chartType": "AreaChart",
"options": {
"isStacked": true,
"width": 1000,
"height": 1000
}
},
"multiSeries": {
"groupXAxisBy": "Date",
"series": "Part Type",
"value": "Sales",
"tooltip": "Tooltip"
},
"formatting": {
"Sales": {
"type": "NumberFormat",
"format": "CURRENCY"
}
},
"query": "SELECT t.date AS `Date`,\r\n IFNULL (t.part_type, 'Misc. Lineitems') AS `Part Type`,\r\n ROUND(@running_total:=@running_total + t.sales, 2) AS `Sales`\r\nFROM\r\n(SELECT \r\n`wa_sale`.`document_date` AS `Date`,\r\nIF(wa_sale_line.part_type = '', 'Misc. Lineitems', wa_sale_line.part_type) AS `part_type`,\r\nFORMAT(SUM(wa_sale_line.quantity * `wa_sale_line`.`price`), 2) AS `sales`\r\nFROM \r\n`wa_sale_line`\r\nINNER JOIN `wa_sale` USING(`sale_id`)\r\nWHERE\r\n`wa_sale`.`status` = 'Invoice' AND wa_sale.document_date IS NOT NULL\r\n GROUP BY \r\n `wa_sale`.`document_date`, `wa_sale_line`.`part_type`) t\r\n JOIN (SELECT @running_total:=0) r\r\n ORDER BY t.Date;"
}
Adding charts to reports
Adding charts to reports is handled entirely in the interface of Pro web, on the Configuration > Dashboard screen. Each row in the database view wa_dashboard_report_chart
defines the association of one chart to one report, the rank of the chart within the report, and any JSON to apply to the chart when displayed in that report.
Report Chart Database Row - wa_dashboard_report_chart
Property | Type | Description
---- | ---- | --------
report_chart_id | Unsigned integer
| Required - Primary key. Auto incremented.
dashboard_report_id | Unsigned integer
| Required - Foreign key constraint with wa_dashboard_report.dashboard_report_id
.
chart_id | Unsigned integer
| Required - Foreign key constraint with wa_dashboard_chart.dashboad_chart_id
. chart_id
and dashboard_report_id
must be a unique pair.
rank | Unsigned integer
| The order to display the chart in on the report. Defaults to 1.
json_override | Text
| Parsed as JSON on the server. Contains any JSON properties to be applied to the chart for the given report, overriding any of the same property on the base chart. Primarily used for chartWarpper options. Default NULL
.