From 464de07064d25f191a29c8d670040c81b70d84bb Mon Sep 17 00:00:00 2001 From: Azdim Zul Fahmi Date: Sun, 12 Dec 2021 15:20:17 +0700 Subject: [PATCH] feat(request-list): Support CRUD for request list by using this request list, user doesn't need to memorise the endpoint & the request anymore, they can store the request and come again if they need it. at the moment the data is store in IndexDB (browser), hence it doesn't need backend effort. --- index/css/style.css | 49 ++++++++++++ index/index.html | 56 +++++++++++++- index/js/db.js | 143 ++++++++++++++++++++++++++++++++++ index/js/request.list.js | 162 +++++++++++++++++++++++++++++++++++++++ index/js/style.js | 5 ++ 5 files changed, 412 insertions(+), 3 deletions(-) create mode 100644 index/js/db.js create mode 100644 index/js/request.list.js diff --git a/index/css/style.css b/index/css/style.css index ae61674..4e4b66e 100644 --- a/index/css/style.css +++ b/index/css/style.css @@ -200,4 +200,53 @@ circle { transform: scaleY(1.0); -webkit-transform: scaleY(1.0); } +} + +.save-button-dropdown { + padding-left: 10px; + padding-right: 15px; +} + +.save-button-dropdown .dropdown-menu.show { + transform: translate3d(639px, 46px, 0px); +} + +.one-long-line { + margin-bottom: 0; + margin-left: 5px; + max-width: 100%; + white-space:nowrap; + overflow:hidden; + text-overflow:ellipsis; +} +.one-long-line:hover { + cursor: pointer; + overflow:visible; +} + +.column-row-left { + display: flex; + flex-direction: column; + margin-top: 8px; +} + +.column-row-left .md-form{ + margin-bottom: 0; +} + +.search { + width: 100%; +} + +.request-list { + display: flex; + padding: 5px; +} + +.request-list .fa { + color: red; +} + +.request-list.selected { + background: #dadfe3;; } \ No newline at end of file diff --git a/index/index.html b/index/index.html index 9896a5c..bd6ae44 100644 --- a/index/index.html +++ b/index/index.html @@ -14,14 +14,37 @@ -
-
-
+
+
+
+
+
+
+
+ + +
+
    +
    +
    +
    +
    + +
    +
    @@ -174,15 +197,42 @@
    + + + + + diff --git a/index/js/db.js b/index/js/db.js new file mode 100644 index 0000000..119df2c --- /dev/null +++ b/index/js/db.js @@ -0,0 +1,143 @@ +const objectStoreRequests = "requests"; +let dbConn = null; + +function gdb(){ + if (!window.indexedDB) { + alert(`Your browser doesn't support IndexedDB`) + return; + } + return new Promise(function (success, error){ + if (dbConn !== null){ + success(dbConn) + return + } + + const request = indexedDB.open('grpcox',1); + request.onerror = (event) => { + error(request.error) + }; + + request.onsuccess = (event) => { + // add implementation here + console.log("success open DB") + dbConn = event.target.result; + success(dbConn); + }; + // create the Contacts object store and indexes + request.onupgradeneeded = (event) => { + let dbConn = event.target.result; + let store = dbConn.createObjectStore(objectStoreRequests,{ + keyPath:"name" + }); + }; + }) +} + + +function getRequest(name) { + return new Promise(async function (success, error){ + let db = await gdb() + const txn = db.transaction(objectStoreRequests, 'readwrite'); + const store = txn.objectStore(objectStoreRequests); + let idbRequest = store.get(name); + idbRequest.onerror = function (param) { + error(idbRequest.error.name) + } + idbRequest.onsuccess = function (event) { + success(event.target.result) + } + }) +} + +function getAllRequestKey() { + return new Promise(async function (success, error){ + let db = await gdb(); + const txn = db.transaction(objectStoreRequests, 'readwrite'); + // get the Contacts object store + const store = txn.objectStore(objectStoreRequests); + let idbRequest = store.getAllKeys(); + idbRequest.onerror = function (param) { + error(param.target) + } + idbRequest.onsuccess = function (event) { + success(event.target.result) + } + }) +} + +function insertRequest(request) { + return new Promise(async function(success, error){ + let db = await gdb() + + // create a new transaction + const txn = db.transaction(objectStoreRequests, 'readwrite'); + + const store = txn.objectStore(objectStoreRequests); + + let query = store.add(request); + + // handle success case + query.onsuccess = function (event) { + success('success') + }; + + // handle the error case + query.onerror = function (event) { + if (query.error.name === "ConstraintError") { + error('Duplicate request name') + return + } + error(query.error.name) + } + }) +} + +function updateRequest(request) { + return new Promise(async function(success, error){ + let db = await gdb() + + // create a new transaction + const txn = db.transaction(objectStoreRequests, 'readwrite'); + + const store = txn.objectStore(objectStoreRequests); + + let query = store.put(request); + + // handle success case + query.onsuccess = function (event) { + success('success') + }; + + // handle the error case + query.onerror = function (event) { + if (query.error.name === "ConstraintError") { + error('Duplicate request name') + return + } + error(query.error.name) + } + }) +} + +function deleteRequest(name){ + return new Promise(async function (success, error){ + let db = await gdb() + + // create a new transaction + const txn = db.transaction(objectStoreRequests, 'readwrite'); + + const store = txn.objectStore(objectStoreRequests); + + let query = store.delete(name); + + // handle success case + query.onsuccess = function (event) { + success('success') + }; + + // handle the error case + query.onerror = function (event) { + error(query.error.name) + } + }) +} \ No newline at end of file diff --git a/index/js/request.list.js b/index/js/request.list.js new file mode 100644 index 0000000..f4a88c8 --- /dev/null +++ b/index/js/request.list.js @@ -0,0 +1,162 @@ +$('#save-request').click(function(){ + let requestName = document.getElementById("input-request-name").value; + if (requestName === "") { + alert("request name is require") + } else { + let data = getReqResData(); + data.name = requestName + insertRequest(data).then(success => { + window.location.reload() + }).catch(error => { + alert(error); + }) + } +}); + +$('#show-modal-save-request').click(function () { + const reqData = getReqResData(); + const activeRequestName = getActiveRequestListName(); + if ( activeRequestName === ""){ + console.log(activeRequestName); + // generate name + // name format will be method + $('#input-request-name').val(`${reqData.selected_function}`) + $('#saveRequest').modal('toggle'); + } else { + reqData.name = activeRequestName + updateRequest(reqData).catch(error => { + alert(error); + }) + } +}); +$('#show-modal-save-as-request').click(function () { + const reqData = getReqResData(); + // generate name + // name format will be method + $('#input-request-name').val(`copy ${reqData.selected_function}`) + $('#saveRequest').modal('toggle'); +}); + +function getReqResData() { + const serverTarget = document.getElementById("server-target").value; + const selectService = document.getElementById("select-service").value; + const selectFunction = document.getElementById("select-function").value; + const responseHTML = document.getElementById("json-response").innerHTML; + const schemaProtoHTML = document.getElementById("schema-proto").innerHTML; + editor = ace.edit("editor"); + return { + server_target:serverTarget, + selected_service:selectService, + selected_function:selectFunction, + raw_request:editor.getValue(), + response_html:responseHTML, + schema_proto_html:schemaProtoHTML, + } +} + +function setReqResData(data) { + $('#server-target').val(data.server_target); + target = data.server_target; + $("#select-service").html(new Option(data.selected_service, data.selected_service,true,true)); + $('#choose-service').show(); + $("#select-function").html(new Option(data.selected_function.substr(data.selected_service.length), data.selected_function,true,true)); + $('#choose-function').show(); + generate_editor(data.raw_request); + $('#body-request').show(); + $('#schema-proto').html(data.schema_proto_html); + $('#json-response').html(data.response_html); + $('#response').show(); +} + +function resetReqResData() { + target=""; + $('#choose-service').hide(); + $('#choose-function').hide(); + $('#body-request').hide(); + $('#response').hide(); +} + +async function renderRequestList() { + const ul = document.getElementById("request-list") + ul.innerHTML = "" + + const nameList = await getAllRequestKey(); + + nameList.forEach(function (item){ + let node = document.createElement("li") + node.classList.add("list-group-item","request-list") + node.setAttribute("request-name",item) + node.addEventListener("click", function(el){ + updateRequestView(el.target.children[1]) + }); + node.innerHTML = ` + +

    ${item}

    + ` + ul.appendChild(node); + }) +} + +function removeRequestSelectedClass(){ + const elems = document.querySelectorAll(".request-list"); + [].forEach.call(elems, function(el) { + el.classList.remove("selected"); + }); +} + +function getActiveRequestListName(){ + const elems = document.querySelectorAll(".request-list"); + for (let i = 0; i < elems.length; i++) { + const e = elems[i] + if (e.classList.contains("selected")) { + return e.innerText; + } + } + return "" +} + +function setServerTargetActive() { + const elems = document.querySelectorAll('[for="server-target"]'); + [].forEach.call(elems, function(el) { + el.classList.add("active"); + }); +} + +function updateRequestView(elm) { + if (elm) { + getRequest(elm.innerText).then(data => { + resetReqResData() + setReqResData(data) + removeRequestSelectedClass() + elm.parentElement.classList.add('selected') + setServerTargetActive(); + }).catch(error => { + alert(error) + }) + } +} + +function removeRequest(elm) { + const requestName = elm.parentElement.lastElementChild.innerText; + deleteRequest(requestName).then(()=>{ + window.location.reload() + }).catch((error)=>{ + alert(error) + }) +} + +function search(elm) { + const li = document.querySelectorAll(".request-list") + li.forEach(function (el) { + if (el.getAttribute("request-name").toLowerCase().includes(elm.value.toLowerCase())){ + el.style.display = "" + }else{ + el.style.display = "none" + } + + }) +} + +$(document).ready(function(){ + renderRequestList() +}); \ No newline at end of file diff --git a/index/js/style.js b/index/js/style.js index f214850..6d9079f 100644 --- a/index/js/style.js +++ b/index/js/style.js @@ -1,6 +1,11 @@ var target, use_tls, editor; $('#get-services').click(function(){ + + // reset all selected list + resetReqResData() + removeRequestSelectedClass() + var t = get_valid_target(); use_tls = "false";