- Fixed the paging number.
- Node.js v20 compatibility.
- Mongoose v8 compatibility.
- MongoDB v7 compatibility.
- Fixed document array errors when viewing model versions.
- Added the ability to change the location of certain scripts and styles.
- Navigation items are now sorted alphabetically.
- Fixed the nav sidebar from preventing scrolling in some instances.
- Fixed default exports not appearing in the selected order.
- Added the ability to customise the linz authentication strategy through
successful
andfailed
properties. These should be functions that accept the following propertieserr
,failureFlash
,failureRedirect
,info
,next
,req
,res
,successFlash
,successRedirect
anduser
.
- Fixed missing dataAttributes causing pages to error.
- Fixed exports with a space in the name.
- Added prettier.
- Replaced readthedocs with Docusaurus.
- Fixed binddata not recording date picker changes.
- Fixed opening a documentArray with a datepicker resetting other date pickers on the main page to the current date.
- Fixed multiple
linzTimezoneOffset
attributes. - Fixed incorrect datepicker dates across multiple timezones.
- Fixed ckeditor double escaping values.
- Fixed a XSS vulnerability with the
checkboxesWithAddition
widget.
- Added the ability to define a custom
admin forgot password path
.
- Fixed UI bug preventing export buttons from showing up on smaller devices.
- Fixed an export issue when using filters.
- Added protection to help mitigate XSS attacks.
- Added protection to help mitigate mass assignment attacks.
- Added an API to escape data before rendering.
- Updated formist to the latest version.
- Updated export to support new inclusions property.
- Deprecated the export exclusions property in favour of the inclusions property.
- Improved development environment.
- Improved client side CSRF code.
- Fixed a validation issue when a form has a remote validator.
- Added a new api
linz.api.formtools.list.getFilters(req)
to get the current list view filters from a post request.
- Fixed a bug preventing invalid date fields from being validated.
- Fixed group actions on the list view.
- Added support for
modal
form to custom exports.
- Stopped empty date fields getting today's date automatically applied.
- Added the ability to split object fields over multiple columns in the default export.
- Made the export api more generic so you can pass in any stream instead of a query.
- Fixed the transform function to pass the correct parameters.
- Fixed listQuery not being applied in the exports.
- Fixed single field and record exports not showing up correctly.
- Fixed concurrency plugin.
- Added
session options
default object passed toexpress-session
middleware. - Added
cookie options
default object passed tocookie-parser
andexpress-session
middleware. - The
linzReturnUrl
cookie is now signed by default. - Through the above, updated Linz's default cookie settings to be more inline with OWASP recommendations.
- The example app demonstrates how to extend the default session options.
- Removed the X-Powered-By header.
- Added the X-XSS-Protection header.
- Linz's error handling middleware will now add the error to
req
. - Linz's error handling middleware can now return errors via JSON.
- Updated error handling for JSON errors.
- Added
linz.api.error
functions. - Added routes to the example app to generate errors for testing purposes.
- Updated documentation.
- Made the modal selector more generic so it also works with custom modals.
- Made it much harder to post a form before the CSRF token is added.
- Added new dataAttributes, nomodule, nonce, and referrerpolicy properties to scripts.
- Added new dataAttributes to styles.
- Development app now starts using
start
instead ofdev
.
- The default record delete button now uses a post request.
- Added csrf protection across all routes. For custom forms, the user will need to add
csrfToken: req.csrfToken()
to the options when usinglinz.api.model.generateFormString()
. - Csrf protection can be customised by setting the linz option
csrf options
. This takes an object with the same options listed here https://www.npmjs.com/package/csurf. - Fixed not being able to return html in an overview section.
- Export fields are no longer required to be in the formDSL.
app
now has it's ownpackage.json
with linz as a file-based dependency.app
dependencies have now been removed from Linz'spackage.json
devDependencies
.- A dev-only Dockerfile (
Dockerfile.dev
) has now been created for development purposes. Dockerfile
is now purely focused on building Linz, not running an app using Linz.- You can now run
yarn dev
andyarn test
at the same time.
Rereleased v1.0.0-17.1.0 as v1.0.0-17.1.1.
- Added the ability to transform individual export values.
form[field].transpose.export => (val) => Promise.resolve(val)
. This function must return a promise. - Deprecated the transpose function in favour of the context one.
transpose: (val) => ...
should now betranspose: { form: (val) => ... }
. - Updated the modelExport route to
transpose
fields if atranspose
ortranspose.export
function is provided in the formDSL. This allows you to completely customise exported fields before displaying them in the exported file. - Custom export routes can now take advantage of
linz.api.util.generateExport()
to fully customise what kind of file is generated. For example you can generate.xls
and.csv
files and customise the content. - Added the ability to provide a custom default renderer for the versions plugin.
- Replaced
linz.publicMiddleware.namespace
withlinz.api.middleware.setLinzNamespace()
. - Moved all public middleware to the
linz.api.middleware
namespace. - Removed the datetime and datetimelocal field types, the date type should be used instead.
- Added the ability to create a custom form based on the model schema via
linz.api.model.generateForm()
andlinz.api.model.generateFormString()
. - Added the ability to define custom fields in the form DSL. When specifying a custom field you should add a
type
property if you want an input other thantext
. - Add the ability to edit
public
andviews
files without restarting the node process. - Added persistent storage to the local development environment.
- Added new formtool apis
namespaceForm
,namespaceList
,namespaceOverview
,parseForm
. - Added new middleware apis
setLinzNamespace
,setModelForm
,setRecord
. - Added the ability to provide custom scripts and styles to linz.api.views.render using
data.scripts
anddata.styles
. - Added the ability to manually set a timezone offset using
data-utc-offset
in the date widget. This must be in the ISO offset format and begin with a plus (+) or minus (-) symbol with the hours and minutes having a leading 0 eg+00:00
- Added the ability to provide helpText to a document array field.
- Turned off autocomplete for some widgets.
- Fixed the datepicker in documentarray modals.
- Fixed the datetimepicker on documentarray fields.
- Fixed model version compare forms being undefined.
- Added support for primary record actions with a modal on the model index.
- Added a new default
routes
, which allows you to define middleware to be executed during the processing of a Linz route.
- Updated the reference renderer to link to the record overview.
- Added a new
Linz.initModels
method to allow initialising manually set models viaLinz.set('models', {})
.
- Linz will now default labels for all schema fields, using sentence case.
- Removed response-time middleware that was causing issues with the builds.
- Added support for customising the login and logout paths.
login path
andlogout path
defaults must be set whenadmin path
has been customised. - Merged in the Linz minitwitter basic repo to simplify testing.
- Fixed a rare case where an empty database with configs would cause an
Unable to write config file %s to database. E11000 duplicate key error
error. - Fixed an issue where Linz would try to
.toString()
null values while exporting.
- Re-release of v1.0.0-15.2.0 to include updated changelog.
- You can now supply a
defaultOrder
forsortBy
property of the List DSL. - Ascending/descending options are directly listed in the sorting dropdown for each field in the
sortBy
array. - When the model index can't find any records for the current query, the model index now shows the words "No records found", and removes sorting and paging controls.
- Fix handlebars vulnerability.
- Added codecov support.
- Fixed filtering using date ranges.
- Added missing
namespaceForm
middleware to certain routes. - Better handling of errors in
modelSave
middleware. - Rewrote
modelSave
route removing usage of Async.
- Added support for a
content
property when supplyingscripts
andstyles
defaults. Supplyingcontent
for a script will ensure the content is placed within two script tags (i.e.<script>{{{content}}}</script>
). Supplyingcontent
for a style will ensure the content is placed within two style tags (as opposed to using a link tag) (i.e.<style>{{{content}}}</style>
). - Added the
linz.formtools.cellRenderers.email
renderer to render an email in ana
with themailto:
protocol. - Added the
linz.formtools.cellRenderers.tel
renderer to render a telephone number in ana
with thetel:
protocol. - Cleaned up the print preview styles.
- Fixed the
linz.addLoadEvent
method so the onload process doesn't get overridden. - Added a new
linz.api.session.getTimezone(req)
function that allows you to get the timezone offset of the current user. - Added the ability to transform date fields in the Linz export through
useLocalTime
which converts the time to the local browser time. - Added a
dateFormat
option which adds the ability to export the date in a different format (Uses moment datetime formats). - Upgraded to Mongoose
v4.13.12
. - Migrated unit tests from Mocha to Jest.
- The
linz.formtools.widgets.date
andlinz.formtools.widgets.dateRange
are functions which must be executed. Previously you could simply reference them. However, you can pass in a date format which will be used to customise the display of the date in the UI.
- Added the ability to set some help text which will appear in a Bootstrap popover, on a model list view.
- Fixed a race condition where
req.linz.model.linz.formtools.form
would be undefined. - Fixed Linz not being able to find labels for embedded documents.
- Fixed ckeditor for non
/admin
admin paths. - Fixed scoping of the multiselect within a documentarray.
- Update the default for the
linz.formtools.widgets.documents
widget create button to beCreate
, and made it configurable by passing inbuttonLabel: 'New label'
to the widget. - Reworked some Linz internals to allow code using
linz.api.views.render
to take advantage of Linz's Notifications API. Also moved the render notifications functionality into thelinz.api.views
namespace and updated all code that rendered notifications to use this API function. - Moved Linz's
namespace
middleware intomiddleware-public
so that it can be accessed in other applications usinglinz.middleware.namespace
. - Moved Linz's
notifications
middleware intomiddleware-public
so that it can be accessed in other applications usinglinz.middleware.notifications
. - Add a 404 page for all Linz record routes. You can customise this page by setting the linz option
404
to a function that returns a Promise. This function will be passed thereq
object. - Everything that uses
linz.formtools.widgets.date
now uses the Bootstrap DateTime Picker UI client-side. - Everything that uses
linz.formtools.filters.date
orlinz.formtools.filters.dateRange
now uses the Bootstrap DateTime Picker UI client-side. - Widgets can supply a
transform
function, on the returned widget function, which will be executed when saving data. This provides the ability for a widget to transform values in the form, before saving to the database.
- When rendering the overview, Linz will no longer infer the cell renderer type from the Form DSL type data. If Linz isn't rendering the overview cell with the correct cell renderer, you should supply the renderer (i.e.
{ label: 'x', renderer: linz.formtools.cellRenderers.text }
). - When supplying a function for the config form, model list, form and overview DSLs, you no longer get passed
user
, but insteadreq
(which obviously has user atreq.user
).
- Fixes
#169
, an issue in which the actions column wouldn't render when permissions weren't explicitly set. - Improved the Express param for model. It no longer process list, overview or form DSL. These are now only processed when required. Improving the efficiency of any route that used
:model
. - When supplying functions for config form, model list, form and overview DSLs, you now get
req
rather than justuser
. This provides much more flexibility in what you return, as now it can be based on the record being rendered, not just the user making the request.
- Fixes issues on the model list in IE, due to use of the template tag.
- Fixed a problem with model lists, showing the wrong number of records. This could occur when a
listQuery
static was employed and have an impact on the number of results being returned. - Improves usage of the
.reponsive-table
class. Still not perfect, but definitely useable. - You can now add
type='primary'
to a record action to have it rendered inline (i.e. not within the dropdown) with the edit and delete buttons on a model list. - You can now add
type=primary
to an overview action to have it rendered inline (i.e. not within the actions dropdown).
linz.api.views.render
now requiresdata, req, res
.callback
is optional.- The
listQuery
static is now passedreq, query, callback
(additional parameter isreq
). - When using modal actions, your HTML now has to supply the
<div class="modal-dialog"><div class="modal-content"></div></div>
tags.
- Now that the
listQuery
static is passedreq
, you have more information (such asreq.user
) which can be used to alter the query that Linz will execute. - Fixes a long term (development only) issue
TypeError: filteredNavigation.forEach is not a function
. utils.js
has been move back into the head. Client-side scripts can now make use oflinz.loadScript
andlinz.addLoadEvent
once again.- Added a new default
mongoose options
which can be used to control the options passed to Mongoose when making a connection. Provides support for Mongoose4.11.x
in which the default connection logic has been removed. - By allowing the results of record/overview actions to return the
.modal-dialog
div, you have more flexibility on the size of the modal (i.e.<div class="modal-dialog modal-lg">
renders a large modal). - Removed
.modal-dialog .modal-content
from the modal divs inlayout.pug
. They should now be included in the HTML returned from any record/overview actions that specify the use of a modal. - You can now use
req.flash('linz-notification', linz.api.views.notification({ text: 'Hi' }))
to have Linz show a notification for you on redirect. - You can now use
req.linz.notifications.push(linz.api.views.notification({ text: 'Hi' }))
to have Linz show a notification for you. - Notifications are now shown in models list, model create, model list, record edit and record overview pages.
- All
filters
must now return HTML from therenderer
function, wrapped in<template>
tags. - All models must either have a
title
field, or supplymodel.title
with the value of the schema field that should be used as the title. - The
title
virtual, when creating, will no longer uselabel
,name
orthis.toString()
to return a label. It will only ever usetoLabel
method if provided, or the value of the title property.
- Add
data-linz-view
to Model create and list, and record edit and overview pages. This gives CSS hooks to target CSS to certain views. - Added a new search button on the model list that always lives next to the Add filter button. This replaces the Filter now button that used to only be exposed when there were filters.
- The Add filter and Search buttons are now disabled once the form has been submitted.
- The new
list.search
defaults to['title']
and will always be on unless you setlist.search
tofalse
. - A models title field, is always in the standard list query.
- A model is now sorted by
dateModifed
in descending order by default.
- All
canDelete
andcanEdit
functions now pass through the request object and call the callbackcanDelete(req, callback)
. This allows you to disable records on the index view based on the current logged in user.
- Add the ability to set an
alwaysOn
property for filters. This should be a boolean and will hide the close button and automatically show the filter. - Add the ability to provide a
default
value foralwaysOn
filters. - Add the ability to remove the filter from the dropdown and hide the close button using
once: true
. - Fixed the multi-select filter, when using numbers as the value.
- Integrated the static
getQuery
into the model export process. - Pagination is now always present.
- Fixed buttons that show content in a modal, on slower connections.
- Fixed typo in password placeholder text.
- Updated the model export, field selection cookie, to be user specific.
- Fixed issues with datePicker code on the client-side.
- Fixed embedded document overview cell renderer.
- Deprecated
adminJSFile
andadminCSSFile
defaults. Please usescripts
andstyles
instead.
- Add
navigationTransform
property to the Linz initialisation options. This is a function that accepts a navigation and data object parameter(nav, { user })
and allows customisation of the main navigation menu with additional contexts not available at initialisation. - Add
customAttributes
property to the Linz initialisation options. This is a function that accepts areq
object that has gone through all the Linz middleware. i.e. the user is available at this point. - Allow custom scripts and styles through the
scripts
andstyles
Linz options. These should be functions that takereq
andres
objects and return a promise that resolves with an array of scripts and styles. The array should contain objects with the same properties as the HTML equivalents. - Now passing
form
anduser
totransform
function. - Now passing
record
totranspose
function. - Expose
linz.api.views.getScripts
andlinz.api.views.getStyles
api. - Added ability to provide Linz with custom navigation via setting
linz.set('navigation', navigation);
. - Added ability to display icons (html) in custom navigations by adding an icon property
icon: '<i class="fa fa-home" aria-hidden="true"></i>'
.
- Add
.linz
class to the Linz navbar.
- Fixes an issue with the grid renderer not showing default record actions (edit and delete).
- Fixes an issue with the pre-save middleware (when
req
doesn't exist).
- Fixed a bug when trying to wrap the list DSL with a
(user, callback)
function. - Fixed the List DSL to support renderers that return HTML.
- Created record action renderers, which can be used in conjunction with a custom List renderer.
- All modal containers now contain the
div.modal-dialog > div.modal-content
structure. - Record actions now support
modal: true
to have the URL content displayed within a modal. - Fixed issue in which action URLs are sometimes updated twice and then no longer function correctly.
- Rather than supplying Mongoose, Express, Passport and an options object as arguments to Linz's init function (in any order), Linz now expects an object. The object can have
mongoose
,express
,passport
andoptions
keys as required. - Added ability to customise the homepage route by setting
admin home
in theoptions
object or usinglinz.set('admin home', '/new/path')
. - Added the ability to render a view in the context of Linz.
- The
list.showSummary
boolean now excludes record count and sorting if set tofalse
. - The list render data now contains the query parameters.
- Linz filters that render will no longer get stuck.
- Linz can now show alerts (model list view) to the user by pushing objects (formatted via
linz.api.views.notification
) into thereq.linz.notifications
array. Uses the Noty library.
- Search and replaced
Grid
withList
. You will need to update all your models to uselist
rather thangrid
now. - Search and replaced
Columns
withFields
. You will need to update all your models to usefields
rather thancolumns
now. - Inline with the above, rename any
gridQuery
statics tolistQuery
.
- The List DSL now includes a
renderer
property. currently available renderers includelinz.formtools.listRenderers.default
(alias forgrid
),linz.formtools.listRenderers.grid
, andlinz.formtools.listRenderers.list
. - If a
listRenderer
has not been set, the defaultlinz.formtools.listRenderers.grid
will be used.
-
When Linz retrieves data for the list view, it no longer retrieves all fields from the database. It retrieves only fields found in
grid.columns
. This means, yourtoLabel
and other Mongoose related functionality may not get a complete model record. You can create a static calledgridQuery
which Linz will execute if found, to customise the query that will be executed by Linz. -
The
findForReference
static that Linz will execute if found, must now accept either oneid
or an array ofid
s. This is to supportref
field optimisations.
Focus on this release was optimization of the list view. Making it much more performant.
- Model counts are now using
model.count
rather than the results of amodel.find
. - Record counts are now using
model.count
rather than the results of amodel.find
. - Cell renderers for
ref
fields are now provided the value of the reference, not just the ObjectID. This is to reduce the number of necessary requests to the database. Cell renderers forref
fields should no longer need to do this now, because the data is provided to them. - Previously Linz only supported the type
linz.mongoose.Schema.Types.ObjectId
forref
fields. It now supportslinz.mongoose.Schema.Types.Mixed
and can successfully handle ObjectIds, strings andundefined
values. - Linz is now automatically indexing fields which are used in
grid.sortBy
andgrid.filters
to ensure a basic level of indexing support. It also indexesdateModified
anddateCreated
by default. - Field names included in
model.find
are now sorted alphabetically for the list view query to make it easier to formulate compound index strategies. You can be guaranteed field names will always appear in alphabetical order. - You can create a static called
gridQuery
which if found, will be executed by Linz. Linz will provide the function the query it is about to run for the list view, so that you have an opportunity to customise it as required. - Only fields found in
grid.column
are included in themodel.find
for the list view query.
- Updated
lib.api.url.getAdminPasswordResetLink
to accept anid
andhash
. If included, it will add those to the URL it returns.
- Linz's Mongoose document plugin no longer recognises the
fields
property (and nestedusePublishingDate
andusePublishingStatus
properties) from theoptions
object. - A
publishingDate
property is no longer added to your models. - A
status
property is no longer added to your models.
- Linz's Mongoose document plugin will now automatically update the
labels
property from theoptions
object with a label for the mandatory propertiesdateCreated
anddateModified
, unless otherwise provided.