From 9f0c730ba5fee5b9993d31ac5b19a6b660a6da30 Mon Sep 17 00:00:00 2001 From: 1eque Date: Sun, 19 Jun 2022 23:45:09 +0530 Subject: [PATCH] final --- index.html | 12 ++- package-lock.json | 181 ++++++++++++++++++++++++++++++++- src/auth_required.js | 3 + src/init.js | 157 +++++++++++++++++++++++++++++ src/main.js | 214 +++++++++++++++++++++++++++++++++++++++- src/no_auth_required.js | 5 +- 6 files changed, 563 insertions(+), 9 deletions(-) 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