Commit fd008b434faa8f5a5832b2e33ed3d63cf41b5977

Authored by Brad Shuttleworth
1 parent 76ce69c5

re-enable notification-specification on workflows.


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@5967 c91229c3-7414-0410-bfa2-8a42b809f60b
lib/widgets/forms.inc.php
@@ -237,7 +237,10 @@ class KTForm { @@ -237,7 +237,10 @@ class KTForm {
237 return $this->renderContaining($sWidgets . ' ' . $sButtons); 237 return $this->renderContaining($sWidgets . ' ' . $sButtons);
238 } 238 }
239 239
240 - function renderPage($sTitle, $sDescription = null) { 240 + function renderPage($sTitle = null, $sDescription = null) {
  241 + if ($sTitle == null) {
  242 + $sTitle = $this->sLabel;
  243 + }
241 $pageval = $this->render(); 244 $pageval = $this->render();
242 $sHelpText = ''; 245 $sHelpText = '';
243 if (!is_null($sDescription)) { 246 if (!is_null($sDescription)) {
plugins/ktcore/KTCorePlugin.php
@@ -139,6 +139,7 @@ class KTCorePlugin extends KTPlugin { @@ -139,6 +139,7 @@ class KTCorePlugin extends KTPlugin {
139 $this->registerWidget('KTCoreTransparentFieldsetWidget', 'ktcore.widgets.transparentfieldset', 'KTWidgets.php'); 139 $this->registerWidget('KTCoreTransparentFieldsetWidget', 'ktcore.widgets.transparentfieldset', 'KTWidgets.php');
140 $this->registerWidget('KTCoreCollectionWidget', 'ktcore.widgets.collection', 'KTWidgets.php'); 140 $this->registerWidget('KTCoreCollectionWidget', 'ktcore.widgets.collection', 'KTWidgets.php');
141 $this->registerWidget('KTCoreTreeMetadataWidget', 'ktcore.widgets.treemetadata', 'KTWidgets.php'); 141 $this->registerWidget('KTCoreTreeMetadataWidget', 'ktcore.widgets.treemetadata', 'KTWidgets.php');
  142 + $this->registerWidget('KTDescriptorSelectionWidget', 'ktcore.widgets.descriptorselection', 'KTWidgets.php');
142 143
143 $this->registerPage('collection', 'KTCoreCollectionPage', 'KTWidgets.php'); 144 $this->registerPage('collection', 'KTCoreCollectionPage', 'KTWidgets.php');
144 145
@@ -154,6 +155,7 @@ class KTCorePlugin extends KTPlugin { @@ -154,6 +155,7 @@ class KTCorePlugin extends KTPlugin {
154 $this->registerValidator('KTFieldsetValidator', 'ktcore.validators.fieldset', 'KTValidators.php'); 155 $this->registerValidator('KTFieldsetValidator', 'ktcore.validators.fieldset', 'KTValidators.php');
155 $this->registerValidator('KTFileValidator', 'ktcore.validators.file', 'KTValidators.php'); 156 $this->registerValidator('KTFileValidator', 'ktcore.validators.file', 'KTValidators.php');
156 $this->registerValidator('KTRequiredFileValidator', 'ktcore.validators.requiredfile', 'KTValidators.php'); 157 $this->registerValidator('KTRequiredFileValidator', 'ktcore.validators.requiredfile', 'KTValidators.php');
  158 + $this->registerValidator('KTArrayValidator', 'ktcore.validators.array', 'KTValidators.php');
157 159
158 // criterion 160 // criterion
159 $this->registerCriterion('NameCriterion', 'ktcore.criteria.name', KT_LIB_DIR . '/browse/Criteria.inc'); 161 $this->registerCriterion('NameCriterion', 'ktcore.criteria.name', KT_LIB_DIR . '/browse/Criteria.inc');
plugins/ktcore/KTValidators.php
@@ -397,4 +397,27 @@ class KTFileValidator extends KTValidator { @@ -397,4 +397,27 @@ class KTFileValidator extends KTValidator {
397 } 397 }
398 } 398 }
399 399
  400 +
  401 +class KTArrayValidator extends KTValidator {
  402 + var $sNamespace = 'ktcore.validators.array';
  403 +
  404 + function validate($data) {
  405 + $results = array();
  406 + $errors = array();
  407 +
  408 + // very simple if we're required and not present, fail
  409 + // otherwise, its ok.
  410 + $val = KTUtil::arrayGet($data, $this->sInputVariable);
  411 + //var_dump($data); exit(0);
  412 + if ($this->bProduceOutput) {
  413 + $results[$this->sOutputVariable] = $val;
  414 + }
  415 +
  416 + return array(
  417 + 'errors' => $errors,
  418 + 'results' => $results,
  419 + );
  420 + }
  421 +}
  422 +
400 ?> 423 ?>
plugins/ktcore/KTWidgets.php
@@ -272,6 +272,55 @@ class KTCoreEntitySelectionWidget extends KTCoreSelectionWidget { @@ -272,6 +272,55 @@ class KTCoreEntitySelectionWidget extends KTCoreSelectionWidget {
272 } 272 }
273 } 273 }
274 274
  275 +
  276 +class KTDescriptorSelectionWidget extends KTWidget {
  277 + var $sNamespace = 'ktcore.widgets.descriptorselection';
  278 + var $sTemplate = 'ktcore/forms/widgets/descriptor';
  279 +
  280 + var $aJavascript = array('resources/js/jsonlookup.js');
  281 +
  282 + function configure($aOptions) {
  283 + $res = parent::configure($aOptions);
  284 + if (PEAR::isError($res)) {
  285 + return $res;
  286 + }
  287 +
  288 +
  289 + }
  290 +
  291 + function getWidget() {
  292 + $oTemplating =& KTTemplating::getSingleton();
  293 + $oTemplate = $oTemplating->loadTemplate($this->sTemplate);
  294 +
  295 + $src_location = $this->aOptions['src'];
  296 + $sJS = sprintf("addLoadEvent(initJSONLookup(\"%s\", \"%s\"));", $this->sBasename, $src_location);
  297 +
  298 +
  299 + // its bad, but that's life.
  300 + $oPage =& $GLOBALS['main'];
  301 + $oPage->requireJSStandalone($sJS);
  302 +
  303 + $this->aOptions['multi'] = true;
  304 +
  305 + $aTemplateData = array(
  306 + "context" => $this,
  307 + "label" => $this->sLabel,
  308 + "description" => $this->sDescription,
  309 + "name" => $this->sName,
  310 + "required" => $this->bRequired,
  311 + "has_id" => ($this->sId !== null),
  312 + "id" => $this->sId,
  313 + "has_value" => ($this->value !== null),
  314 + "value" => $this->value,
  315 + "has_errors" => $bHasErrors,
  316 + "errors" => $this->aErrors,
  317 + 'short_name' => $this->sBasename,
  318 + "options" => $this->aOptions,
  319 + );
  320 + return $oTemplate->render($aTemplateData);
  321 + }
  322 +}
  323 +
275 class KTCoreTreeMetadataWidget extends KTWidget { 324 class KTCoreTreeMetadataWidget extends KTWidget {
276 var $sNamespace = 'ktcore.widgets.treemetadata'; 325 var $sNamespace = 'ktcore.widgets.treemetadata';
277 var $iFieldId; 326 var $iFieldId;
plugins/ktcore/admin/workflowsv2.php
@@ -1696,6 +1696,270 @@ class KTWorkflowAdminV2 extends KTAdminDispatcher { @@ -1696,6 +1696,270 @@ class KTWorkflowAdminV2 extends KTAdminDispatcher {
1696 exit(0); 1696 exit(0);
1697 } 1697 }
1698 1698
  1699 + function do_managenotifications() {
  1700 + $oTemplate =& $this->oValidator->validateTemplate("ktcore/workflow/admin/manage_notifications");
  1701 + $oTemplate->setData(array(
  1702 + 'context' => $this,
  1703 + 'states' => KTWorkflowState::getByWorkflow($this->oWorkflow),
  1704 + ));
  1705 + return $oTemplate->render();
  1706 + }
  1707 +
  1708 + function describeStateNotifications($oState) {
  1709 + $aAllowed = KTWorkflowUtil::getInformedForState($oState);
  1710 +
  1711 + $aUsers = array();
  1712 + $aGroups = array();
  1713 + $aRoles = array();
  1714 +
  1715 + foreach (KTUtil::arrayGet($aAllowed,'user',array()) as $iUserId) {
  1716 + $oU = User::get($iUserId);
  1717 + if (PEAR::isError($oU) || ($oU == false)) {
  1718 + continue;
  1719 + } else {
  1720 + $aUsers[] = $oU->getName();
  1721 + }
  1722 + }
  1723 +
  1724 + foreach (KTUtil::arrayGet($aAllowed,'group',array()) as $iGroupId) {
  1725 + $oG = Group::get($iGroupId);
  1726 + if (PEAR::isError($oG) || ($oG == false)) {
  1727 + continue;
  1728 + } else {
  1729 + $aGroups[] = $oG->getName();
  1730 + }
  1731 + }
  1732 +
  1733 + foreach (KTUtil::arrayGet($aAllowed,'role',array()) as $iRoleId) {
  1734 + $oR = Role::get($iRoleId);
  1735 + if (PEAR::isError($oR) || ($oR == false)) {
  1736 + continue;
  1737 + } else {
  1738 + $aRoles[] = $oR->getName();
  1739 + }
  1740 + }
  1741 +
  1742 + $sNotify = '';
  1743 + if (!empty($aUsers)) {
  1744 + $sNotify .= '<em>' . _kt('Users:') . '</em> ';
  1745 + $sNotify .= implode(', ', $aUsers);
  1746 + }
  1747 +
  1748 + if (!empty($aGroups)) {
  1749 + if (!empty($sNotify)) { $sNotify .= ' &mdash; '; }
  1750 + $sNotify .= '<em>' . _kt('Groups:') . '</em> ';
  1751 + $sNotify .= implode(', ', $aGroups);
  1752 + }
  1753 +
  1754 + if (!empty($aRoles)) {
  1755 + if (!empty($sNotify)) { $sNotify .= ' &mdash; '; }
  1756 + $sNotify .= '<em>' . _kt('Roles:') . '</em> ';
  1757 + $sNotify .= implode(', ', $aRoles);
  1758 + }
  1759 +
  1760 + if (empty($sNotify)) { $sNotify = _kt('No notifications.'); }
  1761 +
  1762 + return $sNotify;
  1763 + }
  1764 +
  1765 + function descriptorToJSON($aAllowed) {
  1766 + $values = array();
  1767 +
  1768 + foreach (KTUtil::arrayGet($aAllowed,'user',array()) as $oU) {
  1769 + if (!is_object($oU)) {
  1770 + $iUserId = $oU;
  1771 + $oU = User::get($iUserId);
  1772 + } else {
  1773 + $iUserId = $oU->getId();
  1774 + }
  1775 +
  1776 + if (PEAR::isError($oU) || ($oU == false)) {
  1777 + continue;
  1778 + } else {
  1779 + $values[sprintf("users[%d]", $iUserId)] = sprintf('User: %s', $oU->getName());
  1780 + }
  1781 + }
  1782 +
  1783 + foreach (KTUtil::arrayGet($aAllowed,'group',array()) as $oG) {
  1784 + if (!is_object($oG)) {
  1785 + $iGroupId = $oG;
  1786 + $oG = Group::get($iGroupId);
  1787 + } else {
  1788 + $iGroupId = $oG->getId();
  1789 + }
  1790 + if (PEAR::isError($oG) || ($oG == false)) {
  1791 + continue;
  1792 + } else {
  1793 + $values[sprintf("groups[%d]", $iGroupId)] = sprintf('Group: %s', $oG->getName());
  1794 + }
  1795 + }
  1796 +
  1797 + foreach (KTUtil::arrayGet($aAllowed,'role',array()) as $oR) {
  1798 + if (!is_object($oR)) {
  1799 + $iRoleId = $oR;
  1800 + $oR = Role::get($iRoleId);
  1801 + } else {
  1802 + $iRoleId = $oR->getId();
  1803 + }
  1804 +
  1805 + if (PEAR::isError($oR) || ($oR == false)) {
  1806 + continue;
  1807 + } else {
  1808 + $values[sprintf("roles[%d]", $iRoleId)] = sprintf('Role: %s', $oR->getName());
  1809 + }
  1810 + }
  1811 +
  1812 + return $values;
  1813 + }
  1814 +
  1815 + function form_editnotifications($oState) {
  1816 + $oForm = new KTForm;
  1817 + $oForm->setOptions(array(
  1818 + 'context' => $this,
  1819 + 'label' => _kt("Edit State Notifications."),
  1820 + 'identifier' => 'ktcore.workflow.notifications',
  1821 + 'submit_label' => _kt("Update Notifications"),
  1822 + 'cancel_action' => 'managenotifications',
  1823 + 'action' => 'savenotifications',
  1824 + 'fail_action' => 'editnotifications',
  1825 + ));
  1826 + $preval = KTWorkflowUtil::getInformedForState($oState);
  1827 + $oForm->setWidgets(array(
  1828 + array('ktcore.widgets.descriptorselection', array(
  1829 + 'label' => _kt("Users to inform"),
  1830 + 'description' => _kt("Select which users, groups and roles to be notified."),
  1831 + 'name' => 'users',
  1832 + 'src' => KTUtil::addQueryStringSelf($this->meldPersistQuery(array('json_action'=> 'notificationusers'), "json")),
  1833 + 'value' => $this->descriptorToJSON($preval),
  1834 + )),
  1835 + ));
  1836 + $oForm->setValidators(array(
  1837 + array('ktcore.validators.array', array(
  1838 + 'test' => 'users',
  1839 + 'output' => 'users',
  1840 + )),
  1841 + ));
  1842 + return $oForm;
  1843 + }
  1844 +
  1845 + function do_editnotifications() {
  1846 + $oForm = $this->form_editnotifications($this->oState);
  1847 + return $oForm->renderPage();
  1848 + }
  1849 +
  1850 + function do_savenotifications() {
  1851 +
  1852 +
  1853 + $oForm = $this->form_editnotifications($this->oState);
  1854 + $res = $oForm->validate();
  1855 +
  1856 + if (!empty($res['errors'])) {
  1857 + return $oForm->handleError();
  1858 + }
  1859 +
  1860 + $data = $res['results'];
  1861 + // now, an annoying problem is that we do *not* have the final set.
  1862 + // so we need to get the original, add the new ones, remove the old ones.
  1863 + //
  1864 + // because its not *really* isolated properly, we need to post-process
  1865 + // the data.
  1866 +
  1867 + // we need the old one
  1868 + $aAllowed = KTWorkflowUtil::getInformedForState($this->oState);
  1869 +
  1870 + $user_pattern = '|users\[(.*)\]|';
  1871 + $group_pattern = '|groups\[(.*)\]|';
  1872 + $role_pattern = '|roles\[(.*)\]|';
  1873 +
  1874 + $user = KTUtil::arrayGet($aAllowed, 'user', array());
  1875 + $group = KTUtil::arrayGet($aAllowed, 'group', array());
  1876 + $role = KTUtil::arrayGet($aAllowed, 'role', array());
  1877 +
  1878 + // do a quick overpass
  1879 + $newAllowed = array();
  1880 + if (!empty($user)) { $newAllowed['user'] = array_combine($user, $user); }
  1881 + else { $newAllowed['user'] = array(); }
  1882 + if (!empty($group)) { $newAllowed['group'] = array_combine($group, $group); }
  1883 + else { $newAllowed['group'] = array(); }
  1884 + if (!empty($role)) { $newAllowed['role'] = array_combine($role, $role); }
  1885 + else { $newAllowed['role'] = array(); }
  1886 +
  1887 + $added = explode(',', $data['users']['added']);
  1888 + $removed = explode(',', $data['users']['removed']);
  1889 +
  1890 + foreach ($added as $akey) {
  1891 + $matches = array();
  1892 + if (preg_match($user_pattern, $akey, $matches)) { $newAllowed['user'][$matches[1]] = $matches[1]; }
  1893 + else if (preg_match($group_pattern, $akey, $matches)) { $newAllowed['group'][$matches[1]] = $matches[1]; }
  1894 + else if (preg_match($role_pattern, $akey, $matches)) { $newAllowed['role'][$matches[1]] = $matches[1]; }
  1895 + }
  1896 +
  1897 + foreach ($removed as $akey) {
  1898 + $matches = array();
  1899 + if (preg_match($user_pattern, $akey, $matches)) { unset($newAllowed['user'][$matches[1]]); }
  1900 + else if (preg_match($group_pattern, $akey, $matches)) { unset($newAllowed['group'][$matches[1]]); }
  1901 + else if (preg_match($role_pattern, $akey, $matches)) { unset($newAllowed['role'][$matches[1]]); }
  1902 + }
  1903 +
  1904 + // FIXME check that these are all users.
  1905 +
  1906 + $res = KTWorkflowUtil::setInformedForState($this->oState, $newAllowed);
  1907 + if (PEAR::isError($res)) {
  1908 + return $oForm->handleError($res->getMessage());
  1909 + }
  1910 +
  1911 + $this->successRedirectTo("managenotifications", _kt("Notifications updated."));
  1912 + }
  1913 +
  1914 + function json_notificationusers() {
  1915 + $sFilter = KTUtil::arrayGet($_REQUEST, 'filter', false);
  1916 + if ($sFilter == false) {
  1917 + $values = array('off'=>'-- Please filter --'); // default
  1918 + }
  1919 + $sFilter = trim($sFilter);
  1920 + $values = array('off'=>'-- Please filter --'); // default
  1921 +
  1922 + if (!empty($sFilter)) {
  1923 + $allowed = array();
  1924 + $q = sprintf('name like "%%%s%%"', DBUtil::escapeSimple($sFilter));
  1925 +
  1926 + $aUsers = User::getList($q);
  1927 + $aGroups = Group::getList($q);
  1928 + $aRoles = Role::getList($q);
  1929 +
  1930 + $empty = true;
  1931 +
  1932 + if (!PEAR::isError($aUsers)) {
  1933 + $allowed['user'] = $aUsers;
  1934 + if (!empty($aUsers)) {
  1935 + $empty = false;
  1936 + }
  1937 + }
  1938 +
  1939 + if (!PEAR::isError($aGroups)) {
  1940 + $allowed['group'] = $aGroups;
  1941 + if (!empty($aGroups)) {
  1942 + $empty = false;
  1943 + }
  1944 + }
  1945 +
  1946 + if (!PEAR::isError($aRole)) {
  1947 + $allowed['role'] = $aRoles;
  1948 + if (!empty($aRoles)) {
  1949 + $empty = false;
  1950 + }
  1951 +
  1952 + }
  1953 +
  1954 + if ($empty) {
  1955 + $values = array('off'=>'-- No results --'); // default
  1956 + } else {
  1957 + $values = $this->descriptorToJSON($allowed);
  1958 + }
  1959 + }
  1960 +
  1961 + return $values;
  1962 + }
1699 } 1963 }
1700 1964
1701 ?> 1965 ?>
resources/js/jsonlookup.js
@@ -2,9 +2,9 @@ var _aLookupWidgets = {}; @@ -2,9 +2,9 @@ var _aLookupWidgets = {};
2 2
3 function getJSONLookupWidget(name) { 3 function getJSONLookupWidget(name) {
4 if(!isUndefinedOrNull(_aLookupWidgets[name])) { 4 if(!isUndefinedOrNull(_aLookupWidgets[name])) {
5 - return _aLookupWidgets[name]; 5 + return _aLookupWidgets[name];
6 } else { 6 } else {
7 - return false; 7 + return false;
8 } 8 }
9 } 9 }
10 10
@@ -16,260 +16,260 @@ JSONLookupWidget.prototype = { @@ -16,260 +16,260 @@ JSONLookupWidget.prototype = {
16 /* bind_add and bind_remove are functions to be called with the key:value's of selected items */ 16 /* bind_add and bind_remove are functions to be called with the key:value's of selected items */
17 17
18 'initialize' : function(name, action) { 18 'initialize' : function(name, action) {
19 - bindMethods(this); 19 + bindMethods(this);
20 20
21 - this.sName = name;  
22 - this.sAction = action; 21 + this.sName = name;
  22 + this.sAction = action;
23 23
24 -  
25 - this.oSelectAvail = $('select_' + name + '_avail');  
26 - this.oSelectAssigned = $('select_' + name + '_assigned');  
27 - this.oFilterAvail = $('filter_' + name + '_avail');  
28 - this.oFilterAssigned = $('filter_' + name + '_assigned');  
29 -  
30 - this.savedFilter = this.oFilterAvail.value;  
31 - this.savedSelector = this.oFilterAssigned.value;  
32 - this.filterTimer = null;  
33 -  
34 - this.aItemsAdded = [];  
35 - this.aItemsRemoved = [];  
36 -  
37 - connect(this.oFilterAvail, 'onkeyup', this, 'onchangeFilter');  
38 - connect(this.oFilterAssigned, 'onkeyup', this, 'onchangeSelector');  
39 - connect(name + '_add', 'onclick', this, 'onclickAdd');  
40 - connect(name + '_remove', 'onclick', this, 'onclickRemove');  
41 - connect(name + '_show_all', 'onclick', this, 'onclickShowAll');  
42 -  
43 - this.triggers = {};  
44 - this.triggers['add'] = null;  
45 - this.triggers['remove'] = null; 24 +
  25 + this.oSelectAvail = $('select_' + name + '_avail');
  26 + this.oSelectAssigned = $('select_' + name + '_assigned');
  27 + this.oFilterAvail = $('filter_' + name + '_avail');
  28 + this.oFilterAssigned = $('filter_' + name + '_assigned');
  29 +
  30 + this.savedFilter = this.oFilterAvail.value;
  31 + this.savedSelector = this.oFilterAssigned.value;
  32 + this.filterTimer = null;
  33 +
  34 + this.aItemsAdded = [];
  35 + this.aItemsRemoved = [];
  36 +
  37 + connect(this.oFilterAvail, 'onkeyup', this, 'onchangeFilter');
  38 + connect(this.oFilterAssigned, 'onkeyup', this, 'onchangeSelector');
  39 + connect(name + '_add', 'onclick', this, 'onclickAdd');
  40 + connect(name + '_remove', 'onclick', this, 'onclickRemove');
  41 + connect(name + '_show_all', 'onclick', this, 'onclickShowAll');
  42 +
  43 + this.triggers = {};
  44 + this.triggers['add'] = null;
  45 + this.triggers['remove'] = null;
46 46
47 - this.initialValuesLoaded = false;  
48 - var d = this.getValues();  
49 - d.addCallback(this.postInitialize); 47 + this.initialValuesLoaded = false;
  48 + var d = this.getValues();
  49 + d.addCallback(this.postInitialize);
50 }, 50 },
51 51
52 'addTrigger' : function(event, func) { 52 'addTrigger' : function(event, func) {
53 - this.triggers[event] = func; 53 + this.triggers[event] = func;
54 }, 54 },
55 55
56 56
57 // values handling 57 // values handling
58 58
59 'getValues' : function(all) { 59 'getValues' : function(all) {
60 - var act = this.sAction;  
61 - if(!isUndefinedOrNull(all)) {  
62 - act += '&' + queryString({'filter' : '%'});  
63 - } else if(this.savedFilter) {  
64 - act += '&' + queryString({'filter' : this.savedFilter});  
65 - } else if(!this.initialValuesLoaded) {  
66 - act += '&' + queryString({'selected' : '1'});  
67 - }  
68 -  
69 - var d = loadJSONDoc(act);  
70 - d.addErrback(this.errGetValues);  
71 - d.addCallback(checkKTError);  
72 - d.addCallback(this.saveValues);  
73 - d.addCallback(this.renderValues);  
74 - return d; 60 + var act = this.sAction;
  61 + if(!isUndefinedOrNull(all)) {
  62 + act += '&' + queryString({'filter' : '%'});
  63 + } else if(this.savedFilter) {
  64 + act += '&' + queryString({'filter' : this.savedFilter});
  65 + } else if(!this.initialValuesLoaded) {
  66 + act += '&' + queryString({'selected' : '1'});
  67 + }
  68 +
  69 + var d = loadJSONDoc(act);
  70 + d.addErrback(this.errGetValues);
  71 + d.addCallback(checkKTError);
  72 + d.addCallback(this.saveValues);
  73 + d.addCallback(this.renderValues);
  74 + return d;
75 }, 75 },
76 76
77 'errGetValues' : function(res) { 77 'errGetValues' : function(res) {
78 - alert('There was an error retrieving data. Please check connectivity and try again.');  
79 - this.oValues = {'off':'-- Error fetching values --'};  
80 - this.renderValues(); 78 + alert('There was an error retrieving data. Please check connectivity and try again.');
  79 + this.oValues = {'off':'-- Error fetching values --'};
  80 + this.renderValues();
81 }, 81 },
82 82
83 'saveValues' : function(res) { 83 'saveValues' : function(res) {
84 - this.oValues = res;  
85 - return res; 84 + this.oValues = res;
  85 + return res;
86 }, 86 },
87 87
88 'renderValues' : function() { 88 'renderValues' : function() {
89 - var aOptions = [];  
90 - var bSelFound = false;  
91 - for(var k in this.oValues) {  
92 - var found = false;  
93 - for(var i=0; i<this.oSelectAssigned.options.length; i++) {  
94 - if(this.oSelectAssigned.options[i].value == k) {  
95 - found = true; break;  
96 - }  
97 - }  
98 -  
99 - if(found) {  
100 - continue;  
101 - }  
102 -  
103 -  
104 - var aParam = {'value':k};  
105 - if(k == 'off') {  
106 - aParam['disabled'] = 'disabled';  
107 - }  
108 -  
109 - var val = this.oValues[k];  
110 - var sDisp = val;  
111 -  
112 - if(!isUndefinedOrNull(val['display'])) {  
113 - var sDisp = val['display'];  
114 - if(!isUndefinedOrNull(val['selected']) && val['selected'] === true) {  
115 - val['selected'] = undefined;  
116 - aParam['selected'] = true;  
117 - bSelFound = true;  
118 - aParam['value'] = k;  
119 - }  
120 - }  
121 - var oO = OPTION(aParam, sDisp);  
122 - aOptions.push(oO);  
123 - }  
124 -  
125 - replaceChildNodes(this.oSelectAvail, aOptions);  
126 - if(bSelFound) {  
127 - this.onclickAdd();  
128 - } 89 + var aOptions = [];
  90 + var bSelFound = false;
  91 + for(var k in this.oValues) {
  92 + var found = false;
  93 + for(var i=0; i<this.oSelectAssigned.options.length; i++) {
  94 + if(this.oSelectAssigned.options[i].value == k) {
  95 + found = true; break;
  96 + }
  97 + }
  98 +
  99 + if(found) {
  100 + continue;
  101 + }
  102 +
  103 +
  104 + var aParam = {'value':k};
  105 + if(k == 'off') {
  106 + aParam['disabled'] = 'disabled';
  107 + }
  108 +
  109 + var val = this.oValues[k];
  110 + var sDisp = val;
  111 +
  112 + if(!isUndefinedOrNull(val['display'])) {
  113 + var sDisp = val['display'];
  114 + if(!isUndefinedOrNull(val['selected']) && val['selected'] === true) {
  115 + val['selected'] = undefined;
  116 + aParam['selected'] = true;
  117 + bSelFound = true;
  118 + aParam['value'] = k;
  119 + }
  120 + }
  121 + var oO = OPTION(aParam, sDisp);
  122 + aOptions.push(oO);
  123 + }
  124 +
  125 + replaceChildNodes(this.oSelectAvail, aOptions);
  126 + if(bSelFound) {
  127 + this.onclickAdd();
  128 + }
129 }, 129 },
130 130
131 'postInitialize' : function(res) { 131 'postInitialize' : function(res) {
132 - if(!isUndefinedOrNull(this.triggers['postInitialize'])) {  
133 - this.triggers['postInitialize']();  
134 - } 132 + if(!isUndefinedOrNull(this.triggers['postInitialize'])) {
  133 + this.triggers['postInitialize']();
  134 + }
135 }, 135 },
136 - 136 +
137 137
138 'modItems' : function(type, value) { 138 'modItems' : function(type, value) {
139 - var aTarget = (type == 'add') ? 'aItemsAdded' : 'aItemsRemoved';  
140 - var aOtherTarget = (type == 'remove') ? 'aItemsAdded' : 'aItemsRemoved';  
141 -  
142 - // check against other - if other has value, remove it from other, skip next bit  
143 - var aNewOther = [];  
144 - var exists = false;  
145 - var i = 0;  
146 - for(i=0; i<this[aOtherTarget].length; i++) {  
147 - if(this[aOtherTarget][i]!=value) {  
148 - aNewOther.push(this[aOtherTarget][i]);  
149 - } else {  
150 - exists = true;  
151 - }  
152 - }  
153 - if(exists) {  
154 - this[aOtherTarget] = aNewOther;  
155 - var sHidden = this.sName + '_items_' + ((type == 'remove') ? 'added' : 'removed');  
156 - $(sHidden).value = this[aOtherTarget].join(",");  
157 - return;  
158 - }  
159 -  
160 - exists = false;  
161 - for(i=0; i<this[aTarget].length; i++) {  
162 - if(this[aTarget][i] == value) {  
163 - exists = true;  
164 - break;  
165 - }  
166 - }  
167 -  
168 - if(!exists) {  
169 - this[aTarget].push(value);  
170 - var sHidden = this.sName + '_items_' + ((type == 'add') ? 'added' : 'removed');  
171 - $(sHidden).value = this[aTarget].join(",");  
172 - }  
173 - 139 + var aTarget = (type == 'add') ? 'aItemsAdded' : 'aItemsRemoved';
  140 + var aOtherTarget = (type == 'remove') ? 'aItemsAdded' : 'aItemsRemoved';
  141 +
  142 + // check against other - if other has value, remove it from other, skip next bit
  143 + var aNewOther = [];
  144 + var exists = false;
  145 + var i = 0;
  146 + for(i=0; i<this[aOtherTarget].length; i++) {
  147 + if(this[aOtherTarget][i]!=value) {
  148 + aNewOther.push(this[aOtherTarget][i]);
  149 + } else {
  150 + exists = true;
  151 + }
  152 + }
  153 + if(exists) {
  154 + this[aOtherTarget] = aNewOther;
  155 + var sHidden = this.sName + '_items_' + ((type == 'remove') ? 'added' : 'removed');
  156 + $(sHidden).value = this[aOtherTarget].join(",");
  157 + return;
  158 + }
  159 +
  160 + exists = false;
  161 + for(i=0; i<this[aTarget].length; i++) {
  162 + if(this[aTarget][i] == value) {
  163 + exists = true;
  164 + break;
  165 + }
  166 + }
  167 +
  168 + if(!exists) {
  169 + this[aTarget].push(value);
  170 + var sHidden = this.sName + '_items_' + ((type == 'add') ? 'added' : 'removed');
  171 + $(sHidden).value = this[aTarget].join(",");
  172 + }
  173 +
174 }, 174 },
175 -  
176 - 175 +
  176 +
177 // signals handling 177 // signals handling
178 178
179 - 'onchangeFilter' : function(e) {  
180 - if(this.savedFilter != this.oFilterAvail.value) {  
181 - this.savedFilter = this.oFilterAvail.value;  
182 - if(!isUndefinedOrNull(this.filterTimer)) {  
183 - this.filterTimer.canceller();  
184 - }  
185 - this.filterTimer = callLater(0.2, this.getValues);  
186 - }  
187 - return true; 179 + 'onchangeFilter' : function(e) {
  180 + if(this.savedFilter != this.oFilterAvail.value) {
  181 + this.savedFilter = this.oFilterAvail.value;
  182 + if(!isUndefinedOrNull(this.filterTimer)) {
  183 + this.filterTimer.canceller();
  184 + }
  185 + this.filterTimer = callLater(0.2, this.getValues);
  186 + }
  187 + return true;
188 }, 188 },
189 189
190 'onchangeSelector' : function(e) { 190 'onchangeSelector' : function(e) {
191 - if(this.savedSelector != this.oFilterAssigned.value) {  
192 - this.savedSelector = this.oFilterAssigned.value;  
193 - forEach(this.oSelectAssigned.options, bind(function(o) {  
194 - if(!this.savedSelector.length) {  
195 - o.selected = false;  
196 - } else {  
197 - if(o.innerHTML.toLowerCase().search(this.savedSelector) != -1) {  
198 - o.selected = true;  
199 - } else {  
200 - o.selected = false;  
201 - }  
202 - }  
203 - }, this));  
204 - } 191 + if(this.savedSelector != this.oFilterAssigned.value) {
  192 + this.savedSelector = this.oFilterAssigned.value;
  193 + forEach(this.oSelectAssigned.options, bind(function(o) {
  194 + if(!this.savedSelector.length) {
  195 + o.selected = false;
  196 + } else {
  197 + if(o.innerHTML.toLowerCase().search(this.savedSelector) != -1) {
  198 + o.selected = true;
  199 + } else {
  200 + o.selected = false;
  201 + }
  202 + }
  203 + }, this));
  204 + }
205 }, 205 },
206 206
207 '_moveOptions' : function(dir) { 207 '_moveOptions' : function(dir) {
208 }, 208 },
209 209
210 'onclickAdd' : function(e) { 210 'onclickAdd' : function(e) {
211 - var aCurOptions = extend([], this.oSelectAssigned.options);  
212 - forEach(this.oSelectAvail.options, bind(  
213 - function(o) {  
214 - try {  
215 - if(o.value == 'off') return;  
216 - var a = o.selected;  
217 - if(a == 'selected' || a === true) {  
218 - this.modItems('add', o.value);  
219 - try {  
220 - o.selected = false;  
221 - } catch(e) {  
222 - o.setAttribute('selected', false);  
223 - }  
224 - aCurOptions.push(o);  
225 -  
226 - if(!isUndefinedOrNull(this.triggers['add'])) {  
227 - this.triggers['add'](this.oValues[o.value]);  
228 - }  
229 - }  
230 - } catch(e) {  
231 - log('exception');  
232 - // forEach(keys(e), function(k) { log(k,':', e[k]); });  
233 - }  
234 - }, this));  
235 -  
236 - aCurOptions.sort(keyComparator('innerHTML'));  
237 - replaceChildNodes(this.oSelectAssigned, aCurOptions); 211 + var aCurOptions = extend([], this.oSelectAssigned.options);
  212 + forEach(this.oSelectAvail.options, bind(
  213 + function(o) {
  214 + try {
  215 + if(o.value == 'off') return;
  216 + var a = o.selected;
  217 + if(a == 'selected' || a === true) {
  218 + this.modItems('add', o.value);
  219 + try {
  220 + o.selected = false;
  221 + } catch(e) {
  222 + o.setAttribute('selected', false);
  223 + }
  224 + aCurOptions.push(o);
  225 +
  226 + if(!isUndefinedOrNull(this.triggers['add'])) {
  227 + this.triggers['add'](this.oValues[o.value]);
  228 + }
  229 + }
  230 + } catch(e) {
  231 + log('exception');
  232 + // forEach(keys(e), function(k) { log(k,':', e[k]); });
  233 + }
  234 + }, this));
  235 +
  236 + aCurOptions.sort(keyComparator('innerHTML'));
  237 + replaceChildNodes(this.oSelectAssigned, aCurOptions);
238 238
239 }, 239 },
240 240
241 'onclickRemove' : function(e) { 241 'onclickRemove' : function(e) {
242 - var aOptions = [];  
243 - forEach(this.oSelectAssigned.options, bind(function(o) {  
244 - if(o.selected == 'selected' || o.selected === true) {  
245 - this.modItems('remove', o.value);  
246 - if(!isUndefinedOrNull(this.triggers['remove'])) {  
247 - var obj = { 'type' : (o.value.substring(0,1) == 'g') ? 'group' : 'role',  
248 - 'id' : o.value.substring(1) };  
249 - this.triggers['remove'](obj);  
250 - }  
251 - } else {  
252 - aOptions.push(o);  
253 - }  
254 - }, this));  
255 - replaceChildNodes(this.oSelectAssigned, aOptions);  
256 - this.renderValues(); 242 + var aOptions = [];
  243 + forEach(this.oSelectAssigned.options, bind(function(o) {
  244 + if(o.selected == 'selected' || o.selected === true) {
  245 + this.modItems('remove', o.value);
  246 + if(!isUndefinedOrNull(this.triggers['remove'])) {
  247 + var obj = { 'type' : (o.value.substring(0,1) == 'g') ? 'group' : 'role',
  248 + 'id' : o.value.substring(1) };
  249 + this.triggers['remove'](obj);
  250 + }
  251 + } else {
  252 + aOptions.push(o);
  253 + }
  254 + }, this));
  255 + replaceChildNodes(this.oSelectAssigned, aOptions);
  256 + this.renderValues();
257 }, 257 },
258 258
259 'onclickShowAll' : function(e) { 259 'onclickShowAll' : function(e) {
260 - this.oFilterAvail.value = '';  
261 - this.savedFilter = '';  
262 - this.getValues(true);  
263 - e.stop(); 260 + this.oFilterAvail.value = '';
  261 + this.savedFilter = '';
  262 + this.getValues(true);
  263 + e.stop();
264 } 264 }
265 } 265 }
266 266
267 function initJSONLookup(name, action) { 267 function initJSONLookup(name, action) {
268 return function() { 268 return function() {
269 - _aLookupWidgets[name] = new JSONLookupWidget();  
270 - _aLookupWidgets[name].initialize(name, action); 269 + _aLookupWidgets[name] = new JSONLookupWidget();
  270 + _aLookupWidgets[name].initialize(name, action);
271 } 271 }
272 } 272 }
273 273
274 274
275 -  
276 \ No newline at end of file 275 \ No newline at end of file
  276 +
templates/ktcore/forms/widgets/descriptor.smarty 0 → 100644
  1 +
  2 +<table>
  3 +
  4 +<thead>
  5 + <tr>
  6 + <td style="width:45%"><label for="select_{$short_name}_avail">{i18n}Available{/i18n} {$user_name}</label></td>
  7 + <td style="width:10%">&nbsp;</td>
  8 + <td style="width:45%"><label for="select_{$short_name}_assigned">{i18n}Assigned{/i18n} {$user_name}</label></td>
  9 + </tr>
  10 +</thead>
  11 +
  12 +<tbody>
  13 + <tr>
  14 + <td style="vertical-align: top">
  15 +
  16 + <select name="select_{$short_name}_avail" id="select_{$short_name}_avail" {if $options.multi}multiple="true"{/if} {if $options.size}size="{$options.size}"{/if}>
  17 + {foreach item=lookup key=lookup_key from=$options.vocab}
  18 + <option value="{$lookup_key}" {if ($value == $lookup_key)}selected="selected"{/if}>{$lookup}</option>
  19 + {/foreach}
  20 + </select>
  21 +
  22 + <div><label for="filter_{$short_name}_avail">{i18n}Filter{/i18n}</label><input type="text" id="filter_{$short_name}_avail" /><br/><a href="#" id="{$short_name}_show_all">{i18n}Show All{/i18n}</a></div>
  23 + </td>
  24 +
  25 + <td>
  26 +
  27 + <input type="button" id="{$short_name}_add" value="&raquo;" />
  28 + <br /><br/>
  29 + <input type="button" id="{$short_name}_remove" value="&laquo;" />
  30 +
  31 + </td>
  32 +
  33 + <td style="vertical-align: top">
  34 +
  35 + <select name="{$name}[final]" id="select_{$short_name}_assigned" {if $options.multi}multiple="true"{/if} {if $options.size}size="{$options.size}"{/if}>
  36 + {foreach item=lookup key=lookup_key from=$value}
  37 + <option value="{$lookup_key}" {if ($value == $lookup_key)}selected="selected"{/if}>{$lookup}</option>
  38 + {/foreach}
  39 + </select>
  40 + <div><label for="filter_{$short_name}_assigned">Filter</label><input type="text" id="filter_{$short_name}_assigned" /></div>
  41 + </td>
  42 + </tr>
  43 +</tbody>
  44 +</table>
  45 +
  46 + <input name="{$name}[added]" id="{$short_name}_items_added" type="hidden" />
  47 + <input name="{$name}[removed]" id="{$short_name}_items_removed" type="hidden" />
templates/ktcore/workflow/admin/effects_overview.smarty
@@ -8,5 +8,5 @@ with the role &quot;Reviewer&quot; on that document are informed.&lt;/p&gt; @@ -8,5 +8,5 @@ with the role &quot;Reviewer&quot; on that document are informed.&lt;/p&gt;
8 8
9 <ul class="descriptiveText"> 9 <ul class="descriptiveText">
10 <li><a href="{addQS context=$context}action=transitionactions{/addQS}">Transition Effects</a></li> 10 <li><a href="{addQS context=$context}action=transitionactions{/addQS}">Transition Effects</a></li>
11 - <li><a href="{addQS context=$context}action=statenotifications{/addQS}">Notifications</a></li> 11 + <li><a href="{addQS context=$context}action=managenotifications{/addQS}">Notifications</a></li>
12 </ul> 12 </ul>