Commit 6c1351ad7230c5f35bdd335504dd78517a3ab5e7

Authored by megan_w
1 parent 21d7958e

KTS-3161

"Allow the user to change the ordering of the browse columns"
Fixed. Added the logic to change the order.

Committed by: Megan Watson
Reviewed by: Jonathan Byrne



git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@8334 c91229c3-7414-0410-bfa2-8a42b809f60b
lib/browse/columnentry.inc.php
... ... @@ -6,46 +6,46 @@
6 6 * KnowledgeTree Open Source Edition
7 7 * Document Management Made Simple
8 8 * Copyright (C) 2004 - 2008 The Jam Warehouse Software (Pty) Limited
9   - *
  9 + *
10 10 * This program is free software; you can redistribute it and/or modify it under
11 11 * the terms of the GNU General Public License version 3 as published by the
12 12 * Free Software Foundation.
13   - *
  13 + *
14 14 * This program is distributed in the hope that it will be useful, but WITHOUT
15 15 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 16 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
17 17 * details.
18   - *
  18 + *
19 19 * You should have received a copy of the GNU General Public License
20 20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21   - *
  21 + *
22 22 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
23 23 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
24   - *
  24 + *
25 25 * The interactive user interfaces in modified source and object code versions
26 26 * of this program must display Appropriate Legal Notices, as required under
27 27 * Section 5 of the GNU General Public License version 3.
28   - *
  28 + *
29 29 * In accordance with Section 7(b) of the GNU General Public License version 3,
30 30 * these Appropriate Legal Notices must retain the display of the "Powered by
31   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  31 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
32 32 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
33   - * must display the words "Powered by KnowledgeTree" and retain the original
34   - * copyright notice.
  33 + * must display the words "Powered by KnowledgeTree" and retain the original
  34 + * copyright notice.
35 35 * Contributor( s): ______________________________________
36 36 *
37 37 */
38   -
  38 +
39 39 class KTColumnEntry extends KTEntity {
40 40  
41   -
  41 +
42 42 /** role object primary key */
43 43 var $sViewNamespace;
44 44 var $sColumnNamespace;
45   - var $iPosition;
  45 + var $iPosition;
46 46 var $sConfigArray;
47 47 var $bRequired;
48   -
  48 +
49 49 var $_aFieldToSelect = array(
50 50 'iId' => 'id',
51 51 'sColumnNamespace' => 'column_namespace',
... ... @@ -54,24 +54,24 @@ class KTColumnEntry extends KTEntity {
54 54 'sConfigArray' => 'config_array',
55 55 'bRequired' => 'required'
56 56 );
57   -
  57 +
58 58 var $_bUsePearError = true;
59 59  
60   - function getColumnNamespace() { return $this->sColumnNamespace; }
  60 + function getColumnNamespace() { return $this->sColumnNamespace; }
61 61 function setColumnNamespace($sNewValue) { $this->sColumnNamespace = $sNewValue; }
62   - function getViewNamespace() { return $this->sViewNamespace; }
  62 + function getViewNamespace() { return $this->sViewNamespace; }
63 63 function setViewNamespace($sNewValue) { $this->sViewNamespace = $sNewValue; }
64   - function getPosition() { return $this->iPosition; }
  64 + function getPosition() { return $this->iPosition; }
65 65 function setPosition($iNewValue) { $this->iPosition = $iNewValue; }
66   - function getConfigArray() { return unserialize($this->sConfigArray); }
  66 + function getConfigArray() { return unserialize($this->sConfigArray); }
67 67 function setConfigArray($aNewValue) { $this->sConfigArray = serialize($aNewValue); }
68   - function getRequired() { return $this->bRequired; }
  68 + function getRequired() { return $this->bRequired; }
69 69 function setRequired($bNewValue) { $this->bRequired = $bNewValue; }
70 70  
71   -
  71 +
72 72 function _fieldValues () { return array(
73 73 'column_namespace' => $this->sColumnNamespace,
74   - 'view_namespace' => $this->sViewNamespace,
  74 + 'view_namespace' => $this->sViewNamespace,
75 75 'config_array' => $this->sConfigArray,
76 76 'position' => $this->iPosition,
77 77 'required' => $this->bRequired,
... ... @@ -81,22 +81,172 @@ class KTColumnEntry extends KTEntity {
81 81 function _table () { return KTUtil::getTableName('column_entries'); }
82 82 function get($iEntryId) { return KTEntityUtil::get('KTColumnEntry', $iEntryId); }
83 83 function & getList($sWhereClause = null) { return KTEntityUtil::getList2('KTColumnEntry', $sWhereClause); }
84   - function & createFromArray($aOptions) {
85   - // transparently convert the options.
86   -
  84 + function & createFromArray($aOptions) {
  85 + // transparently convert the options.
  86 +
87 87 $aOptions['configarray'] = serialize(KTUtil::arrayGet($aOptions, 'config', array()));
88 88 unset($aOptions['config']);
89   -
90   - return KTEntityUtil::createFromArray('KTColumnEntry', $aOptions);
91   - }
92   -
  89 +
  90 + return KTEntityUtil::createFromArray('KTColumnEntry', $aOptions);
  91 + }
  92 +
93 93 function & getByView($sViewNamespace, $aOptions = null) {
94 94 if (is_null($aOptions)) { $aOptions = array(); }
95 95 $aOptions['multi'] = true;
  96 + $aOptions['orderby'] = 'position';
96 97 $aSelect = array('view_namespace' => $sViewNamespace);
97   -
  98 +
98 99 return KTEntityUtil::getByDict('KTColumnEntry', $aSelect, $aOptions);
99 100 }
100 101  
  102 + /**
  103 + * Get the postion of the last entry
  104 + */
  105 + function getNextEntryPosition($sViewNamespace){
  106 + $sql = "SELECT position FROM column_entries
  107 + WHERE view_namespace = ?
  108 + ORDER BY position DESC LIMIT 1";
  109 + $aParams = array($sViewNamespace);
  110 +
  111 + $result = DBUtil::getResultArray(array($sql, $aParams));
  112 +
  113 + if(PEAR::isError($result) || empty($result)){
  114 + return 1000;
  115 + }
  116 + return $result[0]['position'] + 1;
  117 + }
  118 +
  119 + /**
  120 + * Reset the order of the columns
  121 + *
  122 + */
  123 + function reorderColumns($sViewNamespace) {
  124 + // Get the columns in the order they'll appear - first by position then by id
  125 + $sql = "SELECT id, position FROM column_entries
  126 + WHERE view_namespace = ?
  127 + ORDER BY position, id ASC";
  128 + $aParams = array($sViewNamespace);
  129 +
  130 + $result = DBUtil::getResultArray(array($sql, $aParams));
  131 +
  132 + if(PEAR::isError($result) || empty($result)){
  133 + return false;
  134 + }
  135 +
  136 + // Set all positions to be unique and in order
  137 + foreach($result as $key => $column){
  138 + $position = $column['position'];
  139 +
  140 + // If the column position is correct in the order, continue
  141 + if($position == $key){
  142 + continue;
  143 + }
  144 +
  145 + // Reset the position
  146 + $aFields = array();
  147 + $aFields['position'] = $key;
  148 +
  149 + $res = DBUtil::autoUpdate('column_entries', $aFields, $column['id']);
  150 + }
  151 + return true;
  152 + }
  153 +
  154 + /**
  155 + * Get the next postion up / down
  156 + */
  157 + function getNextPosition($sViewNamespace, $iId, $position, $dir = 'up') {
  158 + switch($dir){
  159 + case 'down':
  160 + $comp = '>';
  161 + $order = 'ASC';
  162 + break;
  163 + default:
  164 + $comp = '<';
  165 + $order = 'DESC';
  166 + }
  167 +
  168 + // Get the column above / below to swop position
  169 + $sql = "SELECT id, position FROM column_entries
  170 + WHERE view_namespace = ? AND (position {$comp} ? OR (position = ? AND id {$comp} ?))
  171 + ORDER BY position {$order} LIMIT 1";
  172 + $aParams = array($sViewNamespace, $position, $position, $iId);
  173 +
  174 + $result = DBUtil::getOneResult(array($sql, $aParams));
  175 +
  176 + if(PEAR::isError($result) || empty($result)){
  177 + return false;
  178 + }
  179 + return $result;
  180 + }
  181 +
  182 + /**
  183 + * Get the updated position of the column
  184 + *
  185 + * @param int $iId
  186 + * @return int
  187 + */
  188 + function getNewPosition($iId){
  189 + // Get the new position
  190 + $sql = "SELECT id, position FROM column_entries
  191 + WHERE id = ?";
  192 + $aParams = array($iId);
  193 + $result = DBUtil::getOneResult(array($sql, $aParams));
  194 +
  195 + if(PEAR::isError($result) || empty($result)){
  196 + return false;
  197 + }
  198 + return $result['position'];
  199 + }
  200 +
  201 + /**
  202 + * Update the position of a column
  203 + */
  204 + function updatePosition($iId, $position) {
  205 + $aFields = array('position' => $position);
  206 + DBUtil::autoUpdate('column_entries', $aFields, $iId);
  207 + }
  208 +
  209 + /**
  210 + * Move the display position of the column up / down
  211 + */
  212 + function movePosition($sViewNamespace, $iId, $dir = 'up') {
  213 + $position = $this->getPosition();
  214 +
  215 + // Get the column to swop position with
  216 + $next = $this->getNextPosition($sViewNamespace, $iId, $position, $dir);
  217 + if($next === false){
  218 + return false;
  219 + }
  220 +
  221 + // Get position of the next column up / down
  222 + $newPos = $next['position'];
  223 + $iNextId = $next['id'];
  224 +
  225 + if($newPos == $position){
  226 + // 2 columns have the same position - reorder them
  227 + $res = $this->reorderColumns($sViewNamespace);
  228 + if($res === false){
  229 + return false;
  230 + }
  231 +
  232 + $position = $this->getNewPosition($iId);
  233 + if($position === false){
  234 + return false;
  235 + }
  236 +
  237 + // Get the column to swop with
  238 + $next = $this->getNextPosition($sViewNamespace, $iId, $position, $dir);
  239 + if($next === false){
  240 + return false;
  241 + }
  242 + $newPos = $next['position'];
  243 + $iNextId = $next['id'];
  244 + }
  245 +
  246 + // update the columns
  247 + $this->updatePosition($iId, $newPos);
  248 + $this->updatePosition($iNextId, $position);
  249 + return true;
  250 + }
101 251 }
102 252 ?>
103 253 \ No newline at end of file
... ...
plugins/ktcore/admin/manageViews.php
1 1 <?php
2 2 /**
3 3 * $Id$
4   - *
  4 + *
5 5 * KnowledgeTree Open Source Edition
6 6 * Document Management Made Simple
7 7 * Copyright (C) 2004 - 2008 The Jam Warehouse Software (Pty) Limited
8   - *
  8 + *
9 9 * This program is free software; you can redistribute it and/or modify it under
10 10 * the terms of the GNU General Public License version 3 as published by the
11 11 * Free Software Foundation.
12   - *
  12 + *
13 13 * This program is distributed in the hope that it will be useful, but WITHOUT
14 14 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 15 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 16 * details.
17   - *
  17 + *
18 18 * You should have received a copy of the GNU General Public License
19 19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20   - *
  20 + *
21 21 * You can contact The Jam Warehouse Software (Pty) Limited, Unit 1, Tramber Place,
22 22 * Blake Street, Observatory, 7925 South Africa. or email info@knowledgetree.com.
23   - *
  23 + *
24 24 * The interactive user interfaces in modified source and object code versions
25 25 * of this program must display Appropriate Legal Notices, as required under
26 26 * Section 5 of the GNU General Public License version 3.
27   - *
  27 + *
28 28 * In accordance with Section 7(b) of the GNU General Public License version 3,
29 29 * these Appropriate Legal Notices must retain the display of the "Powered by
30   - * KnowledgeTree" logo and retain the original copyright notice. If the display of the
  30 + * KnowledgeTree" logo and retain the original copyright notice. If the display of the
31 31 * logo is not reasonably feasible for technical reasons, the Appropriate Legal Notices
32   - * must display the words "Powered by KnowledgeTree" and retain the original
33   - * copyright notice.
  32 + * must display the words "Powered by KnowledgeTree" and retain the original
  33 + * copyright notice.
34 34 * Contributor( s): ______________________________________
35 35 */
36 36  
... ... @@ -38,42 +38,42 @@ require_once(KT_LIB_DIR . &#39;/templating/templating.inc.php&#39;);
38 38 require_once(KT_LIB_DIR . '/widgets/reorderdisplay.inc.php');
39 39 require_once(KT_LIB_DIR . '/dispatcher.inc.php');
40 40 require_once(KT_LIB_DIR . '/browse/columnregistry.inc.php');
41   -
  41 +
42 42 class ManageViewDispatcher extends KTAdminDispatcher {
43 43  
44 44 function check() {
45   -
  45 +
46 46 $this->aBreadcrumbs[] = array('url' => $_SERVER['PHP_SELF'], 'name' => _kt('Manage Views'));
47 47 return parent::check();
48 48 }
49 49  
50 50 function do_main() {
51 51 $oTemplating =& KTTemplating::getSingleton();
52   - $oTemplate = $oTemplating->loadTemplate('ktcore/misc/columns/select_view');
53   -
54   - $oColumnRegistry =& KTColumnRegistry::getSingleton();
55   -
  52 + $oTemplate = $oTemplating->loadTemplate('ktcore/misc/columns/select_view');
  53 +
  54 + $oColumnRegistry =& KTColumnRegistry::getSingleton();
  55 +
56 56 $aViews = $oColumnRegistry->getViews();
57 57  
58   - $aTemplateData = array(
59   - 'context' => $this,
  58 + $aTemplateData = array(
  59 + 'context' => $this,
60 60 'views' => $aViews,
61 61 );
62 62 return $oTemplate->render($aTemplateData);
63 63 }
64 64  
65   - function do_editView() {
  65 + function do_editView() {
66 66 $oTemplating =& KTTemplating::getSingleton();
67   - $oTemplate = $oTemplating->loadTemplate('ktcore/misc/columns/edit_view');
68   -
69   - $oColumnRegistry =& KTColumnRegistry::getSingleton();
  67 + $oTemplate = $oTemplating->loadTemplate('ktcore/misc/columns/edit_view');
  68 +
  69 + $oColumnRegistry =& KTColumnRegistry::getSingleton();
70 70 $aColumns = $oColumnRegistry->getColumnsForView($_REQUEST['viewNS']);
71 71 //var_dump($aColumns); exit(0);
72 72 $aAllColumns = $oColumnRegistry->getColumns();
73 73  
74   - $view_name = $oColumnRegistry->getViewName($_REQUEST['viewNS']);
  74 + $view_name = $oColumnRegistry->getViewName(($_REQUEST['viewNS']));
75 75 $this->oPage->setTitle($view_name);
76   - $this->oPage->setBreadcrumbDetails($view_name);
  76 + $this->oPage->setBreadcrumbDetails($view_name);
77 77  
78 78 $aOptions = array();
79 79 $vocab = array();
... ... @@ -83,59 +83,98 @@ class ManageViewDispatcher extends KTAdminDispatcher {
83 83 $aOptions['vocab'] = $vocab;
84 84 $add_field = new KTLookupWidget(_kt("Columns"), _kt("Select a column to add to the view. Please note that while you can add multiple copies of a column, they will all behave as a single column"), 'column_ns', null, $this->oPage, true, null, $aErrors = null, $aOptions);
85 85  
86   - $aTemplateData = array(
  86 + $aTemplateData = array(
87 87 'context' => $this,
88 88 'current_columns' => $aColumns,
89 89 'all_columns' => $aAllColumns,
90 90 'view' => $_REQUEST['viewNS'],
91 91 'add_field' => $add_field,
92 92 );
93   - return $oTemplate->render($aTemplateData);
94   - }
95   -
96   - function do_deleteEntry() {
97   - $entry_id = KTUtil::arrayGet($_REQUEST, 'entry_id');
98   - $view = KTUtil::arrayGet($_REQUEST, 'viewNS');
99   -
100   - // none of these conditions can be reached "normally".
101   -
  93 + return $oTemplate->render($aTemplateData);
  94 + }
  95 +
  96 + function do_deleteEntry() {
  97 + $entry_id = KTUtil::arrayGet($_REQUEST, 'entry_id');
  98 + $view = KTUtil::arrayGet($_REQUEST, 'viewNS');
  99 +
  100 + // none of these conditions can be reached "normally".
  101 +
102 102 $oEntry = KTColumnEntry::get($entry_id);
103 103 if (PEAR::isError($oEntry)) {
104 104 $this->errorRedirectToMain(_kt("Unable to locate the entry"));
105 105 }
106   -
  106 +
107 107 if ($oEntry->getRequired()) {
108 108 $this->errorRedirectToMain(_kt("That column is required"));
109 109 }
110   -
  110 +
111 111 if ($oEntry->getViewNamespace() != $view) {
112 112 $this->errorRedirectToMain(_kt("That column is not for the specified view"));
113 113 }
114   -
  114 +
115 115 $res = $oEntry->delete();
116   -
  116 +
117 117 if (PEAR::isError($res)) {
118 118 $this->errorRedirectToMain(sprintf(_kt("Failed to remove that column: %s"), $res->getMessage()));
119   - }
120   -
  119 + }
  120 +
121 121 $this->successRedirectTo("editView", _kt("Deleted Entry"), sprintf("viewNS=%s", $view));
122   - }
123   -
  122 + }
  123 +
124 124 function do_addEntry() {
125   - $column_ns = KTUtil::arrayGet($_REQUEST, 'column_ns');
126   - $view = KTUtil::arrayGet($_REQUEST, 'viewNS');
  125 + $column_ns = KTUtil::arrayGet($_REQUEST, 'column_ns');
  126 + $view = KTUtil::arrayGet($_REQUEST, 'viewNS');
127 127  
128   - $this->startTransaction();
129   -
  128 + $this->startTransaction();
  129 +
  130 + $position = KTColumnEntry::getNextEntryPosition($view);
130 131 $oEntry = KTColumnEntry::createFromArray(array(
131 132 'ColumnNamespace' => $column_ns,
132 133 'ViewNamespace' => $view,
133   - 'Position' => 1000, // start it at the bottom
  134 + 'Position' => $position, // start it at the bottom
134 135 'config' => array(), // stub, for now.
135 136 'Required' => 0
136   - ));
  137 + ));
  138 +
  139 + $this->successRedirectTo("editView", _kt("Added Entry"), sprintf("viewNS=%s", $view));
  140 + }
  141 +
  142 + function do_orderUp(){
  143 + $entryId = $_REQUEST['entry_id'];
  144 + $view = $_REQUEST['viewNS'];
  145 +
  146 + $oEntry = KTColumnEntry::get($entryId);
  147 + if (PEAR::isError($oEntry)) {
  148 + $this->errorRedirectTo('editView', _kt('Unable to locate the column entry'), "viewNS={$view}");
  149 + exit();
  150 + }
  151 +
  152 + $res = $oEntry->movePosition($view, $entryId, 'up');
  153 + if (PEAR::isError($res)) {
  154 + $this->errorRedirectTo('editView', $res->getMessage(), "viewNS={$view}");
  155 + exit();
  156 + }
  157 +
  158 + $this->redirectTo('editView', "viewNS={$view}");
  159 + }
  160 +
  161 + function do_orderDown(){
  162 + $entryId = $_REQUEST['entry_id'];
  163 + $view = $_REQUEST['viewNS'];
  164 +
  165 + $oEntry = KTColumnEntry::get($entryId);
  166 + if (PEAR::isError($oEntry)) {
  167 + $this->errorRedirectTo('editView', _kt('Unable to locate the column entry'), "viewNS={$view}");
  168 + exit();
  169 + }
  170 +
  171 + $res = $oEntry->movePosition($view, $entryId, 'down');
  172 + if (PEAR::isError($res)) {
  173 + $this->errorRedirectTo('editView', $res->getMessage(), "viewNS={$view}");
  174 + exit();
  175 + }
137 176  
138   - $this->successRedirectTo("editView", _kt("Added Entry"), sprintf("viewNS=%s", $view));
  177 + $this->redirectTo("editView", "viewNS={$view}");
139 178 }
140 179  
141 180 }
... ...
templates/ktcore/misc/columns/edit_view.smarty
1 1 <h2>{i18n}Edit View{/i18n}</h2>
2 2  
3   -<p class="descriptiveText">{i18n}The columns included in this view are displayed below. To add additional columns into the
  3 +<p class="descriptiveText">{i18n}The columns included in this view are displayed below. To add additional columns into the
4 4 view, use the form below the list. To remove items, click on the "delete" icon next to the column name. Note that some columns may be required
5   -in a given view. Also, while you can
  5 +in a given view. Also, while you can
6 6 have multiple copies of a given column in a specific view this is not recommended.{/i18n}</p>
7 7  
8 8 {if (!empty($current_columns))}
9 9 <table class="kt_collection narrow" cellspacing="0">
10 10 <thead>
11 11 <tr>
12   - <th>{i18n}Column{/i18n}</th>
13   - <th>{i18n}Delete{/i18n}</th>
  12 + <th>{i18n}Column{/i18n}</th>
  13 + <th>{i18n}Delete{/i18n}</th>
  14 + <th colspan="2">{i18n}Position{/i18n}</th>
14 15 </tr>
15 16 </thead>
16 17 <tbody>
17   - {foreach from=$current_columns item=oColumn}
  18 + {foreach name=cols from=$current_columns item=oColumn}
18 19 <tr>
19 20 <td>{$oColumn->getName()}</td>
20 21  
21 22 {if $oColumn->getRequiredInView()}
22 23 <td>&mdash;</td>
23   - {else}
24   - <td><a href="{addQS}action=deleteEntry&entry_id={$oColumn->getEntryId()}&viewNS={$view}{/addQS}" class="ktAction ktDelete">{i18n}Delete{/i18n}</a></td>
  24 + {else}
  25 + <td><a href="{addQS}action=deleteEntry&entry_id={$oColumn->getEntryId()}&viewNS={$view}{/addQS}" class="ktAction ktDelete">{i18n}Delete{/i18n}</a></td>
25 26 {/if}
26   - </tr>
  27 +
  28 + <td>
  29 + {if !$smarty.foreach.cols.first}
  30 + <a href="{addQS}action=orderUp&entry_id={$oColumn->getEntryId()}&viewNS={$view}{/addQS}" class="ktAction ktMoveUp">{i18n}Reorder up{/i18n}</a>
  31 + {/if}
  32 + </td>
  33 + <td>
  34 + {if !$smarty.foreach.cols.last}
  35 + <a href="{addQS}action=orderDown&entry_id={$oColumn->getEntryId()}&viewNS={$view}{/addQS}" class="ktAction ktMoveDown">{i18n}Reorder down{/i18n}</a>
  36 + {/if}
  37 + </td>
  38 + </tr>
27 39 {/foreach}
28 40 </tbody>
29 41 </table>
... ... @@ -38,9 +50,9 @@ have multiple copies of a given column in a specific view this is not recommende
38 50 {$add_field->render()}
39 51  
40 52 <div class="form_actions">
41   - <input type="submit" value="{i18n}Add Column to View{/i18n}"/>
  53 + <input type="submit" value="{i18n}Add Column to View{/i18n}"/>
42 54 <input type="hidden" name="action" value="addEntry" />
43   - <input type="hidden" name="viewNS" value="{$view}" />
44   - </div>
  55 + <input type="hidden" name="viewNS" value="{$view}" />
  56 + </div>
45 57 </fieldset>
46 58 </form>
47 59 \ No newline at end of file
... ...