Commit e753f8cf authored by Carsten  Rose's avatar Carsten Rose
Browse files

dnd update: update of the 'ord' values implemented. Check documentation how to use it.

parent 35053677
Pipeline #751 passed with stage
in 1 minute and 34 seconds
......@@ -6440,7 +6440,7 @@ Manually sorting and ordering of elements via `HTML5 drag and drop` is supported
should be represented by a database record with an order column. If the elements are unordered, they will be ordered after
the first 'drag and drop' move of an element.
Functionality is divided into:
Functionality divides into:
* Display list: the records will be displayed via QFQ/report.
* Sort records: updates of the order column are managed by a specific definition form. The form is not a regular form
......@@ -6450,16 +6450,16 @@ Functionality is divided into:
Part 1: Display list
''''''''''''''''''''
Display the list of elements via a regular QFQ content record. All 'drag and drop' elements have to be nested by an HTML
element:
Display the list of elements via a regular QFQ content record. All 'drag and drop' elements together have to be nested by a HTML
element. Such HTML element:
* With `class="qfq-dnd-sort"`.
* With a form name: `{{'form=<form name>' AS _data-dnd-api}}`
* Only direct children of such element can be dragged.
* With a form name: `{{'form=<form name>' AS _data-dnd-api}}` (will be replaced by QFQ)
* Only *direct* children of such element can be dragged.
* Every children needs a unique identifier `data-dnd-id="<unique>"`. Typically this is the corresponding record id.
* The record needs a dedicated order column, which will be updated through API calls in time.
A `<div>` example HTML output: ::
A `<div>` example HTML output (HTML send to the browser): ::
<div class="qfq-dnd-sort" data-dnd-api="typo3conf/ext/qfq/qfq/api/dragAndDrop.php?s=badcaffee1234">
<div class="anyClass" id="<uniq1>" data-dnd-id="55">
......@@ -6488,7 +6488,7 @@ A typical QFQ report which generates those `<div>` HTML: ::
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. ::
which the same column 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">
......@@ -6516,10 +6516,32 @@ A typical QFQ report which generates those HTML: ::
tail = </tbody><table>
}
Show / update order value in the browser
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
The 'drag and drop' action does not trigger a reload of the page. In case the order number is shown and the user does
a 'drag and drop', the order number shows the old. To update the dragable elements with the latest order number, a
predefined html id has to be assigned them. After an update, all changed order number (referenced by the html id) will
be updated via AJAX.
The html id per element is defined by `qfq-dnd-ord-id-<id>` where `<id>` is the record id. Same example as above, but
with an updated `n.ord` column: ::
10 {
sql = SELECT '<tr id="anytag-', n.id,'" data-dnd-id="', n.id,'" data-columns="3">' , n.id AS '_+td', n.note AS '_+td',
'<td id="qfq-dnd-ord-id-', n.id, '">', n.ord, '</td></tr>'
FROM Note AS n
WHERE grId=28
ORDER BY n.ord
head = <table><tbody class="qfq-dnd-sort" {{'form=dndSortNote&grId=28' AS _data-dnd-api}} data-columns="3">
tail = </tbody><table>
}
Part 2: Sort records
''''''''''''''''''''
A dedicated `Form`, without any `FormElements`, is used to define the database update definition.
A dedicated `Form`, without any `FormElements`, is used to define the reorder logic (database update definition).
Fields:
......@@ -6548,6 +6570,8 @@ The form related to the example of part 1 ('div' or 'table'): ::
Form.parameter: orderColumn = ord
Form.parameter: dragAndDropOrderSql = {{!SELECT n.id AS id, n.ord AS ord FROM Note AS n WHERE n.grId={{grId:S0}} ORDER BY n.ord}}
Re-Order:
QFQ iterates over the result set of `dragAndDropOrderSql`. The value of column `id` have to correspond to the dragged HTML
element (given by `data-dnd-id`). Reordering always start with `orderInterval` and is incremented by `orderInterval` with each
record of the result set. The client reports a) the id of the dragged HTML element, b) the id of the hovered element and
......
......@@ -59,6 +59,7 @@ try {
$qfq = new QuickFormQuery(['bodytext' => '']);
$data = $qfq->dragAndDrop();
$answer = array_merge($data, $answer);
$answer[API_STATUS] = API_ANSWER_STATUS_SUCCESS;
$answer[API_MESSAGE] = 'reorder: success';
......@@ -66,7 +67,6 @@ try {
// $answer[API_ELEMENT_UPDATE] = $data[API_ELEMENT_UPDATE];
// unset($answer[API_FORM_UPDATE][API_ELEMENT_UPDATE]);
// $answer[API_ELEMENT_UPDATE] = [ 'dynamic-125' => [ 'content' => 'latest news', 'attr' => [ 'title' => 'latest title'] ] ];
$answer['elementUpdate'] = [ 'dynamic-125' => [ 'content' => 'latest news', 'attr' => [ 'title' => 'latest title'] ] ];
} catch (qfq\UserFormException $e) {
$answer[API_MESSAGE] = $e->formatMessage();
......
......@@ -1544,4 +1544,5 @@ const DND_COLUMN_ID = 'id';
const DND_COLUMN_ORD = 'ord';
const DND_COLUMN_ORD_NEW = 'ordNew';
const DND_DATA_DND_API = 'data-dnd-api';
const DND_ORD_HTML_ID_PREFIX = 'qfq-dnd-ord-id-';
......@@ -319,6 +319,7 @@ class QuickFormQuery {
private function doForm($formMode) {
$data = '';
$foundInStore = '';
$flagApiStructureReGroup=true;
// Fill STORE_FORM
if ($formMode === FORM_UPDATE || $formMode === FORM_SAVE || $formMode === FORM_DRAG_AND_DROP) {
......@@ -527,7 +528,8 @@ class QuickFormQuery {
$formAction->elements($recordId, $this->feSpecAction, FE_TYPE_BEFORE_LOAD);
$dragAndDrop = new DragAndDrop($this->formSpec);
$dragAndDrop->process();
$data = $dragAndDrop->process();
$flagApiStructureReGroup=false;
$formAction->elements($recordId, $this->feSpecAction, FE_TYPE_AFTER_LOAD);
break;
......@@ -536,7 +538,7 @@ class QuickFormQuery {
throw new CodeException("This statement should never be reached", ERROR_CODE_SHOULD_NOT_HAPPEN);
}
if (is_array($data)) {
if ($flagApiStructureReGroup && is_array($data)) {
// $data['element-update']=...
$data = $this->groupElementUpdateEntries($data);
}
......@@ -717,7 +719,7 @@ class QuickFormQuery {
unlink($file);
} else {
$form[FORM_LOG_FILE . '_' . $mode] = $file;
$form[FORM_LOG_ACTIVE]=1;
$form[FORM_LOG_ACTIVE] = 1;
}
}
}
......@@ -1380,9 +1382,7 @@ class QuickFormQuery {
*/
public function dragAndDrop() {
$json = $this->doForm(FORM_DRAG_AND_DROP);
return $json;
return $this->doForm(FORM_DRAG_AND_DROP);
}
/**
......
......@@ -86,19 +86,34 @@ class DragAndDrop {
return [];
}
$this->reorder($this->formSpec[F_DRAG_AND_DROP_ORDER_SQL], $dragId, $setTo, $hoverId, $orderColumn, $orderInterval, $this->formSpec[F_TABLE_NAME]);
$data = $this->reorder($this->formSpec[F_DRAG_AND_DROP_ORDER_SQL], $dragId, $setTo, $hoverId, $orderColumn,
$orderInterval, $this->formSpec[F_TABLE_NAME]);
return [];
return $data;
}
/**
* @param array $rows
* @param $dragId
* @param $setTo
* @param $hoverId
* @param $orderColumn
* @param $orderInterval
* @param $tableName
* Calculate new ord values. The array rows$ contains the old order with
* [
* [
* [DND_COLUMN_ID] => 1,
* [DND_COLUMN_ORD] => 10
* ], [
* [DND_COLUMN_ID] => 2,
* [DND_COLUMN_ORD] => 20
* ],
* ...
* ]
*
* @param array $rows Array with id/ord in the old order.
* @param int $dragId Id of the element which has been drag'ed
* @param string $setTo DND_SET_TO_BEFORE|DND_SET_TO_AFTER Indicates if the drop zone is before or after the $hoverId
* @param int $hoverId Id of element where the drag'ed element has been dropped on.
* @param string $orderColumn Table column where to save the new calculated order.
* @param int $orderInterval Order increment.
* @param string $tableName Table name where to update the order records.
* @return array Array with html-id references to update order values in the browser. Check PROTOCOL.md for 'element-update'.
*
* @throws CodeException
* @throws DbException
* @throws UserFormException
......@@ -106,6 +121,7 @@ class DragAndDrop {
private function reorder(array $rows, $dragId, $setTo, $hoverId, $orderColumn, $orderInterval, $tableName) {
$ord = $orderInterval;
$ordDragOld = -1;
$data = array();
// Reorder. Get index for 'drag' and 'hover'
foreach ($rows as $key => $row) {
......@@ -121,43 +137,52 @@ class DragAndDrop {
switch ($setTo) {
case DND_SET_TO_BEFORE:
$this->setNewOrder($tableName, $orderColumn, $dragId, $ordDragOld, $ord);
$data = $this->setNewOrder($tableName, $orderColumn, $dragId, $ordDragOld, $ord, $data);
$ord += $orderInterval;
$this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord);
$data = $this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord, $data);
break;
case DND_SET_TO_AFTER:
$this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord);
$data = $this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord, $data);
$ord += $orderInterval;
$this->setNewOrder($tableName, $orderColumn, $dragId, $ordDragOld, $ord);
$data = $this->setNewOrder($tableName, $orderColumn, $dragId, $ordDragOld, $ord, $data);
break;
default:
throw new CodeException('Unkown setTo string', $setTo, ERROR_UNKNOWN_TOKEN);
}
} else {
$this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord);
$data = $this->setNewOrder($tableName, $orderColumn, $row[DND_COLUMN_ID], $row[DND_COLUMN_ORD], $ord, $data);
}
$ord += $orderInterval;
}
return $data;
}
/**
* @param $tableName
* @param $orderColumn
* @param $id
* @param $ordOld
* @param $ordNew
* @param string $tableName
* @param string $orderColumn
* @param int $id
* @param int $ordOld
* @param int $ordNew
* @param array $data
* @return array
* @throws CodeException
* @throws DbException
* @throws UserFormException
*/
private function setNewOrder($tableName, $orderColumn, $id, $ordOld, $ordNew) {
private function setNewOrder($tableName, $orderColumn, $id, $ordOld, $ordNew, array $data) {
if ($ordNew == $ordOld) {
return;
return $data;
}
$this->db->sql("UPDATE $tableName SET $orderColumn=? WHERE id=?", ROW_REGULAR, [$ordNew, $id]);
// Converting to string is necessary: JSON detects int else.
$data[API_ELEMENT_UPDATE][DND_ORD_HTML_ID_PREFIX . $id][API_ELEMENT_CONTENT] = (string)$ordNew;
return $data;
}
}
\ No newline at end of file
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