diff --git a/kthelp/.htaccess b/kthelp/.htaccess new file mode 100644 index 0000000..2c1b49f --- /dev/null +++ b/kthelp/.htaccess @@ -0,0 +1,3 @@ +Order deny,allow +Deny from all + diff --git a/kthelp/ktcore/EN/admin/workflow/overview.html b/kthelp/ktcore/EN/admin/workflow/overview.html new file mode 100644 index 0000000..b5b0cd8 --- /dev/null +++ b/kthelp/ktcore/EN/admin/workflow/overview.html @@ -0,0 +1,25 @@ + + +
+ + +Workflow allows you to assign a series of steps to the document creation and +management process. For example, a "News" workflow might have documents which +go from Research to Draft to Under Review +to Published, +with different people participating in the document's +lifecycle at each stage. Naturally, not all documents have the +same needs in terms of workflow: Invoices (which must be drawn up, mailed, and then marked as paid) are very different from Marketing documents.
+To facilitate this, KnowledgeTree™ allows the Administrator to +define a number of different workflows, each of which can be applied to +different documents as their organisation requires.
+ + + diff --git a/lib/browse/BrowseColumns.inc.php b/lib/browse/BrowseColumns.inc.php index c318442..0ab38a4 100644 --- a/lib/browse/BrowseColumns.inc.php +++ b/lib/browse/BrowseColumns.inc.php @@ -72,7 +72,7 @@ class TitleColumn extends BrowseColumn { function renderFolderLink($aDataRow) { $outStr = ''; $outStr .= $aDataRow["folder"]->getName(); - $outStr .= ''; + $outStr .= ' '; return $outStr; } diff --git a/plugins/ktcore/KTDocumentActions.php b/plugins/ktcore/KTDocumentActions.php index 7f483cf..bd92476 100644 --- a/plugins/ktcore/KTDocumentActions.php +++ b/plugins/ktcore/KTDocumentActions.php @@ -585,7 +585,7 @@ class KTDocumentWorkflowAction extends KTDocumentAction { $oUser =& User::get($_SESSION['userID']); $aTransitions = KTWorkflowUtil::getTransitionsForDocumentUser($oDocument, $oUser); - $aWorkflows = KTWorkflow::getList(); + $aWorkflows = KTWorkflow::getList('start_state_id IS NOT NULL'); $fieldErrors = null; diff --git a/plugins/ktcore/admin/workflows.php b/plugins/ktcore/admin/workflows.php index 2b19a00..defcae5 100755 --- a/plugins/ktcore/admin/workflows.php +++ b/plugins/ktcore/admin/workflows.php @@ -18,16 +18,232 @@ require_once(KT_LIB_DIR . '/search/savedsearch.inc.php'); require_once(KT_LIB_DIR . '/actions/documentaction.inc.php'); +require_once(KT_LIB_DIR . '/widgets/portlet.inc.php'); + +class WorkflowNavigationPortlet extends KTPortlet { + var $oWorkflow; + + function WorkflowNavigationPortlet($sTitle, $oWorkflow = null) { + $this->oWorkflow = $oWorkflow; + parent::KTPortlet($sTitle); + } + + function render() { + if (is_null($this->oWorkflow)) { return _('No Workflow Selected.'); } + + $aAdminPages = array(); + $aAdminPages[] = array('name' => _('Overview'), 'url' => $_SERVER['PHP_SELF'] . '?action=editWorkflow&fWorkflowId=' . $this->oWorkflow->getId()); + $aAdminPages[] = array('name' => _('States'), 'url' => $_SERVER['PHP_SELF'] . '?action=manageStates&fWorkflowId=' . $this->oWorkflow->getId()); + $aAdminPages[] = array('name' => _('Transitions'), 'url' => $_SERVER['PHP_SELF'] . '?action=manageTransitions&fWorkflowId=' . $this->oWorkflow->getId()); + $aAdminPages[] = array('name' => _('Actions'), 'url' => $_SERVER['PHP_SELF'] . '?action=manageActions&fWorkflowId=' . $this->oWorkflow->getId()); + + + $oTemplating = new KTTemplating; + $oTemplate = $oTemplating->loadTemplate("ktcore/workflow/admin_portlet"); + $aTemplateData = array( + "context" => $this, + "aAdminPages" => $aAdminPages, + ); + + return $oTemplate->render($aTemplateData); + } +} + class KTWorkflowDispatcher extends KTAdminDispatcher { var $bAutomaticTransaction = true; + var $sHelpPage = 'ktcore/admin/workflow/overview.html'; + var $aWorkflowInfo; + var $oWorkflow; - // {{{ WORKFLOW HANDLING - // {{{ do_main - function do_main () { + function check() { $this->aBreadcrumbs[] = array( 'url' => $_SERVER['PHP_SELF'], 'name' => _('Workflows'), ); + $this->oWorkflow =& KTWorkflow::get($_REQUEST['fWorkflowId']); + if (!PEAR::isError($this->oWorkflow)) { + $this->aBreadcrumbs[] = array( + 'url' => $_SERVER['PHP_SELF'], + 'query' => 'action=editWorkflow&fWorkflowId=' . $this->oWorkflow->getId(), + 'name' => $this->oWorkflow->getName(), + ); + $this->oPage->addPortlet(new WorkflowNavigationPortlet(_('Workflow'), $this->oWorkflow)); + } + + return true; + } + + // helper function to construct the set of workflow information + function buildWorkflowInfo($oWorkflow) { + if ($this->aWorkflowInfo != null) { return $this->aWorkflowInfo; } + + $aInfo = array(); + $aInfo['workflow'] = $oWorkflow; + + // roles + $aRoles = Role::getList(); + $aKeyRoles = array(); + foreach ($aRoles as $oRole) { $aKeyRoles[$oRole->getId()] = $oRole; } + $aInfo['roles'] = $aKeyRoles; + + // groups + $aGroups = Group::getList(); + $aKeyGroups = array(); + foreach ($aGroups as $oGroup) { $aKeyGroups[$oGroup->getId()] = $oGroup; } + $aInfo['groups'] = $aKeyGroups; + + // states. + $aStates = KTWorkflowState::getByWorkflow($oWorkflow); + $aKeyStates = array(); + foreach ($aStates as $oState) { $aKeyStates[$oState->getId()] = $oState; } + $aInfo['states'] = $aKeyStates; + + // transitions + $aTransitions = KTWorkflowTransition::getByWorkflow($oWorkflow); + $aKeyTransitions = array(); + foreach ($aTransitions as $oTransition) { $aKeyTransitions[$oTransition->getId()] = $oTransition; } + $aInfo['transitions'] = $aKeyTransitions; + + // permissions + $aPermissions = KTPermission::getList(); + $aKeyPermissions = array(); + foreach ($aPermissions as $oPermission) { $aKeyPermissions[$oPermission->getId()] = $oPermission; } + $aInfo['permissions'] = $aKeyPermissions; + + // actions + $aInfo['actions'] = KTDocumentActionUtil::getAllDocumentActions(); + $aKeyActions = array(); + foreach ($aInfo['actions'] as $oAction) { $aKeyActions[$oAction->getName()] = $oAction; } + $aInfo['actions_by_name'] = $aKeyActions; + + $aInfo['controlled_actions'] = KTWorkflowUtil::getControlledActionsForWorkflow($oWorkflow); + + /* + * now we need to do the crossmappings. + */ + + $aActionsByState = array(); + foreach ($aInfo['states'] as $oState) { + $aActionsByState[$oState->getId()] = KTWorkflowUtil::getEnabledActionsForState($oState);; + } + $aInfo['actions_by_state'] = $aActionsByState; + + // FIXME handle notified users and groups + $aTransitionsFromState = array(); + foreach ($aInfo['states'] as $oState) { + $aTransitionsFromState[$oState->getId()] = KTWorkflowUtil::getTransitionsFrom($oState); + } + $aInfo['transitions_from_state'] = $aTransitionsFromState; + + $aTransitionsToState = array(); + foreach ($aInfo['states'] as $oState) { + $aTransitionsToState[$oState->getId()] = KTWorkflowTransition::getByTargetState($oState); + } + $aInfo['transitions_to_state'] = $aTransitionsToState; + + $this->aWorkflowInfo = $aInfo; + + return $aInfo; + } + + + function getActionStringForState($oState) { + $aInfo = $this->aWorkflowInfo; + + // no controlled actions => all available + if (empty($aInfo['controlled_actions'])) { return _('All actions available.'); } + + + $aAlways = array(); + foreach ($aInfo['actions'] as $iActionId => $aAction) { + if (!array_key_exists($iActionId, $aInfo['controlled_actions'])) { + $aAlways[$iActionId] = $aAction; + } + } + + $aNamedActions = array(); + foreach ($aInfo['actions_by_state'][$oState->getId()] as $sName) { + $aNamedActions[] = $aInfo['actions_by_name'][$sName]; + } + + $aThese = array_merge($aAlways, $aNamedActions); + // some controlled. we need to be careful here: list actions that _are always_ available + if (empty($aThese)) { return _('No actions available.'); } + + // else + $aActions = array(); + foreach ($aThese as $oAction) { $aActions[] = $oAction->getDisplayName(); } + return implode(', ', $aActions); + } + + function getTransitionToStringForState($oState) { + $aInfo = $this->aWorkflowInfo; + //var_dump($aInfo['transitions_to_state'][$oState->getId()]); + if (($aInfo['workflow']->getStartStateId() != $oState->getId()) && (empty($aInfo['transitions_to_state'][$oState->getId()]))) { + return '' . _('This state is unreachable.') . ''; + } + + + if ($aInfo['workflow']->getStartStateId() == $oState->getId() && (empty($aInfo['transitions_to_state'][$oState->getId()]))) { + return '' . _('Documents start in this state') . ''; + } + $aT = array(); + if ($aInfo['workflow']->getStartStateId() == $oState->getId()) { + $aT[] = '' . _('Documents start in this state') . ''; + } + + foreach ($aInfo['transitions_to_state'][$oState->getId()] as $aTransition) { + $aT[] = sprintf('%s', $_SERVER['PHP_SELF'], $aInfo['workflow']->getId(), $aTransition->getId() ,$aTransition->getName()); + } + + return implode(', ',$aT); + } + + function getNotificationStringForState($oState) { + return _('No roles and groups notified.'); + } + + function transitionAvailable($oTransition, $oState) { + $aInfo = $this->aWorkflowInfo; + + $val = false; + foreach ($aInfo['transitions_from_state'][$oState->getId()] as $oT) { + if ($oTransition->getId() == $oT->getId()) { $val = true; } + } + + return $val; + } + + function actionAvailable($oAction, $oState) { + $aInfo = $this->aWorkflowInfo; + + $val = false; + + foreach ($aInfo['actions_by_state'][$oState->getId()] as $oA) { + + if ($oAction->getName() == $oA) { $val = true; } + } + + return $val; + } + + function getTransitionFromStringForState($oState) { + $aInfo = $this->aWorkflowInfo; + + if (empty($aInfo['transitions_from_state'][$oState->getId()])) { + return '' . _('No transitions available') . ''; + } + + $aT = array(); + foreach ($aInfo['transitions_from_state'][$oState->getId()] as $aTransition) { + $aT[] = sprintf('%s', $_SERVER['PHP_SELF'], $aInfo['workflow']->getId(), $aTransition->getId() ,$aTransition->getName()); + } + return implode(', ', $aT); + } + + // {{{ WORKFLOW HANDLING + // {{{ do_main + function do_main () { $add_fields = array(); $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 { return $oTemplate; } // }}} - + // {{{ do_editWorkflow function do_editWorkflow() { $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/editWorkflow'); $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']); - $aStates = KTWorkflowState::getByWorkflow($oWorkflow); - $aPermissions = KTPermission::getList(); + + + $aInfo = $this->buildWorkflowInfo($oWorkflow); + + $aPermissions = $aInfo['permissions']; + $aStates = $aInfo['states']; $edit_fields = array(); $edit_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the workflow.'), 'fName', $oWorkflow->getName(), $this->oPage, true); $aOptions = array(); $vocab = array(); - $vocab[0] = 'None'; + $vocab[0] = 'None - documents cannot use this workflow.'; foreach($aStates as $state) { $vocab[$state->getId()] = $state->getName(); } - $aOptions['vocab'] = $vocab; - $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); + $aOptions['vocab'] = $vocab; + $edit_fields[] = new KTLookupWidget(_('Starting State'), _('When a document has this workflow applied to it, to which state should it initially be set. Note that workflows without a starting state cannot be applied to documents.'), 'fStartStateId', $oWorkflow->getStartStateId(), $this->oPage, false, null, null, $aOptions); + if (is_null($oWorkflow->getStartStateId())) { + $this->oPage->addInfo(_('This workflow is currently disabled. To enable it, please assign a starting state in the "Edit workflow properties" box.')); + } + /* $add_state_fields = array(); $add_state_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the state.'), 'fName', null, $this->oPage, true); - $add_transition_fields = array(); - $add_transition_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the transition.'), 'fName', null, $this->oPage, true); - $aOptions = array(); - $vocab = array(); - foreach($aStates as $state) { - $vocab[$state->getId()] = $state->getName(); - } - $aOptions['vocab'] = $vocab; - $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); - $aOptions = array(); - $vocab = array(); - foreach($aPermissions as $permission) { - $vocab[$permission->getId()] = $permission->getHumanName(); - } - $aOptions['vocab'] = $vocab; - $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); + */ + - $this->aBreadcrumbs[] = array( - 'url' => $_SERVER['PHP_SELF'], - 'name' => _('Workflows'), - ); - $this->aBreadcrumbs[] = array( - 'url' => $_SERVER['PHP_SELF'], - 'query' => 'action=editWorkflow&fWorkflowId=' . $oWorkflow->getId(), - 'name' => $oWorkflow->getName(), - ); $oTemplate->setData(array( + 'context' => $this, 'oWorkflow' => $oWorkflow, + 'aStates' => $aStates, - 'aTransitions' => KTWorkflowTransition::getByWorkflow($oWorkflow), + 'aTransitions' => $aInfo['transitions'], 'aPermissions' => $aPermissions, - 'aActions' => KTDocumentActionUtil::getAllDocumentActions(), - 'aActionsSelected' => KTWorkflowUtil::getControlledActionsForWorkflow($oWorkflow), + 'aActions' => $aInfo['actions'], + 'aActionsSelected' => $aInfo['controlled_actions'], + + // info + 'workflow_info' => $aInfo, - // fields + // subform 'edit_fields' => $edit_fields, - 'add_state_fields' => $add_state_fields, - 'add_transition_fields' => $add_transition_fields, )); return $oTemplate; } @@ -168,6 +372,137 @@ class KTWorkflowDispatcher extends KTAdminDispatcher { } // }}} + function do_manageActions() { + $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/manageActions'); + $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']); + + $aInfo = $this->buildWorkflowInfo($oWorkflow); + + $oTemplate->setData(array( + 'context' => $this, + 'oWorkflow' => $oWorkflow, + + 'aActions' => $aInfo['actions'], + 'aActionsSelected' => $aInfo['controlled_actions'], + + // info + 'workflow_info' => $aInfo, + )); + return $oTemplate; + + } + + function do_manageStates() { + $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/manageStates'); + $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']); + + $aInfo = $this->buildWorkflowInfo($oWorkflow); + + $add_fields = array(); + $add_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the state.'), 'fName', null, $this->oPage, true); + + + + $oTemplate->setData(array( + 'context' => $this, + 'oWorkflow' => $oWorkflow, + + // info + 'workflow_info' => $aInfo, + + // subform + 'add_fields' => $add_fields, + )); + return $oTemplate; + } + + function do_manageTransitions() { + $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/manageTransitions'); + $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']); + + $aInfo = $this->buildWorkflowInfo($oWorkflow); + + $add_transition_fields = array(); + $add_transition_fields[] = new KTStringWidget(_('Name'), _('A human-readable name for the transition.'), 'fName', null, $this->oPage, true); + $aOptions = array(); + $vocab = array(); + foreach($aInfo['states'] as $state) { + $vocab[$state->getId()] = $state->getName(); + } + $aOptions['vocab'] = $vocab; + $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); + $aOptions = array(); + $vocab = array(); + foreach($aInfo['permissions'] as $permission) { + $vocab[$permission->getId()] = $permission->getHumanName(); + } + $aOptions['vocab'] = $vocab; + $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); + + $oTemplate->setData(array( + 'context' => $this, + 'oWorkflow' => $oWorkflow, + + // info + 'workflow_info' => $aInfo, + + // subform + 'add_fields' => $add_transition_fields, + )); + return $oTemplate; + } + + function do_setTransitionAvailability() { + $oTemplate =& $this->oValidator->validateTemplate('ktcore/workflow/editWorkflow'); + $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']); + + $transitionMap = (array) KTUtil::arrayGet($_REQUEST, 'fTransitionAvailability'); + + $aInfo = $this->buildWorkflowInfo($oWorkflow); + + $this->startTransaction(); + foreach ($aInfo['states'] as $oState) { + + $a = (array) $transitionMap[$oState->getId()]; + $transitions = array(); + foreach ($a as $tid => $on) { $transitions[] = $tid; } + + $res = KTWorkflowUtil::saveTransitionsFrom($oState, $transitions); + if (PEAR::isError($res)) { + $this->errorRedirectTo('manageTransitions', _('Error updating transitions:') . $res->getMessage(), sprintf('fWorkflowId=%d', $oWorkflow->getId())); + } + } + $this->commitTransaction(); + + $this->successRedirectTo('manageTransitions', _('Availability updated.'), sprintf('fWorkflowId=%d', $oWorkflow->getId())); + } + + + function do_updateActionAvailability() { + $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']); + + $actionMap = (array) KTUtil::arrayGet($_REQUEST, 'fAvailableActions'); + + $aInfo = $this->buildWorkflowInfo($oWorkflow); + + $this->startTransaction(); + foreach ($aInfo['states'] as $oState) { + + $a = (array) $actionMap[$oState->getId()]; + $actions = array_keys($a); + + + + $res = KTWorkflowUtil::setEnabledActionsForState($oState, $actions); + if (PEAR::isError($res)) { + $this->errorRedirectTo('manageActions', _('Error updating actions:') . $res->getMessage(), sprintf('fWorkflowId=%d', $oWorkflow->getId())); + } + } + $this->commitTransaction(); + + $this->successRedirectTo('manageActions', _('Action availability updated.'), sprintf('fWorkflowId=%d', $oWorkflow->getId())); + } + // {{{ do_setWorkflowActions function do_setWorkflowActions() { $oWorkflow =& $this->oValidator->validateWorkflow($_REQUEST['fWorkflowId']); @@ -247,9 +582,14 @@ class KTWorkflowDispatcher extends KTAdminDispatcher { 'query' => 'action=editWorkflow&fWorkflowId=' . $oWorkflow->getId(), 'name' => $oWorkflow->getName(), ); - $this->oPage->setBreadcrumbDetails(_('state') . ': ' . $oState->getName()); + $this->oPage->setBreadcrumbDetails(_('State') . ': ' . $oState->getName()); $aInformed = KTWorkflowUtil::getInformedForState($oState); + + + $editForm = array(); + $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); + $oTemplate->setData(array( 'oWorkflow' => $oWorkflow, 'oState' => $oState, @@ -263,6 +603,7 @@ class KTWorkflowDispatcher extends KTAdminDispatcher { 'aRoles' => Role::getList(), 'aUsers' => User::getList(), 'aInformed' => $aInformed, + 'editForm' => $editForm, )); return $oTemplate; } @@ -402,7 +743,7 @@ class KTWorkflowDispatcher extends KTAdminDispatcher { 'redirect_to' => array('editWorkflow', 'fWorkflowId=' . $oWorkflow->getId()), 'message' => _('Could not create workflow transition'), )); - $this->successRedirectTo('editWorkflow', _('Workflow transition created'), 'fWorkflowId=' . $oWorkflow->getId()); + $this->successRedirectTo('editTransition', _('Workflow transition created'), sprintf('fWorkflowId=%d&fTransitionId=%d', $oWorkflow->getId(), $res->getId())); exit(0); } // }}} diff --git a/resources/css/kt-framing.css b/resources/css/kt-framing.css index 03f2962..3c9fbe5 100644 --- a/resources/css/kt-framing.css +++ b/resources/css/kt-framing.css @@ -103,6 +103,11 @@ body { border-bottom: 1px solid white; } + +.ktLoggedInUser { + font-weight: bold; +} + /* a.main_nav_item { background: transparent url(../../resources/graphics/home-navbar.gif) center left no-repeat; @@ -580,9 +585,9 @@ a.main_nav_item { .ktInfo { padding: 0 1em; - border: 1px solid #ffc21e; + border: 1px solid #c5c5c5; margin: 0.5em 0; - background: #ffdd80; + background: #dedede; } .ktInfo p { @@ -655,6 +660,8 @@ The text will be hidden for screen view. The generic fahrner-ish approach comes /* =========== standard listings. */ + + .listing td { padding: 0.5em; vertical-align: top; diff --git a/resources/css/workflow-admin.css b/resources/css/workflow-admin.css new file mode 100644 index 0000000..42c09d1 --- /dev/null +++ b/resources/css/workflow-admin.css @@ -0,0 +1,18 @@ +#workflow-states-list { + list-style-type: none; + margin-left: 0; + padding-left: 0; +} + +#workflow-states-list ul { + list-style-type: none; + margin-left: 0; + padding-left: 1em; + border-top: 1px solid #dedede; + margin-top: 0.5em; + margin-bottom: 1.5em; +} + +.workflow_element { + font-weight: bold; +} \ No newline at end of file diff --git a/templates/kt3/standard_page.smarty b/templates/kt3/standard_page.smarty index 05bc528..fc95fda 100644 --- a/templates/kt3/standard_page.smarty +++ b/templates/kt3/standard_page.smarty @@ -64,9 +64,7 @@No content specified for this help file yet. Edit it first.
{i18n}Edit this help page.{/i18n}{i18n}Edit this help page.{/i18n}
\ No newline at end of file diff --git a/templates/ktcore/metadata/listFieldsets.smarty b/templates/ktcore/metadata/listFieldsets.smarty index 8e698a6..81fe1ad 100644 --- a/templates/ktcore/metadata/listFieldsets.smarty +++ b/templates/ktcore/metadata/listFieldsets.smarty @@ -60,7 +60,7 @@ {$oWidget->render()} {/foreach} -As documents move through their lifecycle, they +are placed in certain states. For example, an invoice +which has been mailed might be in the "Pending" state after +the "sent" transition has been performed by a user.
+ + + + +*} + + + + +{* +{i18n}While in this workflow state, additional permissions +may be given. This is done either to expose the document to more users +or to allow a particular role to be fulfilled before a workflow +transition can be accomplished.{/i18n}
+*} + + + + + + + + + diff --git a/templates/ktcore/workflow/documentWorkflow.smarty b/templates/ktcore/workflow/documentWorkflow.smarty index 430fbaa..f7b65b2 100644 --- a/templates/ktcore/workflow/documentWorkflow.smarty +++ b/templates/ktcore/workflow/documentWorkflow.smarty @@ -25,7 +25,7 @@ lifecycle of the document.{/i18n} {else}{i18n}There are no defined workflows which can be started on this document. An administrator can create workflows to map the lifecycle of a document. Contact your administrator to discuss diff --git a/templates/ktcore/workflow/editState.smarty b/templates/ktcore/workflow/editState.smarty index 863cb5e..0589ce0 100644 --- a/templates/ktcore/workflow/editState.smarty +++ b/templates/ktcore/workflow/editState.smarty @@ -1,18 +1,25 @@
As documents move through their lifecycle, they +are placed in certain states. For example, an invoice +which has been mailed might be in the "Pending" state after +the "sent" transition has been performed by a user.
+ - +{* -*} +{if (empty($aGroups) && empty($aRoles))} +{i18n}No groups or roles are defined in the DMS.{/i18n}
No actions are controlled by this workflow, so all actions are available when +documents are in this state.
FIXME insert intelligent help.
- - -{if $aStates} -{i18n}Select a state to update its properties.{/i18n}
-FIXME insert intelligent help.
- - - - -{if $aTransitions} -{i18n}This page allows you to get a quick overview of the +workflow. To modify items, either select them from the overview below, +or use the "Workflow" menu on the left to create new ones.{/i18n}
+ +{if (empty($aStates))} +This workflow does not define any states. Please use the +Workflow menu (on the left) to create new states.
{i18n}Workflow is a description of a document's lifecycle. It is made up of +workflow states, which describe where in the lifecycle the document is, +and workflow transitions, which describe the next steps within the +lifecycle of the document.{/i18n}