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 72 function renderFolderLink($aDataRow) {
73 73 $outStr = '<a href="' . $this->buildFolderLink($aDataRow) . '">';
74 74 $outStr .= $aDataRow["folder"]->getName();
75   - $outStr .= '</a>';
  75 + $outStr .= '</a> ';
76 76 return $outStr;
77 77 }
78 78  
... ...
plugins/ktcore/KTDocumentActions.php
... ... @@ -585,7 +585,7 @@ class KTDocumentWorkflowAction extends KTDocumentAction {
585 585  
586 586 $oUser =& User::get($_SESSION['userID']);
587 587 $aTransitions = KTWorkflowUtil::getTransitionsForDocumentUser($oDocument, $oUser);
588   - $aWorkflows = KTWorkflow::getList();
  588 + $aWorkflows = KTWorkflow::getList('start_state_id IS NOT NULL');
589 589  
590 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 18  
19 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 52 class KTWorkflowDispatcher extends KTAdminDispatcher {
22 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 59 $this->aBreadcrumbs[] = array(
28 60 'url' => $_SERVER['PHP_SELF'],
29 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 248 $add_fields = array();
33 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 258 return $oTemplate;
43 259 }
44 260 // }}}
45   -
  261 +
46 262 // {{{ do_editWorkflow
47 263 function do_editWorkflow() {
48 264  
49 265 $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/editWorkflow');
50 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 275 $edit_fields = array();
56 276 $edit_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the workflow.'), 'fName', $oWorkflow->getName(), $this->oPage, true);
57 277 $aOptions = array();
58 278 $vocab = array();
59   - $vocab[0] = 'None';
  279 + $vocab[0] = 'None - documents cannot use this workflow.';
60 280 foreach($aStates as $state) {
61 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 290 $add_state_fields = array();
67 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 297 $oTemplate->setData(array(
  298 + 'context' => $this,
97 299 'oWorkflow' => $oWorkflow,
  300 +
98 301 'aStates' => $aStates,
99   - 'aTransitions' => KTWorkflowTransition::getByWorkflow($oWorkflow),
  302 + 'aTransitions' => $aInfo['transitions'],
100 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 311 'edit_fields' => $edit_fields,
106   - 'add_state_fields' => $add_state_fields,
107   - 'add_transition_fields' => $add_transition_fields,
108 312 ));
109 313 return $oTemplate;
110 314 }
... ... @@ -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 506 // {{{ do_setWorkflowActions
172 507 function do_setWorkflowActions() {
173 508 $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']);
... ... @@ -247,9 +582,14 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
247 582 'query' => 'action=editWorkflow&fWorkflowId=' . $oWorkflow->getId(),
248 583 'name' => $oWorkflow->getName(),
249 584 );
250   - $this->oPage->setBreadcrumbDetails(_('state') . ': ' . $oState->getName());
  585 + $this->oPage->setBreadcrumbDetails(_('State') . ': ' . $oState->getName());
251 586  
252 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 593 $oTemplate->setData(array(
254 594 'oWorkflow' => $oWorkflow,
255 595 'oState' => $oState,
... ... @@ -263,6 +603,7 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
263 603 'aRoles' => Role::getList(),
264 604 'aUsers' => User::getList(),
265 605 'aInformed' => $aInformed,
  606 + 'editForm' => $editForm,
266 607 ));
267 608 return $oTemplate;
268 609 }
... ... @@ -402,7 +743,7 @@ class KTWorkflowDispatcher extends KTAdminDispatcher {
402 743 'redirect_to' => array('editWorkflow', 'fWorkflowId=' . $oWorkflow->getId()),
403 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 747 exit(0);
407 748 }
408 749 // }}}
... ...
resources/css/kt-framing.css
... ... @@ -103,6 +103,11 @@ body
103 103 {
104 104 border-bottom: 1px solid white;
105 105 }
  106 +
  107 +.ktLoggedInUser {
  108 + font-weight: bold;
  109 +}
  110 +
106 111 /*
107 112 a.main_nav_item {
108 113 background: transparent url(../../resources/graphics/home-navbar.gif) center left no-repeat;
... ... @@ -580,9 +585,9 @@ a.main_nav_item {
580 585 .ktInfo
581 586 {
582 587 padding: 0 1em;
583   - border: 1px solid #ffc21e;
  588 + border: 1px solid #c5c5c5;
584 589 margin: 0.5em 0;
585   - background: #ffdd80;
  590 + background: #dedede;
586 591 }
587 592  
588 593 .ktInfo p {
... ... @@ -655,6 +660,8 @@ The text will be hidden for screen view. The generic fahrner-ish approach comes
655 660  
656 661 /* =========== standard listings. */
657 662  
  663 +
  664 +
658 665 .listing td {
659 666 padding: 0.5em;
660 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 19 \ No newline at end of file
... ...
templates/kt3/standard_page.smarty
... ... @@ -64,9 +64,7 @@
64 64  
65 65 <!-- user menu -->
66 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 68 {/if}
71 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 1 {if (!$help_body)}
3 2 <div class="ktError"><p>No content specified for this help file yet. <strong>Edit it first.</strong></p></div>
4 3 {else}
5 4 {$help_body}
6   -{/if}
7 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 11 \ No newline at end of file
... ...
templates/ktcore/metadata/listFieldsets.smarty
... ... @@ -60,7 +60,7 @@
60 60 {$oWidget->render()}
61 61 {/foreach}
62 62  
63   -<div class="form_actions"
  63 +<div class="form_actions">
64 64 <input type="submit" name="submit" value="{i18n}Create{/i18n}" />
65 65 </div>
66 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 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 25 </form>
26 26 {else}
27 27 <h3>{i18n}No defined workflows{/i18n}</h3>
28   -<div class="ktError">
  28 +<div class="ktInfo">
29 29 <p>{i18n}There are no defined workflows which can be started on this
30 30 document. An administrator can create workflows to map the lifecycle of
31 31 a document. Contact your administrator to discuss
... ...
templates/ktcore/workflow/editState.smarty
1 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 8 <form action="{$smarty.server.PHP_SELF}" method="POST">
4 9 <fieldset>
5 10 <legend>{i18n}Edit state properties{/i18n}</legend>
6 11 <input type="hidden" name="action" value="saveState" />
7 12 <input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
8 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 17 <div class="form_actions">
11 18 <input type="submit" name="submit" value="{i18n}Save{/i18n}" />
12 19 </div>
13 20 </fieldset>
14 21 </form>
15   -
  22 +{*
16 23 <form action="{$smarty.server.PHP_SELF}" method="POST">
17 24 <input type="hidden" name="action" value="saveInform" />
18 25 <input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
... ... @@ -32,25 +39,20 @@ informed when this state is reached.{/i18n}&lt;/p&gt;
32 39 {/foreach}
33 40 {/if}
34 41  
  42 +{if $aGroups}
35 43 <h3>{i18n}Groups{/i18n}</h3>
36 44 {entity_checkboxes entities=$aGroups name="fGroupIds" multiple="true" selected=$aInformed.group assign=aBoxes}
37 45 {foreach from=$aBoxes item=sBox}
38 46 {$sBox}<br />
39 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 54 </fieldset>
53   -
  55 +*}
54 56  
55 57 {*
56 58 <h3>{i18n}Assigned Permissions{/i18n}</h3>
... ... @@ -63,9 +65,13 @@ transition can be accomplished.{/i18n}&lt;/p&gt;
63 65  
64 66 <fieldset>
65 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 75 <h3>{i18n}Transitions to this state{/i18n}</h3>
70 76 {if (!empty($aTransitionsTo))}
71 77 <ul>
... ... @@ -76,11 +82,11 @@ title=&quot;Transition
76 82 {$oTransition->getId()}">{$oTransition->getName()|escape}</a></li>
77 83 {/foreach}
78 84 </ul>
79   -{else}
80   -{i18n}No transitions lead to this state.{/i18n}
81   -{/if}
82 85  
83 86 {/if}
  87 +{else}
  88 +<div class="ktInfo"><p>{i18n}No transitions lead to this state.{/i18n}</p></div>
  89 +{/if}
84 90  
85 91 <h3>{i18n}Transitions from this state{/i18n}</h3>
86 92 <form action="{$smarty.server.PHP_SELF}" method="POST">
... ... @@ -89,12 +95,12 @@ title=&quot;Transition
89 95 <input type="hidden" name="fStateId" value="{$oState->getId()}" />
90 96  
91 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 99 <div class="form_actions">
94 100 <input type="submit" name="submit" value="{i18n}Save{/i18n}" />
95 101 </div>
96 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 104 {/if}
99 105 </form>
100 106 </fieldset>
... ... @@ -102,6 +108,8 @@ title=&quot;Transition
102 108  
103 109  
104 110  
  111 +
  112 +{if (!empty($aActions))}
105 113 <form action="{$smarty.server.PHP_SELF}" method="POST">
106 114 <fieldset>
107 115 <legend>Actions allowed</legend>
... ... @@ -110,7 +118,6 @@ title=&quot;Transition
110 118 <input type="hidden" name="fWorkflowId" value="{$oWorkflow->getId()}" />
111 119 <input type="hidden" name="fStateId" value="{$oState->getId()}" />
112 120  
113   -{if (!empty($aActions))}
114 121 <ul>
115 122 {entity_checkboxes name="fActions" entities=$aActions idmethod="getName" method="getDisplayName" assign="aCheckboxes" selected="$aActionsSelected"}
116 123 {foreach from=$aCheckboxes item=sCheckbox}
... ... @@ -120,9 +127,11 @@ title=&quot;Transition
120 127 <div class="form_actions">
121 128 <input type="submit" name="submit" value="Set allowed actions" />
122 129 </div>
123   -{else}
124   -No actions defined.
125   -{/if}
126 130 </fieldset>
127 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 5 <form action="{$smarty.server.PHP_SELF}" method="POST">
6 6 <fieldset>
... ... @@ -18,98 +18,34 @@
18 18 </fieldset>
19 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 49 {/foreach}
89 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 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 8 <form action="{$smarty.server.PHP_SELF}" method="POST">
4 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 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 75 \ No newline at end of file
... ...