diff --git a/.gitignore b/.gitignore index f4107ab..0c5b9cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,3 @@ -############ -## Windows -############ - -# Windows image file caches -Thumbs.db - -# Folder config file -Desktop.ini - -# MySQL Config files -include/mysql_connect.php -include/login/config.php -/nbproject/private/ \ No newline at end of file +/vendor +/.idea +/nbproject/private/ diff --git a/.htaccess b/.htaccess deleted file mode 100644 index 3c79f01..0000000 --- a/.htaccess +++ /dev/null @@ -1,4 +0,0 @@ -## Default .htaccess file -## RewriteEngine On -## RewriteCond %{HTTP_HOST} !^www\.ecdb\.net -## RewriteRule (.*) http://www.ecdb.net/$1 [R=301,L] \ No newline at end of file diff --git a/INSTALL.md b/INSTALL.md new file mode 100644 index 0000000..f2515f2 --- /dev/null +++ b/INSTALL.md @@ -0,0 +1,76 @@ +# Installation instructions + +Installing ecDB requires following steps: +* get the code +* install dependencies +* setup mysql database +* setup web server + +## Getting the code + +:point_right: this installation instruction expects files to be extracted into /var/www/ecdb folder. + +Download [latest ZIP file](https://github.com/petslane/ecDB/archive/master.zip) and extract to desired folder +```bash +wget https://github.com/petslane/ecDB/archive/master.zip +unzip master.zip -d ecdb +``` +or do git clone +```bash +git clone https://github.com/petslane/ecDB.git +``` + +## Installing dependencies + +:point_right: Dependencies are handled by [Composer](https://getcomposer.org/) and expects it's already installed. If not, [here](https://getcomposer.org/download/) is how to do it. + +Install dependencies with Composer: +```bash +composer install +``` +## Setup MySQL database + +Start MySQL command-line tool and connect to db server with admin user: +```bash +mysql -u admin_user -p +``` + +In MySQL cli tool, create database: +```bash +mysql> CREATE DATABASE ecdb; +``` + +create new user: +```bash +mysql> CREATE USER 'ecdb'@'localhost' IDENTIFIED BY 'some_strong_password'; +``` + +grant user access to `dcdb` database: +```bash +mysql> GRANT ALL PRIVILEGES ON ecdb.* TO 'ecdb'@'localhost'; +``` + +## Setup web server + +### Apache + +Example apache configuration can be found in `config/apache.conf`. ecDB uses rewrite rules and `AllowOverride` must be +allowed. If you want to ecDB be accessible from base path (eg. http://domain/myecdb/), then configure `RewriteBase` to +specify base path in `htdocs/.htaccess`. + +### PHP built-in server + +PHP built-in server is supported. Run following command to start webserver on localhost with port 8888: +```bash +php -S localhost:8888 -t htdocs htdocs/index.php +``` +If you want to start server on port 80 (or any port below 1024), then change "8888" appropriately and run this command with root privileges. + +# Configurations + +On first install MySQL must be configured. Got to file `config/config.php` and make appropriate changes in `$confg['db']`. + +Rest of configs are optionals and should work as is. + +In case Apache web server was used and ecDB was installed under subpath, then `RewriteBase` must be configured in `.htdocs/.htaccess`. + diff --git a/README.md b/README.md index fc937b9..a16b28f 100644 --- a/README.md +++ b/README.md @@ -37,16 +37,12 @@ Currently there is no documentation available. Please feel free to create it! ## Installation -- Either download the latest stable release from the [download page](https://github.com/ElectricMan/ecDB/downloads). Or download this git. -- Create a MySQL database. -- Import `ecdb_databse.sql` database structure to your MySQL-database. -- Insert your MySQL data in the configuration file, `include/mysql_connect.php`. -- **You are now set to go!** The default username is `demo` and password `demo`. +[Installation instructions](INSTALL.md) ### Requirements - Web Server. -- PHP Version 5.2.4 or above. +- PHP Version 5.5 or above. - MySQL Version 5.0 or above. ## Contributing diff --git a/about.php b/about.php deleted file mode 100644 index 325cc5a..0000000 --- a/about.php +++ /dev/null @@ -1,94 +0,0 @@ - - - - - - - - - About - ecDB - - - - -
- - - - - - - - - - -
-
-
-
- Check out the new ecDB blog. Or follow @ecDBnet at Twitter to get the latest updates! -
-

What is ecDB?

- - ecDB is basically a place where you, as an electronics hobbyist (or professional) can add your own components to your personal database to keep track of what components you own, where they are, how many you own and so on. - -

- -

-

Who & Why?

- - ecDB is created by Nils Fredriksson and designed by Buildlog.

- - Me, Nils, have always wanted to have a system like this to keep track of what component I own. Before I created this system I (I guess you too...) had to dig through boxes filled with components to maybe find that component I needed. This is an unnecessary task to do, it not only takes time, and it also can be really frustrating not to find that component you are looking for. So I ended up creating this website where I easily can keep track of my components! - -

-

What does it cost?

- - ecDB is completely free!
- But if you like ecDB you can use this button to donate us some money. -
- - - -
- -
-

Is ecDB really done?

- No! ecDB is still under development. Here are some of the upcoming features:

- - - Public components - a place where you easily can trade components.
- - View to physically print the personal database. Old-school typewritten text and nice colums!
- - Datasheet and picture uploading.
- - Advanced component search with parameters.
- - Log for each component. See when the component last was used/edited/bought etc.
- - Barcode implementation for easy storage management.
- - Import and export of personal database to text/spreadsheet.
- - Quick edit function of component data directly from the database view.
- - Add personal categories and fields.
- - Borrow component data from other components in the database to easily add components. -
-
-
-
- - - - - - -
- - \ No newline at end of file diff --git a/add.php b/add.php deleted file mode 100644 index 6587ce8..0000000 --- a/add.php +++ /dev/null @@ -1,355 +0,0 @@ - - - - - - - - - - - Add component - ecDB - - - - - - - - - - - - -
- - - - - - - - - - -
- - - Add(); - ?> - - -
-
- -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Name - - - - Category - - - - Quantity - - -
- Manufacturer - - - - Package - - - - Pins - - -
- Location - - - - Price - - - - To order - - -
- SMD - - Yes '; - echo ' No'; - } - else{ - echo ' Yes '; - echo ' No'; - } - ?> - - Scrap - - Yes '; - echo ' No'; - } - else{ - echo ' Yes '; - echo ' No'; - } - ?> - - Public - - Yes '; - echo ' No'; - } - else{ - echo ' Yes '; - echo ' No'; - } - ?> -
- Weight - - - - Width - - -
- Depth - - -
- Datasheet URL - - - - Height - - -
- Image URL 1 - - - - Image URL 2 - - - - -
- Image URL 3 - - - - Image URL 4 - - - - -
- Add component to project - - Quantity -
- - - -
-
-
- -
-
-
-
- - - - -
- - \ No newline at end of file diff --git a/add_based.php b/add_based.php deleted file mode 100644 index 3aa6b89..0000000 --- a/add_based.php +++ /dev/null @@ -1,378 +0,0 @@ - - - - - - - - - - - Add component - ecDB - - - - -
- - - - - - - - - - -
- -

Add new component based on

- - Add(); - ?> - -
-
- -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Name - - - - Category - - - - Quantity - - -
- Manufacturer - - - - Package - - - - Pins - - -
- Location - - - - Price - - - - To order - - -
- SMD - - Yes '; - echo ' No'; - } - else{ - echo ' Yes '; - echo ' No'; - } - ?> - - Scrap - - Yes '; - echo ' No'; - } - else{ - echo ' Yes '; - echo ' No'; - } - ?> - - Public - - Yes '; - echo ' No'; - } - else{ - echo ' Yes '; - echo ' No'; - } - ?> -
- Weight - - - - Width - - -
- Depth - - -
- Datasheet URL - - - - Height - - -
- Image URL 1 - - - - Image URL 2 - - - - -
- Image URL 3 - - - - Image URL 4 - - - - -
- Add component to project - - Quantity -
- - - -
-
-
- -
-
-
-
- - - - - -
- - diff --git a/category.php b/category.php deleted file mode 100644 index 5a33aac..0000000 --- a/category.php +++ /dev/null @@ -1,115 +0,0 @@ - - - - - - - - - Category - ecDB - - - - -
- - - - - - - -
- -
-
    - Sub(); - ?> -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - Category(); - ?> - -
NameCategoryPackagePinsImageDatasheetSMDPriceQuantityComment
-
- - - - -
- - diff --git a/component.php b/component.php deleted file mode 100644 index d2ac59b..0000000 --- a/component.php +++ /dev/null @@ -1,487 +0,0 @@ - - - - - - - - - - - View component - <?php echo $executesql['name']; ?> - ecDB - - - -
- - - - - - - -
-

- '; - echo $executesql_head_catname['name']; - echo ' / '; - - echo ' '; - echo $executesql_sub_catname['name']; - ?> - / -

- -
-
-
- '; - echo 'No Image'; - echo '
'; - } - else { - echo ''; - } - ?> -
-
-
    - '; - } - ?> - '; - } - ?> - '; - } - ?> -
-
-
- -
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Location - -
Quantity - -
- - -
-
Price - - Order quantity - -
- - -
-
Manufacturer - - Package - - Pins - -
SMD - '; - } - else { - echo ''; - } - ?> - Scrap - '; - } - else { - echo ''; - } - ?> - Public - '; - } - else { - echo ''; - } - ?> -
Width - - Weight - -
Depth - - -
Height - - -
Datasheet - '; - } - ?> -
-
- -
-
-
- - - -
-
-
- -
- - - - - - - diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..bea1c47 --- /dev/null +++ b/composer.json @@ -0,0 +1,14 @@ +{ + "autoload": { + "psr-4": { + "Ecdb\\Controllers\\": "controllers/" + } + }, + "require": { + "doctrine/dbal": "*", + "erusev/parsedown": "*", + "php": "^5.5.0 || ^7.0", + "slim/slim": "^3.8", + "smarty/smarty": "^3.1" + } +} diff --git a/config/apache.conf b/config/apache.conf new file mode 100644 index 0000000..b2e6da5 --- /dev/null +++ b/config/apache.conf @@ -0,0 +1,6 @@ +Alias /ecdb /var/www/ecdb/htdocs + + AllowOverride All + Order allow,deny + Allow from all + diff --git a/config/config.php b/config/config.php new file mode 100644 index 0000000..6a7b1f0 --- /dev/null +++ b/config/config.php @@ -0,0 +1,25 @@ + 'localhost', + 'username' => 'username', + 'password' => 'password', + 'db' => 'database', +); + +/** + * Google Analytics config + */ +$config['google_analytics'] = array( + 'account' => '', // UA-xxxxxxxx-x + 'site' => '', // ecdb.net +); + +/** + * Directory where Smarty will store compiled templates + */ +$config['smarty_compile_dir'] = sys_get_temp_dir(); diff --git a/contact.php b/contact.php deleted file mode 100644 index edf400c..0000000 --- a/contact.php +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - Contact - ecDB - - - - -
- '; - include 'include/header.php'; - echo ''; - - echo ''; - include 'include/menu.php'; - echo ''; - } - else { - echo ''; - include 'include/header_public.php'; - echo ''; - - echo ''; - include 'include/menu_public.php'; - echo ''; - } - ?> - -
-
-
-

Contact us

- If you have any suggestions, questions or what not. Send us an email to info@ecdb.net -
-
-
-
- - - - -
- - \ No newline at end of file diff --git a/contact_php_mail.php b/contact_php_mail.php deleted file mode 100644 index 23ac475..0000000 --- a/contact_php_mail.php +++ /dev/null @@ -1,173 +0,0 @@ - -' . "\r\n" . 'Reply-To: ' . $email; - - mail($emailTo, $subject, $body, $headers); - $emailSent = true; - } -} -?> - - - - - - - - Home - ecDB - - - - - - - - - -
- '; - include 'include/header.php'; - echo ''; - - echo ''; - include 'include/menu.php'; - echo ''; - } - else { - echo ''; - echo ''; - echo ''; - - echo ''; - echo ''; - echo ''; - } - ?> - -
-

Contact us

- If you have a suggestion for ecDB please use this form to let us know about it!

- - '; - echo 'Please check if you have filled all the fields with valid information.'; - echo '
'; - } - - if(isset($emailSent) && $emailSent == true) { - echo '
'; - echo 'Thank you '; - echo $name; - echo '!
Your message was successfully sent.'; - echo '
'; - } - ?> - -
-
- -
-
-
- -
-
-
- -
-
-
- -
-
-
- -
- -
-
-
-
- -
-
-
- -
- - - - - - - diff --git a/controllers/AboutController.php b/controllers/AboutController.php new file mode 100644 index 0000000..a5c70d1 --- /dev/null +++ b/controllers/AboutController.php @@ -0,0 +1,13 @@ +view->assign('selected_menu', 'About'); + return $this->view->display('about.tpl'); + } + +} + diff --git a/controllers/AjaxController.php b/controllers/AjaxController.php new file mode 100644 index 0000000..8251f27 --- /dev/null +++ b/controllers/AjaxController.php @@ -0,0 +1,69 @@ +getParam('q'); + $field = $req->getParam('f'); + $q = strtolower($q); + if (!in_array($field, array('manufacturer', 'name', 'package'))) { + $field = 'name'; + } + + $sql = "select DISTINCT {$field} as f from data where {$field} LIKE ? ORDER by {$field} ASC"; + $values = $this->db->fetchAll($sql, array( + "%{$q}%", + )); + + foreach ($values as $value) { + echo $value['f'],"\n"; + } + } + + public function component_count(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + + $owner = $_SESSION['SESS_MEMBER_ID']; + $component_id = $req->getParam('component_id'); + $field = $req->getParam('field'); + $increase = (bool) $req->getParam('increase'); + + if (!in_array($field, array('quantity', 'order_quantity'))) { + return $response->withJson(array( + 'error' => 'Unknown component field', + )); + } + + $sql = "UPDATE data SET {$field} = {$field} + 1 WHERE owner = ? AND id = ?"; + if (!$increase) { + $sql = "UPDATE data SET {$field} = {$field} - 1 WHERE owner = ? AND id = ?"; + } + $changes = $this->db->executeUpdate($sql, array( + $owner, + $component_id, + )); + + if (!$changes) { + return $response->withJson(array( + 'error' => 'Component not found', + )); + } + + $sql = 'SELECT * FROM data WHERE owner = ? and id = ?'; + $component = $this->db->fetchAssoc($sql, array( + $owner, + $component_id, + )); + + return $response->withJson(array( + 'data' => array( + 'name' => $field, + 'value' => $component[$field], + ), + )); + } + +} + diff --git a/controllers/BaseController.php b/controllers/BaseController.php new file mode 100644 index 0000000..03c6775 --- /dev/null +++ b/controllers/BaseController.php @@ -0,0 +1,64 @@ +app = $app; + $this->view = $app->getContainer()->get('view'); + $this->db = $app->getContainer()->get('db'); + } + + protected function render($template_filename) { + + $message_types = array( + 'ERRMSG_ARR' => 'errors', + 'messages' => 'messages', + 'info' => 'info', + ); + foreach ($message_types as $var_session=>$var_tpl) { + if (!empty($_SESSION[$var_session])) { + $existing_messages = empty($this->view->tpl_vars[$var_tpl]->value) ? array() : $this->view->tpl_vars[$var_tpl]->value; + $this->view->assign($var_tpl, array_merge($existing_messages, $_SESSION[$var_session])); + unset($_SESSION[$var_session]); + } + } + + return $this->view->display($template_filename); + } + + protected function renderError(\Slim\Http\Response $response, $error_code) { + $this->view->assign('error_code', $error_code); + $this->view->display('error.tpl'); + return $response->withStatus(403); + } + + protected function redirect($response, $path_or_name, $args=array()) { + try { + $path = $this->app->getContainer()->get('router')->pathFor($path_or_name, $args); + } catch (\Exception $e) { + $path = $path_or_name; + } + + return $response->withRedirect($path); + } + +} \ No newline at end of file diff --git a/controllers/ComponentController.php b/controllers/ComponentController.php new file mode 100644 index 0000000..2d1c9d9 --- /dev/null +++ b/controllers/ComponentController.php @@ -0,0 +1,565 @@ +getParam('q'); + $query = trim(strip_tags(strtoupper($query))); + $by = $req->getParam('by'); + $order = $req->getParam('order'); + + if (!in_array($order, array('asc', 'desc'))) { + $order = 'asc'; + } + + $by_map = array( + 'price' => 'price+0', + 'pins' => 'pins+0', + 'quantity' => 'quantity+0', + 'name' => 'name', + 'category' => 'category', + 'package' => 'package', + 'smd' => 'smd', + 'manufacturer' => 'manufacturer', + ); + if (!array_key_exists($by, $by_map)) { + $by = 'name'; + } else { + $by = $by_map[$by]; + } + + $sql = "SELECT d.* + , c.`name` as nx + , sc.name as snx + , sc.id as scid + FROM data d + JOIN category_sub sc ON d.category = sc.id + JOIN category_head c ON c.id = FLOOR(sc.id / 100) + WHERE (d.name LIKE ? OR d.package LIKE ? OR d.manufacturer LIKE ? OR d.pins LIKE ? OR d.location LIKE ? OR d.comment LIKE ?) + AND owner = ? + ORDER BY {$by} {$order}"; + $components = $this->db->fetchAll($sql, array( + "%{$query}%", + "%{$query}%", + "%{$query}%", + "%{$query}%", + "%{$query}%", + "%{$query}%", + $owner, + )); + + + + $this->view->assign('components', $components); + $this->view->assign('selected_menu', 'search'); + + return $this->render('components_search.tpl'); + } + + public function public_listing(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + + $this->view->assign('selected_menu', 'components_public'); + + return $this->render('components_public.tpl'); + } + + public function save(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + $owner = $_SESSION['SESS_MEMBER_ID']; + $id = !empty($args['id']) ? $args['id'] : null; + + $new_component = $req->getAttribute('route')->getName() == 'component_add'; + + $component = $req->getParam('component'); + + $name = isset($component['name']) ? $component['name'] : ''; + $quantity = isset($component['quantity']) ? $component['quantity'] : ''; + $category = isset($component['category']) ? $component['category'] : ''; + $comment = isset($component['comment']) ? $component['comment'] : ''; + $order_quantity = isset($component['order_quantity']) ? $component['order_quantity'] : ''; + $price = isset($component['price']) ? $component['price'] : ''; + $location = isset($component['location']) ? $component['location'] : ''; + $manufacturer = isset($component['manufacturer']) ? $component['manufacturer'] : ''; + $package = isset($component['package']) ? $component['package'] : ''; + $pins = isset($component['pins']) ? $component['pins'] : ''; + $scrap = isset($component['scrap']) ? $component['scrap'] : 'No'; + $smd = isset($component['smd']) ? $component['smd'] : 'No'; + $width = isset($component['width']) ? $component['width'] : null; + $height = isset($component['height']) ? $component['height'] : null; + $depth = isset($component['depth']) ? $component['depth'] : null; + $weight = isset($component['weight']) ? $component['weight'] : null; + $datasheet = isset($component['datasheet']) ? $component['datasheet'] : null; + $url1 = isset($component['url1']) ? $component['url1'] : ''; + $url2 = isset($component['url2']) ? $component['url2'] : ''; + $url3 = isset($component['url3']) ? $component['url3'] : ''; + $url4 = isset($component['url4']) ? $component['url4'] : ''; + $public = isset($component['public']) ? $component['public'] : 'No'; + + $project = $req->getParam('project'); + $projquant = $req->getParam('projquant'); + + if (mb_strlen($name) < 2) { + $_SESSION['ERRMSG_ARR'][] = 'You have to specify a name!'; + } + if (!$category) { + $_SESSION['ERRMSG_ARR'][] = 'You have to choose a category!'; + } + if (strlen($comment) >= 2500) { + $_SESSION['ERRMSG_ARR'][] = 'Max 2500 characters in the comment!'; + } + if ($quantity && !is_numeric($quantity)) { + $_SESSION['ERRMSG_ARR'][] = 'The quantity must only be a number!'; + } + if ($pins && !is_numeric($pins)) { + $_SESSION['ERRMSG_ARR'][] = 'The pin-count must only be a number!'; + } + if ($price && !is_numeric($price)) { + $_SESSION['ERRMSG_ARR'][] = 'The price must only be a number!'; + } + if ($order_quantity && !is_numeric($order_quantity)) { + $_SESSION['ERRMSG_ARR'][] = 'The order quantity must only be a number!'; + } + if ($weight && !is_numeric($weight)) { + $_SESSION['ERRMSG_ARR'][] = 'The weight must only be a number!'; + } + if ($width && !is_numeric($width)) { + $_SESSION['ERRMSG_ARR'][] = 'The width must only be a number!'; + } + if ($depth && !is_numeric($depth)) { + $_SESSION['ERRMSG_ARR'][] = 'The depth must only be a number!'; + } + if ($height && !is_numeric($height)) { + $_SESSION['ERRMSG_ARR'][] = 'The height must only be a number!'; + } + if ($projquant && !$project) { + $_SESSION['ERRMSG_ARR'][] = 'You have to choose a project!'; + } + if ($project && !$projquant) { + $_SESSION['ERRMSG_ARR'][] = 'You have to specify a quantity for this component to add to the project!'; + } + + $inserted = false; + $updated = false; + + if (empty($_SESSION['ERRMSG_ARR'])) { + if ($id && !$new_component) { + $updated = $this->db->update('data', array( + 'name' => $name, + 'manufacturer' => $manufacturer, + 'package' => $package, + 'pins' => $pins, + 'smd' => $smd, + 'quantity' => $quantity, + 'location' => $location, + 'scrap' => $scrap, + 'width' => $width, + 'height' => $height, + 'depth' => $depth, + 'weight' => $weight, + 'datasheet' => $datasheet, + 'comment' => $comment, + 'category' => $category, + 'url1' => $url1, + 'url2' => $url2, + 'url3' => $url3, + 'url4' => $url4, + 'price' => $price, + 'order_quantity' => $order_quantity, + 'public' => $public, + ), array( + 'id' => $id, + )); + if ($updated) { + $_SESSION['messages'][] = 'Updated'; + } + + $edit_projects = $req->getParam('projquantedit'); + foreach ($edit_projects as $edit_project_id=>$edit_project_quantity) { + if ($edit_project_quantity < 1) { + $project_deleted = $this->db->delete('projects_data', array( + 'projects_data_owner_id' => $owner, + 'projects_data_project_id' => $edit_project_id, + 'projects_data_component_id' => $id, + )); + if ($project_deleted) { + $_SESSION['messages'][] = 'Component deleted from project'; + } + } else { + $project_updated = $this->db->update('projects_data', array( + 'projects_data_quantity' => $edit_project_quantity, + ), array( + 'projects_data_owner_id' => $owner, + 'projects_data_project_id' => $edit_project_id, + 'projects_data_component_id' => $id, + )); + if ($project_updated) { + $_SESSION['messages'][] = 'Component quantity in project updated'; + } + } + } + } else { + $inserted = $this->db->insert('data', array( + 'owner' => $owner, + 'name' => $name, + 'manufacturer' => $manufacturer, + 'package' => $package, + 'pins' => $pins, + 'smd' => $smd, + 'quantity' => $quantity, + 'location' => $location, + 'scrap' => $scrap, + 'width' => $width, + 'height' => $height, + 'depth' => $depth, + 'weight' => $weight, + 'datasheet' => $datasheet, + 'comment' => $comment, + 'category' => $category, + 'url1' => $url1, + 'url2' => $url2, + 'url3' => $url3, + 'url4' => $url4, + 'price' => $price, + 'order_quantity' => $order_quantity, + 'public' => $public, + )); + if ($inserted) { + $id = $this->db->lastInsertId(); + // TODO: base path here + $_SESSION['messages'][] = "Component added! - View component ({$name})"; + } + } + + if ($project && $projquant) { + $this->db->insert('projects_data', array( + 'projects_data_owner_id' => $owner, + 'projects_data_project_id' => $project, + 'projects_data_component_id' => $id, + 'projects_data_quantity' => $projquant, + )); + } + } + + if ($inserted || $updated) { + return $this->redirect($response, 'component_edit', array( + 'id' => $id, + )); + } + + $args['post_component'] = $component; + + if ($new_component) { + return $this->add($req, $response, $args); + } + return $this->edit($req, $response, $args); + } + + public function listing(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + + $owner = $_SESSION['SESS_MEMBER_ID']; + + $category_id = $req->getParam('cat'); + $sub_category_id = $req->getParam('subcat'); + $by = $req->getParam('by'); + $order = $req->getParam('order'); + if (!in_array($order, array('asc', 'desc'))) { + $order = 'asc'; + } + $by_map = array( + 'price' => 'price+0 ' . $order, + 'pins' => 'pins+0 ' . $order, + 'quantity' => 'quantity+0 ' . $order, + 'category' => "nx {$order}, snx {$order}", + 'name' => 'd.name ' . $order, + 'package' => 'package ' . $order, + 'smd' => 'smd ' . $order, + ); + $components_order = in_array($by, $by_map) ? $by_map[$by] : "d.name $order"; + + if (!$category_id && $sub_category_id) { + $sql = "SELECT floor(id / 100) FROM category_sub where id = ?"; + $category_id = $this->db->fetchColumn($sql, array($sub_category_id)); + } + + $sql = "SELECT ch.id + , ch.name + , COUNT(d.id) elements + FROM category_head ch + LEFT JOIN data d ON floor(d.category / 100) = ch.id + GROUP BY ch.name + ORDER BY ch.name ASC"; + $categories = $this->db->fetchAll($sql); + + if ($category_id) { + $sql = "SELECT c.id + , c.name + , COUNT(d.id) elements + FROM category_sub c + LEFT JOIN data d ON d.category = c.id + WHERE floor(c.id / 100) = ? + GROUP BY c.name + ORDER by c.name ASC"; + $sub_categories = $this->db->fetchAll($sql, array($category_id)); + $sub_category_ids = array(); + foreach ($sub_categories as $sub_category) { + $sub_category_ids[] = $sub_category['id']; + } + + $sql = "SELECT category FROM data WHERE owner = ? AND category IN (?) GROUP BY category"; + $stmt = $this->db->executeQuery($sql, array( + $owner, + $sub_category_ids, + ), array( + \PDO::PARAM_INT, + \Doctrine\DBAL\Connection::PARAM_INT_ARRAY, + )); + $subcategories_with_components = $stmt->fetchAll(); + $subcategories_with_components = array_map(function ($row) { + return (int) $row['category']; + }, $subcategories_with_components); + + $this->view->assign('sub_categories', $sub_categories); + $this->view->assign('subcategories_with_components', $subcategories_with_components); + } + + $sql = "SELECT d.id + , d.name + , d.category + , d.package + , d.pins + , d.datasheet + , d.url1 + , d.smd + , d.price + , d.quantity + , d.comment + , d.location + , c.`name` as nx + , sc.name as snx + , sc.id as scid + FROM data d + JOIN category_sub sc ON d.category = sc.id + JOIN category_head c ON c.id = FLOOR(sc.id / 100) + WHERE owner = ?"; + $params = array( + $owner, + ); + if ($category_id) { + $sql .= " AND c.id = ? "; + $params[] = $category_id; + } + if ($sub_category_id) { + $sql .= " AND sc.id = ? "; + $params[] = $sub_category_id; + } + $sql .= "ORDER BY {$components_order}"; + $components = $this->db->fetchAll($sql, $params); + + $this->view->assign('categories', $categories); + $this->view->assign('category_id', $category_id); + $this->view->assign('sub_category_id', $sub_category_id); + $this->view->assign('components', $components); + $this->view->assign('order', $order); + $this->view->assign('selected_menu', 'components'); + + return $this->render('components.tpl'); + } + + public function delete(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + + $deleted = $this->db->delete('data', array( + 'id' => $args['id'], + 'owner' => $_SESSION['SESS_MEMBER_ID'], + )); + + if ($deleted) { + $_SESSION['messages'][] = 'Component deleted'; + return $this->redirect($response, 'index'); + } + + $_SESSION['ERRMSG_ARR'][] = 'Component not found'; + return $this->redirect($response, 'component', array( + 'id' => $args['id'], + )); + } + + public function edit(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + $owner = $_SESSION['SESS_MEMBER_ID']; + $id = !empty($args['id']) ? $args['id'] : null; + + $component = $this->getComponent($id); + + if (!$component) { + return $this->renderError($response, 2); + } + + $category = $this->getCategoriesNames($component['category']); + $project = $this->getComponentProject($component['id']); + + $sql = 'SELECT currency, measurement FROM members WHERE member_id = ?'; + $member_settings = $this->db->fetchAssoc($sql, array( + $owner, + )); + + if (!empty($args['post_component'])) { + $args['post_component']['id'] = $id; + $this->view->assign('component', $args['post_component']); + } else { + $this->view->assign('component', $component); + } + $this->view->assign('member_settings', $member_settings); + $this->view->assign('category', $category); + $this->view->assign('project', $project); + $this->view->assign('projects', $this->getAllProjects()); + $this->view->assign('category_tree', $this->getCategoryTree()); + $this->view->assign('selected_menu', 'components'); + + return $this->render('component_edit.tpl'); + } + + private function getCategoryTree() { + $sql = 'SELECT id, name FROM category_head ORDER by name ASC'; + $data = $this->db->fetchAll($sql); + + $sql = 'SELECT id, name FROM category_sub WHERE floor(id / 100) = ? ORDER by name ASC'; + foreach ($data as &$row) { + $row['subcategories'] = $this->db->fetchAll($sql, array($row['id'])); + } + + return $data; + } + + private function getComponent($id) { + $owner = $_SESSION['SESS_MEMBER_ID']; + + $sql = 'SELECT * FROM data WHERE id = ? AND owner = ?'; + $component = $this->db->fetchAssoc($sql, array( + $id, + $owner, + )); + + return $component; + } + + private function getCategoriesNames($subcategory_id) { + $sql = 'SELECT c.name category_name + , c.id category_id + , cs.name sub_category_name + , cs.id sub_category_id + FROM category_head c + JOIN category_sub cs ON c.id = floor(cs.id / 100) + WHERE cs.id = ?'; + $category = $this->db->fetchAssoc($sql, array( + $subcategory_id, + )); + + return $category; + } + + private function getComponentProject($component_id) { + $sql = "SELECT projects_data.projects_data_project_id + , projects_data.projects_data_quantity + , projects_data.projects_data_project_id + , projects_data.projects_data_component_id + , projects.project_id + , projects.project_name + FROM projects_data + , projects + WHERE projects_data.projects_data_project_id = projects.project_id + AND projects_data.projects_data_component_id = ? + LIMIT 1"; + $project = $this->db->fetchAssoc($sql, array( + $component_id, + )); + return $project; + } + + private function getAllProjects() { + $owner = $_SESSION['SESS_MEMBER_ID']; + + $sql = "SELECT * FROM projects WHERE project_owner = ?"; + $projects = $this->db->fetchAll($sql, array( + $owner, + )); + + return $projects; + } + + public function view(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + $owner = $_SESSION['SESS_MEMBER_ID']; + $id = !empty($args['id']) ? $args['id'] : null; + + $component = $this->getComponent($id); + + if (!$component) { + return $this->renderError($response, 1); + } + + $sql = 'SELECT currency, measurement FROM members WHERE member_id = ?'; + $member_settings = $this->db->fetchAssoc($sql, array( + $owner, + )); + + $category = $this->getCategoriesNames($component['category']); + $project = $this->getComponentProject($component['id']); + + $this->view->assign('component', $component); + $this->view->assign('member_settings', $member_settings); + $this->view->assign('category', $category); + $this->view->assign('project', $project); + $this->view->assign('selected_menu', 'components'); + + return $this->render('component.tpl'); + } + + public function add(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + $owner = $_SESSION['SESS_MEMBER_ID']; + $id_based = !empty($args['id']) ? $args['id'] : null; + + $component = false; + if ($id_based) { + $component = $this->getComponent($id_based); + } + + if ($id_based && !$component) { + return $this->renderError($response, 2); + } + + if ($component) { + $category = $this->getCategoriesNames($component['category']); + $project = $this->getComponentProject($component['id']); + + $this->view->assign('category', $category); + $this->view->assign('project', $project); + } + + $sql = 'SELECT currency, measurement FROM members WHERE member_id = ?'; + $member_settings = $this->db->fetchAssoc($sql, array( + $owner, + )); + + if (!empty($args['post_component'])) { + if ($id_based) { + $args['post_component']['id'] = $id_based; + } + $this->view->assign('component', $args['post_component']); + } else { + $this->view->assign('component', $component); + } + $this->view->assign('member_settings', $member_settings); + $this->view->assign('projects', $this->getAllProjects()); + $this->view->assign('category_tree', $this->getCategoryTree()); + $this->view->assign('new_component', true); + $this->view->assign('id_based', $id_based); + $this->view->assign('selected_menu', 'component_add'); + + return $this->render('component_edit.tpl'); + } +} + diff --git a/controllers/ContactController.php b/controllers/ContactController.php new file mode 100644 index 0000000..9e82559 --- /dev/null +++ b/controllers/ContactController.php @@ -0,0 +1,12 @@ +view->display('contact.tpl'); + } + +} + diff --git a/controllers/DonateController.php b/controllers/DonateController.php new file mode 100644 index 0000000..4c974c7 --- /dev/null +++ b/controllers/DonateController.php @@ -0,0 +1,13 @@ +view->assign('selected_menu', 'donate'); + return $this->view->display('donate.tpl'); + } + +} + diff --git a/controllers/LoginController.php b/controllers/LoginController.php new file mode 100644 index 0000000..3592b1f --- /dev/null +++ b/controllers/LoginController.php @@ -0,0 +1,79 @@ +withRedirect('login'); + } + + public function auth(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + //Array to store validation errors + $errmsg_arr = array(); + + //Sanitize the POST values + $login = $req->getParam('login'); + $password = $req->getParam('password'); + + //Input Validations + if (!$login) { + $errmsg_arr[] = 'Login ID missing'; + } + if (!$password) { + $errmsg_arr[] = 'Password missing'; + } + + //If there are input validations, redirect back to the login form + if ($errmsg_arr) { + $_SESSION['ERRMSG_ARR'] = $errmsg_arr; + + return $response->withRedirect('login'); + } + + $data = $this->db->fetchAssoc('SELECT * FROM members WHERE login=? AND passwd=?', array( + $login, + md5($_POST['password']), + )); + + if (!$data) { + $_SESSION['ERRMSG_ARR'] = 'Invalid username/password'; + + return $response->withRedirect('login'); + } + + //Login Successful + session_regenerate_id(true); + $_SESSION['SESS_MEMBER_ID'] = $data['member_id']; + $_SESSION['SESS_FIRST_NAME'] = $data['firstname']; + $_SESSION['SESS_LAST_NAME'] = $data['lastname']; + $_SESSION['SESS_IS_ADMIN'] = intval($data['admin']); + session_write_close(); + + $member_id = $_SESSION['SESS_MEMBER_ID']; + $this->db->insert('members_stats', array('members_stats_member' => $member_id)); + + return $this->redirect($response, 'index'); + } + + public function index(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + //Unset the variables stored in session + unset($_SESSION['SESS_MEMBER_ID']); + unset($_SESSION['SESS_FIRST_NAME']); + unset($_SESSION['SESS_LAST_NAME']); + unset($_SESSION['SESS_IS_ADMIN']); + + $this->view->assign('selected_menu', 'Login'); + + return $this->view->display('login.tpl'); + } + +} + diff --git a/controllers/MemberController.php b/controllers/MemberController.php new file mode 100644 index 0000000..95df13f --- /dev/null +++ b/controllers/MemberController.php @@ -0,0 +1,101 @@ +db->fetchAssoc('SELECT COUNT(*) AS c FROM members WHERE member_id = ? AND passwd = ?', array( + $member_id, + md5($password), + )); + + return !empty($data['c']); + } + + public function edit(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + + + if($req->isPost()) { + $owner = $_SESSION['SESS_MEMBER_ID']; + $firstname = $req->getParam('firstname'); + $lastname = $req->getParam('lastname'); + $mail = $req->getParam('mail'); + $measurement = (int) $req->getParam('measurement'); + $currency = $req->getParam('currency'); + $oldpass = $req->getParam('oldpass'); + $newpass = $req->getParam('newpass'); + + if (!in_array($currency, array('SEK', 'USD', 'EUR', 'GBP'))) { + $currency = 'SEK'; + } + + if (!$firstname) { + $_SESSION['ERRMSG_ARR'][] = 'First name missing'; + } else if (strlen($firstname) < 2) { + $_SESSION['ERRMSG_ARR'][] = 'Minimum of 2 chars in first name.'; + } + + if (!$lastname) { + $_SESSION['ERRMSG_ARR'][] = 'Last name missing'; + } else if (strlen($lastname) < 2) { + $_SESSION['ERRMSG_ARR'][] = 'Minimum of 2 chars in last name.'; + } + + if (!$mail) { + $_SESSION['ERRMSG_ARR'][] = 'Mail missing'; + } else if (!filter_var($mail, FILTER_VALIDATE_EMAIL)) { + $_SESSION['ERRMSG_ARR'][] = 'Invalid e-mail address'; + } + + if (!$oldpass && $newpass) { + $_SESSION['ERRMSG_ARR'][] = 'For setting new password, please provide current password'; + } else if ($oldpass && !$newpass && strlen($newpass) < 5) { + $_SESSION['ERRMSG_ARR'][] = 'Minimum of 5 chars in password'; + } else if ($oldpass && !$this->inPasswordValid($owner, $oldpass)) { + $_SESSION['ERRMSG_ARR'][] = 'Provided current password is incorrect'; + } + + if (empty($_SESSION['ERRMSG_ARR'])) { + $data = array( + 'firstname' => $firstname, + 'lastname' => $lastname, + 'mail' => $mail, + 'passwd' => md5($newpass), + 'measurement' => $measurement, + 'currency' => $currency, + ); + if ($oldpass && $newpass) { + $data['passwd'] = md5($newpass); + } + $this->db->update('members', $data, array( + 'member_id' => $owner, + )); + $_SESSION['messages'][] = 'Settings updated'; + return $this->redirect($response, 'my'); + } + } + + $data = $this->db->fetchAssoc('SELECT * FROM members WHERE member_id = ?', array( + $_SESSION['SESS_MEMBER_ID'] + )); + + unset($data['passwd']); + + if ($req->isPost()) { + $data['firstname'] = $firstname; + $data['lastname'] = $lastname; + $data['mail'] = $mail; + $data['measurement'] = $measurement; + $data['currency'] = $currency; + } + + $this->view->assign('member', $data); + + $this->view->assign('selected_menu', 'my'); + + return $this->view->display('member.tpl'); + } + +} + diff --git a/controllers/ProjectController.php b/controllers/ProjectController.php new file mode 100644 index 0000000..b0790de --- /dev/null +++ b/controllers/ProjectController.php @@ -0,0 +1,224 @@ +getParam('order'); + if (!in_array($order, array('asc', 'desc'))) { + $order = 'asc'; + } + + $by_map = array( + 'name' => 'd.name', + 'category' => "c.name {$order}, sc.subcategory", + 'manufacturer' => 'manufacturer', + 'package' => 'package', + 'smd' => 'smd', + 'price' => 'price', + 'stock_quantity' => 'quantity', + 'order_quantity' => 'order_quantity', + 'quantity' => 'projects_data_quantity', + 'bin_location' => '', // ? + ); + $by = $req->getParam('by', 'name'); + if (!array_key_exists($by, $by_map)) { + $by = 'name'; + } + + $data = $this->getProject($id, $owner); + + if (!$data) { + return $response->withRedirect('proj_list'); + } + + $this->view->assign('project', $data); + + $sql = "SELECT pd.* + , d.* + , sc.name as subcategory + , c.name as category + FROM projects_data pd + JOIN data d ON pd.projects_data_component_id = d.id + JOIN category_sub sc ON d.category = sc.id + JOIN category_head c ON c.id = floor(sc.id / 100) + WHERE pd.projects_data_project_id = ? ORDER BY {$by_map[$by]} {$order}"; + $components = $this->db->fetchAll($sql, array( + $id, + )); + $this->view->assign('components', $components); + + // TODO: improve this weird query + $sql = 'SELECT sum(project_total.total) as total + , m.currency + FROM (SELECT cast(cast(price as decimal(14, 3)) * projects_data_quantity as decimal(14, 2)) AS total + FROM projects_data + JOIN `data` + WHERE data.id = projects_data_component_id + AND projects_data_project_id = ?) AS project_total + , projects p + JOIN members m ON m.member_id = p.project_owner + where p.project_id = ? + group by m.currency'; + $sum = $this->db->fetchAssoc($sql, array($id, $id)); + $this->view->assign('price', $sum); + + $this->view->assign('selected_menu', 'projects'); + + return $this->view->display('project-view.tpl'); + } + + private function getProject($id, $owner_id) { + $sql = 'SELECT * FROM projects WHERE project_id = ? AND project_owner = ?'; + return $this->db->fetchAssoc($sql, array( + $id, + $owner_id, + )); + } + + public function edit(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + + $owner = $_SESSION['SESS_MEMBER_ID']; + $id = (int) $args['id']; + + if ($req->isPost() && $req->getParam('delete', false) === false) { + $name = $req->getParam('name'); + $public = (int) $req->getParam('project_public'); + $url = $req->getParam('project_url'); + $description = $req->getParam('project_desc'); + + if (!$name) { + $_SESSION['ERRMSG_ARR'][] = 'Project name missing'; + } + } else if ($req->isPost() && $req->getParam('delete', false) !== false) { + $deleted = $this->db->delete('projects', array( + 'project_id' => $id, + 'project_owner' => $owner, + )); + if ($deleted) { + $_SESSION['messages'][] = 'Project deleted'; + return $this->redirect($response, 'projects'); + } else { + $_SESSION['ERRMSG_ARR'][] = 'Unable to delete project'; + return $this->redirect($response, 'project_edit', array( + 'id' => $id, + )); + } + } + + $data = $this->getProject($id, $owner); + + if (!$data) { + $_SESSION['ERRMSG_ARR'][] = 'Project not found'; + return $response->withRedirect('proj_list'); + } + + if ($req->isPost() && !empty($_SESSION['ERRMSG_ARR'])) { + if (!empty($name)) { + $data['project_name'] = $name; + } + if (isset($public)) { + $data['project_public'] = $public; + } + if (isset($url)) { + $data['project_url'] = $url; + } + if (isset($description)) { + $data['project_desc'] = $description; + } + } + + if ($req->isPost() && empty($_SESSION['ERRMSG_ARR'])) { + $this->db->update('projects', array( + 'project_name' => $name, + 'project_public' => $public, + 'project_url' => $url, + 'project_desc' => $description, + ), array( + 'project_id' => $id, + )); + $_SESSION['messages'][] = 'Project saved'; + return $this->redirect($response, 'project_edit', array('id'=>$id)); + } + + $this->view->assign('project', $data); + $this->view->assign('selected_menu', 'projects'); + + return $this->render('project-edit.tpl'); + } + + public function add(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + + $owner = $_SESSION['SESS_MEMBER_ID']; + $name = $req->getParam('name'); + + if (!$name) { + $_SESSION['ERRMSG_ARR'] = array( + 'You have to specify a name!', + ); + + return $response->withRedirect('proj_list'); + } + + $added = $this->db->insert('projects', array( + 'project_owner' => $owner, + 'project_name' => $name, + )); + + if ($added) { + $_SESSION['messages'] = array( + 'Project added!', + ); + return $this->redirect($response, 'project_edit', array( + 'id' => $this->db->lastInsertId(), + )); + } else { + $_SESSION['ERRMSG_ARR'][] = 'Error creating new project'; + } + return $this->redirect($response, 'projects'); + } + + public function projects(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + + + $owner = $_SESSION['SESS_MEMBER_ID']; + + $order = strtolower($req->getParam('order', 'asc')) == 'asc' ? 'asc' : 'desc'; + $sql = "SELECT projects.* + , m.currency currency + , SUM(pd1.projects_data_id) AS qty + , CAST(data.price as decimal(14, 2)) * pd1.projects_data_quantity AS total_price + FROM projects + LEFT JOIN projects_data AS pd1 ON pd1.projects_data_project_id = projects.project_id + LEFT JOIN data ON data.id = pd1.projects_data_component_id + JOIN members m ON project_owner = m.member_id + WHERE project_owner = ? + group by projects.project_id + ORDER BY project_name ".$order; + $data = $this->db->fetchAll($sql, array($owner)); + + $this->view->assign('projects', $data); + + if ($owner) { + $data = $this->db->fetchAssoc('SELECT COUNT(*) c FROM projects WHERE project_owner = ?', array( + $owner, + )); + if (empty($data['c'])) { + $_SESSION['info'] = array( + 'To create a BOM-list (Bill Of Material) you have to first create a project. You will then be able to add your components to your project and automaticly create a BOM-list.', + ); + } + } + + $this->view->assign('selected_menu', 'projects'); + $this->view->assign('order', $order); + + return $this->view->display('projects-list.tpl'); + } + +} + diff --git a/controllers/RegisterController.php b/controllers/RegisterController.php new file mode 100644 index 0000000..50835e9 --- /dev/null +++ b/controllers/RegisterController.php @@ -0,0 +1,99 @@ +view->assign('selected_menu', 'Register'); + } + + public function index(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + return $this->view->display('registration.tpl'); + } + + public function register(\Slim\Http\Request $req, \Slim\Http\Response $response, $args) { + + //Array to store validation errors + $errors = array(); + + //Sanitize the POST values + $fname = $req->getParam('fname'); + $lname = $req->getParam('lname'); + $login = $req->getParam('login'); + $mail = $req->getParam('mail'); + $password = $req->getParam('password'); + $cpassword = $req->getParam('cpassword'); + + //Input Validations + if (!$fname) { + $errors[] = 'First name missing'; + } else if (strlen($fname) < 2) { + $errors[] = 'Minimum of 2 chars in first name.'; + } + if (!$lname) { + $errors[] = 'Last name missing'; + } else if (strlen($lname) < 2) { + $errors[] = 'Minimum of 2 chars in last name.'; + } + if (!$login) { + $errors[] = 'Username missing'; + } else if (strlen($login) < 2) { + $errors[] = 'Minimum of 2 chars in username.'; + } + if (!$mail) { + $errors[] = 'Mail missing'; + } else if (!filter_var($mail, FILTER_VALIDATE_EMAIL)) { + $errors[] = 'Invalid e-mail address'; + } + if (!$password) { + $errors[] = 'Password missing'; + } else if (strlen($password) < 5) { + $errors[] = 'Minimum of 5 chars in password.'; + } + if (!$cpassword) { + $errors[] = 'Confirm password missing'; + } else if (strcmp($password, $cpassword) != 0) { + $errors[] = 'Passwords do not match'; + } + + //Check for duplicate login ID + if ($login) { + $data = $this->db->fetchAssoc('SELECT COUNT(*) as count FROM members WHERE login=?', array( + $login, + )); + if ($data['count']) { + $errors[] = 'Username already in use'; + } + } + + //If there are input validations, redirect back to the registration form + if ($errors) { + $_SESSION['ERRMSG_ARR'] = $errors; + + $this->view->assign('fname', $fname); + $this->view->assign('lname', $lname); + $this->view->assign('login', $login); + $this->view->assign('mail', $mail); + return $this->render('registration.tpl'); + } + + //Create INSERT query + $added = $this->db->insert('members', array( + 'firstname' => $fname, + 'lastname' => $lname, + 'login' => $login, + 'mail' => $mail, + 'passwd' => md5($_POST['password']), + )); + + $_SESSION['messages'][] = 'User created'; + + // TODO: just do auto-login, why user has to login + return $response->withRedirect('login'); + } + +} + diff --git a/controllers/ShopController.php b/controllers/ShopController.php new file mode 100644 index 0000000..36ffb86 --- /dev/null +++ b/controllers/ShopController.php @@ -0,0 +1,53 @@ +getParam('order'); + $order = $req->getParam('by'); + + if (!in_array($order, array('asc', 'desc'))) { + $order = 'asc'; + } + if (!array_key_exists($by, $order_fields)) { + $by = 'name'; + } + + $sql = "SELECT * FROM data WHERE owner = ? AND order_quantity > 0 ORDER by {$by} {$order}"; + $data = $this->db->fetchAll($sql, array( + $_SESSION['SESS_MEMBER_ID'], + )); + $this->view->assign('components', $data); + + $total_price = 0; + foreach ($data as $row) { + $total_price += (float) $row['price'] * (int) $row['order_quantity']; + } + $this->view->assign('total_price', $total_price); + + $sql = "SELECT currency FROM members WHERE member_id = ?"; + $currency = $this->db->fetchAssoc($sql, array( + $_SESSION['SESS_MEMBER_ID'], + )); + $this->view->assign('currency', $currency['currency']); + + $this->view->assign('selected_menu', 'shop_list'); + + return $this->view->display('shop_list.tpl'); + } + +} + diff --git a/controllers/TermsController.php b/controllers/TermsController.php new file mode 100644 index 0000000..04a3661 --- /dev/null +++ b/controllers/TermsController.php @@ -0,0 +1,12 @@ +view->display('terms.tpl'); + } + +} + diff --git a/donate.php b/donate.php deleted file mode 100644 index c81149a..0000000 --- a/donate.php +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - Contact - ecDB - - - - -
- '; - include 'include/header.php'; - echo ''; - - echo ''; - include 'include/menu.php'; - echo ''; - } - else { - echo ''; - echo ''; - echo ''; - - echo ''; - echo ''; - echo ''; - } - ?> - -
-
-
-

Donate

- ecDB is completely free!
- However, if you like ecDB you may use the button below to donate some money to the project!

-
- - - -
-
-
-
-
- - - - -
- - \ No newline at end of file diff --git a/edit_component.php b/edit_component.php deleted file mode 100644 index 6df4162..0000000 --- a/edit_component.php +++ /dev/null @@ -1,459 +0,0 @@ - - - - - - - - - - - Edit component - <?php echo $executesql['name']; ?> - ecDB - - - - -
- - - - - - - - - - -
-

- '; - echo $executesql_head_catname['name']; - echo ' / '; - - echo ' '; - echo $executesql_sub_catname['name']; - ?> - /

- - - - Add(); - ?> - - -
-
- -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - '; - echo ''; - echo ''; - } - else { - echo ''; - echo ''; - echo ''; - } - - ?> - - - - - - -
- Name - - - - Category - - - - Quantity - - - - -
- Manufacturer - - - - Package - - - - Pins - - -
- Location - - - - Price - - - - To order - - - - -
- SMD - - Yes '; - echo ' No'; - } - else{ - echo ' Yes '; - echo ' No'; - } - ?> - - Scrap - - Yes '; - echo ' No'; - } - else{ - echo ' Yes '; - echo ' No'; - } - ?> - - Public - - Yes '; - echo ' No'; - } - else{ - echo ' Yes '; - echo ' No'; - } - ?> -
- Weight - - - - Width - - - -
- Depth - - -
- Datasheet URL - - - - Height - - -
- Image URL 1 - - - - Image URL 2 - - - - -
- Image URL 3 - - - - Image URL 4 - - - - -
- Add to project - - Quantity - ProjectQuantity
- - - - - MenuProj(); - ?> -
- -
-
- - - -
-
-
-
- - - - - -
- - diff --git a/error.php b/error.php deleted file mode 100644 index 8ea087f..0000000 --- a/error.php +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - Error - ecDB - - - - -
- - - - - - - -
-
- -
-
- - - - -
- - diff --git a/error/400.html b/error/400.html deleted file mode 100644 index f83ae58..0000000 --- a/error/400.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - ERROR 400 - Bad Request! - - - - - -
- -
-

The following error occurred:

-

You have used invalid syntax.

-

Please contact the webmaster with any queries.

-
- -
- - diff --git a/error/401.html b/error/401.html deleted file mode 100644 index 49c7b47..0000000 --- a/error/401.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - ERROR 401 - Unauthorized! - - - - - -
- -
-

The following error occurred:

-

The URL requested requires authorisation.

-

Please contact the webmaster with any queries.

-
- -
- - diff --git a/error/403.html b/error/403.html deleted file mode 100644 index 12934ce..0000000 --- a/error/403.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - ERROR 403 - Forbidden! - - - - - -
- -
-

The following error occurred:

-

You are not permitted to access the requested URL.

-

Please contact the webmaster with any queries.

-
- -
- - diff --git a/error/404.html b/error/404.html deleted file mode 100644 index fb17b2a..0000000 --- a/error/404.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - ERROR 404 - Not Found! - - - - - -
- -
-

The following error occurred:

-

The requested URL was not found on this server.

-

Please check the URL or contact the webmaster.

-
- -
- - diff --git a/error/405.html b/error/405.html deleted file mode 100644 index e5f66a8..0000000 --- a/error/405.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - ERROR 405 - Method Not Allowed! - - - - - -
- -
-

The following error occurred:

-

The method used is not permitted.

-

Please contact the webmaster with any queries.

-
- -
- - diff --git a/error/500.html b/error/500.html deleted file mode 100644 index 4413bf5..0000000 --- a/error/500.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - ERROR 500 - Internal Server Error! - - - - - -
- -
-

The following error occurred:

-

The requested URL caused an internal server error.

-

If you get this message repeatedly please contact the webmaster.

-
- -
- - diff --git a/error/502.html b/error/502.html deleted file mode 100644 index 4bcdc95..0000000 --- a/error/502.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - ERROR 502 - Bad Gateway! - - - - - -
- -
-

The following error occurred:

-

This server received an invalid response from an upstream server it accessed to fulfill the request.

-

If you get this message repeatedly please contact the webmaster.

-
- -
- - diff --git a/error/503.html b/error/503.html deleted file mode 100644 index 983ce26..0000000 --- a/error/503.html +++ /dev/null @@ -1,61 +0,0 @@ - - - - ERROR 503 - Service Unavailable! - - - - - -
- -
-

The following error occurred:

-

The Service is not available at the moment due to a temporary overloading or maintenance of the server. Please try again later.

-

Please contact the webmaster with any queries.

-
- -
- - diff --git a/htdocs/.htaccess b/htdocs/.htaccess new file mode 100644 index 0000000..df9eab3 --- /dev/null +++ b/htdocs/.htaccess @@ -0,0 +1,5 @@ +RewriteEngine On +#RewriteBase /ecdb/ +RewriteCond %{REQUEST_FILENAME} !-f +RewriteCond %{REQUEST_FILENAME} !-d +RewriteRule ^ index.php [QSA,L] diff --git a/include/autocomplete/jquery.autocomplete.css b/htdocs/css/jquery.autocomplete.css similarity index 86% rename from include/autocomplete/jquery.autocomplete.css rename to htdocs/css/jquery.autocomplete.css index cc8b179..4739367 100644 --- a/include/autocomplete/jquery.autocomplete.css +++ b/htdocs/css/jquery.autocomplete.css @@ -1,49 +1,49 @@ -.ac_results { - padding: 0px; - border: 1px solid #888; - background-color: white; - box-shadow:0 0 5px #aaa; - overflow: hidden; - z-index: 99999; - min-width:210px; -} - -.ac_results ul { - width: 100%; - list-style-position: outside; - list-style: none; - padding: 0; - margin: 0; -} - -.ac_results li { - margin: 0px; - padding:5px; - cursor: default; - display: block; - /* - if width will be 100% horizontal scrollbar will apear - when scroll mode will be used - */ - /*width: 100%;*/ - font-size: 14px; - /* - it is very important, if line-height not setted or setted - in relative units scroll will be broken in firefox - */ - line-height: 16px; - overflow: hidden; -} - -.ac_loading { - background: white url('indicator.gif') right center no-repeat; -} - -.ac_odd { - background-color: #eee; -} - -.ac_over { - background-color: #404040; - color:#fff; -} +.ac_results { + padding: 0px; + border: 1px solid #888; + background-color: white; + box-shadow:0 0 5px #aaa; + overflow: hidden; + z-index: 99999; + min-width:210px; +} + +.ac_results ul { + width: 100%; + list-style-position: outside; + list-style: none; + padding: 0; + margin: 0; +} + +.ac_results li { + margin: 0px; + padding:5px; + cursor: default; + display: block; + /* + if width will be 100% horizontal scrollbar will apear + when scroll mode will be used + */ + /*width: 100%;*/ + font-size: 14px; + /* + it is very important, if line-height not setted or setted + in relative units scroll will be broken in firefox + */ + line-height: 16px; + overflow: hidden; +} + +.ac_loading { + background: white url('../img/indicator.gif') right center no-repeat; +} + +.ac_odd { + background-color: #eee; +} + +.ac_over { + background-color: #404040; + color:#fff; +} diff --git a/include/jquery.tweet.css b/htdocs/css/jquery.tweet.css similarity index 100% rename from include/jquery.tweet.css rename to htdocs/css/jquery.tweet.css diff --git a/include/style.css b/htdocs/css/style.css similarity index 99% rename from include/style.css rename to htdocs/css/style.css index 2c70b8e..eb70023 100644 --- a/include/style.css +++ b/htdocs/css/style.css @@ -104,7 +104,7 @@ div.logoWrapper{position:absolute;top:10px;left:0;} .curDollar.medium{background-position:-80px -104px;} .shre.medium{background-position:-96px -104px;} .blIcon{background:url("../img/ecdbSpriteV1.png") no-repeat 0 -168px;width:77px;height:25px;display:inline-block;border:none;margin-bottom:-8px;} -.packageImage{position:absolute;top:170px;right:115px;} +.packageImage{position:relative;top:-25px;left:-160px;} div#menu{width:870px;padding:0 8px;margin:auto;} div#menu ul{list-style:none;} div#menu ul li{list-style:none;display:inline-block;} @@ -215,7 +215,7 @@ div.aboutComponentHeader{overflow:auto;} color:#888; font-size:14px; text-shadow:0 1px 0 #fff; - background:url("/img/dataBackground.png") #f7f7f7; + background:url("../img/dataBackground.png") #f7f7f7; border-radius:2px;-moz-border-radius:2px;-webkit-border-radius:2px; } div.componentGallery div.smallImages{float:left;text-align:right;} diff --git a/favicon.ico b/htdocs/favicon.ico similarity index 100% rename from favicon.ico rename to htdocs/favicon.ico diff --git a/img/about/add.png b/htdocs/img/about/add.png similarity index 100% rename from img/about/add.png rename to htdocs/img/about/add.png diff --git a/img/about/add_thumbnail.png b/htdocs/img/about/add_thumbnail.png similarity index 100% rename from img/about/add_thumbnail.png rename to htdocs/img/about/add_thumbnail.png diff --git a/img/about/index.png b/htdocs/img/about/index.png similarity index 100% rename from img/about/index.png rename to htdocs/img/about/index.png diff --git a/img/about/index_thumbnail.png b/htdocs/img/about/index_thumbnail.png similarity index 100% rename from img/about/index_thumbnail.png rename to htdocs/img/about/index_thumbnail.png diff --git a/img/about/shoplist.png b/htdocs/img/about/shoplist.png similarity index 100% rename from img/about/shoplist.png rename to htdocs/img/about/shoplist.png diff --git a/img/about/shoplist_thumbnail.png b/htdocs/img/about/shoplist_thumbnail.png similarity index 100% rename from img/about/shoplist_thumbnail.png rename to htdocs/img/about/shoplist_thumbnail.png diff --git a/img/apple.png b/htdocs/img/apple.png similarity index 100% rename from img/apple.png rename to htdocs/img/apple.png diff --git a/img/bg.png b/htdocs/img/bg.png similarity index 100% rename from img/bg.png rename to htdocs/img/bg.png diff --git a/img/boxSize.png b/htdocs/img/boxSize.png similarity index 100% rename from img/boxSize.png rename to htdocs/img/boxSize.png diff --git a/img/checkbox_checked.png b/htdocs/img/checkbox_checked.png similarity index 100% rename from img/checkbox_checked.png rename to htdocs/img/checkbox_checked.png diff --git a/img/checkbox_unchecked.png b/htdocs/img/checkbox_unchecked.png similarity index 100% rename from img/checkbox_unchecked.png rename to htdocs/img/checkbox_unchecked.png diff --git a/img/checkmark.png b/htdocs/img/checkmark.png similarity index 100% rename from img/checkmark.png rename to htdocs/img/checkmark.png diff --git a/img/cube.png b/htdocs/img/cube.png similarity index 100% rename from img/cube.png rename to htdocs/img/cube.png diff --git a/img/cur_dollar.png b/htdocs/img/cur_dollar.png similarity index 100% rename from img/cur_dollar.png rename to htdocs/img/cur_dollar.png diff --git a/img/dataBackground.png b/htdocs/img/dataBackground.png similarity index 100% rename from img/dataBackground.png rename to htdocs/img/dataBackground.png diff --git a/img/dataBackground.psd b/htdocs/img/dataBackground.psd similarity index 100% rename from img/dataBackground.psd rename to htdocs/img/dataBackground.psd diff --git a/img/doc_lines_stright.png b/htdocs/img/doc_lines_stright.png similarity index 100% rename from img/doc_lines_stright.png rename to htdocs/img/doc_lines_stright.png diff --git a/img/document.png b/htdocs/img/document.png similarity index 100% rename from img/document.png rename to htdocs/img/document.png diff --git a/img/ecdbSpriteV1.png b/htdocs/img/ecdbSpriteV1.png similarity index 100% rename from img/ecdbSpriteV1.png rename to htdocs/img/ecdbSpriteV1.png diff --git a/img/ecdbSpriteV1.psd b/htdocs/img/ecdbSpriteV1.psd similarity index 100% rename from img/ecdbSpriteV1.psd rename to htdocs/img/ecdbSpriteV1.psd diff --git a/img/ecdb_loggo.png b/htdocs/img/ecdb_loggo.png similarity index 100% rename from img/ecdb_loggo.png rename to htdocs/img/ecdb_loggo.png diff --git a/img/ecdb_loggo.psd b/htdocs/img/ecdb_loggo.psd similarity index 100% rename from img/ecdb_loggo.psd rename to htdocs/img/ecdb_loggo.psd diff --git a/img/icon-search.png b/htdocs/img/icon-search.png similarity index 100% rename from img/icon-search.png rename to htdocs/img/icon-search.png diff --git a/img/inbox.png b/htdocs/img/inbox.png similarity index 100% rename from img/inbox.png rename to htdocs/img/inbox.png diff --git a/htdocs/img/indexBG.png b/htdocs/img/indexBG.png new file mode 100644 index 0000000..da83e2f Binary files /dev/null and b/htdocs/img/indexBG.png differ diff --git a/include/autocomplete/indicator.gif b/htdocs/img/indicator.gif similarity index 100% rename from include/autocomplete/indicator.gif rename to htdocs/img/indicator.gif diff --git a/img/key.png b/htdocs/img/key.png similarity index 100% rename from img/key.png rename to htdocs/img/key.png diff --git a/img/pencil.png b/htdocs/img/pencil.png similarity index 100% rename from img/pencil.png rename to htdocs/img/pencil.png diff --git a/img/picture.png b/htdocs/img/picture.png similarity index 100% rename from img/picture.png rename to htdocs/img/picture.png diff --git a/img/print.png b/htdocs/img/print.png similarity index 100% rename from img/print.png rename to htdocs/img/print.png diff --git a/img/round_minus.png b/htdocs/img/round_minus.png similarity index 100% rename from img/round_minus.png rename to htdocs/img/round_minus.png diff --git a/img/round_plus.png b/htdocs/img/round_plus.png similarity index 100% rename from img/round_plus.png rename to htdocs/img/round_plus.png diff --git a/img/save.png b/htdocs/img/save.png similarity index 100% rename from img/save.png rename to htdocs/img/save.png diff --git a/img/share.png b/htdocs/img/share.png similarity index 100% rename from img/share.png rename to htdocs/img/share.png diff --git a/img/shop_cart.png b/htdocs/img/shop_cart.png similarity index 100% rename from img/shop_cart.png rename to htdocs/img/shop_cart.png diff --git a/img/spechbubble.png b/htdocs/img/spechbubble.png similarity index 100% rename from img/spechbubble.png rename to htdocs/img/spechbubble.png diff --git a/img/spechbubble_sq.png b/htdocs/img/spechbubble_sq.png similarity index 100% rename from img/spechbubble_sq.png rename to htdocs/img/spechbubble_sq.png diff --git a/img/trash.png b/htdocs/img/trash.png similarity index 100% rename from img/trash.png rename to htdocs/img/trash.png diff --git a/img/user.png b/htdocs/img/user.png similarity index 100% rename from img/user.png rename to htdocs/img/user.png diff --git a/htdocs/index.php b/htdocs/index.php new file mode 100644 index 0000000..dc2251b --- /dev/null +++ b/htdocs/index.php @@ -0,0 +1,23 @@ + array( + 'determineRouteBeforeAppMiddleware' => true, + ), +)); + +require_once __DIR__ . '/../include/dependencies.php'; +require_once __DIR__ . '/../include/middlewares.php'; +require_once __DIR__ . '/../include/routes.php'; + +$app->run(); diff --git a/include/autocomplete/jquery.autocomplete.js b/htdocs/js/jquery.autocomplete.js similarity index 96% rename from include/autocomplete/jquery.autocomplete.js rename to htdocs/js/jquery.autocomplete.js index 37a6a8a..9d12a29 100644 --- a/include/autocomplete/jquery.autocomplete.js +++ b/htdocs/js/jquery.autocomplete.js @@ -1,808 +1,808 @@ -/* - * jQuery Autocomplete plugin 1.1 - * - * Copyright (c) 2009 Jörn Zaefferer - * - * Dual licensed under the MIT and GPL licenses: - * http://www.opensource.org/licenses/mit-license.php - * http://www.gnu.org/licenses/gpl.html - * - * Revision: $Id: jquery.autocomplete.js 15 2009-08-22 10:30:27Z joern.zaefferer $ - */ - -;(function($) { - -$.fn.extend({ - autocomplete: function(urlOrData, options) { - var isUrl = typeof urlOrData == "string"; - options = $.extend({}, $.Autocompleter.defaults, { - url: isUrl ? urlOrData : null, - data: isUrl ? null : urlOrData, - delay: isUrl ? $.Autocompleter.defaults.delay : 10, - max: options && !options.scroll ? 10 : 150 - }, options); - - // if highlight is set to false, replace it with a do-nothing function - options.highlight = options.highlight || function(value) { return value; }; - - // if the formatMatch option is not specified, then use formatItem for backwards compatibility - options.formatMatch = options.formatMatch || options.formatItem; - - return this.each(function() { - new $.Autocompleter(this, options); - }); - }, - result: function(handler) { - return this.bind("result", handler); - }, - search: function(handler) { - return this.trigger("search", [handler]); - }, - flushCache: function() { - return this.trigger("flushCache"); - }, - setOptions: function(options){ - return this.trigger("setOptions", [options]); - }, - unautocomplete: function() { - return this.trigger("unautocomplete"); - } -}); - -$.Autocompleter = function(input, options) { - - var KEY = { - UP: 38, - DOWN: 40, - DEL: 46, - TAB: 9, - RETURN: 13, - ESC: 27, - COMMA: 188, - PAGEUP: 33, - PAGEDOWN: 34, - BACKSPACE: 8 - }; - - // Create $ object for input element - var $input = $(input).attr("autocomplete", "off").addClass(options.inputClass); - - var timeout; - var previousValue = ""; - var cache = $.Autocompleter.Cache(options); - var hasFocus = 0; - var lastKeyPressCode; - var config = { - mouseDownOnSelect: false - }; - var select = $.Autocompleter.Select(options, input, selectCurrent, config); - - var blockSubmit; - - // prevent form submit in opera when selecting with return key - $.browser.opera && $(input.form).bind("submit.autocomplete", function() { - if (blockSubmit) { - blockSubmit = false; - return false; - } - }); - - // only opera doesn't trigger keydown multiple times while pressed, others don't work with keypress at all - $input.bind(($.browser.opera ? "keypress" : "keydown") + ".autocomplete", function(event) { - // a keypress means the input has focus - // avoids issue where input had focus before the autocomplete was applied - hasFocus = 1; - // track last key pressed - lastKeyPressCode = event.keyCode; - switch(event.keyCode) { - - case KEY.UP: - event.preventDefault(); - if ( select.visible() ) { - select.prev(); - } else { - onChange(0, true); - } - break; - - case KEY.DOWN: - event.preventDefault(); - if ( select.visible() ) { - select.next(); - } else { - onChange(0, true); - } - break; - - case KEY.PAGEUP: - event.preventDefault(); - if ( select.visible() ) { - select.pageUp(); - } else { - onChange(0, true); - } - break; - - case KEY.PAGEDOWN: - event.preventDefault(); - if ( select.visible() ) { - select.pageDown(); - } else { - onChange(0, true); - } - break; - - // matches also semicolon - case options.multiple && $.trim(options.multipleSeparator) == "," && KEY.COMMA: - case KEY.TAB: - case KEY.RETURN: - if( selectCurrent() ) { - // stop default to prevent a form submit, Opera needs special handling - event.preventDefault(); - blockSubmit = true; - return false; - } - break; - - case KEY.ESC: - select.hide(); - break; - - default: - clearTimeout(timeout); - timeout = setTimeout(onChange, options.delay); - break; - } - }).focus(function(){ - // track whether the field has focus, we shouldn't process any - // results if the field no longer has focus - hasFocus++; - }).blur(function() { - hasFocus = 0; - if (!config.mouseDownOnSelect) { - hideResults(); - } - }).click(function() { - // show select when clicking in a focused field - if ( hasFocus++ > 1 && !select.visible() ) { - onChange(0, true); - } - }).bind("search", function() { - // TODO why not just specifying both arguments? - var fn = (arguments.length > 1) ? arguments[1] : null; - function findValueCallback(q, data) { - var result; - if( data && data.length ) { - for (var i=0; i < data.length; i++) { - if( data[i].result.toLowerCase() == q.toLowerCase() ) { - result = data[i]; - break; - } - } - } - if( typeof fn == "function" ) fn(result); - else $input.trigger("result", result && [result.data, result.value]); - } - $.each(trimWords($input.val()), function(i, value) { - request(value, findValueCallback, findValueCallback); - }); - }).bind("flushCache", function() { - cache.flush(); - }).bind("setOptions", function() { - $.extend(options, arguments[1]); - // if we've updated the data, repopulate - if ( "data" in arguments[1] ) - cache.populate(); - }).bind("unautocomplete", function() { - select.unbind(); - $input.unbind(); - $(input.form).unbind(".autocomplete"); - }); - - - function selectCurrent() { - var selected = select.selected(); - if( !selected ) - return false; - - var v = selected.result; - previousValue = v; - - if ( options.multiple ) { - var words = trimWords($input.val()); - if ( words.length > 1 ) { - var seperator = options.multipleSeparator.length; - var cursorAt = $(input).selection().start; - var wordAt, progress = 0; - $.each(words, function(i, word) { - progress += word.length; - if (cursorAt <= progress) { - wordAt = i; - return false; - } - progress += seperator; - }); - words[wordAt] = v; - // TODO this should set the cursor to the right position, but it gets overriden somewhere - //$.Autocompleter.Selection(input, progress + seperator, progress + seperator); - v = words.join( options.multipleSeparator ); - } - v += options.multipleSeparator; - } - - $input.val(v); - hideResultsNow(); - $input.trigger("result", [selected.data, selected.value]); - return true; - } - - function onChange(crap, skipPrevCheck) { - if( lastKeyPressCode == KEY.DEL ) { - select.hide(); - return; - } - - var currentValue = $input.val(); - - if ( !skipPrevCheck && currentValue == previousValue ) - return; - - previousValue = currentValue; - - currentValue = lastWord(currentValue); - if ( currentValue.length >= options.minChars) { - $input.addClass(options.loadingClass); - if (!options.matchCase) - currentValue = currentValue.toLowerCase(); - request(currentValue, receiveData, hideResultsNow); - } else { - stopLoading(); - select.hide(); - } - }; - - function trimWords(value) { - if (!value) - return [""]; - if (!options.multiple) - return [$.trim(value)]; - return $.map(value.split(options.multipleSeparator), function(word) { - return $.trim(value).length ? $.trim(word) : null; - }); - } - - function lastWord(value) { - if ( !options.multiple ) - return value; - var words = trimWords(value); - if (words.length == 1) - return words[0]; - var cursorAt = $(input).selection().start; - if (cursorAt == value.length) { - words = trimWords(value) - } else { - words = trimWords(value.replace(value.substring(cursorAt), "")); - } - return words[words.length - 1]; - } - - // fills in the input box w/the first match (assumed to be the best match) - // q: the term entered - // sValue: the first matching result - function autoFill(q, sValue){ - // autofill in the complete box w/the first match as long as the user hasn't entered in more data - // if the last user key pressed was backspace, don't autofill - if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != KEY.BACKSPACE ) { - // fill in the value (keep the case the user has typed) - $input.val($input.val() + sValue.substring(lastWord(previousValue).length)); - // select the portion of the value not typed by the user (so the next character will erase) - $(input).selection(previousValue.length, previousValue.length + sValue.length); - } - }; - - function hideResults() { - clearTimeout(timeout); - timeout = setTimeout(hideResultsNow, 200); - }; - - function hideResultsNow() { - var wasVisible = select.visible(); - select.hide(); - clearTimeout(timeout); - stopLoading(); - if (options.mustMatch) { - // call search and run callback - $input.search( - function (result){ - // if no value found, clear the input box - if( !result ) { - if (options.multiple) { - var words = trimWords($input.val()).slice(0, -1); - $input.val( words.join(options.multipleSeparator) + (words.length ? options.multipleSeparator : "") ); - } - else { - $input.val( "" ); - $input.trigger("result", null); - } - } - } - ); - } - }; - - function receiveData(q, data) { - if ( data && data.length && hasFocus ) { - stopLoading(); - select.display(data, q); - autoFill(q, data[0].value); - select.show(); - } else { - hideResultsNow(); - } - }; - - function request(term, success, failure) { - if (!options.matchCase) - term = term.toLowerCase(); - var data = cache.load(term); - // recieve the cached data - if (data && data.length) { - success(term, data); - // if an AJAX url has been supplied, try loading the data now - } else if( (typeof options.url == "string") && (options.url.length > 0) ){ - - var extraParams = { - timestamp: +new Date() - }; - $.each(options.extraParams, function(key, param) { - extraParams[key] = typeof param == "function" ? param() : param; - }); - - $.ajax({ - // try to leverage ajaxQueue plugin to abort previous requests - mode: "abort", - // limit abortion to this input - port: "autocomplete" + input.name, - dataType: options.dataType, - url: options.url, - data: $.extend({ - q: lastWord(term), - limit: options.max - }, extraParams), - success: function(data) { - var parsed = options.parse && options.parse(data) || parse(data); - cache.add(term, parsed); - success(term, parsed); - } - }); - } else { - // if we have a failure, we need to empty the list -- this prevents the the [TAB] key from selecting the last successful match - select.emptyList(); - failure(term); - } - }; - - function parse(data) { - var parsed = []; - var rows = data.split("\n"); - for (var i=0; i < rows.length; i++) { - var row = $.trim(rows[i]); - if (row) { - row = row.split("|"); - parsed[parsed.length] = { - data: row, - value: row[0], - result: options.formatResult && options.formatResult(row, row[0]) || row[0] - }; - } - } - return parsed; - }; - - function stopLoading() { - $input.removeClass(options.loadingClass); - }; - -}; - -$.Autocompleter.defaults = { - inputClass: "ac_input", - resultsClass: "ac_results", - loadingClass: "ac_loading", - minChars: 1, - delay: 400, - matchCase: false, - matchSubset: true, - matchContains: false, - cacheLength: 10, - max: 100, - mustMatch: false, - extraParams: {}, - selectFirst: true, - formatItem: function(row) { return row[0]; }, - formatMatch: null, - autoFill: false, - width: 0, - multiple: false, - multipleSeparator: ", ", - highlight: function(value, term) { - return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" + term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]*>)(?![^&;]+;)", "gi"), "$1"); - }, - scroll: true, - scrollHeight: 180 -}; - -$.Autocompleter.Cache = function(options) { - - var data = {}; - var length = 0; - - function matchSubset(s, sub) { - if (!options.matchCase) - s = s.toLowerCase(); - var i = s.indexOf(sub); - if (options.matchContains == "word"){ - i = s.toLowerCase().search("\\b" + sub.toLowerCase()); - } - if (i == -1) return false; - return i == 0 || options.matchContains; - }; - - function add(q, value) { - if (length > options.cacheLength){ - flush(); - } - if (!data[q]){ - length++; - } - data[q] = value; - } - - function populate(){ - if( !options.data ) return false; - // track the matches - var stMatchSets = {}, - nullData = 0; - - // no url was specified, we need to adjust the cache length to make sure it fits the local data store - if( !options.url ) options.cacheLength = 1; - - // track all options for minChars = 0 - stMatchSets[""] = []; - - // loop through the array and create a lookup structure - for ( var i = 0, ol = options.data.length; i < ol; i++ ) { - var rawValue = options.data[i]; - // if rawValue is a string, make an array otherwise just reference the array - rawValue = (typeof rawValue == "string") ? [rawValue] : rawValue; - - var value = options.formatMatch(rawValue, i+1, options.data.length); - if ( value === false ) - continue; - - var firstChar = value.charAt(0).toLowerCase(); - // if no lookup array for this character exists, look it up now - if( !stMatchSets[firstChar] ) - stMatchSets[firstChar] = []; - - // if the match is a string - var row = { - value: value, - data: rawValue, - result: options.formatResult && options.formatResult(rawValue) || value - }; - - // push the current match into the set list - stMatchSets[firstChar].push(row); - - // keep track of minChars zero items - if ( nullData++ < options.max ) { - stMatchSets[""].push(row); - } - }; - - // add the data items to the cache - $.each(stMatchSets, function(i, value) { - // increase the cache size - options.cacheLength++; - // add to the cache - add(i, value); - }); - } - - // populate any existing data - setTimeout(populate, 25); - - function flush(){ - data = {}; - length = 0; - } - - return { - flush: flush, - add: add, - populate: populate, - load: function(q) { - if (!options.cacheLength || !length) - return null; - /* - * if dealing w/local data and matchContains than we must make sure - * to loop through all the data collections looking for matches - */ - if( !options.url && options.matchContains ){ - // track all matches - var csub = []; - // loop through all the data grids for matches - for( var k in data ){ - // don't search through the stMatchSets[""] (minChars: 0) cache - // this prevents duplicates - if( k.length > 0 ){ - var c = data[k]; - $.each(c, function(i, x) { - // if we've got a match, add it to the array - if (matchSubset(x.value, q)) { - csub.push(x); - } - }); - } - } - return csub; - } else - // if the exact item exists, use it - if (data[q]){ - return data[q]; - } else - if (options.matchSubset) { - for (var i = q.length - 1; i >= options.minChars; i--) { - var c = data[q.substr(0, i)]; - if (c) { - var csub = []; - $.each(c, function(i, x) { - if (matchSubset(x.value, q)) { - csub[csub.length] = x; - } - }); - return csub; - } - } - } - return null; - } - }; -}; - -$.Autocompleter.Select = function (options, input, select, config) { - var CLASSES = { - ACTIVE: "ac_over" - }; - - var listItems, - active = -1, - data, - term = "", - needsInit = true, - element, - list; - - // Create results - function init() { - if (!needsInit) - return; - element = $("
") - .hide() - .addClass(options.resultsClass) - .css("position", "absolute") - .appendTo(document.body); - - list = $("
+ + +
{$component.comment|@nl2br}
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Location{$component.location|default:'-'}
Quantity + {$component.quantity|default:'-'} + + + Price + {if $component.price} + {$component.price} {$member_settings.currency} + {else} + - + {/if} + Order quantity + {$component.order_quantity|default:'-'} + + +
Manufacturer + {$component.manufacturer|default:'-'} + Package + {$component.package|default:'-'} + Pins + {$component.pins|default:'-'} +
SMD + {if $component.smd == "Yes"} + + {else} + + {/if} + Scrap + {if $component.scrap == "Yes"} + + {else} + + {/if} + Public + {if $component.public == "Yes"} + + {else} + + {/if} +
Width + {if $component.width} + {$component.width} + {if $member_settings.measurement == 1} + mm + {else} + " + {/if} + {else} + - + {/if} + Weight + {if $component.weight} + {$component.weight} + {if $member_settings.measurement == 1} + g + {else} + {*TODO: g?*} + g + {/if} + {else} + - + {/if} +
Depth + {if $component.depth} + {$component.depth} + {if $member_settings.measurement == 1} + mm + {else} + " + {/if} + {else} + - + {/if} +
Height + {if $component.height} + {$component.height} + {if $member_settings.measurement == 1} + mm + {else} + " + {/if} + {else} + - + {/if} +
Datasheet + {if $component.datasheet} + + {else} + - + {/if} +
+
+ +
+
+
+ + + +
+
+
+ +
+
+{/block} \ No newline at end of file diff --git a/views/component_edit.tpl b/views/component_edit.tpl new file mode 100644 index 0000000..00091c3 --- /dev/null +++ b/views/component_edit.tpl @@ -0,0 +1,336 @@ +{extends file='layout.tpl'} + +{block name=title} + {if !$new_component} + Edit component - {$component.name} - ecDB + {else} + Add component - ecDB + {/if} +{/block} + +{block name=head} + + + + + + +{/block} + +{block name=body} + {if !$new_component} +

+ {$category.category_name} / + {$category.sub_category_name} / {$component.name} +

+ {elseif $new_component && $component} +

Add new component based on {$component.name}

+ {/if} + +
+
+ +
+ +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {if $project and !$new_component} + + + + {else} + + + + {/if} + + + + + + {if $project and !$new_component} + + + {else} + + + {/if} + + +
Name + + Category + + Quantity + + {if !$new_component} + + + {/if} +
Manufacturer + + Package + + Pins + +
Location + + Price + {$member_settings.currency} + To order + + {if !$new_component} + + + {/if} +
SMD + Yes + No + Scrap + Yes + No + Public + Yes + No +
Weight + + {if $member_settings.measurement == 1} + g + {else} + g {* TODO: g? *} + {/if} + Width + + {if $member_settings.measurement == 1} + mm + {else} + in + {/if} + + +
Depth + + {if $member_settings.measurement == 1} + mm + {else} + in + {/if} +
Datasheet URL + + + Height + + + {if $member_settings.measurement == 1} + mm + {else} + in + {/if} +
Image URL 1 + + Image URL 2 + +
Image URL 3 + + Image URL 4 + +
Add to projectQuantityProjectQuantity
+ + + + {$project.project_name} + +
+ +
+
+ {if !$new_component} + + + + {else} + + {/if} +
+
+
+ +
+
+{/block} \ No newline at end of file diff --git a/views/components.tpl b/views/components.tpl new file mode 100644 index 0000000..662d3ce --- /dev/null +++ b/views/components.tpl @@ -0,0 +1,135 @@ +{extends file='layout.tpl'} + +{block name=title}Home - ecDB{/block} + +{block name=head}{/block} + +{block name=body} + + + + {if $sub_categories} +
+ +
+ {/if} + + + + {assign var="filter_params" value=""} + {if $smarty.get.cat} + {assign var="filter_params" value=$filter_params|cat:'&cat='|cat:$smarty.get.cat} + {/if} + {if $smarty.get.subcat} + {assign var="filter_params" value=$filter_params|cat:'&subcat='|cat:$smarty.get.subcat} + {/if} + + + + + + + + + + + + + + + + + {foreach from=$components item=component} + + + + + + + + + + + + + + {/foreach} + +
+ + Name + + Category + + Package + + Pins + + Image + + Datasheet + + SMD + + Price + + Quantity + + Comment +
+ + {$component.name} + {$component.nx} / {$component.snx} + {$component.package|default:'-'}{$component.pins|default:'-'} + {if $component.url1} + + + + + + + {else} + - + {/if} + + {if $component.datasheet} + + + + {else} + - + {/if} + + {if $component.smd == 'No'} + + {else} + + {/if} + {$component.price|default:'-'}{$component.quantity|default:'-'} + {if $component.comment} +
+ + {$component.comment|@nl2br} +
+ {else} +
-
+ {/if} +
+ + +{/block} \ No newline at end of file diff --git a/views/components_public.tpl b/views/components_public.tpl new file mode 100644 index 0000000..684c8f4 --- /dev/null +++ b/views/components_public.tpl @@ -0,0 +1,19 @@ +{extends file='layout.tpl'} + +{block name=title}Home - ecDB{/block} + +{block name=head}{/block} + +{block name=body} + +

Public Components

+ +
+ When you add a component there is a button called "public". If you choose to set that to yes, it means that other people can see that you own that component.

+ + The thought with that setting is, for example; You are building a project and missed to order one component, to skip expensive shipping costs, long shipping time etc. you just make a quick search on ecDB for that component and contact the owner. Hopefully he is kind enough to send you that component quickly for a small charge. +
+ +

This function is under development...

+ +{/block} \ No newline at end of file diff --git a/views/components_search.tpl b/views/components_search.tpl new file mode 100644 index 0000000..dcf0939 --- /dev/null +++ b/views/components_search.tpl @@ -0,0 +1,120 @@ +{extends file='layout.tpl'} + +{block name=title}Home - ecDB{/block} + +{block name=head}{/block} + +{block name=body} + +

Search results

+ + + {assign var="filter_params" value=""} + {if $smarty.get.cat} + {assign var="filter_params" value=$filter_params|cat:'&cat='|cat:$smarty.get.cat} + {/if} + {if $smarty.get.subcat} + {assign var="filter_params" value=$filter_params|cat:'&subcat='|cat:$smarty.get.subcat} + {/if} + {if $smarty.get.q} + {assign var="filter_params" value=$filter_params|cat:'&q='|cat:$smarty.get.q} + {/if} + + + + + + + + + + + + + + + + + + {foreach from=$components item=component} + + + + + + + + + + + + + + + {/foreach} + +
+ + Name + + Category + + Manufacturer + + Package + + Pins + + Image + + Datasheet + + SMD + + Price + + Quantity + + Comment +
+ + {$component.name} + {$component.nx} / {$component.snx} + {$component.manufacturer|default:'-'}{$component.package|default:'-'}{$component.pins|default:'-'} + {if $component.url1} + + + + + + + {else} + - + {/if} + + {if $component.datasheet} + + + + {else} + - + {/if} + + {if $component.smd == 'No'} + + {else} + + {/if} + {$component.price|default:'-'}{$component.quantity|default:'-'} + {if $component.comment} +
+ + {$component.comment|@nl2br} +
+ {else} +
-
+ {/if} +
+ + +{/block} \ No newline at end of file diff --git a/views/contact.tpl b/views/contact.tpl new file mode 100644 index 0000000..b508880 --- /dev/null +++ b/views/contact.tpl @@ -0,0 +1,13 @@ +{extends file='layout.tpl'} + +{block name=title}Contact - ecDB{/block} + +{block name=head}{/block} + +{block name=body} + +

Contact us

+ + If you have any suggestions, questions or what not. Contact through the ecDB GitHub Project. + +{/block} \ No newline at end of file diff --git a/views/donate.tpl b/views/donate.tpl new file mode 100644 index 0000000..2af0f9b --- /dev/null +++ b/views/donate.tpl @@ -0,0 +1,21 @@ +{extends file='layout.tpl'} + +{block name=title}Donate - ecDB{/block} + +{block name=head}{/block} + +{block name=body} + +

Donate

+ + ecDB is completely free!
+ + However, if you like ecDB you may use the button below to donate some money to the project!

+ +
+ + + +
+ +{/block} \ No newline at end of file diff --git a/views/error.tpl b/views/error.tpl new file mode 100644 index 0000000..b605be8 --- /dev/null +++ b/views/error.tpl @@ -0,0 +1,19 @@ +{extends file='layout.tpl'} + +{block name=title}Error - ecDB{/block} + +{block name=head}{/block} + +{block name=body} +
+ {if $error_code == 1} + You don't have permission to view this component. + {elseif $error_code == 2} + You don't have permission to edit this component. + {elseif $error_code == 3} + Oh crap! Something broke... + {else} + Error! + {/if} +
+{/block} \ No newline at end of file diff --git a/views/layout.tpl b/views/layout.tpl new file mode 100644 index 0000000..e124ba6 --- /dev/null +++ b/views/layout.tpl @@ -0,0 +1,131 @@ + + + + + + + + + + {block name=title}Home - ecDB{/block} + {if $ga.account} + + {/if} + + {block name=head}{/block} + + +
+ + + + + + +
+
+ {if !empty($errors)} + {foreach from=$errors item=$msg} +
+
  • {$msg}
+
+ {/foreach} + {/if} + {if !empty($messages)} + {foreach from=$messages item=$msg} +
+ {$msg} +
+ {/foreach} + {/if} + {if !empty($info)} + {foreach from=$info item=$msg} +
+ {$msg} +
+ {/foreach} + {/if} +
+ {block name=body}{/block} +
+ +
+
+
+ © 2010 - {'Y'|@date} ecDB - Created by Nils Fredriksson + - Contact us + - Terms & Privacy + - About +
+ +
+ + {$STATS.members} + members, + + {$STATS.components} + components and + + {$STATS.projects} + projects. +
+
+
+ Design by +
+
+ +
+ + diff --git a/views/login.tpl b/views/login.tpl new file mode 100644 index 0000000..f856bde --- /dev/null +++ b/views/login.tpl @@ -0,0 +1,46 @@ +{extends file='layout.tpl'} + +{block name=title}ecDB - electronics component DataBase{/block} + +{block name=head}{/block} + +{block name=body} + + +
+
+ +
+ You want to build something and need some components for your project. + You don't know if you have those components, or where they are. + This is a problem many of us recognise. + We want to change that for you by making a online inventory system for your electronic components + that is easy to use. + Add your components. Search to find it, and then use it! +
+ +
+
+ +
+ To try ecDB, login with demo:demo
+ +
+
+
+ +
+
+
+
+ +
+
+
+
+
+
+ +{/block} \ No newline at end of file diff --git a/views/member.tpl b/views/member.tpl new file mode 100644 index 0000000..291e50e --- /dev/null +++ b/views/member.tpl @@ -0,0 +1,73 @@ +{extends file='layout.tpl'} + +{block name=title}Home - ecDB{/block} + +{block name=head}{/block} + +{block name=body} +

Settings

+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + {if $smarty.session.SESS_IS_ADMIN} + + + + + {/if} + +
First Name + + Last Name + +
Email + +
Current Password + + New password + +
Measurement System + Metric + American System (Imperial) +
Currency + +
Administrative User + {if $member.admin == 1}Yes{else}No{/if} +
+
+
+ +
+
+
+{/block} \ No newline at end of file diff --git a/views/project-edit.tpl b/views/project-edit.tpl new file mode 100644 index 0000000..e6f30a4 --- /dev/null +++ b/views/project-edit.tpl @@ -0,0 +1,26 @@ +{extends file='layout.tpl'} + +{block name=title}Your Projects - ecDB{/block} + +{block name=head}{/block} + +{block name=body} + + +

Edit Project

+ +
+
+ +
+
+ +
+
+ + +
+
+
+ +{/block} \ No newline at end of file diff --git a/views/project-view.tpl b/views/project-view.tpl new file mode 100644 index 0000000..122a0ef --- /dev/null +++ b/views/project-view.tpl @@ -0,0 +1,95 @@ +{extends file='layout.tpl'} + +{block name=title}Viewing project - {$project.project_name} - ecDB{/block} + +{block name=head} + + + +{/block} + +{block name=body} +

+ Viewing project + + {if $project.project_url} + {$project.project_name} + {else} + {$project.project_name} + {/if} + +

+ + + + + + + + + + + + + + + + + {foreach from=$components item=component} + + {if $smarty.session.SESS_MEMBER_ID} + + + {else} + + + {/if} + + + + + + + + + {/foreach} + +
+ Name + + Category + + Manufacturer + + Package + + SMD + + Price + + Quantity in stock + + Quantity in project +
+ + + {$component.name} + {$component.name}{$component.category} / {$component.subcategory}{if $component.manufacturer}{$component.manufacturer}{else}-{/if}{if $component.package}{$component.package}{else}-{/if}{if $component.price}{$component.price}{else}-{/if}{if $component.quantity}{$component.quantity}{else}-{/if}{if $component.projects_data_quantity}{$component.projects_data_quantity}{else}-{/if}
+ +
+ {if !$price.total} + 0 {$price.currency} + {else} + {$price.total} {$price.currency} + {/if} +
+{/block} diff --git a/views/projects-list.tpl b/views/projects-list.tpl new file mode 100644 index 0000000..ca7f8d3 --- /dev/null +++ b/views/projects-list.tpl @@ -0,0 +1,58 @@ +{extends file='layout.tpl'} + +{block name=title}Your Projects - ecDB{/block} + +{block name=head}{/block} + +{block name=body} + + + {if $smarty.session.SESS_MEMBER_ID} + +
+
+ +
+
+
+
+ +
+
+
+
+ {/if} + + + + + + + + + + + + {foreach from=$projects item=project} + + {if $smarty.session.SESS_MEMBER_ID} + + {else} + + {/if} + + + + + {/foreach} + +
Name + Number of ComponentsTotal cost
{$project.project_name}{$project.qty|default:'-'} + {if $project.total_price} + {$project.total_price} {$project.currency|default:'-'} + {else} + - + {/if} +
+ +{/block} \ No newline at end of file diff --git a/views/registration.tpl b/views/registration.tpl new file mode 100644 index 0000000..5feafda --- /dev/null +++ b/views/registration.tpl @@ -0,0 +1,55 @@ +{extends file='layout.tpl'} + +{block name=title}Register - ecDB{/block} + +{block name=head}{/block} + +{block name=body} + + +
+
+
+ You want to build something and need some components for your project. + You don't know if you have those components, or where they are. + This is a problem many of us recognise. + We want to change that for you by making a online inventory system for your electronic components that is easy to use. + Add your components. Search to find it, and then use it! +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ By registering you accept the Terms and Contidions.

+
+ +
+
+
+
+
+
+ +{/block} \ No newline at end of file diff --git a/views/shop_list.tpl b/views/shop_list.tpl new file mode 100644 index 0000000..52e4695 --- /dev/null +++ b/views/shop_list.tpl @@ -0,0 +1,79 @@ +{extends file='layout.tpl'} + +{block name=title}Shopping list - ecDB{/block} + +{block name=head}{/block} + +{block name=body} + + + + + + + + + + + + + + + + {foreach from=$components item=component} + + + + + + + + + + + + {/foreach} + +
+ Name + + Manufacturer + + Package + + SMD + + Price + + Quantity + + Quantity to order + + Comment +
+ + + {$component.name} + {$component.manufacturer|default:'-'}{$component.package|default:'-'} + {if $component.smd == 'No'} + + {else} + + {/if} + {$component.price|default:'-'}{$component.quantity|default:'-'}{$component.order_quantity|default:'-'} +
+ {if $component.comment == ''} + - + {else} + + + {$component.comment} + + {/if} +
+
+
+ {$total_price} {$currency} +
+ +{/block} \ No newline at end of file diff --git a/views/terms.tpl b/views/terms.tpl new file mode 100644 index 0000000..454f6f2 --- /dev/null +++ b/views/terms.tpl @@ -0,0 +1,41 @@ +{extends file='layout.tpl'} + +{block name=title}Terms & Privacy - ecDB{/block} + +{block name=head}{/block} + +{block name=body} +

Terms and Conditions & Privacy Policy

+ +

1. Terms

+ + By accessing this web site, you are agreeing to be bound by these web site Terms and Conditions of Use, all applicable laws and regulations, and agree that you are responsible for compliance with any applicable local laws. If you do not agree with any of these terms, you are prohibited from using or accessing this site. The materials contained in this web site are protected by applicable copyright and trademark law.

+ +

2. Membership

+ + As a condition to using the services you are required to register with ecDB. By registering with ecDB you certify that you always provide valid, and updated information, you are an individual (i.e., not a corporate entity) and that you have the legal rights to enter such an agreement. The ID and password (from now referred to as "login-data") is the sole responsibility. It is required that you, as a registered ecDB user maintain the safety of your own login-data.

+ + ecDB maintains the right to terminate your membership at any time, with or without motivation or warning. All members are responsible for the consequences of use of this website. In cases of conflict with one or more non-members or members, will ecDB not be liable for any damages caused, in the current situation or future, resulting from the conflict.

+ + As a registered ecDB user you warrant and agree to the fact that you will not contribute any content that (a) infringes, violates or otherwise interferes with any copyright or trademark of another party, (b) reveal any trade secret, unless you own the trade secret or has the owner’s permission to post it, (c) infringes any intellectual property right of another or the privacy or publicity rights of another, (d) is libelous, defamatory, abusive, threatening, harassing, hateful, offensive or otherwise violates any law or right of any third party.

+ +

3. Disclaimer

+ + ecDB reserves all rights and disclaims all liability. ecDB makes no guarantee of reliability, safety or operation of this site.
+ As a registered user, you have full responsibility, without contradiction, for the information you publish and make widely available here.

+ +

4. Ownership

+ + It is strictly forbidden to copy, distribute, or modify any material from ecDB. You may print material for private use. For all other use requires permission from ecDB.

+ +

5. Site Terms of Use Modifications

+ + ecDB may revise these terms of use at any time without notice. By using ecDB you are agreeing to be bound by the then current version of these Terms and Conditions of Use.

+ +

Privacy Policy

+ + ecDB handles your personal information in accordance with the European data protection laws.

+ + Third parties can get access to all the information you intended to make public through your settings. Your email address or other personal data is NEVER shared by us to third parties. + +{/block} \ No newline at end of file