From ec061a75fe57a25eb7ef0894f5e723397ba35472 Mon Sep 17 00:00:00 2001 From: arno Date: Wed, 11 Aug 2010 21:31:50 +0200 Subject: [PATCH] interface to manage list of created routes --- application/configs/application.ini | 10 ++- application/controllers/AccountController.php | 16 +--- application/controllers/ListController.php | 45 ++++++++++ application/controllers/PathController.php | 47 ++++++---- .../controllers/helpers/SyjSession.php | 22 +++++ application/layouts/scripts/footer.phtml | 12 +++ application/models/PathMapper.php | 15 +++- application/views/scripts/list/index.phtml | 81 +++++++++++++++++ public/css/list.css | 63 +++++++++++++ public/js/list.js | 90 +++++++++++++++++++ public/js/syj.js | 8 +- 11 files changed, 372 insertions(+), 37 deletions(-) create mode 100644 application/controllers/ListController.php create mode 100644 application/views/scripts/list/index.phtml create mode 100644 public/css/list.css create mode 100644 public/js/list.js diff --git a/application/configs/application.ini b/application/configs/application.ini index 80b2420..fa4ec8b 100644 --- a/application/configs/application.ini +++ b/application/configs/application.ini @@ -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" diff --git a/application/controllers/AccountController.php b/application/controllers/AccountController.php index 7612490..f1d977f 100644 --- a/application/controllers/AccountController.php +++ b/application/controllers/AccountController.php @@ -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 index 0000000..317505e --- /dev/null +++ b/application/controllers/ListController.php @@ -0,0 +1,45 @@ +_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"), + ); + } + +} diff --git a/application/controllers/PathController.php b/application/controllers/PathController.php index c3c085a..aa41866 100644 --- a/application/controllers/PathController.php +++ b/application/controllers/PathController.php @@ -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 { diff --git a/application/controllers/helpers/SyjSession.php b/application/controllers/helpers/SyjSession.php index 702bfa2..11c369f 100644 --- a/application/controllers/helpers/SyjSession.php +++ b/application/controllers/helpers/SyjSession.php @@ -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)); + } } diff --git a/application/layouts/scripts/footer.phtml b/application/layouts/scripts/footer.phtml index 08b2ff9..cce5e7f 100644 --- a/application/layouts/scripts/footer.phtml +++ b/application/layouts/scripts/footer.phtml @@ -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 */ diff --git a/application/models/PathMapper.php b/application/models/PathMapper.php index c899364..1e0e973 100644 --- a/application/models/PathMapper.php +++ b/application/models/PathMapper.php @@ -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 index 0000000..31d3a50 --- /dev/null +++ b/application/views/scripts/list/index.phtml @@ -0,0 +1,81 @@ + + +
+ + +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 ('
%s
', $noroutecontent); + return; + } + + $pages = $this->paginator->getPages(); + if (isset($pages->previous) or isset($pages->next)) { + print ''; + } + + print '
'; + foreach ($this->paginator as $item) { + + $map = sprintf('
', $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('%s', $this->translate("duplicate")); + $deletelink = sprintf('%s', $this->translate("delete")); + + printf ('
+
%s
+
%s
%s
%s
+
%s
+
+ ', + (int)$item->id, $maplink, $modifylink, $duplicatelink, $deletelink, $this->escape($item->displayTitle)); + + } + print '
'; +?> diff --git a/public/css/list.css b/public/css/list.css new file mode 100644 index 0000000..c78f909 --- /dev/null +++ b/public/css/list.css @@ -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 index 0000000..db95dc5 --- /dev/null +++ b/public/js/list.js @@ -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: ""); +} diff --git a/public/js/syj.js b/public/js/syj.js index f2ae9e1..5400ff3 100644 --- a/public/js/syj.js +++ b/public/js/syj.js @@ -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; -- 2.39.2