Change Log
All notable changes to this project will be documented in this file.
[0.5.8] - 2026-02-24
🔧 Changed
- SecOpt: Converted
getCenter,toHtml,getIndex,cfrom prototype methods to arrow function properties for reliablethisbinding - ReportHelpers.buildRepeatableSubsec(): Now passes loop index
itogetSecHtmlso section headers resolve correctly on every iteration - ReportHelpers.buildRepeatablePhotoSec(): Same fix — passes
itogetSecHtml - ReportHelpers.getPhotoLoc(): Simplified
.toFixed().toString()to.toFixed()(already returns a string)
🐛 Fix
- ReportHelpers.getSecHtml() / getSecTxt(): Fixed falsy check
!secOpt.indexthat treated index0as unset, breaking the first repeatable entry's section header. Replaced withsecOpt.index == null
[0.5.7] - 2026-02-18
✨ Added
- FulcrumHelpers.mkLocalFvDict(): Creates a local dictionary of
{form_value: data_name}for fields within a specified element or the entire form - FulcrumHelpers.repeatable2jrows(): Converts a repeatable field's value into an array of objects with data names as keys
- Excludes non-data field types (Label, Section, Repeatable, HyperlinkField)
- Supports excluding specific data names via
excparameter
- MerjentApp.dnDueDate: New property for due date field (default:
'due_date') - StatusMixins.active_resolved_pd(): Three-state status method: Active → Resolved → Past Due
- Uses
dnDueDateto determine if record is past due when not resolved
- Uses
🔧 Changed
- FieldHelpers (Mfld): Moved
Mfld.typesstatic array outside class asMfldTypesmodule constant for runtime compatibility - FieldHelpers.mkMfld(): Type is now copied directly to
_type, bypassing setter validation to support all Fulcrum field types - ReportHelpers.buildYNSection(): Enhanced to handle mixed field types
- YesNo fields render as checkboxes, other non-blank fields render as note divs
- Excludes non-data field types (Label, Section, PhotoField, Repeatable, etc.)
- Utils.arrUnique(): Changed from spread operator
[...new Set()]toArray.from(new Set())for broader runtime compatibility - MLoadRecords.updateLoadedRecords(): Added guard for when
dnRecLinkis not set, falls back to loading all records
🐛 Fix
- MLoadRecords.processRecords(): Fixed to pass
this.appRecords(processed records) instead of rawrecordstoenterLoadedDatacallback
📚 Document
- ReportHelpers.buildTableHeaders(): Fixed JSDoc param type from
*tostring[] - ReportHelpers.formRequestSchema(): Added
@todonote about using QUERY API instead of GET request - README.md: Updated changelog section to show latest entries
- New tutorial:
08_mapp-cheat-sheet.md- MerjentApp configuration cheat sheet with all properties in categorized tables
[0.5.6] - 2026-01-22
✨ Added
- PermissionMixins: New individual permission methods extracted from
standardUpdatestandardAdmin()- Admin restrictions: all fields editable unless complete lock, status always editablestandardEditor()- Editor restrictions: fields editable unless complete lock, respects disableLocationEditstandardUser()- User restrictions: fields editable unless complete lock, respects disableLocationEditstandardViewer()- Viewer restrictions: all fields read-only, location and status locked
- MerjentApp.dnAutoName: New property to auto-populate a field with user's full name on new record creation
- ReportTemplateBlocks.sideBar: New HTML template for sidebar layout
🔧 Changed
- DefaultTemplate.start(): Restructured event handlers
disableNewRecordCreationnow runs onload-recordinstead ofnew-recordevent- Added auto-population of
dnAutoNamefield onnew-recordevent
- Utils.fVal(): Improved handling of choice fields with "other" values
- Now filters out duplicate values when "other" option matches a choice_value
- Formats output as "choice1, choice2, other_value" without duplicates
🐛 Fix
- PermissionMixins: Fixed arrow function
thisbinding issue- Converted
standardAdmin,standardEditor,standardUser,standardViewerfrom arrow functions to regular functions - Arrow functions cannot be rebound with
.bind(), causingthisto be undefined when called fromstandardUpdate
- Converted
📚 Document
- JSDoc cleanup: Removed redundant
@methodtags from MerjentApp stub methods - New permission methods: Added JSDoc for all 4 new permission methods in both PermissionMixins and MerjentApp stubs
[0.5.5] - 2026-01-13
♻️ Refactored
- Build system: Completely refactored
buildPkg.ps1to use native PowerShell- Removed
rexreplacenpm dependency - Version/timestamp injection now uses PowerShell regex replacement
- Footer injection uses native string operations
- Simplified export pattern fixing with native PowerShell
- Removed
🔧 Changed
- Report assets centralized: Moved report styles and templates to
merjent-fulcrum-coresibling repo- CSS files (
MJNT_Report.css,MJNT_Charts.css,MJNT_Themes.css) →merjent-fulcrum-core/report-style/ - HTML boilerplates →
merjent-fulcrum-core/report-boilerplates/ - Build now generates
ReportTemplateBlocks.jsfrom core templates automatically
- CSS files (
📚 Document
- MerjentApp JSDoc: Major documentation improvements for template/mixin architecture
MerjentApp.js: Added architecture overview, file structure diagram, mixin table, and binding tableDefaultTemplate.js: Added mixin bindings table, composite methods list, extension hooks- All mixin files: Added usage examples,
@seecross-references, clearer@namespacedocs
- Tutorials updated: References updated for merjent-fulcrum-core structure
01_overview.md,02_mtools.md,04_pdf-reports.md,06_merjent-dev.md
🗑️ Removed
- Build artifacts: Deleted files now managed by merjent-fulcrum-core
build/DataEventsContents.js,build/version.txt,build/footer*.txtbuild/copyButtonScript.html,build/copyButtonStyle.html
- Report style directory: Entire
report-style/moved to merjent-fulcrum-core - Working files:
src/Mtools/ReportTemplateBlocks_WORKING.js(no longer needed) - Root CLAUDE.md: Consolidated into
.claude/CLAUDE.md - docs/ from git tracking: JSDoc output now in
.gitignore(generated locally by build)
[0.5.4] - 2025-12-09
✨ Added
- FulcrumHelpers.clearRLAutoPops(): New method to clear Record-Link auto-populate fields
- Clears all auto-populate destination fields when a record-link field is emptied
- Use with
ON('change', 'record_link_field', clearRLAutoPops)in data events
🔧 Changed
- ReportTemplateBlocks: Improved Yes/No checkbox template layout
ynTemplate()now wraps checkbox groups inflex-rowcontainer with individualchecksdivsynnaTemplate()updated with same flex-row pattern for Yes/No/NA options- Better visual grouping of checkbox-label pairs
- MJNT_Report.css: Enhanced
.flex-rowstyling- Added
flex-wrap: wrapfor better responsive behavior - Added
column-gap: 8pxfor consistent spacing between checkbox groups
- Added
📚 Document
- FulcrumHelpers.digElement(): Fixed JSDoc - collector parameter is
object, notArray
[0.5.3] - 2025-11-24
✨ Added
- MLoadRecords enhancements: New properties and methods for record link management
sortOrderproperty - Allows specifying sort order for loaded records (e.g.,[['report_id', 'dsc']])dnRefreshRLproperty - Data name of record link field to refresh on changerefreshRecordLink()method - Refreshes record link field with updated recordsprocessRefreshRL()method - Processes refreshed record link recordsclearAutoFields()method - Clears auto-populated fields when record link is clearedaddOnRefreshRL()callback - Hook for custom logic after record link refresh
🔧 Changed
- MLoadRecords: Improved duplicate check and record processing
selfDupCheck()now uses "equal_to" operator instead of "contains" for more precise matchingprocessSelfDupCheck()now usesfv2DnRows()for proper field value conversionprocessForm()now handlesdnRefreshRLrefresh flow separatelyfilterTemplate()order parameter handling simplified
🐛 Fix
- DataEventHelpers.updateMStates(): Fixed to return empty array
[]instead ofnullwhen no choice_values, preventing potential null reference errors
📚 Document
- Python tools migration: Updated documentation to reflect Python tools moved to separate repository
- Updated
tutorials/01_overview.mdwith note about merjent-fulcrum-pyTools repository - Removed
tutorials/05_python-tools.md(content moved to pyTools repo) - Added PowerShell runner script references for calling Python tools
- Updated
[0.5.2] - 2025-11-13
🐛 Fix
- ⚠️ CRITICAL FIX - Utils.isDateStr(): Fixed false positive date detection for non-date strings
- JavaScript's
Dateconstructor is extremely permissive and was parsing strings like "Access to STR 1" as valid dates (January 1, 2001) - Added pattern-based validation to check if strings match common date formats before attempting to parse
- Now validates against patterns for ISO dates, US dates (MM/DD/YYYY), month names (January 15, 2024), and datetime formats
- Prevents false positives while maintaining support for all legitimate date string formats
- JavaScript's
- Utils.fVal(): Minor refinement to default value handling (changed
??to||operator)
🔧 Changed
- Enhanced JSDoc documentation for
Utils.isDateStr()to clarify validation behavior
[0.5.0] - 2025-11-10
🔥 Breaking Changes
- Module naming: Renamed entry point files for clarity
src/dataEventMtools.js→src/MtoolsDataEvents.jssrc/merjentAppModule.js→src/MtoolsMerjentApp.jssrc/reportMtools.js→src/MtoolsReports.jssrc/utilsMtools.js→src/MtoolsUtils.js
- Python tools architecture: Complete restructure of tools directory
- Removed
loopMtoolsApps.pymodule (replaced bycore/app_looper.py) - Moved
helpers.py→lib/utils.py(breaking import paths) - Moved
fulcrum_helpers.py→lib/fulcrum_helpers.py(breaking import paths)
- Removed
♻️ Refactored
- MerjentApp architecture: Converted to mixin-based composition pattern
- Deleted monolithic method files:
AppTemplates.js,DefaultMethods.js,PermissionMethods.js,StatusMethods.js,TemplateMethods.js - Created new
src/mApp/mixins/directory with modular mixins:LockingMixins.js- Field locking functionalityPermissionMixins.js- User permission handlingPhotoMixins.js- Photo-related operationsStatusMixins.js- Record status management
- Created
src/mApp/templates/DefaultTemplate.jsfor app templates - Updated
src/mApp/merjentApp.jsto use mixin pattern
- Deleted monolithic method files:
- Python tools architecture: Complete restructure into modular framework
- Created
tools/core/directory for infrastructure:base_tool.py- Abstract base class for all batch operation toolsfulcrum_client.py- Centralized Fulcrum API client singleton with better token loadingapp_looper.py- Reusable app/template iteration infrastructure
- Created
tools/lib/directory for shared utilities:utils.py(formerly helpers.py) - General utilities with new functionsfulcrum_helpers.py- Fulcrum-specific utilities
- Refactored existing tools to use new framework:
findMtoolFunctions.py- Updated to use BaseMToolTool classupdateMtools.py- Updated to use BaseMToolTool class
- Created
✨ Added
- Python utilities: New text parsing functions in
lib/utils.pyfind_matching_bracket()- Find closing bracket position using stack-based algorithmextract_bracket_content()- Extract content between matching brackets with full position info
- Documentation: New comprehensive tutorials
tutorials/05_python-tools.md- Python tools usage guidetutorials/06_merjent-dev.md- Merjent-specific development guidetutorials/07_general-dev.md- General development workflowstools/README.md- Complete architecture documentation for Python tools frameworktools/EXAMPLE_export_data_events.py- Example tool implementation
- MerjentApp features: New mixin-based functionality
PhotoDirHandlerclass - Enhanced photo directory management
🔧 Changed
- Fulcrum API client: Enhanced token loading in
fulcrum_client.py- Now supports flexible token file paths via optional parameter
- Improved error handling for missing token files
- Better default path resolution (../../mikel-fulcrum-api.txt)
- Added token validation at module load time
- App looper: Enhanced error handling in
app_looper.py- Better HTTP error reporting for template fetching (shows status code and response)
- Added JSON decode error handling with informative messages
- Added validation for empty API tokens
- Build process: Updated build scripts
- Modified
build/buildPkg.ps1for new module names - Updated
build/version.txtto 0.5.0
- Modified
📚 Document
- Massive tutorial expansion: Added ~2,700 lines of documentation
tutorials/01_overview.md- Enhanced with new architecture overviewtutorials/02_mtools.md- Expanded with detailed API documentationtutorials/03_mapp.md- Updated for mixin-based architecturetutorials/04_pdf-reports.md- Enhanced with more examples
- Updated JSDOC: Regenerated all HTML documentation
- New mixin documentation files (LockingMixins, PermissionMixins, PhotoMixins, StatusMixins)
- Updated module documentation for renamed files
- New class documentation (Mfld, MfldColl, SecOpt, PhotoDirHandler)
- Removed deprecated documentation files
- README.md: Major update with comprehensive changes
- Updated architecture documentation
- Added Python tools section with usage examples
- Enhanced build instructions
🐛 Fix
- Fixed Fulcrum client initialization in app_looper.py (token now properly loaded from file)
- Improved error handling for missing API tokens with clear error messages
- Better validation in updateMtools.py for search/replace edge cases
🗑️ Removed
- Deprecated Python files:
tools/_deprecated_r_between_brackets.py- Obsolete bracket parsing (replaced by utils.py functions)tools/loopMtoolsApps.py- Replaced by modular frameworktools/helpers.py- Moved to lib/utils.pytools/fulcrum_helpers.py- Moved to lib/fulcrum_helpers.py
- Legacy MerjentApp files (replaced by mixins):
src/mApp/AppTemplates.jssrc/mApp/DefaultMethods.jssrc/mApp/PermissionMethods.jssrc/mApp/StatusMethods.jssrc/mApp/TemplateMethods.js
- Documentation cleanup:
tutorials/05_other-dev.md- Replaced by more specific tutorials (05, 06, 07)tutorials/Mtools.png- Moved to docs/tutorials/tutorials.json- No longer needed
📝 Migration Guide
For Python Tools Users:
Old import pattern:
import helpers as H
import fulcrum_helpers as FH
import loopMtoolsApps as LMA
New import pattern:
from lib import utils as U
from lib import fulcrum_helpers as FH
from core.app_looper import loop_apps
from core.base_tool import BaseMToolTool
Old tool pattern:
def handleApp(form, templateNames, replaceDict):
# ... logic ...
return results
results = LMA.loopApps(records, recordsLen, handleApp, replaceDict)
New tool pattern:
class MyTool(BaseMToolTool):
def handle_app(self, form, template_names, context):
# ... logic ...
return results
if __name__ == '__main__':
MyTool().run()
See tools/README.md and tools/EXAMPLE_export_data_events.py for complete examples.
[0.4.9] - 2025-11-03
🔥 Breaking Changes
- Renamed
src/Mtools/Helpers.jstosrc/Mtools/Utils.js - Renamed
src/helpersMtools.jstosrc/utilsMtools.js(exports changed fromHtoU) SecOpt.html()method renamed toSecOpt.toHtml()
♻️ Refactored
- ReportTemplateBlocks converted to static class with static methods
- All HTML template strings moved to static methods for better code organization
- Enables template string flattening during build process
- ReportHelpers refactored to use ReportTemplateBlocks static methods instead of inline HTML strings
- Changed
formatValtofValthroughout - Changed
this.isInstance(secOpt, SecOpt)tosecOpt instanceof SecOpt
✨ Added
- New
buildBullets()method in ReportHelpers to convert paragraphs to HTML bullet lists - Added
Convert-JSMultilineStringsPowerShell function to build script for flattening template literals - Added custom CSS styling for bullet lists (ul/li) in MJNT_Report.css
- Added terser configuration to package.json with class/function name preservation
🔧 Changed
- Build process now uses
npxfor rexreplace and terser commands - Build process now flattens ReportTemplateBlocks_WORKING.js to ReportTemplateBlocks.js
- Moved all dependencies to devDependencies in package.json
- Updated rexreplace from 7.1.11 to ^7.1.13
📚 Document
- Updated Merjent App Tutorial with information about changing field names and data names
- Added snippet layout for data events
- Updated CHANGELOG with complete git history from version 0.3.0
[0.4.8] - 2025-10-27
📚 Document
- Adjusted some JSDOC inaccuracies
✨ Added
- Added restrictNewRecords property to MerjentApp
[0.4.7] - 2025-10-27
- Many updates to documentation
- Large update to begin tutorial section
- JSDOC updated throughout for more clear documentation in compiled JSDOC
- Changelog started
- MloadRecords updated to reflect changes in Fulcrum LOADRECORDS expression
🔥 Breaking Change
- For clarity and naming consistency the following methods had names changed.
- check4PhotoCaps -> photoCheck4Caps
- checkPhotoCapLen -> photoCheckCapLen
- convertFV2DN -> fv2DnRows
- getFldSummaryObj -> makeDnsRow
- getUserInit -> userInit
- obj2Summary -> rows2Summary
- rep2Obj -> makeRepRows
- setLatLon -> popLatLon
- addCustomPhotoFlds -> photoAddCustomFields
- addItemNo -> photoAddItemNo
- buildPhotoObjFromRows -> photoObjFromRows
- getChoices -> choiceListRequest
- getDesc -> buildDescription
- getFormCell -> buildDefaultCell
- getFormFlds -> formRequestSchema
- getFormRows -> buildDefaultRows
- getPhotoGrid1x3 -> buildPhotoGrid1x3
- getPhotoLoc -> photoRequestMeta
- getPhotos -> photosRequest
- getPhotoWraped -> buildPhotoWrapper
- getRecords -> recordsRequest
- getRepRecs -> repRequestRecords
- getRLrecords -> requestRLrecords
- getSigTime -> buildSigTime
- getSimpleCell -> buildSimpleCell
- getSimpleRows -> buildSimpleRows
- getTaggedPhotos -> photosRequestTagged
- makeMfldsFromFormJSON -> schema2Mflds
- parseObj2Div -> rows2Divs
- remPhotoPre -> photoRemTag
- formatVal -> fVal
🔧 Changed
- MloadRecords
- Class updated to reflect changes to Fulcrum LOADRECORDS expression.
- Allows for query filter of records
- Class updated to reflect changes to Fulcrum LOADRECORDS expression.
♻️ Refactor
- getRepDn moved to FulcrumHelpers class
- makeDnsRow() refactored
- digElement()/digElements() refactored
- makeFvDict() refactored
- Template Strings for PDF report generation moved to separate class: ReportTemplateBlocks
📚 Document
- Split tutorial into tree
- Added component diagram
- Added report snippetss
- JSDOC summary tags added to all methods
[0.4.5] - 2025-09-29
🔧 Changed
- Updated buildPkg.ps1 to add copy button to tutorials
[0.4.5] - 2025-09-25
📚 Document
- Updated read-me
[0.4.5] - 2025-09-20
🔧 Changed
- Updated MloadRecs class to include a separate initiator method. One for getting form field schema on load and one to get field schema and immediately load all recs on load.
♻️ Refactor
- Converted Mfld, MfldColl and SecOpt to proper class format
📚 Document
- Updated JSDOC comments throughout
- Updated read-me
[0.4.4] - 2025-09-15
- Dev branch Git test
[0.4.4] - 2025-09-11
- Testing Git dev branch pull
🐛 Fix
- Bugfixes in SecOpts Class
[0.4.4] - 2025-09-09
♻️ Refactor
- Replaced most uses of .forEach method with for...of...
📚 Document
- Updated readme.md
✨ Added
- Created SecOpts class to replace object used in parameters of ReportHelpers methods
- Added digElements method to FulcrumHelpers
[0.4.3] - 2025-08-27
♻️ Refactor
- Reorganized file structure
[0.4.3] - 2025-08-20
✨ Added
- Added .disableNewRecordCreation property to mApp
- Added .defaultPermissionLevel property to mApp
- Added updateMStates: copies state choice from one choice field to another
- Added report mFld option: -hn for hide null
- Added isMerjentEmail method to check if current user is Merjent employee
- MLoadRecs class was added
- MfldColl, Mfld, and SecOpt classes were exposed in Report Mtools
🐛 Fix
- Fixed bug with mFld not printing choice_values in certain situations
- Helpers class was cleaned up and various small bugs fixed
🔥 Breaking Changes
- The following method names were changed:
- remVarr -> arrRem
- getObjs -> rowsFind
- countArrItems -> arrCountItems
- sortNum -> arrSort
- reverseNum -> arrReverse
- objArrSort -> rowsSort
- dupList -> arrListDups
- toTitleCase -> dn2Title
- capitalizeWord -> strProper
- addDays -> dtAddDays
- daysDiff -> dtDaysDiff
[0.4.0] - 2025-06-05
✨ Added
- Added JSDOC documentation
- Added Report HTML Boiler Plates to Info
- Added optional custom css property to ReportHelpers.buildRepeatableSubsec() and ReportHelpers.getSecHtml()
🔧 Changed
- Updated Helpers.isBlank()
- Updated ReportHelpers.getFormRows() to handle excluded fields (ie. exclude field used for subsection title with ReportHelpers.buildRepeatableSubsec())
- Replaced string concatenation with template strings in RequestHelpers and other classes
[0.3.9] - 2025-05-01
🔧 Changed
- Updated updateMtools.py to include pushing updates to report template script as well as data events
[0.3.9] - 2025-04-30
✨ Added
- Updated MerjentApp enterReportID() to include prefix
- Added getRLrecords() to ReportHelpers
- Added addItemNo() to enumerate photos
- Added buildPhotoObjFromRows() to build photoObj from query response
🐛 Fix
- Fixed missing timestamp in enterReportID()
[0.3.8] - 2025-03-28
🐛 Fix
- Fixed still more bugs in isBlank()
♻️ Refactor
- Adjusted MJNT_Report.css style
- Modified MerjentApp to turn off updateStatus if dnSubmit = null
[0.3.8] - 2025-03-27
🐛 Fix
- Fixed more bugs in isBlank()
- Adjusted MJNT_Report.css style for photo width to fit 3 photos per page
[0.3.8] - 2025-03-25
🐛 Fix
- Fixed isBlank() method
🔧 Changed
- Updated ReportHelpers and MNJT_Report.css photo grid styling
[0.3.8] - 2025-03-23
✨ Added
- Added minimum jsdoc comments
- Merged Mtools and MerjentApp classes in module.exports
🐛 Fix
- Updated Helpers.isBlank() to check for empty objects and arrays
♻️ Refactor
- FulcrumHelpers.check4PhotoCaps() returns boolean as well as ALERT
- FulcrumHelpers.photoLandscape() returns boolean as well as ALERT
- FulcrumHelpers.photoLandscape() updated properties to be more readable
[0.3.7] - 2025-03-22
♻️ Refactor
- Changed module and class names to read more easily and re-organized package structure
📚 Document
- Started adding jsdoc comments
- Added foodoc jsdoc template
[0.3.6] - 2025-03-18
♻️ Refactor
- Changed dir structure src/Mapp and src/Mtools
- Added src/jsdoc.json for JSDOC config
🐛 Fix
- Fixed buildPkg.ps1 to replace version in package.json
[0.3.5] - 2025-03-13
🗑️ Removed
- Removed node_modules
[0.3.5] - 2025-03-13
✨ Added
- Added DataEventBoilerPlates Class
- With get current weather, fire danger and PLSS
- Added function for report id generation
- Added functions to convert repeatables and record links (from LOADRECORD) to objects
[0.3.3] - 2025-01-10
♻️ Refactor
- Merjent App is now es2015 class
[0.3.0] - 2025-01-03
✨ Added
- Initial Commit