diff --git a/app/admin/incFunctions.php b/app/admin/incFunctions.php index 86a4613..12256bf 100644 --- a/app/admin/incFunctions.php +++ b/app/admin/incFunctions.php @@ -40,7 +40,7 @@ html_attr_tags_ok($str) -- same as html_attr, but allowing HTML tags Notification() -- class for providing a standardized html notifications functionality sendmail($mail) -- sends an email using PHPMailer as specified in the assoc array $mail( ['to', 'name', 'subject', 'message', 'debug'] ) and returns true on success or an error message on failure - safe_html($str, $noBr = false) -- sanitize HTML strings, and apply nl2br() to non-HTML ones (unless optional 2nd param is passed as true) + safe_html($str, $preserveNewLines = false) -- sanitize HTML strings, and convert new lines (\n) to breaks (
) for non-HTML ones (unless optional 2nd param is passed as true) get_tables_info($skip_authentication = false) -- retrieves table properties as a 2D assoc array ['table_name' => ['prop1' => 'val', ..], ..] getLoggedMemberID() -- returns memberID of logged member. If no login, returns anonymous memberID getLoggedGroupID() -- returns groupID of logged member, or anonymous groupID @@ -187,7 +187,7 @@ function get_tables_info($skip_authentication = false) { return $accessible_tables; } ######################################################### - function getTableList($skip_authentication = false) { + function getTableList($skip_authentication = false, $include_internal_tables = false) { $arrAccessTables = []; $arrTables = [ /* 'table_name' => ['table caption', 'homepage description', 'icon', 'table group name'] */ @@ -202,7 +202,31 @@ function getTableList($skip_authentication = false) { 'units' => ['Units', 'Listing of all units, its details and current status.', 'resources/table_icons/change_password.png', 'Assets/Setup'], 'unit_photos' => ['Unit photos', '', 'resources/table_icons/camera_link.png', 'Assets/Setup'], ]; - if($skip_authentication || getLoggedAdmin()) return $arrTables; + + if($skip_authentication || getLoggedAdmin()) { + if($include_internal_tables) { + // merge internal tables with user tables + $internalIcon = 'resources/images/appgini-icon.png'; + $internalTables = [ + 'appgini_csv_import_jobs', + 'appgini_query_log', + 'membership_cache', + 'membership_grouppermissions', + 'membership_groups', + 'membership_userpermissions', + 'membership_userrecords', + 'membership_users', + 'membership_usersessions', + ]; + + // format internal tables as 'tn' => ['tn', '', icon, ''] and merge with user tables + $arrTables = array_merge($arrTables, array_combine( + $internalTables, + array_map(function($tn) use($internalIcon) { return [$tn, '', $internalIcon, '']; }, $internalTables) + )); + } + return $arrTables; + } foreach($arrTables as $tn => $tc) { $arrPerm = getTablePermissions($tn); @@ -436,27 +460,7 @@ function createQueryLogTable() { static $created = false; if($created) return true; - $o = [ - 'silentErrors' => true, - 'noSlowQueryLog' => true, - 'noErrorQueryLog' => true - ]; - - sql("CREATE TABLE IF NOT EXISTS `appgini_query_log` ( - `datetime` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, - `statement` LONGTEXT, - `duration` DECIMAL(10,2) UNSIGNED DEFAULT 0.0, - `error` TEXT, - `memberID` VARCHAR(200), - `uri` VARCHAR(200) - ) CHARSET " . mysql_charset, $o); - - // check if table created - //$o2 = $o; - //$o2['error'] = ''; - //sql("SELECT COUNT(1) FROM 'appgini_query_log'", $o2); - - //$created = empty($o2['error']); + createTableIfNotExists('appgini_query_log'); $created = true; return $created; @@ -913,8 +917,9 @@ function get_table_keys($tn) { return $keys; } ######################################################################## - function get_table_fields($tn = null) { - static $schema = null; + function get_table_fields($tn = null, $include_internal_tables = false) { + static $schema = null, $internalTables = null; + if($schema === null) { /* application schema as created in AppGini */ $schema = [ @@ -1702,11 +1707,101 @@ function get_table_fields($tn = null) { ], ], ]; + + $internalTablesSimple = [ + 'appgini_csv_import_jobs' => [ + 'id' => "VARCHAR(40) NOT NULL PRIMARY KEY", + 'memberID' => "VARCHAR(100) NOT NULL", + 'config' => "TEXT", + 'insert_ts' => "INT", + 'last_update_ts' => "INT", + 'total' => "INT DEFAULT '99999999'", + 'done' => "INT DEFAULT '0'", + ], + 'appgini_query_log' => [ + 'datetime' => "TIMESTAMP DEFAULT CURRENT_TIMESTAMP", + 'statement' => "LONGTEXT", + 'duration' => "DECIMAL(10,2) UNSIGNED DEFAULT '0.00'", + 'error' => "TEXT", + 'memberID' => "VARCHAR(200)", + 'uri' => "VARCHAR(200)", + ], + 'membership_cache' => [ + 'request' => "VARCHAR(100) NOT NULL PRIMARY KEY", + 'request_ts' => "INT", + 'response' => "LONGTEXT", + ], + 'membership_grouppermissions' => [ + 'permissionID' => "INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT", + 'groupID' => "INT UNSIGNED", + 'tableName' => "VARCHAR(100)", + 'allowInsert' => "TINYINT NOT NULL DEFAULT '0'", + 'allowView' => "TINYINT NOT NULL DEFAULT '0'", + 'allowEdit' => "TINYINT NOT NULL DEFAULT '0'", + 'allowDelete' => "TINYINT NOT NULL DEFAULT '0'", + ], + 'membership_groups' => [ + 'groupID' => "INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT", + 'name' => "VARCHAR(100) NOT NULL UNIQUE", + 'description' => "TEXT", + 'allowSignup' => "TINYINT", + 'needsApproval' => "TINYINT", + 'allowCSVImport' => "TINYINT NOT NULL DEFAULT '0'", + ], + 'membership_userpermissions' => [ + 'permissionID' => "INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT", + 'memberID' => "VARCHAR(100) NOT NULL", + 'tableName' => "VARCHAR(100)", + 'allowInsert' => "TINYINT NOT NULL DEFAULT '0'", + 'allowView' => "TINYINT NOT NULL DEFAULT '0'", + 'allowEdit' => "TINYINT NOT NULL DEFAULT '0'", + 'allowDelete' => "TINYINT NOT NULL DEFAULT '0'", + ], + 'membership_userrecords' => [ + 'recID' => "BIGINT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT", + 'tableName' => "VARCHAR(100)", + 'pkValue' => "VARCHAR(255)", + 'memberID' => "VARCHAR(100)", + 'dateAdded' => "BIGINT UNSIGNED", + 'dateUpdated' => "BIGINT UNSIGNED", + 'groupID' => "INT UNSIGNED", + ], + 'membership_users' => [ + 'memberID' => "VARCHAR(100) NOT NULL PRIMARY KEY", + 'passMD5' => "VARCHAR(255)", + 'email' => "VARCHAR(100)", + 'signupDate' => "DATE", + 'groupID' => "INT UNSIGNED", + 'isBanned' => "TINYINT", + 'isApproved' => "TINYINT", + 'custom1' => "TEXT", + 'custom2' => "TEXT", + 'custom3' => "TEXT", + 'custom4' => "TEXT", + 'comments' => "TEXT", + 'pass_reset_key' => "VARCHAR(100)", + 'pass_reset_expiry' => "INT UNSIGNED", + 'flags' => "TEXT", + 'allowCSVImport' => "TINYINT NOT NULL DEFAULT '0'", + 'data' => "LONGTEXT", + ] + ]; + + $internalTables = []; + // add 'appgini' and 'info' keys to internal tables fields + foreach($internalTablesSimple as $tableName => $fields) { + $internalTables[$tableName] = []; + foreach($fields as $fn => $fd) { + $internalTables[$tableName][$fn] = ['appgini' => $fd, 'info' => ['caption' => $fn, 'description' => '']]; + } + } } - if($tn === null) return $schema; + if($tn === null && !$include_internal_tables) return $schema; - return isset($schema[$tn]) ? $schema[$tn] : []; + if($tn === null) return array_merge($schema, $internalTables); + + return $schema[$tn] ?? $internalTables[$tn] ?? []; } ######################################################################## function updateField($tn, $fn, $dataType, $notNull = false, $default = null, $extra = null) { @@ -1810,21 +1905,27 @@ function addIndex($tn, $fields, $unique = false) { } ######################################################################## - function update_membership_groups() { - $tn = 'membership_groups'; + function createTableIfNotExists($tn, $return_schema_without_executing = false) { + $schema = get_table_fields($tn); + if(!$schema) return false; + + $create_sql = "CREATE TABLE IF NOT EXISTS `{$tn}` ("; + foreach($schema as $fn => $fd) { + $create_sql .= "\n `{$fn}` {$fd['appgini']}, "; + } + $create_sql = rtrim($create_sql, ', ') . "\n) CHARSET " . mysql_charset; + $create_sql = trim($create_sql); + + if($return_schema_without_executing) return $create_sql; + $eo = ['silentErrors' => true, 'noErrorQueryLog' => true]; + sql($create_sql, $eo); + } - sql( - "CREATE TABLE IF NOT EXISTS `{$tn}` ( - `groupID` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `name` varchar(100) NOT NULL, - `description` TEXT, - `allowSignup` TINYINT, - `needsApproval` TINYINT, - `allowCSVImport` TINYINT NOT NULL DEFAULT '0', - PRIMARY KEY (`groupID`) - ) CHARSET " . mysql_charset, - $eo); + ######################################################################## + function update_membership_groups() { + $tn = 'membership_groups'; + createTableIfNotExists($tn); updateField($tn, 'name', 'VARCHAR(100)', true); addIndex($tn, 'name', true); @@ -1833,31 +1934,7 @@ function update_membership_groups() { ######################################################################## function update_membership_users() { $tn = 'membership_users'; - $eo = ['silentErrors' => true, 'noErrorQueryLog' => true]; - - sql( - "CREATE TABLE IF NOT EXISTS `{$tn}` ( - `memberID` VARCHAR(100) NOT NULL, - `passMD5` VARCHAR(255), - `email` VARCHAR(100), - `signupDate` DATE, - `groupID` INT UNSIGNED, - `isBanned` TINYINT, - `isApproved` TINYINT, - `custom1` TEXT, - `custom2` TEXT, - `custom3` TEXT, - `custom4` TEXT, - `comments` TEXT, - `pass_reset_key` VARCHAR(100), - `pass_reset_expiry` INT UNSIGNED, - `flags` TEXT, - `allowCSVImport` TINYINT NOT NULL DEFAULT '0', - `data` LONGTEXT, - PRIMARY KEY (`memberID`), - INDEX `groupID` (`groupID`) - ) CHARSET " . mysql_charset, - $eo); + createTableIfNotExists($tn); updateField($tn, 'pass_reset_key', 'VARCHAR(100)'); updateField($tn, 'pass_reset_expiry', 'INT UNSIGNED'); @@ -1871,25 +1948,7 @@ function update_membership_users() { ######################################################################## function update_membership_userrecords() { $tn = 'membership_userrecords'; - $eo = ['silentErrors' => true, 'noErrorQueryLog' => true]; - - sql( - "CREATE TABLE IF NOT EXISTS `{$tn}` ( - `recID` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, - `tableName` VARCHAR(100), - `pkValue` VARCHAR(255), - `memberID` VARCHAR(100), - `dateAdded` BIGINT UNSIGNED, - `dateUpdated` BIGINT UNSIGNED, - `groupID` INT UNSIGNED, - PRIMARY KEY (`recID`), - UNIQUE INDEX `tableName_pkValue` (`tableName`, `pkValue`(100)), - INDEX `pkValue` (`pkValue`), - INDEX `tableName` (`tableName`), - INDEX `memberID` (`memberID`), - INDEX `groupID` (`groupID`) - ) CHARSET " . mysql_charset, - $eo); + createTableIfNotExists($tn); addIndex($tn, ['tableName' => null, 'pkValue' => 100], true); addIndex($tn, 'pkValue'); @@ -1901,40 +1960,14 @@ function update_membership_userrecords() { ######################################################################## function update_membership_grouppermissions() { $tn = 'membership_grouppermissions'; - $eo = ['silentErrors' => true, 'noErrorQueryLog' => true]; - - sql( - "CREATE TABLE IF NOT EXISTS `{$tn}` ( - `permissionID` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `groupID` INT UNSIGNED, - `tableName` VARCHAR(100), - `allowInsert` TINYINT NOT NULL DEFAULT '0', - `allowView` TINYINT NOT NULL DEFAULT '0', - `allowEdit` TINYINT NOT NULL DEFAULT '0', - `allowDelete` TINYINT NOT NULL DEFAULT '0', - PRIMARY KEY (`permissionID`) - ) CHARSET " . mysql_charset, - $eo); + createTableIfNotExists($tn); addIndex($tn, ['groupID', 'tableName'], true); } ######################################################################## function update_membership_userpermissions() { $tn = 'membership_userpermissions'; - $eo = ['silentErrors' => true, 'noErrorQueryLog' => true]; - - sql( - "CREATE TABLE IF NOT EXISTS `{$tn}` ( - `permissionID` INT UNSIGNED NOT NULL AUTO_INCREMENT, - `memberID` VARCHAR(100) NOT NULL, - `tableName` VARCHAR(100), - `allowInsert` TINYINT NOT NULL DEFAULT '0', - `allowView` TINYINT NOT NULL DEFAULT '0', - `allowEdit` TINYINT NOT NULL DEFAULT '0', - `allowDelete` TINYINT NOT NULL DEFAULT '0', - PRIMARY KEY (`permissionID`) - ) CHARSET " . mysql_charset, - $eo); + createTableIfNotExists($tn); updateField($tn, 'memberID', 'VARCHAR(100)', true); addIndex($tn, ['memberID', 'tableName'], true); @@ -1942,10 +1975,13 @@ function update_membership_userpermissions() { ######################################################################## function update_membership_usersessions() { $tn = 'membership_usersessions'; + + // not using createTableIfNotExists() here because we need to add a composite unique index, + // which is not supported by that function yet $eo = ['silentErrors' => true, 'noErrorQueryLog' => true]; sql( - "CREATE TABLE IF NOT EXISTS `membership_usersessions` ( + "CREATE TABLE IF NOT EXISTS `$tn` ( `memberID` VARCHAR(100) NOT NULL, `token` VARCHAR(100) NOT NULL, `agent` VARCHAR(100) NOT NULL, @@ -1959,16 +1995,7 @@ function update_membership_usersessions() { ######################################################################## function update_membership_cache() { $tn = 'membership_cache'; - $eo = ['silentErrors' => true, 'noErrorQueryLog' => true]; - - sql( - "CREATE TABLE IF NOT EXISTS `membership_cache` ( - `request` VARCHAR(100) NOT NULL, - `request_ts` INT, - `response` LONGTEXT, - PRIMARY KEY (`request`) - ) CHARSET " . mysql_charset, - $eo); + createTableIfNotExists($tn); updateField($tn, 'response', 'LONGTEXT'); } @@ -2461,9 +2488,9 @@ function sendmail($mail) { return true; } ######################################################### - function safe_html($str, $noBr = false) { + function safe_html($str, $preserveNewLines = false) { /* if $str has no HTML tags, apply nl2br */ - if($str == strip_tags($str)) return $noBr ? $str : nl2br($str); + if($str == strip_tags($str)) return $preserveNewLines ? $str : nl2br($str); $hc = new CI_Input(datalist_db_encoding); $str = $hc->xss_clean(bgStyleToClass($str)); @@ -2819,7 +2846,7 @@ function to_utf8($str) { * @brief converts string from utf8 to app-configured encoding * * @param [in] $str string to convert from utf8 - * @return utf8-decoded string + * @return string utf8-decoded string * * @details if the constant 'datalist_db_encoding' is not defined, original string is returned */ @@ -3153,6 +3180,12 @@ function parseTemplate($template) { $template = str_replace(['', ''], ['{MaxSize}', '{FileTypes}'], $template); $template = str_replace('<%%BASE_UPLOAD_PATH%%>', getUploadDir(''), $template); + // strip lines that only contain HTML comments + $template = preg_replace('/^\s*\s*$/m', '', $template); + + // strip lines that only contain whitespace + $template = preg_replace('/^\s*$/m', '', $template); + return $template; } ######################################################### diff --git a/app/admin/pageRebuildFields.php b/app/admin/pageRebuildFields.php index f327f1d..5925f88 100644 --- a/app/admin/pageRebuildFields.php +++ b/app/admin/pageRebuildFields.php @@ -14,10 +14,11 @@ $schema: [ tablename => [ fieldname => [ appgini => '...', 'db' => '...'], ... ], ... ] */ - /* application schema as created in AppGini */ - $schema = get_table_fields(); + /* application schema as created in AppGini, including internal tables */ + $schema = get_table_fields(null, true); - $table_captions = getTableList(); + /* list of all tables in the database, including internal tables */ + $table_captions = getTableList(true, true); /* function for preparing field definition for comparison */ function prepare_def($def) { @@ -46,6 +47,9 @@ function prepare_def($def) { /* ignore zero-padding for date data types */ $def = preg_replace("/date\s*default\s*'([0-9]{4})-0?([1-9])-0?([1-9])'/i", "date default '$1-$2-$3'", $def); + /* if default is CURRENT_TIMESTAMP, remove single quotes */ + $def = preg_replace("/default\s*'CURRENT_TIMESTAMP'/i", "default current_timestamp", $def); + return trim($def); } @@ -248,7 +252,7 @@ function fix_field($fix_table, $fix_field, $schema, &$qry) { - + @@ -258,18 +262,37 @@ function fix_field($fix_table, $fix_field, $schema, &$qry) { $fields) { ?> - + $fd) { ?> - - + + '; } } else { // TVP - if($i) $this->HTML .= "\n\t
-

" , $tn , $Translation['table name title']) ; ?>">

+
+

+ + ", $tn, $Translation['table name title'])); ?>"> + + + + +
+ + +
+

+ -
+ + + {$fd['db']}", $Translation['does not exist']); ?> @@ -288,8 +311,19 @@ function fix_field($fix_table, $fix_field, $schema, &$qry) {
\n"; @@ -987,8 +981,8 @@ class="btn btn-default" /* default field values */ $rdata = $jdata = get_defaults('applications_leases'); - if($selected_id) { - $jdata = get_joined_record('applications_leases', $selected_id); + if($hasSelectedId) { + $jdata = get_joined_record('applications_leases', $selectedId); if($jdata === false) $jdata = get_defaults('applications_leases'); $rdata = $row; } @@ -997,7 +991,7 @@ class="btn btn-default" // hook: applications_leases_dv if(function_exists('applications_leases_dv')) { $args = []; - applications_leases_dv(($selected_id ? $selected_id : FALSE), getMemberInfo(), $templateCode, $args); + applications_leases_dv(($hasSelectedId ? $selectedId : FALSE), getMemberInfo(), $templateCode, $args); } return $templateCode; diff --git a/app/common.js b/app/common.js index 43c8cfa..d8174c9 100644 --- a/app/common.js +++ b/app/common.js @@ -1,6 +1,6 @@ var AppGini = AppGini || {}; -AppGini.version = 24.14; +AppGini.version = 24.15; /* initials and fixes */ jQuery(function() { @@ -32,7 +32,7 @@ jQuery(function() { $j('.detail_view .img-responsive').css({'max-width' : parseInt($j('.detail_view').width() * full_img_factor) + 'px'}); - /* change height of sizer div below navbar to accomodate navbar height */ + /* change height of sizer div below navbar to accommodate navbar height */ $j('.top-margin-adjuster').height($j('.navbar-fixed-top:visible').height() ?? 10); /* remove labels from truncated buttons, leaving only glyphicons */ @@ -318,7 +318,7 @@ jQuery(function() { }) // in TVP, disable lightbox for images - if($j('#current_view').val() == 'TVP') { + if(AppGini.currentViewIs('TVP')) { const links = document.querySelectorAll('a[data-lightbox]'); links.forEach(function(link) { const img = link.innerHTML; // Get the inner HTML of the tag, which should be an element @@ -342,6 +342,9 @@ jQuery(function() { } }); + AppGini.renderTVRecordsPerPageSelector(); + AppGini.appendRecordsPerPageToTableLinks(); + }); /* show/hide TV action buttons based on whether records are selected or not */ @@ -374,7 +377,7 @@ AppGini.ajaxCache = function() { var _tests = []; /* - An array of functions that receive a parameterless url and a parameters object, + An array of functions that receive a parameter-less url and a parameters object, makes a test, and if test passes, executes something and/or returns a non-false value if test passes, @@ -2504,7 +2507,7 @@ AppGini.updateChildrenCount = (scheduleNextCall = true) => { } // TVP? - if($j('#current_view').val() == 'TVP' && !AppGini._childRecordsInfoAdaptedToTVP) { + if(AppGini.currentViewIs('TVP') && !AppGini._childRecordsInfoAdaptedToTVP) { // show only the count, no link, no add new $j('.child-records-info').not('th').html('
'); AppGini._childRecordsInfoAdaptedToTVP = true; @@ -2626,15 +2629,19 @@ AppGini.localeFormat = (num, isInt, locale) => { // if locale not provided, default to current locale locale = locale || navigator.language; + const globalNumeralsRegex = /[\d\u0660-\u0669\u0966-\u096F\u09E6-\u09EF\u0BE6-\u0BEF\u0E50-\u0E59\u1040-\u1049\u17E0-\u17E9]/g; + // decimal separator based on locale - const decimalSeparator = new Intl.NumberFormat(locale).format(1.1).replace(/\d/g, ''); + const decimalSeparator = new Intl.NumberFormat(locale).format(1.1).replace(globalNumeralsRegex, ''); // thousands separator based on locale - const thousandsSeparator = new Intl.NumberFormat(locale).format(11111).replace(/\d/g, ''); + const thousandsSeparator = new Intl.NumberFormat(locale).format(11111).replace(globalNumeralsRegex, ''); + // Localized NaN + const lNaN = new Intl.NumberFormat(locale).format(NaN); // if number is a raw number (e.g. 1234.5 or 12.34), format it based on locale if (!isInt && num.indexOf(decimalSeparator) === -1) { let lfn = new Intl.NumberFormat(locale).format(num); - return lfn === 'NaN' ? num : lfn; + return lfn === lNaN ? num : lfn; } // if number is already formatted in the locale, return it as is @@ -2645,6 +2652,7 @@ AppGini.localeFormat = (num, isInt, locale) => { // return the number formatted in the locale return new Intl.NumberFormat(locale).format(parseFloat(num.replace(decimalSeparator, '.'))); } + AppGini.storedLayout = (val) => { const view = $j('[name="current_view"]').val(); @@ -2750,3 +2758,159 @@ AppGini.applyTripleColumnLayout = () => { } +AppGini.preparePagesMenu = (recordsPerPage, pagesMenuId, lastPage, currentPage, lump) => { + const addPageNumbers = (fromPage, toPage) => { + const pagesMenu = document.getElementById(pagesMenuId); + let ellipsesIndex = 0; + + if(fromPage > toPage) return; + + if(fromPage > 0) { + if(pagesMenu.options[pagesMenu.options.length - 1].text != fromPage) { + ellipsesIndex = pagesMenu.options.length; + fromPage--; + } + } + + for(i = fromPage; i <= toPage; i++) { + var option = document.createElement("option"); + option.text = (i + 1); + option.value = i; + if(i == currentPage) { option.selected = "selected"; } + try{ + /* for IE earlier than version 8 */ + pagesMenu.add(option, pagesMenu.options[null]); + }catch(e) { + pagesMenu.add(option, null); + } + } + + if(ellipsesIndex > 0) { + pagesMenu.options[ellipsesIndex].text = " ... "; + } + } + + // empty the pages menu and clear any previous event handlers + $j(`#${pagesMenuId}`).empty() + .off('change') + .on('change', function() { + // get parent form + const parentForm = $j(this).closest('form'); + + // novalidate + parentForm.attr('novalidate', 'novalidate'); + + // set NoDV hidden field value to 1 + parentForm.find('input[name=NoDV]').val(1); + + // and FirstRecord + parentForm.find('input[name=FirstRecord]').val(parseInt($j(this).val()) * recordsPerPage + 1); + + // submit the form + parentForm.submit(); + }); + + if(lastPage <= lump * 3) { + addPageNumbers(0, lastPage); + return; + } + + addPageNumbers(0, lump - 1); + if(currentPage < lump) addPageNumbers(lump, currentPage + lump / 2); + if(currentPage >= lump && currentPage < (lastPage - lump)) { + addPageNumbers( + Math.max(currentPage - lump / 2, lump), + Math.min(currentPage + lump / 2, lastPage - lump - 1) + ); + } + if(currentPage >= (lastPage - lump)) addPageNumbers(currentPage - lump / 2, lastPage - lump - 1); + addPageNumbers(lastPage - lump, lastPage); +} + +AppGini.storedRecordsPerPage = (val) => { + if(val !== undefined) { + localStorage.setItem(`rental_property_manager.${AppGini.currentTableName()}.recordsPerPage`, val); + } + return localStorage.getItem(`rental_property_manager.${AppGini.currentTableName()}.recordsPerPage`); +} + +AppGini.renderTVRecordsPerPageSelector = () => { + // if not TV, return + if(!AppGini.currentViewIs('TV')) return; + + // if records per page selector already rendered, return + if($j('#records-per-page-selector').length) return; + + // to override the default records per page options, + // set AppGini.config.recordsPerPageOptions as an array of integers + // in hooks/header-extras.php or hooks/footer-extras.php + let rppOptions = [5, 10, 20, 30, 40, 50, 100, 200]; + if(AppGini.config.recordsPerPageOptions) { + rppOptions = AppGini.config.recordsPerPageOptions; + } + + // create the records per page selector and append to .record-count-info + $j('.record-count-info').append(` +
+ + +
+
+ `); + + // handle change event + $j('#records-per-page-selector').on('change', function() { + const newRecordsPerPage = $j(this).val(); + + AppGini.storedRecordsPerPage(newRecordsPerPage); + + // get parent form + const parentForm = $j(this).closest('form'); + + // novalidate + parentForm.attr('novalidate', 'novalidate'); + + // no DV + parentForm.find('input[name=NoDV]').val(1); + + // set first record hidden field value to 1 + parentForm.find('input[name=FirstRecord]').val(1); + + // set RecordsPerPage hidden field value + parentForm.find('input[name=RecordsPerPage]').val(newRecordsPerPage); + + // submit the form + parentForm.submit(); + }); + + // if stored records per page > 0 and not the same as the default, + // set the selected option to the stored value and trigger change event + const defaultRecordsPerPage = $j('[name=RecordsPerPage]').val(); + const storedRecordsPerPage = AppGini.storedRecordsPerPage(); + if(storedRecordsPerPage > 0 && storedRecordsPerPage != defaultRecordsPerPage && storedRecordsPerPage <= 200) { + $j('#records-per-page-selector').val(storedRecordsPerPage).trigger('change'); + return; + } + + // set the selected option based on the current records per page + $j('#records-per-page-selector').val(defaultRecordsPerPage); +} + +AppGini.currentViewIs = (view) => $j('#current_view').val()?.toLowerCase() == view?.toLowerCase(); + +AppGini.appendRecordsPerPageToTableLinks = () => { + // find stored records per page and extract table names from keys + Object.keys(localStorage).filter(k => k.match(/rental_property_manager\..*?\.recordsPerPage/)).forEach(k => { + const tableName = k.split('.')[1]; + $j(`a[href*="/${tableName}_view.php"], a[href^="${tableName}_view.php"]`).each(function() { + const href = new URL($j(this).attr('href'), window.location.href); + href.searchParams.set('RecordsPerPage', localStorage.getItem(k)); + $j(this).attr('href', href.toString()); + }); + }); +} diff --git a/app/datalist.php b/app/datalist.php index eaddba2..928520a 100644 --- a/app/datalist.php +++ b/app/datalist.php @@ -156,6 +156,13 @@ function Render() { $deselect_x = Request::val('deselect_x'); $addNew_x = Request::val('addNew_x'); $dvprint_x = Request::val('dvprint_x'); + + // records per page: if user-provided and > 0, use it, else use default + $defaultRPP = $this->RecordsPerPage; + $userRPP = intval(Request::val('RecordsPerPage')); + $appliedRecordsPerPage = ($userRPP > 0 ? $userRPP : $defaultRPP); + $this->RecordsPerPage = $appliedRecordsPerPage; + $DisplayRecords = (in_array(Request::val('DisplayRecords'), ['user', 'group']) ? Request::val('DisplayRecords') : 'all'); list($this->FilterAnd, $this->FilterField, $this->FilterOperator, $this->FilterValue) = $this->validate_filters($_REQUEST, $FiltersPerGroup); $record_selector = []; @@ -676,7 +683,7 @@ function Render() { } } - $tvRecords = $this->getTVRevords($FirstRecord); + $tvRecords = $this->getTVRecords($FirstRecord); $fieldCountTV = count($this->QueryFieldsTV); $indexOfSelectedID = null; @@ -835,11 +842,11 @@ function Render() { $this->HTML .= $this->tv_tools(); $this->HTML .= '

'; $this->HTML .= ''; - - $this->HTML .= '
'; - $tvRowNeedsClosing = true; } + $this->HTML .= '
'; + $tvRowNeedsClosing = true; + if($Print_x != '') { /* fix top margin for print-preview */ $this->HTML .= ''; @@ -1067,110 +1074,73 @@ function Render() { $pagesMenu = ''; if($RecordCount > $this->RecordsPerPage) { $pagesMenuId = "{$this->TableName}_pagesMenu"; - $pagesMenu = $this->translation['go to page'] . ' '; - - $pagesMenu .= ''; + + $pagesMenu = ""; + $pagesMenu .= ''; + $pagesMenu .= ''; } $this->HTML .= "\n\t"; - if($i) { // 1 or more records found - $this->HTML .= "
'; $this->HTML .= ' '; $this->HTML .= $this->translation['No matches found!']; $this->HTML .= ''; + $this->HTML .= ''; $this->HTML .= '
", '' . $FirstRecord . '', $this->HTML); - $this->HTML = str_replace("", '' . $i . '', $this->HTML); - $this->HTML = str_replace("", '' . $RecordCount . '', $this->HTML); $tvShown = true; $this->HTML .= "
\n"; - /* highlight quick search matches */ - if(strlen($SearchString) && $RecordCount) $this->HTML .= ''; + // records count TV/TVP footer + $recordCountHtml = str_replace( + ['', '', ''], + [ + '' . $FirstRecord . '', + '' . $i . '', + '' . $RecordCount . '' + ], + $this->translation['records x to y of z'] + ); + $this->HTML .= '
' . $recordCountHtml . '
'; - if($Print_x == '' && $i) { // TV - $this->HTML .= '
'; - $this->HTML .= '
'; + // records count and pagination in TV if 1 or more records found + if($i && $Print_x == '') { + + $this->HTML .= '
'; + $this->HTML .= '
'; if($FirstRecord > 1) - $this->HTML .= '
 
' . - ''; + $this->HTML .= ''; $this->HTML .= '
'; - $this->HTML .= '
'; - $this->HTML .= $pagesMenu; - $this->HTML .= '
'; + $this->HTML .= '
' . $pagesMenu . '
'; - $this->HTML .= '
'; + $this->HTML .= '
'; if($i < $RecordCount) - $this->HTML .= '
 
' . - ''; + $this->HTML .= ''; $this->HTML .= '
'; $this->HTML .= '
'; } + /* highlight quick search matches */ + if(strlen($SearchString) && $RecordCount) $this->HTML .= ''; + $this->HTML .= '
'; // end of div.table_view $this->HTML .= $this->hideInaccessibleChildrenFromTV(); @@ -1195,7 +1165,9 @@ function Render() { $this->HTML .= ''; $this->HTML .= ''; $this->HTML .= ''; - if($this->QuickSearch && !strpos($this->HTML, 'SearchString')) $this->HTML .= ''; + $this->HTML .= ''; + if(/*$this->QuickSearch &&*/ !strpos($this->HTML, ' name="SearchString"')) $this->HTML .= ''; + // hidden variables: filters ... $FiltersCode = ''; for($i = 1; $i <= (datalist_filters_count * $FiltersPerGroup); $i++) { // Number of filters allowed @@ -1661,7 +1633,7 @@ function getTVQuery($first) { return $this->buildQuery($tvFields, $first - 1, $this->RecordsPerPage); } - function getTVRevords($first) { + function getTVRecords($first) { //$eo = ['silentErrors' => true]; $result = sql($this->getTVQuery($first), $eo); $tvRecords = []; diff --git a/app/defaultFilters.php b/app/defaultFilters.php index 36a6e48..9b29229 100644 --- a/app/defaultFilters.php +++ b/app/defaultFilters.php @@ -248,6 +248,9 @@ } ?> + + +
diff --git a/app/definitions.php b/app/definitions.php index f963f4d..1727819 100644 --- a/app/definitions.php +++ b/app/definitions.php @@ -3,7 +3,7 @@ @define('SESSION_NAME', 'Rental_property_manager'); @define('APP_TITLE', 'Rental Property Manager'); @define('APP_DIR', __DIR__); - @define('APP_VERSION', '24.14'); + @define('APP_VERSION', '24.15'); @define('maxSortBy', 4); @define('empty_lookup_value', '{empty_value}'); @define('MULTIPLE_SUPER_ADMINS', false); diff --git a/app/dynamic.css b/app/dynamic.css index a4babc0..92b5331 100644 --- a/app/dynamic.css +++ b/app/dynamic.css @@ -1029,3 +1029,24 @@ td.row .img-responsive { padding: 0 0 0 1em; } } + +.form-group > .col-lg-9:not(:has(.datetimepicker)) { + overflow-x: auto; +} + +/* pagination section */ +.pagination-section { + display: flex; + justify-content: flex-start; + align-items: center; + gap: 1em; +} +.pagination-section > div { + flex-grow: 1; +} +.pagination-section > div:not(:last-child):not(:first-child) { + text-align: center; +} +.pagination-section > div:last-child { + text-align: right; +} diff --git a/app/employment_and_income_history_dml.php b/app/employment_and_income_history_dml.php index c9b2e52..89f0682 100644 --- a/app/employment_and_income_history_dml.php +++ b/app/employment_and_income_history_dml.php @@ -181,31 +181,40 @@ function employment_and_income_history_update(&$selected_id, &$error_message = ' set_record_owner('employment_and_income_history', $selected_id); } -function employment_and_income_history_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, $AllowDelete = 1, $separateDV = 0, $TemplateDV = '', $TemplateDVP = '') { +function employment_and_income_history_form($selectedId = '', $allowUpdate = true, $allowInsert = true, $allowDelete = true, $separateDV = true, $templateDV = '', $templateDVP = '') { // function to return an editable form for a table records - // and fill it with data of record whose ID is $selected_id. If $selected_id + // and fill it with data of record whose ID is $selectedId. If $selectedId // is empty, an empty form is shown, with only an 'Add New' // button displayed. global $Translation; $eo = ['silentErrors' => true]; - $noUploads = null; - $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; - + $noUploads = $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; $noSaveAsCopy = false; + $hasSelectedId = strlen($selectedId) > 0; // mm: get table permissions $arrPerm = getTablePermissions('employment_and_income_history'); - if(!$arrPerm['insert'] && $selected_id == '') + $allowInsert = ($arrPerm['insert'] ? true : false); + $allowUpdate = $hasSelectedId && check_record_permission('employment_and_income_history', $selectedId, 'edit'); + $allowDelete = $hasSelectedId && check_record_permission('employment_and_income_history', $selectedId, 'delete'); + + if(!$allowInsert && !$hasSelectedId) // no insert permission and no record selected - // so show access denied error unless TVDV + // so show access denied error -- except if TVDV: just hide DV return $separateDV ? $Translation['tableAccessDenied'] : ''; - $AllowInsert = ($arrPerm['insert'] ? true : false); + + if($hasSelectedId && !check_record_permission('employment_and_income_history', $selectedId, 'view')) + return $Translation['tableAccessDenied']; + // print preview? - $dvprint = false; - if(strlen($selected_id) && Request::val('dvprint_x') != '') { - $dvprint = true; - } + $dvprint = $hasSelectedId && Request::val('dvprint_x') != ''; + + $showSaveNew = !$dvprint && ($allowInsert && !$hasSelectedId); + $showSaveChanges = !$dvprint && $allowUpdate && $hasSelectedId; + $showDelete = !$dvprint && $allowDelete && $hasSelectedId; + $showSaveAsCopy = !$dvprint && ($allowInsert && $hasSelectedId && !$noSaveAsCopy); + $fieldsAreEditable = !$dvprint && (($allowInsert && !$hasSelectedId) || ($allowUpdate && $hasSelectedId) || $showSaveAsCopy); $filterer_tenant = Request::val('filterer_tenant'); @@ -232,17 +241,8 @@ function employment_and_income_history_form($selected_id = '', $AllowUpdate = 1, $combo_employed_till->MonthNames = $Translation['month names']; $combo_employed_till->NamePrefix = 'employed_till'; - if($selected_id) { - if(!check_record_permission('employment_and_income_history', $selected_id, 'view')) - return $Translation['tableAccessDenied']; - - // can edit? - $AllowUpdate = check_record_permission('employment_and_income_history', $selected_id, 'edit'); - - // can delete? - $AllowDelete = check_record_permission('employment_and_income_history', $selected_id, 'delete'); - - $res = sql("SELECT * FROM `employment_and_income_history` WHERE `id`='" . makeSafe($selected_id) . "'", $eo); + if($hasSelectedId) { + $res = sql("SELECT * FROM `employment_and_income_history` WHERE `id`='" . makeSafe($selectedId) . "'", $eo); if(!($row = db_fetch_array($res))) { return error_message($Translation['No records found'], 'employment_and_income_history_view.php', false); } @@ -265,7 +265,7 @@ function employment_and_income_history_form($selected_id = '', $AllowUpdate = 1, \n"; @@ -595,8 +597,8 @@ class="btn btn-default" /* default field values */ $rdata = $jdata = get_defaults('employment_and_income_history'); - if($selected_id) { - $jdata = get_joined_record('employment_and_income_history', $selected_id); + if($hasSelectedId) { + $jdata = get_joined_record('employment_and_income_history', $selectedId); if($jdata === false) $jdata = get_defaults('employment_and_income_history'); $rdata = $row; } @@ -605,7 +607,7 @@ class="btn btn-default" // hook: employment_and_income_history_dv if(function_exists('employment_and_income_history_dv')) { $args = []; - employment_and_income_history_dv(($selected_id ? $selected_id : FALSE), getMemberInfo(), $templateCode, $args); + employment_and_income_history_dv(($hasSelectedId ? $selectedId : FALSE), getMemberInfo(), $templateCode, $args); } return $templateCode; diff --git a/app/footer.php b/app/footer.php index 6e8fd61..c16688a 100644 --- a/app/footer.php +++ b/app/footer.php @@ -9,7 +9,7 @@
diff --git a/app/header.php b/app/header.php index c04d237..2f24c98 100644 --- a/app/header.php +++ b/app/header.php @@ -35,13 +35,6 @@ + TableName) && is_file(__DIR__ . "/hooks/{$x->TableName}-tv.js")) { ?> diff --git a/app/home.php b/app/home.php index 237c339..d03a867 100644 --- a/app/home.php +++ b/app/home.php @@ -196,7 +196,12 @@ $j('div[id$="-tile"] .panel-body-description').css({height: 'auto'}); } - $j('.panel-body .btn').height(32); + // adjust button heights to be equal and at least 32px + AppGini.repeatUntil({ + action: () => $j('.panel-body .btn').height(32), + condition: () => Math.min(...$j('.panel-body .btn').map((_, el) => $j(el).height()).get().filter(height => height >= 0)) >= 32, + frequency: 100, + }) $j('.btn-add-new').click(function() { var tn = $j(this).attr('id').replace(/_add_new$/, ''); diff --git a/app/incCommon.php b/app/incCommon.php index 920e7a6..ce91917 100644 --- a/app/incCommon.php +++ b/app/incCommon.php @@ -879,6 +879,21 @@ function get_embed($provider, $url, $max_width = '', $max_height = '', $retrieve return ''; } + // if html data not empty, apply max width and height in place of provided height and width + $provided_width = $data['width'] ?? null; + $provided_height = $data['height'] ?? null; + if($provided_width && $provided_height) { + $aspect_ratio = $provided_width / $provided_height; + if($max_width / $aspect_ratio < $max_height) { + $max_height = intval($max_width / $aspect_ratio); + } else { + $max_width = intval($max_height * $aspect_ratio); + } + + $data['html'] = str_replace("width=\"{$provided_width}\"", "width=\"{$max_width}\"", $data['html']); + $data['html'] = str_replace("height=\"{$provided_height}\"", "height=\"{$max_height}\"", $data['html']); + } + return (isset($data[$retrieve]) ? $data[$retrieve] : $data['html']); } diff --git a/app/lang.js.php b/app/lang.js.php new file mode 100644 index 0000000..cd9e389 --- /dev/null +++ b/app/lang.js.php @@ -0,0 +1,75 @@ + + +var AppGini = AppGini || {}; + +/* translation strings */ +AppGini.Translate = { + _map: , + _encoding: '', + apply: () => { + // find elements with data-translate attribute that don't have .translated class + const contentEls = document.querySelectorAll('[data-translate]:not(.translated)'); + + // find elements with data-title attribute that don't have .translated class + const titleEls = document.querySelectorAll('[data-title]:not(.translated)'); + + // abort if no elements found + if(!contentEls.length && !titleEls.length) return; + + // translate content of elements that have data-translate attribute + contentEls.forEach(el => { + const key = el.getAttribute('data-translate'); + if(!key) return; + + const translation = AppGini.Translate._map[key]; + if(!translation) return; + + el.innerHTML = translation; + el.classList.add('translated'); + }); + + // translate title of elements that have data-title attribute + titleEls.forEach(el => { + const key = el.getAttribute('data-title'); + if(!key) return; + + const translation = AppGini.Translate._map[key]; + if(!translation) return; + + el.setAttribute('title', translation); + el.classList.add('translated'); + }); + }, +} diff --git a/app/properties_dml.php b/app/properties_dml.php index 06f54a0..fd5e85d 100644 --- a/app/properties_dml.php +++ b/app/properties_dml.php @@ -295,31 +295,40 @@ function properties_update(&$selected_id, &$error_message = '') { set_record_owner('properties', $selected_id); } -function properties_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, $AllowDelete = 1, $separateDV = 0, $TemplateDV = '', $TemplateDVP = '') { +function properties_form($selectedId = '', $allowUpdate = true, $allowInsert = true, $allowDelete = true, $separateDV = true, $templateDV = '', $templateDVP = '') { // function to return an editable form for a table records - // and fill it with data of record whose ID is $selected_id. If $selected_id + // and fill it with data of record whose ID is $selectedId. If $selectedId // is empty, an empty form is shown, with only an 'Add New' // button displayed. global $Translation; $eo = ['silentErrors' => true]; - $noUploads = null; - $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; - + $noUploads = $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; $noSaveAsCopy = false; + $hasSelectedId = strlen($selectedId) > 0; // mm: get table permissions $arrPerm = getTablePermissions('properties'); - if(!$arrPerm['insert'] && $selected_id == '') + $allowInsert = ($arrPerm['insert'] ? true : false); + $allowUpdate = $hasSelectedId && check_record_permission('properties', $selectedId, 'edit'); + $allowDelete = $hasSelectedId && check_record_permission('properties', $selectedId, 'delete'); + + if(!$allowInsert && !$hasSelectedId) // no insert permission and no record selected - // so show access denied error unless TVDV + // so show access denied error -- except if TVDV: just hide DV return $separateDV ? $Translation['tableAccessDenied'] : ''; - $AllowInsert = ($arrPerm['insert'] ? true : false); + + if($hasSelectedId && !check_record_permission('properties', $selectedId, 'view')) + return $Translation['tableAccessDenied']; + // print preview? - $dvprint = false; - if(strlen($selected_id) && Request::val('dvprint_x') != '') { - $dvprint = true; - } + $dvprint = $hasSelectedId && Request::val('dvprint_x') != ''; + + $showSaveNew = !$dvprint && ($allowInsert && !$hasSelectedId); + $showSaveChanges = !$dvprint && $allowUpdate && $hasSelectedId; + $showDelete = !$dvprint && $allowDelete && $hasSelectedId; + $showSaveAsCopy = !$dvprint && ($allowInsert && $hasSelectedId && !$noSaveAsCopy); + $fieldsAreEditable = !$dvprint && (($allowInsert && !$hasSelectedId) || ($allowUpdate && $hasSelectedId) || $showSaveAsCopy); $filterer_owner = Request::val('filterer_owner'); @@ -391,17 +400,8 @@ function properties_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, } $combo_State->SelectName = 'State'; - if($selected_id) { - if(!check_record_permission('properties', $selected_id, 'view')) - return $Translation['tableAccessDenied']; - - // can edit? - $AllowUpdate = check_record_permission('properties', $selected_id, 'edit'); - - // can delete? - $AllowDelete = check_record_permission('properties', $selected_id, 'delete'); - - $res = sql("SELECT * FROM `properties` WHERE `id`='" . makeSafe($selected_id) . "'", $eo); + if($hasSelectedId) { + $res = sql("SELECT * FROM `properties` WHERE `id`='" . makeSafe($selectedId) . "'", $eo); if(!($row = db_fetch_array($res))) { return error_message($Translation['No records found'], 'properties_view.php', false); } @@ -434,7 +434,7 @@ function properties_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, \n"; @@ -793,8 +795,8 @@ class="btn btn-default" /* default field values */ $rdata = $jdata = get_defaults('properties'); - if($selected_id) { - $jdata = get_joined_record('properties', $selected_id); + if($hasSelectedId) { + $jdata = get_joined_record('properties', $selectedId); if($jdata === false) $jdata = get_defaults('properties'); $rdata = $row; } @@ -803,7 +805,7 @@ class="btn btn-default" // hook: properties_dv if(function_exists('properties_dv')) { $args = []; - properties_dv(($selected_id ? $selected_id : FALSE), getMemberInfo(), $templateCode, $args); + properties_dv(($hasSelectedId ? $selectedId : FALSE), getMemberInfo(), $templateCode, $args); } return $templateCode; diff --git a/app/property_photos_dml.php b/app/property_photos_dml.php index a73a50c..e5b9446 100644 --- a/app/property_photos_dml.php +++ b/app/property_photos_dml.php @@ -204,31 +204,40 @@ function property_photos_update(&$selected_id, &$error_message = '') { set_record_owner('property_photos', $selected_id); } -function property_photos_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, $AllowDelete = 1, $separateDV = 0, $TemplateDV = '', $TemplateDVP = '') { +function property_photos_form($selectedId = '', $allowUpdate = true, $allowInsert = true, $allowDelete = true, $separateDV = true, $templateDV = '', $templateDVP = '') { // function to return an editable form for a table records - // and fill it with data of record whose ID is $selected_id. If $selected_id + // and fill it with data of record whose ID is $selectedId. If $selectedId // is empty, an empty form is shown, with only an 'Add New' // button displayed. global $Translation; $eo = ['silentErrors' => true]; - $noUploads = null; - $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; - + $noUploads = $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; $noSaveAsCopy = false; + $hasSelectedId = strlen($selectedId) > 0; // mm: get table permissions $arrPerm = getTablePermissions('property_photos'); - if(!$arrPerm['insert'] && $selected_id == '') + $allowInsert = ($arrPerm['insert'] ? true : false); + $allowUpdate = $hasSelectedId && check_record_permission('property_photos', $selectedId, 'edit'); + $allowDelete = $hasSelectedId && check_record_permission('property_photos', $selectedId, 'delete'); + + if(!$allowInsert && !$hasSelectedId) // no insert permission and no record selected - // so show access denied error unless TVDV + // so show access denied error -- except if TVDV: just hide DV return $separateDV ? $Translation['tableAccessDenied'] : ''; - $AllowInsert = ($arrPerm['insert'] ? true : false); + + if($hasSelectedId && !check_record_permission('property_photos', $selectedId, 'view')) + return $Translation['tableAccessDenied']; + // print preview? - $dvprint = false; - if(strlen($selected_id) && Request::val('dvprint_x') != '') { - $dvprint = true; - } + $dvprint = $hasSelectedId && Request::val('dvprint_x') != ''; + + $showSaveNew = !$dvprint && ($allowInsert && !$hasSelectedId); + $showSaveChanges = !$dvprint && $allowUpdate && $hasSelectedId; + $showDelete = !$dvprint && $allowDelete && $hasSelectedId; + $showSaveAsCopy = !$dvprint && ($allowInsert && $hasSelectedId && !$noSaveAsCopy); + $fieldsAreEditable = !$dvprint && (($allowInsert && !$hasSelectedId) || ($allowUpdate && $hasSelectedId) || $showSaveAsCopy); $filterer_property = Request::val('filterer_property'); @@ -239,17 +248,8 @@ function property_photos_form($selected_id = '', $AllowUpdate = 1, $AllowInsert // combobox: property $combo_property = new DataCombo; - if($selected_id) { - if(!check_record_permission('property_photos', $selected_id, 'view')) - return $Translation['tableAccessDenied']; - - // can edit? - $AllowUpdate = check_record_permission('property_photos', $selected_id, 'edit'); - - // can delete? - $AllowDelete = check_record_permission('property_photos', $selected_id, 'delete'); - - $res = sql("SELECT * FROM `property_photos` WHERE `id`='" . makeSafe($selected_id) . "'", $eo); + if($hasSelectedId) { + $res = sql("SELECT * FROM `property_photos` WHERE `id`='" . makeSafe($selectedId) . "'", $eo); if(!($row = db_fetch_array($res))) { return error_message($Translation['No records found'], 'property_photos_view.php', false); } @@ -270,7 +270,7 @@ function property_photos_form($selected_id = '', $AllowUpdate = 1, $AllowInsert \n"; @@ -556,8 +558,8 @@ class="btn btn-default" /* default field values */ $rdata = $jdata = get_defaults('property_photos'); - if($selected_id) { - $jdata = get_joined_record('property_photos', $selected_id); + if($hasSelectedId) { + $jdata = get_joined_record('property_photos', $selectedId); if($jdata === false) $jdata = get_defaults('property_photos'); $rdata = $row; } @@ -566,7 +568,7 @@ class="btn btn-default" // hook: property_photos_dv if(function_exists('property_photos_dv')) { $args = []; - property_photos_dv(($selected_id ? $selected_id : FALSE), getMemberInfo(), $templateCode, $args); + property_photos_dv(($hasSelectedId ? $selectedId : FALSE), getMemberInfo(), $templateCode, $args); } return $templateCode; diff --git a/app/references_dml.php b/app/references_dml.php index a3efd56..1b4c009 100644 --- a/app/references_dml.php +++ b/app/references_dml.php @@ -171,31 +171,40 @@ function references_update(&$selected_id, &$error_message = '') { set_record_owner('references', $selected_id); } -function references_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, $AllowDelete = 1, $separateDV = 0, $TemplateDV = '', $TemplateDVP = '') { +function references_form($selectedId = '', $allowUpdate = true, $allowInsert = true, $allowDelete = true, $separateDV = true, $templateDV = '', $templateDVP = '') { // function to return an editable form for a table records - // and fill it with data of record whose ID is $selected_id. If $selected_id + // and fill it with data of record whose ID is $selectedId. If $selectedId // is empty, an empty form is shown, with only an 'Add New' // button displayed. global $Translation; $eo = ['silentErrors' => true]; - $noUploads = null; - $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; - + $noUploads = $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; $noSaveAsCopy = false; + $hasSelectedId = strlen($selectedId) > 0; // mm: get table permissions $arrPerm = getTablePermissions('references'); - if(!$arrPerm['insert'] && $selected_id == '') + $allowInsert = ($arrPerm['insert'] ? true : false); + $allowUpdate = $hasSelectedId && check_record_permission('references', $selectedId, 'edit'); + $allowDelete = $hasSelectedId && check_record_permission('references', $selectedId, 'delete'); + + if(!$allowInsert && !$hasSelectedId) // no insert permission and no record selected - // so show access denied error unless TVDV + // so show access denied error -- except if TVDV: just hide DV return $separateDV ? $Translation['tableAccessDenied'] : ''; - $AllowInsert = ($arrPerm['insert'] ? true : false); + + if($hasSelectedId && !check_record_permission('references', $selectedId, 'view')) + return $Translation['tableAccessDenied']; + // print preview? - $dvprint = false; - if(strlen($selected_id) && Request::val('dvprint_x') != '') { - $dvprint = true; - } + $dvprint = $hasSelectedId && Request::val('dvprint_x') != ''; + + $showSaveNew = !$dvprint && ($allowInsert && !$hasSelectedId); + $showSaveChanges = !$dvprint && $allowUpdate && $hasSelectedId; + $showDelete = !$dvprint && $allowDelete && $hasSelectedId; + $showSaveAsCopy = !$dvprint && ($allowInsert && $hasSelectedId && !$noSaveAsCopy); + $fieldsAreEditable = !$dvprint && (($allowInsert && !$hasSelectedId) || ($allowUpdate && $hasSelectedId) || $showSaveAsCopy); $filterer_tenant = Request::val('filterer_tenant'); @@ -206,17 +215,8 @@ function references_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, // combobox: tenant $combo_tenant = new DataCombo; - if($selected_id) { - if(!check_record_permission('references', $selected_id, 'view')) - return $Translation['tableAccessDenied']; - - // can edit? - $AllowUpdate = check_record_permission('references', $selected_id, 'edit'); - - // can delete? - $AllowDelete = check_record_permission('references', $selected_id, 'delete'); - - $res = sql("SELECT * FROM `references` WHERE `id`='" . makeSafe($selected_id) . "'", $eo); + if($hasSelectedId) { + $res = sql("SELECT * FROM `references` WHERE `id`='" . makeSafe($selectedId) . "'", $eo); if(!($row = db_fetch_array($res))) { return error_message($Translation['No records found'], 'references_view.php', false); } @@ -237,7 +237,7 @@ function references_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, \n"; @@ -516,8 +518,8 @@ class="btn btn-default" /* default field values */ $rdata = $jdata = get_defaults('references'); - if($selected_id) { - $jdata = get_joined_record('references', $selected_id); + if($hasSelectedId) { + $jdata = get_joined_record('references', $selectedId); if($jdata === false) $jdata = get_defaults('references'); $rdata = $row; } @@ -526,7 +528,7 @@ class="btn btn-default" // hook: references_dv if(function_exists('references_dv')) { $args = []; - references_dv(($selected_id ? $selected_id : FALSE), getMemberInfo(), $templateCode, $args); + references_dv(($hasSelectedId ? $selectedId : FALSE), getMemberInfo(), $templateCode, $args); } return $templateCode; diff --git a/app/rental_owners_dml.php b/app/rental_owners_dml.php index 8e27067..332122d 100644 --- a/app/rental_owners_dml.php +++ b/app/rental_owners_dml.php @@ -210,31 +210,40 @@ function rental_owners_update(&$selected_id, &$error_message = '') { set_record_owner('rental_owners', $selected_id); } -function rental_owners_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, $AllowDelete = 1, $separateDV = 0, $TemplateDV = '', $TemplateDVP = '') { +function rental_owners_form($selectedId = '', $allowUpdate = true, $allowInsert = true, $allowDelete = true, $separateDV = true, $templateDV = '', $templateDVP = '') { // function to return an editable form for a table records - // and fill it with data of record whose ID is $selected_id. If $selected_id + // and fill it with data of record whose ID is $selectedId. If $selectedId // is empty, an empty form is shown, with only an 'Add New' // button displayed. global $Translation; $eo = ['silentErrors' => true]; - $noUploads = null; - $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; - + $noUploads = $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; $noSaveAsCopy = false; + $hasSelectedId = strlen($selectedId) > 0; // mm: get table permissions $arrPerm = getTablePermissions('rental_owners'); - if(!$arrPerm['insert'] && $selected_id == '') + $allowInsert = ($arrPerm['insert'] ? true : false); + $allowUpdate = $hasSelectedId && check_record_permission('rental_owners', $selectedId, 'edit'); + $allowDelete = $hasSelectedId && check_record_permission('rental_owners', $selectedId, 'delete'); + + if(!$allowInsert && !$hasSelectedId) // no insert permission and no record selected - // so show access denied error unless TVDV + // so show access denied error -- except if TVDV: just hide DV return $separateDV ? $Translation['tableAccessDenied'] : ''; - $AllowInsert = ($arrPerm['insert'] ? true : false); + + if($hasSelectedId && !check_record_permission('rental_owners', $selectedId, 'view')) + return $Translation['tableAccessDenied']; + // print preview? - $dvprint = false; - if(strlen($selected_id) && Request::val('dvprint_x') != '') { - $dvprint = true; - } + $dvprint = $hasSelectedId && Request::val('dvprint_x') != ''; + + $showSaveNew = !$dvprint && ($allowInsert && !$hasSelectedId); + $showSaveChanges = !$dvprint && $allowUpdate && $hasSelectedId; + $showDelete = !$dvprint && $allowDelete && $hasSelectedId; + $showSaveAsCopy = !$dvprint && ($allowInsert && $hasSelectedId && !$noSaveAsCopy); + $fieldsAreEditable = !$dvprint && (($allowInsert && !$hasSelectedId) || ($allowUpdate && $hasSelectedId) || $showSaveAsCopy); // populate filterers, starting from children to grand-parents @@ -280,17 +289,8 @@ function rental_owners_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = } $combo_state->SelectName = 'state'; - if($selected_id) { - if(!check_record_permission('rental_owners', $selected_id, 'view')) - return $Translation['tableAccessDenied']; - - // can edit? - $AllowUpdate = check_record_permission('rental_owners', $selected_id, 'edit'); - - // can delete? - $AllowDelete = check_record_permission('rental_owners', $selected_id, 'delete'); - - $res = sql("SELECT * FROM `rental_owners` WHERE `id`='" . makeSafe($selected_id) . "'", $eo); + if($hasSelectedId) { + $res = sql("SELECT * FROM `rental_owners` WHERE `id`='" . makeSafe($selectedId) . "'", $eo); if(!($row = db_fetch_array($res))) { return error_message($Translation['No records found'], 'rental_owners_view.php', false); } @@ -329,10 +329,10 @@ function rental_owners_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = // open the detail view template if($dvprint) { - $template_file = is_file("./{$TemplateDVP}") ? "./{$TemplateDVP}" : './templates/rental_owners_templateDVP.html'; + $template_file = is_file("./{$templateDVP}") ? "./{$templateDVP}" : './templates/rental_owners_templateDVP.html'; $templateCode = @file_get_contents($template_file); } else { - $template_file = is_file("./{$TemplateDV}") ? "./{$TemplateDV}" : './templates/rental_owners_templateDV.html'; + $template_file = is_file("./{$templateDV}") ? "./{$templateDV}" : './templates/rental_owners_templateDV.html'; $templateCode = @file_get_contents($template_file); } @@ -341,8 +341,9 @@ function rental_owners_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = $templateCode = str_replace('<%%RND1%%>', $rnd1, $templateCode); $templateCode = str_replace('<%%EMBEDDED%%>', (Request::val('Embedded') ? 'Embedded=1' : ''), $templateCode); // process buttons - if($AllowInsert) { - if(!$selected_id) $templateCode = str_replace('<%%INSERT_BUTTON%%>', '', $templateCode); + if($showSaveNew) { + $templateCode = str_replace('<%%INSERT_BUTTON%%>', '', $templateCode); + } elseif($showSaveAsCopy) { $templateCode = str_replace('<%%INSERT_BUTTON%%>', '', $templateCode); } else { $templateCode = str_replace('<%%INSERT_BUTTON%%>', '', $templateCode); @@ -355,14 +356,14 @@ function rental_owners_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = $backAction = '$j(\'form\').eq(0).attr(\'novalidate\', \'novalidate\'); document.myform.reset(); return true;'; } - if($selected_id) { + if($hasSelectedId) { if(!Request::val('Embedded')) $templateCode = str_replace('<%%DVPRINT_BUTTON%%>', '', $templateCode); - if($AllowUpdate) + if($allowUpdate) $templateCode = str_replace('<%%UPDATE_BUTTON%%>', '', $templateCode); else $templateCode = str_replace('<%%UPDATE_BUTTON%%>', '', $templateCode); - if($AllowDelete) + if($allowDelete) $templateCode = str_replace('<%%DELETE_BUTTON%%>', '', $templateCode); else $templateCode = str_replace('<%%DELETE_BUTTON%%>', '', $templateCode); @@ -375,8 +376,8 @@ function rental_owners_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = // if not in embedded mode and user has insert only but no view/update/delete, // remove 'back' button if( - $arrPerm['insert'] - && !$arrPerm['update'] && !$arrPerm['delete'] && !$arrPerm['view'] + $allowInsert + && !$allowUpdate && !$allowDelete && !$arrPerm['view'] && !Request::val('Embedded') ) $templateCode = str_replace('<%%DESELECT_BUTTON%%>', '', $templateCode); @@ -401,7 +402,7 @@ class="btn btn-default" } // set records to read only if user can't insert new records and can't edit current record - if(($selected_id && !$AllowUpdate && !$AllowInsert) || (!$selected_id && !$AllowInsert)) { + if(!$fieldsAreEditable) { $jsReadOnly = ''; $jsReadOnly .= "\tjQuery('#first_name').replaceWith('
' + (jQuery('#first_name').val() || '') + '
');\n"; $jsReadOnly .= "\tjQuery('#last_name').replaceWith('
' + (jQuery('#last_name').val() || '') + '
');\n"; @@ -421,15 +422,16 @@ class="btn btn-default" $jsReadOnly .= "\tjQuery('.select2-container').hide();\n"; $noUploads = true; - } elseif($AllowInsert) { - $jsEditable = "\tjQuery('form').eq(0).data('already_changed', true);"; // temporarily disable form change handler + } else { + // temporarily disable form change handler till time and datetime pickers are enabled + $jsEditable = "\tjQuery('form').eq(0).data('already_changed', true);"; $jsEditable .= "\tjQuery('form').eq(0).data('already_changed', false);"; // re-enable form change handler } // process combos $templateCode = str_replace( '<%%COMBO(date_of_birth)%%>', - ($selected_id && !$arrPerm['edit'] && ($noSaveAsCopy || !$arrPerm['insert']) ? + (!$fieldsAreEditable ? '
' . $combo_date_of_birth->GetHTML(true) . '
' : $combo_date_of_birth->GetHTML() ), $templateCode); @@ -472,7 +474,7 @@ class="btn btn-default" $templateCode = str_replace('<%%UPLOADFILE(comments)%%>', '', $templateCode); // process values - if($selected_id) { + if($hasSelectedId) { if( $dvprint) $templateCode = str_replace('<%%VALUE(id)%%>', safe_html($urow['id']), $templateCode); if(!$dvprint) $templateCode = str_replace('<%%VALUE(id)%%>', html_attr($row['id']), $templateCode); $templateCode = str_replace('<%%URLVALUE(id)%%>', urlencode($urow['id']), $templateCode); @@ -511,7 +513,7 @@ class="btn btn-default" if( $dvprint) $templateCode = str_replace('<%%VALUE(zip)%%>', safe_html($urow['zip']), $templateCode); if(!$dvprint) $templateCode = str_replace('<%%VALUE(zip)%%>', html_attr($row['zip']), $templateCode); $templateCode = str_replace('<%%URLVALUE(zip)%%>', urlencode($urow['zip']), $templateCode); - if($AllowUpdate || $AllowInsert) { + if($fieldsAreEditable) { $templateCode = str_replace('<%%HTMLAREA(comments)%%>', '', $templateCode); } else { $templateCode = str_replace('<%%HTMLAREA(comments)%%>', '
' . $row['comments'] . '
', $templateCode); @@ -567,7 +569,7 @@ class="btn btn-default" $templateCode .= $jsReadOnly; $templateCode .= $jsEditable; - if(!$selected_id) { + if(!$hasSelectedId) { $templateCode.="\n\tif(document.getElementById('primary_emailEdit')) { document.getElementById('primary_emailEdit').style.display='inline'; }"; $templateCode.="\n\tif(document.getElementById('primary_emailEditLink')) { document.getElementById('primary_emailEditLink').style.display='none'; }"; $templateCode.="\n\tif(document.getElementById('alternate_emailEdit')) { document.getElementById('alternate_emailEdit').style.display='inline'; }"; @@ -599,8 +601,8 @@ class="btn btn-default" /* default field values */ $rdata = $jdata = get_defaults('rental_owners'); - if($selected_id) { - $jdata = get_joined_record('rental_owners', $selected_id); + if($hasSelectedId) { + $jdata = get_joined_record('rental_owners', $selectedId); if($jdata === false) $jdata = get_defaults('rental_owners'); $rdata = $row; } @@ -609,7 +611,7 @@ class="btn btn-default" // hook: rental_owners_dv if(function_exists('rental_owners_dv')) { $args = []; - rental_owners_dv(($selected_id ? $selected_id : FALSE), getMemberInfo(), $templateCode, $args); + rental_owners_dv(($hasSelectedId ? $selectedId : FALSE), getMemberInfo(), $templateCode, $args); } return $templateCode; diff --git a/app/residence_and_rental_history_dml.php b/app/residence_and_rental_history_dml.php index 5b72121..0d4c761 100644 --- a/app/residence_and_rental_history_dml.php +++ b/app/residence_and_rental_history_dml.php @@ -183,31 +183,40 @@ function residence_and_rental_history_update(&$selected_id, &$error_message = '' set_record_owner('residence_and_rental_history', $selected_id); } -function residence_and_rental_history_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, $AllowDelete = 1, $separateDV = 0, $TemplateDV = '', $TemplateDVP = '') { +function residence_and_rental_history_form($selectedId = '', $allowUpdate = true, $allowInsert = true, $allowDelete = true, $separateDV = true, $templateDV = '', $templateDVP = '') { // function to return an editable form for a table records - // and fill it with data of record whose ID is $selected_id. If $selected_id + // and fill it with data of record whose ID is $selectedId. If $selectedId // is empty, an empty form is shown, with only an 'Add New' // button displayed. global $Translation; $eo = ['silentErrors' => true]; - $noUploads = null; - $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; - + $noUploads = $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; $noSaveAsCopy = false; + $hasSelectedId = strlen($selectedId) > 0; // mm: get table permissions $arrPerm = getTablePermissions('residence_and_rental_history'); - if(!$arrPerm['insert'] && $selected_id == '') + $allowInsert = ($arrPerm['insert'] ? true : false); + $allowUpdate = $hasSelectedId && check_record_permission('residence_and_rental_history', $selectedId, 'edit'); + $allowDelete = $hasSelectedId && check_record_permission('residence_and_rental_history', $selectedId, 'delete'); + + if(!$allowInsert && !$hasSelectedId) // no insert permission and no record selected - // so show access denied error unless TVDV + // so show access denied error -- except if TVDV: just hide DV return $separateDV ? $Translation['tableAccessDenied'] : ''; - $AllowInsert = ($arrPerm['insert'] ? true : false); + + if($hasSelectedId && !check_record_permission('residence_and_rental_history', $selectedId, 'view')) + return $Translation['tableAccessDenied']; + // print preview? - $dvprint = false; - if(strlen($selected_id) && Request::val('dvprint_x') != '') { - $dvprint = true; - } + $dvprint = $hasSelectedId && Request::val('dvprint_x') != ''; + + $showSaveNew = !$dvprint && ($allowInsert && !$hasSelectedId); + $showSaveChanges = !$dvprint && $allowUpdate && $hasSelectedId; + $showDelete = !$dvprint && $allowDelete && $hasSelectedId; + $showSaveAsCopy = !$dvprint && ($allowInsert && $hasSelectedId && !$noSaveAsCopy); + $fieldsAreEditable = !$dvprint && (($allowInsert && !$hasSelectedId) || ($allowUpdate && $hasSelectedId) || $showSaveAsCopy); $filterer_tenant = Request::val('filterer_tenant'); @@ -234,17 +243,8 @@ function residence_and_rental_history_form($selected_id = '', $AllowUpdate = 1, $combo_to->MonthNames = $Translation['month names']; $combo_to->NamePrefix = 'to'; - if($selected_id) { - if(!check_record_permission('residence_and_rental_history', $selected_id, 'view')) - return $Translation['tableAccessDenied']; - - // can edit? - $AllowUpdate = check_record_permission('residence_and_rental_history', $selected_id, 'edit'); - - // can delete? - $AllowDelete = check_record_permission('residence_and_rental_history', $selected_id, 'delete'); - - $res = sql("SELECT * FROM `residence_and_rental_history` WHERE `id`='" . makeSafe($selected_id) . "'", $eo); + if($hasSelectedId) { + $res = sql("SELECT * FROM `residence_and_rental_history` WHERE `id`='" . makeSafe($selectedId) . "'", $eo); if(!($row = db_fetch_array($res))) { return error_message($Translation['No records found'], 'residence_and_rental_history_view.php', false); } @@ -267,7 +267,7 @@ function residence_and_rental_history_form($selected_id = '', $AllowUpdate = 1, \n"; @@ -604,8 +606,8 @@ class="btn btn-default" /* default field values */ $rdata = $jdata = get_defaults('residence_and_rental_history'); - if($selected_id) { - $jdata = get_joined_record('residence_and_rental_history', $selected_id); + if($hasSelectedId) { + $jdata = get_joined_record('residence_and_rental_history', $selectedId); if($jdata === false) $jdata = get_defaults('residence_and_rental_history'); $rdata = $row; } @@ -614,7 +616,7 @@ class="btn btn-default" // hook: residence_and_rental_history_dv if(function_exists('residence_and_rental_history_dv')) { $args = []; - residence_and_rental_history_dv(($selected_id ? $selected_id : FALSE), getMemberInfo(), $templateCode, $args); + residence_and_rental_history_dv(($hasSelectedId ? $selectedId : FALSE), getMemberInfo(), $templateCode, $args); } return $templateCode; diff --git a/app/resources/lib/CSVImport.php b/app/resources/lib/CSVImport.php index 2a5d7be..3b6ee5a 100644 --- a/app/resources/lib/CSVImport.php +++ b/app/resources/lib/CSVImport.php @@ -876,36 +876,24 @@ private function saveJob() { } private function setupDb() { - $eo = ['silentErrors' => true]; - $tn = self::JOBS_TABLE; - sql( - "CREATE TABLE IF NOT EXISTS `{$tn}` ( - `id` VARCHAR(40) NOT NULL, - `memberID` VARCHAR(100) NOT NULL, - `config` TEXT, - `insert_ts` INT, - `last_update_ts` INT, - `total` INT DEFAULT 99999999, - `done` INT DEFAULT 0, - PRIMARY KEY (`id`), - INDEX `memberID` (`memberID`) - ) CHARSET " . mysql_charset, - $eo); + createTableIfNotExists($tn); + addIndex($tn, 'memberID'); // TODO /* $tn = self::JOBS_LOG_TABLE; - sql( - "CREATE TABLE IF NOT EXISTS `{$tn}` ( - `id` BIGINT NOT NULL AUTO_INCREMENT, - `job_id` VARCHAR(40) NOT NULL, - `ts` INT, - `details` TEXT, - PRIMARY KEY (`id`), - INDEX `job_id` (`job_id`) - ) CHARSET " . mysql_charset, - $eo); + createTableIfNotExists($tn); + addIndex($n, 'job_id'); + + CREATE TABLE IF NOT EXISTS `{$tn}` ( + `id` BIGINT NOT NULL AUTO_INCREMENT, + `job_id` VARCHAR(40) NOT NULL, + `ts` INT, + `details` TEXT, + PRIMARY KEY (`id`), + INDEX `job_id` (`job_id`) + ) CHARSET mysql_charset */ } diff --git a/app/unit_photos_dml.php b/app/unit_photos_dml.php index 57719ee..ed77e1a 100644 --- a/app/unit_photos_dml.php +++ b/app/unit_photos_dml.php @@ -204,31 +204,40 @@ function unit_photos_update(&$selected_id, &$error_message = '') { set_record_owner('unit_photos', $selected_id); } -function unit_photos_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, $AllowDelete = 1, $separateDV = 0, $TemplateDV = '', $TemplateDVP = '') { +function unit_photos_form($selectedId = '', $allowUpdate = true, $allowInsert = true, $allowDelete = true, $separateDV = true, $templateDV = '', $templateDVP = '') { // function to return an editable form for a table records - // and fill it with data of record whose ID is $selected_id. If $selected_id + // and fill it with data of record whose ID is $selectedId. If $selectedId // is empty, an empty form is shown, with only an 'Add New' // button displayed. global $Translation; $eo = ['silentErrors' => true]; - $noUploads = null; - $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; - + $noUploads = $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; $noSaveAsCopy = false; + $hasSelectedId = strlen($selectedId) > 0; // mm: get table permissions $arrPerm = getTablePermissions('unit_photos'); - if(!$arrPerm['insert'] && $selected_id == '') + $allowInsert = ($arrPerm['insert'] ? true : false); + $allowUpdate = $hasSelectedId && check_record_permission('unit_photos', $selectedId, 'edit'); + $allowDelete = $hasSelectedId && check_record_permission('unit_photos', $selectedId, 'delete'); + + if(!$allowInsert && !$hasSelectedId) // no insert permission and no record selected - // so show access denied error unless TVDV + // so show access denied error -- except if TVDV: just hide DV return $separateDV ? $Translation['tableAccessDenied'] : ''; - $AllowInsert = ($arrPerm['insert'] ? true : false); + + if($hasSelectedId && !check_record_permission('unit_photos', $selectedId, 'view')) + return $Translation['tableAccessDenied']; + // print preview? - $dvprint = false; - if(strlen($selected_id) && Request::val('dvprint_x') != '') { - $dvprint = true; - } + $dvprint = $hasSelectedId && Request::val('dvprint_x') != ''; + + $showSaveNew = !$dvprint && ($allowInsert && !$hasSelectedId); + $showSaveChanges = !$dvprint && $allowUpdate && $hasSelectedId; + $showDelete = !$dvprint && $allowDelete && $hasSelectedId; + $showSaveAsCopy = !$dvprint && ($allowInsert && $hasSelectedId && !$noSaveAsCopy); + $fieldsAreEditable = !$dvprint && (($allowInsert && !$hasSelectedId) || ($allowUpdate && $hasSelectedId) || $showSaveAsCopy); $filterer_unit = Request::val('filterer_unit'); @@ -239,17 +248,8 @@ function unit_photos_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, // combobox: unit $combo_unit = new DataCombo; - if($selected_id) { - if(!check_record_permission('unit_photos', $selected_id, 'view')) - return $Translation['tableAccessDenied']; - - // can edit? - $AllowUpdate = check_record_permission('unit_photos', $selected_id, 'edit'); - - // can delete? - $AllowDelete = check_record_permission('unit_photos', $selected_id, 'delete'); - - $res = sql("SELECT * FROM `unit_photos` WHERE `id`='" . makeSafe($selected_id) . "'", $eo); + if($hasSelectedId) { + $res = sql("SELECT * FROM `unit_photos` WHERE `id`='" . makeSafe($selectedId) . "'", $eo); if(!($row = db_fetch_array($res))) { return error_message($Translation['No records found'], 'unit_photos_view.php', false); } @@ -270,7 +270,7 @@ function unit_photos_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, \n"; @@ -556,8 +558,8 @@ class="btn btn-default" /* default field values */ $rdata = $jdata = get_defaults('unit_photos'); - if($selected_id) { - $jdata = get_joined_record('unit_photos', $selected_id); + if($hasSelectedId) { + $jdata = get_joined_record('unit_photos', $selectedId); if($jdata === false) $jdata = get_defaults('unit_photos'); $rdata = $row; } @@ -566,7 +568,7 @@ class="btn btn-default" // hook: unit_photos_dv if(function_exists('unit_photos_dv')) { $args = []; - unit_photos_dv(($selected_id ? $selected_id : FALSE), getMemberInfo(), $templateCode, $args); + unit_photos_dv(($hasSelectedId ? $selectedId : FALSE), getMemberInfo(), $templateCode, $args); } return $templateCode; diff --git a/app/units_dml.php b/app/units_dml.php index acfbfad..0212d55 100644 --- a/app/units_dml.php +++ b/app/units_dml.php @@ -276,31 +276,40 @@ function units_update(&$selected_id, &$error_message = '') { set_record_owner('units', $selected_id); } -function units_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, $AllowDelete = 1, $separateDV = 0, $TemplateDV = '', $TemplateDVP = '') { +function units_form($selectedId = '', $allowUpdate = true, $allowInsert = true, $allowDelete = true, $separateDV = true, $templateDV = '', $templateDVP = '') { // function to return an editable form for a table records - // and fill it with data of record whose ID is $selected_id. If $selected_id + // and fill it with data of record whose ID is $selectedId. If $selectedId // is empty, an empty form is shown, with only an 'Add New' // button displayed. global $Translation; $eo = ['silentErrors' => true]; - $noUploads = null; - $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; - + $noUploads = $row = $urow = $jsReadOnly = $jsEditable = $lookups = null; $noSaveAsCopy = false; + $hasSelectedId = strlen($selectedId) > 0; // mm: get table permissions $arrPerm = getTablePermissions('units'); - if(!$arrPerm['insert'] && $selected_id == '') + $allowInsert = ($arrPerm['insert'] ? true : false); + $allowUpdate = $hasSelectedId && check_record_permission('units', $selectedId, 'edit'); + $allowDelete = $hasSelectedId && check_record_permission('units', $selectedId, 'delete'); + + if(!$allowInsert && !$hasSelectedId) // no insert permission and no record selected - // so show access denied error unless TVDV + // so show access denied error -- except if TVDV: just hide DV return $separateDV ? $Translation['tableAccessDenied'] : ''; - $AllowInsert = ($arrPerm['insert'] ? true : false); + + if($hasSelectedId && !check_record_permission('units', $selectedId, 'view')) + return $Translation['tableAccessDenied']; + // print preview? - $dvprint = false; - if(strlen($selected_id) && Request::val('dvprint_x') != '') { - $dvprint = true; - } + $dvprint = $hasSelectedId && Request::val('dvprint_x') != ''; + + $showSaveNew = !$dvprint && ($allowInsert && !$hasSelectedId); + $showSaveChanges = !$dvprint && $allowUpdate && $hasSelectedId; + $showDelete = !$dvprint && $allowDelete && $hasSelectedId; + $showSaveAsCopy = !$dvprint && ($allowInsert && $hasSelectedId && !$noSaveAsCopy); + $fieldsAreEditable = !$dvprint && (($allowInsert && !$hasSelectedId) || ($allowUpdate && $hasSelectedId) || $showSaveAsCopy); $filterer_property = Request::val('filterer_property'); @@ -342,17 +351,8 @@ function units_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, $Allo } $combo_features->SelectName = 'features'; - if($selected_id) { - if(!check_record_permission('units', $selected_id, 'view')) - return $Translation['tableAccessDenied']; - - // can edit? - $AllowUpdate = check_record_permission('units', $selected_id, 'edit'); - - // can delete? - $AllowDelete = check_record_permission('units', $selected_id, 'delete'); - - $res = sql("SELECT * FROM `units` WHERE `id`='" . makeSafe($selected_id) . "'", $eo); + if($hasSelectedId) { + $res = sql("SELECT * FROM `units` WHERE `id`='" . makeSafe($selectedId) . "'", $eo); if(!($row = db_fetch_array($res))) { return error_message($Translation['No records found'], 'units_view.php', false); } @@ -378,7 +378,7 @@ function units_form($selected_id = '', $AllowUpdate = 1, $AllowInsert = 1, $Allo \n"; @@ -723,7 +725,7 @@ class="btn btn-default" $templateCode .= "\t\t\tcontentType: 'application/x-www-form-urlencoded; charset=" . datalist_db_encoding . "',\n"; $templateCode .= "\t\t\ttype: 'GET',\n"; $templateCode .= "\t\t\tbeforeSend: function() { \$j('#property$rnd1').prop('disabled', true); },\n"; - $templateCode .= "\t\t\tcomplete: function() { " . (($arrPerm['insert'] || (($arrPerm['edit'] == 1 && $ownerMemberID == getLoggedMemberID()) || ($arrPerm['edit'] == 2 && $ownerGroupID == getLoggedGroupID()) || $arrPerm['edit'] == 3)) ? "\$j('#property$rnd1').prop('disabled', false); " : "\$j('#property$rnd1').prop('disabled', true); ")." \$j(window).resize(); }\n"; + $templateCode .= "\t\t\tcomplete: function() { " . (($allowInsert || $allowUpdate) ? "\$j('#property$rnd1').prop('disabled', false); " : "\$j('#property$rnd1').prop('disabled', true); ")." \$j(window).resize(); }\n"; } $templateCode .= "\t\t});\n"; $templateCode .= "\t};\n"; @@ -747,8 +749,8 @@ class="btn btn-default" /* default field values */ $rdata = $jdata = get_defaults('units'); - if($selected_id) { - $jdata = get_joined_record('units', $selected_id); + if($hasSelectedId) { + $jdata = get_joined_record('units', $selectedId); if($jdata === false) $jdata = get_defaults('units'); $rdata = $row; } @@ -757,7 +759,7 @@ class="btn btn-default" // hook: units_dv if(function_exists('units_dv')) { $args = []; - units_dv(($selected_id ? $selected_id : FALSE), getMemberInfo(), $templateCode, $args); + units_dv(($hasSelectedId ? $selectedId : FALSE), getMemberInfo(), $templateCode, $args); } return $templateCode; diff --git a/app/updateDB.php b/app/updateDB.php index 2156cad..f06ffd1 100644 --- a/app/updateDB.php +++ b/app/updateDB.php @@ -9,195 +9,40 @@ // check if this setup file already run if($thisMD5 != $prevMD5) { // set up tables - setupTable( - 'applicants_and_tenants', " - CREATE TABLE IF NOT EXISTS `applicants_and_tenants` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`), - `last_name` VARCHAR(40) NULL, - `first_name` VARCHAR(40) NULL, - `email` VARCHAR(80) NULL, - `phone` VARCHAR(15) NULL, - `birth_date` DATE NULL, - `driver_license_number` VARCHAR(15) NULL, - `driver_license_state` VARCHAR(15) NULL, - `requested_lease_term` VARCHAR(15) NULL, - `monthly_gross_pay` DECIMAL(8,2) NULL, - `additional_income` DECIMAL(8,2) NULL, - `assets` DECIMAL(8,2) NULL, - `status` VARCHAR(40) NOT NULL DEFAULT 'Applicant', - `notes` TEXT NULL - ) CHARSET utf8" - ); - - setupTable( - 'applications_leases', " - CREATE TABLE IF NOT EXISTS `applications_leases` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`), - `tenants` INT UNSIGNED NULL, - `status` VARCHAR(40) NOT NULL DEFAULT 'Application', - `property` INT UNSIGNED NULL, - `unit` INT UNSIGNED NULL, - `type` VARCHAR(40) NOT NULL DEFAULT 'Fixed', - `total_number_of_occupants` VARCHAR(15) NULL, - `start_date` DATE NULL, - `end_date` DATE NULL, - `recurring_charges_frequency` VARCHAR(40) NOT NULL DEFAULT 'Monthly', - `next_due_date` DATE NULL, - `rent` DECIMAL(10,2) NULL, - `security_deposit` DECIMAL(15,2) NULL, - `security_deposit_date` DATE NULL, - `emergency_contact` VARCHAR(100) NULL, - `co_signer_details` VARCHAR(100) NULL, - `notes` TEXT NULL, - `agreement` VARCHAR(40) NULL - ) CHARSET utf8" - ); + setupTable('applicants_and_tenants', []); + + setupTable('applications_leases', []); setupIndexes('applications_leases', ['tenants','property','unit',]); - setupTable( - 'residence_and_rental_history', " - CREATE TABLE IF NOT EXISTS `residence_and_rental_history` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`), - `tenant` INT UNSIGNED NULL, - `address` VARCHAR(40) NULL, - `landlord_or_manager_name` VARCHAR(100) NULL, - `landlord_or_manager_phone` VARCHAR(15) NULL, - `monthly_rent` DECIMAL(10,2) NULL, - `duration_of_residency_from` DATE NULL, - `to` DATE NULL, - `reason_for_leaving` VARCHAR(40) NULL, - `notes` TEXT NULL - ) CHARSET utf8" - ); + setupTable('residence_and_rental_history', []); setupIndexes('residence_and_rental_history', ['tenant',]); - setupTable( - 'employment_and_income_history', " - CREATE TABLE IF NOT EXISTS `employment_and_income_history` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`), - `tenant` INT UNSIGNED NULL, - `employer_name` VARCHAR(100) NULL, - `city` VARCHAR(100) NULL, - `employer_phone` VARCHAR(15) NULL, - `employed_from` DATE NULL, - `employed_till` DATE NULL, - `occupation` VARCHAR(40) NULL, - `notes` TEXT NULL - ) CHARSET utf8" - ); + setupTable('employment_and_income_history', []); setupIndexes('employment_and_income_history', ['tenant',]); - setupTable( - 'references', " - CREATE TABLE IF NOT EXISTS `references` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`), - `tenant` INT UNSIGNED NULL, - `reference_name` VARCHAR(100) NULL, - `phone` VARCHAR(15) NULL - ) CHARSET utf8" - ); + setupTable('references', []); setupIndexes('references', ['tenant',]); - setupTable( - 'rental_owners', " - CREATE TABLE IF NOT EXISTS `rental_owners` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`), - `first_name` VARCHAR(40) NULL, - `last_name` VARCHAR(40) NULL, - `company_name` VARCHAR(40) NULL, - `date_of_birth` DATE NULL, - `primary_email` VARCHAR(40) NULL, - `alternate_email` VARCHAR(40) NULL, - `phone` VARCHAR(40) NULL, - `country` VARCHAR(40) NULL, - `street` VARCHAR(40) NULL, - `city` VARCHAR(40) NULL, - `state` VARCHAR(40) NULL, - `zip` DECIMAL(15,0) NULL, - `comments` TEXT NULL - ) CHARSET utf8" - ); - - setupTable( - 'properties', " - CREATE TABLE IF NOT EXISTS `properties` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`), - `property_name` VARCHAR(100) NOT NULL, - `photo` VARCHAR(40) NULL, - `type` VARCHAR(40) NOT NULL, - `number_of_units` DECIMAL(15,0) NULL, - `owner` INT UNSIGNED NULL, - `operating_account` VARCHAR(40) NULL, - `property_reserve` DECIMAL(15,0) NULL, - `lease_term` VARCHAR(15) NULL, - `country` VARCHAR(40) NULL, - `street` VARCHAR(40) NULL, - `City` VARCHAR(40) NULL, - `State` VARCHAR(40) NULL, - `ZIP` DECIMAL(15,0) NULL - ) CHARSET utf8" - ); + setupTable('rental_owners', []); + + setupTable('properties', []); setupIndexes('properties', ['owner',]); - setupTable( - 'property_photos', " - CREATE TABLE IF NOT EXISTS `property_photos` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`), - `property` INT UNSIGNED NULL, - `photo` VARCHAR(40) NULL, - `description` TEXT NULL - ) CHARSET utf8" - ); + setupTable('property_photos', []); setupIndexes('property_photos', ['property',]); - setupTable( - 'units', " - CREATE TABLE IF NOT EXISTS `units` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`), - `property` INT UNSIGNED NULL, - `unit_number` VARCHAR(40) NULL, - `photo` VARCHAR(40) NULL, - `status` VARCHAR(40) NOT NULL, - `size` VARCHAR(40) NULL, - `country` INT UNSIGNED NULL, - `street` INT UNSIGNED NULL, - `city` INT UNSIGNED NULL, - `state` INT UNSIGNED NULL, - `postal_code` INT UNSIGNED NULL, - `rooms` VARCHAR(40) NULL, - `bathroom` DECIMAL(15,0) NULL, - `features` TEXT NULL, - `market_rent` DECIMAL(15,2) NULL, - `rental_amount` DECIMAL(10,2) NULL, - `deposit_amount` DECIMAL(10,2) NULL, - `description` TEXT NULL - ) CHARSET utf8" - ); + setupTable('units', []); setupIndexes('units', ['property',]); - setupTable( - 'unit_photos', " - CREATE TABLE IF NOT EXISTS `unit_photos` ( - `id` INT UNSIGNED NOT NULL AUTO_INCREMENT, - PRIMARY KEY (`id`), - `unit` INT UNSIGNED NULL, - `photo` VARCHAR(40) NULL, - `description` TEXT NULL - ) CHARSET utf8" - ); + setupTable('unit_photos', []); setupIndexes('unit_photos', ['unit',]); + // set up internal tables + setupTable('appgini_query_log', []); + setupTable('appgini_csv_import_jobs', []); + // save MD5 @file_put_contents($setupHash, $thisMD5); } @@ -216,15 +61,17 @@ function setupIndexes($tableName, $arrFields) { } - function setupTable($tableName, $createSQL = '', $arrAlter = '') { + function setupTable($tableName, $arrAlter = []) { global $Translation; $oldTableName = ''; + + $createSQL = createTableIfNotExists($tableName, true); ob_start(); echo '
'; // is there a table rename query? - if(is_array($arrAlter)) { + if(!empty($arrAlter)) { $matches = []; if(preg_match("/ALTER TABLE `(.*)` RENAME `$tableName`/i", $arrAlter[0], $matches)) { $oldTableName = $matches[1]; @@ -234,7 +81,7 @@ function setupTable($tableName, $createSQL = '', $arrAlter = '') { if($res = @db_query("SELECT COUNT(1) FROM `$tableName`")) { // table already exists if($row = @db_fetch_array($res)) { echo str_replace(['', ''], [$tableName, $row[0]], $Translation['table exists']); - if(is_array($arrAlter)) { + if(!empty($arrAlter)) { echo '
'; foreach($arrAlter as $alter) { if($alter != '') { @@ -267,9 +114,9 @@ function setupTable($tableName, $createSQL = '', $arrAlter = '') { echo '' . $Translation['ok'] . ''; } - if(is_array($arrAlter)) setupTable($tableName, $createSQL, false, $arrAlter); // execute Alter queries on renamed table ... + if(!empty($arrAlter)) setupTable($tableName, $arrAlter); // execute Alter queries on renamed table ... } else { // if old tableName doesn't exist (nor the new one since we're here), then just create the table. - setupTable($tableName, $createSQL, false); // no Alter queries passed ... + setupTable($tableName); // no Alter queries passed ... } } else { // tableName doesn't exist and no rename, so just create the table echo str_replace("", $tableName, $Translation["creating table"]); diff --git a/orpm.axp b/orpm.axp index 4c39935..fa00a93 100644 --- a/orpm.axp +++ b/orpm.axp @@ -1 +1 @@ -rental_property_managerlocalhostUTF-8FalseFalse12FalseAmerica/New_YorkFalseFalseTrueFalsebootstrap.cssTrueTrue03424.132024-05-20 21:55:41C:\Users\micro\vm-shared\appgini-open-source-apps\online-rental-property-manager\app0False402TrueTrueFalseFalse{"events":{"end-of-lease":{"type":"end-of-lease","color":"danger","textColor":"danger","table":"applications_leases","customWhere":"`applications_leases`.`status` = 'Lease'","title":"<b>End of lease</b><br>Property {4} unit# {5}","allDay":true,"startDateField":"end_date","startTimeField":"","endDateField":"","endTimeField":""},"start-of-lease":{"type":"start-of-lease","color":"success","textColor":"success","table":"applications_leases","customWhere":"`applications_leases`.`status` = 'Lease'","title":"<b>Start of lease</b><br>Property {4} unit# {5}","allDay":true,"startDateField":"start_date","startTimeField":"","endDateField":"","endTimeField":""}},"calendars":{"lease-start-end":{"id":"lease-start-end","title":"Leases starting/ending","initial-view":"dayGridMonth","initial-date":"[today]","events":["end-of-lease","start-of-lease"],"locale":"","groups":["Admins"],"links-home":"1","links-navmenu":"1"}}}dummy12:9:1:4:13:9001:[{"report_hash":"id5fq91qu393nf0k42r1","title":"Applicants By Status","table":"applicants_and_tenants","table_index":0,"label":"status","caption1":"Status","caption2":"Count of Applicants and tenants","group_function":"count","group_function_field":null,"group_array":[],"look_up_table":"","look_up_value":"","label_field_index":"13","report_header_url":"","report_footer_url":"","data_table_section":1,"barchart_section":0,"piechart_section":1,"override_permissions":0,"custom_where":"","date_separator":"\/"}][{"label":"Change status","icon":"circle-arrow-right","field":"status","value":"allowUserToSpecify","fixedValue":"","confirmation":1,"groups":[],"hash":"m8xfpspfv9y3762768or"},{"label":"Edit Notes","icon":"pencil","field":"notes","value":"allowUserToSpecify","fixedValue":"","confirmation":1,"groups":[],"hash":"li3ml58uplm5oyp54b8x"}]applicants_and_tenantsFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010references;employment_and_income_history;residence_and_rental_history;applications_leasesTrueFalseFalse2ascaccount_balances.png0False0TruehorizontalFalseFalse25%-1id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falselast_name15400FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse1False00FalseFalseleft0000Falsefirst_name15400FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falseemail15800FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3False31FalseFalseleft0000Falsephone15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse4False00FalseFalseleft0000Falsebirth_date900FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse5False00FalseFalseleft0000Falsedriver_license_number15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse6False00FalseFalsecenter0000Falsedriver_license_state15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueTrueFalseFalse7False00FalseFalsecenter0000Falserequested_lease_term15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueTrueFalseFalse8False00FalseFalseleft0000Falsemonthly_gross_pay882FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse9False00FalseFalseright0000Falseadditional_income882FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse10False00FalseFalseright0000Falseassets882FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse11False00FalseFalseright0000Falsestatus15400FalseFalseTrueFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse12False00FalseFalsecenter0000Falsenotes1800FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseTrueFalseFalse13True00FalseFalseleft0000False
1:3:2:5:7:8:16:9001:[{"report_hash":"rs1tinh2qcc2azdob0r6","title":"Applications\/Leases Over Time","table":"applications_leases","table_index":1,"label":"status","caption1":"Application status","caption2":"Count of Applications\/Leases","group_function":"count","group_function_field":null,"group_array":[],"look_up_table":"","look_up_value":"","label_field_index":"3","date_field":"start_date","date_field_index":"8","report_header_url":"","report_footer_url":"","data_table_section":1,"barchart_section":1,"piechart_section":0,"override_permissions":0,"custom_where":"","date_separator":"\/"},{"report_hash":"7dlamlewaen7fh5e7omb","title":"Applications\/Leases By Property","table":"applications_leases","table_index":1,"label":"property","caption1":"Property","caption2":"Count of Applications\/Leases","group_function":"count","group_function_field":null,"group_array":[],"look_up_table":"properties","look_up_value":"property_name","label_field_index":"4","date_field":"start_date","date_field_index":"8","report_header_url":"","report_footer_url":"","data_table_section":1,"barchart_section":0,"piechart_section":1,"override_permissions":0,"custom_where":"","date_separator":"\/"},{"report_hash":"uh2omkvwpr1oqfvdt70y","title":"Leases By Property Over Time","table":"applications_leases","table_index":1,"label":"property","caption1":"Property","caption2":"Count of Applications\/Leases","group_function":"count","group_function_field":null,"group_array":[],"look_up_table":"properties","look_up_value":"property_name","label_field_index":"4","date_field":"start_date","date_field_index":"8","report_header_url":"","report_footer_url":"","data_table_section":1,"barchart_section":0,"piechart_section":1,"override_permissions":0,"custom_where":"`applications_leases`.`status`='Lease'","date_separator":"\/"},{"report_hash":"lezfr2w8z8mwp5yq26pw","title":"Lease Value By Property Over Time","table":"applications_leases","table_index":1,"label":"property","caption1":"Property","caption2":"Sum of Applications\/Leases","group_function":"sum","group_function_field":"rent","group_array":[],"look_up_table":"properties","look_up_value":"property_name","label_field_index":"4","date_field":"start_date","date_field_index":"8","report_header_url":"","report_footer_url":"","data_table_section":1,"barchart_section":0,"piechart_section":1,"override_permissions":0,"custom_where":"`applications_leases`.`status` LIKE '%lease'","date_separator":"\/"}][{"label":"Approve application","icon":"ok","field":"status","value":"fixedValue","fixedValue":"Lease","confirmation":1,"groups":[],"hash":"ghqe4agakj7de10gc0ba"}]applications_leasesFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010TrueFalseFalse0asccurriculum_vitae.png0True0TruehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falsetenants400FalseFalseFalseFalseFalseTrueFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsefirst_namelast_nameidapplicants_and_tenantsTrueFalseFalse01FalseFalseFalseFalse1False00FalseFalseleft0000Falsestatus15400FalseFalseTrueFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse2False00FalseFalseleft0000Falseproperty400FalseFalseFalseFalseFalseTrueFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseproperty_nameidpropertiesTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000Falseunit400FalseFalseFalseFalseFalseTrueFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseunit_numberidunitsTrueFalseFalse01FalseFalseFalseFalse4False00FalseFalsepropertyleft0000Falsetype15400FalseFalseTrueFalseFalseFalseFalseFalse40True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse5False00FalseFalseleft0000Falsetotal_number_of_occupants15150FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse6False00FalseFalsecenter0000Falsestart_date900FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse7False00FalseFalseleft0000Falseend_date900FalseFalseFalseFalseFalseFalseFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse8False00FalseFalseleft0000Falserecurring_charges_frequency15400FalseFalseTrueFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse9False00FalseFalseleft0000Falsenext_due_date900FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse10False00FalseFalseleft0000Falserent8102FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse11False00FalseFalseright0000Falsesecurity_deposit8152FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse12False00FalseFalseright0000Falsesecurity_deposit_date900FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse13False00FalseFalseleft0000Falseemergency_contact151000FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse14False00FalseFalseleft0000Falseco_signer_details151000FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse15False00FalseFalseleft0000Falsenotes1800FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse16True00FalseFalseleft0000FalseThe applicant must agree to the following terms:
  1. I understand that this is a routine application to establish credit, character, employment, and rental history.

  2. I also understand that this is NOT an agreement to rent and that all applications must be approved.

  3. I authorize verification of references given.

  4. I declare that the statements above are true and correct, and I agree that the landlord may terminate my agreement entered into in reliance on any misstatement made above.

  5. ]]>agreement15400FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse17False00TrueFalsecenter0000False
1:8:9:9001:residence_and_rental_historyFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010TrueTrueTrue0ascdocument_comment_above.png0True0FalsehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falsetenant400FalseFalseFalseFalseFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsefirst_namelast_nameidapplicants_and_tenantsTrueFalseFalse01TrueFalseFalseFalse1False00FalseFalseright0000Falseaddress15400FalseFalseFalseFalseFalseTrueFalseFalse180True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falselandlord_or_manager_name151000FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000Falselandlord_or_manager_phone15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse4False00FalseFalseleft0000Falsemonthly_rent8102FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse5False00FalseFalseright0000Falseduration_of_residency_from900FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse6False00FalseFalseleft0000Falseto900FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse7False00FalseFalseleft0000Falsereason_for_leaving15400FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse8False00FalseFalseleft0000Falsenotes1800FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse9True00FalseFalseleft0000False
1:2:7:8:9001:employment_and_income_historyFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010TrueTrueTrue0asccash_stack.png0True0FalsehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falsetenant400FalseFalseFalseFalseFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsefirst_namelast_nameidapplicants_and_tenantsTrueFalseFalse01TrueFalseFalseFalse1False00FalseFalseright0000Falseemployer_name151000FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsecity151000FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000Falseemployer_phone15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse4False00FalseFalseleft0000Falseemployed_from900FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse5False00FalseFalseleft0000Falseemployed_till900FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse6False00FalseFalseleft0000Falseoccupation15400FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse7False00FalseFalsecenter0000Falsenotes1800FalseFalseFalseFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse8True00FalseFalseleft0000False
1:9001:referencesFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010TrueTrueTrue0ascapplication_from_storage.png0True0FalsehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falsetenant400FalseFalseFalseFalseFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsefirst_namelast_nameidapplicants_and_tenantsTrueFalseFalse01TrueFalseFalseFalse1False00FalseFalseleft0000Falsereference_name151000FalseFalseFalseFalseFalseFalseFalseFalse160True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsephone15150FalseFalseFalseFalseFalseFalseFalseFalse160True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000False
2:7:13:9001:rental_ownersFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010propertiesTrueFalseFalse0ascadministrator.png0True1TruehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falsefirst_name15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse1False00FalseFalseleft0000Falselast_name15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsecompany_name15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000Falsedate_of_birth900FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse4False00FalseFalseleft0000Falseprimary_email15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse5False31FalseFalseleft0000Falsealternate_email15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse6False31FalseFalseleft0000Falsephone15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse7False00FalseFalseleft0000Falsecountry15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse8False00FalseFalseleft0000Falsestreet15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse9False00FalseFalseleft0000Falsecity15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse10False00FalseFalseleft0000Falsestate15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse11False00FalseFalseleft0000Falsezip8150FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse12False00FalseFalseright0000Falsecomments1800FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse13True00FalseFalseleft0000False
3:5:6:11:13:12:9001:propertiesFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010property_photos;units;applications_leasesTrueFalseFalse1descapplication_home.png0True1Trueleft_imageTrueFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falseproperty_name151000FalseFalseTrueFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse1False00FalseFalseleft0000FalseAllowed file types: jpg, jpeg, gif, png, webp]]>photo15400FalseFalseFalseFalseFalseFalseFalseFalse60True0TrueTrueFalseTrue250300TrueFalseTrue600800FalseFalse2048000jpg|jpeg|gif|png|webpFalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsetype15400FalseFalseTrueFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse3False00FalseFalseleft0000Falsenumber_of_units8150FalseFalseFalseFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse4False00FalseFalseleft0000Falseowner400FalseFalseFalseFalseFalseTrueFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsefirst_namelast_nameidrental_ownersTrueFalseFalse01FalseFalseFalseFalse5False00FalseFalseleft0000Falseoperating_account15400FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseTrueFalseFalse6False00FalseFalseleft0000Falseproperty_reserve8150FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseTrueFalseFalse7False00FalseFalseright0000Falselease_term15150FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueTrueFalseFalse8False00FalseFalseleft0000Falsecountry15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse9False00FalseFalseleft0000Falsestreet15400FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse10False00FalseFalseleft0000FalseCity15400FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse11False00FalseFalseleft0000FalseState15400FalseFalseFalseFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse12False00FalseFalseleft0000FalseZIP8150FalseFalseFalseFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse13False00FalseFalseleft0000False
1:3:9001:property_photosFalseFalseTrueFalseFalseTrueFalseTrueTrueFalseTrueTrueTrueFalseTrueTrue11010TrueTrueTrue0asccamera_link.png0True1FalsehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falseproperty400FalseFalseFalseFalseFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseproperty_nameidpropertiesTrueTrueFalse00TrueFalseFalseFalse1False00FalseFalseleft0000FalseAllowed file types: jpg, jpeg, gif, png]]>photo15400FalseFalseFalseFalseFalseFalseFalseFalse150False0TrueTrueFalseTrue100100TrueFalseTrue250250FalseFalse2048000jpg|jpeg|gif|png|webpFalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsedescription1800FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3True00FalseFalseleft0000False
1:8:7:9:2:4:11:12:13:15:9001:[{"label":"Change status","icon":"tags","field":"status","value":"allowUserToSpecify","fixedValue":"","confirmation":1,"groups":[],"hash":"02ra72cumuxuqy0sm1hq"}]unitsFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010unit_photos;applications_leasesTrueFalseFalse2ascchange_password.png0True1TruehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falseproperty400FalseFalseFalseFalseFalseTrueFalseFalse90True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseproperty_nameidpropertiesTrueFalseFalse01FalseFalseFalseFalse1False00FalseFalseleft0000Falseunit_number15400FalseFalseFalseFalseFalseTrueFalseFalse40True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000FalseAllowed file types: jpg, jpeg, gif, png]]>photo15400FalseFalseFalseFalseFalseFalseFalseFalse60True0TrueTrueFalseTrue250250TrueFalseTrue250250FalseFalse2048000jpg|jpeg|gif|png|webpFalseFalseTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000Falsestatus15400FalseFalseTrueFalseFalseFalseFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse4False00FalseFalseleft0000Falsesize15400FalseFalseFalseFalseFalseFalseFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse5False00FalseFalsecenter0000Falsecountry400FalseFalseFalseFalseFalseTrueFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsecountryidpropertiesTrueFalseTrue01TrueFalseFalseFalse6False00FalseFalseleft0000Falsestreet400FalseFalseFalseFalseFalseTrueFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsestreetidpropertiesTrueFalseTrue01FalseFalseFalseFalse7False00FalseFalseleft0000Falsecity400FalseFalseFalseFalseFalseTrueFalseFalse55True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseCityidpropertiesTrueFalseTrue01FalseFalseFalseFalse8False00FalseFalseleft0000Falsestate400FalseFalseFalseFalseFalseTrueFalseFalse40True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseStateidpropertiesTrueFalseTrue01FalseFalseFalseFalse9False00FalseFalsecenter0000Falsepostal_code400FalseFalseFalseFalseFalseTrueFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseZIPidpropertiesTrueFalseTrue01TrueFalseFalseFalse10False00FalseFalseleft0000Falserooms15400FalseFalseFalseFalseFalseFalseFalseFalse45True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse11False00FalseFalsecenter0000Falsebathroom8150FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse12False00FalseFalsecenter0000Falsefeatures1800FalseFalseFalseFalseFalseFalseFalseFalse150True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse31FalseFalseFalseFalse13False00FalseFalseleft0000Falsemarket_rent8152FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueTrueFalseFalse14False00FalseFalseright0000Falserental_amount8102FalseFalseFalseFalseFalseFalseFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse15False00FalseFalseright0000Falsedeposit_amount8102FalseFalseFalseFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueTrueFalseFalse16False00FalseFalseright0000Falsedescription1800FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse17True00FalseFalseleft0000False
1:3:9001:unit_photosFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010TrueTrueTrue0asccamera_link.png0True1FalsehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falseunit400FalseFalseFalseFalseFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsepropertyunit_numberidunitsTrueTrueFalse00TrueFalseFalseFalse1False00FalseFalseleft0000FalseAllowed file types: jpg, jpeg, gif, png]]>photo15400FalseFalseFalseFalseFalseFalseFalseFalse150False0TrueTrueFalseTrue100100TrueFalseTrue250250FalseFalse2048000jpg|jpeg|gif|png|webpFalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsedescription1800FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3True00FalseFalseleft0000False
+rental_property_managerlocalhostUTF-8FalseFalse12FalseAmerica/New_YorkFalseFalseTrueFalsebootstrap.cssTrueTrue03424.142024-06-04 18:41:56C:\Users\micro\vm-shared\appgini-open-source-apps\online-rental-property-manager\app0False402TrueTrueFalseFalse{"events":{"end-of-lease":{"type":"end-of-lease","color":"danger","textColor":"danger","table":"applications_leases","customWhere":"`applications_leases`.`status` = 'Lease'","title":"<b>End of lease</b><br>Property {4} unit# {5}","allDay":true,"startDateField":"end_date","startTimeField":"","endDateField":"","endTimeField":""},"start-of-lease":{"type":"start-of-lease","color":"success","textColor":"success","table":"applications_leases","customWhere":"`applications_leases`.`status` = 'Lease'","title":"<b>Start of lease</b><br>Property {4} unit# {5}","allDay":true,"startDateField":"start_date","startTimeField":"","endDateField":"","endTimeField":""}},"calendars":{"lease-start-end":{"id":"lease-start-end","title":"Leases starting/ending","initial-view":"dayGridMonth","initial-date":"[today]","events":["end-of-lease","start-of-lease"],"locale":"","groups":["Admins"],"links-home":"1","links-navmenu":"1"}}}dummy12:9:1:4:13:9001:[{"report_hash":"id5fq91qu393nf0k42r1","title":"Applicants By Status","table":"applicants_and_tenants","table_index":0,"label":"status","caption1":"Status","caption2":"Count of Applicants and tenants","group_function":"count","group_function_field":null,"group_array":[],"look_up_table":"","look_up_value":"","label_field_index":"13","report_header_url":"","report_footer_url":"","data_table_section":1,"barchart_section":0,"piechart_section":1,"override_permissions":0,"custom_where":"","date_separator":"\/"}][{"label":"Change status","icon":"circle-arrow-right","field":"status","value":"allowUserToSpecify","fixedValue":"","confirmation":1,"groups":[],"hash":"m8xfpspfv9y3762768or"},{"label":"Edit Notes","icon":"pencil","field":"notes","value":"allowUserToSpecify","fixedValue":"","confirmation":1,"groups":[],"hash":"li3ml58uplm5oyp54b8x"}]applicants_and_tenantsFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010references;employment_and_income_history;residence_and_rental_history;applications_leasesTrueFalseFalse2ascaccount_balances.png0False0TruehorizontalFalseFalse25%-1id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falselast_name15400FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse1False00FalseFalseleft0000Falsefirst_name15400FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falseemail15800FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3False31FalseFalseleft0000Falsephone15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse4False00FalseFalseleft0000Falsebirth_date900FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse5False00FalseFalseleft0000Falsedriver_license_number15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse6False00FalseFalsecenter0000Falsedriver_license_state15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueTrueFalseFalse7False00FalseFalsecenter0000Falserequested_lease_term15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueTrueFalseFalse8False00FalseFalseleft0000Falsemonthly_gross_pay882FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse9False00FalseFalseright0000Falseadditional_income882FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse10False00FalseFalseright0000Falseassets882FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse11False00FalseFalseright0000Falsestatus15400FalseFalseTrueFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse12False00FalseFalsecenter0000Falsenotes1800FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseTrueFalseFalse13True00FalseFalseleft0000False
1:3:2:5:7:8:16:9001:[{"report_hash":"rs1tinh2qcc2azdob0r6","title":"Applications\/Leases Over Time","table":"applications_leases","table_index":1,"label":"status","caption1":"Application status","caption2":"Count of Applications\/Leases","group_function":"count","group_function_field":null,"group_array":[],"look_up_table":"","look_up_value":"","label_field_index":"3","date_field":"start_date","date_field_index":"8","report_header_url":"","report_footer_url":"","data_table_section":1,"barchart_section":1,"piechart_section":0,"override_permissions":0,"custom_where":"","date_separator":"\/"},{"report_hash":"7dlamlewaen7fh5e7omb","title":"Applications\/Leases By Property","table":"applications_leases","table_index":1,"label":"property","caption1":"Property","caption2":"Count of Applications\/Leases","group_function":"count","group_function_field":null,"group_array":[],"look_up_table":"properties","look_up_value":"property_name","label_field_index":"4","date_field":"start_date","date_field_index":"8","report_header_url":"","report_footer_url":"","data_table_section":1,"barchart_section":0,"piechart_section":1,"override_permissions":0,"custom_where":"","date_separator":"\/"},{"report_hash":"uh2omkvwpr1oqfvdt70y","title":"Leases By Property Over Time","table":"applications_leases","table_index":1,"label":"property","caption1":"Property","caption2":"Count of Applications\/Leases","group_function":"count","group_function_field":null,"group_array":[],"look_up_table":"properties","look_up_value":"property_name","label_field_index":"4","date_field":"start_date","date_field_index":"8","report_header_url":"","report_footer_url":"","data_table_section":1,"barchart_section":0,"piechart_section":1,"override_permissions":0,"custom_where":"`applications_leases`.`status`='Lease'","date_separator":"\/"},{"report_hash":"lezfr2w8z8mwp5yq26pw","title":"Lease Value By Property Over Time","table":"applications_leases","table_index":1,"label":"property","caption1":"Property","caption2":"Sum of Applications\/Leases","group_function":"sum","group_function_field":"rent","group_array":[],"look_up_table":"properties","look_up_value":"property_name","label_field_index":"4","date_field":"start_date","date_field_index":"8","report_header_url":"","report_footer_url":"","data_table_section":1,"barchart_section":0,"piechart_section":1,"override_permissions":0,"custom_where":"`applications_leases`.`status` LIKE '%lease'","date_separator":"\/"}][{"label":"Approve application","icon":"ok","field":"status","value":"fixedValue","fixedValue":"Lease","confirmation":1,"groups":[],"hash":"ghqe4agakj7de10gc0ba"}]applications_leasesFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010TrueFalseFalse0asccurriculum_vitae.png0True0TruehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falsetenants400FalseFalseFalseFalseFalseTrueFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsefirst_namelast_nameidapplicants_and_tenantsTrueFalseFalse01FalseFalseFalseFalse1False00FalseFalseleft0000Falsestatus15400FalseFalseTrueFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse2False00FalseFalseleft0000Falseproperty400FalseFalseFalseFalseFalseTrueFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseproperty_nameidpropertiesTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000Falseunit400FalseFalseFalseFalseFalseTrueFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseunit_numberidunitsTrueFalseFalse01FalseFalseFalseFalse4False00FalseFalsepropertyleft0000Falsetype15400FalseFalseTrueFalseFalseFalseFalseFalse40True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse5False00FalseFalseleft0000Falsetotal_number_of_occupants15150FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse6False00FalseFalsecenter0000Falsestart_date900FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse7False00FalseFalseleft0000Falseend_date900FalseFalseFalseFalseFalseFalseFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse8False00FalseFalseleft0000Falserecurring_charges_frequency15400FalseFalseTrueFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse9False00FalseFalseleft0000Falsenext_due_date900FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse10False00FalseFalseleft0000Falserent8102FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse11False00FalseFalseright0000Falsesecurity_deposit8152FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse12False00FalseFalseright0000Falsesecurity_deposit_date900FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse13False00FalseFalseleft0000Falseemergency_contact151000FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse14False00FalseFalseleft0000Falseco_signer_details151000FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse15False00FalseFalseleft0000Falsenotes1800FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse16True00FalseFalseleft0000FalseThe applicant must agree to the following terms:
  1. I understand that this is a routine application to establish credit, character, employment, and rental history.

  2. I also understand that this is NOT an agreement to rent and that all applications must be approved.

  3. I authorize verification of references given.

  4. I declare that the statements above are true and correct, and I agree that the landlord may terminate my agreement entered into in reliance on any misstatement made above.

  5. ]]>agreement15400FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse17False00TrueFalsecenter0000False
1:8:9:9001:residence_and_rental_historyFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010TrueTrueTrue0ascdocument_comment_above.png0True0FalsehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falsetenant400FalseFalseFalseFalseFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsefirst_namelast_nameidapplicants_and_tenantsTrueFalseFalse01TrueFalseFalseFalse1False00FalseFalseright0000Falseaddress15400FalseFalseFalseFalseFalseTrueFalseFalse180True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falselandlord_or_manager_name151000FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000Falselandlord_or_manager_phone15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse4False00FalseFalseleft0000Falsemonthly_rent8102FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse5False00FalseFalseright0000Falseduration_of_residency_from900FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse6False00FalseFalseleft0000Falseto900FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse7False00FalseFalseleft0000Falsereason_for_leaving15400FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse8False00FalseFalseleft0000Falsenotes1800FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse9True00FalseFalseleft0000False
1:2:7:8:9001:employment_and_income_historyFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010TrueTrueTrue0asccash_stack.png0True0FalsehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falsetenant400FalseFalseFalseFalseFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsefirst_namelast_nameidapplicants_and_tenantsTrueFalseFalse01TrueFalseFalseFalse1False00FalseFalseright0000Falseemployer_name151000FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsecity151000FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000Falseemployer_phone15150FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse4False00FalseFalseleft0000Falseemployed_from900FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse5False00FalseFalseleft0000Falseemployed_till900FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse6False00FalseFalseleft0000Falseoccupation15400FalseFalseFalseFalseFalseFalseFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse7False00FalseFalsecenter0000Falsenotes1800FalseFalseFalseFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse8True00FalseFalseleft0000False
1:9001:referencesFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010TrueTrueTrue0ascapplication_from_storage.png0True0FalsehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falsetenant400FalseFalseFalseFalseFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsefirst_namelast_nameidapplicants_and_tenantsTrueFalseFalse01TrueFalseFalseFalse1False00FalseFalseleft0000Falsereference_name151000FalseFalseFalseFalseFalseFalseFalseFalse160True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsephone15150FalseFalseFalseFalseFalseFalseFalseFalse160True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000False
2:7:13:9001:rental_ownersFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010propertiesTrueFalseFalse0ascadministrator.png0True1TruehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falsefirst_name15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse1False00FalseFalseleft0000Falselast_name15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsecompany_name15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000Falsedate_of_birth900FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse4False00FalseFalseleft0000Falseprimary_email15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse5False31FalseFalseleft0000Falsealternate_email15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse6False31FalseFalseleft0000Falsephone15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse7False00FalseFalseleft0000Falsecountry15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse8False00FalseFalseleft0000Falsestreet15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse9False00FalseFalseleft0000Falsecity15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse10False00FalseFalseleft0000Falsestate15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse11False00FalseFalseleft0000Falsezip8150FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse12False00FalseFalseright0000Falsecomments1800FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse13True00FalseFalseleft0000False
3:5:6:11:13:12:9001:propertiesFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010property_photos;units;applications_leasesTrueFalseFalse1descapplication_home.png0True1Trueleft_imageTrueFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falseproperty_name151000FalseFalseTrueFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse1False00FalseFalseleft0000FalseAllowed file types: jpg, jpeg, gif, png, webp]]>photo15400FalseFalseFalseFalseFalseFalseFalseFalse60True0TrueTrueFalseTrue250300TrueFalseTrue600800FalseFalse2048000jpg|jpeg|gif|png|webpFalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsetype15400FalseFalseTrueFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse3False00FalseFalseleft0000Falsenumber_of_units8150FalseFalseFalseFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse4False00FalseFalseleft0000Falseowner400FalseFalseFalseFalseFalseTrueFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsefirst_namelast_nameidrental_ownersTrueFalseFalse01FalseFalseFalseFalse5False00FalseFalseleft0000Falseoperating_account15400FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseTrueFalseFalse6False00FalseFalseleft0000Falseproperty_reserve8150FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseTrueFalseFalse7False00FalseFalseright0000Falselease_term15150FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueTrueFalseFalse8False00FalseFalseleft0000Falsecountry15400FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse9False00FalseFalseleft0000Falsestreet15400FalseFalseFalseFalseFalseFalseFalseFalse120True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse10False00FalseFalseleft0000FalseCity15400FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse11False00FalseFalseleft0000FalseState15400FalseFalseFalseFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse12False00FalseFalseleft0000FalseZIP8150FalseFalseFalseFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse13False00FalseFalseleft0000False
1:3:9001:property_photosFalseFalseTrueFalseFalseTrueFalseTrueTrueFalseTrueTrueTrueFalseTrueTrue11010TrueTrueTrue0asccamera_link.png0True1FalsehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falseproperty400FalseFalseFalseFalseFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseproperty_nameidpropertiesTrueTrueFalse00TrueFalseFalseFalse1False00FalseFalseleft0000FalseAllowed file types: jpg, jpeg, gif, png]]>photo15400FalseFalseFalseFalseFalseFalseFalseFalse150False0TrueTrueFalseTrue100100TrueFalseTrue250250FalseFalse2048000jpg|jpeg|gif|png|webpFalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsedescription1800FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3True00FalseFalseleft0000False
1:8:7:9:2:4:11:12:13:15:9001:[{"label":"Change status","icon":"tags","field":"status","value":"allowUserToSpecify","fixedValue":"","confirmation":1,"groups":[],"hash":"02ra72cumuxuqy0sm1hq"}]unitsFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010unit_photos;applications_leasesTrueFalseFalse2ascchange_password.png0True1TruehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falseproperty400FalseFalseFalseFalseFalseTrueFalseFalse90True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseproperty_nameidpropertiesTrueFalseFalse01FalseFalseFalseFalse1False00FalseFalseleft0000Falseunit_number15400FalseFalseFalseFalseFalseTrueFalseFalse40True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000FalseAllowed file types: jpg, jpeg, gif, png]]>photo15400FalseFalseFalseFalseFalseFalseFalseFalse60True0TrueTrueFalseTrue250250TrueFalseTrue250250FalseFalse2048000jpg|jpeg|gif|png|webpFalseFalseTrueFalseFalse01FalseFalseFalseFalse3False00FalseFalseleft0000Falsestatus15400FalseFalseTrueFalseFalseFalseFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse21FalseFalseFalseFalse4False00FalseFalseleft0000Falsesize15400FalseFalseFalseFalseFalseFalseFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse5False00FalseFalsecenter0000Falsecountry400FalseFalseFalseFalseFalseTrueFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsecountryidpropertiesTrueFalseTrue01TrueFalseFalseFalse6False00FalseFalseleft0000Falsestreet400FalseFalseFalseFalseFalseTrueFalseFalse100True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsestreetidpropertiesTrueFalseTrue01FalseFalseFalseFalse7False00FalseFalseleft0000Falsecity400FalseFalseFalseFalseFalseTrueFalseFalse55True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseCityidpropertiesTrueFalseTrue01FalseFalseFalseFalse8False00FalseFalseleft0000Falsestate400FalseFalseFalseFalseFalseTrueFalseFalse40True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseStateidpropertiesTrueFalseTrue01FalseFalseFalseFalse9False00FalseFalsecenter0000Falsepostal_code400FalseFalseFalseFalseFalseTrueFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseZIPidpropertiesTrueFalseTrue01TrueFalseFalseFalse10False00FalseFalseleft0000Falserooms15400FalseFalseFalseFalseFalseFalseFalseFalse45True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse11False00FalseFalsecenter0000Falsebathroom8150FalseFalseFalseFalseFalseFalseFalseFalse70True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse12False00FalseFalsecenter0000Falsefeatures1800FalseFalseFalseFalseFalseFalseFalseFalse150True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse31FalseFalseFalseFalse13False00FalseFalseleft0000Falsemarket_rent8152FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueTrueFalseFalse14False00FalseFalseright0000Falserental_amount8102FalseFalseFalseFalseFalseFalseFalseFalse60True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse15False00FalseFalseright0000Falsedeposit_amount8102FalseFalseFalseFalseFalseFalseFalseFalse50True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueTrueFalseFalse16False00FalseFalseright0000Falsedescription1800FalseFalseFalseFalseFalseFalseFalseFalse80True0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse17True00FalseFalseleft0000False
1:3:9001:unit_photosFalseFalseTrueFalseFalseTrueFalseTrueTrueTrueTrueTrueTrueFalseTrueTrue11010TrueTrueTrue0asccamera_link.png0True1FalsehorizontalFalseFalse25%id400TrueFalseFalseTrueFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01TrueFalseFalseFalse0False00FalseFalseright0000Falseunit400FalseFalseFalseFalseFalseTrueFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalsepropertyunit_numberidunitsTrueTrueFalse00TrueFalseFalseFalse1False00FalseFalseleft0000FalseAllowed file types: jpg, jpeg, gif, png]]>photo15400FalseFalseFalseFalseFalseFalseFalseFalse150False0TrueTrueFalseTrue100100TrueFalseTrue250250FalseFalse2048000jpg|jpeg|gif|png|webpFalseFalseTrueFalseFalse01FalseFalseFalseFalse2False00FalseFalseleft0000Falsedescription1800FalseFalseFalseFalseFalseFalseFalseFalse150False0FalseFalseFalseFalse00FalseFalseFalse00FalseFalse0FalseFalseTrueFalseFalse01FalseFalseFalseFalse3True00FalseFalseleft0000False