Commit 38c18432432a0ea39d16fd110d481e31c14ef9ef

Authored by bshuttle
1 parent 33b4625b

- massively improve the workflow editing / management system

- fix html-error in listFieldsets
- make the titlebar slightly less verbose to accommodate smaller screens better.


git-svn-id: https://kt-dms.svn.sourceforge.net/svnroot/kt-dms/trunk@4699 c91229c3-7414-0410-bfa2-8a42b809f60b
kthelp/.htaccess 0 โ†’ 100644
  1 +Order deny,allow
  2 +Deny from all
  3 +
kthelp/ktcore/EN/admin/workflow/overview.html 0 โ†’ 100644
  1 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  2 +<html>
  3 +<head>
  4 +
  5 +
  6 + <title>Workflow Overview</title>
  7 +</head>
  8 +
  9 +<body>
  10 +
  11 +<h2>Workflow Overview</h2>
  12 +
  13 +<p>Workflow allows you to assign a series of steps to the document creation and
  14 +management process. For example, a "News" workflow might have documents which
  15 +go from <strong>Research</strong> to <strong>Draft</strong> to <strong>Under Review</strong>
  16 +to <strong>Published</strong>,
  17 +with different people participating in the document's
  18 +lifecycle at each stage. &nbsp;Naturally, not all documents have the
  19 +same needs in terms of workflow: &nbsp;Invoices (which must be <span style="font-weight: bold;">drawn up</span>, <span style="font-weight: bold;">maile</span>d, and then marked as <span style="font-weight: bold;">paid</span>) are very different from Marketing documents.&nbsp;</p>
  20 +<p>To facilitate this, KnowledgeTree&trade; allows the Administrator to
  21 +define a number of different workflows, each of which can be applied to
  22 +different documents as their organisation requires.</p>
  23 +
  24 +</body>
  25 +</html>
lib/browse/BrowseColumns.inc.php
@@ -72,7 +72,7 @@ class TitleColumn extends BrowseColumn { @@ -72,7 +72,7 @@ class TitleColumn extends BrowseColumn {
72 function renderFolderLink($aDataRow) { 72 function renderFolderLink($aDataRow) {
73 $outStr = '<a href="' . $this->buildFolderLink($aDataRow) . '">'; 73 $outStr = '<a href="' . $this->buildFolderLink($aDataRow) . '">';
74 $outStr .= $aDataRow["folder"]->getName(); 74 $outStr .= $aDataRow["folder"]->getName();
75 - $outStr .= '</a>'; 75 + $outStr .= '</a> ';
76 return $outStr; 76 return $outStr;
77 } 77 }
78 78
plugins/ktcore/KTDocumentActions.php
@@ -585,7 +585,7 @@ class KTDocumentWorkflowAction extends KTDocumentAction { @@ -585,7 +585,7 @@ class KTDocumentWorkflowAction extends KTDocumentAction {
585 585
586 $oUser =& User::get($_SESSION['userID']); 586 $oUser =& User::get($_SESSION['userID']);
587 $aTransitions = KTWorkflowUtil::getTransitionsForDocumentUser($oDocument, $oUser); 587 $aTransitions = KTWorkflowUtil::getTransitionsForDocumentUser($oDocument, $oUser);
588 - $aWorkflows = KTWorkflow::getList(); 588 + $aWorkflows = KTWorkflow::getList('start_state_id IS NOT NULL');
589 589
590 $fieldErrors = null; 590 $fieldErrors = null;
591 591
plugins/ktcore/admin/workflows.php
@@ -18,16 +18,232 @@ require_once(KT_LIB_DIR . &#39;/search/savedsearch.inc.php&#39;); @@ -18,16 +18,232 @@ require_once(KT_LIB_DIR . &#39;/search/savedsearch.inc.php&#39;);
18 18
19 require_once(KT_LIB_DIR . '/actions/documentaction.inc.php'); 19 require_once(KT_LIB_DIR . '/actions/documentaction.inc.php');
20 20
  21 +require_once(KT_LIB_DIR . '/widgets/portlet.inc.php');
  22 +
  23 +class WorkflowNavigationPortlet extends KTPortlet {
  24 + var $oWorkflow;
  25 +
  26 + function WorkflowNavigationPortlet($sTitle, $oWorkflow = null) {
  27 + $this->oWorkflow = $oWorkflow;
  28 + parent::KTPortlet($sTitle);
  29 + }
  30 +
  31 + function render() {
  32 + if (is_null($this->oWorkflow)) { return _('No Workflow Selected.'); }
  33 +
  34 + $aAdminPages = array();
  35 + $aAdminPages[] = array('name' => _('Overview'), 'url' => $_SERVER['PHP_SELF'] . '?action=editWorkflow&fWorkflowId=' . $this->oWorkflow->getId());
  36 + $aAdminPages[] = array('name' => _('States'), 'url' => $_SERVER['PHP_SELF'] . '?action=manageStates&fWorkflowId=' . $this->oWorkflow->getId());
  37 + $aAdminPages[] = array('name' => _('Transitions'), 'url' => $_SERVER['PHP_SELF'] . '?action=manageTransitions&fWorkflowId=' . $this->oWorkflow->getId());
  38 + $aAdminPages[] = array('name' => _('Actions'), 'url' => $_SERVER['PHP_SELF'] . '?action=manageActions&fWorkflowId=' . $this->oWorkflow->getId());
  39 +
  40 +
  41 + $oTemplating = new KTTemplating;
  42 + $oTemplate = $oTemplating->loadTemplate("ktcore/workflow/admin_portlet");
  43 + $aTemplateData = array(
  44 + "context" => $this,
  45 + "aAdminPages" => $aAdminPages,
  46 + );
  47 +
  48 + return $oTemplate->render($aTemplateData);
  49 + }
  50 +}
  51 +
21 class KTWorkflowDispatcher extends KTAdminDispatcher { 52 class KTWorkflowDispatcher extends KTAdminDispatcher {
22 var $bAutomaticTransaction = true; 53 var $bAutomaticTransaction = true;
  54 + var $sHelpPage = 'ktcore/admin/workflow/overview.html';
  55 + var $aWorkflowInfo;
  56 + var $oWorkflow;
23 57
24 - // {{{ WORKFLOW HANDLING  
25 - // {{{ do_main  
26 - function do_main () { 58 + function check() {
27 $this->aBreadcrumbs[] = array( 59 $this->aBreadcrumbs[] = array(
28 'url' => $_SERVER['PHP_SELF'], 60 'url' => $_SERVER['PHP_SELF'],
29 'name' => _('Workflows'), 61 'name' => _('Workflows'),
30 ); 62 );
  63 + $this->oWorkflow =& KTWorkflow::get($_REQUEST['fWorkflowId']);
  64 + if (!PEAR::isError($this->oWorkflow)) {
  65 + $this->aBreadcrumbs[] = array(
  66 + 'url' => $_SERVER['PHP_SELF'],
  67 + 'query' => 'action=editWorkflow&fWorkflowId=' . $this->oWorkflow->getId(),
  68 + 'name' => $this->oWorkflow->getName(),
  69 + );
  70 + $this->oPage->addPortlet(new WorkflowNavigationPortlet(_('Workflow'), $this->oWorkflow));
  71 + }
  72 +
  73 + return true;
  74 + }
  75 +
  76 + // helper function to construct the set of workflow information
  77 + function buildWorkflowInfo($oWorkflow) {
  78 + if ($this->aWorkflowInfo != null) { return $this->aWorkflowInfo; }
  79 +
  80 + $aInfo = array();
  81 + $aInfo['workflow'] = $oWorkflow;
  82 +
  83 + // roles
  84 + $aRoles = Role::getList();
  85 + $aKeyRoles = array();
  86 + foreach ($aRoles as $oRole) { $aKeyRoles[$oRole->getId()] = $oRole; }
  87 + $aInfo['roles'] = $aKeyRoles;
  88 +
  89 + // groups
  90 + $aGroups = Group::getList();
  91 + $aKeyGroups = array();
  92 + foreach ($aGroups as $oGroup) { $aKeyGroups[$oGroup->getId()] = $oGroup; }
  93 + $aInfo['groups'] = $aKeyGroups;
  94 +
  95 + // states.
  96 + $aStates = KTWorkflowState::getByWorkflow($oWorkflow);
  97 + $aKeyStates = array();
  98 + foreach ($aStates as $oState) { $aKeyStates[$oState->getId()] = $oState; }
  99 + $aInfo['states'] = $aKeyStates;
  100 +
  101 + // transitions
  102 + $aTransitions = KTWorkflowTransition::getByWorkflow($oWorkflow);
  103 + $aKeyTransitions = array();
  104 + foreach ($aTransitions as $oTransition) { $aKeyTransitions[$oTransition->getId()] = $oTransition; }
  105 + $aInfo['transitions'] = $aKeyTransitions;
  106 +
  107 + // permissions
  108 + $aPermissions = KTPermission::getList();
  109 + $aKeyPermissions = array();
  110 + foreach ($aPermissions as $oPermission) { $aKeyPermissions[$oPermission->getId()] = $oPermission; }
  111 + $aInfo['permissions'] = $aKeyPermissions;
  112 +
  113 + // actions
  114 + $aInfo['actions'] = KTDocumentActionUtil::getAllDocumentActions();
  115 + $aKeyActions = array();
  116 + foreach ($aInfo['actions'] as $oAction) { $aKeyActions[$oAction->getName()] = $oAction; }
  117 + $aInfo['actions_by_name'] = $aKeyActions;
  118 +
  119 + $aInfo['controlled_actions'] = KTWorkflowUtil::getControlledActionsForWorkflow($oWorkflow);
  120 +
  121 + /*
  122 + * now we need to do the crossmappings.
  123 + */
  124 +
  125 + $aActionsByState = array();
  126 + foreach ($aInfo['states'] as $oState) {
  127 + $aActionsByState[$oState->getId()] = KTWorkflowUtil::getEnabledActionsForState($oState);;
  128 + }
  129 + $aInfo['actions_by_state'] = $aActionsByState;
  130 +
  131 + // FIXME handle notified users and groups
  132 + $aTransitionsFromState = array();
  133 + foreach ($aInfo['states'] as $oState) {
  134 + $aTransitionsFromState[$oState->getId()] = KTWorkflowUtil::getTransitionsFrom($oState);
  135 + }
  136 + $aInfo['transitions_from_state'] = $aTransitionsFromState;
  137 +
  138 + $aTransitionsToState = array();
  139 + foreach ($aInfo['states'] as $oState) {
  140 + $aTransitionsToState[$oState->getId()] = KTWorkflowTransition::getByTargetState($oState);
  141 + }
  142 + $aInfo['transitions_to_state'] = $aTransitionsToState;
  143 +
  144 + $this->aWorkflowInfo = $aInfo;
  145 +
  146 + return $aInfo;
  147 + }
  148 +
  149 +
  150 + function getActionStringForState($oState) {
  151 + $aInfo = $this->aWorkflowInfo;
  152 +
  153 + // no controlled actions => all available
  154 + if (empty($aInfo['controlled_actions'])) { return _('All actions available.'); }
  155 +
  156 +
  157 + $aAlways = array();
  158 + foreach ($aInfo['actions'] as $iActionId => $aAction) {
  159 + if (!array_key_exists($iActionId, $aInfo['controlled_actions'])) {
  160 + $aAlways[$iActionId] = $aAction;
  161 + }
  162 + }
  163 +
  164 + $aNamedActions = array();
  165 + foreach ($aInfo['actions_by_state'][$oState->getId()] as $sName) {
  166 + $aNamedActions[] = $aInfo['actions_by_name'][$sName];
  167 + }
  168 +
  169 + $aThese = array_merge($aAlways, $aNamedActions);
  170 + // some controlled. we need to be careful here: list actions that _are always_ available
  171 + if (empty($aThese)) { return _('No actions available.'); }
  172 +
  173 + // else
  174 + $aActions = array();
  175 + foreach ($aThese as $oAction) { $aActions[] = $oAction->getDisplayName(); }
  176 + return implode(', ', $aActions);
  177 + }
  178 +
  179 + function getTransitionToStringForState($oState) {
  180 + $aInfo = $this->aWorkflowInfo;
  181 + //var_dump($aInfo['transitions_to_state'][$oState->getId()]);
  182 + if (($aInfo['workflow']->getStartStateId() != $oState->getId()) && (empty($aInfo['transitions_to_state'][$oState->getId()]))) {
  183 + return '<strong>' . _('This state is unreachable.') . '</strong>';
  184 + }
  185 +
  186 +
  187 + if ($aInfo['workflow']->getStartStateId() == $oState->getId() && (empty($aInfo['transitions_to_state'][$oState->getId()]))) {
  188 + return '<strong>' . _('Documents start in this state') . '</strong>';
  189 + }
  190 + $aT = array();
  191 + if ($aInfo['workflow']->getStartStateId() == $oState->getId()) {
  192 + $aT[] = '<strong>' . _('Documents start in this state') . '</strong>';
  193 + }
  194 +
  195 + foreach ($aInfo['transitions_to_state'][$oState->getId()] as $aTransition) {
  196 + $aT[] = sprintf('<a href="%s?action=editTransition&fWorkflowId=%d&fTransitionId=%d">%s</a>', $_SERVER['PHP_SELF'], $aInfo['workflow']->getId(), $aTransition->getId() ,$aTransition->getName());
  197 + }
  198 +
  199 + return implode(', ',$aT);
  200 + }
  201 +
  202 + function getNotificationStringForState($oState) {
  203 + return _('No roles and groups notified.');
  204 + }
  205 +
  206 + function transitionAvailable($oTransition, $oState) {
  207 + $aInfo = $this->aWorkflowInfo;
  208 +
  209 + $val = false;
  210 + foreach ($aInfo['transitions_from_state'][$oState->getId()] as $oT) {
  211 + if ($oTransition->getId() == $oT->getId()) { $val = true; }
  212 + }
  213 +
  214 + return $val;
  215 + }
  216 +
  217 + function actionAvailable($oAction, $oState) {
  218 + $aInfo = $this->aWorkflowInfo;
  219 +
  220 + $val = false;
  221 +
  222 + foreach ($aInfo['actions_by_state'][$oState->getId()] as $oA) {
  223 +
  224 + if ($oAction->getName() == $oA) { $val = true; }
  225 + }
  226 +
  227 + return $val;
  228 + }
  229 +
  230 + function getTransitionFromStringForState($oState) {
  231 + $aInfo = $this->aWorkflowInfo;
  232 +
  233 + if (empty($aInfo['transitions_from_state'][$oState->getId()])) {
  234 + return '<strong>' . _('No transitions available') . '</strong>';
  235 + }
  236 +
  237 + $aT = array();
  238 + foreach ($aInfo['transitions_from_state'][$oState->getId()] as $aTransition) {
  239 + $aT[] = sprintf('<a href="%s?action=editTransition&fWorkflowId=%d&fTransitionId=%d">%s</a>', $_SERVER['PHP_SELF'], $aInfo['workflow']->getId(), $aTransition->getId() ,$aTransition->getName());
  240 + }
  241 + return implode(', ', $aT);
  242 + }
  243 +
  244 + // {{{ WORKFLOW HANDLING
  245 + // {{{ do_main
  246 + function do_main () {
31 247
32 $add_fields = array(); 248 $add_fields = array();
33 $add_fields[] = new KTStringWidget(_('Name'),_('A human-readable name for the workflow.'), 'fName', null, $this->oPage, true); 249 $add_fields[] = new KTStringWidget(_('Name'),_('A human-readable name for the workflow.'), 'fName', null, $this->oPage, true);
@@ -42,69 +258,57 @@ class KTWorkflowDispatcher extends KTAdminDispatcher { @@ -42,69 +258,57 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
42 return $oTemplate; 258 return $oTemplate;
43 } 259 }
44 // }}} 260 // }}}
45 - 261 +
46 // {{{ do_editWorkflow 262 // {{{ do_editWorkflow
47 function do_editWorkflow() { 263 function do_editWorkflow() {
48 264
49 $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/editWorkflow'); 265 $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/editWorkflow');
50 $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']); 266 $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
51 267
52 - $aStates = KTWorkflowState::getByWorkflow($oWorkflow);  
53 - $aPermissions = KTPermission::getList(); 268 +
  269 +
  270 + $aInfo = $this->buildWorkflowInfo($oWorkflow);
  271 +
  272 + $aPermissions = $aInfo['permissions'];
  273 + $aStates = $aInfo['states'];
54 274
55 $edit_fields = array(); 275 $edit_fields = array();
56 $edit_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the workflow.'), 'fName', $oWorkflow->getName(), $this->oPage, true); 276 $edit_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the workflow.'), 'fName', $oWorkflow->getName(), $this->oPage, true);
57 $aOptions = array(); 277 $aOptions = array();
58 $vocab = array(); 278 $vocab = array();
59 - $vocab[0] = 'None'; 279 + $vocab[0] = 'None - documents cannot use this workflow.';
60 foreach($aStates as $state) { 280 foreach($aStates as $state) {
61 $vocab[$state->getId()] = $state->getName(); 281 $vocab[$state->getId()] = $state->getName();
62 } 282 }
63 - $aOptions['vocab'] = $vocab;  
64 - $edit_fields[] = new KTLookupWidget(_('Starting State'), _('When a document has this workflow applied to it, to which state should it initially be set'), 'fStartStateId', $oWorkflow->getStartStateId(), $this->oPage, false, null, null, $aOptions); 283 + $aOptions['vocab'] = $vocab;
  284 + $edit_fields[] = new KTLookupWidget(_('Starting State'), _('When a document has this workflow applied to it, to which state should it initially be set. <strong>Note that workflows without a starting state cannot be applied to documents.</strong>'), 'fStartStateId', $oWorkflow->getStartStateId(), $this->oPage, false, null, null, $aOptions);
  285 + if (is_null($oWorkflow->getStartStateId())) {
  286 + $this->oPage->addInfo(_('This workflow is currently disabled. To enable it, please assign a starting state in the "Edit workflow properties" box.'));
  287 + }
65 288
  289 + /*
66 $add_state_fields = array(); 290 $add_state_fields = array();
67 $add_state_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the state.'), 'fName', null, $this->oPage, true); 291 $add_state_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the state.'), 'fName', null, $this->oPage, true);
68 292
69 293
70 - $add_transition_fields = array();  
71 - $add_transition_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the transition.'), 'fName', null, $this->oPage, true);  
72 - $aOptions = array();  
73 - $vocab = array();  
74 - foreach($aStates as $state) {  
75 - $vocab[$state->getId()] = $state->getName();  
76 - }  
77 - $aOptions['vocab'] = $vocab;  
78 - $add_transition_fields[] = new KTLookupWidget(_('Destination State'), _('Once this transition is complete, which state should the document be in?'), 'fTargetStateId', $oWorkflow->getStartStateId(), $this->oPage, true, null, null, $aOptions);  
79 - $aOptions = array();  
80 - $vocab = array();  
81 - foreach($aPermissions as $permission) {  
82 - $vocab[$permission->getId()] = $permission->getHumanName();  
83 - }  
84 - $aOptions['vocab'] = $vocab;  
85 - $add_transition_fields[] = new KTLookupWidget(_('Guard Permission.'), _('Which permission must the user have in order to follow this transition?'), 'fPermissionId', $oWorkflow->getStartStateId(), $this->oPage, true, null, null, $aOptions); 294 + */
  295 +
86 296
87 - $this->aBreadcrumbs[] = array(  
88 - 'url' => $_SERVER['PHP_SELF'],  
89 - 'name' => _('Workflows'),  
90 - );  
91 - $this->aBreadcrumbs[] = array(  
92 - 'url' => $_SERVER['PHP_SELF'],  
93 - 'query' => 'action=editWorkflow&fWorkflowId=' . $oWorkflow->getId(),  
94 - 'name' => $oWorkflow->getName(),  
95 - );  
96 $oTemplate->setData(array( 297 $oTemplate->setData(array(
  298 + 'context' => $this,
97 'oWorkflow' => $oWorkflow, 299 'oWorkflow' => $oWorkflow,
  300 +
98 'aStates' => $aStates, 301 'aStates' => $aStates,
99 - 'aTransitions' => KTWorkflowTransition::getByWorkflow($oWorkflow), 302 + 'aTransitions' => $aInfo['transitions'],
100 'aPermissions' => $aPermissions, 303 'aPermissions' => $aPermissions,
101 - 'aActions' => KTDocumentActionUtil::getAllDocumentActions(),  
102 - 'aActionsSelected' => KTWorkflowUtil::getControlledActionsForWorkflow($oWorkflow), 304 + 'aActions' => $aInfo['actions'],
  305 + 'aActionsSelected' => $aInfo['controlled_actions'],
  306 +
  307 + // info
  308 + 'workflow_info' => $aInfo,
103 309
104 - // fields 310 + // subform
105 'edit_fields' => $edit_fields, 311 'edit_fields' => $edit_fields,
106 - 'add_state_fields' => $add_state_fields,  
107 - 'add_transition_fields' => $add_transition_fields,  
108 )); 312 ));
109 return $oTemplate; 313 return $oTemplate;
110 } 314 }
@@ -168,6 +372,137 @@ class KTWorkflowDispatcher extends KTAdminDispatcher { @@ -168,6 +372,137 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
168 } 372 }
169 // }}} 373 // }}}
170 374
  375 + function do_manageActions() {
  376 + $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/manageActions');
  377 + $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
  378 +
  379 + $aInfo = $this->buildWorkflowInfo($oWorkflow);
  380 +
  381 + $oTemplate->setData(array(
  382 + 'context' => $this,
  383 + 'oWorkflow' => $oWorkflow,
  384 +
  385 + 'aActions' => $aInfo['actions'],
  386 + 'aActionsSelected' => $aInfo['controlled_actions'],
  387 +
  388 + // info
  389 + 'workflow_info' => $aInfo,
  390 + ));
  391 + return $oTemplate;
  392 +
  393 + }
  394 +
  395 + function do_manageStates() {
  396 + $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/manageStates');
  397 + $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
  398 +
  399 + $aInfo = $this->buildWorkflowInfo($oWorkflow);
  400 +
  401 + $add_fields = array();
  402 + $add_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the state.'), 'fName', null, $this->oPage, true);
  403 +
  404 +
  405 +
  406 + $oTemplate->setData(array(
  407 + 'context' => $this,
  408 + 'oWorkflow' => $oWorkflow,
  409 +
  410 + // info
  411 + 'workflow_info' => $aInfo,
  412 +
  413 + // subform
  414 + 'add_fields' => $add_fields,
  415 + ));
  416 + return $oTemplate;
  417 + }
  418 +
  419 + function do_manageTransitions() {
  420 + $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/manageTransitions');
  421 + $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
  422 +
  423 + $aInfo = $this->buildWorkflowInfo($oWorkflow);
  424 +
  425 + $add_transition_fields = array();
  426 + $add_transition_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the transition.'), 'fName', null, $this->oPage, true);
  427 + $aOptions = array();
  428 + $vocab = array();
  429 + foreach($aInfo['states'] as $state) {
  430 + $vocab[$state->getId()] = $state->getName();
  431 + }
  432 + $aOptions['vocab'] = $vocab;
  433 + $add_transition_fields[] = new KTLookupWidget(_('Destination State'), _('Once this transition is complete, which state should the document be in?'), 'fTargetStateId', $oWorkflow->getStartStateId(), $this->oPage, true, null, null, $aOptions);
  434 + $aOptions = array();
  435 + $vocab = array();
  436 + foreach($aInfo['permissions'] as $permission) {
  437 + $vocab[$permission->getId()] = $permission->getHumanName();
  438 + }
  439 + $aOptions['vocab'] = $vocab;
  440 + $add_transition_fields[] = new KTLookupWidget(_('Guard Permission.'), _('Which permission must the user have in order to follow this transition?'), 'fPermissionId', $oWorkflow->getStartStateId(), $this->oPage, true, null, null, $aOptions);
  441 +
  442 + $oTemplate->setData(array(
  443 + 'context' => $this,
  444 + 'oWorkflow' => $oWorkflow,
  445 +
  446 + // info
  447 + 'workflow_info' => $aInfo,
  448 +
  449 + // subform
  450 + 'add_fields' => $add_transition_fields,
  451 + ));
  452 + return $oTemplate;
  453 + }
  454 +
  455 + function do_setTransitionAvailability() {
  456 + $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/editWorkflow');
  457 + $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
  458 +
  459 + $transitionMap = (array) KTUtil::arrayGet($_REQUEST, 'fTransitionAvailability');
  460 +
  461 + $aInfo = $this->buildWorkflowInfo($oWorkflow);
  462 +
  463 + $this->startTransaction();
  464 + foreach ($aInfo['states'] as $oState) {
  465 +
  466 + $a = (array) $transitionMap[$oState->getId()];
  467 + $transitions = array();
  468 + foreach ($a as $tid => $on) { $transitions[] = $tid; }
  469 +
  470 + $res = KTWorkflowUtil::saveTransitionsFrom($oState, $transitions);
  471 + if (PEAR::isError($res)) {
  472 + $this->errorRedirectTo('manageTransitions', _('Error updating transitions:') . $res->getMessage(), sprintf('fWorkflowId=%d', $oWorkflow->getId()));
  473 + }
  474 + }
  475 + $this->commitTransaction();
  476 +
  477 + $this->successRedirectTo('manageTransitions', _('Availability updated.'), sprintf('fWorkflowId=%d', $oWorkflow->getId()));
  478 + }
  479 +
  480 +
  481 + function do_updateActionAvailability() {
  482 + $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
  483 +
  484 + $actionMap = (array) KTUtil::arrayGet($_REQUEST, 'fAvailableActions');
  485 +
  486 + $aInfo = $this->buildWorkflowInfo($oWorkflow);
  487 +
  488 + $this->startTransaction();
  489 + foreach ($aInfo['states'] as $oState) {
  490 +
  491 + $a = (array) $actionMap[$oState->getId()];
  492 + $actions = array_keys($a);
  493 +
  494 +
  495 +
  496 + $res = KTWorkflowUtil::setEnabledActionsForState($oState, $actions);
  497 + if (PEAR::isError($res)) {
  498 + $this->errorRedirectTo('manageActions', _('Error updating actions:') . $res->getMessage(), sprintf('fWorkflowId=%d', $oWorkflow->getId()));
  499 + }
  500 + }
  501 + $this->commitTransaction();
  502 +
  503 + $this->successRedirectTo('manageActions', _('Action availability updated.'), sprintf('fWorkflowId=%d', $oWorkflow->getId()));
  504 + }
  505 +
171 // {{{ do_setWorkflowActions 506 // {{{ do_setWorkflowActions
172 function do_setWorkflowActions() { 507 function do_setWorkflowActions() {
173 $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']); 508 $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
@@ -247,9 +582,14 @@ class KTWorkflowDispatcher extends KTAdminDispatcher { @@ -247,9 +582,14 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
247 'query' => 'action=editWorkflow&fWorkflowId=' . $oWorkflow->getId(), 582 'query' => 'action=editWorkflow&fWorkflowId=' . $oWorkflow->getId(),
248 'name' => $oWorkflow->getName(), 583 'name' => $oWorkflow->getName(),
249 ); 584 );
250 - $this->oPage->setBreadcrumbDetails(_('state') . ': ' . $oState->getName()); 585 + $this->oPage->setBreadcrumbDetails(_('State') . ': ' . $oState->getName());
251 586
252 $aInformed = KTWorkflowUtil::getInformedForState($oState); 587 $aInformed = KTWorkflowUtil::getInformedForState($oState);
  588 +
  589 +
  590 + $editForm = array();
  591 + $editForm[] = new KTStringWidget(_('Name'), _('A human-readable name for this state. This is shown on the "Browse" page, as well as on the user\'s workflow page.'), 'fName', $oState->getName(), $this->oPage, true);
  592 +
253 $oTemplate->setData(array( 593 $oTemplate->setData(array(
254 'oWorkflow' => $oWorkflow, 594 'oWorkflow' => $oWorkflow,
255 'oState' => $oState, 595 'oState' => $oState,
@@ -263,6 +603,7 @@ class KTWorkflowDispatcher extends KTAdminDispatcher { @@ -263,6 +603,7 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
263 'aRoles' => Role::getList(), 603 'aRoles' => Role::getList(),
264 'aUsers' => User::getList(), 604 'aUsers' => User::getList(),
265 'aInformed' => $aInformed, 605 'aInformed' => $aInformed,
  606 + 'editForm' => $editForm,
266 )); 607 ));
267 return $oTemplate; 608 return $oTemplate;
268 } 609 }
@@ -402,7 +743,7 @@ class KTWorkflowDispatcher extends KTAdminDispatcher { @@ -402,7 +743,7 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
402 'redirect_to' => array('editWorkflow', 'fWorkflowId=' . $oWorkflow->getId()), 743 'redirect_to' => array('editWorkflow', 'fWorkflowId=' . $oWorkflow->getId()),
403 'message' => _('Could not create workflow transition'), 744 'message' => _('Could not create workflow transition'),
404 )); 745 ));
405 - $this->successRedirectTo('editWorkflow', _('Workflow transition created'), 'fWorkflowId=' . $oWorkflow->getId()); 746 + $this->successRedirectTo('editTransition', _('Workflow transition created'), sprintf('fWorkflowId=%d&fTransitionId=%d', $oWorkflow->getId(), $res->getId()));
406 exit(0); 747 exit(0);
407 } 748 }
408 // }}} 749 // }}}
resources/css/kt-framing.css
@@ -103,6 +103,11 @@ body @@ -103,6 +103,11 @@ body
103 { 103 {
104 border-bottom: 1px solid white; 104 border-bottom: 1px solid white;
105 } 105 }
  106 +
  107 +.ktLoggedInUser {
  108 + font-weight: bold;
  109 +}
  110 +
106 /* 111 /*
107 a.main_nav_item { 112 a.main_nav_item {
108 background: transparent url(../../resources/graphics/home-navbar.gif) center left no-repeat; 113 background: transparent url(../../resources/graphics/home-navbar.gif) center left no-repeat;
@@ -580,9 +585,9 @@ a.main_nav_item { @@ -580,9 +585,9 @@ a.main_nav_item {
580 .ktInfo 585 .ktInfo
581 { 586 {
582 padding: 0 1em; 587 padding: 0 1em;
583 - border: 1px solid #ffc21e; 588 + border: 1px solid #c5c5c5;
584 margin: 0.5em 0; 589 margin: 0.5em 0;
585 - background: #ffdd80; 590 + background: #dedede;
586 } 591 }
587 592
588 .ktInfo p { 593 .ktInfo p {
@@ -655,6 +660,8 @@ The text will be hidden for screen view. The generic fahrner-ish approach comes @@ -655,6 +660,8 @@ The text will be hidden for screen view. The generic fahrner-ish approach comes
655 660
656 /* =========== standard listings. */ 661 /* =========== standard listings. */
657 662
  663 +
  664 +
658 .listing td { 665 .listing td {
659 padding: 0.5em; 666 padding: 0.5em;
660 vertical-align: top; 667 vertical-align: top;
resources/css/workflow-admin.css 0 โ†’ 100644
  1 +#workflow-states-list {
  2 + list-style-type: none;
  3 + margin-left: 0;
  4 + padding-left: 0;
  5 +}
  6 +
  7 +#workflow-states-list ul {
  8 + list-style-type: none;
  9 + margin-left: 0;
  10 + padding-left: 1em;
  11 + border-top: 1px solid #dedede;
  12 + margin-top: 0.5em;
  13 + margin-bottom: 1.5em;
  14 +}
  15 +
  16 +.workflow_element {
  17 + font-weight: bold;
  18 +}
0 \ No newline at end of file 19 \ No newline at end of file
templates/kt3/standard_page.smarty
@@ -64,9 +64,7 @@ @@ -64,9 +64,7 @@
64 64
65 <!-- user menu --> 65 <!-- user menu -->
66 <li class="pref">{if ($page->user)} 66 <li class="pref">{if ($page->user)}
67 - Logged in as <strong>{$page->user->getName()}</strong>  
68 - {else}  
69 - FIXME: page does not set user. 67 + <span class="ktLoggedInUser">{$page->user->getName()}</span>
70 {/if} 68 {/if}
71 &middot; 69 &middot;
72 70
templates/ktcore/help_with_edit.smarty
1 -<p><a href="{$rootUrl}/admin.php/misc/helpmanagement?action=customise&name={$target_name}">Edit this help page.</a></p>  
2 {if (!$help_body)} 1 {if (!$help_body)}
3 <div class="ktError"><p>No content specified for this help file yet. <strong>Edit it first.</strong></p></div> 2 <div class="ktError"><p>No content specified for this help file yet. <strong>Edit it first.</strong></p></div>
4 {else} 3 {else}
5 {$help_body} 4 {$help_body}
6 -{/if}  
7 \ No newline at end of file 5 \ No newline at end of file
  6 +{/if}
  7 +
  8 +<hr />
  9 +<p><a href="{$rootUrl}/admin.php/misc/helpmanagement?action=customise&name={$target_name}" class="ktAction ktEdit" style="float:
  10 +left; padding-right: 0.5em;">{i18n}Edit this help page.{/i18n}</a><a href="{$rootUrl}/admin.php/misc/helpmanagement?action=customise&name={$target_name}">{i18n}Edit this help page.{/i18n}</a></p>
8 \ No newline at end of file 11 \ No newline at end of file
templates/ktcore/metadata/listFieldsets.smarty
@@ -60,7 +60,7 @@ @@ -60,7 +60,7 @@
60 {$oWidget->render()} 60 {$oWidget->render()}
61 {/foreach} 61 {/foreach}
62 62
63 -<div class="form_actions" 63 +<div class="form_actions">
64 <input type="submit" name="submit" value="{i18n}Create{/i18n}" /> 64 <input type="submit" name="submit" value="{i18n}Create{/i18n}" />
65 </div> 65 </div>
66 </fieldset> 66 </fieldset>
templates/ktcore/workflow/admin_portlet.smarty 0 โ†’ 100644
  1 +<ul class="actionlist">
  2 +{foreach from=$aAdminPages item=aAdminPage}
  3 + <li><a href="{$aAdminPage.url}">{$aAdminPage.name}</a></li>
  4 +{/foreach}
  5 +</ul>
0 \ No newline at end of file 6 \ No newline at end of file
templates/ktcore/workflow/createState.smarty 0 โ†’ 100644
  1 +<h2>{i18n}New State{/i18n}</h2>
  2 +
  3 +<p class="descriptiveText">As documents move through their lifecycle, they
  4 +are placed in certain <strong>states</strong>. For example, an invoice
  5 +which has been mailed might be in the "Pending" <strong>state</strong> after
  6 +the "sent" <strong>transition</strong> has been performed by a user.</p>
  7 +
  8 +<form action="{$smarty.server.PHP_SELF}" method="POST">
  9 +<fieldset>
  10 +<legend>{i18n}Edit state properties{/i18n}</legend>
  11 +<input type="hidden" name="action" value="saveState" />
  12 +<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
  13 +<input type="hidden" name="fStateId" value="{$oState->getId()}" />
  14 +{foreach item=oWidget from=$editForm}
  15 + {$oWidget->render()}
  16 +{/foreach}
  17 +<div class="form_actions">
  18 + <input type="submit" name="submit" value="{i18n}Save{/i18n}" />
  19 +</div>
  20 +</fieldset>
  21 +</form>
  22 +
  23 +<form action="{$smarty.server.PHP_SELF}" method="POST">
  24 +<input type="hidden" name="action" value="saveInform" />
  25 +<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
  26 +<input type="hidden" name="fStateId" value="{$oState->getId()}" />
  27 +
  28 +<fieldset>
  29 +<legend>{i18n}Inform Which Users?{/i18n}</legend>
  30 +<p class="descriptiveText">{i18n}Please select which roles or groups should be
  31 +informed when this state is reached.{/i18n}</p>
  32 +
  33 +
  34 +{if $aRoles}
  35 +<h3>{i18n}Roles{/i18n}</h3>
  36 +{entity_checkboxes entities=$aRoles name="fRoleIds" multiple="true" selected=$aInformed.role assign=aBoxes}
  37 +{foreach from=$aBoxes item=sBox}
  38 +{$sBox}<br />
  39 +{/foreach}
  40 +{/if}
  41 +
  42 +<h3>{i18n}Groups{/i18n}</h3>
  43 +{entity_checkboxes entities=$aGroups name="fGroupIds" multiple="true" selected=$aInformed.group assign=aBoxes}
  44 +{foreach from=$aBoxes item=sBox}
  45 +{$sBox}<br />
  46 +{/foreach}
  47 +
  48 +{*
  49 +<h3>{i18n}Users{/i18n}</h3>
  50 +{entity_checkboxes entities=$aUsers name="fUserIds" multiple="true" selected=$aInformed.user assign=aBoxes}
  51 +{foreach from=$aBoxes item=sBox}
  52 +{$sBox}<br />
  53 +{/foreach}
  54 +<input type="submit" name="submit" value="{i18n}Save{/i18n}" />
  55 +
  56 +</form>
  57 +*}
  58 +
  59 +</fieldset>
  60 +
  61 +
  62 +{*
  63 +<h3>{i18n}Assigned Permissions{/i18n}</h3>
  64 +<p class="descriptiveText">{i18n}While in this workflow state, additional permissions
  65 +may be given. This is done either to expose the document to more users
  66 +or to allow a particular role to be fulfilled before a workflow
  67 +transition can be accomplished.{/i18n}</p>
  68 +*}
  69 +
  70 +
  71 +<fieldset>
  72 +<legend>{i18n}Transitions{/i18n}</legend>
  73 +
  74 +<p class="descriptiveText">{i18n}Transitions are how documents move from one
  75 +state to another. Typically, most transitions can only be performed by people
  76 +with a specific <strong>role</strong> (e.g. Manager) or part of a specific group
  77 +(e.g. Marketing Department).{/i18n}</p>
  78 +
  79 +{if $aTransitionsTo}
  80 +<h3>{i18n}Transitions to this state{/i18n}</h3>
  81 +{if (!empty($aTransitionsTo))}
  82 +<ul>
  83 +{foreach from=$aTransitionsTo item=oTransition}
  84 + <li><a
  85 +href="?action=editTransition&fWorkflowId={$oWorkflow->getId()}&fTransitionId={$oTransition->getId()}"
  86 +title="Transition
  87 +{$oTransition->getId()}">{$oTransition->getName()|escape}</a></li>
  88 +{/foreach}
  89 +</ul>
  90 +
  91 +{/if}
  92 +{else}
  93 +<div class="ktInfo"><p>{i18n}No transitions lead to this state.{/i18n}</p></div>
  94 +{/if}
  95 +
  96 +<h3>{i18n}Transitions from this state{/i18n}</h3>
  97 +<form action="{$smarty.server.PHP_SELF}" method="POST">
  98 +<input type="hidden" name="action" value="saveTransitions" />
  99 +<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
  100 +<input type="hidden" name="fStateId" value="{$oState->getId()}" />
  101 +
  102 +{if (!empty($aTransitions))}
  103 +{entity_checkboxes entities=$aTransitions name="fTransitionIds" multiple="true" selected=$aTransitionsSelected separator="<br />"}
  104 +<div class="form_actions">
  105 +<input type="submit" name="submit" value="{i18n}Save{/i18n}" />
  106 +</div>
  107 +{else}
  108 +<div class="ktInfo"><p>{i18n}No transitions have been defined for this workflow.{/i18n}</p></div>
  109 +{/if}
  110 +</form>
  111 +</fieldset>
  112 +
  113 +
  114 +
  115 +
  116 +<form action="{$smarty.server.PHP_SELF}" method="POST">
  117 +<fieldset>
  118 +<legend>Actions allowed</legend>
  119 +
  120 +<input type="hidden" name="action" value="setStateActions" />
  121 +<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
  122 +<input type="hidden" name="fStateId" value="{$oState->getId()}" />
  123 +
  124 +{if (!empty($aActions))}
  125 +<ul>
  126 +{entity_checkboxes name="fActions" entities=$aActions idmethod="getName" method="getDisplayName" assign="aCheckboxes" selected="$aActionsSelected"}
  127 +{foreach from=$aCheckboxes item=sCheckbox}
  128 +<li>{$sCheckbox}</li>
  129 +{/foreach}
  130 +</ul>
  131 +<div class="form_actions">
  132 + <input type="submit" name="submit" value="Set allowed actions" />
  133 +</div>
  134 +{else}
  135 +No actions defined.
  136 +{/if}
  137 +</fieldset>
  138 +</form>
  139 +
templates/ktcore/workflow/documentWorkflow.smarty
@@ -25,7 +25,7 @@ lifecycle of the document.{/i18n} @@ -25,7 +25,7 @@ lifecycle of the document.{/i18n}
25 </form> 25 </form>
26 {else} 26 {else}
27 <h3>{i18n}No defined workflows{/i18n}</h3> 27 <h3>{i18n}No defined workflows{/i18n}</h3>
28 -<div class="ktError"> 28 +<div class="ktInfo">
29 <p>{i18n}There are no defined workflows which can be started on this 29 <p>{i18n}There are no defined workflows which can be started on this
30 document. An administrator can create workflows to map the lifecycle of 30 document. An administrator can create workflows to map the lifecycle of
31 a document. Contact your administrator to discuss 31 a document. Contact your administrator to discuss
templates/ktcore/workflow/editState.smarty
1 <h2>{i18n}State{/i18n}: {$oState->getName()|escape}</h2> 1 <h2>{i18n}State{/i18n}: {$oState->getName()|escape}</h2>
2 2
  3 +<p class="descriptiveText">As documents move through their lifecycle, they
  4 +are placed in certain <strong>states</strong>. For example, an invoice
  5 +which has been mailed might be in the "Pending" <strong>state</strong> after
  6 +the "sent" <strong>transition</strong> has been performed by a user.</p>
  7 +
3 <form action="{$smarty.server.PHP_SELF}" method="POST"> 8 <form action="{$smarty.server.PHP_SELF}" method="POST">
4 <fieldset> 9 <fieldset>
5 <legend>{i18n}Edit state properties{/i18n}</legend> 10 <legend>{i18n}Edit state properties{/i18n}</legend>
6 <input type="hidden" name="action" value="saveState" /> 11 <input type="hidden" name="action" value="saveState" />
7 <input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" /> 12 <input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
8 <input type="hidden" name="fStateId" value="{$oState->getId()}" /> 13 <input type="hidden" name="fStateId" value="{$oState->getId()}" />
9 -<input type="textbox" name="fName" value="{$oState->getName()|escape}" /> 14 +{foreach item=oWidget from=$editForm}
  15 + {$oWidget->render()}
  16 +{/foreach}
10 <div class="form_actions"> 17 <div class="form_actions">
11 <input type="submit" name="submit" value="{i18n}Save{/i18n}" /> 18 <input type="submit" name="submit" value="{i18n}Save{/i18n}" />
12 </div> 19 </div>
13 </fieldset> 20 </fieldset>
14 </form> 21 </form>
15 - 22 +{*
16 <form action="{$smarty.server.PHP_SELF}" method="POST"> 23 <form action="{$smarty.server.PHP_SELF}" method="POST">
17 <input type="hidden" name="action" value="saveInform" /> 24 <input type="hidden" name="action" value="saveInform" />
18 <input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" /> 25 <input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
@@ -32,25 +39,20 @@ informed when this state is reached.{/i18n}&lt;/p&gt; @@ -32,25 +39,20 @@ informed when this state is reached.{/i18n}&lt;/p&gt;
32 {/foreach} 39 {/foreach}
33 {/if} 40 {/if}
34 41
  42 +{if $aGroups}
35 <h3>{i18n}Groups{/i18n}</h3> 43 <h3>{i18n}Groups{/i18n}</h3>
36 {entity_checkboxes entities=$aGroups name="fGroupIds" multiple="true" selected=$aInformed.group assign=aBoxes} 44 {entity_checkboxes entities=$aGroups name="fGroupIds" multiple="true" selected=$aInformed.group assign=aBoxes}
37 {foreach from=$aBoxes item=sBox} 45 {foreach from=$aBoxes item=sBox}
38 {$sBox}<br /> 46 {$sBox}<br />
39 {/foreach} 47 {/foreach}
  48 +{/if}
40 49
41 -{*  
42 -<h3>{i18n}Users{/i18n}</h3>  
43 -{entity_checkboxes entities=$aUsers name="fUserIds" multiple="true" selected=$aInformed.user assign=aBoxes}  
44 -{foreach from=$aBoxes item=sBox}  
45 -{$sBox}<br />  
46 -{/foreach}  
47 -<input type="submit" name="submit" value="{i18n}Save{/i18n}" />  
48 -  
49 -</form>  
50 -*} 50 +{if (empty($aGroups) && empty($aRoles))}
  51 +<div class="ktInfo"><p>{i18n}No groups or roles are defined in the DMS.{/i18n}</p></div>
  52 +{/if}
51 53
52 </fieldset> 54 </fieldset>
53 - 55 +*}
54 56
55 {* 57 {*
56 <h3>{i18n}Assigned Permissions{/i18n}</h3> 58 <h3>{i18n}Assigned Permissions{/i18n}</h3>
@@ -63,9 +65,13 @@ transition can be accomplished.{/i18n}&lt;/p&gt; @@ -63,9 +65,13 @@ transition can be accomplished.{/i18n}&lt;/p&gt;
63 65
64 <fieldset> 66 <fieldset>
65 <legend>{i18n}Transitions{/i18n}</legend> 67 <legend>{i18n}Transitions{/i18n}</legend>
66 -{if $aTransitionsTo}  
67 68
  69 +<p class="descriptiveText">{i18n}Transitions are how documents move from one
  70 +state to another. Typically, most transitions can only be performed by people
  71 +with a specific <strong>role</strong> (e.g. Manager) or part of a specific group
  72 +(e.g. Marketing Department).{/i18n}</p>
68 73
  74 +{if $aTransitionsTo}
69 <h3>{i18n}Transitions to this state{/i18n}</h3> 75 <h3>{i18n}Transitions to this state{/i18n}</h3>
70 {if (!empty($aTransitionsTo))} 76 {if (!empty($aTransitionsTo))}
71 <ul> 77 <ul>
@@ -76,11 +82,11 @@ title=&quot;Transition @@ -76,11 +82,11 @@ title=&quot;Transition
76 {$oTransition->getId()}">{$oTransition->getName()|escape}</a></li> 82 {$oTransition->getId()}">{$oTransition->getName()|escape}</a></li>
77 {/foreach} 83 {/foreach}
78 </ul> 84 </ul>
79 -{else}  
80 -{i18n}No transitions lead to this state.{/i18n}  
81 -{/if}  
82 85
83 {/if} 86 {/if}
  87 +{else}
  88 +<div class="ktInfo"><p>{i18n}No transitions lead to this state.{/i18n}</p></div>
  89 +{/if}
84 90
85 <h3>{i18n}Transitions from this state{/i18n}</h3> 91 <h3>{i18n}Transitions from this state{/i18n}</h3>
86 <form action="{$smarty.server.PHP_SELF}" method="POST"> 92 <form action="{$smarty.server.PHP_SELF}" method="POST">
@@ -89,12 +95,12 @@ title=&quot;Transition @@ -89,12 +95,12 @@ title=&quot;Transition
89 <input type="hidden" name="fStateId" value="{$oState->getId()}" /> 95 <input type="hidden" name="fStateId" value="{$oState->getId()}" />
90 96
91 {if (!empty($aTransitions))} 97 {if (!empty($aTransitions))}
92 -{entity_checkboxes entities=$aTransitions name="fTransitionIds" multiple="true" selected=$aTransitionsSelected} 98 +{entity_checkboxes entities=$aTransitions name="fTransitionIds" multiple="true" selected=$aTransitionsSelected separator="<br />"}
93 <div class="form_actions"> 99 <div class="form_actions">
94 <input type="submit" name="submit" value="{i18n}Save{/i18n}" /> 100 <input type="submit" name="submit" value="{i18n}Save{/i18n}" />
95 </div> 101 </div>
96 {else} 102 {else}
97 -{i18n}No transitions defined.{/i18n} 103 +<div class="ktInfo"><p>{i18n}No transitions have been defined for this workflow.{/i18n}</p></div>
98 {/if} 104 {/if}
99 </form> 105 </form>
100 </fieldset> 106 </fieldset>
@@ -102,6 +108,8 @@ title=&quot;Transition @@ -102,6 +108,8 @@ title=&quot;Transition
102 108
103 109
104 110
  111 +
  112 +{if (!empty($aActions))}
105 <form action="{$smarty.server.PHP_SELF}" method="POST"> 113 <form action="{$smarty.server.PHP_SELF}" method="POST">
106 <fieldset> 114 <fieldset>
107 <legend>Actions allowed</legend> 115 <legend>Actions allowed</legend>
@@ -110,7 +118,6 @@ title=&quot;Transition @@ -110,7 +118,6 @@ title=&quot;Transition
110 <input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" /> 118 <input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
111 <input type="hidden" name="fStateId" value="{$oState->getId()}" /> 119 <input type="hidden" name="fStateId" value="{$oState->getId()}" />
112 120
113 -{if (!empty($aActions))}  
114 <ul> 121 <ul>
115 {entity_checkboxes name="fActions" entities=$aActions idmethod="getName" method="getDisplayName" assign="aCheckboxes" selected="$aActionsSelected"} 122 {entity_checkboxes name="fActions" entities=$aActions idmethod="getName" method="getDisplayName" assign="aCheckboxes" selected="$aActionsSelected"}
116 {foreach from=$aCheckboxes item=sCheckbox} 123 {foreach from=$aCheckboxes item=sCheckbox}
@@ -120,9 +127,11 @@ title=&quot;Transition @@ -120,9 +127,11 @@ title=&quot;Transition
120 <div class="form_actions"> 127 <div class="form_actions">
121 <input type="submit" name="submit" value="Set allowed actions" /> 128 <input type="submit" name="submit" value="Set allowed actions" />
122 </div> 129 </div>
123 -{else}  
124 -No actions defined.  
125 -{/if}  
126 </fieldset> 130 </fieldset>
127 </form> 131 </form>
  132 +{else}
  133 +<div class="ktInfo"><p>No actions are controlled by this workflow, so all actions are available when
  134 +documents are in this state.</p></div>
  135 +{/if}
  136 +
128 137
templates/ktcore/workflow/editWorkflow.smarty
1 -<h2>{i18n}Workflow{/i18n}: {$oWorkflow->getName()|escape}</h2>  
2 - 1 +{$context->oPage->requireCSSResource('resources/css/workflow-admin.css')}
3 2
  3 +<h2>{i18n}Workflow Overview{/i18n}: {$oWorkflow->getName()|escape}</h2>
4 4
5 <form action="{$smarty.server.PHP_SELF}" method="POST"> 5 <form action="{$smarty.server.PHP_SELF}" method="POST">
6 <fieldset> 6 <fieldset>
@@ -18,98 +18,34 @@ @@ -18,98 +18,34 @@
18 </fieldset> 18 </fieldset>
19 </form> 19 </form>
20 20
21 -<h3>States</h3>  
22 -<p class="descriptiveText"><strong>FIXME</strong> insert intelligent help.</p>  
23 -<form action="{$smarty.server.PHP_SELF}" method="POST">  
24 -<fieldset>  
25 -<legend>{i18n}Create a new state{/i18n}</legend>  
26 -<input type="hidden" name="action" value="newState" />  
27 -<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />  
28 -  
29 -  
30 -{foreach item=oWidget from=$add_state_fields}  
31 - {$oWidget->render()}  
32 -{/foreach}  
33 -  
34 -<div class="form_actions">  
35 -<input type="submit" name="submit" value="{i18n}Create state{/i18n}" />  
36 -</div>  
37 -</fieldset>  
38 -</form>  
39 -  
40 -{if $aStates}  
41 -<h4>{i18n}Existing states{/i18n}</h4>  
42 -<p class="descriptiveText">{i18n}Select a state to update its properties.{/i18n}</p>  
43 -<ul>  
44 -{foreach from=$aStates item=oState}  
45 - <li><a  
46 -href="?action=editState&fWorkflowId={$oWorkflow->getId()}&fStateId={$oState->getId()}"  
47 -title="State {$oState->getId()}">{$oState->getName()|escape}</a></li>  
48 -{/foreach}  
49 -</ul>  
50 -{/if}  
51 -  
52 -  
53 -  
54 -  
55 -{* check that there are states, and, if not, don't show transitions *}  
56 -{if $aStates}  
57 -  
58 -<h3>{i18n}Transitions{/i18n}</h3>  
59 -  
60 -<p class="descriptiveText"><strong>FIXME</strong> insert intelligent help.</p>  
61 -  
62 -<form action="{$smarty.server.PHP_SELF}" method="POST">  
63 -<fieldset>  
64 -<legend>{i18n}Create a new transition{/i18n}</legend>  
65 -<input type="hidden" name="action" value="newTransition" />  
66 -<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />  
67 -  
68 -  
69 -{foreach item=oWidget from=$add_transition_fields}  
70 - {$oWidget->render()}  
71 -{/foreach}  
72 -  
73 -<div class="form_actions">  
74 -<input type="submit" name="submit" value="{i18n}Create transition{/i18n}" />  
75 -</div>  
76 -</fieldset>  
77 -</form>  
78 -  
79 -  
80 -{if $aTransitions}  
81 -<h3>{i18n}Existing transitions{/i18n}</h3>  
82 -  
83 -<ul>  
84 -{foreach from=$aTransitions item=oTransition}  
85 - <li><a  
86 -href="?action=editTransition&fWorkflowId={$oWorkflow->getId()}&fTransitionId={$oTransition->getId()}"  
87 -title="Transition {$oTransition->getId()}">{$oTransition->getName()|escape}</a></li> 21 +<p class="descriptiveText">{i18n}This page allows you to get a quick overview of the
  22 +workflow. To modify items, either select them from the overview below,
  23 +or use the "Workflow" menu on the left to create new ones.{/i18n}</p>
  24 +
  25 +{if (empty($aStates))}
  26 +<div class="ktInfo"><p>This workflow does not define any states. Please use the
  27 +Workflow menu (on the left) to create new states.</p></div>
  28 +{else}
  29 +<ul id="workflow-states-list">
  30 +{foreach item=oState from=$aStates}
  31 + <li><span class="workflow_element">State:</span> <a href="{$smarty.server.PHP_SELF}?action=editState&fStateId={$oState->getId()}&fWorkflowId={$oWorkflow->getId()}" class="workflow_label">{$oState->getName()}</a>
  32 + <ul>
  33 + <li>{i18n}Notified groups &amp; roles:{/i18n}
  34 + {$context->getNotificationStringForState($oState)}
  35 + </li>
  36 + <li>{i18n}Actions available: {/i18n}
  37 + {$context->getActionStringForState($oState)}
  38 + </li>
  39 +
  40 + <li>{i18n}Transitions available: {/i18n}
  41 + {$context->getTransitionFromStringForState($oState)}
  42 + </li>
  43 +
  44 + <li>{i18n}Transitions to this state: {/i18n}
  45 + {$context->getTransitionToStringForState($oState)}
  46 + </li>
  47 + </ul>
  48 + </li>
88 {/foreach} 49 {/foreach}
89 </ul> 50 </ul>
90 -{/if}  
91 -  
92 -{/if}  
93 -  
94 -  
95 -  
96 -<form action="{$smarty.server.PHP_SELF}" method="POST">  
97 -<fieldset>  
98 -<legend>{i18n}Actions controlled{/i18n}</legend>  
99 -  
100 -<p class="descriptiveText"><strong>FIXME</strong> be helpful</p>  
101 -  
102 -<input type="hidden" name="action" value="setWorkflowActions" />  
103 -<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />  
104 -  
105 -<ul>  
106 -{entity_checkboxes name="fActions" entities=$aActions idmethod="getName" method="getDisplayName" assign="aCheckboxes" selected="$aActionsSelected"}  
107 -{foreach from=$aCheckboxes item=sCheckbox}  
108 -<li>{$sCheckbox}</li>  
109 -{/foreach}  
110 -</ul>  
111 -<div class="form_actions">  
112 - <input type="submit" name="submit" value="{i18n}Set controlled actions{/i18n}" />  
113 -</div>  
114 -</fieldset>  
115 -</form> 51 +{/if}
116 \ No newline at end of file 52 \ No newline at end of file
templates/ktcore/workflow/listWorkflows.smarty
1 -<h2>{i18n}Workflow{/i18n}</h2> 1 +<h2>{i18n}Workflows{/i18n}</h2>
  2 +
  3 +<p class="descriptiveText">{i18n}Workflow is a description of a document's lifecycle. It is made up of
  4 +workflow states, which describe where in the lifecycle the document is,
  5 +and workflow transitions, which describe the next steps within the
  6 +lifecycle of the document.{/i18n}</p>
2 7
3 <form action="{$smarty.server.PHP_SELF}" method="POST"> 8 <form action="{$smarty.server.PHP_SELF}" method="POST">
4 <fieldset> 9 <fieldset>
templates/ktcore/workflow/manageActions.smarty 0 โ†’ 100644
  1 +{$context->oPage->requireCSSResource('resources/css/workflow-admin.css')}
  2 +<h2>{i18n}Manage Actions{/i18n}</h2>
  3 +
  4 +<p class="descriptiveText">{i18n}An important part of workflow is controlling which
  5 +actions are available to users at various stages. For example, it may be
  6 +necessary to prevent the "Edit Metadata" action from being used when a document
  7 +is "published". Doing this is a two step process: first, you need to specify
  8 +that "Edit Metadata" is an action you wish to control within this workflow; second,
  9 +you need to specify that the action is <strong>not</strong> to be made available
  10 +when documents are in the "published" state.{/i18n}</p>
  11 +
  12 +<form>
  13 +<fieldset><legend>{i18n}Specify Controlled Actions{/i18n}</legend>
  14 +<p class="descriptiveText">{i18n}Select the actions you want this workflow
  15 +to control from the list below. Actions you do not specify will be available no
  16 +matter what the state of the document.{/i18n}</p>
  17 +
  18 +<input type="hidden" name="action" value="setWorkflowActions" />
  19 +<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
  20 +
  21 +
  22 +{entity_checkboxes name="fActions" entities="$aActions" idmethod="getName" method="getDisplayName" assign="aCheckboxes" selected="$aActionsSelected" separator="<br />"}
  23 +{foreach from=$aCheckboxes item=sCheckbox}
  24 +{$sCheckbox}
  25 +{/foreach}
  26 +
  27 +<div class="form_actions">
  28 + <input type="submit" name="submit" value="{i18n}Set controlled actions{/i18n}" />
  29 +</div>
  30 +
  31 +</fieldset>
  32 +</form>
  33 +
  34 +<h3>Assign Actions to States</h3>
  35 +
  36 +<p class="descriptiveText">The table below lists the actions you have specified
  37 +as controlled by this workflow, and all the states within the workflow. From here
  38 +you can assign those actions to the various states in this workflow.</p>
  39 +
  40 +{if (empty($aActionsSelected))}
  41 +<div class="ktInfo"><p>{i18n}No actions are controlled by this workflow. All actions
  42 +will be available at all states.{/i18n}</p></div>
  43 +{else}
  44 +<form action="{$smarty.server.PHP_SELF}" method="POST">
  45 +<input type="hidden" name="action" value="updateActionAvailability" />
  46 +<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
  47 +<table class="kt_collection" style="width: auto;">
  48 +<thead>
  49 + <tr>
  50 + <th>&nbsp;</th>
  51 + {foreach from=$aActions item=oAction}
  52 + <th>{$oAction->getDisplayName()}</th>
  53 + {/foreach}
  54 + </tr>
  55 +</thead>
  56 +<tbody>
  57 +{foreach item=oState from=$workflow_info.states}
  58 + <tr class='{cycle values="odd,even"}'>
  59 + <td>{$oState->getName()}</td>
  60 + {foreach item=oAction from=$aActions}
  61 + <td><input type="checkbox" name="fAvailableActions[{$oState->getId()}][{$oAction->getName()}]" {if ($context->actionAvailable($oAction, $oState))}checked="true"{/if}/></td>
  62 + {/foreach}
  63 + </tr>
  64 +{/foreach}
  65 +</tbody>
  66 +</table>
  67 +
  68 +<div class="form_actions">
  69 + <input type="submit" value="{i18n}Update Action Availability{/i18n}" />
  70 +</div>
  71 +</form>
  72 +{/if}
  73 +
templates/ktcore/workflow/manageStates.smarty 0 โ†’ 100644
  1 +{$context->oPage->requireCSSResource('resources/css/workflow-admin.css')}
  2 +<h2>{i18n}Manage States{/i18n}</h2>
  3 +
  4 +<p class="descriptiveText">As documents move through their lifecycle, they
  5 +are placed in certain <strong>states</strong>. For example, an invoice
  6 +which has been mailed might be in the "Pending" <strong>state</strong> after
  7 +the "sent" <strong>transition</strong> has been performed by a user.</p>
  8 +
  9 +<form action="{$smarty.server.PHP_SELF}" method="POST">
  10 +<fieldset>
  11 +<legend>{i18n}Create a new state{/i18n}</legend>
  12 +
  13 +<p class="descriptiveText">Please note that additional configuration is
  14 +possible on states beyond what is specified here (e.g. which users to notify
  15 +about the document, etc). Please edit the state
  16 +to access and modify these other properties.</p>
  17 +
  18 +<input type="hidden" name="action" value="newState" />
  19 +<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
  20 +
  21 +{* Standard Form *}
  22 +
  23 +{foreach item=oWidget from=$add_fields}
  24 + {$oWidget->render()}
  25 +{/foreach}
  26 +
  27 +<div class="form_actions">
  28 +<input type="submit" name="submit" value="{i18n}Create state{/i18n}" />
  29 +</div>
  30 +</fieldset>
  31 +</form>
  32 +
  33 +{if (empty($workflow_info.states))}
  34 +<div class="ktInfo"><p>This workflow does not define any states.</p></div>
  35 +{else}
  36 +<ul id="workflow-states-list">
  37 +{foreach item=oState from=$workflow_info.states}
  38 + <li><span class="workflow_element">State:</span> <a href="{$smarty.server.PHP_SELF}?action=editState&fStateId={$oState->getId()}&fWorkflowId={$oWorkflow->getId()}" class="workflow_label">{$oState->getName()}</a>
  39 + <ul>
  40 + <li><a href="{$smarty.server.PHP_SELF}?action=editState&fStateId={$oState->getId()}&fWorkflowId={$oWorkflow->getId()}">{i18n}Notified groups & roles:{/i18n}</a>
  41 + {$context->getNotificationStringForState($oState)}
  42 + </li>
  43 + <li><a href="{$smarty.server.PHP_SELF}?action=editState&fStateId={$oState->getId()}&fWorkflowId={$oWorkflow->getId()}">{i18n}Actions available: {/i18n}</a>
  44 + {$context->getActionStringForState($oState)}
  45 + </li>
  46 +
  47 + <li><a href="{$smarty.server.PHP_SELF}?action=editTransitions&fWorkflowId={$oWorkflow->getId()}">{i18n}Transitions available: {/i18n}</a>
  48 + {$context->getTransitionFromStringForState($oState)}
  49 + </li>
  50 +
  51 + <li>{i18n}Transitions to this state: {/i18n}
  52 + {$context->getTransitionToStringForState($oState)}
  53 + </li>
  54 + </ul>
  55 + </li>
  56 +{/foreach}
  57 +</ul>
  58 +{/if}
0 \ No newline at end of file 59 \ No newline at end of file
templates/ktcore/workflow/manageTransitions.smarty 0 โ†’ 100644
  1 +<h2>{i18n}Manage Transitions{/i18n}</h2>
  2 +
  3 +<p class="descriptiveText">{i18n}Transitions are what drive the workflow of documents.
  4 +Each step that needs to be followed in the document's lifecycle could
  5 +map to a transition, and can be allowed or denied by a combination
  6 +of roles, permissions and groups.{/i18n}</p>
  7 +
  8 +<p class="descriptiveText">{i18n}Use the form below to create a new Transition, and
  9 +assign or edit existing transitions using the table below.{/i18n}</p>
  10 +
  11 +<form action="{$smarty.server.PHP_SELF}" method="POST">
  12 +<fieldset>
  13 +<legend>{i18n}Create a new state{/i18n}</legend>
  14 +
  15 +<input type="hidden" name="action" value="newTransition" />
  16 +<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
  17 +
  18 +{* Standard Form *}
  19 +
  20 +{foreach item=oWidget from=$add_fields}
  21 + {$oWidget->render()}
  22 +{/foreach}
  23 +
  24 +<div class="form_actions">
  25 +<input type="submit" name="submit" value="{i18n}Create transition{/i18n}" />
  26 +</div>
  27 +</fieldset>
  28 +</form>
  29 +
  30 +<h3>{i18n}Transition Availability{/i18n}</h3>
  31 +
  32 +<p class="descriptiveText">Click on any transition below to edit it directly,
  33 +or use the checkboxes to assign which states the transition is available from.</p>
  34 +
  35 +<form action="{$smarty.server.PHP_SELF}" method="POST">
  36 +<input type="hidden" name="action" value="setTransitionAvailability">
  37 +<input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
  38 +
  39 +<table class="kt_collection" style="width: auto">
  40 +<thead>
  41 + <tr>
  42 + <th>
  43 + &nbsp;
  44 + </th>
  45 + {foreach item=oState from=$workflow_info.states}
  46 + <th>
  47 + {$oState->getName()}
  48 + </th>
  49 + {/foreach}
  50 + </tr>
  51 +</thead>
  52 +<tbody>
  53 + {foreach item=oTransition from=$workflow_info.transitions}
  54 + <tr class='{cycle values="odd,even"}'>
  55 + <td>
  56 + <a href="{$smarty.server.PHP_SELF}?action=editTransition&fWorkflowId={$oWorkflow->getId()}&fTransitionId={$oTransition->getId()}">{$oTransition->getName()}</a>
  57 + </td>
  58 + {foreach item=oState from=$workflow_info.states}
  59 + <td>
  60 + {if ($oState->getId() != $oTransition->getTargetStateId())}
  61 + <input type="checkbox" name="fTransitionAvailability[{$oState->getId()}][{$oTransition->getId()}]" {if ($context->transitionAvailable($oTransition, $oState))}checked="true"{/if}>
  62 + {else}&mdash;{/if}
  63 + </td>
  64 + {/foreach}
  65 + </tr>
  66 + {/foreach}
  67 +</tbody>
  68 +<table>
  69 +
  70 +<div class="form_actions">
  71 + <input type="submit" value="{i18n}Assign Transition Availability{/i18n}" />
  72 +</div>
  73 +
  74 +</form>
0 \ No newline at end of file 75 \ No newline at end of file