diff --git a/agent/ui/AgentJobView.html b/agent/ui/AgentJobView.html
new file mode 100644
index 0000000..d514aa2
--- /dev/null
+++ b/agent/ui/AgentJobView.html
@@ -0,0 +1,140 @@
+
+
+
+
+
+
+
+ loops
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Here you will get an overview of the current jobs registered in the agent system
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/agent/ui/AgentJobViewDetail.html b/agent/ui/AgentJobViewDetail.html
new file mode 100644
index 0000000..f04aaa5
--- /dev/null
+++ b/agent/ui/AgentJobViewDetail.html
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+ loops
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Here you will get an overview of the current jobs registered in the agent system
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/agent/ui/AgentOutlookMailView.html b/agent/ui/AgentOutlookMailView.html
new file mode 100644
index 0000000..18b4925
--- /dev/null
+++ b/agent/ui/AgentOutlookMailView.html
@@ -0,0 +1,137 @@
+
+
+
+
+
+
+
+ loops
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ All currently available Outlook Mails collected by the loops agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/agent/ui/AgentStart.html b/agent/ui/AgentStart.html
new file mode 100644
index 0000000..ec9d95d
--- /dev/null
+++ b/agent/ui/AgentStart.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+ loops
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ This page contains some information about the loops agent UI. On the left side you can find the
+ navigation panel where you can choose between a general job overview to be displayed, add a job or change the
+ logging options. Also below this navigation menue you will find a button which switches the User mode between
+ Professional and Simple Mode . This button is to be found on this start page only.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/agent/ui/StartUpAgentUI.tac.py b/agent/ui/StartUpAgentUI.tac.py
new file mode 100644
index 0000000..82117ff
--- /dev/null
+++ b/agent/ui/StartUpAgentUI.tac.py
@@ -0,0 +1,26 @@
+#-------------------------------------------------
+# StartUpAgentUI.tac.py
+# start the twisted webserver and initialize the
+# nevow framework/application
+# author: Juergen Menzinger
+# version: 01.alpha
+# start with twistd.py -noy StartUpAgentUI.tac.py
+# requires AgentStart.html
+# AgentJobView.html
+# AgentJobViewDetail.html
+# AgentOutlookMailView.html
+#-------------------------------------------------
+
+
+from twisted.application import internet
+from twisted.application import service
+from nevow import appserver
+import web
+import sys, os, socket
+
+
+application = service.Application('loops agent')
+site = appserver.NevowSite(web.AgentHome())
+webServer = internet.TCPServer(8080, site)
+webServer.setServiceParent(application)
+
diff --git a/agent/ui/css/base.css b/agent/ui/css/base.css
new file mode 100644
index 0000000..ff50e70
--- /dev/null
+++ b/agent/ui/css/base.css
@@ -0,0 +1,99 @@
+/*
+ $Id: base.css 1779 2007-06-07 19:37:44Z helmutm $
+
+ based on http://www.tjkdesign.com/articles/liquid/4.asp
+
+*/
+
+body {
+ min-width:640px;
+ margin: 0;
+ padding: 0;
+ font: 9pt Verdana, Tahoma, Arial, Helvetica, sans-serif;
+ background-color: white;
+ color: #000040;
+}
+
+#global,#menu,#sub-section,#footer {
+ overflow: hidden;
+ display: inline-block;
+}
+
+#content {
+ display: inline-block;
+}
+
+#global,#footer {width:100%}
+#menu,#content,#sub-section {float:left}
+#menu {width:20%}
+#content {width:62%}
+#sub-section {width:17%}
+#footer {clear:left}
+
+/* more general stuff */
+
+.top image {
+ margin-top: -1px;
+}
+
+div.box {
+ margin: 12px 12px 8px 10px;
+ border: 1px solid #ccc;
+ border-bottom: none;
+}
+
+div.box h4 {
+ font: 110% Verdana, Tahoma, Arial, Helvetica, sans-serif;
+ color: #000040;
+ border: none;
+ border-bottom: 1px solid #ccc;
+ padding: 4px;
+ padding-top: 1px;
+ padding-bottom: 3px;
+ background-color: #ddd;
+ height: auto;
+}
+
+table.listing {
+ margin: 1px;
+ margin-top: 6px;
+
+}
+
+table.listing th {
+ font-family: Verdana, Tahoma, Arial, Helvetica, sans-serif;
+ color: #000040;
+}
+
+.footer {
+ text-align: center;
+ border-top: 1px solid #ccc;
+ border-bottom: none;
+ margin-top: 12px;
+ padding-top: 6px;
+}
+
+.itemViews {
+ border-bottom-width: 2px;
+}
+
+.button {
+ margin: 1em 0 1em 0;
+}
+
+.button a {
+ padding: 2px 4px 2px 4px;
+ background-color: #e8e8e8;
+ text-decoration: None;
+ color: Black;
+ border-width: 2px;
+ border-style: solid;
+ border-color: #f4f4f4 #989898 #989898 #f4f4f4;
+}
+
+pre {
+ background-color: #f4f4f4;
+}
+
+#footer { border-bottom: none; }
+
diff --git a/agent/ui/css/custom.css b/agent/ui/css/custom.css
new file mode 100644
index 0000000..15b15c1
--- /dev/null
+++ b/agent/ui/css/custom.css
@@ -0,0 +1,24 @@
+/*
+ $Id: custom.css 1302 2006-08-17 15:21:10Z helmutm $
+
+ cyberconcepts specialties
+
+*/
+
+body {
+ color: #242424;
+}
+
+a {
+ text-decoration: none;
+ color: #344080;
+ background-color: transparent;
+}
+
+.top {
+ border-bottom: 1px solid #d0d0d0;
+ margin-bottom: 2px;
+ /*background-image: url('bg_cyberview.gif')
+ height: 75px;*/
+}
+
diff --git a/agent/ui/css/loops.css b/agent/ui/css/loops.css
new file mode 100644
index 0000000..5535bbd
--- /dev/null
+++ b/agent/ui/css/loops.css
@@ -0,0 +1,138 @@
+/*
+ $Id: loops.css 1729 2007-05-13 08:56:47Z helmutm $
+
+ settings specific for view / node objects
+
+*/
+
+a[href]:hover {
+ text-decoration: none;
+ color: #803000;
+}
+
+pre {
+ overflow: scroll;
+ max-height: 35em;
+}
+
+.box div.body div.even {
+ background-color: #f4f4f4;
+}
+
+.box {
+ margin: 12px;
+}
+
+#body {
+ margin-left: 5px;
+}
+
+/*.content-1 h1 { */
+h1 {
+ font-size: 160%;
+ font-weight: bold;
+}
+
+.content-2 h1, h2 {
+ font-size: 140%;
+}
+
+.content-3 h1, .content-2 h2, h3 {
+ font-size: 130%;
+ font-weight: bold;
+}
+
+.content-4 h1, .content-3 h2, .content-2 h3, .content-1 h4 {
+ font-size: 120%;
+}
+
+.content-5 h1, .content-4 h2, .content-3 h3, content-2 h4 {
+ font-size: 100%;
+ border: none;
+}
+
+.subcolumn {
+ display: inline;
+ float: left;
+}
+
+.box {
+ margin: 5px;
+ padding: 6px;
+ padding-top: 0;
+}
+
+.box h1, .box h2, .box h3 {
+ border-bottom: None;
+}
+
+div.menu-1, div.menu-2 {
+ border-top: 1px solid #eeeeee;
+ font-weight: bold;
+}
+
+.box div.body div.menu-3 {
+ border-top: none;
+ padding-left: 1.5em;
+}
+
+.box div.body div.menu-4 {
+ padding-left: 3em;
+ font-size: 90%
+}
+
+.flow-left {
+ float: left;
+}
+
+.flow-right {
+ float: right;
+}
+
+div.image {
+ margin-top: 10px;
+ margin-right: 5px;
+}
+
+
+/* search stuff */
+
+.searchForm input.button, input.submit {
+ padding: 2px;
+}
+
+.searchForm input.submit {
+ font-weight: bold;
+}
+
+/* dojo stuff */
+
+/*.dojoComboBox {
+ width: 200px;
+}*/
+
+.dojoDialog {
+ background: #eee;
+ border: 1px solid #999;
+ -moz-border-radius: 5px;
+ padding: 4px;
+}
+
+.dojoDialog th {
+ font-size: 120%;
+ padding: 0 5px 8px 5px;
+}
+
+.dojoDialog .headline {
+ font-weight: bold;
+}
+
+.dojoDialog input.text {
+ width: 100%;
+ margin-right: 10px;
+}
+
+.dojoDialog input.submit {
+ font-weight: bold;
+}
+
diff --git a/agent/ui/css/print.css b/agent/ui/css/print.css
new file mode 100644
index 0000000..6232184
--- /dev/null
+++ b/agent/ui/css/print.css
@@ -0,0 +1,13 @@
+/*
+ $Id: print.css 1340 2006-09-12 08:39:40Z helmutm $
+
+*/
+
+.top, #header, #menu, #sub-section, #footer {
+ display: none;
+}
+
+#content {
+ width: 100%;
+ color: Black;
+}
diff --git a/agent/ui/css/zope3_tablelayout.css b/agent/ui/css/zope3_tablelayout.css
new file mode 100644
index 0000000..70aceb6
--- /dev/null
+++ b/agent/ui/css/zope3_tablelayout.css
@@ -0,0 +1,662 @@
+/*
+** Zope3 style sheet for CSS2-capable browsers.
+** For future skin see zope.app.boston.
+*/
+
+/*
+* { border: 1px dotted red }
+*/
+
+
+/* Basic Elements */
+
+body {
+ font: 85% Helvetica, Arial, sans-serif;
+ background: White;
+ color: Black;
+ margin: 0;
+ padding: 0;
+/* These work in IE only, changes the look of the scrollbar + textareas */
+ scrollbar-base-color: White;
+ scrollbar-highlight-color: White;
+ scrollbar-track-color: #F8F8F8;
+ scrollbar-darkshadow-color: #F8F8F8;
+ scrollbar-3dlight-color: #369;
+ scrollbar-shadow-color: #369;
+ scrollbar-arrow-color: Black;
+}
+
+table {
+ border-collapse: collapse;
+ font-size: 100%;
+}
+
+a {
+ text-decoration: none;
+ color: #369;
+ background-color: transparent;
+}
+
+a[href]:active {
+ text-decoration: underline;
+}
+
+img {
+ border: none;
+ vertical-align: middle;
+}
+
+p {
+ margin: 0.5em 0em 1em 0em;
+ line-height: 1.5em;
+}
+
+p a:visited {
+ color: Purple;
+ background-color: transparent;
+}
+
+p a:active {
+ color: Red;
+ background-color: transparent;
+}
+
+p img {
+ border: 0;
+ margin: 0;
+}
+
+
+hr {
+ clear: both;
+ height: 1px;
+ color: #369;
+ background-color: transparent;
+}
+
+
+h1, h2, h3, h4, h5, h6 {
+ color: Black;
+ clear: left;
+ font: 100% bold Verdana, Helvetica, Arial, sans-serif;
+ margin: 0;
+ padding-top: 0.5em;
+ border-bottom: 1px solid #369;
+}
+
+h1 {
+ font-size: 160%;
+}
+
+h2 {
+ font-size: 150%;
+}
+
+h3 {
+ font-size: 140%;
+}
+
+h4 {
+ font-size: 120%;
+}
+
+h5 {
+ font-size: 100%;
+}
+
+h6 {
+ font-size: 80%;
+}
+
+ul {
+ line-height: 1.5em;
+ /* list-style-image: url("bullet.gif"); */
+ margin-left: 2em;
+ padding:0;
+}
+
+ol {
+ line-height: 1.5em;
+ margin-left: 2em;
+ padding:0;
+}
+
+dl {
+}
+
+dt {
+ font-weight: bold;
+}
+
+dd {
+ line-height: 1.5em;
+ margin-bottom: 1em;
+}
+
+
+fieldset {
+ border: 1px solid #A0A0A0;
+ /*
+ margin: 2em 0em 1em 0em;
+ padding: 1em 0em;
+ */
+ margin: 0em 0em 2em 0em;
+ padding: 0 1em 1em 1em;
+}
+
+legend {
+ background: White;
+ padding: 0.5em;
+}
+
+
+form {
+ border: none;
+ margin: 0;
+}
+
+textarea {
+ color: Black;
+ width: 88%;
+ padding: 0.1em;
+}
+
+input {
+ font: normal 100% Verdana, Helvetica, Arial, sans-serif;
+ color: Black;
+ vertical-align: middle;
+ margin-bottom: 1px; /* IE bug fix */
+ padding: 0.1em;
+}
+
+select {
+ font: normal 100% Verdana, Helvetica, Arial, sans-serif;
+ vertical-align: top;
+}
+
+abbr, acronym, .explain {
+ border-bottom: 1px dotted Black;
+ color: Black;
+ background-color: transparent;
+ cursor: help;
+}
+
+q {
+ font-family: Times, "Times New Roman", serif;
+ font-style: italic;
+ font-size: 120%;
+}
+
+blockquote {
+ font-family: Times, "Times New Roman", serif;
+ font-style: italic;
+ font-size: 120%;
+}
+
+code {
+ font-size: 120%;
+ color: Black;
+ background-color: #CCCCCC;
+}
+
+pre {
+ font-size: 120%;
+ padding: 1em;
+ border: 1px solid #A0A0A0;
+ color: Black;
+ background-color: #CCCCCC;
+}
+
+.netscape4 {
+ display: none;
+}
+
+/* layout table
+*/
+
+#layout {
+ width: 100%;
+ table-layout: auto;
+ font-size: 100%;
+ border-collapse: collapse;
+ padding: 0px;
+ margin: 0px;
+}
+
+#layout td {
+ vertical-align: top;
+}
+
+#layout td.global {
+ width: 100%;
+}
+
+#layout td.navigators {
+ width: 200px;
+}
+
+#layout td.workspace {
+}
+
+
+/* Styles for xmltree
+*/
+
+#navtreecontents {
+ padding-right: 35px;
+}
+
+#navtreecontents a {
+ cursor: pointer;
+ height: 20px;
+}
+
+#navtreecontents loading {
+ display: block;
+ padding-left: 31px;
+ height: 18px;
+}
+
+#navtreecontents expand {
+ background-repeat: no-repeat;
+ padding-left: 14px;
+ display: inline;
+ cursor: pointer;
+}
+
+#navtreecontents icon {
+ background-repeat: no-repeat;
+ padding-left: 20px;
+ display: inline;
+ cursor: auto;
+}
+
+#navtreecontents collection {
+ display: block;
+ margin-left: 10px;
+/* border: red solid 1pt; */
+ height: auto;
+}
+
+
+/* Structural elements
+*/
+
+#top {
+ border-bottom: 0.1em solid black;
+}
+
+#top #userDetails {
+ float:right;
+ margin-top: 1.2em;
+ padding-right: 0.5em;
+}
+
+div#action {
+ height: 24px;
+ width: 100%;
+ background-color: #336699;
+}
+
+div#action ul {
+ line-height: 24px;
+ color: #FFF;
+ white-space: nowrap;
+ float: right;
+ margin: 0px;
+ padding: 0px 5px 0px 0px;
+}
+
+div#action li {
+ list-style-type: none;
+ display: inline;
+}
+
+div#action li a {
+ color: #FFF;
+ text-decoration: none;
+ border-left: 1px dashed white;
+ padding: 0px 5px;
+}
+
+div#action li a:link {
+ color: #FFF;
+}
+
+div#action li a:hover {
+ color: black;
+ background-color: white;
+}
+
+#breadcrumbs {
+ margin: 0;
+ padding: 5px 5px 5px 5px;
+}
+
+#navigation {
+ width: 200px;
+ vertical-align: top;
+ padding: 0px;
+ margin: 0px;
+}
+
+#navigators {
+ padding: 10px 20px 0px 5px;
+}
+
+/* slot boxes
+*/
+
+div.box {
+ background: #CCCCCC;
+ border-right: 1px solid #CCCCCC;
+ border-left: 1px solid #CCCCCC;
+ margin-bottom: 10px;
+ padding: 0px;
+}
+
+div.box h4 {
+ background: #CCCCCC;
+ border: 1px solid #CCCCCC;
+ border-style: solid solid none solid;
+ color: #808080;
+ padding: 0px 5px;
+ display: block;
+ height: 22px;
+}
+
+.box div.body {
+ background: white;
+ border-bottom: 1px solid #CCCCCC;
+}
+
+.box div.body div {
+ color: #777777;
+ padding: 2px 0px 5px 5px;
+ margin: 0px;
+}
+
+.box div.treebody {
+ background: white;
+ border-bottom: 1px solid #CCCCCC;
+}
+
+.box div.treebody table {
+ margin: 2px;
+}
+
+.box div.body div.tip {
+ color: #B30000;
+ padding: 2px 0px 5px 5px;
+}
+
+.box div.body div.even {
+ background: #EBEBE2;
+ padding: 4px;
+}
+
+.box div.body div.odd {
+ padding: 4px;
+}
+
+.box .content {
+ padding: 0.5em;
+}
+
+.box h1,
+.box h2,
+.box h3,
+.box h4 {
+ margin: 0;
+}
+
+
+#content {
+}
+
+#context_information {
+ padding-top: 1em;
+ width: 15%;
+ float: left;
+ padding-left: 0.5em;
+}
+
+#workspace {
+ width: 100%;
+}
+
+#helpers {
+}
+
+#inspectors {
+}
+
+#footer {
+ border-bottom: 1px solid black;
+ float: left;
+ clear: both;
+}
+
+input.textType {
+ width: 88%; /* Same as textarea */
+}
+
+input.editcheck {
+ float:left;
+ position:relative;
+ top:1em;
+}
+
+div.row {
+ padding-top: 1em;
+}
+
+/*
+div.label {
+ #clear: both;
+ padding-top: 10px;
+}
+*/
+
+/* div.row div.field doesn't appear to be selecting. div.row div
+ is a workaround */
+/* This seems to work in Firefox 1.0 and IE6. */
+
+div.row div.field {
+ clear: left;
+ padding-top: 1px;
+}
+
+div.row div.label {
+ background: #369;
+ color: #fff;
+ padding: 0.1em 0.5em 0.1em 0.5em; /* Same as .itemViews */
+ border: 1px solid #369; /* Same as .itemViews */
+ margin: 0;
+ float: left;
+ clear: both;
+}
+
+div.row span.error {
+ background: red;
+ color: white;
+ padding: 0.1em 0.5em 0.1em 0.5em; /* Same as .itemViews */
+ border: 1px solid red; /* Same as .itemViews */
+ margin: 0;
+ float: left;
+ clear: both;
+}
+/*
+div.row div.error:before {
+ content: "\2190 ";
+}
+*/
+
+#metadata .label {
+ font-size: 80%;
+}
+
+.itemViews {
+ background: transparent;
+ border-collapse: collapse;
+ border-bottom: 1px solid #369;
+ padding-top: 1px;
+ padding-bottom: 1px;
+ padding-left: 1em;
+ margin-top: 0.8em;
+ white-space: nowrap;
+}
+
+.itemViews a {
+ background: transparent;
+ border: 1px solid #369;
+ color: Black;
+ font-weight: normal;
+ margin-right: 0.5em;
+ padding: 0.1em 0.5em 0.1em 0.5em;
+}
+
+.itemViews a.selected {
+ background: #369;
+ border-bottom: #369 1px solid;
+ color: White;
+ font-weight: normal;
+}
+
+
+.itemViews a:hover {
+ background-color: #369;
+ color: White;
+}
+
+#viewspace {
+ border-collapse: collapse;
+ margin: 0;
+}
+
+table.listingdescription, table.listing {
+ /* The default table for document listings. Contains name, document types, modification times etc in a file-browser-like fashion */
+ border-collapse: collapse;
+ border-left: 1px solid #CCCCCC;
+ border-bottom: 1px solid #CCCCCC;
+ margin: 1em 0em 1em 0em;
+/* clear: both; */
+}
+
+table.listingdescription {
+ width: 100%;
+}
+
+table.listingdescription th, table.listing th {
+ background: #CCCCCC;
+ border-top: 1px solid #CCCCCC;
+ border-bottom: 1px solid #CCCCCC;
+ border-right: 1px solid #CCCCCC;
+ color: #808080;
+ font-weight: normal;
+ padding: 0em 1em 0em 1em;
+ white-space: nowrap;
+}
+
+table.listingdescription td.top, table.listing td.top {
+ border-left: 1px solid White;
+ border-top: 1px solid White ! important;
+ border-right: 1px solid White ! important;
+ text-align: right ! important;
+ padding: 0em 0em 1em 0em;
+ /* insane IE row bug workaround */
+ position: relative;
+ left: -1px;
+ top: -1px;
+}
+
+table.listingdescription tr.odd, table.listing tr.odd {
+ /*every second line should be shaded */
+ background: White;
+}
+
+table.listingdescription tr.even, table.listing tr.even {
+ background: #F8F8F8;
+}
+
+table.listing td {
+ border-right: 1px solid #CCCCCC;
+ padding: 0em 0.3em;
+ text-align: left;
+ white-space: nowrap;
+}
+
+
+table.listingdescription img, table.listing img {
+ vertical-align: middle;
+}
+
+table.listingdescription td {
+ border-right: 1px solid #CCCCCC;
+ padding: 5px;
+ text-align: left;
+}
+
+
+/*colorize the matrix table used in grant.html*/
+table.matrix td.default {
+ background: green;
+}
+
+
+table.matrix td.changed {
+ background: red;
+}
+
+
+div.spacer {
+ clear: both;
+}
+
+
+.registrationSummary {
+ margin-left: 2em;
+ margin-bottom: 1em;
+}
+.registrationSummary .usageSummary {
+ font-weight: bold;
+}
+.registrationSummary .modificationLink {
+ display: block;
+}
+
+
+div.message {
+ background: #FFCE7B;
+ border: 1px solid #FFA500;
+ color: Black;
+ font: bold 80% Verdana, Helvetica, Arial, sans-serif;
+ margin: 2em 0em 1em 0em;
+ padding: 0.5em 1em;
+ vertical-align: middle;
+}
+
+div.message a {
+ color: Black;
+}
+
+/* Style for page error divs. Use this for displaying errors for a
+ page as a whole.
+ */
+div.page_error {
+ background: #FFCE7B;
+ font: bold 80% Verdana, Helvetica, Arial, sans-serif;
+ padding: 0.5em 1em;
+ vertical-align: middle;
+}
+
+div.bug {
+ background: #FFCE7B;
+ border: 1px solid #FFA500;
+ color: Black;
+ font: bold 80% Verdana, Helvetica, Arial, sans-serif;
+ margin: 2em 1em 1em 0em;
+ padding: 0.5em 1em;
+ vertical-align: middle;
+}
+
diff --git a/agent/ui/images/favicon.png b/agent/ui/images/favicon.png
new file mode 100644
index 0000000..1fc7485
Binary files /dev/null and b/agent/ui/images/favicon.png differ
diff --git a/agent/ui/images/loops_logo2.png b/agent/ui/images/loops_logo2.png
new file mode 100644
index 0000000..2c0af50
Binary files /dev/null and b/agent/ui/images/loops_logo2.png differ
diff --git a/agent/ui/joblist.txt b/agent/ui/joblist.txt
new file mode 100644
index 0000000..ae42774
--- /dev/null
+++ b/agent/ui/joblist.txt
@@ -0,0 +1,4 @@
+FileSysCont_1234;C:\Documents;*.doc;daily;transfer(http:loops.sampleserver.de)
+MailCrawl_2121;Outlook(Account_Root);daily;transfer(http:loops.sampleserver.de)
+MailCrawl_4040;Outlook(Subj:Update);20s;transfer(http:loops.sampleserver.de)
+FileSysCont_8797;C:\Tmp;size<100kByte;transfer(http:loops.sampleserver.de)
\ No newline at end of file
diff --git a/agent/ui/loops.js b/agent/ui/loops.js
new file mode 100644
index 0000000..bb7751e
--- /dev/null
+++ b/agent/ui/loops.js
@@ -0,0 +1,126 @@
+/* $Id: loops.js 1667 2007-03-26 10:43:15Z helmutm $ */
+
+function openEditWindow(url) {
+ zmi = window.open(url, 'zmi');
+ zmi.focus();
+ return false;
+}
+
+function focusOpener() {
+ if (typeof(opener) != 'undefined' && opener != null) {
+ opener.location.reload();
+ opener.focus();
+ }
+}
+
+function replaceFieldsNode(targetId, typeId, url) {
+ token = dojo.byId(typeId).value;
+ uri = url + '?form.type=' + token;
+ dojo.io.updateNode(targetId, uri);
+}
+
+function submitReplacing(targetId, formId, actionUrl) {
+ dojo.io.updateNode(targetId, {
+ url: actionUrl,
+ formNode: dojo.byId(formId),
+ method: 'post'
+ });
+ return false;
+}
+
+function inlineEdit(id, saveUrl) {
+ var iconNode = dojo.byId('inlineedit_icon');
+ iconNode.style.visibility = 'hidden';
+ editor = dojo.widget.createWidget('Editor',
+ {items: ['save', '|', 'formatblock', '|',
+ 'insertunorderedlist', 'insertorderedlist', '|',
+ 'bold', 'italic', '|', 'createLink', 'insertimage'],
+ saveUrl: saveUrl,
+ //closeOnSave: true,
+ htmlEditing: true
+ //onClose: function() {
+ /* onSave: function() {
+ this.disableToolbar(true);
+ iconNode.style.visibility = 'visible';
+ //window.location.reload();
+ }*/
+ }, dojo.byId(id));
+ editor._save = function (e) {
+ if (!this._richText.isClosed) {
+ if (this.saveUrl.length) {
+ var content = {};
+ this._richText.contentFilters = [];
+ content[this.saveArgName] = this.getHtml();
+ content['version'] = 'this';
+ dojo.io.bind({method:this.saveMethod,
+ url:this.saveUrl,
+ content:content,
+ handle:function(type, data, ti, kwargs) {
+ location.reload(false);
+ }
+ }); //alert('save');
+ } else {
+ dojo.debug("please set a saveUrl for the editor");
+ }
+ if (this.closeOnSave) {
+ this._richText.close(e.getName().toLowerCase() == "save");
+ }
+ }
+ }
+ return false;
+}
+
+function setConceptTypeForComboBox(typeId, cbId) {
+ var t = dojo.byId(typeId).value;
+ var cb = dojo.widget.manager.getWidgetById(cbId)
+ var dp = cb.dataProvider;
+ var baseUrl = dp.searchUrl.split('&')[0];
+ var newUrl = baseUrl + '&searchType=' + t;
+ dp.searchUrl = newUrl;
+ cb.setValue('');
+}
+
+var dialogs = {}
+
+function objectDialog(dlgName, url) {
+ dojo.require('dojo.widget.Dialog');
+ dojo.require('dojo.widget.ComboBox');
+ dlg = dialogs[dlgName];
+ if (!dlg) {
+ //dlg = dojo.widget.fromScript('Dialog',
+ dlg = dojo.widget.createWidget('Dialog',
+ {bgColor: 'white', bgOpacity: 0.5, toggle: 'fade', toggleDuration: 250,
+ executeScripts: true,
+ href: url
+ }, dojo.byId('dialog.' + dlgName));
+ dialogs[dlgName] = dlg;
+ }
+ dlg.show();
+}
+
+function addConceptAssignment() {
+ dojo.require('dojo.html')
+ node = dojo.byId('form.assignments');
+ els = document.forms[0].elements;
+ for (var i=0; i' + title + ' ';
+ var tr = document.createElement('tr');
+ tr.appendChild(td);
+ node.appendChild(tr);
+}
+
diff --git a/agent/ui/twistd.py b/agent/ui/twistd.py
new file mode 100644
index 0000000..3be2802
--- /dev/null
+++ b/agent/ui/twistd.py
@@ -0,0 +1,21 @@
+#!C:\Python25\python.exe
+
+# Twisted, the Framework of Your Internet
+# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
+# See LICENSE for details.
+
+
+
+### Twisted Preamble
+# This makes sure that users don't have to set up their environment
+# specially in order to run these programs from bin/.
+import sys, os, string
+if string.find(os.path.abspath(sys.argv[0]), os.sep+'Twisted') != -1:
+ sys.path.insert(0, os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir, os.pardir)))
+if hasattr(os, "getuid") and os.getuid() != 0:
+ sys.path.insert(0, os.path.abspath(os.getcwd()))
+### end of preamble
+
+
+from twisted.scripts.twistd import run
+run()
diff --git a/agent/ui/usermode.ini b/agent/ui/usermode.ini
new file mode 100644
index 0000000..c6aee86
--- /dev/null
+++ b/agent/ui/usermode.ini
@@ -0,0 +1 @@
+UserMode:Simple
\ No newline at end of file
diff --git a/agent/ui/web.py b/agent/ui/web.py
index 9bdeeb0..d70b9df 100644
--- a/agent/ui/web.py
+++ b/agent/ui/web.py
@@ -1,32 +1,283 @@
-#
-# Copyright (c) 2007 Helmut Merz helmutm@cy55.de
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-#
+#------------------------------------------------------
+# AgentHome.py
+# source file for agent UI
+# author: Juergen Menzinger
+# version: 0.1
+#------------------------------------------------------
+
+# one possibility is to always stay in the same class by calling its object instance as
+# a return value when returning from a methodCall'. But this would require to change the current
+# __init__ procedure so that the changes concerning the ini file are always directly written
+# to the file or there is a routine which starts one time to initialize (maybe for example reading the
+# whole ini File into the self.IniDict if it is not already filled and for each setting just chnaging the
+# self.IniDict
+
+from nevow import loaders, rend, static, url, inevow
+from nevow.inevow import IRequest
+from twisted.internet import defer
"""
-Web interfaces for the loops agent.
-
-$Id$
+Import could look like this:
+from loops.agent.crawl.MailCrawler import MailCrawler
"""
-from nevow import loaders, rend
+# ---- global definitions ---------------------------------
+# THIS SECTION IS USED FOR PROJECT INTERNAL DEBUG ONLY
+INIFILE = "usermode.ini"
+JOBFILE = "joblist.txt"
+#----------------------------------------------------------
+
+
+#/////////////////////////////////////////////////////////////////////////////////////////////
+#---------------------------- AgentHome --------------------------------------------------
+# root page of the Agent UI
+# every method called on the agent ui has it s child
+# method inside here
class AgentHome(rend.Page):
- addSlash = True
- docFactory = loaders.xmlfile('ui/agent.html')
+ child_css = static.File('css')
+ child_images = static.File('images')
+ docFactory = loaders.xmlfile('AgentStart.html')
+
+ def __init__(self,IniDict={}):
+
+ #TODO: implement automatic reading of default ini file, or one passed via constructor
+ #-------- ini settings ------------------------
+ # THIS SECTION IS USED FOR PROJECT INTERNAL DEBUG ONLY
+ self.iniFile = INIFILE
+ self.IniDict = IniDict
+ #-----------------------------------------------
+
+ #-------- get ini settings from file --------
+ # stores IniFile settings in self.IniDict
+
+ if self.IniDict == {}:
+
+ fPointer = open(self.iniFile,"r")
+ IniSettings = fPointer.readlines()
+
+ for iniLine in IniSettings:
+ elem = iniLine.split(":")
+ self.IniDict[elem[0]] = elem[1]
+
+ fPointer.close()
+
+ print "[AgentHome] self.UserMode: ", self.IniDict["UserMode"]
+
+
+ """
+ def locateChild(self, ctx, segments):
+ return self, ()
+ """
+ # see nevow.url.py ?
+
+ #///////////////////////////////////////////////////////////////////
+ #----------AgentHome: CHILD PAGES SECTION--------------------------------------
+ # this code section contains all child methods that load
+ # a new (html-) page
+
+ def child_joboverview(self,context):
+
+ """ User requested page from menue: "job overview" """
+ return JobOverView(self.IniDict)
+
+ #//////////////////////////////////////////////////////////////////
+ #--------AgentHome: CHILD METHODS SECTION-------------------------------------
+ # this code section contains all form methods invoked in AgentHome
+ # including their callback methods
+
+ #---- page "Startpage" methods (class AgentHome) ----
+
+ def child_ChangeUserMode(self,context):
+
+ """User has klicked the Change User Mode button
+ change UserMode from Simple <-> Professional"""
+
+ print "[child_ChangeUserMode] UserMode: ", self.IniDict["UserMode"]
+ print "[child_ChangeUserMode] ----retrieving form values----"
+
+ form = IRequest(context).args
+
+ if form != {}:
+
+ for elem in form:
+ print "[child_ChangeUserMode] ", form[elem]
+
+ if self.IniDict["UserMode"] == "Simple":
+ self.IniDict["UserMode"] = "Advanced"
+
+ else:
+ self.IniDict["UserMode"] = "Simple"
+ print "[child_ChangeUserMode] : ", self.IniDict["UserMode"]
+
+ """
+ Write changed setting back to the iniFile ?
+ filePointer = open(self.iniFile,"rw")
+ """
+
+ return AgentHome(self.IniDict)
+
+
+ def child_collectOutlookMails(self,context):
+
+ """User requested page from menue: "Collect Outlook Mails" """
+
+ """
+ deferred = MailCrawler.getOutlookMails()
+ deferred.addCallback(self.defMailCrawl,context)
+ deferred.addErrback(self.defMailCrawlError,context)
+
+ return deferred
+ """
+
+ return AgentOutlookMailView(self.IniDict)
+
+
+
+ def defMailCrawl(self,MailCollection,context):
+
+ """here the returned collection is forwared to the page
+ that is displaying it"""
+
+ return AgentOutlookMailView(self.IniDict,MailCollection)
+
+
+ def defMailCrawlError(self,ErrorMessage,context):
+
+ """handles errors that ocurred in the MailCrawler"""
+
+ return AgentHome(self.IniDict)
+
+
+ #---- page "job overview" methods (class JobOverView)----
+
+ def child_ViewJobDetails(self,context):
+
+ form = IRequest(context).args
+ selectedJob = form['jobList'][0]
+
+ return JobOverViewDetails(self.IniDict, selectedJob)
+
+
+ #////////////////////////////////////////////////////////////
+ #-------------AgentHome: RENDER SECTION------------------------
+ # this code section contains the Nevow Rendering Methods
+ # for building the page element tree
+
+ def render_getActiveUserMode(self,context,data):
+ return self.IniDict["UserMode"]
+
+
+ def render_getAgentVersion(self,context,data):
+ return "0.1 alpha"
+
+
+
+
+#///////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#----------------- PAGES SECTION -------------------------------------------------------------------------
+# all classes in this section are pages called via the navigation menue of AgentHome
+
+class JobOverView(rend.Page):
+
+ docFactory = loaders.xmlfile('AgentJobView.html')
+
+ def __init__(self, IniDict):
+
+ self.IniSettings = IniDict
+
+ #-------------RENDER SECTION---------------------------------
+ # this code section contains the Nevow Rendering Methods
+ # for building the page element tree
+
+ def data_displayViewForm(self,context,data):
+ return "Overview of all running Crawling jobs"
+
+ def render_getActiveUserMode(self,context,data):
+ return self.IniSettings["UserMode"]
+
+ def render_fillJobList(self,ctx,data):
+
+ #---- get the registered jobs from the jobfile ----
+ #
+ fpJobFile = open(JOBFILE,"r")
+ lines = fpJobFile.readlines()
+ fpJobFile.close()
+ patternList = []
+ gen_pattern = inevow.IQ(ctx).patternGenerator('optionsJobList')
+
+ for elem in lines:
+ patternList.append(gen_pattern(data=elem))
+
+ return patternList
+
+
+
+
+class JobOverViewDetails(rend.Page):
+
+ docFactory = loaders.xmlfile('AgentJobViewDetail.html')
+
+ def __init__(self, IniDict={}, selectedJob=""):
+
+ self.IniSettings = IniDict
+ self.jobdetails = selectedJob
+
+
+ #-------------RENDER SECTION---------------------------------
+ # this code section contains the Nevow Rendering Methods
+ # for building the page element tree
+
+ def data_displayViewForm(self,context,data):
+ return "Detailed view of crawling job."
+
+ def render_getActiveUserMode(self,context,data):
+ return self.IniSettings["UserMode"]
+
+ def render_displayJobDetails(self,ctx,data):
+
+ print "*******************************************************"
+ print "[render_displayJobDetails] received form: ", str(self.jobdetails)
+ print "[render_displayJobDetails] received IniForm: ", str(self.IniSettings)
+ print "*******************************************************"
+
+ patternList = []
+ gen_pattern = inevow.IQ(ctx).patternGenerator('jobDetails')
+
+ for elem in self.jobdetails:
+ patternList.append(gen_pattern(data=elem))
+
+ return patternList
+
+
+class AgentOutlookMailView(rend.Page):
+
+ docFactory = loaders.xmlfile('AgentOutlookMailView.html')
+
+ def __init__(self, IniDict={}, MailCollection=[]):
+
+ self.IniDict = IniDict
+ self.MailCollection = MailCollection
+
+ #-------------RENDER SECTION---------------------------------
+ # this code section contains the Nevow Rendering Methods
+ # for building the page element tree
+
+ def data_displayViewForm(self,context,data):
+ return "Detailed view of all collected Outlook Mails. [DEMO]"
+
+ def render_getActiveUserMode(self,context,data):
+ return self.IniDict["UserMode"]
+
+ def render_displayOutlookMails(self,ctx,data):
+
+ patternList = []
+ gen_pattern = inevow.IQ(ctx).patternGenerator('OutlookMails')
+
+ for elem in self.MailCollection:
+ patternList.append(gen_pattern(data=elem))
+
+ return patternList