1
0
mirror of https://github.com/gusaul/grpcox.git synced 2024-12-26 02:40:10 +00:00

Compare commits

..

4 Commits

Author SHA1 Message Date
Muhammad Auliya
8534ee1dc1
Merge pull request #32 from Nitrillo/feature/TLS
Added TLS checkbox
2021-12-21 17:07:51 +07:00
Muhammad Auliya
54efdebe24
Merge pull request #35 from adzimzf/adzim/save_request
feat(request-list): Support CRUD for request list
2021-12-21 17:07:00 +07:00
Azdim Zul Fahmi
464de07064 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.
2021-12-12 15:20:17 +07:00
Cesar Guirao
e7578eaed5 Added TLS checkbox 2021-07-23 09:41:02 -07:00
5 changed files with 420 additions and 3 deletions

View File

@ -200,4 +200,53 @@ circle {
transform: scaleY(1.0); transform: scaleY(1.0);
-webkit-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;;
} }

View File

@ -14,16 +14,44 @@
</head> </head>
<body> <body>
<div class="container pt-50"> <div class="container-fluid pt-50">
<div class="row animated fadeIn"> <div class="row animated fadeIn justify-content-md-center">
<div class="col"> <div class="col-3">
<div class="row">
<div class="col" style="padding-left: 70px;">
<div class="row column-row-left">
<div class="md-form input-group">
<input type="text" class="form-control search" id="search-request" onkeyup="search(this)">
<label for="search-request" class="">Search Request</label>
</div>
<ul class="list-group list-group-flush list" id="request-list"></ul>
</div>
</div>
</div>
</div>
<div class="col-7">
<div class="md-form input-group"> <div class="md-form input-group">
<input type="text" class="form-control" id="server-target"> <input type="text" class="form-control" id="server-target">
<label for="server-target">gRPC Server Target</label> <label for="server-target">gRPC Server Target</label>
<div class="input-group-append"> <div class="input-group-append">
<button id="get-services" class="btn btn-mdb-color waves-effect m-0" type="button"><i class="fa fa-plug"></i></button> <button id="get-services" class="btn btn-mdb-color waves-effect m-0" type="button"><i class="fa fa-plug"></i></button>
<div class="dropdown">
<button type="button" class="btn btn-mdb-color waves-effect m-0 dropdown-toggle save-button-dropdown" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="true">
</button>
<div class="dropdown-menu dropdown-menu-right" aria-labelledby="btnGroupDrop1">
<a class="dropdown-item" id="show-modal-save-request">Save</a>
<a class="dropdown-item" id="show-modal-save-as-request">Save As</a>
</div>
</div>
</div> </div>
</div> </div>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="use-tls">
<label class="custom-control-label" for="use-tls">Use TLS</label>
</div>
<div class="custom-control custom-checkbox"> <div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="restart-conn"> <input type="checkbox" class="custom-control-input" id="restart-conn">
<label class="custom-control-label" for="restart-conn">Restart Connection</label> <label class="custom-control-label" for="restart-conn">Restart Connection</label>
@ -174,15 +202,42 @@
<div class="rect5"></div> <div class="rect5"></div>
</div> </div>
<!-- Modal Save request-->
<div class="modal fade" id="saveRequest" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Input the name for the request</h5>
</div>
<div class="modal-body">
<form>
<div class="form-group row">
<label for="input-request-name" class="col-sm-2 col-form-label">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="input-request-name">
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button id="save-request" type="button" class="btn btn-primary">Save</button>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="js/jquery-3.3.1.min.js"></script> <script type="text/javascript" src="js/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="js/popper.min.js"></script> <script type="text/javascript" src="js/popper.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script> <script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/mdb.min.js"></script> <script type="text/javascript" src="js/mdb.min.js"></script>
<script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script> <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.1/ace.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.4.1/ace.js"></script>
<script type="text/javascript" src="js/db.js"></script>
<script type="text/javascript" src="js/style.js"></script> <script type="text/javascript" src="js/style.js"></script>
<script type="text/javascript" src="js/proto.js"></script> <script type="text/javascript" src="js/proto.js"></script>
<script type="text/javascript" src="js/ctx.metadata.js"></script> <script type="text/javascript" src="js/ctx.metadata.js"></script>
<script type="text/javascript" src="js/request.list.js"></script>
</body> </body>
</html> </html>

143
index/js/db.js Normal file
View File

@ -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)
}
})
}

162
index/js/request.list.js Normal file
View File

@ -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 = `
<a title="Delete this request" class="delete-request" onclick="removeRequest(this)"><i class="fa fa-times"></i></a>
<p class="one-long-line request" onclick="updateRequestView(this)">${item}</p>
`
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()
});

View File

@ -1,6 +1,11 @@
var target, use_tls, editor; var target, use_tls, editor;
$('#get-services').click(function(){ $('#get-services').click(function(){
// reset all selected list
resetReqResData()
removeRequestSelectedClass()
var t = get_valid_target(); var t = get_valid_target();
use_tls = "false"; use_tls = "false";
@ -8,6 +13,9 @@ $('#get-services').click(function(){
if($('#restart-conn').is(":checked")) { if($('#restart-conn').is(":checked")) {
restart = "1" restart = "1"
} }
if($('#use-tls').is(":checked")) {
use_tls = "true"
}
// determine whether the proto connection will use local proto or not // determine whether the proto connection will use local proto or not
const use_proto = $('#local-proto').is(":checked"); const use_proto = $('#local-proto').is(":checked");