├── .gitignore ├── Lecture1 ├── README.md ├── all_in_one.sql ├── footer.php ├── header.php ├── index.php ├── login.php ├── logout.php ├── mytasks.php ├── newtask.php ├── note.php └── registration.php ├── Lecture2 ├── README.md ├── category.html ├── category.php ├── note_item.php └── restful_api.php ├── Lecture3 ├── README.md ├── connection.php ├── controllers │ ├── items_controller.php │ └── pages_controller.php ├── index.php ├── models │ ├── items.php │ └── pages.php ├── routes.php └── views │ ├── items │ ├── item.php │ ├── item_add.php │ ├── item_add_ok.php │ ├── item_update_ok.php │ └── items.php │ ├── layout.php │ └── pages │ ├── error.php │ └── home.php ├── Lecture4 ├── .gitignore ├── README.md ├── about.html ├── contact.html ├── display_name.js ├── hello.js ├── hello_files.js ├── hello_static.js ├── listneremitter.js ├── package-lock.json ├── package.json ├── read_file.js ├── readstream.js ├── testfile.txt └── timeout_callback.js ├── Lecture5 ├── .gitignore ├── README.md ├── app.js ├── bin │ └── www ├── controllers │ ├── NoteCategoryController.js │ ├── NoteItemController.js │ └── UserController.js ├── dbdata.js ├── models │ ├── NoteCategoryModel.js │ ├── NoteItemModel.js │ └── UserModel.js ├── package-lock.json ├── package.json ├── public │ └── stylesheets │ │ └── style.css ├── routes │ ├── NoteCategoryRoutes.js │ ├── NoteItemRoutes.js │ ├── UserRoutes.js │ └── index.js └── views │ ├── error.hbs │ ├── index.hbs │ ├── layout.hbs │ ├── noteItems │ ├── list.hbs │ └── newNote.hbs │ ├── partials │ ├── footer.hbs │ └── header.hbs │ └── user │ ├── list.hbs │ ├── login.hbs │ ├── profile.hbs │ └── register.hbs ├── Lecture6 ├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── components │ ├── about.js │ ├── home.js │ ├── items-alt.js │ └── items.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── serviceWorker.js │ └── setupTests.js ├── Lecture9 └── ReactRedux │ ├── .gitignore │ ├── README.md │ ├── package-lock.json │ ├── package.json │ ├── public │ ├── favicon.ico │ ├── index.html │ ├── logo192.png │ ├── logo512.png │ ├── manifest.json │ └── robots.txt │ └── src │ ├── App.css │ ├── App.js │ ├── App.test.js │ ├── components │ ├── about.js │ ├── footer.js │ ├── header.js │ ├── home.js │ ├── item-add.js │ ├── item-change.js │ ├── items-all.js │ ├── items-done.js │ ├── items-todo.js │ ├── login.js │ ├── nav-menu.js │ ├── profile.js │ └── register.js │ ├── index.css │ ├── index.js │ ├── logo.svg │ ├── redux │ ├── slices │ │ ├── authSlice.js │ │ ├── itemsSlice.js │ │ ├── sidebarSlice.js │ │ └── userSlice.js │ └── store.js │ ├── serviceWorker.js │ └── setupTests.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | temp/ 2 | .idea -------------------------------------------------------------------------------- /Lecture1/README.md: -------------------------------------------------------------------------------- 1 | # Lecture 1 2 | A simple PHP application Notes, where we write down tasks that we need to do in the future. User can In this example, the following topics are covered: 3 | 1. registration 4 | 2. login 5 | 3. cookies 6 | 4. sessions 7 | 5. HTTP post 8 | 6. HTML forms 9 | 7. Databases 10 | 8. Connection to DB 11 | 12 | # Tools used 13 | 1. WAMP 14 | 2. MyPhpAdmin 15 | 3. MariaDB 16 | 4. PHP Storm 17 | -------------------------------------------------------------------------------- /Lecture1/all_in_one.sql: -------------------------------------------------------------------------------- 1 | create database notes_schema; 2 | 3 | CREATE TABLE notes_schema.user ( 4 | user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 5 | name VARCHAR(255) DEFAULT '', 6 | username VARCHAR(100) NOT NULL, 7 | password VARCHAR(100) NOT NULL 8 | ); 9 | 10 | CREATE TABLE notes_schema.note_item ( 11 | item_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 12 | name VARCHAR(255) DEFAULT '' 13 | ); 14 | 15 | CREATE TABLE notes_schema.note_category ( 16 | category_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 17 | name VARCHAR(255) DEFAULT '' 18 | ); 19 | 20 | 21 | CREATE TABLE notes_schema.note ( 22 | task_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 23 | user_id INT NOT NULL , 24 | category_id INT NOT NULL , 25 | item_id INT NOT NULL , 26 | FOREIGN KEY (user_id) REFERENCES notes_schema.user(user_id), 27 | FOREIGN KEY (category_id) REFERENCES notes_schema.note_category(category_id), 28 | FOREIGN KEY (item_id) REFERENCES notes_schema.note_item(item_id) 29 | ); 30 | 31 | ALTER TABLE notes_schema.note 32 | ADD COLUMN done TINYINT DEFAULT '0' AFTER item_id; 33 | 34 | 35 | INSERT INTO notes_schema.user (name, username, password) VALUES ('Tomaz', 'tomazk', SHA1('12345678')); 36 | INSERT INTO notes_schema.user (name, username, password) VALUES ('Sandi', 'sandim', SHA1('87654321')); 37 | INSERT INTO notes_schema.user (name, username, password) VALUES ('Mario', 'marioc', SHA1('11111111')); 38 | 39 | 40 | INSERT INTO notes_schema.note_item (name) VALUES ('Pedagoske obremenitve'); 41 | INSERT INTO notes_schema.note_item (name) VALUES ('Vpis ocen zagovorov vaj DSMJ'); 42 | INSERT INTO notes_schema.note_item (name) VALUES ('Priprava nalog za tekmovanje Pisek'); 43 | INSERT INTO notes_schema.note_item (name) VALUES ('Kupi pnevmatike'); 44 | INSERT INTO notes_schema.note_item (name) VALUES ('Vadi MAT z Ajdo za test'); 45 | INSERT INTO notes_schema.note_item (name) VALUES ('Priprava prosojnic Kotlin'); 46 | 47 | 48 | INSERT INTO notes_schema.note_category (name) VALUES ('Sluzba'); 49 | INSERT INTO notes_schema.note_category (name) VALUES ('Doma'); 50 | INSERT INTO notes_schema.note_category (name) VALUES ('Nakup'); 51 | 52 | 53 | INSERT INTO notes_schema.note (user_id, category_id, item_id, done) VALUES ('1', '1', '1', '0'); 54 | INSERT INTO notes_schema.note (user_id, category_id, item_id, done) VALUES ('1', '1', '2', '0'); 55 | INSERT INTO notes_schema.note (user_id, category_id, item_id, done) VALUES ('2', '1', '3', '1'); 56 | INSERT INTO notes_schema.note (user_id, category_id, item_id, done) VALUES ('1', '2', '4', '0'); 57 | INSERT INTO notes_schema.note (user_id, category_id, item_id, done) VALUES ('1', '2', '5', '0'); 58 | INSERT INTO notes_schema.note (user_id, category_id, item_id, done) VALUES ('1', '1', '6', '0'); -------------------------------------------------------------------------------- /Lecture1/footer.php: -------------------------------------------------------------------------------- 1 |
2 | Domov 3 | 4 | 5 | -------------------------------------------------------------------------------- /Lecture1/header.php: -------------------------------------------------------------------------------- 1 | set_charset("UTF8"); 10 | ?> 11 | 12 | 13 | 14 | Lecture Notes 1 15 | 16 | 17 |
18 | 19 | 22 | Logout 23 | 28 | Login  29 | Registration 30 | 33 |
34 |
35 | -------------------------------------------------------------------------------- /Lecture1/index.php: -------------------------------------------------------------------------------- 1 | 4 |

Welcome to Notes application!

5 | 17 | -------------------------------------------------------------------------------- /Lecture1/login.php: -------------------------------------------------------------------------------- 1 | query($query); 11 | if ($user_obj = $res->fetch_object()) { 12 | return $user_obj->user_id; 13 | } 14 | return -1; 15 | } 16 | 17 | function get_data($select, $col) 18 | { 19 | global $conn; 20 | $query = $select; 21 | $res = $conn->query($query); 22 | if ($res_obj = $res->fetch_object()) { 23 | return $res_obj->$col; 24 | } else 25 | return false; 26 | } 27 | 28 | 29 | $error = ""; 30 | if (isset($_POST["submit"])) { 31 | if (($user_id = validate_login($_POST["username"], $_POST["password"])) >= 0) { 32 | $_SESSION["USER_ID"] = $user_id; 33 | $cookie_value = get_data("SELECT name FROM user WHERE user.user_id = \"$user_id\";", "name"); 34 | setcookie("notes_user", $cookie_value, time() + (86400), "/"); 35 | header("Location: mytasks.php"); 36 | die(); 37 | } else { 38 | $error = "Login failed."; 39 | } 40 | } 41 | ?> 42 | 43 |

Login

44 |
45 |
46 |
47 |
48 |
49 |
50 | 51 | -------------------------------------------------------------------------------- /Lecture1/logout.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Lecture1/mytasks.php: -------------------------------------------------------------------------------- 1 | query($query); 19 | while ($note = $res->fetch_object()) { 20 | array_push($notes, $note); 21 | } 22 | } 23 | return $notes; 24 | } 25 | 26 | $notes = get_notes(); 27 | ?> 28 | 29 |

My tasks

30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 41 | 42 | 43 | 44 | 45 | 46 | 52 | 53 | 56 |
UserNoteCategoryDoneChange
uname; ?>iname; ?>cname; ?>done == 1) ? "Yes" : "No"); ?> 47 | done == 0) 49 | echo ""; 50 | ?> 51 |
57 | 58 | 61 | -------------------------------------------------------------------------------- /Lecture1/newtask.php: -------------------------------------------------------------------------------- 1 | query($query); 9 | $rows = array(); 10 | while ($row = $res->fetch_object()) { 11 | array_push($rows, $row); 12 | } 13 | return $rows; 14 | } 15 | 16 | $categories = get_rows("SELECT name FROM note_category"); 17 | 18 | function get_data($select, $col) 19 | { 20 | global $conn; 21 | $query = $select; 22 | $res = $conn->query($query); 23 | if ($res_obj = $res->fetch_object()) { 24 | return $res_obj->$col; 25 | } else 26 | return false; 27 | } 28 | 29 | function publish($category, $item, $done) 30 | { 31 | global $conn; 32 | 33 | if (isset($_SESSION["USER_ID"]) && !empty($_SESSION["USER_ID"])) { 34 | $user_id = mysqli_real_escape_string($conn, $_SESSION["USER_ID"]); 35 | $category_id = get_data("SELECT category_id FROM note_category WHERE note_category.name = \"$category\";", 36 | "category_id"); 37 | $item = mysqli_real_escape_string($conn, $item); 38 | $doneInt = ($done == "yes") ? 1 : 0; 39 | 40 | $query_item = "INSERT INTO note_item (name) VALUES('$item');"; 41 | if ($conn->query($query_item)) { 42 | $item_id = get_data("SELECT item_id FROM note_item WHERE note_item.name = \"$item\";", "item_id"); 43 | $query = "INSERT INTO note (user_id, category_id, item_id, done) 44 | VALUES('$user_id', '$category_id', '$item_id', '$doneInt');"; 45 | return ($conn->query($query)) ? true : false; 46 | } 47 | } 48 | return false; 49 | } 50 | 51 | $error = ""; 52 | if (isset($_POST["submit"])) { 53 | if (publish($_POST["category"], $_POST["item"], $_POST["done"])) { 54 | header("Location: newtask.php"); 55 | die(); 56 | } else { 57 | $error = "Task not published."; 58 | } 59 | } 60 | ?> 61 | 62 | 63 | 64 | Connect to notes_schema database 65 | 66 | 67 |

New task

68 |
69 | 70 |
71 |
80 |
83 | 89 |
90 |
91 | 92 |
93 | 94 | -------------------------------------------------------------------------------- /Lecture1/note.php: -------------------------------------------------------------------------------- 1 | query($query); 11 | 12 | while($note = $res->fetch_object()){ 13 | array_push($notes, $note); 14 | } 15 | } 16 | return $notes; 17 | } 18 | 19 | function update_note_item($id){ 20 | global $conn; 21 | if (isset($_SESSION["USER_ID"])) { 22 | if (isset($_GET["done"])) { 23 | $note_item_id = mysqli_real_escape_string($conn, $id); 24 | $query = "UPDATE note SET done= '1' WHERE task_id = $note_item_id;"; 25 | $res = $conn->query($query); 26 | header("Location: note.php?id=".$id); 27 | die(); 28 | } 29 | } 30 | } 31 | 32 | if(!isset($_GET["id"])){ 33 | echo "No parameters!"; 34 | die(); 35 | } 36 | 37 | $id = $_GET["id"]; 38 | $notes = get_note($id); 39 | 40 | if($notes == null){ 41 | echo "No access!"; 42 | die(); 43 | } 44 | 45 | ?> 46 | 47 |

Change item

48 | 49 | 50 | 53 | 54 | 64 | 65 | 66 |
name; ?> 55 | done == 1) 57 | echo "✓"; 58 | else { 59 | ?> 60 | "> 61 | 62 | 63 |
67 | 68 | -------------------------------------------------------------------------------- /Lecture1/registration.php: -------------------------------------------------------------------------------- 1 | query($query)) { 11 | return true; 12 | } else { 13 | echo mysqli_error($conn); 14 | return false; 15 | } 16 | } 17 | 18 | $error = ""; 19 | if (isset($_POST["submit"])) { 20 | if ($_POST["password"] != $_POST["repeat_password"]) { 21 | $error = "Passwords don't match"; 22 | } else if (register_user($_POST["name"], $_POST["username"], $_POST["password"])) { 23 | header("Location: index.php"); 24 | die(); 25 | } else { 26 | $error = "Registration failed."; 27 | } 28 | } 29 | ?> 30 | 31 |

Registration

32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | 41 | -------------------------------------------------------------------------------- /Lecture2/README.md: -------------------------------------------------------------------------------- 1 | # Lecture 2 2 | Demonstration of RESful API with note_items. 3 | 4 | # Tools used 5 | 1. WAMP 6 | 2. MyPhpAdmin 7 | 3. MariaDB 8 | 4. PHP Storm 9 | -------------------------------------------------------------------------------- /Lecture2/category.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Restful API for Notes category 6 | 7 | 8 | 9 |
10 | ID: Name:
11 |
12 | 13 | 14 | 15 | 16 |

17 | Result:
18 | 50 | 51 | -------------------------------------------------------------------------------- /Lecture2/category.php: -------------------------------------------------------------------------------- 1 | name = $name; 9 | $this->category_id = $id; 10 | } 11 | 12 | public static function GetCategoriesArray($db, $id=null) { 13 | if ($id==null) 14 | $qs="Select * from note_category"; 15 | else 16 | $qs="Select * from note_category WHERE category_id=".$id; 17 | 18 | $result=mysqli_query($db,$qs); 19 | 20 | if(mysqli_error($db)) 21 | { 22 | var_dump(mysqli_error($db)); 23 | exit(); 24 | } 25 | $categories=array(); 26 | 27 | while($row = mysqli_fetch_assoc($result)) { 28 | $category=new Category($row["name"],$row["category_id"]); 29 | $categories[]=$category; 30 | } 31 | return $categories; 32 | } 33 | 34 | public static function GetCategory($db, $id) { 35 | $qs="Select * from note_category WHERE category_id=".$id; 36 | $result=mysqli_query($db,$qs); 37 | 38 | if(mysqli_error($db)) 39 | { 40 | var_dump(mysqli_error($db)); 41 | exit(); 42 | } 43 | 44 | $row = mysqli_fetch_assoc($result); 45 | return new Category($row["name"],$row["category_id"]); 46 | } 47 | 48 | public function add($db){ 49 | $qs="insert into note_category (name) values('$this->name');"; 50 | $result=mysqli_query($db,$qs); 51 | 52 | if(mysqli_error($db)) 53 | { 54 | var_dump(mysqli_error($db)); 55 | exit(); 56 | } 57 | $this->category_id=mysqli_insert_id($db); 58 | } 59 | 60 | public function update($db){ 61 | $qs="update note_category set name='$this->name' where category_id=$this->category_id;"; 62 | $result=mysqli_query($db,$qs); 63 | 64 | if(mysqli_error($db)) 65 | { 66 | var_dump(mysqli_error($db)); 67 | exit(); 68 | } 69 | } 70 | public function delete($db){ 71 | $qs="delete from note_category where category_id=$this->category_id;"; 72 | $result=mysqli_query($db,$qs); 73 | 74 | if(mysqli_error($db)) 75 | { 76 | var_dump(mysqli_error($db)); 77 | exit(); 78 | } 79 | } 80 | } 81 | ?> 82 | 83 | 84 | -------------------------------------------------------------------------------- /Lecture2/note_item.php: -------------------------------------------------------------------------------- 1 | name = $name; 9 | $this->item_id = $id; 10 | } 11 | 12 | public static function allNoteItemsArray($db) { 13 | $qs="Select * from note_item"; 14 | $result=mysqli_query($db,$qs); 15 | 16 | if(mysqli_error($db)) 17 | { 18 | var_dump(mysqli_error($db)); 19 | exit(); 20 | } 21 | $note_items=array(); 22 | 23 | while($row = mysqli_fetch_assoc($result)) { 24 | $item=new NoteItem($row["name"],$row["item_id"]); 25 | $note_items[]=$item; 26 | } 27 | return $note_items; 28 | } 29 | } 30 | ?> 31 | 32 | 33 | -------------------------------------------------------------------------------- /Lecture2/restful_api.php: -------------------------------------------------------------------------------- 1 | set_charset("UTF8"); 14 | 15 | $elements = null; 16 | 17 | //restful_api/items 18 | if(isset($request[0])&&($request[0]=='items')) { 19 | switch ($method) { 20 | case 'GET': 21 | $elements = NoteItem::allNoteItemsArray($db); 22 | break; 23 | /* 24 | case 'PUT': 25 | break; 26 | case 'POST': 27 | break; 28 | case 'DELETE': 29 | break; 30 | */ 31 | } 32 | } 33 | 34 | //restful_api/categories 35 | if(isset($request[0])&&($request[0]=='categories')) { 36 | switch ($method) { 37 | case 'GET': 38 | if(isset($request[1])&&$request[1]!=='JSONP') // e.g. /restful_api/categories/1 39 | $elements = Category::GetCategoriesArray($db, $request[1]); 40 | else 41 | $elements = Category::GetCategoriesArray($db); // e.g. /restful_api/categories 42 | break; 43 | case 'POST': 44 | parse_str(file_get_contents('php://input'),$input); 45 | if(isset($input)){ 46 | $category=new Category($input["name"]); 47 | $category->add($db); 48 | $elements=array("info"=>"category ".$category->category_id." added"); 49 | } 50 | break; 51 | case 'PUT': 52 | if(isset($request[1])) { 53 | $category = Category::GetCategory($db, $request[1]); 54 | 55 | $input = json_decode(file_get_contents('php://input'),true); 56 | if (isset($input)) { 57 | $category->name=$input['name']; 58 | $category->update($db); 59 | $elements=array("info"=>"category ".$category->category_id." updated"); 60 | } 61 | } 62 | break; 63 | case 'DELETE': 64 | if(isset($request[1])) { 65 | $category = Category::GetCategory($db, $request[1]); 66 | $category->delete($db); 67 | $elements=array("info"=>"category ".$category->category_id." deleted"); 68 | } 69 | break; 70 | } 71 | } 72 | 73 | header('Content-Type: application/json'); 74 | header("Access-Control-Allow-Origin: *"); 75 | echo json_encode($elements); 76 | ?> 77 | 78 | 79 | -------------------------------------------------------------------------------- /Lecture3/README.md: -------------------------------------------------------------------------------- 1 | # Lecture 3 2 | Demonstration of pattern MVC in PHP. 3 | 4 | # Tools used 5 | 1. WAMP 6 | 2. MyPhpAdmin 7 | 3. MariaDB 8 | 4. PHP Storm 9 | -------------------------------------------------------------------------------- /Lecture3/connection.php: -------------------------------------------------------------------------------- 1 | set_charset("UTF8"); 10 | } 11 | return self::$singleton; 12 | } 13 | } 14 | ?> -------------------------------------------------------------------------------- /Lecture3/controllers/items_controller.php: -------------------------------------------------------------------------------- 1 | 2 | 37 | -------------------------------------------------------------------------------- /Lecture3/controllers/pages_controller.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Lecture3/index.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Lecture3/models/items.php: -------------------------------------------------------------------------------- 1 | name = $name; 8 | $this->item_id = $id; 9 | } 10 | 11 | public static function allNoteItems($db) { 12 | $qs="Select * from note_item"; 13 | $result=mysqli_query($db,$qs); 14 | 15 | if(mysqli_error($db)) 16 | { 17 | var_dump(mysqli_error($db)); 18 | exit(); 19 | } 20 | $note_items=array(); 21 | 22 | while($row = mysqli_fetch_assoc($result)) { 23 | $item=new NoteItem($row["name"],$row["item_id"]); 24 | $note_items[]=$item; 25 | } 26 | return $note_items; 27 | } 28 | 29 | public static function findItem($db, $id) { 30 | //$id_validated = $id; 31 | //$id_validated = intval($id); 32 | //$id_validated = (int) $id; 33 | $id_validated = filter_var($id, FILTER_SANITIZE_NUMBER_INT); 34 | $qs="Select * from note_item where item_id=1 or 1=1".$id_validated; 35 | $result=mysqli_query($db,$qs); 36 | if(mysqli_error($db)) 37 | { 38 | var_dump(mysqli_error($db)); 39 | exit(); 40 | } 41 | $row = mysqli_fetch_assoc($result); 42 | return new NoteItem($row["name"],$row["item_id"]); 43 | } 44 | 45 | public static function addItem($db, $name) { 46 | $qs="Insert into note_item (name) Values (?)"; 47 | if ($stmt = mysqli_prepare($db, $qs)) { 48 | mysqli_stmt_bind_param($stmt, "s", $name); 49 | mysqli_stmt_execute($stmt); 50 | mysqli_stmt_close($stmt); 51 | } 52 | 53 | $id=mysqli_insert_id($db); 54 | return NoteItem::findItem($db, $id); 55 | } 56 | 57 | public static function updateItem($db, $id, $name) { 58 | $id_validated = (int)$id; 59 | $name_validated = strval($name); 60 | 61 | $qs="UPDATE note_item SET name='$name_validated' WHERE (item_id=$id_validated)"; 62 | $result=mysqli_query($db,$qs); 63 | if(mysqli_error($db)) 64 | { 65 | var_dump(mysqli_error($db)); 66 | exit(); 67 | } 68 | 69 | $id=mysqli_insert_id($db); 70 | return NoteItem::findItem($db, $id); 71 | } 72 | 73 | } 74 | ?> 75 | 76 | 77 | -------------------------------------------------------------------------------- /Lecture3/models/pages.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Lecture3/routes.php: -------------------------------------------------------------------------------- 1 | 2 | { $action }(); 10 | } 11 | 12 | if (isset($_GET['controller']) && isset($_GET['action'])) { 13 | $controller = $_GET['controller']; 14 | $action = $_GET['action']; 15 | } else { 16 | 17 | $controller = 'pages'; 18 | $action = 'home'; 19 | } 20 | 21 | $controllers = array('pages' => ['home', 'error'], 22 | 'items' => ['items', 'item', 23 | 'add', 'save', 'update']); 24 | 25 | if (array_key_exists($controller, $controllers)) { 26 | if (in_array($action, $controllers[$controller])) { 27 | call($controller, $action); 28 | } 29 | else { 30 | call('pages', 'error'); 31 | } 32 | } else { 33 | call('pages', 'error'); 34 | } 35 | ?> 36 | 37 | 38 | -------------------------------------------------------------------------------- /Lecture3/views/items/item.php: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 18 | 19 |
#Note item
item_id; ?> 15 | 16 |
20 |
21 | -------------------------------------------------------------------------------- /Lecture3/views/items/item_add.php: -------------------------------------------------------------------------------- 1 |

Add new item

2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 17 | 20 | 21 | 22 |
Note itemDone
15 | 16 | 18 | 19 |
23 |
-------------------------------------------------------------------------------- /Lecture3/views/items/item_add_ok.php: -------------------------------------------------------------------------------- 1 |

Note added!

2 |

You can see ithere

-------------------------------------------------------------------------------- /Lecture3/views/items/item_update_ok.php: -------------------------------------------------------------------------------- 1 |

Note updated!

2 | 3 |

You can see it here !

4 | 5 | -------------------------------------------------------------------------------- /Lecture3/views/items/items.php: -------------------------------------------------------------------------------- 1 |

List of all notes

2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 14 | 15 | 18 | 19 |
Note item
12 | name; ?> 13 |
20 | 21 | -------------------------------------------------------------------------------- /Lecture3/views/layout.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 44 |
45 |
46 | 47 |
48 | 49 |
50 |
51 | 52 | 55 | 56 | -------------------------------------------------------------------------------- /Lecture3/views/pages/error.php: -------------------------------------------------------------------------------- 1 |

Error on web page!

2 | -------------------------------------------------------------------------------- /Lecture3/views/pages/home.php: -------------------------------------------------------------------------------- 1 |

First page!

-------------------------------------------------------------------------------- /Lecture4/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Lecture4/README.md: -------------------------------------------------------------------------------- 1 | # Lecture 4 2 | Demonstration of different Node.js functionalities. 3 | 4 | Tools used: 5 | 1. Node.js 6 | 2. PHP Storm 7 | -------------------------------------------------------------------------------- /Lecture4/about.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Web server and files 6 | 7 | 8 |

Course on Web programming! Hello node.js!

9 | 10 | -------------------------------------------------------------------------------- /Lecture4/contact.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Web server and files 6 | 7 | 8 |

Written by Tomaz Kosar

9 | 10 | -------------------------------------------------------------------------------- /Lecture4/display_name.js: -------------------------------------------------------------------------------- 1 | function DisplayName(x){ 2 | console.log(x); 3 | } 4 | DisplayName('Tomaz'); -------------------------------------------------------------------------------- /Lecture4/hello.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | 3 | let app = http.createServer((req, res) => { 4 | res.writeHead(200, {'Content-Type': 'text/plain'}); 5 | 6 | res.end('Hello World!!!\n'); 7 | console.log('Client request received!'); 8 | }); 9 | 10 | app.listen(3000, '127.0.0.1'); 11 | console.log('Node server running on port 3000'); 12 | 13 | -------------------------------------------------------------------------------- /Lecture4/hello_files.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'), 2 | http = require('http'); 3 | 4 | let app = http.createServer((req, res) => { 5 | 6 | fs.readFile(__dirname + req.url, function (err,data) { 7 | if (err) { 8 | res.writeHead(404, {'Content-type': 'text/html'}); 9 | res.end('

Nothing here!

'); 10 | return; 11 | } 12 | res.writeHead(200, {'Content-type': 'text/html'}); 13 | res.end(data); 14 | 15 | }); 16 | 17 | console.log('Client request received!'); 18 | }); 19 | 20 | app.listen(3000, '127.0.0.1'); 21 | console.log('Node server running on port 3000'); 22 | 23 | -------------------------------------------------------------------------------- /Lecture4/hello_static.js: -------------------------------------------------------------------------------- 1 | const http = require('http'); 2 | 3 | let app = http.createServer((req, res) => { 4 | res.writeHead(200, {'Content-type': 'text/html'}); 5 | 6 | if (req.url === '/index.html' || req.url==='/') { 7 | res.end('

Hello World!

') 8 | } 9 | else if (req.url === '/contact.html') { 10 | res.end('

Written by Tomaz Kosar

') 11 | } 12 | if (req.url === '/about.html') { 13 | res.end('

Web programming course!

') 14 | } 15 | 16 | console.log('Client request received!'); 17 | }); 18 | 19 | app.listen(3000, '127.0.0.1'); 20 | console.log('Node server running on port 3000'); 21 | 22 | -------------------------------------------------------------------------------- /Lecture4/listneremitter.js: -------------------------------------------------------------------------------- 1 | 2 | var emitter = require('events').EventEmitter; 3 | 4 | var em = new emitter(); 5 | 6 | em.addListener('FirstEvent', function (data) { 7 | console.log('First subscriber: ' + data); 8 | }); 9 | 10 | em.addListener('FirstEvent', function (data) { 11 | console.log('Third subscriber: ' + data); 12 | }); 13 | 14 | em.on('SecondEvent', function (data) { // similar 15 | console.log('Second subscriber: ' + data); 16 | }); 17 | 18 | em.emit('FirstEvent', 'First event emitter example.'); 19 | 20 | em.emit('SecondEvent', 'Second event emitter example.'); 21 | 22 | -------------------------------------------------------------------------------- /Lecture4/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "scripts": { 3 | "start" : "node hello.js", 4 | "dev": "nodemon hello.js" 5 | }, 6 | "dependencies": { 7 | "express": "^4.17.1", 8 | "nodemon": "^2.0.15" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Lecture4/read_file.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | 3 | console.log("\nSync call! \n"); 4 | var data = fs.readFileSync('testfile.txt', 'utf8'); 5 | console.log("File contains: ", data); 6 | 7 | console.log("Async call! \n"); 8 | fs.readFile("testfile.txt", readDoneCallback); 9 | function readDoneCallback(error, dataBuffer) { 10 | if (!error) { 11 | console.log("File contains: ", 12 | dataBuffer.toString()); 13 | } 14 | } 15 | console.log("Not yet file received!"); 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Lecture4/readstream.js: -------------------------------------------------------------------------------- 1 | var fs = require("fs"); 2 | 3 | var readableStreamEvent = fs.createReadStream("testfile.txt"); 4 | 5 | readableStreamEvent.on('data', function (chunkBuffer) { 6 | // Called multiple times 7 | console.log('got chunk of', chunkBuffer.length, 'bytes'); 8 | }); 9 | 10 | readableStreamEvent.on('end', function() { 11 | // After read 12 | console.log('got all the data'); 13 | }); 14 | 15 | readableStreamEvent.on('error', function (err) { 16 | console.error('got error', err); 17 | }); 18 | 19 | -------------------------------------------------------------------------------- /Lecture4/testfile.txt: -------------------------------------------------------------------------------- 1 | This is a simple test file! -------------------------------------------------------------------------------- /Lecture4/timeout_callback.js: -------------------------------------------------------------------------------- 1 | var myCallback = function () { 2 | console.log("1 seconds later..."); 3 | }; 4 | setTimeout(myCallback, 1000); 5 | 6 | setTimeout(function () { 7 | console.log("2 seconds later..."); 8 | }, 2000); 9 | 10 | setTimeout(() => { 11 | console.log("3 seconds later..."); 12 | }, 3000); 13 | 14 | 15 | -------------------------------------------------------------------------------- /Lecture5/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Lecture5/README.md: -------------------------------------------------------------------------------- 1 | # Lecture 4 2 | Demonstration of Express on application Notes. 3 | 4 | # Tools used 5 | 1. Node.js 6 | 2. Express 7 | 3. Mongoose 8 | 4. MongoDB 9 | 5. PHP Storm 10 | -------------------------------------------------------------------------------- /Lecture5/app.js: -------------------------------------------------------------------------------- 1 | var dbAuth = require('./dbdata'); 2 | var createError = require('http-errors'); 3 | var express = require('express'); 4 | var path = require('path'); 5 | var cookieParser = require('cookie-parser'); 6 | var logger = require('morgan'); 7 | var mongoose = require('mongoose'); 8 | //CORS - React demo 9 | var cors = require('cors'); 10 | 11 | var mongoDB = 'mongodb+srv://'+dbAuth+'@cluster0-q3d7o.gcp.mongodb.net/NotesDB?retryWrites=true&w=majority'; 12 | mongoose.connect(mongoDB, { useNewUrlParser:true, useUnifiedTopology: true }); 13 | mongoose.Promise = global.Promise; 14 | var db = mongoose.connection; 15 | db.on('error', console.error.bind(console, 16 | 'MongoDB connection error:')); 17 | 18 | var indexRouter = require('./routes/index'); 19 | var usersRouter = require('./routes/UserRoutes'); 20 | var notesItemRouter = require('./routes/NoteItemRoutes'); 21 | var notesCategoriesRouter = require('./routes/NoteCategoryRoutes'); 22 | 23 | var app = express(); 24 | 25 | app.disable('etag'); 26 | 27 | // view engine setup 28 | app.set('views', path.join(__dirname, 'views')); 29 | var hbs = require('hbs'); 30 | app.set("view engine", "hbs"); 31 | app.use(express.static(__dirname + "/public")); 32 | hbs.registerPartials(__dirname + "/views/partials"); 33 | 34 | const oneDay = 1000 * 60 * 60 * 24; 35 | var session = require('express-session'); 36 | var MongoStore = require('connect-mongo'); 37 | app.use(session({ 38 | name: 'session', 39 | secret: 'this is a secret key', 40 | resave: true, 41 | saveUninitialized: false, 42 | cookie: { maxAge: oneDay }, 43 | store: MongoStore.create({ mongoUrl: mongoDB }) 44 | })); 45 | 46 | var allowedOrigins = ['http://localhost:4200', 47 | 'http://localhost:4100', 48 | 'http://localhost:3000']; 49 | 50 | app.use(cors({ 51 | credentials: true, 52 | origin: function(origin, callback){ 53 | // allow requests with no origin 54 | // (like mobile apps or curl requests) 55 | if(!origin) return callback(null, true); 56 | if(allowedOrigins.indexOf(origin) === -1){ 57 | var msg = 'The CORS policy for this site does not ' + 58 | 'allow access from the specified Origin.'; 59 | return callback(new Error(msg), false); 60 | } 61 | return callback(null, true); 62 | } 63 | })); 64 | 65 | app.use(logger('dev')); 66 | app.use(express.json()); 67 | app.use(express.urlencoded({ extended: false })); 68 | app.use(cookieParser()); 69 | app.use(express.static(path.join(__dirname, 'public'))); 70 | 71 | app.use('/', indexRouter); 72 | app.use('/user', usersRouter); 73 | app.use('/items', notesItemRouter); 74 | app.use('/categories', notesCategoriesRouter); 75 | 76 | // catch 404 and forward to error handler 77 | app.use(function(req, res, next) { 78 | next(createError(404)); 79 | }); 80 | 81 | // error handler 82 | app.use(function(err, req, res, next) { 83 | // set locals, only providing error in development 84 | res.locals.message = err.message; 85 | res.locals.error = req.app.get('env') === 'development' ? err : {}; 86 | 87 | // render the error page 88 | res.status(err.status || 500); 89 | res.render('error'); 90 | }); 91 | 92 | module.exports = app; 93 | -------------------------------------------------------------------------------- /Lecture5/bin/www: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /** 4 | * Module dependencies. 5 | */ 6 | 7 | var app = require('../app'); 8 | var debug = require('debug')('notesapp:server'); 9 | var http = require('http'); 10 | 11 | /** 12 | * Get port from environment and store in Express. 13 | */ 14 | 15 | var port = normalizePort(process.env.PORT || '3000'); 16 | app.set('port', port); 17 | 18 | /** 19 | * Create HTTP server. 20 | */ 21 | 22 | var server = http.createServer(app); 23 | 24 | /** 25 | * Listen on provided port, on all network interfaces. 26 | */ 27 | 28 | server.listen(port); 29 | server.on('error', onError); 30 | server.on('listening', onListening); 31 | 32 | /** 33 | * Normalize a port into a number, string, or false. 34 | */ 35 | 36 | function normalizePort(val) { 37 | var port = parseInt(val, 10); 38 | 39 | if (isNaN(port)) { 40 | // named pipe 41 | return val; 42 | } 43 | 44 | if (port >= 0) { 45 | // port number 46 | return port; 47 | } 48 | 49 | return false; 50 | } 51 | 52 | /** 53 | * Event listener for HTTP server "error" event. 54 | */ 55 | 56 | function onError(error) { 57 | if (error.syscall !== 'listen') { 58 | throw error; 59 | } 60 | 61 | var bind = typeof port === 'string' 62 | ? 'Pipe ' + port 63 | : 'Port ' + port; 64 | 65 | // handle specific listen errors with friendly messages 66 | switch (error.code) { 67 | case 'EACCES': 68 | console.error(bind + ' requires elevated privileges'); 69 | process.exit(1); 70 | break; 71 | case 'EADDRINUSE': 72 | console.error(bind + ' is already in use'); 73 | process.exit(1); 74 | break; 75 | default: 76 | throw error; 77 | } 78 | } 79 | 80 | /** 81 | * Event listener for HTTP server "listening" event. 82 | */ 83 | 84 | function onListening() { 85 | var addr = server.address(); 86 | var bind = typeof addr === 'string' 87 | ? 'pipe ' + addr 88 | : 'port ' + addr.port; 89 | debug('Listening on ' + bind); 90 | } 91 | -------------------------------------------------------------------------------- /Lecture5/controllers/NoteCategoryController.js: -------------------------------------------------------------------------------- 1 | var NoteCategoryModel = require('../models/NoteCategoryModel.js'); 2 | 3 | /** 4 | * NoteItemController.js 5 | * 6 | * @description :: Server-side logic for managing NoteItems. 7 | */ 8 | 9 | module.exports = { 10 | /** 11 | * NoteCategoryController.list() 12 | */ 13 | list: function (req, res) { 14 | NoteCategoryModel.find(function (err, NoteCategories) { 15 | if (err) { 16 | return res.status(500).json({ 17 | message: 'Error when getting Categories.', 18 | error: err 19 | }); 20 | } 21 | 22 | return res.json(NoteCategories); 23 | }); 24 | }, 25 | 26 | 27 | }; 28 | -------------------------------------------------------------------------------- /Lecture5/controllers/NoteItemController.js: -------------------------------------------------------------------------------- 1 | var NoteItemModel = require('../models/NoteItemModel.js'); 2 | 3 | /** 4 | * NoteItemController.js 5 | * 6 | * @description :: Server-side logic for managing NoteItems. 7 | */ 8 | 9 | module.exports = { 10 | /** 11 | * NoteItemController.list() 12 | */ 13 | list: function (req, res) { 14 | //React demo 15 | //NoteItemModel.find(function (err, NoteItems) { 16 | //Express demo 17 | NoteItemModel.find({username:req.session.username},function (err, NoteItems) { 18 | if (err) { 19 | return res.status(500).json({ 20 | message: 'Error when getting NoteItem.', 21 | error: err 22 | }); 23 | } 24 | 25 | //React demo 26 | return res.json(NoteItems); 27 | //Express demo 28 | //return res.render('noteItems/list', {data:NoteItems, userId:req.session.userId , username:req.session.username} ); 29 | }); 30 | }, 31 | 32 | openTask: function (req, res) { 33 | NoteItemModel.find({username:req.session.username, done:false},function (err, NoteItems) { 34 | if (err) { 35 | return res.status(500).json({ 36 | message: 'Error when getting NoteItem.', 37 | error: err 38 | }); 39 | } 40 | 41 | return res.render('noteItems/list', {data:NoteItems, userId:req.session.userId , username:req.session.username} ); 42 | }); 43 | }, 44 | 45 | finishedTask: function (req, res) { 46 | NoteItemModel.find({username:req.session.username, done:true},function (err, NoteItems) { 47 | if (err) { 48 | return res.status(500).json({ 49 | message: 'Error when getting NoteItem.', 50 | error: err 51 | }); 52 | } 53 | 54 | return res.render('noteItems/list', {data:NoteItems, userId:req.session.userId , username:req.session.username} ); 55 | }); 56 | }, 57 | 58 | workTask: function (req, res) { 59 | NoteItemModel.find({username:req.session.username, category:"Work"},function (err, NoteItems) { 60 | if (err) { 61 | return res.status(500).json({ 62 | message: 'Error when getting NoteItem.', 63 | error: err 64 | }); 65 | } 66 | 67 | return res.render('noteItems/list', {data:NoteItems, userId:req.session.userId , username:req.session.username} ); 68 | }); 69 | }, 70 | 71 | shopTask: function (req, res) { 72 | NoteItemModel.find({username:req.session.username, category:"Shopping"},function (err, NoteItems) { 73 | if (err) { 74 | return res.status(500).json({ 75 | message: 'Error when getting NoteItem.', 76 | error: err 77 | }); 78 | } 79 | 80 | return res.render('noteItems/list', {data:NoteItems, userId:req.session.userId , username:req.session.username} ); 81 | }); 82 | }, 83 | 84 | 85 | newTask: function (req, res) { 86 | res.render('noteItems/newNote', {userId:req.session.userId , username:req.session.username}); 87 | }, 88 | 89 | /** 90 | * NoteItemController.show() 91 | */ 92 | show: function (req, res) { 93 | var id = req.params.id; 94 | NoteItemModel.findOne({_id: id}, function (err, NoteItem) { 95 | if (err) { 96 | return res.status(500).json({ 97 | message: 'Error when getting NoteItem.', 98 | error: err 99 | }); 100 | } 101 | if (!NoteItem) { 102 | return res.status(404).json({ 103 | message: 'No such NoteItem' 104 | }); 105 | } 106 | return res.json(NoteItem); 107 | }); 108 | }, 109 | 110 | /** 111 | * NoteItemController.create() 112 | */ 113 | create: function (req, res) { 114 | var NoteItem = new NoteItemModel({ 115 | name : req.body.name, 116 | done : req.body.done, 117 | category : req.body.category, 118 | username : req.body.username 119 | 120 | }); 121 | 122 | NoteItem.save(function (err, NoteItem) { 123 | if (err) { 124 | return res.status(500).json({ 125 | message: 'Error when creating NoteItem', 126 | error: err 127 | }); 128 | } 129 | return res.status(201).json(NoteItem); 130 | }); 131 | }, 132 | 133 | /** 134 | * NoteItemController.update() 135 | */ 136 | update: function (req, res) { 137 | var id = req.params.id; 138 | NoteItemModel.findOne({_id: id}, function (err, NoteItem) { 139 | if (err) { 140 | return res.status(500).json({ 141 | message: 'Error when getting NoteItem', 142 | error: err 143 | }); 144 | } 145 | if (!NoteItem) { 146 | return res.status(404).json({ 147 | message: 'No such NoteItem' 148 | }); 149 | } 150 | 151 | NoteItem.id = req.body.id ? req.body.id : NoteItem.id; 152 | NoteItem.name = req.body.name ? req.body.name : NoteItem.name; 153 | NoteItem.done = req.body.done ? req.body.done : NoteItem.done; 154 | NoteItem.category = req.body.category ? req.body.category : NoteItem.category; 155 | NoteItem.username = req.body.username ? req.body.username : NoteItem.username; 156 | 157 | NoteItem.save(function (err, NoteItem) { 158 | if (err) { 159 | return res.status(500).json({ 160 | message: 'Error when updating NoteItem.', 161 | error: err 162 | }); 163 | } 164 | 165 | return res.json(NoteItem); 166 | }); 167 | }); 168 | }, 169 | 170 | /** 171 | * NoteItemController.remove() 172 | */ 173 | remove: function (req, res) { 174 | var id = req.params.id; 175 | NoteItemModel.findByIdAndRemove(id, function (err, NoteItem) { 176 | if (err) { 177 | return res.status(500).json({ 178 | message: 'Error when deleting the NoteItem.', 179 | error: err 180 | }); 181 | } 182 | return res.status(204).json(); 183 | }); 184 | } 185 | }; 186 | -------------------------------------------------------------------------------- /Lecture5/controllers/UserController.js: -------------------------------------------------------------------------------- 1 | var UserModel = require('../models/UserModel.js'); 2 | /** 3 | * UserController.js 4 | * 5 | * @description :: Server-side logic for managing Users. 6 | */ 7 | module.exports = { 8 | 9 | /** 10 | * UserController.list() 11 | */ 12 | list: function (req, res) { 13 | UserModel.find(function (err, Users) { 14 | if (err) { 15 | return res.status(500).json({ 16 | message: 'Error when getting User.', 17 | error: err 18 | }); 19 | } 20 | 21 | //return res.json(Users); 22 | return res.render('user/list', {data:Users, userId:req.session.userId , username:req.session.username} ); 23 | 24 | }); 25 | }, 26 | 27 | showLogin: function (req, res) { 28 | res.render('user/login'); 29 | }, 30 | 31 | showRegistration: function (req, res) { 32 | res.render('user/register'); 33 | }, 34 | 35 | showProfile: function (req, res) { 36 | res.render('user/profile', {userId:req.session.userId , username:req.session.username}); 37 | }, 38 | 39 | showLogout: function (req, res) { 40 | req.session.destroy(); 41 | res.render('index'); 42 | }, 43 | 44 | /** 45 | * UserController.show() 46 | */ 47 | show: function (req, res) { 48 | var id = req.params.id; 49 | 50 | UserModel.findOne({_id: id}, function (err, User) { 51 | if (err) { 52 | return res.status(500).json({ 53 | message: 'Error when getting User.', 54 | error: err 55 | }); 56 | } 57 | 58 | if (!User) { 59 | return res.status(404).json({ 60 | message: 'No such User' 61 | }); 62 | } 63 | 64 | return res.render('user/profile', User); 65 | //return res.json(User); 66 | }); 67 | }, 68 | 69 | /** 70 | * UserController.create() 71 | */ 72 | create: function (req, res) { 73 | var User = new UserModel({ 74 | username: req.body.username, 75 | password: req.body.password, 76 | name: req.body.name 77 | }); 78 | 79 | User.save(function (err, User) { 80 | if (err) { 81 | return res.status(500).json({ 82 | message: 'Error when creating User', 83 | error: err 84 | }); 85 | } 86 | 87 | return res.status(201).json(User); 88 | }); 89 | }, 90 | 91 | login: function (req, res, next) { 92 | UserModel.authenticate(req.body.username, req.body.password, function (error, user) { 93 | if (error || !user) { 94 | var err = new Error("Wrong username or password"); 95 | err.status = 401; 96 | //return res.redirect('/user/login'); 97 | return res.json({ 98 | message: 'Wrong login!', 99 | error: err 100 | }) 101 | } else { 102 | req.session.userId = user._id; 103 | req.session.username = user.username; 104 | 105 | return res.json(user); 106 | //return res.render('index', {userId: req.session.userId, username:req.session.username}); 107 | } 108 | }); 109 | }, 110 | 111 | /** 112 | * UserController.update() 113 | */ 114 | update: function (req, res) { 115 | var id = req.params.id; 116 | 117 | UserModel.findOne({_id: id}, function (err, User) { 118 | if (err) { 119 | return res.status(500).json({ 120 | message: 'Error when getting User', 121 | error: err 122 | }); 123 | } 124 | 125 | if (!User) { 126 | return res.status(404).json({ 127 | message: 'No such User' 128 | }); 129 | } 130 | 131 | User.name = req.body.name ? req.body.name : User.name; 132 | User.username = req.body.username ? req.body.username : User.username; 133 | User.password = req.body.password ? req.body.password : User.password; 134 | 135 | User.save(function (err, User) { 136 | if (err) { 137 | return res.status(500).json({ 138 | message: 'Error when updating User.', 139 | error: err 140 | }); 141 | } 142 | 143 | return res.json(User); 144 | }); 145 | }); 146 | }, 147 | 148 | /** 149 | * UserController.remove() 150 | */ 151 | remove: function (req, res) { 152 | var id = req.params.id; 153 | 154 | UserModel.findByIdAndRemove(id, function (err, User) { 155 | if (err) { 156 | return res.status(500).json({ 157 | message: 'Error when deleting the User.', 158 | error: err 159 | }); 160 | } 161 | 162 | return res.status(204).json(); 163 | }); 164 | } 165 | }; 166 | -------------------------------------------------------------------------------- /Lecture5/dbdata.js: -------------------------------------------------------------------------------- 1 | module.exports = '???:???'; -------------------------------------------------------------------------------- /Lecture5/models/NoteCategoryModel.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose'); 2 | var Schema = mongoose.Schema; 3 | 4 | var NoteCategorySchema = new Schema({ 5 | 'name' : String, 6 | }); 7 | 8 | module.exports = mongoose.model('categories', NoteCategorySchema); 9 | 10 | 11 | -------------------------------------------------------------------------------- /Lecture5/models/NoteItemModel.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose'); 2 | var Schema = mongoose.Schema; 3 | 4 | var NoteItemSchema = new Schema({ 5 | 'name' : String, 6 | 'done' : Boolean, 7 | 'category' : String, 8 | 'username' : String 9 | }); 10 | 11 | module.exports = mongoose.model('items', NoteItemSchema); 12 | 13 | 14 | -------------------------------------------------------------------------------- /Lecture5/models/UserModel.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose'); 2 | var Schema = mongoose.Schema; 3 | var bcrypt = require('bcrypt'); 4 | var SALT_WORK_FACTOR = 10; 5 | 6 | var UserSchema = new Schema({ 7 | 'username' : String, 8 | 'password' : String, 9 | 'name' : String 10 | }); 11 | 12 | UserSchema.statics.authenticate = function(username, password, callback){ 13 | User.findOne({ username: username}) 14 | .exec(function(err, user){ 15 | if(err){ 16 | return callback(err); 17 | } else if(!user){ 18 | var err = new Error("User not found"); 19 | err.status = 401; 20 | return callback(err); 21 | } 22 | bcrypt.compare(password, user.password, function(err, result){ 23 | if(result === true){ 24 | return callback(null, user); 25 | } else{ 26 | return callback(); 27 | } 28 | }); 29 | }); 30 | } 31 | 32 | UserSchema.pre('save', function(next) { 33 | var user = this; 34 | 35 | bcrypt.hash(user.password, SALT_WORK_FACTOR, function(err, hash) { 36 | if (err) return next(err); 37 | user.password = hash; 38 | next(); 39 | }); 40 | }); 41 | 42 | //module.exports = mongoose.model('users', UserSchema); 43 | var User = mongoose.model('users', UserSchema); 44 | module.exports = User; -------------------------------------------------------------------------------- /Lecture5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "notesapp", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www", 7 | "devstart": "nodemon ./bin/www" 8 | }, 9 | "dependencies": { 10 | "bcrypt": "^5.0.1", 11 | "connect-mongo": "^4.6.0", 12 | "cookie-parser": "~1.4.4", 13 | "cors": "^2.8.5", 14 | "debug": "~2.6.9", 15 | "express": "~4.16.1", 16 | "express-handlebars": "^6.0.3", 17 | "express-session": "^1.17.2", 18 | "hbs": "^4.2.0", 19 | "http-errors": "~1.6.3", 20 | "mongoose": "^5.9.6", 21 | "morgan": "~1.9.1" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Lecture5/public/stylesheets/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding: 50px; 3 | font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; 4 | } 5 | 6 | a { 7 | color: #00B7FF; 8 | } 9 | -------------------------------------------------------------------------------- /Lecture5/routes/NoteCategoryRoutes.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var NoteCategoryController = 4 | require('../controllers/NoteCategoryController.js'); 5 | 6 | /* 7 | * GET 8 | */ 9 | router.get('/', NoteCategoryController.list); 10 | 11 | 12 | module.exports = router; 13 | -------------------------------------------------------------------------------- /Lecture5/routes/NoteItemRoutes.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var NoteItemController = 4 | require('../controllers/NoteItemController.js'); 5 | const UserController = require("../controllers/UserController"); 6 | 7 | /* 8 | * GET 9 | */ 10 | router.get('/', NoteItemController.list); 11 | 12 | router.get('/newtask', NoteItemController.newTask); 13 | 14 | router.get('/open', NoteItemController.openTask); 15 | 16 | router.get('/finished', NoteItemController.finishedTask); 17 | 18 | router.get('/work', NoteItemController.workTask); 19 | 20 | router.get('/shopping', NoteItemController.shopTask); 21 | 22 | /* 23 | * GET 24 | */ 25 | router.get('/:id', NoteItemController.show); 26 | 27 | /* 28 | * POST 29 | */ 30 | router.post('/', NoteItemController.create); 31 | 32 | /* 33 | * PUT 34 | */ 35 | router.put('/:id', NoteItemController.update); 36 | 37 | /* 38 | * DELETE 39 | */ 40 | router.delete('/:id', NoteItemController.remove); 41 | 42 | module.exports = router; 43 | -------------------------------------------------------------------------------- /Lecture5/routes/UserRoutes.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | var UserController = require('../controllers/UserController.js'); 4 | 5 | /* 6 | * GET 7 | */ 8 | router.get('/', UserController.list); 9 | 10 | router.get('/login', UserController.showLogin); 11 | 12 | router.get('/logout', UserController.showLogout); 13 | 14 | router.get('/profile', UserController.showProfile); 15 | 16 | router.get('/register', UserController.showRegistration); 17 | 18 | /* 19 | * GET 20 | */ 21 | 22 | router.get('/:id', UserController.show); 23 | /* 24 | 25 | * POST 26 | */ 27 | router.post('/', UserController.create); 28 | 29 | router.post('/login', UserController.login); 30 | 31 | /* 32 | * PUT 33 | */ 34 | router.put('/:id', UserController.update); 35 | 36 | /* 37 | * DELETE 38 | */ 39 | router.delete('/:id', UserController.remove); 40 | 41 | module.exports = router; 42 | -------------------------------------------------------------------------------- /Lecture5/routes/index.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | var router = express.Router(); 3 | 4 | /* GET home page. */ 5 | router.get('/', function(req, res, next) { 6 | //console.log(req.session.userId); 7 | res.render('index', { userId: req.session.userId, username:req.session.username }); 8 | }); 9 | 10 | module.exports = router; 11 | -------------------------------------------------------------------------------- /Lecture5/views/error.hbs: -------------------------------------------------------------------------------- 1 |

Sorry, errors on page: {{message}}

2 |

{{error.status}}

3 |
{{error.stack}}
4 |
Back to main page: Main page
-------------------------------------------------------------------------------- /Lecture5/views/index.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | Lecture Notes 5 4 | 5 | 6 | 7 | {{> header}} 8 | 9 |

Notes application!

10 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Lecture5/views/layout.hbs: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {{title}} 5 | 6 | 7 | 8 | {{{body}}} 9 | 10 | 11 | -------------------------------------------------------------------------------- /Lecture5/views/noteItems/list.hbs: -------------------------------------------------------------------------------- 1 | {{> header}} 2 | 3 |
4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | {{#each data}} 16 | {{#if id}} 17 | 18 | 21 | 24 | 27 | 30 | 33 | 34 | {{/if}} 35 | {{/each}} 36 | 37 |
Note itemCategoryUserDoneChange
19 | {{name}} 20 | 22 | {{category}} 23 | 25 | {{username}} 26 | 28 | {{done}} 29 | 31 | 32 |
38 |
39 | 40 | {{> footer}} 41 | 42 | -------------------------------------------------------------------------------- /Lecture5/views/noteItems/newNote.hbs: -------------------------------------------------------------------------------- 1 | {{> header}} 2 | 3 |

New task

4 |

{{this.id}}

5 |
6 |
9 |
12 | 18 |
19 | 20 |
21 | 22 | {{> footer}} 23 | -------------------------------------------------------------------------------- /Lecture5/views/partials/footer.hbs: -------------------------------------------------------------------------------- 1 |

Back to main page: Main page

2 | 3 | -------------------------------------------------------------------------------- /Lecture5/views/partials/header.hbs: -------------------------------------------------------------------------------- 1 |
2 | 3 | {{#if userId}} 4 | {{username}}(profile)  5 | Logout  6 | {{else}} 7 | Login  8 | Registration 9 | {{/if}} 10 |
11 |
12 | 13 | -------------------------------------------------------------------------------- /Lecture5/views/user/list.hbs: -------------------------------------------------------------------------------- 1 | {{> header}} 2 | 3 |

Users in Notes application

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | {{#each data}} 13 | {{#if id}} 14 | 15 | 18 | 21 | 22 | {{/if}} 23 | {{/each}} 24 | 25 |
NameUsername
16 | {{name}} 17 | 19 | {{username}} 20 |
26 | 27 | {{> footer}} 28 | 29 | -------------------------------------------------------------------------------- /Lecture5/views/user/login.hbs: -------------------------------------------------------------------------------- 1 |

Login

2 |
3 | 4 | 5 |
6 | 7 |
8 |
9 | 10 | {{> footer}} 11 | -------------------------------------------------------------------------------- /Lecture5/views/user/profile.hbs: -------------------------------------------------------------------------------- 1 | {{> header}} 2 | 3 |

Change profile

4 |

{{id}}

5 |
6 | 7 | 8 | 9 | 10 |
11 | 12 | {{> footer}} 13 | -------------------------------------------------------------------------------- /Lecture5/views/user/register.hbs: -------------------------------------------------------------------------------- 1 |

Registration

2 |
3 | 4 | 5 | 6 | 7 |
8 | 9 | {{> footer}} 10 | -------------------------------------------------------------------------------- /Lecture6/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Lecture6/README.md: -------------------------------------------------------------------------------- 1 | # Lecture 6 2 | Demonstration of React on application Notes. To be able to use it, we need running Restful API in Express (Lecture 5). 3 | 4 | # Tools used 5 | 1. Node.js 6 | 2. Express 7 | 3. React 8 | 4. PHP Storm 9 | -------------------------------------------------------------------------------- /Lecture6/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-notes-react", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^9.5.0", 8 | "@testing-library/user-event": "^7.2.1", 9 | "react": "^16.14.0", 10 | "react-dom": "^16.14.0", 11 | "react-router": "^5.1.2", 12 | "react-router-dom": "^5.1.2", 13 | "react-scripts": "3.4.1" 14 | }, 15 | "scripts": { 16 | "start": "set PORT=4100 && react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": "react-app" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /Lecture6/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomazkosar/CourseWebProgramming/3adad1435d3a712013b7658a9970ba3b7d845880/Lecture6/public/favicon.ico -------------------------------------------------------------------------------- /Lecture6/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 18 | 19 | 28 | React App 29 | 30 | 31 | 32 |
33 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Lecture6/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomazkosar/CourseWebProgramming/3adad1435d3a712013b7658a9970ba3b7d845880/Lecture6/public/logo192.png -------------------------------------------------------------------------------- /Lecture6/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomazkosar/CourseWebProgramming/3adad1435d3a712013b7658a9970ba3b7d845880/Lecture6/public/logo512.png -------------------------------------------------------------------------------- /Lecture6/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Lecture6/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Lecture6/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Lecture6/src/App.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | 3 | import { BrowserRouter as Router, Switch, Route, Link} from "react-router-dom"; 4 | import Items from './components/items'; 5 | import ItemsAlt from './components/items-alt'; 6 | import Home from './components/home'; 7 | import About from './components/about'; 8 | 9 | class App extends Component { 10 | state = { 11 | items: [] 12 | } 13 | 14 | render () { 15 | return ( 16 | 17 |
18 |
    19 |
  • 20 | Home 21 |
  • 22 |
  • 23 | About 24 |
  • 25 |
  • 26 | Items (with class) 27 |
  • 28 |
  • 29 | Items (with function) 30 |
  • 31 |
32 | 33 |
34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 | ); 49 | } 50 | 51 | componentDidMount() { 52 | fetch('http://localhost:3000/items') 53 | .then(res => res.json()) 54 | .then((data) => { 55 | this.setState({ items: data }) 56 | }) 57 | .catch(console.log) 58 | } 59 | 60 | } 61 | 62 | export default App; 63 | -------------------------------------------------------------------------------- /Lecture6/src/App.test.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { render } from '@testing-library/react'; 3 | import App from './App'; 4 | 5 | test('renders learn react link', () => { 6 | const { getByText } = render(); 7 | const linkElement = getByText(/learn react/i); 8 | expect(linkElement).toBeInTheDocument(); 9 | }); 10 | -------------------------------------------------------------------------------- /Lecture6/src/components/about.js: -------------------------------------------------------------------------------- 1 | import React, {} from 'react'; 2 | 3 | class Home extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

About...

8 |
9 | ) 10 | } 11 | } 12 | export default Home; -------------------------------------------------------------------------------- /Lecture6/src/components/home.js: -------------------------------------------------------------------------------- 1 | import React, {} from 'react'; 2 | 3 | class Home extends React.Component { 4 | render() { 5 | return ( 6 |
7 |

Home...

8 |
9 | ) 10 | } 11 | } 12 | export default Home; -------------------------------------------------------------------------------- /Lecture6/src/components/items-alt.js: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | 3 | const ItemsAlt = ({ items }) => { 4 | return ( 5 |
6 |

Note items

7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | {items.map((item) => ( 15 | 16 | 17 | 18 | 19 | 21 | 22 | ))} 23 | 24 |
#Note itemDone
{(item._id).toString()}{item.name}{(item.done) ? "Yes" : "No"}
25 |
26 | ) 27 | }; 28 | 29 | export default ItemsAlt 30 | 31 | -------------------------------------------------------------------------------- /Lecture6/src/components/items.js: -------------------------------------------------------------------------------- 1 | import React, { } from 'react' 2 | 3 | class Items extends React.Component{ 4 | render(){ 5 | return ( 6 |
7 | {/*Displaying items in a table*/} 8 |

Note items

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | {this.props.items.map((item) => ( 17 | 18 | 19 | 20 | 21 | 22 | 24 | 25 | ))} 26 | 27 |
#Note itemCategoryDoneChange
{(item._id).toString()}{item.name}{item.category}{(item.done) ? "Yes" : "No"}
28 |
29 | ) 30 | } 31 | } 32 | 33 | export default Items 34 | 35 | 36 | -------------------------------------------------------------------------------- /Lecture6/src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 4 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 12 | monospace; 13 | } 14 | -------------------------------------------------------------------------------- /Lecture6/src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import * as serviceWorker from './serviceWorker'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want your app to work offline and load faster, you can change 15 | // unregister() to register() below. Note this comes with some pitfalls. 16 | // Learn more about service workers: https://bit.ly/CRA-PWA 17 | serviceWorker.unregister(); 18 | -------------------------------------------------------------------------------- /Lecture6/src/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Lecture6/src/serviceWorker.js: -------------------------------------------------------------------------------- 1 | // This optional code is used to register a service worker. 2 | // register() is not called by default. 3 | 4 | // This lets the app load faster on subsequent visits in production, and gives 5 | // it offline capabilities. However, it also means that developers (and users) 6 | // will only see deployed updates on subsequent visits to a page, after all the 7 | // existing tabs open on the page have been closed, since previously cached 8 | // resources are updated in the background. 9 | 10 | // To learn more about the benefits of this model and instructions on how to 11 | // opt-in, read https://bit.ly/CRA-PWA 12 | 13 | const isLocalhost = Boolean( 14 | window.location.hostname === 'localhost' || 15 | // [::1] is the IPv6 localhost address. 16 | window.location.hostname === '[::1]' || 17 | // 127.0.0.0/8 are considered localhost for IPv4. 18 | window.location.hostname.match( 19 | /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/ 20 | ) 21 | ); 22 | 23 | export function register(config) { 24 | if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) { 25 | // The URL constructor is available in all browsers that support SW. 26 | const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href); 27 | if (publicUrl.origin !== window.location.origin) { 28 | // Our service worker won't work if PUBLIC_URL is on a different origin 29 | // from what our page is served on. This might happen if a CDN is used to 30 | // serve assets; see https://github.com/facebook/create-react-app/issues/2374 31 | return; 32 | } 33 | 34 | window.addEventListener('load', () => { 35 | const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`; 36 | 37 | if (isLocalhost) { 38 | // This is running on localhost. Let's check if a service worker still exists or not. 39 | checkValidServiceWorker(swUrl, config); 40 | 41 | // Add some additional logging to localhost, pointing developers to the 42 | // service worker/PWA documentation. 43 | navigator.serviceWorker.ready.then(() => { 44 | console.log( 45 | 'This web app is being served cache-first by a service ' + 46 | 'worker. To learn more, visit https://bit.ly/CRA-PWA' 47 | ); 48 | }); 49 | } else { 50 | // Is not localhost. Just register service worker 51 | registerValidSW(swUrl, config); 52 | } 53 | }); 54 | } 55 | } 56 | 57 | function registerValidSW(swUrl, config) { 58 | navigator.serviceWorker 59 | .register(swUrl) 60 | .then(registration => { 61 | registration.onupdatefound = () => { 62 | const installingWorker = registration.installing; 63 | if (installingWorker == null) { 64 | return; 65 | } 66 | installingWorker.onstatechange = () => { 67 | if (installingWorker.state === 'installed') { 68 | if (navigator.serviceWorker.controller) { 69 | // At this point, the updated precached content has been fetched, 70 | // but the previous service worker will still serve the older 71 | // content until all client tabs are closed. 72 | console.log( 73 | 'New content is available and will be used when all ' + 74 | 'tabs for this page are closed. See https://bit.ly/CRA-PWA.' 75 | ); 76 | 77 | // Execute callback 78 | if (config && config.onUpdate) { 79 | config.onUpdate(registration); 80 | } 81 | } else { 82 | // At this point, everything has been precached. 83 | // It's the perfect time to display a 84 | // "Content is cached for offline use." message. 85 | console.log('Content is cached for offline use.'); 86 | 87 | // Execute callback 88 | if (config && config.onSuccess) { 89 | config.onSuccess(registration); 90 | } 91 | } 92 | } 93 | }; 94 | }; 95 | }) 96 | .catch(error => { 97 | console.error('Error during service worker registration:', error); 98 | }); 99 | } 100 | 101 | function checkValidServiceWorker(swUrl, config) { 102 | // Check if the service worker can be found. If it can't reload the page. 103 | fetch(swUrl, { 104 | headers: { 'Service-Worker': 'script' }, 105 | }) 106 | .then(response => { 107 | // Ensure service worker exists, and that we really are getting a JS file. 108 | const contentType = response.headers.get('content-type'); 109 | if ( 110 | response.status === 404 || 111 | (contentType != null && contentType.indexOf('javascript') === -1) 112 | ) { 113 | // No service worker found. Probably a different app. Reload the page. 114 | navigator.serviceWorker.ready.then(registration => { 115 | registration.unregister().then(() => { 116 | window.location.reload(); 117 | }); 118 | }); 119 | } else { 120 | // Service worker found. Proceed as normal. 121 | registerValidSW(swUrl, config); 122 | } 123 | }) 124 | .catch(() => { 125 | console.log( 126 | 'No internet connection found. App is running in offline mode.' 127 | ); 128 | }); 129 | } 130 | 131 | export function unregister() { 132 | if ('serviceWorker' in navigator) { 133 | navigator.serviceWorker.ready 134 | .then(registration => { 135 | registration.unregister(); 136 | }) 137 | .catch(error => { 138 | console.error(error.message); 139 | }); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /Lecture6/src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom/extend-expect'; 6 | -------------------------------------------------------------------------------- /Lecture9/ReactRedux/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Lecture9/ReactRedux/README.md: -------------------------------------------------------------------------------- 1 | # Lecture 9 2 | Demonstration of React on application Notes. To be able to use it, we need running Restful API in Express (Lecture 5). 3 | 4 | # Tools used 5 | 1. Node.js 6 | 2. Express 7 | 3. React 8 | 4. PHP Storm 9 | -------------------------------------------------------------------------------- /Lecture9/ReactRedux/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-notes-react", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@emotion/react": "^11.9.0", 7 | "@emotion/styled": "^11.8.1", 8 | "@mui/icons-material": "^5.6.2", 9 | "@mui/material": "^5.6.2", 10 | "@reduxjs/toolkit": "^1.8.1", 11 | "@testing-library/jest-dom": "^4.2.4", 12 | "@testing-library/react": "^9.5.0", 13 | "@testing-library/user-event": "^7.2.1", 14 | "axios": "^0.26.1", 15 | "react": "^18.0.0", 16 | "react-dom": "^18.0.0", 17 | "react-redux": "^8.0.0", 18 | "react-router": "^6.3.0", 19 | "react-router-dom": "^6.3.0", 20 | "react-scripts": "^5.0.1" 21 | }, 22 | "scripts": { 23 | "start": "set PORT=4100 && react-scripts start", 24 | "build": "react-scripts build", 25 | "test": "react-scripts test", 26 | "eject": "react-scripts eject" 27 | }, 28 | "eslintConfig": { 29 | "extends": "react-app" 30 | }, 31 | "browserslist": { 32 | "production": [ 33 | ">0.2%", 34 | "not dead", 35 | "not op_mini all" 36 | ], 37 | "development": [ 38 | "last 1 chrome version", 39 | "last 1 firefox version", 40 | "last 1 safari version" 41 | ] 42 | }, 43 | "devDependencies": { 44 | "nodemon": "^2.0.15" 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Lecture9/ReactRedux/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomazkosar/CourseWebProgramming/3adad1435d3a712013b7658a9970ba3b7d845880/Lecture9/ReactRedux/public/favicon.ico -------------------------------------------------------------------------------- /Lecture9/ReactRedux/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 13 | 14 | 18 | 19 | 28 | React App 29 | 30 | 31 | 32 |
33 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /Lecture9/ReactRedux/public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomazkosar/CourseWebProgramming/3adad1435d3a712013b7658a9970ba3b7d845880/Lecture9/ReactRedux/public/logo192.png -------------------------------------------------------------------------------- /Lecture9/ReactRedux/public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tomazkosar/CourseWebProgramming/3adad1435d3a712013b7658a9970ba3b7d845880/Lecture9/ReactRedux/public/logo512.png -------------------------------------------------------------------------------- /Lecture9/ReactRedux/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /Lecture9/ReactRedux/public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /Lecture9/ReactRedux/src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | text-align: center; 3 | } 4 | 5 | .App-logo { 6 | height: 40vmin; 7 | pointer-events: none; 8 | } 9 | 10 | @media (prefers-reduced-motion: no-preference) { 11 | .App-logo { 12 | animation: App-logo-spin infinite 20s linear; 13 | } 14 | } 15 | 16 | .App-header { 17 | background-color: #282c34; 18 | min-height: 100vh; 19 | display: flex; 20 | flex-direction: column; 21 | align-items: center; 22 | justify-content: center; 23 | font-size: calc(10px + 2vmin); 24 | color: white; 25 | } 26 | 27 | .App-link { 28 | color: #61dafb; 29 | } 30 | 31 | @keyframes App-logo-spin { 32 | from { 33 | transform: rotate(0deg); 34 | } 35 | to { 36 | transform: rotate(360deg); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /Lecture9/ReactRedux/src/App.js: -------------------------------------------------------------------------------- 1 | import React, {Component} from 'react'; 2 | import {useEffect} from 'react' 3 | import {BrowserRouter, Routes, Route, Navigate} from "react-router-dom"; 4 | import axios from 'axios'; 5 | import Box from "@mui/material/Box"; 6 | import {useSelector, useDispatch} from "react-redux"; 7 | 8 | import Home from './components/home'; 9 | import About from './components/about'; 10 | import Header from './components/header'; 11 | import Profile from './components/profile'; 12 | import Footer from './components/footer'; 13 | import Login from './components/login'; 14 | import Register from './components/register'; 15 | import ItemsAll from './components/items-all'; 16 | import ItemsDone from "./components/items-done"; 17 | import ItemsTodo from "./components/items-todo"; 18 | import ItemsAdd from "./components/item-add"; 19 | import {getItems} from "./redux/slices/itemsSlice"; 20 | 21 | function RequireAuth({children, redirectTo}) { 22 | const isAuthenticated = useSelector((state) => state.auth.value) 23 | return isAuthenticated ? children : ; 24 | } 25 | 26 | const App = () => { 27 | //class App extends Component { 28 | const items = useSelector((state) => state.items.value); 29 | const dispatch = useDispatch(); 30 | 31 | /* state = { 32 | items: [] 33 | } 34 | */ 35 | 36 | useEffect(() => { 37 | // componentDidMount() { 38 | axios.get(`http://localhost:3000/items`, {withCredentials: true}) 39 | .then(res => { 40 | //this.setState({items: res.data}); 41 | dispatch(getItems(res.data)); 42 | }) 43 | .catch(console.log) 44 | }, [getItems]); 45 | 46 | 47 | // render() { 48 | return ( 49 | 50 | 51 | 52 |
53 | 54 | 55 | 56 | }/> 57 | }/> 58 | }/> 59 | }/> 60 | }/> 61 | 63 | 64 | 65 | }/> 66 | 68 | 69 | 70 | }/> 71 | 73 | 74 | 75 | }/> 76 | 78 | 79 | 80 | }/> 81 | }/> 82 | 83 |