pict-section-form
Advanced tools
Comparing version 1.0.5 to 1.0.6
@@ -47,3 +47,3 @@ const libPictApplication = require('pict-application'); | ||
onAfterInitialize() | ||
onAfterInitializeAsync(fCallback) | ||
{ | ||
@@ -54,3 +54,7 @@ // Set a custom address for all the views to marshal to. | ||
this.pict.views.PostcardNavigation.render() | ||
this.pict.views.PostcardMainApplication.render(); | ||
this.pict.views.PictFormMetacontroller.render(); | ||
return super.onAfterInitialize(fCallback); | ||
} | ||
@@ -57,0 +61,0 @@ |
@@ -25,14 +25,15 @@ { | ||
"Description": "The content and destination for the postcard you would like to send.", | ||
"Groups": [ | ||
{ | ||
"Name": "Content", | ||
"Hash": "Content", | ||
"Description": "The message and recipient of your postcard." | ||
}, | ||
{ | ||
"Name": "Delivery Destination", | ||
"Hash": "Destination", | ||
"Description": "The message and recipient of your postcard." | ||
} | ||
] | ||
"Groups": | ||
[ | ||
{ | ||
"Name": "Content", | ||
"Hash": "Content", | ||
"Description": "The message and recipient of your postcard." | ||
}, | ||
{ | ||
"Name": "Delivery Destination", | ||
"Hash": "Destination", | ||
"Description": "The message and recipient of your postcard." | ||
} | ||
] | ||
}, | ||
@@ -39,0 +40,0 @@ { |
@@ -26,3 +26,3 @@ const libPictProvider = require('pict-provider'); | ||
return fCallback(); | ||
return super.onInitializeAsync(fCallback); | ||
} | ||
@@ -29,0 +29,0 @@ } |
@@ -7,3 +7,3 @@ { | ||
"RenderOnLoad": false, | ||
"AutoRender": false, | ||
@@ -10,0 +10,0 @@ "Templates": [ |
@@ -7,3 +7,3 @@ { | ||
"RenderOnLoad": false, | ||
"AutoRender": false, | ||
@@ -10,0 +10,0 @@ "Templates": [ |
@@ -10,3 +10,3 @@ const libPictView = require('pict-view'); | ||
RenderOnLoad: true, | ||
AutoRender: true, | ||
@@ -46,2 +46,8 @@ CSS: ".PostcardControls { margin-top: 2em; background-color: #fff5f5; }", | ||
onAfterInitialize() | ||
{ | ||
this.pict.views.PostcardNavigation.render() | ||
return super.onAfterInitialize(); | ||
} | ||
onAfterRender() | ||
@@ -52,2 +58,4 @@ { | ||
this.pict.PictApplication.marshalDataFromAppDataToView(); | ||
return super.onAfterRender(); | ||
//return super.onAfterRenderAsync(fCallback); | ||
} | ||
@@ -54,0 +62,0 @@ } |
@@ -7,3 +7,3 @@ { | ||
"RenderOnLoad": true, | ||
"AutoRender": true, | ||
@@ -10,0 +10,0 @@ "CSS": ".PostcardNavigation { background-color: #fff5f5; }", |
@@ -9,3 +9,3 @@ const libPictSectionForm = require('../../source/Pict-Section-Form.js'); | ||
{ | ||
"Product": "PictDefaultFormsApp", | ||
"Product": "Simple", | ||
"DefaultFormManifest": | ||
@@ -59,3 +59,4 @@ { | ||
"Hash":"Name", | ||
"DataType":"Number" | ||
"DataType":"Number", | ||
"Default": 100 | ||
,"PictForm": { "Section":"Area", "Row":2, "Width":1 } | ||
@@ -67,3 +68,4 @@ }, | ||
"Hash":"Type", | ||
"DataType":"Number" | ||
"DataType":"Number", | ||
"Default": 100 | ||
,"PictForm": { "Section":"Area", "Row":2, "Width":1 } | ||
@@ -81,3 +83,3 @@ }, | ||
{ | ||
"Name":"Area of Width Cubed", | ||
"Name":"Area of Height Cubed", | ||
"Hash":"HeightCubeArea", | ||
@@ -84,0 +86,0 @@ "DataType":"String" |
{ | ||
"name": "pict-section-form", | ||
"version": "1.0.5", | ||
"version": "1.0.6", | ||
"description": "Pict dynamic form sections", | ||
@@ -28,10 +28,10 @@ "main": "source/Pict-Section-Form.js", | ||
"browser-env": "^3.3.0", | ||
"pict": "^1.0.178", | ||
"pict-application": "^1.0.15", | ||
"jquery": "^3.7.1", | ||
"pict": "^1.0.183", | ||
"pict-application": "^1.0.17", | ||
"quackage": "^1.0.29" | ||
}, | ||
"dependencies": { | ||
"informary": "^2.0.21", | ||
"pict-provider": "^1.0.2", | ||
"pict-view": "^1.0.45" | ||
"pict-view": "^1.0.46" | ||
}, | ||
@@ -38,0 +38,0 @@ "mocha": { |
@@ -30,2 +30,4 @@ # PICT Forms Section | ||
A tooltip, hover or other kinds of embedded content/help on an input element. | ||
8. Macro: | ||
A small bit of template that's preprocessed and usable by the template partials. | ||
@@ -32,0 +34,0 @@ |
@@ -61,7 +61,3 @@ const libPictViewClass = require('pict-view'); | ||
// Right now this doesn't work with async templates and is intentionally so | ||
// We don't want heavy loading/lifting in the forms controls; if a use case comes up this can change | ||
this.render(); | ||
return super.onAfterInitialize(fCallback); | ||
return super.onAfterInitializeAsync(fCallback); | ||
} | ||
@@ -71,4 +67,8 @@ | ||
{ | ||
this.regenerateAllFormSectionTemplates(); | ||
this.renderAllFormSections(); | ||
if (this.options.AutoPopulateAfterRender) | ||
{ | ||
this.regenerateAllFormSectionTemplates(); | ||
this.renderAllFormSections(); | ||
this.marshalToView(); | ||
} | ||
@@ -190,8 +190,8 @@ return super.onAfterRender(); | ||
bootstrapPictFormViewsFromManifest(pManifest) | ||
bootstrapPictFormViewsFromManifest(pManifestDescription) | ||
{ | ||
let tmpManifest = pManifest; | ||
let tmpManifestDescription = (typeof(pManifestDescription) === 'object') ? pManifestDescription : false; | ||
let tmpSectionList = []; | ||
if (typeof(tmpManifest) != 'object') | ||
if (typeof(tmpManifestDescription) != 'object') | ||
{ | ||
@@ -203,3 +203,3 @@ // Check and see if there is a DefaultFormManifest in the settings | ||
{ | ||
tmpManifest = this.fable.settings.DefaultFormManifest; | ||
tmpManifestDescription = this.fable.settings.DefaultFormManifest; | ||
} | ||
@@ -213,8 +213,20 @@ else | ||
let tmpManifest = this.fable.instantiateServiceProviderWithoutRegistration('Manifest', tmpManifestDescription); | ||
if (this.options.AutoPopulateDefaultObject) | ||
{ | ||
// Fill out the defaults at the marshal location if it doesn't exist | ||
let tmpMarshalDestinationObject = tmpManifest.getValueAtAddress(this, this.viewMarshalDestination); | ||
if (typeof(tmpMarshalDestinationObject) === 'object') | ||
{ | ||
tmpManifest.populateDefaults(tmpMarshalDestinationObject); | ||
} | ||
} | ||
// Get the list of Explicitly Defined section hashes from the Sections property of the manifest | ||
if (tmpManifest.hasOwnProperty('Sections') && Array.isArray(tmpManifest.Sections)) | ||
if (tmpManifestDescription.hasOwnProperty('Sections') && Array.isArray(tmpManifestDescription.Sections)) | ||
{ | ||
for (let i = 0; i < tmpManifest.Sections.length; i++) | ||
for (let i = 0; i < tmpManifestDescription.Sections.length; i++) | ||
{ | ||
let tmpSectionDefinition = this.getSectionDefinition(tmpManifest.Sections[i]); | ||
let tmpSectionDefinition = this.getSectionDefinition(tmpManifestDescription.Sections[i]); | ||
@@ -228,40 +240,36 @@ if (tmpSectionDefinition) | ||
// Check if there are any implicitly defined section hashes in the manifest descriptors | ||
if (tmpManifest.hasOwnProperty('Descriptors') && typeof(tmpManifest.Descriptors) == 'object') | ||
let tmpImplicitSectionHashes = {}; | ||
let tmpDescriptorKeys = Object.keys(tmpManifest.elementDescriptors); | ||
for (let i = 0; i < tmpDescriptorKeys.length; i++) | ||
{ | ||
let tmpImplicitSectionHashes = {}; | ||
let tmpDescriptor = tmpManifest.elementDescriptors[tmpDescriptorKeys[i]]; | ||
let tmpDescriptorKeys = Object.keys(tmpManifest.Descriptors); | ||
for (let i = 0; i < tmpDescriptorKeys.length; i++) | ||
if ( | ||
// If there is an object in the descriptor | ||
typeof(tmpDescriptor) == 'object' && | ||
// AND it has a PictForm property | ||
tmpDescriptor.hasOwnProperty('PictForm') && | ||
// AND the PictForm property is an object | ||
typeof(tmpDescriptor.PictForm) == 'object' && | ||
// AND the PictForm object has a Section property | ||
tmpDescriptor.PictForm.hasOwnProperty('Section') && | ||
// AND the Section property is a string | ||
typeof(tmpDescriptor.PictForm.Section) == 'string' | ||
) | ||
{ | ||
let tmpDescriptor = tmpManifest.Descriptors[tmpDescriptorKeys[i]]; | ||
if ( | ||
// If there is an obect in the descriptor | ||
typeof(tmpDescriptor) == 'object' && | ||
// AND it has a PictForm property | ||
tmpDescriptor.hasOwnProperty('PictForm') && | ||
// AND the PictForm property is an object | ||
typeof(tmpDescriptor.PictForm) == 'object' && | ||
// AND the PictForm object has a Section property | ||
tmpDescriptor.PictForm.hasOwnProperty('Section') && | ||
// AND the Section property is a string | ||
typeof(tmpDescriptor.PictForm.Section) == 'string' | ||
) | ||
{ | ||
tmpImplicitSectionHashes[tmpDescriptor.PictForm.Section] = true; | ||
} | ||
tmpImplicitSectionHashes[tmpDescriptor.PictForm.Section] = true; | ||
} | ||
} | ||
let tmpImplicitSectionKeys = Object.keys(tmpImplicitSectionHashes); | ||
let tmpImplicitSectionKeys = Object.keys(tmpImplicitSectionHashes); | ||
for (let i = 0; i < tmpImplicitSectionKeys.length; i++) | ||
for (let i = 0; i < tmpImplicitSectionKeys.length; i++) | ||
{ | ||
let tmpExistingSection = tmpSectionList.find((pSection) => { return pSection.Hash == tmpImplicitSectionKeys[i]; }); | ||
if (!tmpExistingSection) | ||
{ | ||
let tmpExistingSection = tmpSectionList.find((pSection) => { return pSection.Hash == tmpImplicitSectionKeys[i]; }); | ||
if (!tmpExistingSection) | ||
{ | ||
tmpSectionList.push(this.getSectionDefinition({Hash: tmpImplicitSectionKeys[i]})); | ||
} | ||
tmpSectionList.push(this.getSectionDefinition({Hash: tmpImplicitSectionKeys[i]})); | ||
} | ||
@@ -285,3 +293,3 @@ } | ||
} | ||
tmpViewConfiguration.Manifests.Section = tmpManifest; | ||
tmpViewConfiguration.Manifests.Section = tmpManifestDescription; | ||
tmpViewConfiguration.AutoMarshalDataOnSolve = this.options.AutoMarshalDataOnSolve; | ||
@@ -296,2 +304,29 @@ this.fable.addView(tmpViewHash, tmpViewConfiguration, require('./Pict-Section-Form-View.js')); | ||
module.exports = PictFormMetacontroller; | ||
module.exports.default_configuration = require('./Pict-Form-Metacontroller-DefaultConfiguration.json'); | ||
module.exports.default_configuration = ( | ||
{ | ||
"AutoRender": true, | ||
"AutoPopulateDefaultObject": true, | ||
"AutoPopulateAfterRender": true, | ||
"DefaultRenderable": "Pict-Forms-Metacontainer", | ||
"DefaultDestinationAddress": "#Pict-Form-Container", | ||
"AutoMarshalDataOnSolve": true, | ||
"MetaTemplateHash": "Pict-Forms-Metatemplate", | ||
"Templates": [ | ||
{ | ||
"Hash": "Pict-Forms-Metatemplate", | ||
"Template": "<!-- Pict-Forms-Metatemplate HAS NOT BEEN GENERATED; call pict.views.PictFormsMetatemplate.generateMetatemplate() to build the containers -->" | ||
} | ||
], | ||
"Renderables": [ | ||
{ | ||
"RenderableHash": "Pict-Forms-Metacontainer", | ||
"TemplateHash": "Pict-Forms-Metatemplate", | ||
"DestinationAddress": "#Pict-Form-Container" | ||
} | ||
] | ||
}); |
@@ -6,2 +6,7 @@ module.exports = ( | ||
"Templates":[ | ||
/* | ||
* | ||
* [ Metacontroller Templates ] | ||
* | ||
*/ | ||
// -Form-Container-Header | ||
@@ -19,5 +24,5 @@ { | ||
Glug glug glug | ||
Glug glug glug Oo... | ||
--> | ||
<div id="Pict-{~D:Context[0].UUID~}-FormContainer~}" class="pict-form">` | ||
<div id="Pict-{~D:Context[0].UUID~}-FormContainer" class="pict-form">` | ||
}, | ||
@@ -30,5 +35,6 @@ | ||
<!-- Pict Form Metacontroller container [{~D:Context[0].UUID~}] --> | ||
<div id="Pict-{~D:Context[0].UUID~}-FormContainer~}" class="pict-form">` | ||
<div id="Pict-{~D:Context[0].UUID~}-FormContainer" class="pict-form">` | ||
}, | ||
// -Form-Container | ||
// This is the DIV each section (view) renders into. | ||
{ | ||
@@ -52,2 +58,7 @@ "HashPostfix": "-Template-Form-Container", | ||
/* | ||
* | ||
* [ Section Wrap Templates ] | ||
* | ||
*/ | ||
// -Form-Template-Wrap-Prefix | ||
@@ -88,2 +99,7 @@ { | ||
/* | ||
* | ||
* [ Group and Row Templates (default) ] | ||
* | ||
*/ | ||
// -Form-Template-Group-Prefix | ||
@@ -95,13 +111,5 @@ { | ||
<h3>Group: {~D:Record.Name~}</h3> | ||
<div> | ||
` | ||
}, | ||
// -Form-Template-Group-Postfix | ||
{ | ||
"HashPostfix": "-Template-Group-Postfix", | ||
"Template": /*HTML*/` | ||
</div> | ||
<!-- Form Template Group Prefix [{~D:Context[0].UUID~}]::[{~D:Context[0].Hash~}] {~D:Record.Hash~}::{~D:Record.Name~} --> | ||
` | ||
}, | ||
// -Form-Template-Row-Prefix | ||
@@ -115,3 +123,3 @@ { | ||
}, | ||
// -Form-Template-Group-Postfix | ||
// -Form-Template-Row-Postfix | ||
{ | ||
@@ -124,3 +132,17 @@ "HashPostfix": "-Template-Row-Postfix", | ||
}, | ||
// -Form-Template-Group-Postfix | ||
{ | ||
"HashPostfix": "-Template-Group-Postfix", | ||
"Template": /*HTML*/` | ||
</div> | ||
<!-- Form Template Group Prefix [{~D:Context[0].UUID~}]::[{~D:Context[0].Hash~}] {~D:Record.Hash~}::{~D:Record.Name~} --> | ||
` | ||
}, | ||
/* | ||
* | ||
* [ Input Templates (Default) ] | ||
* | ||
*/ | ||
// -Form-Template-Input | ||
@@ -130,4 +152,4 @@ { | ||
"Template": /*HTML*/` | ||
<!-- Input {~"D:Record.Hash~} {~D:Record.DataType~} --> | ||
<span style="background-color:#fffdfd;">{~D:Record.Name~}:</span> <input type="text" {~D:Record.PictForm.HTMLInputFullProperties~} value=""> | ||
<!-- DEFAULT Input {~"D:Record.Hash~} {~D:Record.DataType~} --> | ||
<span>{~D:Record.Name~}:</span> <input type="text" {~D:Record.Macro.InputFullProperties~} value=""> | ||
` | ||
@@ -140,3 +162,3 @@ }, | ||
<!-- DataType Number {~D:Record.Hash~} {~D:Record.DataType~} --> | ||
<span>{~D:Record.Name~}:</span> <input type="text" {~D:Record.PictForm.HTMLInputFullProperties~} value=""> | ||
<span>{~D:Record.Name~}:</span> <input type="text" {~D:Record.Macro.InputFullProperties~} value=""> | ||
` | ||
@@ -149,3 +171,3 @@ }, | ||
<!-- DataType Number {~D:Record.Hash~} {~D:Record.DataType~} --> | ||
<span>{~D:Record.Name~}:</span> <input type="Number" {~D:Record.PictForm.HTMLInputFullProperties~} value=""> | ||
<span>{~D:Record.Name~}:</span> <input type="Number" {~D:Record.Macro.InputFullProperties~} {~D:Record.Macro.InputChangeHandler~} value=""> | ||
` | ||
@@ -158,6 +180,161 @@ }, | ||
<!-- InputType TextArea {~D:Record.Hash~} {~D:Record.DataType~} --> | ||
<span>{~D:Record.Name~}:</span> <textarea {~D:Record.PictForm.HTMLInputFullProperties~}></textarea> | ||
<span>{~D:Record.Name~}:</span> <textarea {~D:Record.Macro.InputFullProperties~}></textarea> | ||
` | ||
}, | ||
/* | ||
* | ||
* [ Tabular Templates ] | ||
* | ||
*/ | ||
{ | ||
"HashPostfix": "-TabularTemplate-Group-Prefix", | ||
"Template": /*HTML*/` | ||
<div> | ||
<table> | ||
<tbody> | ||
<!-- Form Template Group Prefix [{~D:Context[0].UUID~}]::[{~D:Context[0].Hash~}] {~D:Record.Hash~}::{~D:Record.Name~} --> | ||
` | ||
}, | ||
// These templates are meant to be an easily overridable "add buttons to the row" template. | ||
{ | ||
"HashPostfix": "-TabularTemplate-RowHeader-ExtraPrefix", | ||
"Template": /*HTML*/`<!-- TabularTemplateRowHeader-ExtraPrefix -->` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-Row-ExtraPrefix", | ||
"Template": /*HTML*/`<!-- TabularTemplateRow-ExtraPrefix -->` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-RowHeader-ExtraPostfix", | ||
"Template": /*HTML*/`<!-- TabularTemplateRowHeader-ExtraPostfix -->` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-Row-ExtraPostfix", | ||
"Template": /*HTML*/`<!-- TabularTemplateRow-ExtraPostfix -->` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-RowHeader-Prefix", | ||
"Template": /*HTML*/` | ||
<thead> | ||
<tr>{~T:TabularTemplateRowHeader-ExtraPrefix~} | ||
` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-HeaderCell", | ||
"Template": /*HTML*/` | ||
<!-- Descriptor {~D:Record.Name~} [{~D:Record.Hash~}] -> {~D:Record.Address~} --> | ||
<th>{~D:Record.Name~}</th> | ||
` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-RowHeader-Postfix", | ||
"Template": /*HTML*/` | ||
{~T:TabularTemplateRowHeader-ExtraPostfix~}</tr> | ||
</thead> | ||
<tbody> | ||
` | ||
}, | ||
/* | ||
* | ||
* BEGINNING of the Tabular TemplateSet metatemplate entries | ||
* | ||
*/ | ||
{ | ||
"HashPostfix": "-TabularTemplate-Row-Prefix", | ||
"Template": /*HTML*/` | ||
<tr>{~T:TabularTemplateRow-ExtraPrefix~} | ||
` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-Cell-Prefix", | ||
"Template": /*HTML*/` | ||
<td><!-- {~D:Record.Name~} --> | ||
` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-Cell-Postfix", | ||
"Template": /*HTML*/` | ||
</td> | ||
` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-Row-Postfix", | ||
"Template": /*HTML*/` | ||
{~T:TabularTemplateRow-ExtraPostfix~}</tr>` | ||
}, | ||
/* | ||
* | ||
* END of the above Tabular TemplateSet metatemplate entries | ||
* | ||
*/ | ||
{ | ||
"HashPostfix": "-TabularTemplate-Group-Postfix", | ||
"Template": /*HTML*/` | ||
</tbody> | ||
</table> | ||
</div> | ||
<!-- Form Template Group Prefix [{~D:Context[0].UUID~}]::[{~D:Context[0].Hash~}] {~D:Record.Hash~}::{~D:Record.Name~} --> | ||
` | ||
}, | ||
/* | ||
* | ||
* Input Templates (tabular) | ||
* | ||
*/ | ||
{ | ||
"HashPostfix": "-TabularTemplate-Begin-Input", | ||
"Template": /*HTML*/` | ||
<!-- DEFAULT Input {~"D:Record.Hash~} {~D:Record.DataType~} --> | ||
<input type="text" {~D:Record.Macro.HTMLName~} {~D:Record.Macro.InformaryTabular~} ` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-End-Input", | ||
"Template": /*HTML*/` value="">` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-Begin-Input-DataType-String", | ||
"Template": /*HTML*/` | ||
<!-- DataType Number {~D:Record.Hash~} {~D:Record.DataType~} --> | ||
<input type="text" {~D:Record.Macro.HTMLName~} {~D:Record.Macro.InformaryTabular~} ` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-End-Input-DataType-String", | ||
"Template": /*HTML*/` value="">` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-Begin-Input-DataType-Number", | ||
"Template": /*HTML*/` | ||
<!-- DataType Number {~D:Record.Hash~} {~D:Record.DataType~} --> | ||
<input type="Number" {~D:Record.Macro.HTMLName~} {~D:Record.Macro.InformaryTabular~} ` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-End-Input-DataType-Number", | ||
"Template": /*HTML*/` {~D:Record.Macro.InputChangeHandler~} value=""> | ||
` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-Begin-Input-InputType-TextArea", | ||
"Template": /*HTML*/` | ||
<!-- InputType TextArea {~D:Record.Hash~} {~D:Record.DataType~} --> | ||
<textarea {~D:Record.Macro.HTMLName~} {~D:Record.Macro.InformaryTabular~} ` | ||
}, | ||
{ | ||
"HashPostfix": "-TabularTemplate-End-Input-InputType-TextArea", | ||
"Template": /*HTML*/`></textarea> | ||
` | ||
} | ||
] | ||
}); |
const libPictProvider = require('pict-provider'); | ||
const defaultFormTemplates = require('./Pict-Section-Form-Provider-Templates-DefaultFormTemplates.js'); | ||
const _DefaultFormTemplates = require('./Pict-Section-Form-Provider-Templates-DefaultFormTemplates.js'); | ||
const _DefaultProviderConfiguration = ( | ||
{ | ||
"ProviderIdentifier": "Pict-Section-Form-Provider-Templates-Basic", | ||
"AutoInitialize": true, | ||
"AutoInitializeOrdinal": 0, | ||
"AutoSolveWithApp": false | ||
}); | ||
class PictSectionFormTemplateProvider extends libPictProvider | ||
@@ -9,3 +18,3 @@ { | ||
{ | ||
let tmpOptions = Object.assign({}, JSON.parse(JSON.stringify(require('./Pict-Section-Form-Provider-Templates-DefaultConfiguration.json'))), pOptions); | ||
let tmpOptions = Object.assign({}, JSON.parse(JSON.stringify(_DefaultProviderConfiguration)), pOptions); | ||
@@ -15,3 +24,3 @@ // This is all you're expected to overload in this provider | ||
{ | ||
tmpOptions.MetaTemplateSet = JSON.parse(JSON.stringify(defaultFormTemplates)); | ||
tmpOptions.MetaTemplateSet = JSON.parse(JSON.stringify(_DefaultFormTemplates)); | ||
} | ||
@@ -27,3 +36,3 @@ | ||
// The default template prefix is 'Pict-Forms-Basic' | ||
this.formsTemplateSetPrefix = defaultFormTemplates.TemplatePrefix; | ||
this.formsTemplateSetPrefix = _DefaultFormTemplates.TemplatePrefix; | ||
} | ||
@@ -56,5 +65,5 @@ else if (!this.options.MetaTemplateSet.hasOwnProperty('TemplatePrefix') && (this.options.ProviderIdentifier != 'Pict-Section-Form-Provider-Templates-Basic')) | ||
for (let i = 0; i < defaultFormTemplates.Templates.length; i++) | ||
for (let i = 0; i < _DefaultFormTemplates.Templates.length; i++) | ||
{ | ||
let tmpTemplate = defaultFormTemplates.Templates[i]; | ||
let tmpTemplate = _DefaultFormTemplates.Templates[i]; | ||
let tmpTemplateHash = `${this.formsTemplateSetPrefix}${tmpTemplate.HashPostfix}`; | ||
@@ -82,4 +91,2 @@ // Only load default templates if they are not already defined in the options | ||
module.exports = PictSectionFormTemplateProvider; | ||
module.exports.default_configuration = require('./Pict-Section-Form-Provider-Templates-DefaultConfiguration.json'); | ||
module.exports.default_configuration = _DefaultProviderConfiguration; |
{ | ||
"RenderOnLoad": false, | ||
"AutoRender": false, | ||
@@ -11,3 +11,22 @@ "DefaultRenderable": "Form-Main", | ||
"MacroTemplates": { | ||
"Section": { | ||
"HTMLID": " id=\"Section-{~D:Context[0].UUID~}\" " | ||
}, | ||
"Group": { | ||
"HTMLID": " id=\"Group-{~D:Context[0].UUID~}\" " | ||
}, | ||
"Input": { | ||
"Informary": " data-i-form=\"{~D:Context[0].formID~}\" data-i-datum=\"{~D:Record.PictForm.InformaryDataAddress~}\" ", | ||
"InformaryTabular": " data-i-form=\"{~D:Context[0].formID~}\" data-i-datum=\"{~D:Record.PictForm.InformaryDataAddress~}\" data-i-container=\"{~D:Record.PictForm.InformaryContainerAddress~}\" ", | ||
"HTMLName": " name=\"{~D:Record.Name~}\" ", | ||
"HTMLID": " id=\"{~D:Context[0].UUID~}-FormInput-{~D:Record.Hash~}\" ", | ||
"InputFullProperties": " data-i-form=\"{~D:Context[0].formID~}\" data-i-datum=\"{~D:Record.PictForm.InformaryDataAddress~}\" name=\"{~D:Record.Name~}\" ", | ||
"InputChangeHandler": " onchange=\"_Pict.views['{~D:Context[0].Hash~}'].dataChanged('{~D:Record.Hash~}')\" " | ||
} | ||
}, | ||
"TargetElementAddress": "#Form-Container-Div" | ||
} |
const libPictViewClass = require('pict-view'); | ||
const libInformary = require('informary'); | ||
const libInformary = require('./Pict-Service-Informary.js'); | ||
const libFormsTemplateProvider = require('./Pict-Section-Form-Provider-Templates.js'); | ||
class PictSectionForm extends libPictViewClass | ||
class PictSectionFormView extends libPictViewClass | ||
{ | ||
@@ -39,2 +38,6 @@ constructor(pFable, pOptions, pServiceHash) | ||
} | ||
if (!tmpOptions.SectionTabularRowTemplateHash) | ||
{ | ||
tmpOptions.SectionTabularRowTemplateHash = `Pict-Form-Template-TabularRow-${tmpOptions.Hash}`; | ||
} | ||
@@ -65,4 +68,15 @@ if (tmpOptions.Renderables.length < 1) | ||
} | ||
if (!this.pict.providers.Informary) | ||
{ | ||
let tmpInformary = this.pict.addProvider('Informary', libInformary.default_configuration, libInformary); | ||
tmpInformary.initialize(); | ||
} | ||
// This is for if we decide to abstract metatemplates into a separate provider for code simplification | ||
// if (!this.pict.providers.PictFormSectionMetatemplateGenerator) | ||
// { | ||
// let tmpMetatemplateGenerator = this.pict.addProvider('PictFormSectionMetatemplateGenerator', libFormsMetatemplateGenerator.default_configuration, libFormsMetatemplateGenerator); | ||
// tmpMetatemplateGenerator.initialize(); | ||
// } | ||
// Load any form-specific templates | ||
// Load any view section-specific templates | ||
this.formsTemplateSetPrefix = `PFT-${this.Hash}-${this.UUID}`; | ||
@@ -86,6 +100,9 @@ if (this.options.hasOwnProperty('MetaTemplates') && Array.isArray(this.options.MetaTemplates)) | ||
} | ||
// The default template prefix | ||
this.defaultTemplatePrefix = 'Pict-Forms-Basic'; | ||
this.formID = `Pict-Form-${this.Hash}-${this.UUID}`; | ||
this.informary = new libInformary({ Form:this.formID }) | ||
// Informary is very old and requires jquery. | ||
// TODO: Refactor informary to be a pict service, eliminating this need entirely. | ||
@@ -98,4 +115,30 @@ this.viewMarshalDestination = false; | ||
this.initializeFormGroups(); | ||
this.rebuildMacros(); | ||
} | ||
dataChanged(pInputHash) | ||
{ | ||
// This is what is called whenever a hash is changed. We could marshal from view, solve and remarshal to view. | ||
// TODO: Determine best pattern for allowing others to override this without subclassing this. Maybe a registered provider type? | ||
this.marshalFromView(); | ||
this.pict.PictApplication.solve(); | ||
this.marshalToView(); | ||
} | ||
getMarshalDestinationAddress() | ||
{ | ||
if (this.viewMarshalDestination) | ||
{ | ||
return this.viewMarshalDestination; | ||
} | ||
else if (this.pict.views.PictFormMetacontroller && this.pict.views.PictFormMetacontroller.viewMarshalDestination) | ||
{ | ||
return this.pict.views.PictFormMetacontroller.viewMarshalDestination; | ||
} | ||
else | ||
{ | ||
return 'AppData'; | ||
} | ||
} | ||
getMarshalDestinationObject() | ||
@@ -138,10 +181,3 @@ { | ||
this.informary.marshalDataToForm(tmpMarshalDestinationObject, | ||
function(pError) | ||
{ | ||
if (pError) | ||
{ | ||
this.log.error(`Error marshaling data to view: ${pError}`); | ||
} | ||
}); | ||
this.pict.providers.Informary.marshalDataToForm(tmpMarshalDestinationObject, this.formID); | ||
} | ||
@@ -162,16 +198,3 @@ catch (pError) | ||
if (typeof(tmpMarshalDestinationObject) != 'object') | ||
{ | ||
this.log.error(`Marshal destination object is not an object; if you initialize the view yourself you must set the viewMarshalDestination property to a valid address within the view. Falling back to AppData.`); | ||
tmpMarshalDestinationObject = this.pict.AppData; | ||
} | ||
this.informary.marshalFormToData(tmpMarshalDestinationObject, | ||
function(pError) | ||
{ | ||
if (pError) | ||
{ | ||
this.log.error(`Error marshaling data from view: ${pError}`); | ||
} | ||
}); | ||
this.pict.providers.Informary.marshalFormToData(tmpMarshalDestinationObject, this.formID); | ||
} | ||
@@ -220,2 +243,3 @@ catch (pError) | ||
{ | ||
// TODO: Change this to use the parsed sectionManifest rather than parsing the manifest itself | ||
let tmpDescriptor = this.options.Manifests.Section.Descriptors[tmpDescriptorKeys[i]]; | ||
@@ -252,2 +276,50 @@ | ||
// Check the Group type and get the manifest if it is a RECORDSET-based group. | ||
// The three built-in set groups (Record, Tabular, Columnar) will do this or the | ||
// developer can set a property on Group called "GroupType" to "RecordSet" for | ||
// custom layouts. | ||
if (((tmpGroup.Layout === 'Tabular') || (tmpGroup.Layout === 'Tabular') || (tmpGroup.Layout === 'Tabular')) || | ||
(tmpGroup.GroupType === 'RecordSet')) | ||
{ | ||
// Check for the supporting manifest | ||
if (!tmpGroup.hasOwnProperty('RecordManifest')) | ||
{ | ||
this.pict.log.error(`Dynamic View [${this.UUID}]::[${this.Hash}] Group ${tmpGroup.Hash} is classified as a RecordSet group but thee Group does not contain a RecordManifest property.`); | ||
tmpGroup.supportingManifest = this.fable.instantiateServiceProviderWithoutRegistration('Manifest'); | ||
} | ||
else if (!this.options.Manifests.Section.hasOwnProperty('ReferenceManifests')) | ||
{ | ||
this.pict.log.error(`Dynamic View [${this.UUID}]::[${this.Hash}] Group ${tmpGroup.Hash} is classified as a RecordSet group but there are no ReferenceManifests in the Section description Manifest.`); | ||
tmpGroup.supportingManifest = this.fable.instantiateServiceProviderWithoutRegistration('Manifest'); | ||
} | ||
else if (!this.options.Manifests.Section.ReferenceManifests.hasOwnProperty(tmpGroup.RecordManifest)) | ||
{ | ||
this.pict.log.error(`Dynamic View [${this.UUID}]::[${this.Hash}] Group ${tmpGroup.Hash} is classified as a RecordSet group and has a RecordManifest of [${tmpGroup.RecordManifest}] but the Section.ReferenceManifests object does not contain the referred to manifest.`); | ||
tmpGroup.supportingManifest = this.fable.instantiateServiceProviderWithoutRegistration('Manifest'); | ||
} | ||
else | ||
{ | ||
tmpGroup.supportingManifest = this.fable.instantiateServiceProviderWithoutRegistration('Manifest', this.options.Manifests.Section.ReferenceManifests[tmpGroup.RecordManifest]); | ||
} | ||
} | ||
if (tmpGroup.supportingManifest && (typeof(tmpGroup.RecordSetAddress) == 'string')) | ||
{ | ||
let tmpSupportingManifestDescriptorKeys = Object.keys(tmpGroup.supportingManifest.elementDescriptors); | ||
for (let k = 0; k < tmpSupportingManifestDescriptorKeys.length; k++) | ||
{ | ||
let tmpInput = tmpGroup.supportingManifest.elementDescriptors[tmpSupportingManifestDescriptorKeys[k]]; | ||
if (!tmpInput.hasOwnProperty('PictForm')) | ||
{ | ||
tmpInput.PictForm = {}; | ||
} | ||
tmpInput.PictForm.InformaryDataAddress = tmpSupportingManifestDescriptorKeys[k]; | ||
tmpInput.PictForm.InformaryContainerAddress = tmpGroup.RecordSetAddress; | ||
tmpInput.RowIdentifierTemplateHash = '{~D:Record.RowID~}'; | ||
} | ||
} | ||
let tmpRowHash = (typeof(tmpDescriptor.PictForm.Row) == 'string') ? tmpDescriptor.PictForm.Row : | ||
@@ -275,26 +347,215 @@ (typeof(tmpDescriptor.PictForm.Row) == 'number') ? `Row_${tmpDescriptor.PictForm.Row.toString()}` : | ||
rebuildCustomTemplate() | ||
rebuildMacros() | ||
{ | ||
let tmpTemplate = ``; | ||
let tmpFormTemplatePrefix = 'Pict-Forms-Basic'; | ||
if (!this.options.hasOwnProperty('MacroTemplates')) | ||
{ | ||
return false; | ||
} | ||
if (this.pict.views.PictFormMetacontroller) | ||
// Section macros | ||
let tmpSectionMacroKeys = Object.keys(this.options.MacroTemplates.Section); | ||
if (typeof(this.sectionDefinition.Macro) !== 'object') | ||
{ | ||
if (this.pict.views.PictFormMetacontroller.hasOwnProperty('formTemplatePrefix')) | ||
this.sectionDefinition.Macro = {}; | ||
} | ||
for (let n = 0; n < tmpSectionMacroKeys.length; n++) | ||
{ | ||
this.sectionDefinition.Macro[tmpSectionMacroKeys[n]] = this.pict.parseTemplate (this.options.MacroTemplates.Section[tmpSectionMacroKeys[n]], this.sectionDefinition, null, [this]); | ||
} | ||
for (let i = 0; i < this.sectionDefinition.Groups.length; i++) | ||
{ | ||
let tmpGroup = this.sectionDefinition.Groups[i]; | ||
// Group Macros | ||
let tmpGroupMacroKeys = Object.keys(this.options.MacroTemplates.Group); | ||
if (!tmpGroup.hasOwnProperty('Macro')) | ||
{ | ||
tmpFormTemplatePrefix = this.pict.views.PictFormMetacontroller.formTemplatePrefix; | ||
tmpGroup.Macro = {}; | ||
} | ||
for (let n = 0; n < tmpGroupMacroKeys.length; n++) | ||
{ | ||
tmpGroup.Macro[tmpGroupMacroKeys[n]] = this.pict.parseTemplate (this.options.MacroTemplates.Group[tmpGroupMacroKeys[n]], tmpGroup, null, [this]); | ||
} | ||
if (!Array.isArray(tmpGroup.Rows)) | ||
{ | ||
continue; | ||
} | ||
for (let j = 0; j < tmpGroup.Rows.length; j++) | ||
{ | ||
// TODO: Do we want row macros? Let's be still and find out. | ||
let tmpRow = tmpGroup.Rows[j]; | ||
for (let k = 0; k < tmpRow.Inputs.length; k++) | ||
{ | ||
let tmpInput = tmpRow.Inputs[k]; | ||
// Input Macros | ||
let tmpInputMacroKeys = Object.keys(this.options.MacroTemplates.Input); | ||
if (!tmpInput.hasOwnProperty('Macro')) | ||
{ | ||
tmpInput.Macro = {}; | ||
} | ||
for (let n = 0; n < tmpInputMacroKeys.length; n++) | ||
{ | ||
tmpInput.Macro[tmpInputMacroKeys[n]] = this.pict.parseTemplate (this.options.MacroTemplates.Input[tmpInputMacroKeys[n]], tmpInput, null, [this]); | ||
} | ||
} | ||
} | ||
if (tmpGroup.supportingManifest) | ||
{ | ||
let tmpSupportingManifestDescriptorKeys = Object.keys(tmpGroup.supportingManifest.elementDescriptors); | ||
for (let k = 0; k < tmpSupportingManifestDescriptorKeys.length; k++) | ||
{ | ||
let tmpInput = tmpGroup.supportingManifest.elementDescriptors[tmpSupportingManifestDescriptorKeys[k]]; | ||
// Input Macros | ||
let tmpInputMacroKeys = Object.keys(this.options.MacroTemplates.Input); | ||
if (!tmpInput.hasOwnProperty('Macro')) | ||
{ | ||
tmpInput.Macro = {}; | ||
} | ||
for (let n = 0; n < tmpInputMacroKeys.length; n++) | ||
{ | ||
tmpInput.Macro[tmpInputMacroKeys[n]] = this.pict.parseTemplate (this.options.MacroTemplates.Input[tmpInputMacroKeys[n]], tmpInput, null, [this]); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// Add the Form Prefix stuff | ||
if (this.pict.TemplateProvider.getTemplate(`${this.formsTemplateSetPrefix}-Template-Wrap-Prefix`)) | ||
checkViewSpecificTemplate(pTemplatePostfix) | ||
{ | ||
// This is here to cut down on complex guards, and, so we can optimize/extend it later if we need to. | ||
return this.pict.TemplateProvider.templates.hasOwnProperty(`${this.formsTemplateSetPrefix}${pTemplatePostfix}`) | ||
} | ||
checkThemeSpecificTemplate(pTemplatePostfix) | ||
{ | ||
// This is here to cut down on complex guards, and, so we can optimize/extend it later if we need to. | ||
return this.pict.TemplateProvider.templates.hasOwnProperty(`${this.defaultTemplatePrefix}${pTemplatePostfix}`) | ||
} | ||
getMetatemplateTemplateReference(pTemplatePostfix, pViewDataAddress) | ||
{ | ||
/* This is to abstract the logic of checking for section-specific templates on the metatemplate generation lines. | ||
* This code replace tons of blocks like this: | ||
if (this.pict.TemplateProvider.getTemplate(`${this.formsTemplateSetPrefix}-Template-Wrap-Prefix`)) | ||
{ | ||
tmpTemplate += `{~T:${this.formsTemplateSetPrefix}-Template-Wrap-Prefix:Pict.views["${this.Hash}"].sectionDefinition~}`; | ||
} | ||
else | ||
{ | ||
tmpTemplate += `{~T:${this.defaultTemplatePrefix}-Template-Wrap-Prefix:Pict.views["${this.Hash}"].sectionDefinition~}`; | ||
} | ||
*/ | ||
// 1. Check if there is a section-specific template loaded | ||
if (this.checkViewSpecificTemplate(pTemplatePostfix)) | ||
{ | ||
tmpTemplate += `{~T:${this.formsTemplateSetPrefix}-Template-Wrap-Prefix:Pict.views["${this.Hash}"].sectionDefinition~}`; | ||
return `\n{~T:${this.formsTemplateSetPrefix}${pTemplatePostfix}:Pict.views["${this.Hash}"].${pViewDataAddress}~}` | ||
} | ||
// 2. Check if there is a theme-specific template loaded for this postfix | ||
else if (this.checkThemeSpecificTemplate(pTemplatePostfix)) | ||
{ | ||
return `\n{~T:${this.defaultTemplatePrefix}${pTemplatePostfix}:Pict.views["${this.Hash}"].${pViewDataAddress}~}` | ||
} | ||
// 3. This shouldn't happen if the template is based on the base class. | ||
else | ||
{ | ||
tmpTemplate += `{~T:${tmpFormTemplatePrefix}-Template-Wrap-Prefix:Pict.views["${this.Hash}"].sectionDefinition~}`; | ||
return false; | ||
} | ||
tmpTemplate += `\n{~T:${tmpFormTemplatePrefix}-Template-Section-Prefix:Pict.views["${this.Hash}"].sectionDefinition~}`; | ||
} | ||
getInputMetatemplateTemplateReference(pDataType, pInputType, pViewDataAddress) | ||
{ | ||
// Input types are customizable -- there could be 30 different input types for the string data type with special handling and templates | ||
let tmpTemplateInputTypePostfix = `-Template-Input-InputType-${pInputType}`; | ||
// Data types are not customizable; they are a fixed list based on what is available in Manyfest | ||
let tmpTemplateDataTypePostfix = `-Template-Input-DataType-${pDataType}`; | ||
// First check if there is an "input type" template available in either the section-specific configuration or in the general | ||
if (pInputType) | ||
{ | ||
let tmpTemplate = this.getMetatemplateTemplateReference(tmpTemplateInputTypePostfix, pViewDataAddress); | ||
if (tmpTemplate) | ||
{ | ||
return tmpTemplate; | ||
} | ||
} | ||
// If we didn't find the template for the "input type", check for the "data type" | ||
let tmpTemplate = this.getMetatemplateTemplateReference(tmpTemplateDataTypePostfix, pViewDataAddress); | ||
if (tmpTemplate) | ||
{ | ||
return tmpTemplate; | ||
} | ||
// There wasn't an input type specific or data type specific template, so fall back to the generic input template. | ||
return this.getMetatemplateTemplateReference('-Template-Input', pViewDataAddress); | ||
} | ||
getTabularInputMetatemplateTemplateReference(pDataType, pInputType, pViewDataAddress, pRecordSubAddress) | ||
{ | ||
// Input types are customizable -- there could be 30 different input types for the string data type with special handling and templates | ||
let tmpTemplateBeginInputTypePostfix = `-TabularTemplate-Begin-Input-InputType-${pInputType}`; | ||
let tmpTemplateEndInputTypePostfix = `-TabularTemplate-End-Input-InputType-${pInputType}`; | ||
// Data types are not customizable; they are a fixed list based on what is available in Manyfest | ||
let tmpTemplateBeginDataTypePostfix = `-TabularTemplate-Begin-Input-DataType-${pDataType}`; | ||
let tmpTemplateEndDataTypePostfix = `-TabularTemplate-End-Input-DataType-${pDataType}`; | ||
// Tabular inputs are done in three parts -- the "begin", the "address" of the data and the "end". | ||
// This means it is easily extensible to work on JSON objects as well as arrays. | ||
// TODO: (when we update informary to be a pict plugin, make the data-i-index stuff support data-i-key for objects) | ||
//let tmpAddressTemplate = ` data-i-index="ArrayIndex_${pRecordSubAddress.toString()}" `; | ||
let tmpAddressTemplate = ` data-i-index="{~D:Record.Index~}" `; | ||
// First check if there is an "input type" template available in either the section-specific configuration or in the general | ||
if (pInputType) | ||
{ | ||
let tmpBeginTemplate = this.getMetatemplateTemplateReference(tmpTemplateBeginInputTypePostfix, pViewDataAddress); | ||
let tmpEndTemplate = this.getMetatemplateTemplateReference(tmpTemplateEndInputTypePostfix, pViewDataAddress); | ||
if (tmpBeginTemplate && tmpEndTemplate) | ||
{ | ||
return tmpBeginTemplate + tmpAddressTemplate + tmpEndTemplate; | ||
} | ||
} | ||
// If we didn't find the template for the "input type", check for the "data type" | ||
let tmpBeginTemplate = this.getMetatemplateTemplateReference(tmpTemplateBeginDataTypePostfix, pViewDataAddress); | ||
let tmpEndTemplate = this.getMetatemplateTemplateReference(tmpTemplateEndDataTypePostfix, pViewDataAddress); | ||
if (tmpBeginTemplate && tmpEndTemplate) | ||
{ | ||
return tmpBeginTemplate + tmpAddressTemplate + tmpEndTemplate; | ||
} | ||
// If we didn't find the template for the "input type", or the "data type", fall back to the default | ||
tmpBeginTemplate = this.getMetatemplateTemplateReference('TabularTemplate-Begin-Input', pViewDataAddress); | ||
tmpEndTemplate = this.getMetatemplateTemplateReference('TabularTemplate-End-Input', pViewDataAddress); | ||
if (tmpBeginTemplate && tmpEndTemplate) | ||
{ | ||
return tmpBeginTemplate + tmpAddressTemplate + tmpEndTemplate; | ||
} | ||
// There wasn't some k ind of catastrophic failure -- the above templates should always be loaded. | ||
this.log.error(`PICT Form [${this.UUID}]::[${this.Hash}] catastrophic error generating tabular metatemplate: missing input template for Data Type ${pDataType} and Input Type ${pInputType}, Data Address ${pViewDataAddress} and Record Subaddress ${pRecordSubAddress}}.`) | ||
return ''; | ||
} | ||
rebuildCustomTemplate() | ||
{ | ||
let tmpTemplate = ``; | ||
if (this.pict.views.PictFormMetacontroller) | ||
{ | ||
if (this.pict.views.PictFormMetacontroller.hasOwnProperty('formTemplatePrefix')) | ||
{ | ||
this.defaultTemplatePrefix = this.pict.views.PictFormMetacontroller.formTemplatePrefix; | ||
} | ||
} | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-Template-Wrap-Prefix`, `sectionDefinition`); | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-Template-Section-Prefix`, `sectionDefinition`); | ||
for (let i = 0; i < this.sectionDefinition.Groups.length; i++) | ||
@@ -304,3 +565,11 @@ { | ||
tmpTemplate += `\n{~T:${tmpFormTemplatePrefix}-Template-Group-Prefix:Pict.views["${this.Hash}"].sectionDefinition.Groups[${i}]~}`; | ||
// Group layouts are customizable | ||
// The three basic group layouts: | ||
// 1. Record (default) - Render the whole address as a singleton record | ||
// placing inputs into rows based on configuration. | ||
// 2. Tabular - Expect either an Array of objects or a POJO to | ||
// be rendered one record per row. | ||
let tmpGroupLayout = (typeof(tmpGroup.Layout) === 'string') ? tmpGroup.Layout : | ||
(typeof(this.sectionDefinition.DefaultGroupLayout) === 'string') ? this.sectionDefinition.DefaultGroupLayout : | ||
'Record'; | ||
@@ -312,53 +581,82 @@ if (!Array.isArray(tmpGroup.Rows)) | ||
for (let j = 0; j < tmpGroup.Rows.length; j++) | ||
switch(tmpGroupLayout) | ||
{ | ||
tmpTemplate += `\n{~T:${tmpFormTemplatePrefix}-Template-Row-Prefix:Pict.views["${this.Hash}"].sectionDefinition.Groups[${i}]~}`; | ||
for (let k = 0; k < tmpGroup.Rows[j].Inputs.length; k++) | ||
{ | ||
let tmpTemplateInputScope = '-Template-Input'; | ||
case 'Tabular': | ||
// Tabular layout | ||
let tmpTemplateSetRecordRowTemplate = ''; | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-TabularTemplate-Group-Prefix`, `getGroup("${i}")`); | ||
// Tabular templates only have one "row" for the header in the standard template, and then a row for each record. | ||
// The row for each record happens as a TemplateSet. | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-TabularTemplate-RowHeader-Prefix`, `getGroup("${i}")`); | ||
tmpGroup.Rows[j].Inputs[k].PictForm.HTMLInformaryProperties = ` data-i-form="${this.formID}" data-i-datum="${tmpGroup.Rows[j].Inputs[k].PictForm.InformaryDataAddress}" `; | ||
tmpGroup.Rows[j].Inputs[k].PictForm.HTMLInputName = ` name="${tmpGroup.Rows[j].Inputs[k].Name}" `; | ||
tmpGroup.Rows[j].Inputs[k].PictForm.HTMLInputID = ` id="${this.UUID}-FormInput-${tmpGroup.Rows[j].Inputs[k].Hash}" `; | ||
tmpTemplateSetRecordRowTemplate += this.getMetatemplateTemplateReference(`-TabularTemplate-Row-Prefix`, `getGroup("${i}")`); | ||
for (let j = 0; j < tmpGroup.Rows.length; j++) | ||
{ | ||
tmpGroup.Rows[j].Inputs[k].PictForm.HTMLInputFullProperties = `${tmpGroup.Rows[j].Inputs[k].PictForm.HTMLInputID}${tmpGroup.Rows[j].Inputs[k].PictForm.HTMLInputName}${tmpGroup.Rows[j].Inputs[k].PictForm.HTMLInformaryProperties}`; | ||
let tmpRow = tmpGroup.Rows[j]; | ||
// Tabular are odd in that they have a header row and then a meta TemplateSet for the rows() | ||
// Check for view-specific control/datatype templates | ||
if (this.pict.TemplateProvider.getTemplate(`${this.formsTemplateSetPrefix}${tmpTemplateInputScope}-InputType-${tmpGroup.Rows[j].Inputs[k].PictForm.InputType}`)) | ||
{ | ||
tmpTemplateInputScope += `-InputType-${tmpGroup.Rows[j].Inputs[k].PictForm.InputType}`; | ||
tmpTemplate += `\n{~T:${this.formsTemplateSetPrefix}${tmpTemplateInputScope}:Pict.views["${this.Hash}"].sectionDefinition.Groups[${i}].Rows[${j}].Inputs[${k}]~}`; | ||
// In this case we are going to load the descriptors from the supportingManifests | ||
if (!tmpGroup.supportingManifest) | ||
{ | ||
this.log.error(`PICT Form [${this.UUID}]::[${this.Hash}] error generating tabular metatemplate: missing group manifest ${tmpGroup.RecordManifest} from supportingManifests.`); | ||
continue; | ||
} | ||
// TODO: Keyed objects as the entries | ||
for (let k = 0; k < tmpGroup.supportingManifest.elementAddresses.length; k++) | ||
{ | ||
let tmpSupportingManifestHash = tmpGroup.supportingManifest.elementAddresses[k]; | ||
let tmpInput = tmpGroup.supportingManifest.elementDescriptors[tmpSupportingManifestHash]; | ||
tmpTemplate += this.getMetatemplateTemplateReference('-TabularTemplate-HeaderCell', `getTabularRecordInput("${i}","${k}")`); | ||
tmpTemplateSetRecordRowTemplate += this.getMetatemplateTemplateReference(`-TabularTemplate-Cell-Prefix`, `getTabularRecordInput("${i}","${k}")`); | ||
let tmpInputType = (tmpInput.hasOwnProperty('PictForm')) ? tmpInput.PictForm.InputType : 'Default'; | ||
// Right now the address is just the array element for the record. | ||
tmpTemplateSetRecordRowTemplate += this.getTabularInputMetatemplateTemplateReference(tmpInput.DataType, tmpInputType, `getTabularRecordInput("${i}","${k}")`, k); | ||
// Accidentally did the next part of resolution a step early in the chain | ||
//tmpTemplateSetRecordRowTemplate += this.getTabularInputMetatemplateTemplateReference(tmpInput.DataType, tmpInputType, `getTabularRecordInput("${i}","${tmpSupportingManifestHash}")`); | ||
tmpTemplateSetRecordRowTemplate += this.getMetatemplateTemplateReference(`-TabularTemplate-Cell-Postfix`, `getTabularRecordInput("${i}","${k}")`); | ||
} | ||
} | ||
else if (this.pict.TemplateProvider.getTemplate(`${this.formsTemplateSetPrefix}${tmpTemplateInputScope}-DataType-${tmpGroup.Rows[j].Inputs[k].DataType}`)) | ||
{ | ||
tmpTemplateInputScope += `-DataType-${tmpGroup.Rows[j].Inputs[k].DataType}`; | ||
tmpTemplate += `\n{~T:${this.formsTemplateSetPrefix}${tmpTemplateInputScope}:Pict.views["${this.Hash}"].sectionDefinition.Groups[${i}].Rows[${j}].Inputs[${k}]~}`; | ||
} | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-TabularTemplate-RowHeader-Postfix`, `getGroup("${i}")`); | ||
// Check for theme-specific control/datatype templates | ||
else if (this.pict.TemplateProvider.getTemplate(`${tmpFormTemplatePrefix}${tmpTemplateInputScope}-InputType-${tmpGroup.Rows[j].Inputs[k].PictForm.InputType}`)) | ||
// This is the template by which the tabular template includes the rows. | ||
// The recursion here is difficult to envision without drawing it. | ||
// TODO: Consider making this function available in manyfest in some fashion it seems dope. | ||
tmpTemplate += `\n\n{~TS:${this.options.SectionTabularRowTemplateHash}:Context[0].tabularKeys(${this.getMarshalDestinationAddress()}.${tmpGroup.RecordSetAddress})~}\n`; | ||
tmpTemplateSetRecordRowTemplate += this.getMetatemplateTemplateReference(`-TabularTemplate-Row-Postfix`, `getGroup("${i}")`); | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-TabularTemplate-Group-Postfix`, `getGroup("${i}")`); | ||
// Add the TemplateSetTemplate | ||
this.pict.TemplateProvider.addTemplate(this.options.SectionTabularRowTemplateHash, tmpTemplateSetRecordRowTemplate); | ||
break; | ||
case 'Record': | ||
default: | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-Template-Group-Prefix`, `getGroup("${i}")`); | ||
for (let j = 0; j < tmpGroup.Rows.length; j++) | ||
{ | ||
tmpTemplateInputScope += `-InputType-${tmpGroup.Rows[j].Inputs[k].PictForm.InputType}`; | ||
tmpTemplate += `\n{~T:${tmpFormTemplatePrefix}${tmpTemplateInputScope}:Pict.views["${this.Hash}"].sectionDefinition.Groups[${i}].Rows[${j}].Inputs[${k}]~}`; | ||
} | ||
else if (this.pict.TemplateProvider.getTemplate(`${tmpFormTemplatePrefix}${tmpTemplateInputScope}-DataType-${tmpGroup.Rows[j].Inputs[k].DataType}`)) | ||
{ | ||
tmpTemplateInputScope += `-DataType-${tmpGroup.Rows[j].Inputs[k].DataType}`; | ||
tmpTemplate += `\n{~T:${tmpFormTemplatePrefix}${tmpTemplateInputScope}:Pict.views["${this.Hash}"].sectionDefinition.Groups[${i}].Rows[${j}].Inputs[${k}]~}`; | ||
} | ||
let tmpRow = tmpGroup.Rows[j]; | ||
// Fall back on the default control/datatype template | ||
else | ||
{ | ||
tmpTemplate += `\n{~T:${tmpFormTemplatePrefix}${tmpTemplateInputScope}:Pict.views["${this.Hash}"].sectionDefinition.Groups[${i}].Rows[${j}].Inputs[${k}]~}`; | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-Template-Row-Prefix`, `getGroup("${i}")`); | ||
// There are three row layouts: Record, Tabular and Columnar | ||
for (let k = 0; k < tmpRow.Inputs.length; k++) | ||
{ | ||
let tmpInput = tmpRow.Inputs[k]; | ||
tmpTemplate += this.getInputMetatemplateTemplateReference(tmpInput.DataType, tmpInput.PictForm.InputType, `getInput("${i}","${j}","${k}")`); | ||
} | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-Template-Row-Postfix`, `getGroup("${i}")`); | ||
} | ||
} | ||
tmpTemplate += `\n{~T:${tmpFormTemplatePrefix}-Template-Row-Postfix:Pict.views["${this.Hash}"].sectionDefinition.Groups[${i}]~}`; | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-Template-Group-Postfix`, `getGroup("${i}")`); | ||
break; | ||
} | ||
tmpTemplate += `\n{~T:${tmpFormTemplatePrefix}-Template-Group-Postfix:Pict.views["${this.Hash}"].sectionDefinition.Groups[${i}]~}`; | ||
} | ||
tmpTemplate += `\n{~T:${tmpFormTemplatePrefix}-Template-Section-Postfix:Pict.views["${this.Hash}"].sectionDefinition~}`; | ||
tmpTemplate += `\n{~T:${tmpFormTemplatePrefix}-Template-Wrap-Postfix:Pict.views["${this.Hash}"].sectionDefinition~}`; | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-Template-Section-Postfix`, `sectionDefinition`); | ||
tmpTemplate += this.getMetatemplateTemplateReference(`-Template-Wrap-Postfix`, `sectionDefinition`); | ||
@@ -368,2 +666,159 @@ this.pict.TemplateProvider.addTemplate(this.options.SectionTemplateHash, tmpTemplate); | ||
// Metatemplate Helper Functions | ||
getTabularRecordInput(pGroupIndex, pInputIndex) | ||
{ | ||
// The neat thing about how the tabular groups work is that we can make it clever about whether it's an object or an array. | ||
let tmpGroup = this.getGroup(pGroupIndex); | ||
if (!tmpGroup) | ||
{ | ||
this.log.warn(`PICT View Metatemplate Helper getTabularRowData ${pGroupIndex} was not a valid group.`); | ||
return false; | ||
} | ||
// Now get the supporting manifest and the input element | ||
// This needs more guards | ||
let tmpSupportingManifestHash = tmpGroup.supportingManifest.elementAddresses[pInputIndex]; | ||
return tmpGroup.supportingManifest.elementDescriptors[tmpSupportingManifestHash]; | ||
} | ||
getTabularRecordData(pGroupIndex, pRowIdentifier) | ||
{ | ||
// The neat thing about how the tabular groups work is that we can make it clever about whether it's an object or an array. | ||
let tmpGroup = this.getGroup(pGroupIndex); | ||
if (!tmpGroup) | ||
{ | ||
this.log.warn(`PICT View Metatemplate Helper getTabularRowData ${pGroupIndex} was not a valid group.`); | ||
return false; | ||
} | ||
// Now identify the group | ||
let tmpRowSourceRecord = this.sectionManifest.getValueByHash(this.getMarshalDestinationObject(), tmpGroup.RecordSetAddress); | ||
if (!tmpRowSourceRecord) | ||
{ | ||
// Try the address | ||
tmpRowSourceRecord = this.sectionManifest.getValueAtAddress(this.getMarshalDestinationObject(), tmpGroup.RecordSetAddress); | ||
} | ||
if (!tmpRowSourceRecord) | ||
{ | ||
this.log.warn(`PICT View Metatemplate Helper getTabularRowData ${pGroupIndex} could not find the record set for ${tmpGroup.RecordSetAddress}.`); | ||
return false; | ||
} | ||
// Now we have the source record let's see what it is | ||
try | ||
{ | ||
if (Array.isArray(tmpRowSourceRecord)) | ||
{ | ||
return tmpRowSourceRecord[pRowIdentifier]; | ||
} | ||
else if (typeof(tmpRowSourceRecord) === 'object') | ||
{ | ||
return tmpRowSourceRecord[pRowIdentifier]; | ||
} | ||
else | ||
{ | ||
this.log.warn(`PICT View Metatemplate Helper getTabularRowData ${pGroupIndex} could not determine the type of the record set for ${tmpGroup.RecordSetAddress}.`); | ||
return false; | ||
} | ||
} | ||
catch (pError) | ||
{ | ||
this.log.error(`PICT View Metatemplate Helper getTabularRowData ${pGroupIndex} encountered an error: ${pError}`); | ||
return false; | ||
} | ||
} | ||
getGroup(pGroupIndex) | ||
{ | ||
if (isNaN(pGroupIndex)) | ||
{ | ||
this.log.warn(`PICT View Metatemplate Helper getGroup ${pGroupIndex} was expecting a number.`); | ||
return false; | ||
} | ||
if (pGroupIndex > this.sectionDefinition.Groups.length) | ||
{ | ||
this.log.warn(`PICT View Metatemplate Helper getGroup ${pGroupIndex} was out of bounds.`); | ||
return false; | ||
} | ||
return this.sectionDefinition.Groups[pGroupIndex]; | ||
} | ||
getRow(pGroupIndex, pRowIndex) | ||
{ | ||
let tmpGroup = this.getGroup(pGroupIndex); | ||
if (tmpGroup) | ||
{ | ||
if (isNaN(pRowIndex)) | ||
{ | ||
this.log.warn(`PICT View Metatemplate Helper getRow ${pRowIndex} was expecting a number.`); | ||
return false; | ||
} | ||
if (pRowIndex > tmpGroup.Rows.length) | ||
{ | ||
this.log.warn(`PICT View Metatemplate Helper getRow ${pRowIndex} was out of bounds.`); | ||
return false; | ||
} | ||
return tmpGroup.Rows[pRowIndex]; | ||
} | ||
else | ||
{ | ||
return false; | ||
} | ||
} | ||
getInput(pGroupIndex, pRowIndex, pInputIndex) | ||
{ | ||
let tmpRow = this.getRow(pGroupIndex, pRowIndex); | ||
if (tmpRow) | ||
{ | ||
if (isNaN(pInputIndex)) | ||
{ | ||
this.log.warn(`PICT View Metatemplate Helper getInput ${pInputIndex} was expecting a number.`); | ||
return false; | ||
} | ||
if (pInputIndex > tmpRow.Inputs.length) | ||
{ | ||
this.log.warn(`PICT View Metatemplate Helper getInput ${pInputIndex} was out of bounds.`); | ||
return false; | ||
} | ||
return tmpRow.Inputs[pInputIndex]; | ||
} | ||
else | ||
{ | ||
return false; | ||
} | ||
} | ||
tabularKeys (pDataObject) | ||
{ | ||
// Take an address (or a hash) and get the tabular keys for it | ||
let tmpDataObject = this.getMarshalDestinationObject; | ||
if (!pDataObject) | ||
{ | ||
return []; | ||
} | ||
if (Array.isArray(pDataObject)) | ||
{ | ||
return pDataObject.map((pValue, pIndex) => { return { Index: pIndex }; }); | ||
} | ||
else if (typeof(pDataObject) === 'object') | ||
{ | ||
return Object.keys(pDataObject); | ||
} | ||
else | ||
{ | ||
return []; | ||
} | ||
} | ||
get isPictSectionForm() | ||
@@ -375,2 +830,2 @@ { | ||
module.exports = PictSectionForm; | ||
module.exports = PictSectionFormView; |
@@ -10,5 +10,10 @@ // The container for all the Pict-Section-Form related code. | ||
// The metatemplate generator provider | ||
// (if we decide to abstract this out from the view class) | ||
// module.exports.PictFormMetatemplateGenerator = require('./Pict-Section-Form-MetatemplateGenerator.js'); | ||
// The metacontroller view | ||
module.exports.PictFormMetacontroller = require('./Pict-Form-Metacontroller.js'); | ||
// The application container | ||
module.exports.PictFormApplication = require('./Pict-Section-Form-Application.js'); |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
867389
2
276
22386
271
0
5
- Removedinformary@^2.0.21
- Removeddeep-object-diff@1.1.9(transitive)
- Removedinformary@2.0.21(transitive)
Updatedpict-view@^1.0.46