From 6ee05b85afe24cb84141676550598be378538e44 Mon Sep 17 00:00:00 2001 From: JT Smith Date: Wed, 15 Feb 2006 21:23:22 +0000 Subject: [PATCH] first round of changes to create the ui for building workflows, more to come a few small bug fixes --- docs/upgrades/upgrade_6.8.6-6.9.0.pl | 4 + lib/WebGUI/AdminConsole.pm | 9 + lib/WebGUI/AssetTrash.pm | 2 +- lib/WebGUI/Group.pm | 14 +- lib/WebGUI/Operation.pm | 7 + lib/WebGUI/Operation/Cron.pm | 2 +- lib/WebGUI/Operation/Workflow.pm | 225 +++++++++++++++++++++++ lib/WebGUI/User.pm | 2 +- lib/WebGUI/Workflow.pm | 67 +++++-- lib/WebGUI/Workflow/Activity.pm | 3 +- lib/WebGUI/i18n/English/Workflow.pm | 126 +++++++++++++ lib/WebGUI/i18n/English/Workflow_Cron.pm | 6 - 12 files changed, 441 insertions(+), 26 deletions(-) create mode 100644 lib/WebGUI/Operation/Workflow.pm create mode 100644 lib/WebGUI/i18n/English/Workflow.pm diff --git a/docs/upgrades/upgrade_6.8.6-6.9.0.pl b/docs/upgrades/upgrade_6.8.6-6.9.0.pl index 08c60390b..2a0cfc5d2 100644 --- a/docs/upgrades/upgrade_6.8.6-6.9.0.pl +++ b/docs/upgrades/upgrade_6.8.6-6.9.0.pl @@ -15,6 +15,7 @@ use WebGUI::Session; use File::Path; use WebGUI::Workflow; use WebGUI::Workflow::Cron; +use WebGUI::Group; my $toVersion = "6.9.0"; # make this match what version you're going to my $quiet; # this line required @@ -38,6 +39,9 @@ finish($session); # this line required #------------------------------------------------- sub addWorkflow { print "\tAdding workflow.\n"; + my $group = WebGUI::Group->new($session,"new","pbgroup000000000000015"); + $group->set("groupName", "Workflow Managers"); + $group->set("description", "People who can create, edit, and delete workflows."); $session->config->set("spectreIp","127.0.0.1"); $session->config->set("spectrePort",32133); $session->config->set("spectreSubnets",["127.0.0.1/32"]); diff --git a/lib/WebGUI/AdminConsole.pm b/lib/WebGUI/AdminConsole.pm index 018531b5d..934b56a23 100644 --- a/lib/WebGUI/AdminConsole.pm +++ b/lib/WebGUI/AdminConsole.pm @@ -161,6 +161,15 @@ sub getAdminFunction { func=>"manageVersions", group=>"3" }, + "workflow"=>{ + title=>{ + id=>"topicName", + namespace=>"Workflow" + }, + icon=>"workflow.gif", + op=>"manageWorkflows", + group=>"pbgroup000000000000015" + }, "cron"=>{ title=>{ id=>"topicName", diff --git a/lib/WebGUI/AssetTrash.pm b/lib/WebGUI/AssetTrash.pm index a5337683e..2e774c185 100644 --- a/lib/WebGUI/AssetTrash.pm +++ b/lib/WebGUI/AssetTrash.pm @@ -96,7 +96,7 @@ Deletes an asset from tables and removes anything bound to that asset, including sub purge { my $self = shift; - return undef if ($self->getId eq $self->session->setting->get("defaultPage") || $self->getId eq $self->session->setting->get("notFoundPage") || $self->get("isSystem"); + return undef if ($self->getId eq $self->session->setting->get("defaultPage") || $self->getId eq $self->session->setting->get("notFoundPage") || $self->get("isSystem")); my $kids = $self->getLineage(["children"],{returnObjects=>1, statesToInclude=>['published', 'clipboard', 'clipboard-limbo','trash','trash-limbo']}); foreach my $kid (@{$kids}) { $kid->purge; diff --git a/lib/WebGUI/Group.pm b/lib/WebGUI/Group.pm index 61cbeb126..6618591ba 100755 --- a/lib/WebGUI/Group.pm +++ b/lib/WebGUI/Group.pm @@ -83,6 +83,7 @@ These methods are available from this class: #------------------------------------------------------------------- sub _create { my $self = shift; + my $override = shift; $self->{_groupId} = $self->session->db->setRow("groups","groupId",{ groupId=>"new", dateCreated=>$self->session->datetime->time(), @@ -95,7 +96,7 @@ sub _create { databaseLinkId=>0, dbCacheTimeout=>3600, lastUpdated=>$self->session->datetime->time() - }); + }, $override); $self->addGroups([3]); } @@ -680,7 +681,7 @@ sub name { #------------------------------------------------------------------- -=head2 new ( session, groupId ) +=head2 new ( session, groupId [, overrideId ] ) Constructor. @@ -690,7 +691,11 @@ A reference to the current session. =head3 groupId -The groupId of the group you're creating an object reference for. If specified as "new" then a new group will be created and assigned the next available groupId. If left blank then the object methods will just return default values for everything. +The groupId of the group you're creating an object reference for. If specified as "new" then a new group will be created and assigned a new random groupId. If left blank then the object methods will just return default values for everything. + +=head3 overrideId + +If you specified "new" for groupId, you can use this property to specify an id you wish to create, rather than having the system generate one for you. =cut @@ -701,8 +706,9 @@ sub new { my $self = {}; $self->{_session} = shift; $self->{_groupId} = shift; + my $override = shift; bless $self, $class; - $self->_create() if ($self->{_groupId} eq "new"); + $self->_create($override) if ($self->{_groupId} eq "new"); return $self; } diff --git a/lib/WebGUI/Operation.pm b/lib/WebGUI/Operation.pm index 4a01450e6..cd0a13474 100644 --- a/lib/WebGUI/Operation.pm +++ b/lib/WebGUI/Operation.pm @@ -77,6 +77,13 @@ Returns a hash reference containing operation and package names. sub getOperations { return { + 'addWorkflow' => 'WebGUI::Operation::Workflow', + 'deleteWorkflow' => 'WebGUI::Operation::Workflow', + 'deleteWorkflowActivity' => 'WebGUI::Operation::Workflow', + 'addWorkflowSave' => 'WebGUI::Operation::Workflow', + 'editWorkflow' => 'WebGUI::Operation::Workflow', + 'editWorkflowSave' => 'WebGUI::Operation::Workflow', + 'manageWorkflows' => 'WebGUI::Operation::Workflow', 'manageCron' => 'WebGUI::Operation::Cron', 'editCronJob' => 'WebGUI::Operation::Cron', 'editCronJobSave' => 'WebGUI::Operation::Cron', diff --git a/lib/WebGUI/Operation/Cron.pm b/lib/WebGUI/Operation/Cron.pm index 84f008107..93a0224fd 100644 --- a/lib/WebGUI/Operation/Cron.pm +++ b/lib/WebGUI/Operation/Cron.pm @@ -221,7 +221,7 @@ sub www_manageCron { my $rs = $session->db->read("select taskId, title, concat(minuteOfHour, ' ', hourOfDay, ' ', dayOfMonth, ' ', monthOfYear, ' ', dayOfWeek), enabled from WorkflowSchedule"); while (my ($id, $title, $schedule, $enabled) = $rs->array) { $output .= '' - .$session->icon->delete("op=deleteCronJob;id=".$id, undef, $i18n->get("are you sure you want to delete this scheduled task")) + .$session->icon->delete("op=deleteCronJob;id=".$id, undef, $i18n->get("are you sure you wish to delete this scheduled task")) .$session->icon->edit("op=editCronJob;id=".$id) .''.$title.''.$schedule.'' .($enabled ? $i18n->get("enabled") : $i18n->get("disabled")) diff --git a/lib/WebGUI/Operation/Workflow.pm b/lib/WebGUI/Operation/Workflow.pm new file mode 100644 index 000000000..360558c72 --- /dev/null +++ b/lib/WebGUI/Operation/Workflow.pm @@ -0,0 +1,225 @@ +package WebGUI::Operation::Workflow; + +#------------------------------------------------------------------- +# WebGUI is Copyright 2001-2006 Plain Black Corporation. +#------------------------------------------------------------------- +# Please read the legal notices (docs/legal.txt) and the license +# (docs/license.txt) that came with this distribution before using +# this software. +#------------------------------------------------------------------- +# http://www.plainblack.com info@plainblack.com +#------------------------------------------------------------------- + +use strict; +use Tie::IxHash; +use WebGUI::AdminConsole; +use WebGUI::HTMLForm; +use WebGUI::International; +use WebGUI::Workflow; + +=head1 NAME + +Package WebGUI::Operations::Workflow + +=head1 DESCRIPTION + +Operation handler for managing workflows. + +=cut + +#------------------------------------------------------------------- + +=head2 www_addWorkflow () + +Allows the user to choose the type of workflow that's going to be created. + +=cut + +sub www_addWorkflow { + my $session = shift; + return $session->privilege->insufficient() unless ($session->user->isInGroup("pbgroup000000000000015")); + my $i18n = WebGUI::International->new($session, "Workflow"); + my $f = WebGUI::HTMLForm->new($session); + $f->hidden( + name=>"op", + value=>"addWorkflowSave" + ); + $f->selectBox( + name=>"type", + label=>$i18n->get("object type"), + options=>{ + none=>$i18n->get("none"), + versiontag=>$i18n->get("versiontag"), + user=>$i18n->get("user") + }, + value=>"none", + hoverHelp=>$i18n->get("object type help") + ); + my $ac = WebGUI::AdminConsole->new($session,"workflow"); + $ac->addSubmenuItem($session->url->page("op=manageWorkflows"), $i18n->get("manage workflows")); + return $ac->render($f->print); +} + +#------------------------------------------------------------------- + +=head2 www_addWorkflowSave () + +Saves the results from www_addWorkflow(). + +=cut + +sub www_addWorkflowSave { + my $session = shift; + return $session->privilege->insufficient() unless ($session->user->isInGroup("pbgroup000000000000015")); + my $workflow = WebGUI::Workflow->create($session, {type=>$session->form->get("type")}); + return www_editWorkflowSave($session, $workflow); +} + +#------------------------------------------------------------------- + +=head2 www_deleteWorkflow ( ) + +Deletes an entire workflow. + +=cut + +sub www_deleteWorkflow { + my $session = shift; + return $session->privilege->insufficient() unless ($session->user->isInGroup("pbgroup000000000000015")); + my $workflow = WebGUI::Workflow->new($session, $session->form->get("workflowId")); + $workflow->delete if defined $workflow; + return www_manageWorkflow($session); +} + +#------------------------------------------------------------------- + +=head2 www_deleteWorkflowActivity ( ) + +Deletes an activity from a workflow. + +=cut + +sub www_deleteWorkflowActivity { + my $session = shift; + return $session->privilege->insufficient() unless ($session->user->isInGroup("pbgroup000000000000015")); + my $workflow = WebGUI::Workflow->new($session, $session->form->get("workflowId")); + $workflow->deleteActivity($session->form->get("activityId")) if defined $workflow; + return www_editWorkflow($session); +} + +#------------------------------------------------------------------- + +=head2 www_editWorkflow ( session, workflow ) + +Displays displays the editable properties of a workflow. + +=cut + +sub www_editWorkflow { + my $session = shift; + my $workflow = shift; + return $session->privilege->insufficient() unless ($session->user->isInGroup("pbgroup000000000000015")); + $workflow = WebGUI::Workflow->new($session, $session->form->get("workflowId")) unless (defined $workflow); + my $i18n = WebGUI::International->new($session, "Workflow"); + my $f = WebGUI::HTMLForm->new($session); + $f->hidden( + name=>"op", + value=>"editWorkflowSave" + ); + $f->hidden( + name=>"workflowId", + value=>$workflow->getId + ); + $f->readOnly( + label=>$i18n->get("workflowId"), + value=>$workflow->getId + ); + $f->readOnly( + label=>$i18n->get("object type"), + value=>$workflow->getTypeName + ); + $f->text( + name=>"title", + value=>$workflow->get("title"), + label=>$i18n->get("title"), + hoverHelp=>$i18n->get("title help") + ); + $f->text( + name=>"description", + value=>$workflow->get("description"), + label=>$i18n->get("description"), + hoverHelp=>$i18n->get("description help") + ); + $f->yesNo( + name=>"enabled", + value=>$workflow->get("enabled"), + defaultValue=>0, + label=>$i18n->get("is enabled"), + hoverHelp=>$i18n->get("is enabled help") + ); + $f->yesNo( + name=>"isSerial", + value=>$workflow->get("isSerial"), + defaultValue=>0, + label=>$i18n->get("is serial"), + hoverHelp=>$i18n->get("is serial help") + ); + $f->submit; + my $ac = WebGUI::AdminConsole->new($session,"workflow"); + $ac->addSubmenuItem($session->url->page("op=addWorkflow"), $i18n->get("add a new workflow")); + $ac->addSubmenuItem($session->url->page("op=manageWorkflows"), $i18n->get("manage workflows")); + return $ac->render($f->print); +} + + +#------------------------------------------------------------------- + +=head2 www_editWorkflowSave ( ) + +Saves the results of www_editWorkflow() + +=cut + +sub www_editWorkflowSave { + my $session = shift; + return $session->privilege->insufficient() unless ($session->user->isInGroup("pbgroup000000000000015")); + my $workflow = WebGUI::Workflow::Cron->new($session, $session->form->get("workflowId")); + $workflow->set({ + enabled=>$session->form->get("enabled","yesNo"), + isSerial=>$session->form->get("isSerial","yesNo"), + title=>$session->form->get("title"), + description=>$session->form->get("description","textarea"), + }); + return www_editWorkflow($session, $workflow); +} + + +#------------------------------------------------------------------- + +=head2 www_manageCron ( ) + +Display a list of the workflows. + +=cut + +sub www_manageWorkflows { + my $session = shift; + return $session->privilege->insufficient() unless ($session->user->isInGroup("pbgroup000000000000015")); + my $i18n = WebGUI::International->new($session, "Workflow"); + my $output = ''; + my $rs = $session->db->read("select workflowId, title, enabled from Workflow order by title"); + while (my ($id, $title, $enabled) = $rs->array) { + $output .= '\n"; + } + $output .= '
' + .$session->icon->delete("op=deleteWorkflow;workflowId=".$id, undef, $i18n->get("are you sure you want to delete this workflow")) + .$session->icon->edit("op=editWorkflow;workflowId=".$id) + .''.$title.'' + .($enabled ? $i18n->get("enabled") : $i18n->get("disabled")) + ."
'; + my $ac = WebGUI::AdminConsole->new($session,"workflow"); + $ac->addSubmenuItem($session->url->page("op=addWorkflow"), $i18n->get("add a new workflow")); + return $ac->render($output); +} + +1; diff --git a/lib/WebGUI/User.pm b/lib/WebGUI/User.pm index ffa205dc8..5d051c63f 100644 --- a/lib/WebGUI/User.pm +++ b/lib/WebGUI/User.pm @@ -446,7 +446,7 @@ sub lastUpdated { #------------------------------------------------------------------- -=head2 new ( userId [, overrideId ] ) +=head2 new ( session, userId [, overrideId ] ) Constructor. diff --git a/lib/WebGUI/Workflow.pm b/lib/WebGUI/Workflow.pm index 3326ff38c..5e044fd71 100644 --- a/lib/WebGUI/Workflow.pm +++ b/lib/WebGUI/Workflow.pm @@ -114,7 +114,7 @@ sub delete { =head2 deleteActivity ( activityId ) -Removes an activity from this workflow. +Removes an activity from this workflow. This is just a convenience method, so you don't have to manually load and construct activity objects when you're already working with a workflow. =head3 activityId @@ -125,8 +125,8 @@ The unique id of the activity to remove. sub deleteActivity { my $self = shift; my $activityId = shift; - my ($class) = $self->session->db->quickArray("select className from WorkflowActivity where activityId=?",[$activityId]); - WebGUI::Workflow::Activity->new($self->session, $activityId, $class)->delete; + my $activity = $self->getActivity($activityId); + $activity->delete if ($activity); } #------------------------------------------------------------------- @@ -158,6 +158,32 @@ sub get { } +#------------------------------------------------------------------- + +=head2 getActivity ( activityId [, classname ] ) + +Retrieves an activity object. This is just a convenience method, so you don't have to manually load and construct activity objects when you're already working with a workflow. + +=head3 activityId + +The unique id of the activity. + +=head3 classname + +The classname of the activity. This will be looked up if you don't specify it. + +=cut + +sub getActivity { + my $self = shift; + my $activityId = shift; + my $class = shift; + unless ($class) { + ($class) = $self->session->db->quickArray("select className from WorkflowActivity where activityId=?",[$activityId]); + } + return WebGUI::Workflow::Activity->new($self->session, $activityId, $class); +} + #------------------------------------------------------------------- =head2 getActivities ( ) @@ -172,17 +198,30 @@ sub getActivities { my $rs = $self->session->db->prepare("select activityId, className from WorkflowActivity where workflowId=? order by sequenceNumber"); $rs->execute([$self->getId]); while (my ($activityId, $class) = $rs->array) { - push(@activities, WebGUI::Workflow::Activity->new($self->session, $activityId, $class)); + push(@activities, $self->getActivity($activityId, $class)); } return \@activities; } +#------------------------------------------------------------------- + +=head2 getId ( ) + +Returns the ID of this workflow. + +=cut + +sub getId { + my $self = shift; + return $self->{_id}; +} + #------------------------------------------------------------------- =head2 getList ( session, [ type ] ) -Returns a hash reference of workflowId/title pairs of all the workflows defined in the system. This is a class method. +Returns a hash reference of workflowId/title pairs of all the workflows defined in the system. This is a class method. Note that this will not return anything that is disabled. =head3 session @@ -198,7 +237,7 @@ sub getList { my $class = shift; my $session = shift; my $type = shift; - my $sql = "select workflowId, title from Workflow"; + my $sql = "select workflowId, title from Workflow where enabled=1"; $sql .= " where type=?" if ($type); return $session->db->buildHashRef($sql, $type); } @@ -225,21 +264,27 @@ sub getNextActivity { and sequenceNumber>=? order by sequenceNumber", [$self->getId, $sequenceNumber]); my ($id, $class) = $rs->array; $rs->finish; - return WebGUI::Workflow::Activity->new($self->session, $id, $class); + return $self->getActivity($id, $class); } #------------------------------------------------------------------- -=head2 getId ( ) +=head2 getTypeName ( [ type ] ) -Returns the ID of this workflow. +Returns a human readable name for the object type this workflow supports. + +=head3 type + +Optionally override the type by specifying it here. =cut -sub getId { +sub getTypeName { my $self = shift; - return $self->{_id}; + my $type = shift || $self->get("type"); + my $i18n = WebGUI::International->new($self->session,"Workflow"); + return $i18n->get($type); } #------------------------------------------------------------------- diff --git a/lib/WebGUI/Workflow/Activity.pm b/lib/WebGUI/Workflow/Activity.pm index 14f99f96f..a4b0e164b 100644 --- a/lib/WebGUI/Workflow/Activity.pm +++ b/lib/WebGUI/Workflow/Activity.pm @@ -65,8 +65,8 @@ sub create { my $class = shift; my $session = shift; my $workflowId = shift; - my $classname = shift; my $id = shift; + my $classname = shift; my ($sequenceNumber) = $session->db->quickArray("select count(*) from WorkflowActivity where workflowId=?", [$workflowId]); $sequenceNumber++; my $activityId = $session->db->setRow("WorkflowActivity","activityId", { @@ -196,7 +196,6 @@ sub getType { return "none"; } - #------------------------------------------------------------------- =head2 new ( session, activityId [, classname] ) diff --git a/lib/WebGUI/i18n/English/Workflow.pm b/lib/WebGUI/i18n/English/Workflow.pm new file mode 100644 index 000000000..dae2c79c1 --- /dev/null +++ b/lib/WebGUI/i18n/English/Workflow.pm @@ -0,0 +1,126 @@ +package WebGUI::i18n::English::Workflow; + +our $I18N = { + 'are you sure you want to delete this workflow' => { + message => q|Are you certain you wish to delete this workflow and all running instances of it?|, + context => q|prompt the user before deleting a workflow|, + lastUpdated => 0, + }, + + 'none' => { + message => q|None|, + context => q|Workflow doesn't work on objects.|, + lastUpdated => 0, + }, + + 'versiontag' => { + message => q|Version Tag|, + context => q|Workflow can work on version tag objects.|, + lastUpdated => 0, + }, + + 'user' => { + message => q|User|, + context => q|Workflow can work on user objects.|, + lastUpdated => 0, + }, + + 'object type help' => { + message => q|What type of objects do you want this workflow to be able to handle?|, + context => q|the hover help for the object type field|, + lastUpdated => 0, + }, + + 'object type' => { + message => q|Object Type|, + context => q|a label for the form that lets users choose what kind of objects a workflow can handle|, + lastUpdated => 0, + }, + + 'is serial help' => { + message => q|If yes is selected then only one instance of this workflow will be allowed to be created at one time. Generally speaking this would be a bad idea for approval workflows, but is probably a good idea for workflows the download emails from a remote server, to avoid getting duplicates.|, + context => q|the hover help for the is serial field|, + lastUpdated => 0, + }, + + 'is serial' => { + message => q|Is serial?|, + context => q|A question that asks the user whether this workflow may be instanciated multiple times concurrently or not.|, + lastUpdated => 0, + }, + + 'description help' => { + message => q|Fill out a detailed description of what this workflow does and is used for for future reference.|, + context => q|the hover help for the description field|, + lastUpdated => 0, + }, + + 'description' => { + message => q|Description|, + context => q|A more detailed description of what this workflow does.|, + lastUpdated => 0, + }, + + 'is enabled help' => { + message => q|If this is set to yes, then the system will be allowed to create running instances of this workflow.|, + context => q|the hover help for the enabled field|, + lastUpdated => 0, + }, + + 'is enabled' => { + message => q|Is Enabled?|, + context => q|Yes or no question asking the user if this workflow is enabled.|, + lastUpdated => 0, + }, + + 'title help' => { + message => q|A human readable label to easily identify what this workflow does.|, + context => q|the hover help for the title field|, + lastUpdated => 0, + }, + + 'title' => { + message => q|Title|, + context => q|A human readable label to identify a workflow.|, + lastUpdated => 0, + }, + + 'enabled' => { + message => q|Enabled|, + context => q|A label to indicate that the workflow is ready to run.|, + lastUpdated => 0, + }, + + 'disabled' => { + message => q|Disabled|, + context => q|A label to indicate that the workflow is not ready to run.|, + lastUpdated => 0, + }, + + 'workflowId' => { + message => q|Workflow ID|, + context => q|a label for the unique id representing the workflow|, + lastUpdated => 0, + }, + + 'manage workflows' => { + message => q|Manage all workflows.|, + context => q|clicking on this text linked will show the user a list of all workflows|, + lastUpdated => 0, + }, + + 'add a new workflow' => { + message => q|Add a new workflow.|, + context => q|clicking on this text linked will add a new workflow|, + lastUpdated => 0, + }, + + 'topicName' => { + message => q|Workflow|, + context => q|The title of the workflow interface.|, + lastUpdated => 0, + }, + +}; + +1; diff --git a/lib/WebGUI/i18n/English/Workflow_Cron.pm b/lib/WebGUI/i18n/English/Workflow_Cron.pm index 41a405501..0266a445f 100644 --- a/lib/WebGUI/i18n/English/Workflow_Cron.pm +++ b/lib/WebGUI/i18n/English/Workflow_Cron.pm @@ -145,12 +145,6 @@ our $I18N = { lastUpdated => 0, }, - 'are you sure you want to delete this scheduled task' => { - message => q|Are you certain you wish to delete this task?|, - context => q|The question asked before deleteing a cron job.|, - lastUpdated => 0, - }, - 'disabled' => { message => q|Disabled|, context => q|A label to indicate that the cron job is not ready to run.|,