Selaa lähdekoodia

feat: added operations, refactored how variables work, added trash sound and now is possible to compile the code using js eval

Marcelo Vilas Boas Correa Filho 5 vuotta sitten
vanhempi
commit
80515037fd

+ 13 - 8
app.js

@@ -1,16 +1,21 @@
-var express = require('express');
-var path = require('path');
-var cookieParser = require('cookie-parser');
-var logger = require('morgan');
+const express = require('express');
+const path = require('path');
+const cookieParser = require('cookie-parser');
+const logger = require('morgan');
 
-var indexRouter = require('./routes/index');
-var usersRouter = require('./routes/users');
+const indexRouter = require('./routes/index');
+const usersRouter = require('./routes/users');
 
-var app = express();
+const app = express();
+const bodyParser = require('body-parser');
+
+app.use(bodyParser.urlencoded({
+    extended: true
+}));
 
 app.use(logger('dev'));
 app.use(express.json());
-app.use(express.urlencoded({ extended: false }));
+app.use(express.urlencoded({extended: false}));
 app.use(cookieParser());
 app.use(express.static(path.join(__dirname, 'public')));
 

+ 59 - 15
public/index.html

@@ -15,13 +15,16 @@
         <div class="collapse navbar-collapse" id="navbarSupportedContent">
             <ul class="navbar-nav mr-auto">
                 <li class="nav-item active">
-                    <button class="nav-link" accesskey="a" title="Voltar para essa lista de atalhos Alt + a"
-                            data-toggle="tooltip" data-placement="bottom">Lista de Atalhos<span class="sr-only">Lista de Atalhos</span>
+                    <button class="nav-link btn btn-light" accesskey="a"
+                            title="Voltar para essa lista de atalhos Alt + a"
+                            data-toggle="tooltip" data-placement="bottom">Lista de Atalhos<span class="sr-only">Lista de
+                                Atalhos</span>
                     </button>
                 </li>
                 <li class="nav-item">
                     <a class="nav-link" href="#" title="Ir para a lista de operações Alt + O" data-toggle="tooltip"
-                       data-placement="bottom">Lista de Operações<span class="sr-only">Lista de Operações</span></a>
+                       data-placement="bottom">Lista de Operações<span class="sr-only">Lista de
+                                Operações</span></a>
                 </li>
             </ul>
         </div>
@@ -38,12 +41,39 @@
                     <ul class="nav flex-column">
                         <li class="nav-item">
                             <button class="dropdown-item" accesskey="v" type="button"
-                                    onclick="addVariable()">Adicionar
+                                    onclick="buildVariablesSubmenu()">Variáveis
+                            </button>
+                        </li>
+                        <li class="nav-item">
+                            <button class="dropdown-item" accesskey="v" type="button"
+                                    onclick="buildOperationsSubMenu()">Operações
+                            </button>
+                        </li>
+                        <li class="nav-item">
+                            <button class="btn btn-success" accesskey="v" type="button"
+                                    onclick="compile()">Compilar
                             </button>
                         </li>
                     </ul>
                 </div>
             </nav>
+            <div style="position: absolute; display: none; left: 360px; z-index: 1; width: 400px;" id="subMenuOptions">
+                <div class="card">
+                    <div class="card-title" id="subMenuOptionsTitle">
+                        <div class="text-center">
+                            <h3 id="subMenuOptionsTitleH3">Variáveis</h3>
+                        </div>
+                    </div>
+                    <div class="card-body" id="subMenuOptionsBody">
+
+                    </div>
+                    <div class="card-footer" id="subMenuOptionsFooter">
+                        <button type="button" class="btn btn-danger" onclick="subMenuOptions.style.display = 'none';">
+                            Cancelar
+                        </button>
+                    </div>
+                </div>
+            </div>
             <div id="code" class="col-10 code-editor">
                 <div class="d-flex justify-content-center">
                     <h4>Workspace</h4>
@@ -88,19 +118,33 @@
             </div>
         </div>
     </div>
-    <!-- Where to place the code modal -->
+</div>
+<!-- Where to place the code modal -->
+
+<script src="/javascripts/util/jquery-3.5.0.js"></script>
+<script src="/javascripts/util/jquery.hotkeys.js"></script>
+<script src="/javascripts/bootstrap/bootstrap.bundle.js"></script>
+<script src="/javascripts/bootstrap/bootstrap.js"></script>
+
+<script src="/javascripts/shortcuts/shortcuts-events.js"></script>
+<script src="/javascripts/data-types.js"></script>
+<script src="/javascripts/code-view.js"></script>
+<script src="/javascripts/util/sub-menu.js"></script>
+<script src="/javascripts/compiler.js"></script>
+<!--    <script src="/javascripts/modules/main-code-types.js"></script>-->
+
+<script src="/javascripts/modules/variables/util-variables.js"></script>
+<script src="/javascripts/modules/variables/main-variables.js"></script>
+<script src="/javascripts/modules/variables/workspace-variables.js"></script>
+<script src="/javascripts/modules/variables/sub-menu.js"></script>
+
+<script src="/javascripts/modules/operators/operations.js"></script>
+<script src="/javascripts/modules/operators/sub-menu.js"></script>
+<script src="/javascripts/modules/operators/main-operators.js"></script>
+<script src="/javascripts/modules/operators/util-operators.js"></script>
+<script src="/javascripts/modules/operators/workspace-operators.js"></script>
 
-    <script src="/javascripts/util/jquery-3.5.0.js"></script>
-    <script src="/javascripts/util/jquery.hotkeys.js"></script>
-    <script src="/javascripts/bootstrap/bootstrap.bundle.js"></script>
-    <script src="/javascripts/bootstrap/bootstrap.js"></script>
 
-    <script src="/javascripts/shortcuts/shortcuts-events.js"></script>
-    <script src="/javascripts/data-types.js"></script>
-    <script src="/javascripts/code-view.js"></script>
-    <script src="/javascripts/modules/variables/util-variables.js"></script>
-    <script src="/javascripts/modules/variables/main-variables.js"></script>
-    <script src="/javascripts/modules/variables/workspace-variables.js"></script>
 </body>
 
 </html>

+ 18 - 2
public/javascripts/code-view.js

@@ -2,10 +2,26 @@ const $code = $("#code");
 const $workspace = $("#workspace");
 const $main = $("#main");
 const $functions = $("#functions");
+const trashSound = new Audio("/media/sounds/trash.mp3");
 
-let universalId = 0;
+const mainCodeTypes = {
+    variable: "VARIABLE",
+    operation: "OPERATION",
+    attribution: "ATTRIBUTION",
+    operator: "OPERATOR"
+};
+
+// Sub menu elements
+
+let universalId = {
+    current: 0,
+    next: function () {
+        this.current = this.current + 1;
+        return this.current;
+    }
+};
 
 function getCurrentMainLineNumber() {
     // TO DO: Find a way to know in wath line the main code is
     return $(".code-line").length + 1;
-}
+}

+ 45 - 0
public/javascripts/compiler.js

@@ -0,0 +1,45 @@
+function compile() {
+    let operations = document.getElementsByName('mainOperationsType');
+    let stringToBeCompiled = ``;
+
+    // declaring variables
+    for (let i = 0; i < variables.length; i++) {
+        stringToBeCompiled += `let ${variables[i].name} = ${variables[i].value};`;
+    }
+
+    for (let i = 0; i < operations.length; i++) {
+        switch (operations[i].value) {
+            case mainCodeTypes.attribution: {
+                console.log(operations[i].previousElementSibling.value);
+
+                if (i !== 0)
+                    stringToBeCompiled += `;`;
+
+                stringToBeCompiled += `\n${getVariableById(operations[i].previousElementSibling.value).name} = `;
+                break;
+            }
+            case mainCodeTypes.variable: {
+                console.log(operations[i].previousElementSibling.value);
+                stringToBeCompiled += `${getVariableById(operations[i].previousElementSibling.value).name} `;
+                break;
+            }
+            case mainCodeTypes.operation: {
+                let operation = getOperationById(operations[i].previousElementSibling.value);
+                console.log(`${operation.firstVariable.name} ${operation.operation.operator} ${operation.secondVariable.name}`);
+                stringToBeCompiled += `${operation.firstVariable.name} ${operation.operation.operator} ${operation.secondVariable.name} `;
+                break;
+            }
+            case mainCodeTypes.operator: {
+                console.log(operations[i].previousElementSibling.value);
+                stringToBeCompiled += `${getOperationByValue(operations[i].previousElementSibling.value).operator} `;
+                break;
+            }
+        }
+    }
+
+    for (let i = 0; i < variables.length; i++) {
+        stringToBeCompiled += `\nalert("${variables[i].name} = " + ${variables[i].name});`;
+    }
+
+    eval(stringToBeCompiled);
+}

+ 0 - 2
public/javascripts/data-types.js

@@ -11,8 +11,6 @@ const dataTypes = {
 };
 
 function getVariableTypeBarrier(dataType) {
-    console.log("Getting barrier for type: " + dataType);
-
     switch (dataType) {
         case 'String':
             return "\"";

+ 5 - 0
public/javascripts/modules/main-code-type.js

@@ -0,0 +1,5 @@
+
+
+function dsa() {
+
+}

+ 86 - 0
public/javascripts/modules/operators/main-operators.js

@@ -0,0 +1,86 @@
+function placeOperationAt() {
+    let firstVariable = document.getElementById('firstOperationSubMenuVariable');
+    let operation = document.getElementById('operationTypeSubMenu');
+    let secondVariable = document.getElementById('secondOperationSubMenuVariable');
+    let id = universalId.next();
+    let html = ``;
+
+    let compiledView = `${variables[firstVariable.value].name} ${getOperationByValue(operation.value).operator} ${variables[secondVariable.value].name}`;
+
+    html += `<div class="col-2 p-2 m-2 operation-main" id="workspaceVariableDiv${id}">`;
+    html += `    <input type="hidden" id="workspaceGlobalMenu${id}" name="${WORKSPACE_COMPONENTS_NAME}" value='${compiledView}' ${UNIVERSAL_WORKSPACE_ID}="${id}">`;
+    html += `    <input type="hidden" id="operationId${id}" value='${id}'>`;
+    html += `    <input type="hidden" name="mainOperationsType" value='${mainCodeTypes.operation}'>`;
+    html += `    <div class="row">`;
+    html += `        <div class="col-9 pt-2 text-center" style="border-right: 1px solid #646464;">`;
+    html += `            <h6>${compiledView}</h6>`;
+    html += `        </div>`;
+    html += `        <div class="col-3 text-center" style="border-left: 1px solid #646464;">`;
+    html += `            <button type="button" class="btn btn-danger" onclick="deleteOperationFromMain(${id})">X</button>`;
+    html += `        </div>`;
+    html += `    </div>`;
+    html += `</div>`;
+
+    $(html).insertAfter(`#workspaceVariableDiv${document.getElementById('placeOperationAt').value}`);
+
+    operations.push({
+        id: id,
+        firstVariable: variables[firstVariable.value],
+        operation: getOperationByValue(operation.value),
+        secondVariable: variables[secondVariable.value],
+        usage: document.getElementById(`workspaceVariableDiv${id}`)
+    });
+
+    variables[firstVariable.value].usages.push(document.getElementById(`workspaceVariableDiv${id}`));
+    variables[secondVariable.value].usages.push(document.getElementById(`workspaceVariableDiv${id}`));
+
+    hideSubMenu();
+}
+
+function placeOperatorAt() {
+    let operator = getOperationByValue(document.getElementById('operatorTypeSubMenu').value);
+    let id = universalId.next();
+    let html = ``;
+
+    html += `<div class="col-2 p-2 m-2 operation-main" id="workspaceVariableDiv${id}">`;
+    html += `    <input type="hidden" id="workspaceGlobalMenu${id}" name="${WORKSPACE_COMPONENTS_NAME}" value='${operator.operator}' ${UNIVERSAL_WORKSPACE_ID}="${id}">`;
+    html += `    <input type="hidden" id="operatorValue${id}" value='${operator.value}'>`;
+    html += `    <input type="hidden" name="mainOperationsType" value='${mainCodeTypes.operator}'>`;
+    html += `    <div class="row">`;
+    html += `        <div class="col-9 pt-2 text-center" style="border-right: 1px solid #646464;">`;
+    html += `            <h6>${operator.operator}</h6>`;
+    html += `        </div>`;
+    html += `        <div class="col-3 text-center" style="border-left: 1px solid #646464;">`;
+    html += `            <button type="button" class="btn btn-danger" onclick="deleteOperatorFromMain(${id})">X</button>`;
+    html += `        </div>`;
+    html += `    </div>`;
+    html += `</div>`;
+
+    $(html).insertAfter(`#workspaceVariableDiv${document.getElementById('placeOperatorAt').value}`);
+
+    operatorsMain.push({
+        id: id,
+        operation: operator,
+        usage: document.getElementById(`workspaceVariableDiv${id}`)
+    });
+
+    hideSubMenu();
+}
+
+function deleteOperationFromMain(id) {
+    for (let i = 0; i < operations.length; i++) {
+        if (operations[i].id === id) {
+            operations[i].usage.remove();
+            operations.splice(i, 1);
+        }
+    }
+}
+
+function deleteOperatorFromMain(id) {
+    for (let i = 0; i < operatorsMain.length; i++) {
+        if (operatorsMain[i].id === id) {
+            operatorsMain[i].usage.remove();
+            operatorsMain.splice(i, 1);
+        }
+    }
+}

+ 41 - 0
public/javascripts/modules/operators/operations.js

@@ -0,0 +1,41 @@
+const operators = [
+    {
+        name: "Soma",
+        operator: "+",
+        value: "SUM"
+    },
+    {
+        name: "Subtração",
+        operator: "-",
+        value: "MINUS"
+    },
+    {
+        name: "Multiplicação",
+        operator: "*",
+        value: "MULTIPLICATION"
+    },
+    {
+        name: "Divisão",
+        operator: "/",
+        value: "DIVISION"
+    },
+    {
+        name: "Potência",
+        operator: "^",
+        value: "POTENTIATION"
+    },
+    {
+        name: "Raíz Quadrada",
+        operator: "\u221A",
+        value: "SQUARE_ROOT"
+    }
+];
+
+function getOperationByValue(value) {
+    for (let i = 0; i < operators.length; i++) {
+        if (operators[i].value === value)
+            return operators[i];
+    }
+
+    return null;
+}

+ 92 - 0
public/javascripts/modules/operators/sub-menu.js

@@ -0,0 +1,92 @@
+function buildOperationsSubMenu() {
+    subMenuOptionsTitleH3.innerText = `Operações`;
+
+    let body = ``;
+
+    let allWorkspaceComponents = $(
+        `input[type="hidden"][name="${WORKSPACE_COMPONENTS_NAME}"]`
+    );
+
+    body += `<hr />`;
+
+    // Value attribution manipulation
+    body += `<div class="p-3 text-center">`;
+    body += `    <h5>Atribuir</h5>`;
+    body += `</div>`;
+    body += `<div>`;
+    body += `   <div class="row p-3 operation-sub-menu">`;
+    body += `       <div class="col-md-5 text-center">`;
+    body += `           <select class="form-control" id="firstOperationSubMenuVariable">`;
+    for (let i = 0; i < variables.length; i++) {
+        body += `               <option value="${i}">${variables[i].name}</option>`;
+    }
+    body += `           </select>`;
+    body += `       </div>`;
+    body += `       <div class="col-2 text-center">`;
+    body += `           <select class="form-control" id="operationTypeSubMenu">`;
+    for (let i = 0; i < operators.length; i++) {
+        body += `               <option value="${operators[i].value}">${operators[i].operator}</option>`;
+    }
+    body += `           </select>`;
+    body += `       </div>`;
+    body += `       <div class="col-md-5 text-center">`;
+    body += `           <select class="form-control" id="secondOperationSubMenuVariable">`;
+    for (let i = 0; i < variables.length; i++) {
+        body += `               <option value="${i}">${variables[i].name}</option>`;
+    }
+    body += `           </select>`;
+    body += `       </div>`;
+    body += `    </div>`;
+    body += `    <div class="row">`;
+    body += `        <select class="form-control" id="placeOperationAt">`;
+    body += `            <option value="" disabled>Adicionar após</option>`;
+    for (let i = 0; i < allWorkspaceComponents.length; i++) {
+        body += `<option value="${allWorkspaceComponents[i].attributes.universalworkspaceid.value}">${allWorkspaceComponents[i].value}</option>`;
+    }
+    body += `           </select>`;
+    body += `    </div>`;
+    body += `    <div class="row p-4">`;
+    body += `        <div class="col-md-12 text-center">`;
+    body += `            <button type="button" class="btn btn-info" onclick="placeOperationAt()">Posicionar</button>`;
+    body += `        </div>`;
+    body += `    </div>`;
+    body += `</div>`;
+
+    body += `<hr />`;
+
+    // Add operator to main
+    body += `<div class="p-3 text-center">`;
+    body += `    <h5>Operador</h5>`;
+    body += `</div>`;
+    body += `<div class="row text-center">`;
+    body += `    <div class="col-4">`;
+    body += `    </div>`;
+    body += `    <div class="col-4">`;
+    body += `        <select class="form-control" id="operatorTypeSubMenu">`;
+    for (let i = 0; i < operators.length; i++) {
+        body += `            <option value="${operators[i].value}">${operators[i].operator}</option>`;
+    }
+    body += `        </select>`;
+    body += `    </div>`;
+    body += `    <div class="col-4">`;
+    body += `    </div>`;
+    body += `</div>`;
+    body += `<div>`;
+    body += `    <div class="row p-3">`;
+    body += `        <select class="form-control" id="placeOperatorAt">`;
+    body += `            <option value="" disabled>Adicionar após</option>`;
+    for (let i = 0; i < allWorkspaceComponents.length; i++) {
+        body += `<option value="${allWorkspaceComponents[i].attributes.universalworkspaceid.value}">${allWorkspaceComponents[i].value}</option>`;
+    }
+    body += `           </select>`;
+    body += `    </div>`;
+    body += `    <div class="row p-4">`;
+    body += `        <div class="col-md-12 text-center">`;
+    body += `            <button type="button" class="btn btn-info" onclick="placeOperatorAt()">Posicionar</button>`;
+    body += `        </div>`;
+    body += `    </div>`;
+    body += `</div>`;
+
+    subMenuOptionsBody.innerHTML = body;
+    showSubMenu();
+}

+ 8 - 0
public/javascripts/modules/operators/util-operators.js

@@ -0,0 +1,8 @@
+function getOperationById(id) {
+    for (let i = 0; i < operations.length; i++) {
+        if (operations[i].id == id )
+            return operations[i];
+    }
+
+    return null;
+}

+ 6 - 0
public/javascripts/modules/operators/workspace-operators.js

@@ -0,0 +1,6 @@
+let operations = [];
+let operatorsMain = [];
+
+function asd() {
+
+}

+ 57 - 13
public/javascripts/modules/variables/main-variables.js

@@ -1,29 +1,73 @@
 const UNIVERSAL_WORKSPACE_ID = "universalworkspaceid";
 const WORKSPACE_COMPONENTS_NAME = "workspaceComponents";
 
-function addVariableToMain({id = null, variable = {name: "", type: "String", value: ""}, afterComponentWithId = null}) {
+function addVariableToMain({
+                               id = null,
+                               variable = {name: "", type: "String", value: ""},
+                               afterComponentWithId = null,
+                           }) {
     let html = ``;
-    let code = mountCodeFromVariable(variable);
 
-    html += `<div class="col-3 p-2 m-2" style="background-color: #a6a6a6; border: 1px solid #646464" id="workspaceVariableDiv${id}">`;
-    html += `    <input type="hidden" id="workspaceGlobalMenu${id}" name="${WORKSPACE_COMPONENTS_NAME}" value='${code}' ${UNIVERSAL_WORKSPACE_ID}="${id}">`;
-    html += `    <div class="row">`;
-    html += `        <div class="col-10 pt-2" style="border-right: 1px solid #646464;">`;
-    html += `           <h6>${code}</h6>`;
-    html += `        </div>`;
-    html += `        <div class="col-2 pl-2 pr-1" style="border-left: 1px solid #646464;">`;
-    html += `            <button type="button" class="btn btn-danger" onclick="deleteVariableFromMain(${id})">X</button>`;
+    if (afterComponentWithId === null) {
+        html += `<div class="col-12">`;
+        html += `    <div class="row">`;
+    }
+    html += `        <div class="col-2 p-2 m-2 variable-available-main" id="workspaceVariableDiv${id}">`;
+    html += `            <input type="hidden" id="workspaceGlobalMenu${id}" name="${WORKSPACE_COMPONENTS_NAME}" value='${variable.name}' ${UNIVERSAL_WORKSPACE_ID}="${id}">`;
+    html += `            <input type="hidden" id="variableId${id}" value='${variable.id}'>`;
+    html += `            <input type="hidden" name="mainOperationsType" value='${mainCodeTypes.variable}'>`;
+    html += `            <div class="row">`;
+    html += `                <div class="col-9 pt-2 text-center" style="border-right: 1px solid #646464;">`;
+    html += `                <h6>${variable.name}</h6>`;
+    html += `                </div>`;
+    html += `                <div class="col-3 text-center" style="border-left: 1px solid #646464;">`;
+    html += `                    <button type="button" class="btn btn-danger" onclick="deleteVariableFromMain(${id})">X</button>`;
+    html += `                </div>`;
+    html += `            </div>`;
     html += `        </div>`;
-    html += `    </div>`;
-    html += `</div>`;
+    if (afterComponentWithId === null) {
+        html += `    </div>`;
+        html += `</div>`;
+    }
 
     if (afterComponentWithId == null) {
         $main.append(html);
     } else {
         $(html).insertAfter(`#workspaceVariableDiv${afterComponentWithId}`);
     }
+
+    variable.usages.push(document.getElementById(`workspaceVariableDiv${id}`));
+}
+
+function attributeValueToMain({
+                                  id = null,
+                                  variable = {name: "", type: "String", value: ""},
+                              }) {
+    let html = ``;
+
+    html += `<div class="col-12">`;
+    html += `    <div class="row">`;
+    html += `        <div class="col-2 p-2 m-2 variable-attribution-main" id="workspaceVariableDiv${id}">`;
+    html += `            <input type="hidden" id="workspaceGlobalMenu${id}" name="${WORKSPACE_COMPONENTS_NAME}" value='${variable.name} = ' ${UNIVERSAL_WORKSPACE_ID}="${id}">`;
+    html += `            <input type="hidden" id="variableId${id}" value='${variable.id}'>`;
+    html += `            <input type="hidden" name="mainOperationsType" value='${mainCodeTypes.attribution}'>`;
+    html += `            <div class="row">`;
+    html += `                <div class="col-9 pt-2 text-center" style="border-right: 1px solid #646464;">`;
+    html += `                    <h6>${variable.name} = </h6>`;
+    html += `                </div>`;
+    html += `                <div class="col-3 text-center" style="border-left: 1px solid #646464;">`;
+    html += `                    <button type="button" class="btn btn-danger" onclick="deleteVariableFromMain(${id})">X</button>`;
+    html += `                </div>`;
+    html += `            </div>`;
+    html += `        </div>`;
+    html += `    </div>`;
+    html += `</div>`;
+
+    $main.append(html);
+
+    variable.attributions.push(document.getElementById(`workspaceVariableDiv${id}`));
 }
 
 function deleteVariableFromMain(id = null) {
     $(`#workspaceVariableDiv${id}`).remove();
-}
+}

+ 106 - 0
public/javascripts/modules/variables/sub-menu.js

@@ -0,0 +1,106 @@
+function buildVariablesSubmenu() {
+    subMenuOptionsTitleH3.innerText = `Variáveis`;
+
+    let body = ``;
+
+    body += `<hr />`;
+    body += `<div class="row">`;
+    body += `  <div class="col-md-12 text-center">`;
+    body += `      <button type="button" class="btn btn-info" onclick="addVariable()">Adicionar</button>`;
+    body += `  </div>`;
+    body += `</div>`;
+    body += `<hr />`;
+
+    let allWorkspaceComponents = $(
+        `input[type="hidden"][name="${WORKSPACE_COMPONENTS_NAME}"]`
+    );
+
+    // Place after manipulation
+    body += `<div class="p-3 text-center">`;
+    body += `    <h5>Disponíveis</h5>`;
+    body += `</div>`;
+    for (let i = 0; i < variables.length; i++) {
+        body += `<div class="row p-3 text-center variable-available-sub-menu" id="subMenuOptionVariable${variables[i].id}">`;
+        body += `   <div class="col-md-4">`;
+        body += `       <h5>${variables[i].name}</h5>`;
+        body += `   </div>`;
+        body += `   <div class="col-md-8">`;
+        body += `       <div class="col-md-8">`;
+        body += `           <select class="form-control" id="placeVariableAfter${i}">`;
+        body += `               <option value="" disabled>Adicionar após</option>`;
+        for (let i = 0; i < allWorkspaceComponents.length; i++) {
+            body += `<option value="${allWorkspaceComponents[i].attributes.universalworkspaceid.value}">${allWorkspaceComponents[i].value}</option>`;
+        }
+        body += `           </select>`;
+        body += `       </div>`;
+        body += `   </div>`;
+        body += `</div>`;
+        body += `<div class="row p-3">`;
+        body += `    <div class="col-6 text-center">`;
+        body += `        <button type="button" class="btn btn-info" onclick="positionVariableAfter(${i})">Posicionar</button>`;
+        body += `    </div>`;
+        body += `    <div class="col-6 text-center">`;
+        body += `        <button type="button" class="btn btn-danger" onclick="deleteVariable(${i}, 'subMenuOptionVariable${variables[i].id}')">Excluir</button>`;
+        body += `    </div>`;
+        body += `</div>`;
+    }
+
+    body += `<hr />`;
+
+    // Value attribution manipulation
+    body += `<div class="p-3 text-center">`;
+    body += `    <h5>Atribuir</h5>`;
+    body += `</div>`;
+    body += `<div>`;
+    body += `   <div class="row p-3 variable-attribution-sub-menu">`;
+    body += `       <div class="col-md-10" class="text-center">`;
+    body += `           <select class="form-control" id="variableToBeAttributed">`;
+    for (let i = 0; i < variables.length; i++) {
+        body += `               <option value="${i}">${variables[i].name}</option>`;
+    }
+    body += `           </select>`;
+    body += `       </div>`;
+    body += `       <div class="col-md-2 align-content-center">`;
+    body += `           <h5>=</h5>`;
+    body += `       </div>`;
+    body += `   </div>`;
+    body += `   <div class="row p-4">`;
+    body += `       <div class="col-md-12 text-center">`;
+    body += `           <button type="button" class="btn btn-info" onclick="attributeVariable()">Posicionar</button>`;
+    body += `       </div>`;
+    body += `   </div>`;
+    body += `</div>`;
+
+    subMenuOptionsBody.innerHTML = body;
+    subMenuOptions.style.display = 'inline';
+}
+
+function positionVariableAfter(variableIndex) {
+    let placeAfter = $(`#placeVariableAfter${variableIndex} :selected`).val();
+
+    if (placeAfter !== "") {
+        addVariableToMain({
+            id: universalId.next(),
+            variable: variables[variableIndex],
+            afterComponentWithId: placeAfter,
+        });
+    } else {
+        addVariableToMain({
+            id: universalId.next(),
+            variable: variables[variableIndex],
+        });
+    }
+
+    subMenuOptions.style.display = "none";
+}
+
+function attributeVariable() {
+    let variableToBeAttributed = document.getElementById("variableToBeAttributed");
+
+    attributeValueToMain({
+        id: universalId.next(),
+        variable: variables[variableToBeAttributed.value],
+    });
+
+    hideSubMenu();
+}

+ 9 - 0
public/javascripts/modules/variables/util-variables.js

@@ -1,4 +1,13 @@
 function mountCodeFromVariable(variable = {name: "", type: "String", value: ""}) {
     let variableBarrier = getVariableTypeBarrier(variable.type);
     return `${variable.type} ${variable.name} = ${variableBarrier}${variable.value}${variableBarrier}`;
+}
+
+function getVariableById(id) {
+    for (let i = 0; i < variables.length; i++) {
+        if (variables[i].id == id)
+            return variables[i];
+    }
+
+    return null;
 }

+ 126 - 42
public/javascripts/modules/variables/workspace-variables.js

@@ -1,17 +1,25 @@
 let creatingVariable = false;
+let variables = [];
 
 /*
-* Workspace position modal attributes
-*/
+ * Workspace position modal attributes
+ */
 let $workspacePositionModal = $("#workspacePositionModal");
 let $workspacePositionModalBody = $("#workspacePositionModalBody");
-let $workspacePositionModalPositionsSelect = $("#workspacePositionModalPositionsSelect");
+let $workspacePositionModalPositionsSelect = $(
+    "#workspacePositionModalPositionsSelect"
+);
 
 let workspaceToBeAddId = null;
 let workspaceToBeAddVariable = null;
 let workspaceToBeAddAfterComponent = null;
 
-function addVariable(variable = {name: "", type: dataTypes.String, value: ""}, id = null) {
+function addVariable(
+    variable = {name: "", type: dataTypes.String, value: ""},
+    id = null
+) {
+    subMenuOptions.style.display = "none";
+
     if (creatingVariable === false) {
         // Blocking future variable creation until finish the current creation
         creatingVariable = true;
@@ -78,7 +86,7 @@ function addVariableToCode({id = null}) {
     let variable = {
         name: $("#variableName").val(),
         type: $("#variableType").val(),
-        value: $("#variableValue").val()
+        value: $("#variableValue").val(),
     };
 
     code = mountCodeFromVariable(variable);
@@ -97,75 +105,122 @@ function cancelAddVariable(id = null) {
     // Removing div form for variable creation
     $("#variableCreationDiv").remove();
 
-    if (id != null)
-        $(`#variableDiv${id}`).show();
+    if (id != null) $(`#variableDiv${id}`).show();
 
     // Enabling future variable creation
     creatingVariable = false;
 }
 
-function editVariable(id = null, variable = {name: "", type: dataTypes.String, value: ""}) {
+function editVariable(
+    id = null,
+    variable = {name: "", type: dataTypes.String, value: ""}
+) {
     $(`#variableDiv${id}`).hide();
     addVariable(variable, id);
 }
 
-function deleteVariable(id = null) {
-    if (id != null)
-        $(`#variableDiv${id}`).remove();
+function deleteVariable(variableIndex = null, subMenuOptionId) {
+    trashSound.play();
+
+    document.getElementById(subMenuOptionId).remove();
+
+    for (let i = 0; i < variables[variableIndex].attributions.length; i++) {
+        variables[variableIndex].attributions[i].parentElement.parentElement.remove();
+    }
+
+    for (let i = 0; i < variables[variableIndex].usages.length; i++) {
+        variables[variableIndex].usages[i].remove();
+    }
+
+    variables.splice(variableIndex, 1);
+    // Refresh variables sub menu
+    buildVariablesSubmenu();
 }
 
 function addCodeToScreen({
                              id = null,
                              code = "Some code",
-                             variable = {name: "", type: "String", value: ""}
+                             variable = {name: "", type: "String", value: ""},
                          }) {
     let html = ``;
 
     if (id != null) {
         $(`#mainCode${id}`).html(`<span>${code}</span>`);
         $(`#globalMenu${id}`).val(code);
-        $(`#positionCode${id}`).html(`<button type="button" class="btn btn-dark" id="positionCode${id}" onclick='askWhereToPlaceTheVariable(${id}, ${JSON.stringify(variable)})'>Posicionar</button>`);
-        $(`#editCode${id}`).html(`<button type="button" class="btn btn-info" id="editCodeButton${id}" onclick='editVariable(${id}, ${JSON.stringify(variable)})'>Editar</button>`);
+        $(`#positionCode${id}`).html(
+            `<button type="button" class="btn btn-dark" id="positionCode${id}" onclick='askWhereToPlaceTheVariable(${id}, ${JSON.stringify(
+                variable
+            )})'>Posicionar</button>`
+        );
+        $(`#editCode${id}`).html(
+            `<button type="button" class="btn btn-info" id="editCodeButton${id}" onclick='editVariable(${id}, ${JSON.stringify(
+                variable
+            )})'>Editar</button>`
+        );
         $(`#variableDiv${id}`).show();
+
+        updateVariable({
+            id: id,
+            name: variable.name,
+            type: variable.type,
+            value: variable.value,
+            code: code,
+            element: document.getElementById(`variableDiv${id}`),
+        });
     } else {
-        html += `<div class="col-3 p-2" id="variableDiv${universalId}">`;
-        html += `    <input type="hidden" id="globalMenu${universalId}" value="${code}"/>`;
-        html += `    <div class="card" id="variableCard${universalId}">`;
-        html += `        <div class="card-header" id="variableCardHeader${universalId}">`;
+        id = universalId.next();
+        html += `<div class="col-3 p-2" id="variableDiv${id}">`;
+        html += `    <input type="hidden" id="globalMenu${id}" value="${code}"/>`;
+        html += `    <div class="card" id="variableCard${id}">`;
+        html += `        <div class="card-header" id="variableCardHeader${id}">`;
         html += `            <h4>Variável</h4>`;
         html += `        </div>`;
-        html += `        <div class="card-body" id="variableCardBody${universalId}">`;
-        html += `            <div class="row code-line" id="codeLine${universalId}">`;
-        html += `                <div class="col-2 line-number" id="mainLine${universalId}"><span>${getCurrentMainLineNumber()}</span></div>`;
-        html += `                <div class="col-10 line-code" id="mainCode${universalId}"><span>${code}</span></div>`;
+        html += `        <div class="card-body" id="variableCardBody${id}">`;
+        html += `            <div class="row code-line" id="codeLine${id}">`;
+        html += `                <div class="col-2 line-number" id="mainLine${id}"><span>${getCurrentMainLineNumber()}</span></div>`;
+        html += `                <div class="col-10 line-code" id="mainCode${id}"><span>${code}</span></div>`;
         html += `            </div>`;
         html += `        </div>`;
-        html += `        <div class="card-footer" id="variableCardFooter${universalId}">`;
+        html += `        <div class="card-footer" id="variableCardFooter${id}">`;
         html += `            <div class="row">`;
-        html += `                <div class="col-4" id="deleteCode${universalId}">`;
-        html += `                    <button type="button" class="btn btn-danger" id="deleteCodeButton${universalId}" onclick="deleteVariable(${universalId})">Remover</button>`;
+        html += `                <div class="col-4" id="deleteCode${id}">`;
+        html += `                    <button type="button" class="btn btn-danger" id="deleteCodeButton${id}" onclick="deleteVariable(${id})">Remover</button>`;
         html += `                </div>`;
-        html += `                <div class="col-4 align-self-center" id="positionCode${universalId}">`;
-        html += `                    <button type="button" class="btn btn-dark" id="positionCodeButton${universalId}" onclick='askWhereToPlaceTheVariable(${universalId}, ${JSON.stringify(variable)})'>Posicionar</button>`;
+        html += `                <div class="col-4 align-self-center" id="positionCode${id}">`;
+        html += `                    <button type="button" class="btn btn-dark" id="positionCodeButton${id}" onclick='askWhereToPlaceTheVariable(${id}, ${JSON.stringify(
+            variable
+        )})'>Posicionar</button>`;
         html += `                </div>`;
-        html += `                <div class="col-3" id="editCode${universalId}">`;
-        html += `                    <button type="button" class="btn btn-info" id="editCodeButton${universalId}" onclick='editVariable(${universalId}, ${JSON.stringify(variable)})'>Editar</button>`;
+        html += `                <div class="col-3" id="editCode${id}">`;
+        html += `                    <button type="button" class="btn btn-info" id="editCodeButton${id}" onclick='editVariable(${id}, ${JSON.stringify(
+            variable
+        )})'>Editar</button>`;
         html += `                </div>`;
         html += `            </div>`;
         html += `        </div>`;
         html += `    </div>`;
         html += `</div>`;
 
-        $workspace.append(html);
+        // Saving reference to variable in variables array
+        variables.push({
+            id: id,
+            name: variable.name,
+            type: variable.type,
+            value: variable.value,
+            code: code,
+            element: document.getElementById(`variableDiv${universalId.next()}`),
+            attributions: [],
+            usages: []
+        });
     }
-
-    // Increasing universal id
-    universalId += 1;
 }
 
-function askWhereToPlaceTheVariable(id = null, variable = {name: "", type: "String", value: ""}) {
+function askWhereToPlaceTheVariable(
+    id = null,
+    variable = {name: "", type: "String", value: ""}
+) {
     if (buildAllWorkspaceComponentsSelect()) {
-        $workspacePositionModal.modal('toggle');
+        $workspacePositionModal.modal("toggle");
         $workspacePositionModalPositionsSelect.focus();
 
         workspaceToBeAddId = id;
@@ -176,19 +231,22 @@ function askWhereToPlaceTheVariable(id = null, variable = {name: "", type: "Stri
 }
 
 function buildAllWorkspaceComponentsSelect() {
-    let allWorkspaceComponents = $(`input[type="hidden"][name="${WORKSPACE_COMPONENTS_NAME}"]`);
+    let allWorkspaceComponents = $(
+        `input[type="hidden"][name="${WORKSPACE_COMPONENTS_NAME}"]`
+    );
     let selectOptions = [];
 
     if (allWorkspaceComponents.length > 0) {
         for (let i = 0; i < allWorkspaceComponents.length; i++) {
-            console.log(allWorkspaceComponents[i].attributes);
-            selectOptions.push(`<option value="${allWorkspaceComponents[i].attributes.universalworkspaceid.value}">${allWorkspaceComponents[i].value}</option>`);
+            selectOptions.push(
+                `<option value="${allWorkspaceComponents[i].attributes.universalworkspaceid.value}">${allWorkspaceComponents[i].value}</option>`
+            );
         }
 
         $workspacePositionModalPositionsSelect.empty(); // remove old options
         selectOptions.forEach((object, index, array) => {
             $workspacePositionModalPositionsSelect.append($(object));
-        })
+        });
 
         return true;
     } else {
@@ -197,12 +255,38 @@ function buildAllWorkspaceComponentsSelect() {
 }
 
 $("#workspacePositionModalAddButton").click(() => {
-    addVariableToMain({id: workspaceToBeAddId, variable: workspaceToBeAddVariable, afterComponentWithId: $workspacePositionModalPositionsSelect.val()})
+    addVariableToMain({
+        id: workspaceToBeAddId,
+        variable: workspaceToBeAddVariable,
+        afterComponentWithId: $workspacePositionModalPositionsSelect.val(),
+    });
 
     // Reset variables for future use
     workspaceToBeAddId = null;
     workspaceToBeAddVariable = null;
 
     // Hide position modal
-    $workspacePositionModal.modal('toggle');
-});
+    $workspacePositionModal.modal("toggle");
+});
+
+function updateVariable(
+    variable = {
+        id: 0,
+        name: "Name",
+        type: "String",
+        value: "Value",
+        code: 'String Name = "value"',
+        element: document.getElementById("body"),
+    }
+) {
+    for (let i = 0; i < variables.length; i++) {
+        if (variables[i].id === variable.id) {
+            variables[i] = variable;
+            return;
+        }
+    }
+
+    console.warn(
+        `Can't find variable with id: ${variable.id} to update, please verify the variable universalId`
+    );
+}

+ 22 - 0
public/javascripts/util/sub-menu.js

@@ -0,0 +1,22 @@
+const subMenuOptions = document.getElementById("subMenuOptions");
+const subMenuOptionsTitle = document.getElementById("subMenuOptionsTitle");
+const subMenuOptionsTitleH3 = document.getElementById("subMenuOptionsTitleH3");
+const subMenuOptionsBody = document.getElementById("subMenuOptionsBody");
+const subMenuOptionsFooter = document.getElementById("subMenuOptionsFooter");
+
+function hideSubMenu() {
+    subMenuOptions.style.display = 'none';
+}
+
+function showSubMenu() {
+    subMenuOptions.style.display = 'inline';
+}
+// ==> Code for an class observer that is triggered every time a element style is changed <==
+// var observer = new MutationObserver(function (mutations) {
+//     mutations.forEach(function (mutationRecord) {
+//         console.log("style changed!");
+//     });
+// });
+//
+// var target = document.getElementById('subMenuOptions');
+// observer.observe(target, { attributes: true, attributeFilter: ["style"] });

BIN
public/media/sounds/trash.mp3


+ 23 - 11
public/stylesheets/style.css

@@ -7,16 +7,28 @@ a {
     color: #00B7FF;
 }
 
-/*.code-editor {}*/
+.variable-available-sub-menu {
+    background-color: #80bdff;
+}
+
+.variable-available-main {
+    background-color: #80bdff;
+    border: 1px solid #646464;
+}
+
+.variable-attribution-main {
+    background-color: cornflowerblue;
+    border: 1px solid #646464;
+}
+
+.variable-attribution-sub-menu {
+    background-color: cornflowerblue;
+}
 
-/*.code-line {*/
-/*    border: 1px;*/
-/*    border-style: solid;*/
-/*    border-color: black;*/
-/*}*/
+.operation-sub-menu {
+    background-color: #5e1b7c;
+}
 
-/*.col-1.line-number {*/
-/*    background-color: black;*/
-/*    color: white;*/
-/*    text-align: center;*/
-/*}*/
+.operation-main {
+    background-color: #624e7c;
+}