From dc194bbacb12fd254f3683eeb65956fe08fc503d Mon Sep 17 00:00:00 2001 From: Duffy Gillman Date: Fri, 3 Sep 2010 20:41:51 +0000 Subject: [PATCH] SAK-18864 Abstracted the EventManager such that the old implementation can still be used if one prefers. Then created a Hibernate-backed version. Added a pager to the events log, then filtering to filter on date, type, or job name. Added other types of events and a message property to events in anticipation of adding the ability to log from jobs to the log git-svn-id: https://source.sakaiproject.org/svn/jobscheduler/branches/SAK-18864@82099 66ffb92e-73f9-0310-93c1-f5514f145a0a --- .../scheduler/events/TriggerEventManager.java | 2 +- .../events/TriggerEventManagerImpl.java | 4 +- .../TriggerEventManagerHibernateImpl.java | 14 +- jobscheduler/scheduler-events-model/pom.xml | 44 ++++++ .../TriggerEventHibernateImpl.hbm.xml | 28 ++++ .../events/hibernate/EnumUserType.java | 118 ++++++++++++++++ .../hibernate/TriggerEventEnumUserType.java | 21 +++ .../hibernate/TriggerEventHibernateImpl.java | 112 +++++++++++++++ .../tool/scheduler/bundle/Messages.properties | 28 +++- .../tool/app/scheduler/EventPager.java | 133 ++++++++++++++++-- .../tool/app/scheduler/SchedulerTool.java | 30 ++++ .../src/webapp/WEB-INF/faces-config.xml | 16 +++ .../src/webapp/scheduler/filter_events.jsp | 73 ++++++++++ .../src/webapp/scheduler/main.jsp | 25 ++-- 14 files changed, 614 insertions(+), 34 deletions(-) create mode 100644 jobscheduler/scheduler-events-model/pom.xml create mode 100644 jobscheduler/scheduler-events-model/src/hibernate/org/sakaiproject/scheduler/events/hibernate/TriggerEventHibernateImpl.hbm.xml create mode 100644 jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/EnumUserType.java create mode 100644 jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/TriggerEventEnumUserType.java create mode 100644 jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/TriggerEventHibernateImpl.java create mode 100644 jobscheduler/scheduler-tool/src/webapp/scheduler/filter_events.jsp diff --git a/jobscheduler/scheduler-api/src/java/org/sakaiproject/api/app/scheduler/events/TriggerEventManager.java b/jobscheduler/scheduler-api/src/java/org/sakaiproject/api/app/scheduler/events/TriggerEventManager.java index d1eb518c795b..1e860b330196 100644 --- a/jobscheduler/scheduler-api/src/java/org/sakaiproject/api/app/scheduler/events/TriggerEventManager.java +++ b/jobscheduler/scheduler-api/src/java/org/sakaiproject/api/app/scheduler/events/TriggerEventManager.java @@ -16,7 +16,7 @@ public interface TriggerEventManager public List getTriggerEvents (); - public List getTriggerEvents (Date after, Date before, String jobName, String triggerName, TriggerEvent.TRIGGER_EVENT_TYPE[] types); + public List getTriggerEvents (Date after, Date before, List jobs, String triggerName, TriggerEvent.TRIGGER_EVENT_TYPE[] types); public void purgeEvents (Date before); } diff --git a/jobscheduler/scheduler-component-shared/src/java/org/sakaiproject/component/app/scheduler/events/TriggerEventManagerImpl.java b/jobscheduler/scheduler-component-shared/src/java/org/sakaiproject/component/app/scheduler/events/TriggerEventManagerImpl.java index c95d5d29de54..ed61a83a4ed4 100644 --- a/jobscheduler/scheduler-component-shared/src/java/org/sakaiproject/component/app/scheduler/events/TriggerEventManagerImpl.java +++ b/jobscheduler/scheduler-component-shared/src/java/org/sakaiproject/component/app/scheduler/events/TriggerEventManagerImpl.java @@ -41,7 +41,7 @@ public List getTriggerEvents() return Collections.unmodifiableList(events); } - public List getTriggerEvents(Date after, Date before, String jobName, String triggerName, + public List getTriggerEvents(Date after, Date before, List jobs, String triggerName, TriggerEvent.TRIGGER_EVENT_TYPE[] types) { LinkedList @@ -53,7 +53,7 @@ public List getTriggerEvents(Date after, Date before, String jobNa continue; if (before != null && event.getTime().compareTo(before) == 1) continue; - if (jobName != null && !jobName.equals(event.getJobName())) + if (jobs != null && !jobs.contains(event.getJobName())) continue; if (triggerName != null && !triggerName.equals(event.getTriggerName())) continue; diff --git a/jobscheduler/scheduler-component-shared/src/java/org/sakaiproject/component/app/scheduler/events/hibernate/TriggerEventManagerHibernateImpl.java b/jobscheduler/scheduler-component-shared/src/java/org/sakaiproject/component/app/scheduler/events/hibernate/TriggerEventManagerHibernateImpl.java index 41d9a7200aba..0aa65088a01e 100644 --- a/jobscheduler/scheduler-component-shared/src/java/org/sakaiproject/component/app/scheduler/events/hibernate/TriggerEventManagerHibernateImpl.java +++ b/jobscheduler/scheduler-component-shared/src/java/org/sakaiproject/component/app/scheduler/events/hibernate/TriggerEventManagerHibernateImpl.java @@ -53,7 +53,7 @@ public List getTriggerEvents() return criteria.list(); } - public List getTriggerEvents(Date after, Date before, String jobName, String triggerName, TriggerEvent.TRIGGER_EVENT_TYPE[] types) + public List getTriggerEvents(Date after, Date before, List jobs, String triggerName, TriggerEvent.TRIGGER_EVENT_TYPE[] types) { final Session session = this.getSession(); @@ -64,23 +64,23 @@ public List getTriggerEvents(Date after, Date before, String jobNa if (after != null) { - criteria.add(Restrictions.gt("time", after)); + criteria.add(Restrictions.or(Restrictions.gt("time", after), Restrictions.eq("time", after))); } if (before != null) { - criteria.add(Restrictions.lt("time", before)); + criteria.add(Restrictions.or(Restrictions.lt("time", before), Restrictions.eq("time", before))); } - if (jobName != null) + if (jobs != null && !jobs.isEmpty()) { - criteria.add(Restrictions.eq("job", jobName)); + criteria.add(Restrictions.in("jobName", jobs)); } if (triggerName != null) { - criteria.add(Restrictions.eq("trigger", triggerName)); + criteria.add(Restrictions.eq("triggerName", triggerName)); } if (types != null) { - criteria.add(Restrictions.in("type", types)); + criteria.add(Restrictions.in("eventType", types)); } return criteria.list(); diff --git a/jobscheduler/scheduler-events-model/pom.xml b/jobscheduler/scheduler-events-model/pom.xml new file mode 100644 index 000000000000..bcc74a914c34 --- /dev/null +++ b/jobscheduler/scheduler-events-model/pom.xml @@ -0,0 +1,44 @@ + + + 4.0.0 + + + org.sakaiproject.scheduler + scheduler + 2.8-SNAPSHOT + + + Sakai Job Scheduler Events Model + org.sakaiproject.scheduler + scheduler-events-model + + The Sakai Foundation + http://sakaiproject.org/ + + 2003 + jar + + + shared + + + + + org.sakaiproject.scheduler + scheduler-api + + + org.hibernate + hibernate + + + + + + ${basedir}/src/hibernate + + + + + diff --git a/jobscheduler/scheduler-events-model/src/hibernate/org/sakaiproject/scheduler/events/hibernate/TriggerEventHibernateImpl.hbm.xml b/jobscheduler/scheduler-events-model/src/hibernate/org/sakaiproject/scheduler/events/hibernate/TriggerEventHibernateImpl.hbm.xml new file mode 100644 index 000000000000..7de85e5c63e3 --- /dev/null +++ b/jobscheduler/scheduler-events-model/src/hibernate/org/sakaiproject/scheduler/events/hibernate/TriggerEventHibernateImpl.hbm.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + delete from TriggerEventHibernateImpl as evt + where evt.time < ? + + + \ No newline at end of file diff --git a/jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/EnumUserType.java b/jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/EnumUserType.java new file mode 100644 index 000000000000..48736f41dd69 --- /dev/null +++ b/jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/EnumUserType.java @@ -0,0 +1,118 @@ +package org.sakaiproject.scheduler.events.hibernate; + +import org.hibernate.HibernateException; +import org.hibernate.usertype.UserType; + +import java.io.Serializable; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Types; + +/** + * This custom user type template was created from instructions found on the JBoss site at: + * http://community.jboss.org/wiki/UserTypeforpersistinganEnumwithaVARCHARcolumn + * + * User: duffy + * Date: Aug 26, 2010 + * Time: 4:48:50 PM + * To change this template use File | Settings | File Templates. + */ +public class EnumUserType> implements UserType +{ + private Class + myClass = null; + + private static final int[] + SQL_TYPES = {Types.VARCHAR}; + + protected EnumUserType (Class c) + { + myClass = c; + } + + public int[] sqlTypes() + { + return SQL_TYPES; + } + + public Class returnedClass() + { + return myClass; + } + + public Object nullSafeGet(ResultSet resultSet, String[] names, Object owner) + throws HibernateException, SQLException + { + String + name = resultSet.getString(names[0]); + E + result = null; + + if (!resultSet.wasNull()) + { + result = Enum.valueOf(myClass, name); + } + + return result; + } + + public void nullSafeSet(PreparedStatement preparedStatement, Object value, int index) + throws HibernateException, SQLException + { + if (null == value) + { + preparedStatement.setNull(index, Types.VARCHAR); + } + else + { + preparedStatement.setString(index, ((Enum)value).name()); + } + } + + public Object deepCopy(Object value) + throws HibernateException + { + return value; + } + + public boolean isMutable() + { + return false; + } + + public Object assemble(Serializable cached, Object owner) + throws HibernateException + { + return cached; + } + + public Serializable disassemble(Object value) + throws HibernateException + { + return (Serializable)value; + } + + public Object replace(Object original, Object target, Object owner) + throws HibernateException + { + return original; + } + + public int hashCode(Object x) + throws HibernateException + { + return x.hashCode(); + } + + public boolean equals(Object x, Object y) + throws HibernateException + { + if (x == y) + return true; + if (null == x || null == y) + return false; + + return x.equals(y); + } +} \ No newline at end of file diff --git a/jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/TriggerEventEnumUserType.java b/jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/TriggerEventEnumUserType.java new file mode 100644 index 000000000000..3f6c2bf9c090 --- /dev/null +++ b/jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/TriggerEventEnumUserType.java @@ -0,0 +1,21 @@ +package org.sakaiproject.scheduler.events.hibernate; + +import org.sakaiproject.api.app.scheduler.events.TriggerEvent; + +/** + * This custom user type was created based on the EnumUserType class modelled at: + * http://community.jboss.org/wiki/UserTypeforpersistinganEnumwithaVARCHARcolumn + * + * Created by IntelliJ IDEA. + * User: duffy + * Date: Aug 26, 2010 + * Time: 5:01:30 PM + * To change this template use File | Settings | File Templates. + */ +public class TriggerEventEnumUserType extends EnumUserType +{ + public TriggerEventEnumUserType() + { + super(TriggerEvent.TRIGGER_EVENT_TYPE.class); + } +} diff --git a/jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/TriggerEventHibernateImpl.java b/jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/TriggerEventHibernateImpl.java new file mode 100644 index 000000000000..2c9732c30144 --- /dev/null +++ b/jobscheduler/scheduler-events-model/src/java/org/sakaiproject/scheduler/events/hibernate/TriggerEventHibernateImpl.java @@ -0,0 +1,112 @@ +package org.sakaiproject.scheduler.events.hibernate; + +import org.sakaiproject.api.app.scheduler.events.TriggerEvent; + +import java.util.Date; + +/** + * Created by IntelliJ IDEA. + * User: duffy + * Date: Aug 26, 2010 + * Time: 5:04:12 PM + * To change this template use File | Settings | File Templates. + */ +public class TriggerEventHibernateImpl + implements TriggerEvent +{ + private TRIGGER_EVENT_TYPE + type; + private String + id, + jobName, + triggerName; + private Date + time; + private String + message; + + public TriggerEventHibernateImpl() + {} + + public void setId(String i) + { + id = i; + } + + public String getId() + { + return id; + } + + public void setEventType (TRIGGER_EVENT_TYPE t) + { + type = t; + } + + public TRIGGER_EVENT_TYPE getEventType() + { + return type; + } + + public void setJobName(String name) + { + jobName = name; + } + + public String getJobName() + { + return jobName; + } + + public void setTriggerName(String name) + { + triggerName = name; + } + + public String getTriggerName() + { + return triggerName; + } + + public void setTime(Date t) + { + time = t; + } + + public Date getTime() + { + return time; + } + + public void setMessage(String m) + { + message = m; + } + + public String getMessage() + { + return message; + } + + public int hashCode () + { + return id.hashCode(); + } + + public boolean equals (Object o) + { + if (!TriggerEventHibernateImpl.class.isAssignableFrom (o.getClass())) + return false; + + final TriggerEventHibernateImpl + that = (TriggerEventHibernateImpl)o; + + if (this == that) + return true; + + if (that == null) + return false; + + return (id.equals(that.id)); + } +} diff --git a/jobscheduler/scheduler-tool/src/bundle/org/sakaiproject/tool/scheduler/bundle/Messages.properties b/jobscheduler/scheduler-tool/src/bundle/org/sakaiproject/tool/scheduler/bundle/Messages.properties index 19afd17e78a3..b52ac6d3a46c 100644 --- a/jobscheduler/scheduler-tool/src/bundle/org/sakaiproject/tool/scheduler/bundle/Messages.properties +++ b/jobscheduler/scheduler-tool/src/bundle/org/sakaiproject/tool/scheduler/bundle/Messages.properties @@ -10,9 +10,9 @@ title_list=List title_bar=Scheduler Tool edit_trigger_for_job=Currently editing triggers for job: -bar_create_job=New_Job +bar_create_job=New Job bar_delete_jobs=Delete -bar_create_trigger=New_Trigger +bar_create_trigger=New Trigger bar_delete_triggers=Delete bar_jobs=Jobs bar_post=Post @@ -23,11 +23,11 @@ run_job=Run Job Now Confirmation: already_running=This job is already running. confirm_running_job_now=Are you sure you would like to run the job now? bar_return_jobs=Return_to_Jobs -bar_event_log=Event_Log +bar_event_log=Event Log -select_all=View_All_Events +select_all=View All Events select_today=View_Today's_Events -event_log=Event_Log +event_log=Event Log existing_job_name=Existing Job Name! @@ -46,6 +46,7 @@ trigger_name=Trigger Name: trigger_expression=Cron Expression: job_class=Class: job_type=Type: +message=Message: return_jobs=Return to Jobs return_triggers=Return to Triggers @@ -64,4 +65,19 @@ properties_desc_header=Description properties_required=A required property was not configured edit_trigger_properties=Configure Trigger Properties -trigger_properties_instructions=This job is configurable. The properties below are set with the defaults for this type of job. If you would like to override them for this trigger edit the values below before clicking 'Submit'. Otherwise, click 'Submit' to accept the defaults and continue. \ No newline at end of file +trigger_properties_instructions=This job is configurable. The properties below are set with the defaults for this type of job. If you would like to override them for this trigger edit the values below before clicking 'Submit'. Otherwise, click 'Submit' to accept the defaults and continue. + +filterEvents=Filter Events +filter_current=Current filter +filter_title=Trigger Event Filters +filter_instructions=To filter the events shown in the event log fill in the form below and click "Set Filters". All filters will be reset and the entire log will be shown if you click "Clear Filters". +filter_date_title=Event Dates +filter_date_instructions=Set the beginning and ending date of the events to show. Events will be filtered before or after midnight of the dates you select. +filter_before_title=Events Before Date +filter_after_title=Events After Date +filter_job_instructions=Select the specific jobs for which you would like to see events. +filter_job_title=Jobs +filter_type_instructions=Select the event types you would like to see. +filter_type_title=Event Types +setFilters=Set Event Filters +clearFilters=Clear Event Filters \ No newline at end of file diff --git a/jobscheduler/scheduler-tool/src/java/org/sakaiproject/tool/app/scheduler/EventPager.java b/jobscheduler/scheduler-tool/src/java/org/sakaiproject/tool/app/scheduler/EventPager.java index 49441ed84b1d..a395448c1e00 100644 --- a/jobscheduler/scheduler-tool/src/java/org/sakaiproject/tool/app/scheduler/EventPager.java +++ b/jobscheduler/scheduler-tool/src/java/org/sakaiproject/tool/app/scheduler/EventPager.java @@ -5,8 +5,13 @@ import javax.faces.event.PhaseId; import javax.faces.event.ValueChangeEvent; +import java.text.DateFormat; +import java.text.ParseException; import java.util.Date; +import java.util.HashMap; +import java.util.LinkedList; import java.util.List; +import java.util.Map; /** * Created by IntelliJ IDEA. @@ -17,28 +22,44 @@ */ public class EventPager { + private static String[] + EVENT_TYPE_STRINGS = {"FIRED", "COMPLETED", "INFO", "DEBUG", "ERROR"}; private TriggerEventManager evtManager = null; private Date after = null, before = null; + private List + jobs = new LinkedList(); private String - jobName = null, triggerName = null; - private TriggerEvent.TRIGGER_EVENT_TYPE - types[] = null; private int first = 0, numRows = 10; + private boolean + filterEnabled = false; + private HashMap + selectedEventTypes = new HashMap(); - public String getJobName() + public EventPager() { - return jobName; + setAllEventTypes(true); } - public void setJobName(String jobName) + public Map getSelectedEventTypes() { - this.jobName = jobName; + return selectedEventTypes; + } + + public List getJobs() + { + return jobs; + } + + public void setJobs(List jobs) + { + this.jobs.clear(); + this.jobs.addAll(jobs); } public String getTriggerName() @@ -51,14 +72,99 @@ public void setTriggerName(String triggerName) this.triggerName = triggerName; } + public void setFilterEnabled (boolean filter) + { + filterEnabled = filter; + + if (!filterEnabled) + { + after = null; + before = null; + jobs.clear(); + triggerName = null; + setAllEventTypes(true); + } + + first = 0; + } + + public boolean isFilterEnabled() + { + return filterEnabled; + } + + public String[] getEventTypes() + { + return EVENT_TYPE_STRINGS; + } + public TriggerEvent.TRIGGER_EVENT_TYPE[] getTypes() { - return types; + LinkedList + evtList = new LinkedList(); + + for (String type : selectedEventTypes.keySet()) + { + Boolean + selected = selectedEventTypes.get(type); + + if (selected != null && selected.booleanValue()) + { + if ("FIRED".equals(type)) + evtList.add(TriggerEvent.TRIGGER_EVENT_TYPE.FIRED); + else if ("COMPLETE".equals(type)) + evtList.add(TriggerEvent.TRIGGER_EVENT_TYPE.COMPLETE); + else if ("INFO".equals(type)) + evtList.add(TriggerEvent.TRIGGER_EVENT_TYPE.INFO); + else if ("ERROR".equals(type)) + evtList.add(TriggerEvent.TRIGGER_EVENT_TYPE.ERROR); + else if ("DEBUG".equals(type)) + evtList.add(TriggerEvent.TRIGGER_EVENT_TYPE.DEBUG); + } + } + + TriggerEvent.TRIGGER_EVENT_TYPE[] + typeArr = new TriggerEvent.TRIGGER_EVENT_TYPE[evtList.size()]; + + evtList.toArray(typeArr); + + return typeArr; + } + + private void setAllEventTypes(boolean b) + { + selectedEventTypes.put("FIRED", new Boolean(b)); + selectedEventTypes.put("COMPLETED", new Boolean(b)); + selectedEventTypes.put("INFO", new Boolean(b)); + selectedEventTypes.put("DEBUG", new Boolean(b)); + selectedEventTypes.put("ERROR", new Boolean(b)); } public void setTypes(TriggerEvent.TRIGGER_EVENT_TYPE[] types) { - this.types = types; + setAllEventTypes(false); + + for (TriggerEvent.TRIGGER_EVENT_TYPE type : types) + { + switch (type) + { + case FIRED: + selectedEventTypes.put("FIRED", Boolean.TRUE); + break; + case COMPLETE: + selectedEventTypes.put("COMPLETE", Boolean.TRUE); + break; + case INFO: + selectedEventTypes.put("INFO", Boolean.TRUE); + break; + case ERROR: + selectedEventTypes.put("ERROR", Boolean.TRUE); + break; + case DEBUG: + selectedEventTypes.put("DEBUG", Boolean.TRUE); + break; + } + } } public Date getAfter() @@ -138,7 +244,14 @@ else if (phaseId.equals(PhaseId.UPDATE_MODEL_VALUES)) public List getEvents() { - return getTriggerEventManager().getTriggerEvents(after, before, jobName, triggerName, types); + if (isFilterEnabled()) + { + return getTriggerEventManager().getTriggerEvents(after, before, jobs, triggerName, getTypes()); + } + else + { + return getTriggerEventManager().getTriggerEvents(); + } } } diff --git a/jobscheduler/scheduler-tool/src/java/org/sakaiproject/tool/app/scheduler/SchedulerTool.java b/jobscheduler/scheduler-tool/src/java/org/sakaiproject/tool/app/scheduler/SchedulerTool.java index 6412c2e595f6..aa9b132bab51 100644 --- a/jobscheduler/scheduler-tool/src/java/org/sakaiproject/tool/app/scheduler/SchedulerTool.java +++ b/jobscheduler/scheduler-tool/src/java/org/sakaiproject/tool/app/scheduler/SchedulerTool.java @@ -28,6 +28,7 @@ import javax.faces.component.UIComponent; import javax.faces.context.FacesContext; import javax.faces.event.ActionEvent; +import javax.faces.model.SelectItem; import javax.faces.validator.ValidatorException; import org.apache.commons.logging.Log; @@ -1374,5 +1375,34 @@ public Map getBeanJobs() { } return beanJobs; } + + public String processSetFilters() + { + getEventPager().setFilterEnabled(true); + + return "events"; + } + + public String processClearFilters() + { + getEventPager().setFilterEnabled(false); + + return "events"; + } + + public List getScheduledJobs() throws SchedulerException + { + ArrayList + scheduledJobs = new ArrayList (); + String[] + jArr = schedulerManager.getScheduler().getJobNames(Scheduler.DEFAULT_GROUP); + + for (int i = 0; i < jArr.length; i++) + { + scheduledJobs.add(new SelectItem(jArr[i])); + } + + return scheduledJobs; + } } diff --git a/jobscheduler/scheduler-tool/src/webapp/WEB-INF/faces-config.xml b/jobscheduler/scheduler-tool/src/webapp/WEB-INF/faces-config.xml index 9f3489ddfabb..549ce5a25951 100644 --- a/jobscheduler/scheduler-tool/src/webapp/WEB-INF/faces-config.xml +++ b/jobscheduler/scheduler-tool/src/webapp/WEB-INF/faces-config.xml @@ -38,12 +38,28 @@ /scheduler/main.jsp + + events + /scheduler/main.jsp + jobs /scheduler/jobs.jsp + + filter + /scheduler/filter_events.jsp + + + /scheduler/filter_events.jsp + + events + /scheduler/main.jsp + + + /scheduler/jobs.jsp diff --git a/jobscheduler/scheduler-tool/src/webapp/scheduler/filter_events.jsp b/jobscheduler/scheduler-tool/src/webapp/scheduler/filter_events.jsp new file mode 100644 index 000000000000..31747c89f07f --- /dev/null +++ b/jobscheduler/scheduler-tool/src/webapp/scheduler/filter_events.jsp @@ -0,0 +1,73 @@ +<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %> +<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %> +<%@ taglib uri="http://sakaiproject.org/jsf/sakai" prefix="sakai" %> +<%@ include file="security_static_include.jsp"%> + + + + + + + + + + + + + + + + + +

+ + + +

+ +

+
+

+ +

+
+

+ +

+ + +

+ +

+
+ + + + +

+ +

+
+ + + + + + + + +
+ + + + + + +
+
+
\ No newline at end of file diff --git a/jobscheduler/scheduler-tool/src/webapp/scheduler/main.jsp b/jobscheduler/scheduler-tool/src/webapp/scheduler/main.jsp index 979a0f7eda2b..81900f111849 100644 --- a/jobscheduler/scheduler-tool/src/webapp/scheduler/main.jsp +++ b/jobscheduler/scheduler-tool/src/webapp/scheduler/main.jsp @@ -21,14 +21,17 @@ - - + + + + + + + + + +