diff --git a/index.html b/index.html
index ffda4cf..b225487 100644
--- a/index.html
+++ b/index.html
@@ -59,13 +59,21 @@
+
+
+
diff --git a/package-lock.json b/package-lock.json
index 3a9cab7..9508f6d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,8 +1,187 @@
{
"name": "csoc-task-2-web",
"version": "1.0.0",
- "lockfileVersion": 1,
+ "lockfileVersion": 2,
"requires": true,
+ "packages": {
+ "": {
+ "name": "csoc-task-2-web",
+ "version": "1.0.0",
+ "license": "ISC",
+ "dependencies": {
+ "axios": "^0.21.2",
+ "vite": "^2.3.7"
+ }
+ },
+ "node_modules/axios": {
+ "version": "0.21.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.2.tgz",
+ "integrity": "sha512-87otirqUw3e8CzHTMO+/9kh/FSgXt/eVDvipijwDtEuwbkySWZ9SBm6VEubmJ/kLKEoLQV/POhxXFb66bfekfg==",
+ "dependencies": {
+ "follow-redirects": "^1.14.0"
+ }
+ },
+ "node_modules/colorette": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
+ "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w=="
+ },
+ "node_modules/esbuild": {
+ "version": "0.12.8",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.12.8.tgz",
+ "integrity": "sha512-sx/LwlP/SWTGsd9G4RlOPrXnIihAJ2xwBUmzoqe2nWwbXORMQWtAGNJNYLBJJqa3e9PWvVzxdrtyFZJcr7D87g==",
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ }
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.1",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz",
+ "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
+ },
+ "node_modules/has": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+ "dependencies": {
+ "function-bind": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz",
+ "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==",
+ "dependencies": {
+ "has": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.1.23",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.23.tgz",
+ "integrity": "sha512-FiB0kzdP0FFVGDKlRLEQ1BgDzU87dy5NnzjeW9YZNt+/c3+q82EQDUwniSAUxp/F0gFNI1ZhKU1FqYsMuqZVnw==",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "node_modules/postcss": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.4.tgz",
+ "integrity": "sha512-/tZY0PXExXXnNhKv3TOvZAOUYRyuqcCbBm2c17YMDK0PlVII3K7/LKdt3ScHL+hhouddjUWi+1sKDf9xXW+8YA==",
+ "dependencies": {
+ "colorette": "^1.2.2",
+ "nanoid": "^3.1.23",
+ "source-map-js": "^0.6.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.20.0",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+ "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+ "dependencies": {
+ "is-core-module": "^2.2.0",
+ "path-parse": "^1.0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/rollup": {
+ "version": "2.51.2",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.51.2.tgz",
+ "integrity": "sha512-ReV2eGEadA7hmXSzjxdDKs10neqH2QURf2RxJ6ayAlq93ugy6qIvXMmbc5cWMGCDh1h5T4thuWO1e2VNbMq8FA==",
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.1"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-0.6.2.tgz",
+ "integrity": "sha512-/3GptzWzu0+0MBQFrDKzw/DvvMTUORvgY6k6jd/VS6iCR4RDTKWH6v6WPwQoUO8667uQEf9Oe38DxAYWY5F/Ug==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/vite": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-2.3.7.tgz",
+ "integrity": "sha512-Y0xRz11MPYu/EAvzN94+FsOZHbSvO6FUvHv127CyG7mV6oDoay2bw+g5y9wW3Blf8OY3chaz3nc/DcRe1IQ3Nw==",
+ "dependencies": {
+ "esbuild": "^0.12.5",
+ "postcss": "^8.3.0",
+ "resolve": "^1.19.0",
+ "rollup": "^2.38.5"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.1"
+ }
+ }
+ },
"dependencies": {
"axios": {
"version": "0.21.2",
diff --git a/src/auth_required.js b/src/auth_required.js
index 7f5e7bc..1a5fa6e 100644
--- a/src/auth_required.js
+++ b/src/auth_required.js
@@ -1,3 +1,6 @@
/***
* @todo Redirect the user to login page if token is not present.
*/
+ if (localStorage.token === null ) {
+ window.location.href = 'login/';
+}
\ No newline at end of file
diff --git a/src/init.js b/src/init.js
index 3a88d74..e9abb8f 100644
--- a/src/init.js
+++ b/src/init.js
@@ -5,6 +5,81 @@ function getTasks() {
/***
* @todo Fetch the tasks created by the user and display them in the dom.
*/
+ console.log('getTasks');
+ //get token from local storage for authentication
+ const token = localStorage.getItem('token');
+ axios({
+ url: API_BASE_URL + 'todo/',
+ method: 'get',
+ headers: {
+ 'Authorization': 'Token ' + token
+ },
+ }).then(function ({ data, status }) {
+ console.log(data);
+ const list_group = document.querySelector('.list-group');
+ list_group.textContent = '';
+ data.forEach(d => {
+ const tasks_container = document.createElement('li');
+ tasks_container.classList.add('list-group-item');
+ tasks_container.classList.add('d-flex');
+ tasks_container.classList.add('justify-content-between');
+ tasks_container.classList.add('align-items-center');
+ tasks_container.id = d.id;
+ // add a input field to edit the task
+ const input_field = document.createElement('input');
+ input_field.classList.add('form-control');
+ input_field.classList.add('todo-edit-task-input');
+ input_field.classList.add('hideme');
+ input_field.id = 'input-button-' + d.id;
+ input_field.placeholder = 'Edit The Task';
+ input_field.type = 'text';
+ // create a div to store button
+ const button_container = document.createElement('div');
+ button_container.classList.add('input-group-append');
+ button_container.classList.add('hideme');
+ button_container.id = 'done-button-' + d.id;
+ // create a div and done button inside it to save edited task
+ const done_button = document.createElement('button');
+ done_button.classList.add('btn');
+ done_button.classList.add('btn-success');
+ done_button.classList.add('todo-update-task');
+ done_button.type = 'button';
+ done_button.setAttribute('onclick', 'updateTask(' + d.id + ')');
+ done_button.innerHTML = 'Done';
+ button_container.append(done_button);
+ const task_name = document.createElement('div');
+ task_name.classList.add('todo-task');
+ task_name.innerHTML = d.title;
+ task_name.id = 'task-' + d.id;
+ const span = document.createElement('span');
+ const btn_1 = document.createElement('button');
+ btn_1.classList.add('btn');
+ btn_1.classList.add('btn-outline-warning');
+ btn_1.style.marginRight = '10px';
+ btn_1.addEventListener('click', () => {
+ editTask(d.id);
+ }
+ );
+ const btn_2 = document.createElement('button');
+ btn_2.classList.add('btn');
+ btn_2.classList.add('btn-outline-danger');
+ btn_2.addEventListener('click', () => { deleteTask(d.id) });
+ span.append(btn_1, btn_2);
+ span.id = 'task-actions-' + d.id;
+ tasks_container.append(input_field, button_container, task_name, span);
+ list_group.append(tasks_container);
+ const img_1 = document.createElement('img');
+ img_1.src = 'https://res.cloudinary.com/nishantwrp/image/upload/v1587486663/CSOC/edit.png';
+ img_1.width = '18';
+ img_1.height = '20';
+ btn_1.appendChild(img_1);
+ const img_2 = document.createElement('img');
+ img_2.src = 'https://res.cloudinary.com/nishantwrp/image/upload/v1587486661/CSOC/delete.svg';
+ img_2.width = '18';
+ img_2.height = '22';
+ btn_2.appendChild(img_2);
+ });
+ });
}
axios({
@@ -18,3 +93,85 @@ axios({
document.getElementById('profile-name').innerHTML = data.name;
getTasks();
})
+
+
+function getSearchedTasks(data) {
+ console.log(data);
+ const list_group = document.querySelector('.list-group');
+ list_group.textContent = '';
+ data.forEach(d => {
+ const tasks_container = document.createElement('li');
+ tasks_container.classList.add('list-group-item');
+ tasks_container.classList.add('d-flex');
+ tasks_container.classList.add('justify-content-between');
+ tasks_container.classList.add('align-items-center');
+ tasks_container.id = d.id;
+ const input_field = document.createElement('input');
+ input_field.classList.add('form-control');
+ input_field.classList.add('todo-edit-task-input');
+ input_field.classList.add('hideme');
+ input_field.id = 'input-button-' + d.id;
+ input_field.placeholder = 'Edit The Task';
+ input_field.type = 'text';
+ const button_container = document.createElement('div');
+ button_container.classList.add('input-group-append');
+ button_container.classList.add('hideme');
+ button_container.id = 'done-button-' + d.id;
+ const done_button = document.createElement('button');
+ done_button.classList.add('btn');
+ done_button.classList.add('btn-outline-secondary');
+ done_button.classList.add('todo-update-task');
+ done_button.type = 'button';
+ done_button.setAttribute('onclick', 'updateTask(' + d.id + ')');
+ done_button.innerHTML = 'Done';
+ button_container.append(done_button);
+ const task_name = document.createElement('div');
+ task_name.classList.add('todo-task');
+ task_name.innerHTML = d.title;
+ task_name.id = 'task-' + d.id;
+ const span = document.createElement('span');
+ const btn_1 = document.createElement('button');
+ btn_1.classList.add('btn');
+ btn_1.classList.add('btn-outline-warning');
+ btn_1.style.marginRight = '10px';
+ btn_1.addEventListener('click', () => {
+ editTask(d.id);
+ }
+ );
+ const btn_2 = document.createElement('button');
+ btn_2.classList.add('btn');
+ btn_2.classList.add('btn-outline-danger');
+ btn_2.addEventListener('click', () => { deleteTask(d.id) });
+ span.append(btn_1, btn_2);
+ span.id = 'task-actions-' + d.id;
+ tasks_container.append(input_field, button_container, task_name, span);
+ list_group.append(tasks_container);
+ const img_1 = document.createElement('img');
+ img_1.src = 'https://res.cloudinary.com/nishantwrp/image/upload/v1587486663/CSOC/edit.png';
+ img_1.width = '18';
+ img_1.height = '20';
+ btn_1.appendChild(img_1);
+ const img_2 = document.createElement('img');
+ img_2.src = 'https://res.cloudinary.com/nishantwrp/image/upload/v1587486661/CSOC/delete.svg';
+ img_2.width = '18';
+ img_2.height = '22';
+ btn_2.appendChild(img_2);
+ });
+}
+
+
+
+axios({
+ headers: {
+ Authorization: 'Token ' + localStorage.getItem('token'),
+ },
+ url: API_BASE_URL + 'auth/profile/',
+ method: 'get',
+}).then(function ({ data }) {
+ document.getElementById('avatar-image').src = 'https://ui-avatars.com/api/?name=' + data.name + '&background=fff&size=33&color=007bff';
+ document.getElementById('profile-name').innerHTML = data.name;
+ getTasks();
+})
+//export getTasks() for use in main.js
+export { getTasks };
+export { getSearchedTasks};
diff --git a/src/main.js b/src/main.js
index 05849df..75eea5d 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,4 +1,17 @@
import axios from 'axios';
+//import getTasks from init.js using import
+import {getTasks} from './init';
+import {getSearchedTasks} from './init';
+
+window.register = register;
+window.login = login;
+window.addTask = addTask;
+window.logout=logout;
+window.deleteTask=deleteTask;
+window.editTask=editTask;
+window.updateTask=updateTask;
+window.searchTask=searchTask;
+
function displaySuccessToast(message) {
iziToast.success({
title: 'Success',
@@ -60,36 +73,124 @@ function register() {
url: API_BASE_URL + 'auth/register/',
method: 'post',
data: dataForApiRequest,
- }).then(function({data, status}) {
- localStorage.setItem('token', data.token);
- window.location.href = '/';
- }).catch(function(err) {
- displayErrorToast('An account using same email or username is already created');
+ }).then(function ({ data, status }) {
+ localStorage.setItem('token', data.token);
+ window.location.href = '/';
+ }).catch(function (err) {
+ displayErrorToast('An account using same email or username is already created');
})
}
}
+
function login() {
/***
* @todo Complete this function.
* @todo 1. Write code for form validation.
* @todo 2. Fetch the auth token from backend, login and direct user to home page.
*/
+ // const username = username;
+ // const password = password;
+
+ const username = document.getElementById('inputUsername').value.trim();
+ const password = document.getElementById('inputPassword').value;
+
+ const dataForApiRequest = {
+ username: username,
+ password: password
+ }
+ axios({
+ url: API_BASE_URL + 'auth/login/',
+ method: 'post',
+ data: dataForApiRequest,
+ }).then(function ({ data, status }) {
+ localStorage.setItem('token', data.token);
+ window.location.href = '/';
+ }).catch(function (err) {
+ displayErrorToast('Account does not exist, please register first');
+ })
}
+
function addTask() {
/**
* @todo Complete this function.
* @todo 1. Send the request to add the task to the backend server.
* @todo 2. Add the task in the dom.
*/
+
+ const todoInput = document.querySelector("input");
+ const todoCollection = document.querySelector(".todo-available-tasks");
+
+
+ const dataForApiRequest = {
+ title: todoInput.value,
+ }
+ //check whether the task is empty or not
+ if (todoInput.value === '') {
+ displayErrorToast("Please enter a task");
+ }
+ else {
+
+
+
+ //get token from local storage for authentication
+ const token = localStorage.getItem('token');
+ axios({
+ url: API_BASE_URL + 'todo/create/',
+ method: 'post',
+ headers: {
+ 'Authorization': 'Token ' + token
+ },
+ data: dataForApiRequest,
+ }).then(function ({ data, status }) {
+ console.log(data);
+ getTasks()
+ todoInput.value = '';
+ }).catch(function (err) {
+ displayErrorToast('An error occured while adding the task');
+
+ }
+ )
+
+ }
+
}
+// if (todoInput.value === "") {
+// alert("enter something!");
+// } else {
+// const li = document.createElement("li");
+// const todoTitle = document.createElement("span");
+// li.classList.add("todo-available-tasks-text");
+// todoTitle.classList.add("list-items");
+// todoTitle.innerText = todoInput.value;
+
+// li.appendChild(todoTitle);
+// todoCollection.appendChild(li);
+
+// }
+
+
+// axios({
+// url: API_BASE_URL + 'todo/create/',
+// method: 'post',
+// data: dataForApiRequest,
+// }).then(function ({ data, status }) {
+// localStorage.setItem('token', data.token);
+// window.location.href = '/';
+// }).catch(function (err) {
+// displayErrorToast('please login');
+// })
+
function editTask(id) {
document.getElementById('task-' + id).classList.add('hideme');
document.getElementById('task-actions-' + id).classList.add('hideme');
document.getElementById('input-button-' + id).classList.remove('hideme');
document.getElementById('done-button-' + id).classList.remove('hideme');
+
+
+
}
function deleteTask(id) {
@@ -98,6 +199,35 @@ function deleteTask(id) {
* @todo 1. Send the request to delete the task to the backend server.
* @todo 2. Remove the task from the dom.
*/
+
+
+ const token = localStorage.getItem('token');
+ axios({
+ url: API_BASE_URL + 'todo/' + id + '/',
+ method: 'delete',
+ headers: {
+ 'Authorization': 'Token ' + token
+ },
+ }).then(function ({ data, status }) {
+ // getTasks()
+ //success toast
+ displaySuccessToast('Task deleted successfully');
+ //select the task from the dom
+ const task = document.getElementById(id);
+ //remove the task from the dom
+ task.remove();
+
+ }).catch(function (err) {
+ displayErrorToast('An error occured while deleting the task');
+
+ }
+ )
+ //delete the task from the dom
+ document.getElementById('task-' + id).classList.add('hideme');
+ document.getElementById('task-actions-' + id).classList.add('hideme');
+ document.getElementById('input-button-' + id).classList.remove('hideme');
+ document.getElementById('done-button-' + id).classList.remove('hideme');
+
}
function updateTask(id) {
@@ -106,4 +236,78 @@ function updateTask(id) {
* @todo 1. Send the request to update the task to the backend server.
* @todo 2. Update the task in the dom.
*/
+ //update the edited task and save to dom
+ console.log(id);
+ const todoInput = document.getElementById("input-button-" + id);
+ console.log(todoInput);
+ const todoCollection = document.querySelector(".todo-available-tasks");
+ const token = localStorage.getItem('token');
+ const dataForApiRequest = {
+ title: todoInput.value,
+ }
+ console.log(todoInput.value)
+ axios({
+ url: API_BASE_URL + 'todo/' + id + '/',
+ method: 'put',
+ headers: {
+ 'Authorization': 'Token ' + token
+ },
+ data: dataForApiRequest,
+ }).then(function ({ data, status }) {
+ getTasks()
+ //success toast
+ displaySuccessToast('Task updated successfully');
+
+ }).catch(function (err) {
+ displayErrorToast('An error occured while updating the task');
+ }
+ )
+//save the edited task to dom
+ document.getElementById('task-' + id).classList.remove('hideme');
+ document.getElementById('task-actions-' + id).classList.remove('hideme');
+ document.getElementById('input-button-' + id).classList.add('hideme');
+ document.getElementById('done-button-' + id).classList.add('hideme');
+
+ //show the updated tasks in the dom
+ // const li = document.createElement("li");
+ // const todoTitle = document.createElement("span");
+ // li.classList.add("todo-available-tasks-text");
+ // todoTitle.classList.add("list-items");
+ // todoTitle.innerText = todoInput.value;
+
+
+
+
+
}
+//call a function on click of search button
+function searchTask() {
+ displayInfoToast("Searching Task...");
+
+
+ const token = localStorage.getItem('token');
+ axios({
+ url: API_BASE_URL + 'todo/',
+ method: 'get',
+ headers: {
+ 'Authorization': 'Token ' + token
+ },
+ }).then(function ({ data, status }) {
+ console.log(data);
+ //filter the tasks based on the search input
+ const searchInput = document.getElementById('search-input').value;
+ const filteredTasks = data.filter(function (task) {
+ return task.title.toLowerCase().includes(searchInput.toLowerCase());
+ }
+ );
+ console.log(filteredTasks);
+ getSearchedTasks(filteredTasks);
+ displaySuccessToast('Tasks searched successfully');
+
+ }).catch(function (err) {
+ displayErrorToast('An error occured while getting the tasks');
+ })
+}
+
+
+
\ No newline at end of file
diff --git a/src/no_auth_required.js b/src/no_auth_required.js
index 82558d4..24e828f 100644
--- a/src/no_auth_required.js
+++ b/src/no_auth_required.js
@@ -1,3 +1,6 @@
/***
* @todo Redirect the user to main page if token is present.
- */
\ No newline at end of file
+ */
+ if (localStorage.token) {
+ window.location.href = '/';
+}
\ No newline at end of file