Commit ee012ddb authored by Elias Villiger's avatar Elias Villiger
Browse files

Feature #6249 - Finalize & document subrecord dnd

parent 04bdb19b
Pipeline #691 passed with stage
in 2 minutes and 11 seconds
......@@ -3299,6 +3299,31 @@ will be rendered inside the form as a HTML table.
* *subrecordTableClass*: Optional. Default: 'table table-hover qfq-table-100'. If given, the default will be overwritten.
**Subrecord DragAndDrop**
Subrecords inherently support drag-and-drop, see also `drag_and_drop`_.
The following parameters can be used in the `parameter` field to customize/activate drag-and-drop:
* *orderInterval*: The order interval to be used, default is 10.
* *dndTable*: The table that contains the records to be ordered.
If not given, the table name of the form specified via `form=...` is used.
* *orderColumn*: The dedicated order column in the specified dndTable (needs to match a column in the table definition).
Default is `ord`.
If `dndTable` is an actual table with a column `orderColumn`, QFQ automatically applies drag-and-drop logic
to the rendered subrecord. It does so by using the subrecord field *sql1*. The `sql1` query should
therefore include both a column id (or _id) and ord (or _ord).
Tips:
* If you want to deactivate a drag-and-drop that QFQ automatically renders, set the `orderColumn` to a non-existing column.
E.g., `orderColumn = nonExistingColumn`. This will deactivate drag-and-drop.
* In order to evaluate the `sql1` query dynamically during a drag-and-drop event, the fill store R (with the current form)
is loaded. Currently, SIP parameters and other variables are not supplied to be evaluated during a drag-and-drop event.
This may be added later upon request.
* If the subrecord is rendered with drag-and-drop active, but the order is not affected upon reload, there is
most likely a problem with evaluating the `sql1` query at runtime.
Type: time
^^^^^^^^^^
......@@ -6464,13 +6489,13 @@ A typical QFQ report which generates those `<div>` HTML: ::
WHERE grId=28
ORDER BY n.ord
head = <div class="qfq-dnd-sort" {{'form=dndSortNote&grId=28|A:dnd-sort' AS _data-dnd-api}}">
head = <div class="qfq-dnd-sort" {{'form=dndSortNote&grId=28' AS _data-dnd-api}}">
tail = </div>
}
A `<table>` based setup is also possible. Note the attribute `data-columns="3"` - those generates a dropzone
which the same width as the outer table. ::
A `<table>` based setup is also possible. Note the attribute `data-columns="3"` - this generates a dropzone
which is the same width as the outer table. ::
<table>
<tbody class="qfq-dnd-sort" data-dnd-api="typo3conf/ext/qfq/qfq/api/dragAndDrop.php?s=badcaffee1234" data-columns="3">
......@@ -6486,7 +6511,7 @@ which the same width as the outer table. ::
</tbody>
</table>
A typical QFQ report which generates those HTML: ::
A typical QFQ report which generates this HTML: ::
10 {
sql = SELECT '<tr id="anytag-', n.id,'" data-dnd-id="', n.id,'" data-columns="3">' , n.id AS '_+td', n.note AS '_+td', n.ord AS '_+td', '</tr>'
......@@ -6539,7 +6564,7 @@ QFQ iterates over the result set of `dragAndDropOrderSql`. The value of column `
Take care that the query of part 1 (display list) does a) select the same records and b) in the same order as the query
defined in part 2 (sort records) via `dragAndDropOrderSql`.
If you find that the reorder does not work at expected, those two sql queries are not identically.
If you find that the reorder does not work at expected, those two sql queries are not identical.
QFQ CSS Classes
---------------
......
......@@ -168,18 +168,18 @@ INSERT INTO Form (id, name, title, noteInternal, tableName, permitNew, permitEdi
INSERT INTO FormElement (id, formId, name, label, mode, type, checkType, class, ord, size, note, clientJs, value,
sql1, parameter, feIdContainer, subrecordOption, modeSql, placeholder)
VALUES
(1, 1, 'basic', 'Basic', 'show', 'pill', 'all', 'container', 10, 0, '', '', '', '', '', 0, '', '', ''),
(2, 1, 'access', 'Access', 'show', 'pill', 'all', 'container', 20, 0, '', '', '', '', '', 0, '', '', ''),
(3, 1, 'various', 'Various', 'show', 'pill', 'all', 'container', 30, 0, '', '', '', '', '', 0, '', '', ''),
(4, 1, 'multi', 'Multi', 'show', 'pill', 'all', 'container', 40, 0, '', '', '', '', '', 0, '', '', ''),
(5, 1, 'formelement', 'Formelement', 'show', 'pill', 'all', 'container', 50, 0, '', '', '', '', '', 0, '', '', '');
(1, 1, 'basic', 'Basic', 'show', 'pill', 'all', 'container', 100, 0, '', '', '', '', '', 0, '', '', ''),
(2, 1, 'access', 'Access', 'show', 'pill', 'all', 'container', 400, 0, '', '', '', '', '', 0, '', '', ''),
(3, 1, 'various', 'Various', 'show', 'pill', 'all', 'container', 200, 0, '', '', '', '', '', 0, '', '', ''),
(4, 1, 'multi', 'Multi', 'show', 'pill', 'all', 'container', 300, 0, '', '', '', '', '', 0, '', '', ''),
(5, 1, 'formelement', 'Formelement', 'show', 'pill', 'all', 'container', 500, 0, '', '', '', '', '', 0, '', '', '');
# FormEditor: FormElements for 'form'
INSERT INTO FormElement (formId, name, label, mode, type, checkType, class, ord, size, maxLength, note, clientJs, value,
sql1, parameter, feIdContainer, subrecordOption, modeSql, placeholder, encode, dynamicUpdate, checkPattern)
VALUES
# Make the form a 'delete form' for records Form/FormElement.
(1, 'Delete FE', '', 'show', 'beforeDelete', 'all', 'action', 100, 0, 0, '', '', '', '',
(1, 'Delete FE', '', 'show', 'beforeDelete', 'all', 'action', 10, 0, 0, '', '', '', '',
'sqlAfter={{DELETE FROM FormElement WHERE formId={{id:R}} }}', 0, '', '', '', 'none', 'no', ''),
(1, 'name', 'Name', 'required', 'text', 'pattern', 'native', 120, 0, 0, '<a href="{{documentation:Y}}#form-name">Info</a>', '', '', '', 'autofocus',
1, '', '', '', 'specialchar', 'no', '[a-zA-Z0-9._+-]+'),
......@@ -195,42 +195,42 @@ VALUES
'<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{formLanguageCId:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
(1, 'parameterLanguageD', 'Language: {{formLanguageDLabel:YE}}', 'show', 'text', 'all', 'native', 160, '60,2', 0,
'<a href="{{documentation:Y}}#multi-language-form">Info</a>', '', '', '', '', 1, '', '{{SELECT IF("{{formLanguageDId:YE}}"="","hidden","show" ) }}', '', 'none', 'no', ''),
(1, 'requiredParameterNew', 'Required Parameter NEW', 'show', 'text', 'all', 'native', 200, 0, 0, '<a href="{{documentation:Y}}#required-parameter-new-edit">Info</a>', '', '', '', '', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'requiredParameterEdit', 'Required Parameter EDIT', 'show', 'text', 'all', 'native', 200, 0, 0, '<a href="{{documentation:Y}}#required-parameter-new-edit">Info</a>', '', '', '', '', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'permitNew', 'Permit New', 'show', 'radio', 'all', 'native', 210, 0, 10, '<a href="{{documentation:Y}}#form-permitnewedit">Info</a>', '', '', '', 'buttonClass=btn-default', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'permitEdit', 'Permit Edit', 'show', 'radio', 'all', 'native', 220, 0, 10, '<a href="{{documentation:Y}}#form-permitnewedit">Info</a>', '', '', '', 'buttonClass=btn-default', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'escapeTypeDefault', 'Escape type default', 'show', 'radio', 'all', 'native', 230, 0, 10, '<a href="{{documentation:Y}}#variable-escape">Info</a>', '', '', '',
(1, 'requiredParameterNew', 'Required Parameter NEW', 'show', 'text', 'all', 'native', 410, 0, 0, '<a href="{{documentation:Y}}#required-parameter-new-edit">Info</a>', '', '', '', '', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'requiredParameterEdit', 'Required Parameter EDIT', 'show', 'text', 'all', 'native', 410, 0, 0, '<a href="{{documentation:Y}}#required-parameter-new-edit">Info</a>', '', '', '', '', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'permitNew', 'Permit New', 'show', 'radio', 'all', 'native', 420, 0, 10, '<a href="{{documentation:Y}}#form-permitnewedit">Info</a>', '', '', '', 'buttonClass=btn-default', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'permitEdit', 'Permit Edit', 'show', 'radio', 'all', 'native', 430, 0, 10, '<a href="{{documentation:Y}}#form-permitnewedit">Info</a>', '', '', '', 'buttonClass=btn-default', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'escapeTypeDefault', 'Escape type default', 'show', 'radio', 'all', 'native', 440, 0, 10, '<a href="{{documentation:Y}}#variable-escape">Info</a>', '', '', '',
'itemList=c:config,s:single,d:double,l:ldap search,L:ldap value,m:mysql realEscapeString,-:none\nbuttonClass=btn-default', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'dirtyMode', 'Record Locking', 'show', 'radio', 'all', 'native', 240, 0, 10, '<a href="{{documentation:Y}}#locking-record">Info</a>', '', '', '',
(1, 'dirtyMode', 'Record Locking', 'show', 'radio', 'all', 'native', 450, 0, 10, '<a href="{{documentation:Y}}#locking-record">Info</a>', '', '', '',
'buttonClass=btn-default', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'recordLockTimeoutSeconds', 'Lock timeout (seconds)', 'show', 'text', 'all', 'native', 245, 0, 0, '<a href="{{documentation:Y}}#locking-record">Info</a>', '',
(1, 'recordLockTimeoutSeconds', 'Lock timeout (seconds)', 'show', 'text', 'all', 'native', 455, 0, 0, '<a href="{{documentation:Y}}#locking-record">Info</a>', '',
'{{SELECT IF("{{recordLockTimeoutSeconds:R0}}"=0,"{{recordLockTimeoutSeconds:Y0}}","{{recordLockTimeoutSeconds:R0}}")}}', '', '', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'showButton', 'Show button', 'show', 'checkbox', 'all', 'native', 250, 0, 5, '<a href="{{documentation:Y}}#showbutton">Info</a>', '', '', '', 'checkBoxMode = multi\norientation=vertical', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'forwardMode', 'Forward', 'show', 'radio', 'all', 'native', 300, 0, 0, '<a href="{{documentation:Y}}#form-forward">Info</a>', '', '', '', 'buttonClass=btn-default', 3, '', '', '', 'specialchar', 'no', ''),
(1, 'forwardPage', 'Forward URL / Page', 'show', 'text', 'all', 'native', 310, 0, 0, '<a href="{{documentation:Y}}#form-forward">Info</a>', '', '', '', '', 3, '',
(1, 'showButton', 'Show button', 'show', 'checkbox', 'all', 'native', 450, 0, 5, '<a href="{{documentation:Y}}#showbutton">Info</a>', '', '', '', 'checkBoxMode = multi\norientation=vertical', 2, '', '', '', 'specialchar', 'no', ''),
(1, 'forwardMode', 'Forward', 'show', 'radio', 'all', 'native', 210, 0, 0, '<a href="{{documentation:Y}}#form-forward">Info</a>', '', '', '', 'buttonClass=btn-default', 3, '', '', '', 'specialchar', 'no', ''),
(1, 'forwardPage', 'Forward URL / Page', 'show', 'text', 'all', 'native', 220, 0, 0, '<a href="{{documentation:Y}}#form-forward">Info</a>', '', '', '', '', 3, '',
'', '', 'none', 'no', ''),
(1, 'parameter', 'Parameter', 'show', 'text', 'all', 'native', 320, '40,8', 0, '<a href="{{documentation:Y}}#form-parameter">Info</a>', '', '', '', '', 3, '', '', '', 'none', 'no', ''),
(1, 'bsLabelColumns', 'BS Label Columns', 'show', 'text', 'all', 'native', 330, 0, 0, '<a href="{{documentation:Y}}#form-layout">Info</a>', '', '', '', '', 3, '', '', '{{bsLabelColumns:Y}}', 'specialchar', 'no', ''),
(1, 'bsInputColumns', 'BS Input Columns', 'show', 'text', 'all', 'native', 340, 0, 0, '', '', '', '', '', 3, '', '', '{{bsInputColumns:Y}}', 'specialchar', 'no', ''),
(1, 'bsNoteColumns', 'BS Note Columns', 'show', 'text', 'all', 'native', 350, 0, 0, '', '', '', '', '', 3, '', '', '{{bsNoteColumns:Y}}', 'specialchar', 'no', ''),
(1, 'deleted', 'Deleted', 'show', 'checkbox', 'all', 'native', 360, 0, 0, '', '', '', '', '', 3, '', '', '', 'specialchar', 'no', ''),
(1, 'modified', 'Modified', 'readonly', 'text', 'all', 'native', 370, 0, 20, '', '', '', '', '', 3, '', '', '', 'specialchar', 'no', ''),
(1, 'created', 'Created', 'readonly', 'text', 'all', 'native', 380, 0, 20, '', '', '', '', '', 3, '', '', '',
(1, 'parameter', 'Parameter', 'show', 'text', 'all', 'native', 230, '40,8', 0, '<a href="{{documentation:Y}}#form-parameter">Info</a>', '', '', '', '', 3, '', '', '', 'none', 'no', ''),
(1, 'bsLabelColumns', 'BS Label Columns', 'show', 'text', 'all', 'native', 240, 0, 0, '<a href="{{documentation:Y}}#form-layout">Info</a>', '', '', '', '', 3, '', '', '{{bsLabelColumns:Y}}', 'specialchar', 'no', ''),
(1, 'bsInputColumns', 'BS Input Columns', 'show', 'text', 'all', 'native', 250, 0, 0, '', '', '', '', '', 3, '', '', '{{bsInputColumns:Y}}', 'specialchar', 'no', ''),
(1, 'bsNoteColumns', 'BS Note Columns', 'show', 'text', 'all', 'native', 260, 0, 0, '', '', '', '', '', 3, '', '', '{{bsNoteColumns:Y}}', 'specialchar', 'no', ''),
(1, 'deleted', 'Deleted', 'show', 'checkbox', 'all', 'native', 270, 0, 0, '', '', '', '', '', 3, '', '', '', 'specialchar', 'no', ''),
(1, 'modified', 'Modified', 'readonly', 'text', 'all', 'native', 280, 0, 20, '', '', '', '', '', 3, '', '', '', 'specialchar', 'no', ''),
(1, 'created', 'Created', 'readonly', 'text', 'all', 'native', 290, 0, 20, '', '', '', '', '', 3, '', '', '',
'specialchar', 'no', ''),
(1, 'multi', 'Multi', 'show', 'fieldset', 'all', 'native', 400, 0, 0, '', '', '', '', '', 4, '', '', '',
(1, 'multi', 'Multi', 'show', 'fieldset', 'all', 'native', 310, 0, 0, '', '', '', '', '', 4, '', '', '',
'specialchar', 'no', ''),
(1, 'multiMode', 'Multi Mode', 'show', 'radio', 'all', 'native', 410, 0, 0, '', '', '', '', '', 4, '', '', '',
(1, 'multiMode', 'Multi Mode', 'show', 'radio', 'all', 'native', 320, 0, 0, '', '', '', '', '', 4, '', '', '',
'specialchar', 'no', ''),
(1, 'multiSql', 'Multi SQL', 'show', 'text', 'all', 'native', 420, '40,3', 0, '', '', '', '', '', 4, '', '', '',
(1, 'multiSql', 'Multi SQL', 'show', 'text', 'all', 'native', 330, '40,3', 0, '', '', '', '', '', 4, '', '', '',
'none', 'no', ''),
(1, 'multiDetailForm', 'Multi Detail Form', 'show', 'text', 'all', 'native', 430, 0, 0, '', '', '', '', '', 4,
(1, 'multiDetailForm', 'Multi Detail Form', 'show', 'text', 'all', 'native', 340, 0, 0, '', '', '', '', '', 4,
'', '', '', 'specialchar', 'no', ''),
(1, 'multiDetailFormParameter', 'Multi Detail Form Parameter', 'show', 'text', 'all', 'native', 440, 0, 0, '', '',
(1, 'multiDetailFormParameter', 'Multi Detail Form Parameter', 'show', 'text', 'all', 'native', 350, 0, 0, '', '',
'', '', '', 4, '', '', '', 'none', 'no', ''),
(1, '', 'FormElements', 'show', 'subrecord', 'all', 'native', 500, 0, 0, '', '', '',
'{{!SELECT IF( fe.enabled="yes", IF( fe.enabled="yes" AND fe.feIdContainer=0 AND !ISNULL(feCX.id) AND fe.class="native", "danger", IF( fe.class="container", "text-info", IF( fe.class="action", "text-success", ""))), "text-muted") AS _rowClass, IF( fe.enabled="yes", IF(fe.feIdContainer=0 AND !ISNULL(feCX.id) AND fe.class="native", "Please choose a container for this formelement", fe.class), "Disabled") AS _rowTitle, fe.id AS _id, CONCAT(fe.ord, ''<br><small class="text-muted">'',fe.id, ''</small>'') AS ''Ord|nostrip'', CONCAT( IFNULL( CONCAT( feC.name, " (", fe.feIdContainer, ")"),"")) AS Container, fe.name AS "Name|50", fe.label AS Label, fe.mode AS Mode, fe.class AS Class, fe.type AS Type, IF(fe.dynamicUpdate="yes", \'<span class="glyphicon glyphicon-random"></span>\',"") AS "Dyn|nostrip" FROM FormElement AS fe LEFT JOIN FormElement AS feC ON feC.id=fe.feIdContainer AND feC.formId=fe.formId LEFT JOIN FormElement AS feCX ON feCX.class="container" AND feCX.enabled="yes" AND feCX.formId=fe.formId WHERE fe.formId={{id:R0}} GROUP BY fe.id ORDER BY fe.class DESC, feC.ord, fe.ord, fe.id}}',
(1, '', 'FormElements', 'show', 'subrecord', 'all', 'native', 510, 0, 0, '', '', '',
'{{!SELECT IF( fe.enabled="yes", IF( fe.enabled="yes" AND fe.feIdContainer=0 AND !ISNULL(feCX.id) AND fe.class="native", "danger", IF( fe.class="container", "text-info", IF( fe.class="action", "text-success", ""))), "text-muted") AS _rowClass, IF( fe.enabled="yes", IF(fe.feIdContainer=0 AND !ISNULL(feCX.id) AND fe.class="native", "Please choose a container for this formelement", fe.class), "Disabled") AS _rowTitle, fe.id AS _id, CONCAT(fe.ord, ''<br><small class="text-muted">'',fe.id, ''</small>'') AS ''Ord|nostrip'', CONCAT( IFNULL( CONCAT( feC.name, " (", fe.feIdContainer, ")"),"")) AS Container, fe.name AS "Name|50", fe.label AS Label, fe.mode AS Mode, fe.class AS Class, fe.type AS Type, IF(fe.dynamicUpdate="yes", \'<span class="glyphicon glyphicon-random"></span>\',"") AS "Dyn|nostrip" FROM FormElement AS fe LEFT JOIN FormElement AS feC ON feC.id=fe.feIdContainer AND feC.formId=fe.formId LEFT JOIN FormElement AS feCX ON feCX.class="container" AND feCX.enabled="yes" AND feCX.formId=fe.formId WHERE fe.formId={{id:R0}} GROUP BY fe.id ORDER BY fe.ord, fe.id}}',
'form=formElement\ndetail=id:formId', 5, 'new,edit,delete', '', '', 'none', 'no', '');
#
......@@ -249,11 +249,11 @@ INSERT INTO FormElement (id, formId, name, label, mode, type, checkType, class,
VALUES
(100, 2, 'basic', 'Basic', 'show', 'pill', 'all', 'container', 10, 0, '', '', '', '', '', 0, '', ''),
(101, 2, 'check_order', 'Check & Order', 'show', 'pill', 'all', 'container', 20, 0, '', '', '', '', '', 0, '',
(101, 2, 'check_order', 'Check & Order', 'show', 'pill', 'all', 'container', 290, 0, '', '', '', '', '', 0, '',
''),
(102, 2, 'layout', 'Layout', 'show', 'pill', 'all', 'container', 20, 0, '', '', '', '', '', 0, '', ''),
(103, 2, 'value', 'Value', 'show', 'pill', 'all', 'container', 20, 0, '', '', '', '', '', 0, '', ''),
(104, 2, 'info', 'Info', 'show', 'pill', 'all', 'container', 20, 0, '', '', '', '', '', 0, '', '');
(102, 2, 'layout', 'Layout', 'show', 'pill', 'all', 'container', 390, 0, '', '', '', '', '', 0, '', ''),
(103, 2, 'value', 'Value', 'show', 'pill', 'all', 'container', 490, 0, '', '', '', '', '', 0, '', ''),
(104, 2, 'info', 'Info', 'show', 'pill', 'all', 'container', 590, 0, '', '', '', '', '', 0, '', '');
INSERT INTO FormElement (formId, name, label, mode, type, checkType, class, ord, size, maxLength, note, clientJs, value,
sql1, parameter, feIdContainer, subrecordOption, dynamicUpdate, bsLabelColumns, bsInputColumns,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment