]> dev.renevier.net Git - syj.git/commitdiff
interface to manage list of created routes
authorarno <arno@renevier.net>
Wed, 11 Aug 2010 19:31:50 +0000 (21:31 +0200)
committerarno <arno@renevier.net>
Fri, 13 Aug 2010 11:55:04 +0000 (13:55 +0200)
application/configs/application.ini
application/controllers/AccountController.php
application/controllers/ListController.php [new file with mode: 0644]
application/controllers/PathController.php
application/controllers/helpers/SyjSession.php
application/layouts/scripts/footer.phtml
application/models/PathMapper.php
application/views/scripts/list/index.phtml [new file with mode: 0644]
public/css/list.css [new file with mode: 0644]
public/js/list.js [new file with mode: 0644]
public/js/syj.js

index 80b24205b389f17d0e58260f8b83f0890e04ba9b..fa4ec8ba58aa2aa6ba12c11f833beee8a4d5eaae 100644 (file)
@@ -49,12 +49,14 @@ resources.router.routes.root.defaults.controller = "idx"
 resources.router.routes.path.route = "path/"
 resources.router.routes.path.defaults.controller = "path"
 resources.router.routes.path.defaults.action = "index"
-
 ; path/xxx/update
 resources.router.routes.path_update.route = "path/:idx/update"
 resources.router.routes.path_update.defaults.controller = "path"
 resources.router.routes.path_update.defaults.action = "update"
-
+; path/xxx/delete
+resources.router.routes.path_delete.route = "path/:idx/delete"
+resources.router.routes.path_delete.defaults.controller = "path"
+resources.router.routes.path_delete.defaults.action = "delete"
 ; login/
 resources.router.routes.login.route = "login/"
 resources.router.routes.login.defaults.controller = "login"
@@ -91,6 +93,10 @@ resources.router.routes.cron.defaults.action = "index"
 resources.router.routes.newpwd.route = "newpwd/"
 resources.router.routes.newpwd.defaults.controller = "newpwd"
 resources.router.routes.newpwd.defaults.action = "index"
+; list/
+resources.router.routes.list.route = "list/"
+resources.router.routes.list.defaults.controller = "list"
+resources.router.routes.list.defaults.action = "index"
 
 ; database
 resources.db.params.username = "syj"
index 76124908d504b90645d13658f53b87f5d9f0a7e1..f1d977facaf70ec4818cc3ba20b026c57b8326c9 100644 (file)
@@ -6,6 +6,8 @@ class AccountController extends Zend_Controller_Action
 {
 
     public function init() {
+        $this->_helper->SyjSession->needsLogin();
+
         $this->view->headScript()->appendFile('js/prototype.js');
         $this->view->headScript()->appendFile('js/utils.js');
         $this->view->headScript()->appendFile('js/account.js');
@@ -18,20 +20,6 @@ class AccountController extends Zend_Controller_Action
         $user = $this->_helper->SyjSession->user();
         $request = $this->getRequest();
 
-        if ($user === null) {
-            $encodeduri = implode('/', array_map('urlencode', explode('/', $request->getRequestUri())));
-            $loginurl = $this->view->addParamToUrl($this->view->baseUrl() . '/' . 'login', 'redirect', $encodeduri);
-            $translator = Zend_Registry::get('Zend_Translate');
-            $lang = Zend_Controller_Front::getInstance()->getRequest()->getQuery('lang');
-            if ($lang) {
-                $adapter = $translator->getAdapter();
-                if ($adapter->isAvailable($lang)) {
-                    $loginurl = $this->view->addParamToUrl($loginurl, 'lang', $lang);
-                }
-            }
-            $this->_helper->Redirector->gotoURL($loginurl, array('prependBase' => false));
-        }
-
         $form = new Syj_Form_Account(array('name' => 'accountform'));
         $formData = $request->getPost();
 
diff --git a/application/controllers/ListController.php b/application/controllers/ListController.php
new file mode 100644 (file)
index 0000000..317505e
--- /dev/null
@@ -0,0 +1,45 @@
+<?php
+/*  This file is part of Syj, Copyright (c) 2010 Arnaud Renevier,
+    and is published under the AGPL license. */
+
+class ListController extends Zend_Controller_Action
+{
+
+    public function init() {
+        $this->_helper->SyjSession->needsLogin();
+
+        $this->view->headScript()->appendFile('js/OpenLayers.js');
+        $this->view->headScript()->appendFile('js/prototype.js');
+        $this->view->headScript()->appendFile('js/utils.js');
+        $this->view->headScript()->appendFile('js/list.js');
+
+        $this->view->headLink()->appendStylesheet('css/generic.css');
+        $this->view->headLink()->appendStylesheet('css/list.css');
+        $this->view->headTitle($this->view->translate("my routes"));
+    }
+
+    public function indexAction() {
+        $user = $this->_helper->SyjSession->user();
+        $pathMapper = new Syj_Model_PathMapper();
+        $list = $pathMapper->fetchByCreator($user);
+        $paginator = Zend_Paginator::factory($list);
+
+        $paginator->setDefaultItemCountPerPage(20);
+        $paginator->setCurrentPageNumber($this->_getParam('page', 1));
+        $this->view->paginator = $paginator;
+        $this->_jsLocaleStrings();
+    }
+
+    protected function _jsLocaleStrings() {
+        $this->view->jslocales = array(
+            'confirmDelete' => __("There is no undo. Delete this route definitively ?"),
+            'notReachedError' => __("server could not be reached"),
+            'requestError' => __("server did not understood request. That's probably caused by a bug in SYJ"),
+            'gonePathError' => __("route has been deleted from the server."),
+            'serverError' => __("there was a server error"),
+            'unknownError' => __("there was an unknown error"),
+            'deleteSuccess' => __("route was successfully deleted"),
+            );
+    }
+
+}
index c3c085a8695ff1eddbed1874edea580e8b9644ed..aa41866679103703bb66909032302ecd59fd645d 100644 (file)
@@ -5,10 +5,32 @@
 class PathController extends Zend_Controller_Action
 {
     public function indexAction() {
-        return $this->save(new Syj_Model_Path());
+        $formData = $this->_helper->SyjPostData->getPostData('Syj_Form_Geom');
+        $path = new Syj_Model_Path();
+
+        $user = $this->_helper->SyjSession->user();
+        if (!$user and !$formData["geom_accept"]) {
+            throw new Syj_Exception_Request();
+        }
+        $path->creator = $user;
+        $path->creatorIp = $this->getRequest()->getClientIp(true);
+
+        return $this->save($path, $formData);
     }
 
     public function updateAction() {
+        $formData = $this->_helper->SyjPostData->getPostData('Syj_Form_Geom');
+        return $this->save($this->getPath(), $formData);
+    }
+
+    public function deleteAction() {
+        $path = $this->getPath();
+        $pathMapper = new Syj_Model_PathMapper();
+        $pathMapper->delete ($path);
+        $this->_helper->SyjApi->setCode(204);
+    }
+
+    public function getPath() {
         $idx = $this->getRequest()->getUserParam('idx');
         $path = new Syj_Model_Path();
         $pathMapper = new Syj_Model_PathMapper();
@@ -19,28 +41,15 @@ class PathController extends Zend_Controller_Action
                 throw new Syj_Exception_NotFound('Not Found', 404);
             }
         }
-        return $this->save($path);
-    }
 
-    public function save(Syj_Model_Path $path) {
-        $formData = $this->_helper->SyjPostData->getPostData('Syj_Form_Geom');
-
-        /* authorization check */
         $user = $this->_helper->SyjSession->user();
-        if (!$user and !$formData["geom_accept"]) {
-            throw new Syj_Exception_Request();
-        }
-
-        /* setting creator property */
-        if ($path->getId()) {
-            if (!$path->isCreator($user)) {
-                throw new Syj_Exception_Request();
-            }
-        } else {
-            $path->creator = $user;
+        if (!$path->isCreator($user)) {
+            throw new Syj_Exception_Forbidden();
         }
-        $path->creatorIp = $this->getRequest()->getClientIp(true);
+        return $path;
+    }
 
+    public function save(Syj_Model_Path $path, $formData) {
         /* setting geom property */
         $decoder = new gisconverter\WKT();
         try {
index 702bfa25c739c0923f024ecc3151852c8adf9027..11c369fb34fa7f5cf85c6fa085ad1f5ca4519316 100644 (file)
@@ -53,4 +53,26 @@ class Syj_Controller_Action_Helper_SyjSession extends Zend_Controller_Action_Hel
             return null;
         }
     }
+
+    public function needsLogin() {
+        $user = self::user();
+        if ($user) {
+            return;
+        }
+        $viewRenderer = Zend_Controller_Action_HelperBroker::getStaticHelper('viewRenderer');
+        $view = $viewRenderer->view;
+        $request = $this->getRequest();
+
+        $encodeduri = implode('/', array_map('urlencode', explode('/', $request->getRequestUri())));
+        $loginurl = $view->addParamToUrl($view->baseUrl() . '/' . 'login', 'redirect', $encodeduri);
+        $translator = Zend_Registry::get('Zend_Translate');
+        $lang = $request->getQuery('lang');
+        if ($lang) {
+            $adapter = $translator->getAdapter();
+            if ($adapter->isAvailable($lang)) {
+                $loginurl = $view->addParamToUrl($loginurl, 'lang', $lang);
+            }
+        }
+        $this->getActionController()->getHelper('Redirector')->gotoURL($loginurl, array('prependBase' => false));
+    }
 }
index 08b2ff95e67124410037a5aa61b731706c0167f5..cce5e7fce79304c1d92debe6f9f563e6a83ab835 100644 (file)
@@ -40,6 +40,18 @@ if ($mainpage or $this->loggedUser) {
         'logged-show');
 }
 
+/*
+ * list link
+ */
+if ($mainpage or $this->loggedUser) {
+    echo $this->footerLink(array(
+            'route' => 'list',
+            'action'     => 'index',
+            'controller' => 'list'),
+        $this->translate("my routes"), false,
+        'logged-show');
+}
+
 /*
  * login or logout links
  */
index c89936455905e9c060110665e9d194b864d6adb2..1e0e973c4489dc0e1bb9673cefcbeb30c949a72d 100644 (file)
@@ -42,9 +42,18 @@ class Syj_Model_PathMapper
         return $this->_fetchItem($select, $path);
     }
 
-    public function fetchAll() {
+    public function fetchByCreator(Syj_Model_User $user) {
         $select = $this->_select();
+        $select->where('creator = ?', (int)$user->id)->order('id');
+        return $this->fetchAll($select);
+    }
+
+    public function fetchAll(Zend_Db_Table_Select $select) {
+        if (!isset($select)) {
+            $select = $this->_select();
+        }
 
+        $table = $this->getDbTable();
         $resultSet = $table->fetchAll($select);
 
         $entries   = array();
@@ -69,6 +78,10 @@ class Syj_Model_PathMapper
         }
     }
 
+    public function delete (Syj_Model_Path $path) {
+        $this->getDbTable()->delete(array('id = ?' => $path->getId()));
+    }
+
     protected function _itemFromRow(Syj_Model_Path $item, Zend_Db_Table_Row $row) {
         $decoder = new gisconverter\WKT();
         $geom = $decoder->geomFromText($row->wkt);
diff --git a/application/views/scripts/list/index.phtml b/application/views/scripts/list/index.phtml
new file mode 100644 (file)
index 0000000..31d3a50
--- /dev/null
@@ -0,0 +1,81 @@
+    <noscript>
+        <style type="text/css">
+            #container, #navigation, #message {
+                display: none;
+            }
+        </style>
+
+        <p><?php echo $this->translate('SYJ needs javascript. Please activate scripts in your browser.');?></p>
+    </noscript>
+
+    <div id="message"></div>
+
+
+<?php
+    print $this->localeSwitcher();
+    if ($this->paginator->count() == 0) {
+        $link = $this->Anchor($this->baseUrl(), $this->translate ("create a route"), array(), false);
+        $noroutecontent = $this->translate("you have created no route yet, you may want to %s", $link);
+
+        printf ('<div class="warn noroute">%s</div>', $noroutecontent);
+        return;
+    }
+
+    $pages = $this->paginator->getPages();
+    if (isset($pages->previous) or isset($pages->next)) {
+        print '<div id="navigation">';
+
+        if (isset($pages->previous)) {
+            $title = $this->translate("first page");
+            $href = $this->addParamToUrl($this->url(), 'page', (string)$pages->first, true);
+            printf ('<a class="page-link" title="%s" href="%s">«</a>', $title, $href);
+
+            $title = $this->translate("previous page");
+            $href = $this->addParamToUrl($this->url(), 'page', (string)$pages->previous, true);
+            printf ('<a class="page-link" title="%s" href="%s">&lt;</a>', $title, $href);
+        } else {
+            print '<span class="page-link">«</span>';
+            print '<span class="page-link">&lt;</span>';
+        }
+
+        if (isset($pages->next)) {
+            $title = $this->translate("next page");
+            $href = $this->addParamToUrl($this->url(), 'page', (string)$pages->next, true);
+            printf ('<a class="page-link" title="%s" href="%s">&gt;</a>', $title, $href);
+
+            $title = $this->translate("last page");
+            $href = $this->addParamToUrl($this->url(), 'page', (string)$pages->last, true);
+            printf ('<a class="page-link" title="%s" href="%s">»</a>', $title, $href);
+        } else {
+            print '<span class="page-link">&gt;</span>';
+            print '<span class="page-link">»</span>';
+        }
+
+        print '</div>';
+    }
+
+    print '<div id="container">';
+    foreach ($this->paginator as $item) {
+
+        $map = sprintf('<div class="map" data-geom="%s"></div>', $this->escape($item->geom));
+        $href = $this->url(array(
+            'controller' => 'idx',
+            'action' => 'index',
+            'url' => $item->id
+        ), 'idx');
+        $maplink = $this->Anchor($href, $map, array(), false);
+        $modifylink = $this->Anchor($href, $this->translate("modify"));
+        $duplicatelink = sprintf('<a href="#" class="duplicate-link">%s</a>', $this->translate("duplicate"));
+        $deletelink = sprintf('<a href="#" class="delete-link">%s</a>', $this->translate("delete"));
+
+        printf ('<div class="item" data-id="%d">
+                <div class="geom">%s</div>
+                <div class="controls">%s<br>%s<br>%s</div>
+                <div class="title">%s</div>
+                </div>
+                ',
+                (int)$item->id, $maplink, $modifylink, $duplicatelink, $deletelink, $this->escape($item->displayTitle));
+
+    }
+    print '</div>';
+?>
diff --git a/public/css/list.css b/public/css/list.css
new file mode 100644 (file)
index 0000000..c78f909
--- /dev/null
@@ -0,0 +1,63 @@
+.item {
+    float: left;
+    width: 240px;
+    margin: 0px 10px 10px 10px;
+}
+
+.geom {
+    float: left;
+    border: 1px solid black;
+    width: 100px;
+    height: 100px;
+    margin: 0 10px 6px 0;
+}
+
+.map {
+    width: 100%;
+    height: 100%;
+}
+
+.title {
+    height: 2em;
+    clear: left;
+}
+
+.page-link {
+    margin-left: 10px;
+    margin-right: 10px;
+}
+#navigation {
+    text-align: center;
+}
+
+#footer {
+    position: fixed;
+    z-index: 2000;
+    background-color: white;
+}
+
+.noroute {
+    text-align: center;
+    border-width: 2px;
+    border-style: solid;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    border-radius: 5px;
+    width: 40%;
+    margin: auto;
+    padding: 12px;
+    margin-top: 28px;
+}
+
+#message {
+    width: 40%;
+    margin: 20px auto 20px auto;
+    padding: 1.5em 1.5em 1.5em 1.5em;
+    text-align: center;
+    border-width: 2px;
+    border-style: solid;
+    -moz-border-radius: 5px;
+    -webkit-border-radius: 5px;
+    border-radius: 5px;
+}
+
diff --git a/public/js/list.js b/public/js/list.js
new file mode 100644 (file)
index 0000000..db95dc5
--- /dev/null
@@ -0,0 +1,90 @@
+var WGS84 = new OpenLayers.Projection("EPSG:4326");
+var Mercator = new OpenLayers.Projection("EPSG:900913");
+
+function deletePath(evt) {
+    evt.stop();
+    if (!confirm(SyjStrings.confirmDelete)) {
+        return;
+    }
+    var link = evt.target,
+        item = $(link).up('.item'),
+        id = item.getAttribute('data-id');
+
+    $("message").hide();
+    new Ajax.Request('path/' + id.toString() + '/delete', {
+        method: 'post',
+        onSuccess: function(transport) {
+            item.down('.title').update();
+            item.down('.geom').update().setStyle({backgroundColor: 'gray'});
+            $("message").setMessage(SyjStrings.deleteSuccess, "success");
+        },
+        onFailure: function(transport) {
+            var httpCode = 0, message = "";
+            if (transport) {
+                httpCode = transport.getStatus();
+            }
+            switch (httpCode) {
+                case 0:
+                    message = SyjStrings.notReachedError;
+                break;
+                case 400:
+                case 403:
+                    location = loginlink();
+                    return;
+                break;
+                case 404:
+                     message = SyjStrings.requestError;
+                break;
+                case 410:
+                    message = SyjStrings.gonePathError;
+                break;
+                case 500:
+                    message = SyjStrings.serverError;
+                break;
+                default:
+                    message = SyjStrings.unknownError;
+                break;
+            }
+            $("message").setMessage(message, "error");
+        }
+    });
+}
+
+document.observe("dom:loaded", function() {
+    $("message").hide();
+    $$(".map").each(function(elt) {
+        var geom = elt.getAttribute('data-geom'),
+            baseLayer = new OpenLayers.Layer.OSM("OSM"),
+            map = new OpenLayers.Map(elt, { controls: [], theme: null}),
+            layerOptions = {format:     OpenLayers.Format.WKT,
+                            projection: WGS84,
+                            styleMap:   new OpenLayers.StyleMap({
+                                            "default": new OpenLayers.Style({
+                                                strokeColor: "blue",
+                                                strokeWidth: 5,
+                                                strokeOpacity: 0.7
+                                            })
+                                         })},
+            wkt = new OpenLayers.Format.WKT({ internalProjection: Mercator, externalProjection: WGS84 }),
+            viewLayer = new OpenLayers.Layer.Vector("View Layer", layerOptions),
+            extent;
+
+        map.addLayers([baseLayer, viewLayer]);
+        viewLayer.addFeatures([wkt.read(geom)]);
+        map.zoomToExtent(viewLayer.getDataExtent());
+    });
+    $$(".delete-link").invoke('observe', 'click', deletePath);
+});
+
+function loginlink() {
+    var lang;
+    if (location.search && location.search.length && location.search[0] === '?') {
+        lang = location.search.slice(1).split('&').find(function(str) {
+            return str.startsWith('lang=');
+        });
+        if (lang) {
+            lang = lang.slice('lang='.length);
+        }
+    }
+    return 'login?redirect=' + encodeURIComponent(location.pathname + location.search) + ((lang) ? '&lang=' + lang: "");
+}
index f2ae9e19125230221488fe2c8eb6654a50550533..5400ff3afcd7b4fd20516aef480a178748c3d2f8 100644 (file)
@@ -419,7 +419,7 @@ var SYJView = {
             break;
             case 400:
             case 404:
-                message = SyjStrings.requestError; // default message
+                message = SyjStrings.requestError;
                 if (transport.responseJSON) {
                     switch (transport.responseJSON.message) {
                         case "uniquepath":
@@ -430,6 +430,12 @@ var SYJView = {
                     }
                 }
             break;
+            case 403:
+                message = "";
+                SYJLogin.messenger.setMessage(SyjStrings.loginNeeded, "warn");
+                SYJLogin.modalbox.show();
+                this.needsFormResubmit = true;
+            break;
             case 410:
                 message = SyjStrings.gonePathError;
             break;