Commit 3d3a392f authored by Carsten  Rose's avatar Carsten Rose
Browse files

Merge branch 'develop' into F9052_Report_CodeMirror

parents b2402f14 3d09a019
......@@ -1289,7 +1289,9 @@ Type: date
* Range datetime: '1000-01-01' to '9999-12-31' or '0000-00-00'. (http://dev.mysql.com/doc/refman/5.5/en/datetime.html)
* Optional:
* *FormElement.parameter.dateFormat*: yyyy-mm-dd | dd.mm.yyyy
* *FormElement.parameter.dateFormat*: YYYY-MM-DD | DD.MM.YYYY
Actually datetimepicker is used as default. For more options see :ref:`Installation_datetimepicker`
Type: datetime
^^^^^^^^^^^^^^
......@@ -1299,10 +1301,11 @@ Type: datetime
* *FormElement.parameter*:
* *dateFormat* = yyyy-mm-dd | dd.mm.yyyy
* *dateFormat* = YYYY-MM-DD | DD.MM.YYYY
* *showSeconds* = 0|1 - shows the seconds. Independent if the user specifies seconds, they are displayed '1' or not '0'.
* *showZero* = 0|1 - For an empty timestamp, With '0' nothing is displayed. With '1' the string '0000-00-00 00:00:00' is displayed.
Actually datetimepicker is used as default. For more options see :ref:`Installation_datetimepicker`
Type: extra
^^^^^^^^^^^
......@@ -1944,6 +1947,7 @@ Type: time
* *showSeconds* = `0|1` - shows the seconds. Independent if the user specifies seconds, they are displayed '1' or not '0'.
* *showZero* = `0|1` - For an empty timestamp, With '0' nothing is displayed. With '1' the string '00:00[:00]' is displayed.
Actually datetimepicker is used as default. For more options see :ref:`Installation_datetimepicker`
.. _`input-upload`:
Type: upload
......
......@@ -246,12 +246,10 @@ Setup CSS & JS
file05 = typo3conf/ext/qfq/Resources/Public/Css/qfq-bs.css
file06 = typo3conf/ext/qfq/Resources/Public/Css/tablesorter-bootstrap.css
file07 = typo3conf/ext/qfq/Resources/Public/Css/font-awesome.min.css
file08 = typo3conf/ext/qfq/Resources/Public/Css/bootstrap-datetimepicker.min.css
# Only needed in case FullCalendar is used
file08 = typo3conf/ext/qfq/Resources/Public/Css/fullcalendar.min.css
# Only needed in case FormElement 'datetime'/'date' is used
file09 = typo3conf/ext/qfq/Resources/Public/Css/bootstrap-datetimepicker.min.css
file09 = typo3conf/ext/qfq/Resources/Public/Css/fullcalendar.min.css
}
page.includeJS {
......@@ -268,17 +266,16 @@ Setup CSS & JS
file11 = typo3conf/ext/qfq/Resources/Public/JavaScript/jquery.tablesorter.pager.min.js
file12 = typo3conf/ext/qfq/Resources/Public/JavaScript/widget-columnSelector.min.js
file13 = typo3conf/ext/qfq/Resources/Public/JavaScript/widget-output.min.js
file14 = typo3conf/ext/qfq/Resources/Public/JavaScript/bootstrap-datetimepicker.min.js
# Only needed in case FormElement 'annotate' is used.
file14 = typo3conf/ext/qfq/Resources/Public/JavaScript/fabric.min.js
file15 = typo3conf/ext/qfq/Resources/Public/JavaScript/qfq.fabric.min.js
file15 = typo3conf/ext/qfq/Resources/Public/JavaScript/fabric.min.js
file16 = typo3conf/ext/qfq/Resources/Public/JavaScript/qfq.fabric.min.js
# Only needed in case FullCalendar is used
file16 = typo3conf/ext/qfq/Resources/Public/JavaScript/moment.min.js
file17 = typo3conf/ext/qfq/Resources/Public/JavaScript/fullcalendar.min.js
# Only needed in case FullCalendar is used.
file17 = typo3conf/ext/qfq/Resources/Public/JavaScript/moment.min.js
file18 = typo3conf/ext/qfq/Resources/Public/JavaScript/fullcalendar.min.js
# Only needed in case FormElement 'datetime'/'date' is used
file18 = typo3conf/ext/qfq/Resources/Public/JavaScript/bootstrap-datetimepicker.min.js
}
......@@ -296,6 +293,19 @@ As first option both can be inserted to the setup of the main Template like the
Second option is to use the UZH CD template.
Following configurations can be set over FormElement.parameter:
dateFormat = *DD.MM.YYYY HH:mm:ss* | *MM-DD-YYYY HH:mm* | *dddd DD.MM.YYYY HH:mm* -> DD:day of month,MM:month value,YYYY:year value,HH:24h,hh:12h AM-PM,mm:minutes,ss:seconds,dddd:written day of week
dateDaysOfWeekEnabled = *0,1,6* -> 0:sunday,1:monday,2:tuesday,3:wednesday,4:thursday,5:friday,6:saturday
dateLocale = *en* | *de* -> Set language
min = *03.05.2022* -> minDate that can be selected
max = *23.07.2022* -> maxDate that can be selected
dateViewModeDefault = *days* | *months* | *years*
clearMe = *0* | *1* -> show clear button
dateShowCalendarWeeks = *false* | *true*
dateUseCurrentDatetime = *false* | *true*
datetimeSideBySide = *false* | *true* -> Show time right to date
.. _form-editor:
FormEditor
......@@ -310,6 +320,10 @@ Setup a *report* to manage all *forms*:
file=_formEditor
* Twig version of FormEditor is available too ::
file=_formEditorTwig
.. _install-checklist:
Installation: Check List
......
......@@ -125,6 +125,10 @@ to edit `AutoCron` jobs::
}
Or you can use the following code in a separate QFQ record for the twig version of autoCron::
file=_autoCronTwig
Usage
^^^^^
......
......@@ -1488,11 +1488,21 @@ abstract class AbstractBuildForm {
$formElement[FE_TYPE] = 'hidden';
}
}
// If type password is selected then type text with own class will be taken to fake password over CSS
if($formElement[FE_TYPE] === 'password'){
$formElement[FE_TYPE] = 'text';
$class .= ' qfq-password';
}
$attribute .= HelperFormElement::getAttributeList($formElement, [FE_TYPE, 'size']);
$attribute .= Support::doAttribute('value', htmlentities($value), false);
// $attribute .= Support::doAttribute('value', htmlentities($value, ENT_QUOTES, 'UTF-8'), false);
}
// Set for password to give choice of generated password for user and not autofill password field. Deprecated, we dont use type password anymore.
// if($formElement[FE_TYPE] === 'password') {
// $attribute .= Support::doAttribute('autocomplete', 'new-password');
// }
$attribute .= HelperFormElement::getAttributeList($formElement, [FE_INPUT_AUTOCOMPLETE, 'autofocus', 'placeholder']);
$formElement[FE_CHECK_PATTERN] = Sanitize::getInputCheckPattern($formElement[FE_CHECK_TYPE], $formElement[FE_CHECK_PATTERN]
......@@ -1542,6 +1552,11 @@ abstract class AbstractBuildForm {
$input .= $formElement[FE_INPUT_EXTRA_BUTTON_INFO];
}
//Generate an empty input type text to ignore autocomplete in other elements. deprecated because not using type password anymore.
// if($formElement[FE_TYPE] === 'password'){
// $input = '<input type="text" style="display:none;">'.$input;
// }
return $input;
}
......
......@@ -245,6 +245,7 @@ class BuildFormBootstrap extends AbstractBuildForm {
$form = false;
$url = '';
$status = '';
$requiredNew = '';
switch ($this->formSpec[F_NAME]) {
case 'form':
......@@ -253,6 +254,8 @@ class BuildFormBootstrap extends AbstractBuildForm {
case 'formElement':
if (false !== ($formId = $this->store->getVar(FE_FORM_ID, STORE_SIP . STORE_RECORD))) {
$row = $this->dbArray[$this->dbIndexQfq]->sql("SELECT `f`.`name` FROM `Form` AS f WHERE `id`=" . $formId, ROW_EXPECT_1);
$rowRequiredNew = $this->dbArray[$this->dbIndexQfq]->sql("SELECT `f`.`requiredParameterNew` FROM `Form` AS f WHERE `id`=" . $formId, ROW_EXPECT_1);
$requiredNew = current($rowRequiredNew);
$form = current($row);
}
break;
......@@ -264,7 +267,9 @@ class BuildFormBootstrap extends AbstractBuildForm {
$toolTip = "Form not 'form' or 'formElement'";
$status = 'disabled';
} else {
$requiredNew = $this->store->getVar(F_REQUIRED_PARAMETER_NEW, STORE_RECORD . STORE_EMPTY);
if($requiredNew === ''){
$requiredNew = $this->store->getVar(F_REQUIRED_PARAMETER_NEW, STORE_RECORD . STORE_EMPTY);
}
if (trim($requiredNew) !== '') {
$toolTip = "Form has 'required new' parameters and therefore cannot be previewed.";
$status = 'disabled';
......
......@@ -441,7 +441,6 @@ class Database {
case 'SHOW':
case 'DESCRIBE':
case 'EXPLAIN':
case 'CALL':
if (false === ($result = $this->mysqli_stmt->get_result())) {
throw new \DbException(
json_encode([ERROR_MESSAGE_TO_USER => 'Error DB execute', ERROR_MESSAGE_TO_DEVELOPER => '[ mysqli: ' . $this->mysqli_stmt->errno . ' ] ' . $this->mysqli_stmt->error . $specificMessage]),
......@@ -454,6 +453,19 @@ class Database {
$count = $stat[DB_NUM_ROWS];
$msg = 'Read rows: ' . $stat[DB_NUM_ROWS];
break;
case 'CALL':
$result = $this->mysqli_stmt->get_result();
$queryType = QUERY_TYPE_SELECT;
If($result === false){
$stat[DB_NUM_ROWS] = 0;
$msg = 'Read rows: ' . $stat[DB_NUM_ROWS] . '(No SELECT statement)';
}else{
$this->mysqli_result = $result;
$stat[DB_NUM_ROWS] = $this->mysqli_result->num_rows;
$msg = 'Read rows: ' . $stat[DB_NUM_ROWS];
}
$count = $stat[DB_NUM_ROWS];
break;
case 'REPLACE':
case 'INSERT':
$queryType = QUERY_TYPE_INSERT;
......
......@@ -71,10 +71,18 @@ class SessionCookie {
// $this->arrCookieString[] = "name:$key,value:$value,url:$domain,path:$path";
// qfqpdf seems to have problems if 'domain' is specified: it hangs by fetching the website. Skip domain.
// qfqpdf generates another cookie for pdf (SIPs then not reachable) if the given domain doesnt equal what is set in cookie params. Domain default from qfqpdf is without dot. We need to give the domain with previous dot.
$this->arrQfqPdfCookie[] = "name:$key,value:$value";
}
$linesForWkhtml = '';
for($i = 0; $i < count($wkhtml); $i++){
$linesForWkhtml .= $wkhtml[$i]['name'] . "=".$wkhtml[$i]['value']. "; domain=".$wkhtml[$i]['url']."; "."path=".$wkhtml[$i]['path'].";";
if($i+1 < count($wkhtml)){
$linesForWkhtml .= "\n";
}
}
file_put_contents($this->pathFileNameCookie, json_encode(['cookies' => $wkhtml]), FILE_APPEND);
file_put_contents($this->pathFileNameCookie, $linesForWkhtml, FILE_APPEND);
}
/**
......
......@@ -58,13 +58,14 @@ class Session
// Needed expire date for header() method
$expireDate = date("D, d-M-Y H:i:s", strtotime('+2 days')). ' GMT';
// More information about previous dots in domains: https://stackoverflow.com/questions/348282/php-cookie-domain-subdomain-control
if(PHP_VERSION_ID < 70300) {
session_set_cookie_params($lifetime, $path.';SameSite='.$samesite, $_SERVER['HTTP_HOST'], $secure, $httponly);
session_set_cookie_params($lifetime, $path.';SameSite='.$samesite, null, $secure, $httponly);
} else {
session_set_cookie_params([
'lifetime' => $lifetime,
'path' => $path,
'domain' => $_SERVER['HTTP_HOST'],
'domain' => null,
'secure' => $secure,
'httponly' => $httponly,
'samesite' => $samesite
......
dbIndex={{indexQfq:Y}}
form={{form:S}}
1.sql = SELECT id, status,comment, lastRun, lastStatus, nextRun, frequency, inProgress
FROM Cron WHERE '{{form:SE}}' = '' ORDER BY id
1.twig = {% if store.sip.form == '' %}
<table class='table table-hover qfq-table-50'>
<thead class="qfq-sticky"><tr>
<tr>
<th data-sorter="false" class="filter-false">
{{ ('p:'~store.typo3.pageAlias~'|s|N|U:form=cron') | qfqlink }}
</th>
<th>ID</th>
<th>Next run</th>
<th>Frequency</th>
<th>Comment</th>
<th>Last run</th>
<th>In Progress</th>
<th>Status</th>
<th></th>
</tr>
</thead>
<tbody>
{% for row in result %}
{% set tr_class = "" %}
{% set tr_title = "" %}
{% if row.status != "enable" %}
{% set tr_class = "text-muted" %}
{% elseif row.lastStatus[:5] == "Error" %}
{% set tr_class = "danger" %}
{% set tr_title = "Status: Error" %}
{% elseif row.inProgress != 0 and (row.inProgress|date('U') < "-10 minutes"|date('U')) %}
{% set tr_class = "warning" %}
{% set tr_title = "in Progress > 10mins" %}
{% endif %}
<tr class="{{tr_class}}" title="{{tr_title}}">
<td>{{ ('p:'~store.typo3.pageAlias~'|s|E|U:form=cron&r='~row.id) | qfqlink }}</td>
<td>{{ row.id }}</td>
<td>{{ row.nextRun != 0 ? row.nextRun|date("Y-m-d H:i:s") : "-" }}</td>
<td>{{ row.frequency }} </td>
<td>{{ row.comment }} </td>
<td>{{ row.lastRun != 0 ? row.lastRun|date("Y-m-d H:i:s") : "-" }}</td>
<td>{{ row.inProgress != 0 ? (("now"|date("U")-row.inProgress|date("U"))//60~" minutes") : "-" }}</td>
<td>{{ row.lastStatus[:40] }} </td>
<td>
{{ ('u:/typo3conf/ext/qfq/Classes/Api/delete.php'~
'|s|D|q:Delete Cronjob '~row.id~'?'~
'|U:_modeAnswer=html&_targetUrl=/index.php?id='~store.typo3.pageAlias~
'&form=cron&r='~row.id) | qfqlink }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endif %}
#
# Form
#
# a) List of forms: {{form:S}}='', {{formIdHistory:S}}=''
# b) Edit Form: {{form:S}} - Open form {{form:S}} with record {{r:S}} - typically the FormEditor
# c) Use history of a given form: {{formIdHistory:S}}
#
# {{form:S}}
# {{formIdHistory:S0}} - usage history of form '{{formIdHistory:S}}'
form={{form:SE}}
dbIndex={{indexQfq:Y}}
10.sql = SELECT f.id
, f.name
, f.title
, f.tableName
, COUNT(fsl.id) AS submit_count
, MIN(fsl.created) AS submit_first
, MAX(fsl.created) AS submit_last
, GROUP_CONCAT(DISTINCT fsl.pageId ORDER BY fsl.pageId) AS submit_pages
FROM Form AS f
LEFT JOIN FormSubmitLog AS fsl ON fsl.formId=f.id
WHERE '{{form:SE}}'='' AND {{formIdHistory:S0}}=0
GROUP BY f.id ORDER BY f.name
10.twig = {% if result|length > 0 %}
<table class="table table-hover qfq-table-50 tablesorter tablesorter-filter" id="{{store.typo3.pageAlias}}-form">
<thead class="qfq-sticky"><tr>
<th data-sorter="false" class="filter-false">
<div class="btn-group" role="group">
{{ ('p:'~store.typo3.pageAlias~'|s|N|U:form=form') | qfqlink }}
{{ ('p:'~store.typo3.pageAlias~'|s|G:glyphicon-th-list|o:Edit as JSON|U:form=formJson') | qfqlink }}
</div>
</th>
<th>Name</th>
<th>Title</th>
<th>Table</th>
<th>#</th>
<th><em>Frist</em></th>
<th><em>Last</em></th>
<th><em>PageId</em></th>
</tr></thead>
<tbody>
{% for row in result %}
<tr>
<td>
{{ ('p:'~store.typo3.pageAlias~'|s|E|U:form=form&r='~row.id) | qfqlink }}
{{ ('p:'~store.typo3.pageAlias~'|s|G:glyphicon-th-list|o:Edit as JSON|U:form=formJson&r='~row.id) | qfqlink }}
</td>
<td>{{ row.name }} <span class="text-muted">({{ row.id }})</span></td>
<td>
{{ row.title[:50] }}{%- if row.title|length > 50 -%}
<span class="qfq-more-text">{{ row.title[50:] }}</span>
{% endif %}
</td>
<td>{{ row.tableName }}</td>
<td>
{% if row.submit_count == 0 %}
{% set mode = "|r:3" %}
{% else %}
{% set mode = "" %}
{% endif %}
{{ ('p:'~store.typo3.pageAlias~mode~'|U:formIdHistory='~row.id~'|s|b|t:<span class="badge">'~row.submit_count~'</span>') | qfqlink }}
</td>
<td><em>{{ row.submit_first ? row.submit_first|date('Y-m-d') : "-" }}</em></td>
<td><em>{{ row.submit_last ? (date(row.submit_last).diff(date()).days~" days ago") : "-" }}</em></td>
<td><em>{{ row.submit_pages }}</em></td>
</tr>
{% endfor %}
</tbody></table>
{% endif %}
20.sql = SELECT f.name
, fsl.feUser
, fsl.recordId
, fsl.pageId
, fsl.created
FROM FormSubmitLog AS fsl
LEFT JOIN Form AS f
ON fsl.formId=f.id
WHERE fsl.formId={{formIdHistory:S0}}
ORDER BY fsl.created DESC
20.twig = {% if result|length > 0 %}
<h3>Submit History for {{ result.0.name }}</h3>
<a href="javascript:history.back()">Back</a>
<table class="table table-hover qfq-table-50 tablesorter tablesorter-filter" id="{{store.typo3.pageAlias}}-formHistory">
<thead class="qfq-sticky"><tr><th>Form</th><th>feUser</th><th>recordId</th><th>pageId</th><th>Submit</th></tr></thead>
<tbody>
{% for row in result %}
<tr>
{% for col in row %}
<td>{{ col }}</td>
{% endfor %}
</tr>
{% else %}
{# this should never happen, as we do not provide a link if there is no history #}
<tr><td></td><td></td><td></td><td>no history found</td><td></td><td></td><td></td><td></td><td></td></tr>
{% endfor %}
</tbody></table>
<a href="javascript:history.back()">Back</a>
{% endif %}
......@@ -35,6 +35,8 @@ var QfqNS = QfqNS || {};
this.tabs = {};
this.currentTab = this.getActiveTabFromDOM();
this.eventEmitter = new EventEmitter();
this.currentFormName = $('#' + this.tabId + ' .active a[data-toggle="tab"]')[0].hash.slice(1).split("_")[0];
this.currentRecordId = $('#' + this.tabId + ' a[data-toggle="tab"]')[0].id.split("-")[2];
// Fill this.tabs
this.fillTabInformation();
......@@ -111,7 +113,6 @@ var QfqNS = QfqNS || {};
n.BSTabs.prototype.tabShowHandler = function (event) {
n.Log.debug('Enter: BSTabs.tabShowHandler()');
this.currentTab = event.target.hash.slice(1);
n.Log.debug("BSTabs.tabShowHandler(): invoke user handler(s)");
this.eventEmitter.emitEvent('bootstrap.tab.shown', n.EventEmitter.makePayload(this, null));
this.removeDot(this.currentTab);
......
......@@ -6,7 +6,7 @@ Function.prototype.bind = Function.prototype.bind || function (thisp) {
var fn = this;
return function () {
return fn.apply(thisp, arguments);
return fn.apply(thisp, arguments);
};
};
......@@ -16,15 +16,15 @@ $(document).ready( function () {
(function (n) {
try {
var tablesorterController = new n.TablesorterController();
$('.tablesorter').each(function(i) {
tablesorterController.setup($(this), i);
}); // end .each()
var tablesorterController = new n.TablesorterController();
$('.tablesorter').each(function (i) {
tablesorterController.setup($(this), i);
}); // end .each()
$('.tablesorter-filter').addClass('qfq-skip-dirty');
} catch (e) {
console.log(e);
}
$('.tablesorter-filter').addClass('qfq-skip-dirty');
} catch (e) {
console.log(e);
}
$('.qfq-auto-grow').each(function() {
var minHeight = $(this).attr("rows") * 14 + 18;
......@@ -80,7 +80,7 @@ $(document).ready( function () {
html: "&times;"
});
if (myInput.val() == '' || myInput.is('[disabled=disabled]')) {
closeButton.addClass("hidden");
closeButton.addClass("hidden");
}
closeButton.on("click", function(e) {
myInput.val('');
......@@ -94,7 +94,7 @@ $(document).ready( function () {
closeButton.addClass("hidden");
}
});
});
......@@ -128,17 +128,19 @@ $(document).ready( function () {
$('.qfq-datepicker').each(function() {
var dates = {};
var datesToFormat = ["minDate", "maxDate"];
var correctAttributeNames = ["mindate", "maxdate"];
for(var i = 0; i < datesToFormat.length; i++) {
var date = false;
if($(this).data(datesToFormat[i])) {
var dateArray = $(this).data(datesToFormat[i]).split(".");
date = dateArray[1] + "." + dateArray[0] + "." + dateArray[2];
if($(this).data(correctAttributeNames[i])) {
var dateArray = $(this).data(correctAttributeNames[i]).split(".");
date = dateArray[1] + "/" + dateArray[0] + "/" + dateArray[2];
}
dates[datesToFormat[i]] = date;
}
var options = {
locale: $(this).data("locale") || "en",
daysOfWeekDisabled: $(this).data("days-of-week-disabled") || [0,6],
daysOfWeekDisabled: $(this).data("days-of-week-disabled") || [],
minDate: dates.minDate,
maxDate: dates.maxDate,
format: $(this).data("format") || "DD.MM.YYYY HH:mm",
......@@ -146,12 +148,12 @@ $(document).ready( function () {
showClear: ($(this).data("show-clear-button") !== undefined) ? $(this).data("show-clear-button") : true,
calendarWeeks: ($(this).data("show-calendar-weeks") !== undefined) ? $(this).data("show-calendar-weeks") : false,
useCurrent: ($(this).data("use-current-datetime") !== undefined) ? $(this).data("use-current-datetime") : false,
sideBySide: ($(this).data("datetime-side-by-side") !== undefined) ? $(this).data("datetime-side-by-side") : false
sideBySide: ($(this).data("datetime-side-by-side") !== undefined) ? $(this).data("datetime-side-by-side") : false,
};
var currentDatePicker = $(this).datetimepicker(options);
});
......
......@@ -45,7 +45,36 @@ var QfqNS = QfqNS || {};
try {
this.bsTabs = new n.BSTabs(this.settings.tabsId);
var storedFormInfos = [];
// get current state from session storage
if(sessionStorage.getItem("formInfos") !== null) {
storedFormInfos = JSON.parse(sessionStorage.getItem("formInfos"));
}
var currentForm = this.bsTabs.currentFormName;
var currentRecordId = this.bsTabs.currentRecordId;
var actualIndex = -1;
var indexNr = 0;
if(storedFormInfos.length !== 0){
if(storedFormInfos[0] !== ''){
storedFormInfos.forEach(function callback(element){
if(element === currentForm && storedFormInfos[indexNr+2] === currentRecordId){
actualIndex = indexNr;
}
indexNr++;
});
}
}
var currentState = this.settings.pageState.getPageState();
// load from sessionStorage or from path given hash if not empty
if(actualIndex !== -1 && location.hash === "") {
currentState = storedFormInfos[actualIndex+1];
}
if (currentState !== "") {
this.bsTabs.activateTab(currentState);
n.PageTitle.setSubTitle(this.bsTabs.getTabName(currentState));
......@@ -151,6 +180,53 @@ var QfqNS = QfqNS || {};
}
var currentTabId = obj.target.getCurrentTab();
n.Log.debug('Saving state: ' + currentTabId);
// Implementation save current state in session storage
var storedFormInfos = [];
if(sessionStorage.getItem("formInfos") !== null){
storedFormInfos = JSON.parse(sessionStorage.getItem("formInfos"));
}
var currentForm = obj.target.currentFormName;
var currentRecordId = obj.target.currentRecordId;
var actualIndex = -1;
var indexNr = 0;
if(storedFormInfos.length !== 0) {
if(storedFormInfos[0] !== ''){
storedFormInfos.forEach(function callback(element){
if(element === currentForm && storedFormInfos[indexNr + 2] === currentRecordId){
actualIndex = indexNr;
}
indexNr++;
});
}
}
// fill sessionStorage, there are 3 ways for filling the sessionStorage: 1.If empty - first time filling, 2.If there is anything - add it to them, 3
// 1.If array from storage is empty - fill it first time
if(storedFormInfos.length === 0){
storedFormInfos[0] = currentForm;
storedFormInfos[1] = currentTabId;
storedFormInfos[2] = currentRecordId;
// 2.If there is anything in storage but not the actual opened forms - add this new information to the existing array
}else if(actualIndex === -1) {
storedFormInfos[indexNr] = currentForm;
storedFormInfos[indexNr + 1] = currentTabId;
storedFormInfos[indexNr + 2] = currentRecordId;
// 3.If actual openend form is included in sessionStorage - only change the array values of the existing informations
}else{
storedFormInfos[actualIndex] = currentForm;
storedFormInfos[actualIndex + 1] = currentTabId;
storedFormInfos[actualIndex + 2] = currentRecordId;
}
// Set sessionStorage with customized array
sessionStorage.setItem("formInfos" , JSON.stringify(storedFormInfos));
n.PageTitle.setSubTitle(obj.target.getTabName(currentTabId));
this.settings.pageState.setPageState(currentTabId, n.PageTitle.get());
};
......
......@@ -393,4 +393,16 @@ var QfqNS = QfqNS || {};
<