You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by js...@apache.org on 2012/05/28 18:49:38 UTC

svn commit: r1343316 [1/5] - in /tuscany/sca-cpp/trunk: ./ hosting/server/ hosting/server/htdocs/ hosting/server/htdocs/account/ hosting/server/htdocs/app/ hosting/server/htdocs/clone/ hosting/server/htdocs/create/ hosting/server/htdocs/delete/ hosting...

Author: jsdelfino
Date: Mon May 28 16:49:36 2012
New Revision: 1343316

URL: http://svn.apache.org/viewvc?rev=1343316&view=rev
Log:
Improvements to the hosted composite management app. Simplify and optimize the Web UI a bit. Add test cases and fix some of the logic in the management components.

Added:
    tuscany/sca-cpp/trunk/hosting/server/htdocs/config.js
    tuscany/sca-cpp/trunk/hosting/server/htdocs/delete/
    tuscany/sca-cpp/trunk/hosting/server/htdocs/delete/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/proxy/
    tuscany/sca-cpp/trunk/hosting/server/htdocs/proxy/public/
    tuscany/sca-cpp/trunk/hosting/server/htdocs/proxy/public/oops/
    tuscany/sca-cpp/trunk/hosting/server/htdocs/proxy/public/oops/index.html
      - copied, changed from r1343140, tuscany/sca-cpp/trunk/hosting/server/htdocs/public/oops/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/public/config.js
    tuscany/sca-cpp/trunk/hosting/server/server-test   (contents, props changed)
      - copied, changed from r1343140, tuscany/sca-cpp/trunk/hosting/server/user.py
    tuscany/sca-cpp/trunk/hosting/server/test/
    tuscany/sca-cpp/trunk/hosting/server/test.py   (with props)
    tuscany/sca-cpp/trunk/hosting/server/test/__init__.py
      - copied, changed from r1343140, tuscany/sca-cpp/trunk/hosting/server/user.py
    tuscany/sca-cpp/trunk/hosting/server/test/cache.py
      - copied, changed from r1343140, tuscany/sca-cpp/trunk/hosting/server/accounts.py
    tuscany/sca-cpp/trunk/hosting/server/test/property.py
      - copied, changed from r1343140, tuscany/sca-cpp/trunk/hosting/server/user.py
    tuscany/sca-cpp/trunk/hosting/server/test/reference.py
      - copied, changed from r1343140, tuscany/sca-cpp/trunk/hosting/server/user.py
Modified:
    tuscany/sca-cpp/trunk/.gitignore
    tuscany/sca-cpp/trunk/hosting/server/Makefile.am
    tuscany/sca-cpp/trunk/hosting/server/accounts.py
    tuscany/sca-cpp/trunk/hosting/server/apps.py
    tuscany/sca-cpp/trunk/hosting/server/composites.py
    tuscany/sca-cpp/trunk/hosting/server/dashboards.py
    tuscany/sca-cpp/trunk/hosting/server/htdocs/account/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/app/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/cache-manifest.cmf
    tuscany/sca-cpp/trunk/hosting/server/htdocs/clone/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/create/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/graph/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/home/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/login/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/page/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/public/notauth/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/public/notfound/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/public/notyet/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/public/oops/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/stats/index.html
    tuscany/sca-cpp/trunk/hosting/server/htdocs/store/index.html
    tuscany/sca-cpp/trunk/hosting/server/pages.py
    tuscany/sca-cpp/trunk/hosting/server/server.composite
    tuscany/sca-cpp/trunk/hosting/server/ssl-start
    tuscany/sca-cpp/trunk/hosting/server/start
    tuscany/sca-cpp/trunk/hosting/server/store.py
    tuscany/sca-cpp/trunk/hosting/server/user.py
    tuscany/sca-cpp/trunk/modules/atom/atom-test.cpp
    tuscany/sca-cpp/trunk/modules/atom/atom.hpp
    tuscany/sca-cpp/trunk/modules/http/conf/mime.types
    tuscany/sca-cpp/trunk/modules/http/form-auth-conf
    tuscany/sca-cpp/trunk/modules/http/httpd-conf
    tuscany/sca-cpp/trunk/modules/http/httpd-ssl-conf
    tuscany/sca-cpp/trunk/modules/http/proxy-base-conf
    tuscany/sca-cpp/trunk/modules/http/proxy-conf
    tuscany/sca-cpp/trunk/modules/http/proxy-ssl-conf
    tuscany/sca-cpp/trunk/modules/js/htdocs/atomutil.js
    tuscany/sca-cpp/trunk/modules/js/htdocs/component.js
    tuscany/sca-cpp/trunk/modules/js/htdocs/ui.css
    tuscany/sca-cpp/trunk/modules/js/htdocs/ui.js
    tuscany/sca-cpp/trunk/modules/js/htdocs/util.js

Modified: tuscany/sca-cpp/trunk/.gitignore
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/.gitignore?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/.gitignore (original)
+++ tuscany/sca-cpp/trunk/.gitignore Mon May 28 16:49:36 2012
@@ -56,7 +56,6 @@ m4/
 config.guess
 config.sub
 config.status
-config.js
 all.js
 *-min.html
 *-min.js

Modified: tuscany/sca-cpp/trunk/hosting/server/Makefile.am
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/Makefile.am?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/Makefile.am (original)
+++ tuscany/sca-cpp/trunk/hosting/server/Makefile.am Mon May 28 16:49:36 2012
@@ -20,16 +20,9 @@ if WANT_PYTHON
 moddir = $(prefix)/hosting/server
 dist_mod_SCRIPTS = start stop ssl-start mkapplinks config-backup data-backup
 
-BUILT_SOURCES = htdocs/config.js htdocs/public/config.js
-htdocs/config.js:
-	touch htdocs/config.js
+not_minified = htdocs/public/iframe.html htdocs/create/index.html htdocs/page/index.html htdocs/login/index.html htdocs/public/notfound/index.html htdocs/public/oops/index.html htdocs/proxy/public/oops/index.html htdocs/graph/index.html htdocs/public/notauth/index.html htdocs/account/index.html htdocs/home/index.html htdocs/index.html htdocs/public/notyet/index.html htdocs/clone/index.html htdocs/delete/index.html htdocs/stats/index.html htdocs/app/index.html htdocs/store/index.html htdocs/config.js htdocs/public/config.js
 
-htdocs/public/config.js:
-	touch htdocs/public/config.js
-
-not_minified = htdocs/public/iframe.html htdocs/create/index.html htdocs/page/index.html htdocs/login/index.html htdocs/public/notfound/index.html htdocs/public/oops/index.html htdocs/graph/index.html htdocs/public/notauth/index.html htdocs/account/index.html htdocs/home/index.html htdocs/index.html htdocs/public/notyet/index.html htdocs/clone/index.html htdocs/stats/index.html htdocs/app/index.html htdocs/store/index.html htdocs/config.js htdocs/public/config.js
-
-minified = htdocs/public/iframe-min.html htdocs/create/index-min.html htdocs/page/index-min.html htdocs/login/index-min.html htdocs/public/notfound/index-min.html htdocs/public/oops/index-min.html htdocs/graph/index-min.html htdocs/public/notauth/index-min.html htdocs/account/index-min.html htdocs/home/index-min.html htdocs/index-min.html htdocs/public/notyet/index-min.html htdocs/clone/index-min.html htdocs/stats/index-min.html htdocs/app/index-min.html htdocs/store/index-min.html htdocs/config-min.js htdocs/public/config-min.js
+minified = htdocs/public/iframe-min.html htdocs/create/index-min.html htdocs/page/index-min.html htdocs/login/index-min.html htdocs/public/notfound/index-min.html htdocs/public/oops/index-min.html htdocs/proxy/public/oops/index-min.html htdocs/graph/index-min.html htdocs/public/notauth/index-min.html htdocs/account/index-min.html htdocs/home/index-min.html htdocs/index-min.html htdocs/public/notyet/index-min.html htdocs/clone/index-min.html htdocs/delete/index-min.html htdocs/stats/index-min.html htdocs/app/index-min.html htdocs/store/index-min.html htdocs/config-min.js htdocs/public/config-min.js
 
 resources = server.composite *.py htdocs/*.cmf htdocs/*.ico htdocs/home/*.png htdocs/app/*.cmf htdocs/home/*.b64 htdocs/*.txt htdocs/public/*.png htdocs/public/*.b64 data/palettes/*/palette.composite data/accounts/*/*.account data/apps/*/app.composite data/apps/*/app.stats data/apps/*/htdocs/app.html data/dashboards/*/user.apps data/store/*/store.apps ${not_minified} ${minified}
 
@@ -45,4 +38,7 @@ SUFFIXES = -min.html -min.js
 
 CLEANFILES = ${minified}
 
+dist_noinst_SCRIPTS = server-test test.py
+TESTS = server-test
+
 endif

Modified: tuscany/sca-cpp/trunk/hosting/server/accounts.py
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/accounts.py?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/accounts.py (original)
+++ tuscany/sca-cpp/trunk/hosting/server/accounts.py Mon May 28 16:49:36 2012
@@ -16,17 +16,18 @@
 #  under the License.
 
 # Accounts collection implementation
+from time import strftime
 from util import *
 
 # Convert a particular user id to an account id
 def accountid(user):
-    return ("accounts", user.id(), "user.account")
+    return ('accounts', user.get(()), 'user.account')
 
 # Get the current user's account
 def get(id, user, cache):
     account = cache.get(accountid(user))
     if isNil(account) or account is None:
-        return ()
+        return (("'entry", ("'title", user.get(())), ("'id", user.get(())), ("'updated", strftime('%b %d, %Y'))),)
     return account
 
 # Update the user's account

Modified: tuscany/sca-cpp/trunk/hosting/server/apps.py
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/apps.py?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/apps.py (original)
+++ tuscany/sca-cpp/trunk/hosting/server/apps.py Mon May 28 16:49:36 2012
@@ -16,42 +16,96 @@
 #  under the License.
 
 # App collection implementation
-import os
+from time import strftime
 from util import *
+from sys import debug
 
 # Convert an id to an app id
 def appid(id):
     return ("apps", car(id), "app.stats")
 
 # Put an app into the apps db
-def put(id, app, cache, store, composites, pages):
-    eid = cadr(caddr(car(app)))
-    appentry = (("'entry", cadr(car(app)), ("'id", car(id))),)
+def put(id, app, user, cache, dashboard, store, composites, pages):
+    debug('apps.py::put::id', id)
+    debug('apps.py::put::app', app)
 
-    # Update app in apps db
+    # Update an app
+    eid = cadr(assoc("'id", car(app)))
     if car(id) == eid:
+        # Check app author
+        eapp = cache.get(appid(id));
+        if (not (isNil(eapp) or eapp is None)) and (cadr(assoc("'author", car(eapp))) != user.get(())):
+            debug('apps.py::put', 'different author', cadr(assoc("'author", car(eapp))))
+            return False
+
+        # Update the app in the apps db
+        appentry = (("'entry", assoc("'title", car(app)), ("'id", car(id)), ("'author", user.get(())), ("'updated", strftime('%b %d, %Y')), assoc("'content", car(app))),)
+        debug('apps.py::put::appentry', appentry)
         cache.put(appid(id), appentry)
+        dashboard.put(id, appentry)
+
+        # Create new page and composite if necessary
+        if isNil(eapp) or eapp is None:
+            comp = (("'entry", ("'title", car(id)), ("'id", car(id))),)
+            composites.put(id, comp);
+            page = (("'entry", ("'title", car(id)), ("'id", car(id))),)
+            pages.put(id, comp);
+            return True
         return True
 
-    # Clone an app's composite and page
+    # Check app author
+    eapp = cache.get(appid(id));
+    if (not (isNil(eapp) or eapp is None)) and (cadr(assoc("'author", car(eapp))) != user.get(())):
+        debug('apps.py::put', 'different author', cadr(assoc("'author", car(eapp))))
+        return False
+
+    # Clone an app
+    appentry = (("'entry", assoc("'title", car(app)), ("'id", car(id)), ("'author", user.get(())), ("'updated", strftime('%b %d, %Y')), assoc("'content", car(app))),)
+    debug('apps.py::put::appentry', appentry)
     cache.put(appid(id), appentry)
     composites.put(id, composites.get((eid,)))
     pages.put(id, pages.get((eid,)))
+    dashboard.put(id, appentry)
     return True
 
 # Get an app from the apps db
-def get(id, cache, store, composites, pages):
+def get(id, user, cache, dashboard, store, composites, pages):
+    debug('apps.py::get::id', id)
     if isNil(id):
         return (("'feed", ("'title", "Apps"), ("'id", "apps")),)
+
+    # Get the requested app
     app = cache.get(appid(id));
     if isNil(app) or app is None:
-        return (("'entry", ("'title", car(id)), ("'id", car(id))),)
+        debug('apps.py::get', 'app not found', id)
+
+        # Return a default new app
+        return (("'entry", ("'title", car(id)), ("'id", car(id)), ("'author", user.get(())), ("'updated", strftime('%b %d, %Y')), ("'content", ("'stats", ("'description", '')))),)
+
+    # Return the app
+    debug('apps.py::get::app', app)
     return app
 
 # Delete an app from the apps db
-def delete(id, cache, store, composites, pages):
-    cache.delete(appid(id))
+def delete(id, user, cache, dashboard, store, composites, pages):
+    debug('apps.py::delete::id', id)
+
+    # Get the requested app
+    app = cache.get(appid(id));
+    if isNil(app) or app is None:
+        debug('apps.py::delete', 'app not found', id)
+        return False
+
+    # Check app author
+    author = cadr(assoc("'author", car(app)))
+    if author != user.get(()):
+        debug('apps.py::delete', 'different author', author)
+        return False
+
+    # Delete the app, its composite and page
+    dashboard.delete(id)
     composites.delete(id)
     pages.delete(id)
+    cache.delete(appid(id))
     return True
 

Modified: tuscany/sca-cpp/trunk/hosting/server/composites.py
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/composites.py?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/composites.py (original)
+++ tuscany/sca-cpp/trunk/hosting/server/composites.py Mon May 28 16:49:36 2012
@@ -16,29 +16,82 @@
 #  under the License.
 
 # App composites collection implementation
+from time import strftime
 from util import *
+from sys import debug
 
-# Convert an id to an app id
-def appid(id):
+# Convert an id to a composite id
+def compid(id):
     return ("apps", car(id), "app.composite")
 
-# Put an app into the apps db
-def put(id, app, cache):
-    comp = cdr(cadddr(car(app)))
-    cache.put(appid(id), comp)
-    return True
+# Put a composite into the composite db
+def put(id, comp, user, cache, apps):
+    debug('composites.py::put::id', id)
+    debug('composites.py::put::comp', comp)
 
-# Get an app from the apps db
-def get(id, cache):
+    # Get the requested app
+    app = apps.get(id);
+    if isNil(app) or app is None:
+        debug('composites.py::put', 'app not found', id)
+        return False
+
+    # Check app author
+    author = cadr(assoc("'author", car(app)))
+    if author != user.get(()):
+        debug('composites.py::put', 'different author', author)
+        return False
+
+    # Update the composite in the composite db
+    compentry = (("'entry", assoc("'title", car(app)), ("'id", car(id)), ("'author", user.get(())), ("'updated", strftime('%b %d, %Y')), assoc("'content", car(comp))),)
+    debug('composites.py::put::compentry', compentry)
+    return cache.put(compid(id), compentry)
+
+# Get a composite from the composite db
+def get(id, user, cache, apps):
+    debug('composites.py::get::id', id)
     if isNil(id):
         return (("'feed", ("'title", "Composites"), ("'id", "composites")),)
-    app = cache.get(appid(id));
+
+    # Get the requested app
+    app = apps.get(id)
+    if isNil(app) or app is None:
+        debug('composites.py::get', 'app not found', id)
+
+        # Return a default new composite
+        return (("'entry", ("'title", car(id)), ("'id", car(id)), ("'author", user.get(())), ("'updated", strftime('%b %d, %Y'))),)
+
+    # Get the requested composite
+    comp = cache.get(compid(id));
+    if isNil(comp) or comp is None:
+        debug('composites.py::get', 'composite not found', id)
+
+        # Return a default new composite
+        return (("'entry", ("'title", car(id)), ("'id", car(id)), assoc("'author", car(app)), assoc("'updated", car(app))),)
+
+    # Return the composite
+    def updated(u):
+        return assoc("'updated", car(app)) if isNil(u) or u is None else u
+
+    compentry = (("'entry", assoc("'title", car(app)), ("'id", car(id)), assoc("'author", car(app)), updated(assoc("'updated", car(comp))), assoc("'content", car(comp))),)
+    debug('composites.py::get::compentry', compentry)
+    return compentry
+
+# Delete a composite from the composite db
+def delete(id, user, cache, apps):
+    debug('composites.py::delete::id', id)
+
+    # Get the requested app
+    app = apps.get(id);
     if isNil(app) or app is None:
-        return (("'entry", ("'title", car(id)), ("'id", car(id))),)
-    return (("'entry", ("'title", car(id)), ("'id", car(id)), ("'content", car(app))),)
+        debug('composites.py::delete', 'app not found', id)
+        return False
+
+    # Check app author
+    author = cadr(assoc("'author", car(app)))
+    if author != user.get(()):
+        debug('composites.py::delete', 'different author', author)
+        return False
 
-# Delete an app from the apps db
-def delete(id, cache):
-    cache.delete(appid(id))
-    return True
+    # Delete the composite
+    return cache.delete(compid(id))
 

Modified: tuscany/sca-cpp/trunk/hosting/server/dashboards.py
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/dashboards.py?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/dashboards.py (original)
+++ tuscany/sca-cpp/trunk/hosting/server/dashboards.py Mon May 28 16:49:36 2012
@@ -17,68 +17,89 @@
 
 # Dashboards collection implementation
 from util import *
+from sys import debug
 
 # Convert a particular user id to a dashboard id
 def dashboardid(user):
-    return ("dashboards", user.id(), "user.apps")
+    return ("dashboards", user.get(()), "user.apps")
 
 # Get a dashboard from the cache
 def getdashboard(id, cache):
+    debug('dashboards.py::getdashboard::id', id)
     val = cache.get(id)
     if isNil(val) or val is None:
         return ()
-    return cdddr(car(val))
+    dashboard = cdddr(car(val))
+    if not isNil(dashboard) and isList(car(cadr(car(dashboard)))):
+        # Expand list of entries
+        edashboard = tuple(map(lambda e: cons("'entry", e), cadr(car(dashboard))))
+        debug('dashboards.py::getdashboard::edashboard', edashboard)
+        return edashboard
+
+    debug('dashboards.py::getdashboard::dashboard', dashboard)
+    return dashboard
 
 # Put a dashboard into the cache
 def putdashboard(id, dashboard, cache):
+    debug('dashboards.py::putdashboard::id', id)
+    debug('dashboards.py::putdashboard::dashboard', dashboard)
     val = ((("'feed", ("'title", "Your Apps"), ("'id", cadr(id))) + dashboard),)
+    return cache.put(id, val)
 
 # Put an app into the user's dashboard
 def put(id, app, user, cache, apps):
-    def putapp(app, dashboard):
+    debug('dashboards.py::put::id', id)
+    debug('dashboards.py::put::app', app)
+
+    def putapp(id, app, dashboard):
         if isNil(dashboard):
             return app
-        if cadr(caddr(car(app))) == cadr(caddr(car(dashboard))):
+        if car(id) == cadr(assoc("'id", car(dashboard))):
             return cons(car(app), cdr(dashboard))
-        return cons(car(dashboard), putapp(app, cdr(dashboard)))
+        return cons(car(dashboard), putapp(id, app, cdr(dashboard)))
+
+    appentry = (("'entry", assoc("'title", car(app)), ("'id", car(id)), ("'author", user.get(())), assoc("'updated", car(app)), assoc("'content", car(app))),)
+    debug('dashboards.py::put::appentry', appentry)
 
-    appentry = (("'entry", cadr(car(app)), ("'id", car(id))),)
-    dashboard = putapp(appentry, getdashboard(dashboardid(user), cache))
-    putdashboard(dashboardid(user), dashboard, cache)
-
-    # Update app in app repository
-    apps.put(id, app);
-    return True
+    dashboard = putapp(id, appentry, getdashboard(dashboardid(user), cache))
+    return putdashboard(dashboardid(user), dashboard, cache)
 
 # Get apps from the user's dashboard
 def get(id, user, cache, apps):
+    debug('dashboards.py::get::id', id)
+
     def findapp(id, dashboard):
         if isNil(dashboard):
             return None
-        if car(id) == cadr(caddr(car(dashboard))):
+        if car(id) == cadr(assoc("'id", car(dashboard))):
             return (car(dashboard),)
         return findapp(id, cdr(dashboard))
 
     if isNil(id):
-        return ((("'feed", ("'title", "Your Apps"), ("'id", user.id())) + getdashboard(dashboardid(user), cache)),)
-    return findapp(id, getdashboard(dashboardid(user), cache))
+        dashboard = ((("'feed", ("'title", "Your Apps"), ("'id", user.get(()))) + getdashboard(dashboardid(user), cache)),)
+        debug('dashboards.py::get::dashboard', dashboard)
+        return dashboard
+
+    app = findapp(id, getdashboard(dashboardid(user), cache))
+    debug('dashboards.py::get::app', app)
+    return app
 
 # Delete apps from the user's dashboard
 def delete(id, user, cache, apps):
+    debug('dashboards.py::delete::id', id)
     if isNil(id):
         return cache.delete(dashboardid(user))
 
     def deleteapp(id, dashboard):
         if isNil(dashboard):
             return ()
-        if car(id) == cadr(caddr(car(dashboard))):
+        if car(id) == cadr(assoc("'id", car(dashboard))):
             return cdr(dashboard)
         return cons(car(dashboard), deleteapp(id, cdr(dashboard)))
 
-    dashboard = deleteapp(id, getdashboard(dashboardid(user), cache))
-    putdashboard(dashboardid(user), dashboard, cache)
-
-    # Delete app from app repository
-    apps.delete(id);
-    return True
+    dashboard = getdashboard(dashboardid(user), cache)
+    deleted = deleteapp(id, dashboard)
+    if deleted == dashboard:
+        return False
+    return putdashboard(dashboardid(user), deleted, cache)
 

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/account/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/account/index.html?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/account/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/account/index.html Mon May 28 16:49:36 2012
@@ -17,29 +17,18 @@
  * specific language governing permissions and limitations
  * under the License.    
 -->
-<div id="bodydiv" class="bodydiv">
+<div id="bodydiv" class="body">
 
-<table style="width: 100%;">
-<tr>
-<td><h2><span id="h1"></span><span id="userNameHeader"></span></h2></td>
-<td style="vertical-align: middle; text-align: right;"><span id="status" style="font-weight: bold; color: #808080;"></span></td>
-</tr>
-</table>
-
-<table style="width: 100%;">
-<tr>
-<th class="thl thr" style="padding-top: 4px; padding-bottom: 4px; padding-left: 2px; padding-right: 2px; ">Account</th>
-</tr>
-</table>
+<div class="viewform">
 
 <form id="userForm">
 <table style="width: 100%;">
 <tr><tr><td><b>Photo:</b></td></tr>
 <tr><td><img id="userimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>Name:</b></td></tr>
-<tr><td><input type="text" id="userTitle" size="30" placeholder="Enter your name" style="width: 300px;"/></td></tr>
+<tr><td><input type="text" id="userTitle" class="flatentry" size="30" placeholder="Enter your name" style="width: 300px;"/></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr>
-<tr><td><textarea id="userDescription" cols="40" rows="3" placeholder="Enter a short description of yourself" style="width: 300px;"></textarea></td></tr>
+<tr><td><textarea id="userDescription" class="flatentry" cols="40" rows="3" placeholder="Enter a short description of yourself" style="width: 300px;"></textarea></td></tr>
 </table>
 
 <br/>
@@ -50,11 +39,11 @@
 </table>
 
 <table>
-<tr><td style="padding-right: 2px;"><input type="text" id="sched1" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service1" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="sched2" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service2" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="sched3" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service3" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="sched4" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service4" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="sched5" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service5" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="sched1" class="flatentry" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service1" class="flatentry" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="sched2" class="flatentry" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service2" class="flatentry" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="sched3" class="flatentry" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service3" class="flatentry" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="sched4" class="flatentry" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service4" class="flatentry" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="sched5" class="flatentry" size="10" placeholder="Schedule" style="width: 80px;"/></td><td><input type="text" id="service5" class="flatentry" size="2048" placeholder="Service URL" style="width: 200px;"/></td></tr>
 </table>
 <br/>
 
@@ -65,28 +54,31 @@
 </table>
 
 <table>
-<tr><td style="padding-right: 2px;"><input type="text" id="name1" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value1" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="name2" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value2" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="name3" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value3" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="name4" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value4" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="name5" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value5" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="name6" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value6" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="name7" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value7" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="name8" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value8" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="name9" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value9" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
-<tr><td style="padding-right: 2px;"><input type="text" id="name10" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value10" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="name1" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value1" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="name2" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value2" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="name3" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value3" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="name4" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value4" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="name5" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value5" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="name6" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value6" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="name7" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value7" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="name8" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value8" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="name9" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value9" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
+<tr><td style="padding-right: 2px;"><input type="text" id="name10" class="flatentry" size="10" placeholder="Key name" style="width: 80px;"/></td><td><input type="text" id="value10" class="flatentry" size="2048" placeholder="Key value" style="width: 200px;"/></td></tr>
 </table>
 </form>
 
+</div>
+
 <script type="text/javascript">
 
 // Init service references
 var editWidget = sca.component("EditWidget");
-var user= sca.defun(sca.reference(editWidget, "user"), "id");
+var user= sca.defun(sca.reference(editWidget, "user"));
 var accounts = sca.reference(editWidget, "accounts");
 
 // Set page titles
 document.title = ui.windowtitle(location.hostname) + ' - Account';
+$('viewhead').innerHTML = '<span class="smenu">' + username + '</span>';
 
 // Set images
 $('userimg').src = ui.b64img(appcache.get('/public/user.b64'));
@@ -94,30 +86,28 @@ $('userimg').src = ui.b64img(appcache.ge
 /**
  * The current account entry and corresponding saved XML content.
  */
-var username;
 var accountentry;
 var savedaccountentryxml = '';
 
 /**
  * Get and display the user's account.
  */
-function getaccount(name) {
+function getaccount() {
     showStatus('Loading');
 
     return accounts.get(name, function(doc) {
 
         // Stop now if we didn't get an account
         if (doc == null) {
-            showStatus('No data');
+            showError('App not available');
             return false;
         }
         showStatus(defaultStatus());
 
-        accountentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name));
-        username = cadr(assoc("'id", cdr(accountentry)));
-        var title = cadr(assoc("'title", cdr(accountentry)));
+        accountentry = car(elementsToValues(atom.readATOMEntry(mklist(doc))));
+        //username = cadr(assoc("'id", cdr(accountentry)));
         $('userNameHeader').innerHTML = username;
-        $('userTitle').value = title;
+        $('userTitle').value = cadr(assoc("'title", cdr(accountentry)));
 
         var content = cadr(assoc("'content", cdr(accountentry)));
         var acct = isNil(content)? mklist() : cdr(content);

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/app/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/app/index.html?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/app/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/app/index.html Mon May 28 16:49:36 2012
@@ -37,28 +37,31 @@ appcache.get = function(uri) {
     var u = h == -1? uri : uri.substring(0, h);
 
     // Get resource from local storage first
-    var item = localStorage.getItem(u);
+    var ls = window.lstorage || localStorage;
+    var item = null;
+    try { item = ls.getItem(u); } catch(e) {}
     if (item != null && item != '')
         return item;
 
     // Get resource from network
     var http = new XMLHttpRequest();
     http.open("GET", u, false);
+    http.setRequestHeader("Accept", "*/*");
     http.send(null);
     if (http.status == 200) {
         if (http.getResponseHeader("X-Login") != null) {
-            if (log) log('http error', u, 'X-Login');
+            if (debug) debug('http error', u, 'X-Login');
             // Redirect to login page if not signed in
             document.location = '/login/';
             return null;
         } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) {
-            if (log) log('http error', u, 'No-Content');
+            if (debug) debug('http error', u, 'No-Content');
             return null;
         }
-        localStorage.setItem(u, http.responseText);
+        try { ls.setItem(u, http.responseText); } catch(e) {}
         return http.responseText;
     }
-    if (log) log('http error', u, http.status, http.statusText);
+    if (debug) debug('http error', u, http.status, http.statusText);
     // Redirect to login page if not signed in
     if (http.status == 403)
         document.location = '/login/';
@@ -114,10 +117,17 @@ document.title = appname;
 var contentdiv = $('content');
 
 /**
+ * The main app composite and page definitions.
+ */
+var appcomposite = null;
+var apppage = null;
+
+/**
  * Initialize the app HTTP clients.
  */
 var appWidget = sca.component('AppWidget');
 var pagecomp = sca.reference(appWidget, 'pages');
+var composcomp = sca.reference(appWidget, 'composites');
 var startcomp = sca.httpclient('start', '/' + appname + '/start');
 var stopcomp = sca.httpclient('stop', '/' + appname + '/stop');
 var timercomp = sca.httpclient('timer', '/' + appname + '/timer');
@@ -138,27 +148,29 @@ var appresources = [
  * Handle application cache events.
  */
 applicationCache.addEventListener('checking', function(e) {
-    //log('appcache checking', e);
+    //debug('appcache checking', e);
 }, false);
 applicationCache.addEventListener('error', function(e) {
-    //log('appcache error', e);
+    //debug('appcache error', e);
 }, false);
 applicationCache.addEventListener('noupdate', function(e) {
-    //log('appcache noupdate', e);
+    //debug('appcache noupdate', e);
 }, false);
 applicationCache.addEventListener('downloading', function(e) {
-    //log('appcache downloading', e);
+    //debug('appcache downloading', e);
 }, false);
 applicationCache.addEventListener('progress', function(e) {
-    //log('appcache progress', e);
+    //debug('appcache progress', e);
 }, false);
 applicationCache.addEventListener('updateready', function(e) {
-    //log('appcache updateready', e);
-    applicationCache.swapCache();
-    //log('appcache swapped', e);
+    //debug('appcache updateready', e);
+    try {
+        applicationCache.swapCache();
+    } catch(e) {}
+    //debug('appcache swapped', e);
 }, false);
 applicationCache.addEventListener('cached', function(e) {
-    //log('appcache cached', e);
+    //debug('appcache cached', e);
     map(function(res) {
         appcache.get(res[0]);
     }, appresources);
@@ -168,13 +180,13 @@ applicationCache.addEventListener('cache
  * Handle network offline/online events.
  */
 window.addEventListener('offline', function(e) {
-      //log('going offline');
+      //debug('going offline');
 }, false);
 window.addEventListener('online', function(e) {
-      //log('going online');
+      //debug('going online');
 }, false);
 
-//log(navigator.onLine? 'online' : 'offline');
+//debug(navigator.onLine? 'online' : 'offline');
 
 /**
  * Find a named value in a tree of elements. The value name is given
@@ -545,17 +557,24 @@ function initwidget(e) {
 }
 
 /**
+ * Return the component bound to a uri.
+ */
+function isbound(uri, comps) {
+    return !isNil(filter(function(comp) {
+        return !isNil(filter(function(svc) {
+            return !isNil(filter(function(b) {
+                return uri == scdl.uri(b);
+            }, scdl.bindings(svc)));
+        }, scdl.services(comp)));
+    }, comps));
+}
+
+/**
  * Get app data from the main app page component.
  */
-function getpagedata(appname) {
+function getappdata(appname, page, compos) {
     try {
 
-        // Display component data on the page
-        function displaypage(doc) {
-            updatepage(docdata(doc));
-            return true;
-        }
-
         // Eval a component init script
         function evalcompinit(doc) {
             if (isNil(doc))
@@ -577,55 +596,104 @@ function getpagedata(appname) {
         // Setup the widgets
         map(setupwidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID(contentdiv, 'page').childNodes)));
 
+        // Get the app components
+        var comps = scdl.components(compos);
+
         // Get the component app data
-        startcomp.get(location.search, function(doc, e) {
-            if (isNil(doc)) {
-                log('error on get(start, ' + location.search + ')', e);
-                return false;
-            }
+        if (isbound("start", comps)) {
+            startcomp.get(location.search, function(doc, e) {
+                if (isNil(doc)) {
+                    debug('error on get(start, ' + location.search + ')', e);
+                    return false;
+                }
 
-            // Display data on the page
-            displaypage(doc);
-        });
+                // Display data on the page
+                updatepage(docdata(doc));
+            });
+        }
 
         // Get and eval the optional timer, animation and location watch setup scripts
-        timercomp.get('setup', function(doc, e) {
-            if (isNil(doc)) {
-                log('error on get(timer, setup)', e);
-                return false;
-            }
+        if (isbound("timer", comps)) {
+            timercomp.get('setup', function(doc, e) {
+                if (isNil(doc)) {
+                    debug('error on get(timer, setup)', e);
+                    return false;
+                }
 
-            // Evaluate the component init expression
-            return evalcompinit(doc);
-        });
-        animationcomp.get('setup', function(doc, e) {
-            if (isNil(doc)) {
-                log('error on get(animation, setup)', e);
-                return false;
-            }
+                // Evaluate the component init expression
+                return evalcompinit(doc);
+            });
+        }
 
-            // Evaluate the component init expression
-            return evalcompinit(doc);
-        });
-        locationcomp.get('setup', function(doc, e) {
-            if (isNil(doc)) {
-                log('error on get(location, setup)', e);
-                return false;
-            }
+        if (isbound("animation", comps)) {
+            animationcomp.get('setup', function(doc, e) {
+                if (isNil(doc)) {
+                    debug('error on get(animation, setup)', e);
+                    return false;
+                }
 
-            // Evaluate the component init expression
-            return evalcompinit(doc);
-        });
+                // Evaluate the component init expression
+                return evalcompinit(doc);
+            });
+        }
+
+        if (isbound("location", comps)) {
+            locationcomp.get('setup', function(doc, e) {
+                if (isNil(doc)) {
+                    debug('error on get(location, setup)', e);
+                    return false;
+                }
+
+                // Evaluate the component init expression
+                return evalcompinit(doc);
+            });
+        }
 
         return true;
 
     } catch(e) {
-        log('error in getpagedata()', e);
+        debug('error in getappdata()', e);
         return true;
     }
 }
 
 /**
+ * Return the page in an ATOM entry.
+ */
+function atompage(doc) {
+    var entry = atom.readATOMEntry(mklist(doc));
+    if (isNil(entry))
+        return mklist();
+    var content = namedElementChild("'content", car(entry));
+    if (content == null)
+        return mklist();
+    return elementChildren(content);
+}
+
+/**
+ * Get the app page.
+ */
+function getapppage(appname, compos) {
+    pagecomp.get(appname, function(doc, e) {
+        //debug('page get');
+        if (isNil(doc)) {
+            debug('error in getapppage', e);
+            return false;
+        }
+
+        // Set the app HTML page into the content div
+        var page = atompage(doc);
+        contentdiv.innerHTML = writeStrings(writeXML(page, false));
+        apppage = page;
+
+        // Merge in the app data
+        if (!isNil(appcomposite))
+            getappdata(appname, apppage, appcomposite);
+});
+
+}
+
+/**
  * Build a query string from the values of the page's input fields.
  */
 function compquery() {
@@ -658,7 +726,7 @@ function buttonClickHandler(id, appname)
         var uri = compquery();
         return sca.component(id, appname).get(uri, function(doc, e) {
             if (isNil(doc)) {
-                log('error on get(button, ' + uri + ')', e);
+                debug('error on get(button, ' + uri + ')', e);
                 return false;
             }
 
@@ -666,7 +734,7 @@ function buttonClickHandler(id, appname)
             updatepage(docdata(doc));
         });
     } catch(e) {
-        log('error in buttonClickHandler()', e);
+        debug('error in buttonClickHandler()', e);
         return true;
     }
 }
@@ -679,7 +747,7 @@ function intervalHandler() {
         var uri = compquery();
         return timercomp.get(uri, function(doc, e) {
             if (isNil(doc)) {
-                log('error on get(timer, ' + uri + ')', e);
+                debug('error on get(timer, ' + uri + ')', e);
                 return false;
             }
 
@@ -687,7 +755,7 @@ function intervalHandler() {
             updatepage(docdata(doc));
         });
     } catch(e) {
-        log('error in intervalHandler()', e);
+        debug('error in intervalHandler()', e);
         return true;
     }
 }
@@ -700,7 +768,7 @@ function setupIntervalHandler(msec) {
     try {
         return setInterval(intervalHandler, msec);
     } catch(e) {
-        log('error in setupIntervalHandler()', e);
+        debug('error in setupIntervalHandler()', e);
         return true;
     }
 }
@@ -753,7 +821,7 @@ function animationHandler() {
             var uri = compquery();
             return animationcomp.get(uri, function(doc, e) {
                 if (isNil(doc)) {
-                    log('error on get(animation, ' + uri + ')', e);
+                    debug('error on get(animation, ' + uri + ')', e);
                     return false;
                 }
 
@@ -769,7 +837,7 @@ function animationHandler() {
         return applyAnimation();
 
     } catch(e) {
-        log('error in animationHandler()', e);
+        debug('error in animationHandler()', e);
         return true;
     }
 }
@@ -783,7 +851,7 @@ function setupAnimationHandler(msec, loo
     try {
         return setInterval(animationHandler, msec);
     } catch(e) {
-        log('error in setupAnimationHandler()', e);
+        debug('error in setupAnimationHandler()', e);
         return true;
     }
 }
@@ -800,7 +868,7 @@ function locationHandler(pos) {
         var uri = compquery();
         return locationcomp.get(uri, function(doc, e) {
             if (isNil(doc)) {
-                log('error on get(location, ' + uri + ')', e);
+                debug('error on get(location, ' + uri + ')', e);
                 return false;
             }
 
@@ -813,7 +881,7 @@ function locationHandler(pos) {
 }
 
 function locationErrorHandler(e) {
-    log('location error', e);
+    debug('location error', e);
     if (!isNil(locationWatch)) {
         try {
             navigator.geolocation.clearWatch(locationWatch);
@@ -833,7 +901,7 @@ function setupLocationHandler() {
         try {
             locationWatch = navigator.geolocation.watchPosition(locationHandler, locationErrorHandler);
         } catch(e) {
-            log('error in installLocationHandler()', e);
+            debug('error in installLocationHandler()', e);
         }
         return true;
     }
@@ -844,9 +912,21 @@ function setupLocationHandler() {
 }
 
 /**
- * Return the page in an ATOM entry.
+ * Handle orientation change.
  */
-function atompage(doc) {
+document.body.onorientationchange = function(e) {
+    //debug('onorientationchange');
+
+    // Scroll to the top and hide the address bar
+    window.scrollTo(0, 0);
+
+    return true;
+};
+
+/**
+ * Return the composite in an ATOM entry.
+ */
+function atomcomposite(doc) {
     var entry = atom.readATOMEntry(mklist(doc));
     if (isNil(entry))
         return mklist();
@@ -856,46 +936,51 @@ function atompage(doc) {
     return elementChildren(content);
 }
 
-// Load the app page
-pagecomp.get(appname, function(doc, e) {
-    //log('page get');
-    if (isNil(doc)) {
-        log('error getting app page', e);
-        return false;
-    }
-
-    // Set the app HTML page into the content div
-    //log('page', doc);
-    var el = atompage(doc);
-    contentdiv.innerHTML = writeStrings(writeXML(el, false));
-
-    // Merge in the app data
-    getpagedata(appname);
-});
-
 /**
- * Handle orientation change.
+ * Get the app composite.
  */
-document.body.onorientationchange = function(e) {
-    //log('onorientationchange');
-
-    // Scroll to the top and hide the address bar
-    window.scrollTo(0, 0);
-
-    return true;
-};
+function getappcomposite(appname) {
+    return composcomp.get(appname, function(doc, e) {
+        //debug('page get');
+        if (isNil(doc)) {
+            debug('error in getappcomposite', e);
+            return false;
+        }
+
+        var compos = atomcomposite(doc);
+        if (isNil(compos)) {
+
+            // Create a default empty composite if necessary
+            var x = '<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" ' +
+                'targetNamespace="http://app" name="app"></composite>';
+            compos = readXML(mklist(x));
+        }
+        appcomposite = compos;
+
+        // Merge in the app data
+        if (!isNil(apppage))
+            getappdata(appname, apppage, appcomposite);
+    });
+}
 
 /**
  * Document load post processing.
  */
 function onload() {
-    //log('onload');
+    //debug('onload');
+
+    // Scroll to the top and hide the address bar
+    window.scrollTo(0, 0);
 
     // Show the page
     document.body.style.visibility = 'visible';
 
-    // Scroll to the top and hide the address bar
-    window.scrollTo(0, 0);
+    // Initialize the app composite
+    getappcomposite(appname);
+
+    // Initialize the app page
+    getapppage(appname);
+
     return true;
 }
 

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/cache-manifest.cmf
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/cache-manifest.cmf?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/cache-manifest.cmf (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/cache-manifest.cmf Mon May 28 16:49:36 2012
@@ -1,6 +1,6 @@
 CACHE MANIFEST
 
-# Version 5
+# Version 6
 
 # App resources
 /

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/clone/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/clone/index.html?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/clone/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/clone/index.html Mon May 28 16:49:36 2012
@@ -17,59 +17,45 @@
  * specific language governing permissions and limitations
  * under the License.    
 -->
-<div id="bodydiv" class="bodydiv">
+<div id="bodydiv" class="body">
 
-<table style="width: 100%;">
-<tr>
-<td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td>
-<td style="vertical-align: middle; text-align: right;"><span id="status" style="font-weight: bold; color: #808080;"></span></td>
-</tr>
-</table>
-
-<table style="width: 100%;">
-<tr>
-<th id="th" class="thl thr" style="padding-top: 4px; padding-bottom:4px;">Clone this App</th>
-</tr>
-</table>
+<div class="viewform">
 
 <form id="cloneAppForm">
 <table style="width: 100%;">
 <tr><td><b>New App Name:</b></td></tr>
-<tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr>
+<tr><td><input type="text" id="appName" class="flatentry" size="15" autocapitalize="off" placeholder="Your app name"/></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>Icon:</b></td></tr>
 <tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr>
-<tr><td><input type="checkbox" value="shared"/><span>Shared</span></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>App Title:</b></td></tr>
-<tr><td><input type="text" id="appTitle" size="30" placeholder="Enter the title of your app" style="width: 300px;"/></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>Title:</b></td></tr>
+<tr><td><input type="text" id="appTitle" class="flatentry" size="30" placeholder="Enter the title of your app" style="width: 300px;"/></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr>
-<tr><td><textarea id="appDescription" cols="40" rows="3" placeholder="Enter a short description of your app" style="width: 300px;"></textarea></td></tr>
+<tr><td><textarea id="appDescription" class="flatentry" cols="40" rows="3" placeholder="Enter a short description of your app" style="width: 300px;"></textarea></td></tr>
 <tr><td>
-<input id="cloneAppOKButton" type="submit" class="graybutton" style="font-weight: bold;" value="Clone" title="Clone the app"/>
+<input id="cloneAppOKButton" type="submit" class="graybutton bluebutton" style="font-weight: bold;" value="Clone" title="Clone the app"/>
 <input id="cloneAppCancelButton" type="button" class="graybutton" value="Cancel"/>
 </td></tr>
 </table>
 </form>
 
+</div>
+
 <script type="text/javascript">
 
 // Get the app name
 var appname = ui.fragmentParams(location)['app'];
 
 // Set page titles
-var tclone = isNil(config.clone)? 'Clone' : config.clone;
-document.title = ui.windowtitle(location.hostname) + ' - ' + tclone + ' - ' + appname;
-$('appNameHeader').innerHTML = '<a href=\"/' + appname + '/\" target=\"' + '_blank' + '\">' + appname + '</a>';
-$('th').innerHTML = tclone + ' this App';
-$('cloneAppOKButton').value = tclone;
-$('cloneAppOKButton').title = tclone + ' this app';
+document.title = ui.windowtitle(location.hostname) + ' - ' + config.clone + ' - ' + appname;
+$('viewhead').innerHTML = '<span class="smenu">' + config.clone + ' ' + appname + '</span>';
+$('cloneAppOKButton').value = config.clone;
+$('cloneAppOKButton').title = config.clone + ' this app';
 
 // Set images
 $('appimg').src = ui.b64img(appcache.get('/public/app.b64'));
 
 // Init service references
 var editWidget = sca.component("EditWidget");
-var dashboards = sca.reference(editWidget, "dashboards");
 var apps = sca.reference(editWidget, "apps");
 
 /**
@@ -90,45 +76,58 @@ function getapp(name) {
 
         // Stop now if we didn't get the app
         if (doc == null) {
-            showStatus('No data');
+            showError('App not available');
             return false;
         }
         showStatus(defaultStatus());
 
         appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name));
-        var title = cadr(assoc("'title", cdr(appentry)));
-        $('appTitle').value = title;
-        $('appDescription').innerHTML = '';
+        $('appTitle').value = cadr(assoc("'title", cdr(appentry)));
+        var content = cadr(assoc("'content", cdr(appentry)));
+        var description = assoc("'description", content);
+        $('appDescription').value = isNil(description) || isNil(cadr(description))? '' : cadr(description);
         savedappentryxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
         return true;
     });
 }
 
 /**
- * Clone an app.
+ * Save an app.
  */
-$('cloneAppForm').onsubmit = function() {
-    var name = $('appName').value;
-    if (name == '')
-        return false;
+function save(name, entryxml) {
     showStatus('Saving');
-
-    // Clone the app
-    var title = $('appTitle').value;
-    var app = mklist(mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", appname)));
-    var entry = atom.writeATOMEntry(valuesToElements(app));
-    dashboards.put(name, car(entry), function(e) {
+    savedappentryxml = entryxml;
+    apps.put(name, savedappentryxml, function(e) {
         if (e) {
             showStatus('Local copy');
             return false;
         }
-        showStatus(defaultStatus());
+        showStatus('Saved');
 
         // Open it in the page editor
         ui.navigate('/#view=page&app=' + name, '_view');
         return false;
     });
     return false;
+}
+
+/**
+ * Clone an app.
+ */
+$('cloneAppForm').onsubmit = function() {
+    var name = $('appName').value;
+    if (name == '') {
+        showError('Missing app name');
+        return false;
+    }
+    showStatus('Saving');
+
+    // Clone the app
+    var title = $('appTitle').value;
+    var description = $('appDescription').value;
+    appentry = mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", appname), mklist("'content", mklist("'stats", mklist("'description", description))));
+    var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
+    return save(name, entryxml);
 };
 
 /**

Added: tuscany/sca-cpp/trunk/hosting/server/htdocs/config.js
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/config.js?rev=1343316&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/config.js (added)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/config.js Mon May 28 16:49:36 2012
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+if (isNil(config))
+    config = {};
+
+/**
+ * UI configuration.
+ */
+config.windowtitle = 'App Builder'
+config.pagetitle = '<span style="font-weight: bold;">App Builder</span>';
+config.hometitle = '<br/><span style="font-weight: bold;">Create SCA Composite Apps</span><br/><br/>';
+config.clone = 'Clone';
+config.logic = 'Logic';
+

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/create/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/create/index.html?rev=1343316&r1=1343315&r2=1343316&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/create/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/create/index.html Mon May 28 16:49:36 2012
@@ -17,68 +17,55 @@
  * specific language governing permissions and limitations
  * under the License.    
 -->
-<div id="bodydiv" class="bodydiv">
+<div id="bodydiv" class="body">
 
-<table style="width: 100%;">
-<tr>
-<td><h2><span id="h1"></span></h2></td>
-<td style="vertical-align: middle; text-align: right;"><span id="status" style="font-weight: bold; color: #808080;"></span></td>
-</tr>
-</table>
-
-<table style="width: 100%;">
-<tr>
-<th class="thl thr" style="padding-top: 4px; padding-bottom:4px;">Create an App</th>
-</tr>
-</table>
+<div class="viewform">
 
 <form id="createAppForm">
 <table style="width: 100%;">
 <tr><td><b>App Name:</b></td></tr>
-<tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/></td></tr>
+<tr><td><input type="text" id="appName" class="flatentry" size="15" autocapitalize="off" placeholder="Your app name"/></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr>
 <tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr>
-<tr><td><input type="checkbox" value="shared"/><span>Shared</span></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>App Title:</b></td></tr>
-<tr><td><input type="text" id="appTitle" size="30" placeholder="Enter the title of your app" style="width: 300px;"/></td></tr>
+<tr><td><input type="text" id="appTitle" class="flatentry" size="30" placeholder="Enter the title of your app" style="width: 300px;"/></td></tr>
 <tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr>
-<tr><td><textarea id="appDescription" cols="40" rows="3" placeholder="Enter a short description of your app" style="width: 300px;"></textarea></td></tr>
+<tr><td><textarea id="appDescription" class="flatentry" cols="40" rows="3" placeholder="Enter a short description of your app" style="width: 300px;"></textarea></td></tr>
 <tr><td>
-<input id="createAppOKButton" type="submit" class="graybutton" style="font-weight: bold;" value="Create" title="Create the app"/>
+<input id="createAppOKButton" type="submit" class="graybutton bluebutton" style="font-weight: bold;" value="Create" title="Create the app"/>
 <input id="createAppCancelButton" type="button" class="graybutton" value="Cancel"/>
 </td></tr>
 </table>
 </form>
 
+</div>
+
 <script type="text/javascript">
 
 // Set page titles
 document.title = ui.windowtitle(location.hostname) + ' - Create App';
-$('h1').innerHTML = ui.hometitle(location.hostname);
+$('viewhead').innerHTML = '<span class="smenu">Create an App</span>';
 
 // Set images
 $('appimg').src = ui.b64img(appcache.get('/public/app.b64'));
 
 // Init service references
 var editWidget = sca.component("EditWidget");
-var dashboards = sca.reference(editWidget, "dashboards");
 var apps = sca.reference(editWidget, "apps");
 
 /**
- * Create an app.
+ * The current app entry and corresponding saved XML content.
  */
-$('createAppForm').onsubmit = function() {
-    var name = $('appName').value;
-    if (name == '')
-        return false;
-    showStatus('Saving');
+var appentry;
+var savedappentryxml = '';
 
-    // Clone the '.new' app template
-    var title = $('appTitle').value;
-    var app = mklist(mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", 'new')));
-    var entry = atom.writeATOMEntry(valuesToElements(app));
-    dashboards.put(name, car(entry), function(e) {
+/**
+ * Save an app.
+ */
+function save(name, entryxml) {
+    showStatus('Saving');
+    savedappentryxml = entryxml;
+    apps.put(name, savedappentryxml, function(e) {
         if (e) {
             showStatus('Local copy');
             return false;
@@ -90,6 +77,25 @@ $('createAppForm').onsubmit = function()
         return false;
     });
     return false;
+}
+
+/**
+ * Create an app.
+ */
+$('createAppForm').onsubmit = function() {
+    var name = $('appName').value;
+    if (name == '') {
+        showError('Missing app name');
+        return false;
+    }
+    showStatus('Modified');
+
+    // Clone the 'new' app template
+    var title = $('appTitle').value;
+    var description = $('appDescription').value;
+    appentry = mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", 'new'), mklist("'content", mklist("'stats", mklist("'description", description))));
+    var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
+    return save(name, entryxml);
 };
 
 /**

Added: tuscany/sca-cpp/trunk/hosting/server/htdocs/delete/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/delete/index.html?rev=1343316&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/delete/index.html (added)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/delete/index.html Mon May 28 16:49:36 2012
@@ -0,0 +1,127 @@
+<!DOCTYPE html>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+-->
+<div id="bodydiv" class="body">
+
+<div class="viewform">
+
+<form id="deleteAppForm">
+<table style="width: 100%;">
+<tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr>
+<tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>App Title:</b></td></tr>
+<tr><td><input type="text" id="appTitle" class="flatentry" size="30" readonly="readonly" style="width: 300px;"/></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>Author:</b></td></tr>
+<tr><td><span id="appAuthor"></span></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>Updated:</b></td></tr>
+<tr><td><span id="appUpdated"></span></td></tr>
+<tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr>
+<tr><td><textarea id="appDescription" class="flatentry" cols="40" rows="3" readonly="readonly" style="width: 300px;"></textarea></td></tr>
+<tr><td>
+<input id="deleteAppOKButton" type="submit" class="graybutton bluebutton" style="font-weight: bold;" value="Delete" title="Delete the app"/>
+<input id="deleteAppCancelButton" type="button" class="graybutton" value="Cancel"/>
+</td></tr>
+</table>
+</form>
+
+</div>
+
+<script type="text/javascript">
+
+// Get the app name
+var appname = ui.fragmentParams(location)['app'];
+
+// Set page titles
+document.title = ui.windowtitle(location.hostname) + ' - ' + 'Delete' + ' - ' + appname;
+$('viewhead').innerHTML = '<span class="smenu">Delete ' + appname + '</span>';
+
+// Set images
+$('appimg').src = ui.b64img(appcache.get('/public/app.b64'));
+
+// Init service references
+var editWidget = sca.component("EditWidget");
+var apps = sca.reference(editWidget, "apps");
+
+/**
+ * The current app entry and corresponding saved XML content.
+ */
+var appentry;
+
+/**
+ * Get and display an app.
+ */
+function getapp(name) {
+    if (isNil(name))
+        return false;
+    showStatus('Loading');
+
+    return apps.get(name, function(doc) {
+
+        // Stop now if we didn't get the app
+        if (doc == null) {
+            showError('App not available');
+            return false;
+        }
+        showStatus(defaultStatus());
+
+        appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name));
+        $('appTitle').value = cadr(assoc("'title", cdr(appentry)));
+        $('appAuthor').innerHTML = cadr(assoc("'author", cdr(appentry)));
+        $('appUpdated').innerHTML = cadr(assoc("'updated", cdr(appentry)));
+        var content = cadr(assoc("'content", cdr(appentry)));
+        var description = assoc("'description", content);
+        $('appDescription').value = isNil(description) || isNil(cadr(description))? '' : cadr(description);
+        return true;
+    });
+}
+
+/**
+ * Delete an app.
+ */
+$('deleteAppForm').onsubmit = function() {
+    showStatus('Deleting');
+
+    // Delete the app
+    apps.del(appname, function(e) {
+        if (e) {
+            showStatus('Local copy');
+            return false;
+        }
+        showStatus(defaultStatus());
+
+        // Return to the app store
+        ui.navigate('/#view=store', '_view');
+        return false;
+    });
+    return false;
+};
+
+/**
+ * Cancel cloning an app.
+ */
+$('deleteAppCancelButton').onclick = function() {
+    history.back();
+};
+
+// Get the current app
+getapp(appname);
+
+</script>
+
+</div>