Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17,105 changes: 17,105 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
"test:watch": "nwb test --server"
},
"dependencies": {
"nanoid": "^4.0.2"
},
"devDependencies": {
"nwb": "0.25.x"
Expand Down
8 changes: 8 additions & 0 deletions src/comparison_operators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const comparison = {
equal: "=",
notequal: "!=",
lessthan: "<",
greaterthan: ">"
};

export default comparison;
14 changes: 13 additions & 1 deletion src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@
<meta name="description" content="">
</head>
<body>
<div id="app"></div>
<div id="app">
<div id="heading">
<h3>JS QUERY BUILDER</h3>
</div>
<hr />
<div id="div-top-section">
<select name="logical" id="logical"> </select>
<button id="btn-add-rule">ADD RULE</button>
</div>
<ol id="rules-list"></ol>
<pre id="output-json"></pre>
</div>
<script src="index.js"></script>
</body>
</html>
158 changes: 156 additions & 2 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,157 @@
let app = document.querySelector('#app')
import logical from "./logical_operators";
import comparison from "./comparison_operators";
import studentsData from "./students_data";
import "./styles.css";
import {nanoid} from "nanoid";

app.innerHTML = '<h2>Welcome to js-query-builder</h2>'
let logicalArray = [];

for (const key in logical) {
logicalArray.push(logical[key]);
}

let logicalDropdownList = document.getElementById("logical");
logicalArray.forEach(function (item) {
let option = document.createElement("option");
option.value = option.innerHTML = item;
logicalDropdownList.appendChild(option);
});

const comb = "AND";

logicalDropdownList.addEventListener("change", (e) => {
rulesObj.combinator = e.target.value
outPutJson()
});

let rulesObj = {id: nanoid(), combinator: comb, rules:[]}

outPutJson()

function addNewRule(field, operator, value){
return {
id: nanoid(),
field: field,
operator: operator,
value: value
}
}

document.getElementById("btn-add-rule").addEventListener("click", addRule);

let rulesList = document.getElementById("rules-list");
function addRule() {

let studentsArray = [];
for(const key in studentsData){
studentsArray.push(studentsData[key]);
}
let selectStudentInfo = document.createElement("select");
selectStudentInfo.id = "select-student-info";
let field = "First Name";
let operator = "=";

studentsArray.forEach(function (info) {
let studentOption = document.createElement("option")
studentOption.value = studentOption.innerHTML = info;
selectStudentInfo.appendChild(studentOption);
})

let comparisonArray = [];
for (const key in comparison){
comparisonArray.push(comparison[key]);
}
let selectComparisonOp = document.createElement("select");
selectComparisonOp.id = "select-comp-op";

comparisonArray.forEach(function (comp){
let comparisonOption = document.createElement("option");
comparisonOption.value = comparisonOption.innerHTML = comp;
selectComparisonOp.appendChild(comparisonOption);
})

let input = document.createElement("input");
input.id = "input-value"
let value = input.value;

let deleteRule = document.createElement("button")
deleteRule.id = "btn-delete-rule";
deleteRule.appendChild(document.createTextNode("DELETE"));

rulesObj.rules.push(addNewRule(field, operator, value));

outPutJson()

let id = "";
let getId = function(){
rulesObj.rules.map(rule => {
id = rule.id;
return id;
})}

getId()

let li = document.createElement("li");
li.id = id;
li.appendChild(selectStudentInfo);
li.appendChild(selectComparisonOp);
li.appendChild(input);
li.appendChild(deleteRule);
rulesList.appendChild(li);

onFieldChange(selectStudentInfo, id);
onOperatorChange(selectComparisonOp, id);
onValueChange(input, id);
onDeleteRule(deleteRule, id);
}

function onFieldChange(selectStudentInfo, id){
selectStudentInfo.addEventListener("change", function(e){
rulesObj.rules.map(rule => {
if(rule.id === id){
rule.field = e.target.value;
}
})
outPutJson()
})
}

function onOperatorChange(selectComparisonOp, id){
selectComparisonOp.addEventListener("change", function(e){
rulesObj.rules.map(rule => {
if(rule.id === id){
rule.operator = e.target.value;
}
})
outPutJson()
})
}

function onValueChange(input, id){
input.addEventListener("input", function(e){
rulesObj.rules.map(rule => {
if(rule.id === id){
rule.value = e.target.value;
}
})
outPutJson()
})
}

function onDeleteRule(deleteRule, id){
deleteRule.addEventListener("click", function(){
rulesObj.rules = rulesObj.rules.filter(rule => rule.id !== id)

let node = document.getElementById(id)
rulesList.removeChild(node)

outPutJson()
})
}

function outPutJson(){
let outPutJson = document.getElementById("output-json");
if(outPutJson){
outPutJson.innerHTML = JSON.stringify(rulesObj, null, 2)
}
}
6 changes: 6 additions & 0 deletions src/logical_operators.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
const logical = {
and: "AND",
or: "OR"
};

export default logical;
9 changes: 9 additions & 0 deletions src/students_data.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const studentsData={
firstName: "First Name",
lastName: "Last Name",
age: "Age",
level: "Level",
enrollment_year: "Enrollment Year"
}

export default studentsData;
104 changes: 104 additions & 0 deletions src/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
body {
font-family: 'Times New Roman', Times, serif;
display: flex;
justify-content: center;
}

#app {
margin: 20px;
display: grid;
align-items: center;
width: 50vw;
background-color:rgb(9, 65, 114);
border-radius: 2px;
}

#heading {
display: grid;
justify-content: center;
color: white;
}

hr {
background-color: gainsboro;
height: 1px;
border: none;
margin: 0 10px 0 10px;
}

#div-top-section {
display: flex;
align-items: center;
margin-top: 10px;
}

#logical {
margin: 10px;
padding: 8px;
border: 1px solid gainsboro;
border-radius: 2px;
font-size: 14px;
font-family: 'Times New Roman', Times, serif;
}

#btn-add-rule {
padding: 9px;
border-radius: 2px;
cursor: pointer;
border: none;
color: white;
font-size: 14px;
background-color: rgb(49, 148, 49);
font-family: 'Times New Roman', Times, serif;
}

#rules-list {
list-style: none;
padding: 0;
}

#select-student-info {
margin: 0 10px 0 10px;
padding: 8px;
border: 1px solid gainsboro;
border-radius: 2px;
font-size: 16px;
font-family: 'Times New Roman', Times, serif;
}

#select-comp-op {
margin: 0 10px 0 10px;
padding: 8px;
border: 1px solid gainsboro;
border-radius: 2px;
font-size: 16px;
}

#input-value {
margin: 0 10px 10px 10px;
padding: 8px;
border: 1px solid gainsboro;
border-radius: 2px;
font-size: 16px;
font-family: 'Times New Roman', Times, serif;
}

#btn-delete-rule {
padding: 9px;
margin: 0 10px 10px 10px;
border-radius: 2px;
cursor: pointer;
border: none;
color: white;
font-size: 14px;
background-color: rgb(169, 43, 43);
font-family: 'Times New Roman', Times, serif;
}

#output-json {
background-color: white;
padding: 10px;
margin: 10px;
border-radius: 2px;
font-size: 16px;
}