From 22b4b2b2f9cb738624d17ccac39eb324c2b2571b Mon Sep 17 00:00:00 2001 From: scrat Date: Wed, 11 Jul 2007 21:07:54 +0000 Subject: [PATCH] git-svn-id: svn://svn.cy55.de/Zope3/src/loops/trunk@1823 fd906abe-77d9-0310-91a1-e0d9ade77398 --- agent/ui/AgentJobView.html | 140 ++++++ agent/ui/AgentJobViewDetail.html | 137 ++++++ agent/ui/AgentOutlookMailView.html | 137 ++++++ agent/ui/AgentStart.html | 133 ++++++ agent/ui/StartUpAgentUI.tac.py | 26 ++ agent/ui/css/base.css | 99 +++++ agent/ui/css/custom.css | 24 ++ agent/ui/css/loops.css | 138 ++++++ agent/ui/css/print.css | 13 + agent/ui/css/zope3_tablelayout.css | 662 +++++++++++++++++++++++++++++ agent/ui/images/favicon.png | Bin 0 -> 580 bytes agent/ui/images/loops_logo2.png | Bin 0 -> 13258 bytes agent/ui/joblist.txt | 4 + agent/ui/loops.js | 126 ++++++ agent/ui/twistd.py | 21 + agent/ui/usermode.ini | 1 + agent/ui/web.py | 297 ++++++++++++- 17 files changed, 1935 insertions(+), 23 deletions(-) create mode 100644 agent/ui/AgentJobView.html create mode 100644 agent/ui/AgentJobViewDetail.html create mode 100644 agent/ui/AgentOutlookMailView.html create mode 100644 agent/ui/AgentStart.html create mode 100644 agent/ui/StartUpAgentUI.tac.py create mode 100644 agent/ui/css/base.css create mode 100644 agent/ui/css/custom.css create mode 100644 agent/ui/css/loops.css create mode 100644 agent/ui/css/print.css create mode 100644 agent/ui/css/zope3_tablelayout.css create mode 100644 agent/ui/images/favicon.png create mode 100644 agent/ui/images/loops_logo2.png create mode 100644 agent/ui/joblist.txt create mode 100644 agent/ui/loops.js create mode 100644 agent/ui/twistd.py create mode 100644 agent/ui/usermode.ini 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 + + + + + + + + + + + + + + + + + + + + + +
+
+
+

loops agent.GUI

+
+
+ + + +
+
+
+ +
+
+

+
+
+

Agent Job overview

+ +
    +
  • Here you will get an overview of the current jobs registered in the agent system
  • +
+
+
+

Overview

+
    +
  • Current jobs
  • +
+
+
+ +

+
+
+
+
+
+ +
+
+ + + +
+ + + + \ 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 + + + + + + + + + + + + + + + + + + + + + +
+
+
+

loops agent.GUI

+
+
+ + + +
+
+
+ +
+
+

+
+
+

Agent Job overview

+ +
    +
  • Here you will get an overview of the current jobs registered in the agent system
  • +
+
+
+

Overview

+
    +
  • Job details
  • +
+
+ +

+

+

+
+
+
+
+
+ +
+
+ + + +
+ + + + \ 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 + + + + + + + + + + + + + + + + + + + + + +
+
+
+

loops agent.GUI

+
+
+ + + +
+
+
+ +
+
+

+
+
+

Agent: collected Outlook Mails

+ +
    +
  • All currently available Outlook Mails collected by the loops agent
  • +
+
+
+

Overview

+
    +
  • Mail Collection
  • +
+
+ +

+

+

+
+
+
+
+
+ +
+
+ + + +
+ + + + \ 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 + + + + + + + + + + + + + + + + + + + + + +
+
+
+

loops agent.GUI

+
+
+ + + +
+
+
+ +
+
+

+
+
+

Startpage

+ +
    +
  • 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.
  • +
+
+
+

Version

+
    +
  • Agent:
  • +
+
+
+
+ +
+
+ + + +
+ + + + \ 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 0000000000000000000000000000000000000000..1fc74855de236f397eaa38e086a2a0e0d1006cf2 GIT binary patch literal 580 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' + 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