diff --git a/README.md b/README.md index e015e62..24dd391 100644 --- a/README.md +++ b/README.md @@ -14,33 +14,27 @@ This file is required for FPMax algorithm (for mining design rules) to execute. There must be a file name `ruleJson.txt` in the project folder in which all rules are stored. `grammar` field is recently added for each rule. It is mandatory but is generated for newly added rules. Here is an example for this file: -``` +```javascript [ { - "index": 1, + "index": "1", "title": "All Buttons must have a title", "description": "IF a JButton is created\nTHEN it should be initialized and have a title upon creating.", "tags": [ "Labeling" ], - "ruleType": { - "constraint": "FOLDER", - "checkFor": [ - "src" - ], - "type": "WITHIN" - }, - "quantifier": { - "detail": "JButtons", - "command": "src:unit/src:class/src:block//src:decl_stmt/src:decl[src:type/src:name/text()=\"JButton\"]" - }, - "constraint": { - "detail": "JButtons with labels in constructor", - "command": "src:unit/src:class/src:block//src:decl_stmt/src:decl[src:type/src:name/text()=\"JButton\" and count(src:init/src:expr/src:call/src:argument_list/src:argument)>0]" - } + "checkForFilesFolders": [ + "src" + ], + "checkForFilesFoldersConstraints": "INCLUDE", + "processFilesFolders": "WITHIN", + // JButtons + "quantifierXPathQuery": ["src:unit/src:class/src:block//src:decl_stmt/src:decl[src:type/src:name/text()=\"JButton\"]"], + // JButtons with labels in constructor + "constraintXPathQuery": ["src:unit/src:class/src:block//src:decl_stmt/src:decl[src:type/src:name/text()=\"JButton\" and count(src:init/src:expr/src:call/src:argument_list/src:argument)>0]"] }, { - "index": 6, + "index": "6", "title": "Communication between artifacts should be indirected through a Command", "description": "IF an Artifact needs to communicate with another artifact\nTHEN it should create a Command describing the desired action to be performed.\nEach Artifact exists in a separate shard, which may execute in parallel on a separate server. An artifact may communicate with another artifact by creating a Command which describes the action that it wishes the receiving Artifact to perform.", "tags": [ @@ -49,52 +43,39 @@ It is mandatory but is generated for newly added rules. Here is an example for t "Entity", "Persistence" ], - "ruleType": { - "constraint": "FOLDER", - "checkFor": [ - "src/com/crowdcoding/commands", "src/com/crowdcoding/entities" - ], - "type": "MIXED" - }, - "quantifier": { - "type": "FIND_FROM_TEXT", - "detail": "Calling constructors of all entity objects", - "command1": "//src:unit/src:class[(src:annotation/src:name[text()=\"Entity\"] or src:annotation/src:name[text()=\"Subclass\"])]/src:name/text()", - "command2": "//src:unit/src:class[src:super/src:extends/src:name/text()=\"Command\"]/src:block/src:class/src:block/descendant-or-self::src:decl_stmt/src:decl[src:init/src:expr/src:call/src:name/text()=\"\"]" - }, - "constraint": { - "type": "RETURN_TO_BASE", - "detail": "Calling constructors of allowed entity objects", - "command1": "//src:unit/src:class/src:block/src:function_decl[src:name/text()=\"execute\"]/src:parameter_list/src:parameter/src:decl/src:type/src:name[not(text()=\"String\")]/text()", - "command2": "//src:unit/src:class[src:name/text()=\"\" or (src:super/src:extends/src:name/text()=\"\")]/src:name/text()", - "command3": "//src:unit/src:class[src:super/src:extends/src:name/text()=\"Command\"]/src:block/src:class/src:block/descendant-or-self::src:decl_stmt/src:decl[src:init/src:expr/src:call/src:name/text()=\"\"]" - } + "checkForFilesFolders": [ + "src/com/crowdcoding/commands", "src/com/crowdcoding/entities" + ], + "checkForFilesFoldersConstraints": "INCLUDE", + "processFilesFolders": "MIXED", + "quantifierQueryType": "FIND_FROM_TEXT", + // Calling constructors of all entity objects + "quantifierXPathQuery": ["//src:unit/src:class[(src:annotation/src:name[text()=\"Entity\"] or src:annotation/src:name[text()=\"Subclass\"])]/src:name/text()", + "//src:unit/src:class[src:super/src:extends/src:name/text()=\"Command\"]/src:block/src:class/src:block/descendant-or-self::src:decl_stmt/src:decl[src:init/src:expr/src:call/src:name/text()=\"\"]"] + "constraintQueryType": "RETURN_TO_BASE", + // Calling constructors of allowed entity objects", + "constraintXPathQuery": ["//src:unit/src:class/src:block/src:function_decl[src:name/text()=\"execute\"]/src:parameter_list/src:parameter/src:decl/src:type/src:name[not(text()=\"String\")]/text()", + "//src:unit/src:class[src:name/text()=\"\" or (src:super/src:extends/src:name/text()=\"\")]/src:name/text()", + "//src:unit/src:class[src:super/src:extends/src:name/text()=\"Command\"]/src:block/src:class/src:block/descendant-or-self::src:decl_stmt/src:decl[src:init/src:expr/src:call/src:name/text()=\"\"]"] }, { - "index": 11, + "index": "11", "title": "@Entity classes must be registered in the CrowdServlet class", "description": "IF a class is an Entity class or subclass \nTHEN it must be registered in 'CrowdServlet' class by ObjectifyService.\nAll entities needs to be registered with Objectify, so that Objectify knows to persist them. The registration must be done in 'CrowdServlet.java'", "tags": [ "Entity", "Objectify", "Persistence" ], - "ruleType": { - "constraint": "FOLDER", - "checkFor": [ - "src/com/crowdcoding/entities", - "src/com/crowdcoding/servlets" - ], - "type": "MIXED" - }, - "quantifier": { - "detail": "Entity classes", - "command": "//src:unit/src:class[(src:annotation/src:name[text()=\"Entity\"] or src:annotation/src:name[text()=\"Subclass\"])]" - }, - "constraint": { - "type": "FIND_FROM_TEXT", - "detail": "Registered classes", - "command1": "//src:unit/src:class[src:name/text()=\"CrowdServlet\"]//src:expr_stmt/src:expr/src:call[src:name/src:name/text()=\"ObjectifyService\" and src:name/src:name/text()=\"register\"]/src:argument_list/src:argument/src:expr/src:name/src:name[1]/text()", - "command2": "//src:unit/src:class[src:name/text()=\"\"]" - } + "checkForFilesFolders": [ + "src/com/crowdcoding/entities", "src/com/crowdcoding/servlets" + ], + "checkForFilesFoldersConstraints": "INCLUDE", + "processFilesFolders": "MIXED", + // Entity classes + "quantifierXPathQuery": ["//src:unit/src:class[(src:annotation/src:name[text()=\"Entity\"] or src:annotation/src:name[text()=\"Subclass\"])]"] + "constraintQueryType": "FIND_FROM_TEXT", + // Registered classes + "constraintXPathQuery": ["//src:unit/src:class[src:name/text()=\"CrowdServlet\"]//src:expr_stmt/src:expr/src:call[src:name/src:name/text()=\"ObjectifyService\" and src:name/src:name/text()=\"register\"]/src:argument_list/src:argument/src:expr/src:name/src:name[1]/text()", + "//src:unit/src:class[src:name/text()=\"\"]"] } ] ``` @@ -104,13 +85,15 @@ It is mandatory but is generated for newly added rules. Here is an example for t There is also another json file named `tagJson.txt`. In this file we store information about tags. Here is an example for this file: -``` +```javascript [ { + "ID": "0", "tagName": "Labeling", "detail": "Rules about labeling the items used in the application. The labeling must follows special policies." }, { + "ID": "1", "tagName": "Objects", "detail": "Rules about object created in the application. For each object there might be some constraints and considerations." } diff --git a/src/App.js b/src/App.js index 2eaa6f1..56cb24c 100644 --- a/src/App.js +++ b/src/App.js @@ -7,12 +7,12 @@ import {connect} from "react-redux"; import WebSocketManager from "./core/webSocketManager"; import {hashChange} from "./actions"; -import TableOfContent from "./ui/tableOfContent"; +import TableOfContents from "./ui/tableOfContents"; import RuleTable from "./ui/ruleTable"; import NavBar from "./ui/navBar"; import HeaderBar from "./ui/headerBar"; -import MinedRulesComponent from "./ui/minedRulesComponent"; -import FeatureSelection from "./ui/FeatureSelection"; +import MinedRulesComponent from "./ui/MiningRules/minedRulesComponent"; +import FeatureSelection from "./ui/MiningRules/featureSelection"; class App extends Component { @@ -64,25 +64,25 @@ class App extends Component {
- +
@@ -97,7 +97,7 @@ class App extends Component { // map state to props function mapStateToProps(state) { return { - hash: state["hash"] + currentHash: state.currentHash } } diff --git a/src/actions.js b/src/actions.js index eff9bbf..2b4349f 100644 --- a/src/actions.js +++ b/src/actions.js @@ -1,51 +1,144 @@ // action creator +/** + * If the hash is #/hash1/hash2 + * @param hash array of hashes ["hash1", "hash2"] + * @return {{data: {hash: array}, type: string}} + */ export const hashChange = (hash) => { - return {type: "HASH", value: hash}; + return { + type: "HASH", + data: + {currentHash: hash} + }; }; +/** + * @param ws + * @return {{data: {ws: *}, type: string}} + */ export const updateWS = (ws) => { - return {type: "NEW_WS", value: ws}; + return { + type: "NEW_WS", + data: + {ws: ws} + }; }; +/** + * @param xmlFiles + * @return {{data: {xmlFiles: []}, type: string}} + */ export const updateXmlFiles = (xmlFiles) => { return { type: "UPDATE_XML_FILES", - xmlFiles: xmlFiles + data: + {xmlFiles: xmlFiles} } }; +/** + * @param newTagTable + * @return {{data: {tagTable: []}, type: string}} + */ export const updateTagTable = (newTagTable) => { - return {type: "UPDATE_TAG_TABLE", value: newTagTable}; + return { + type: "UPDATE_TAG_TABLE", + data: {tagTable: newTagTable} + }; }; +/** + * @param newRuleTable + * @return {{data: {ruleTable: []}, type: string}} + */ export const updateRuleTable = (newRuleTable) => { - return {type: "UPDATE_RULE_TABLE", ruleTable: newRuleTable}; + return { + type: "UPDATE_RULE_TABLE", + data: {ruleTable: newRuleTable} + }; +}; + + +export const updateRule = () => { + return {type: "UPDATE_RULE"}; +}; + + +export const submitNewRule = () => { + return {type: "SUBMIT_NEW_RULE"} }; -export const updateRule = (updatedRule) => { - return {type: "UPDATE_RULE", updatedRule: updatedRule}; + +export const submitNewTag = () => { + return {type: "SUBMIT_NEW_TAG"} }; +/** + * @param hierarchyData + * @return {{data: {hierarchyData: *}, type: string}} + */ export const updateProjectHierarchyData = (hierarchyData) => { - return {type: "HIERARCHY_DATA", hierarchyData: hierarchyData}; + return { + type: "HIERARCHY_DATA", + data: {hierarchyData: hierarchyData} + }; +}; + +/** + * @param projectPath string + * @return {{data: {projectPath: string}, type: string}} + */ +export const updateProjectPath = (projectPath) => { + return { + type: "PROJECT_PATH", + data: {projectPath: projectPath} + } }; +/* + file Handling + */ -export const ignoreFile = (shouldIgnore) => { - return {type: "IGNORE_FILE", shouldIgnore: shouldIgnore}; +/** + * + * @param shouldIgnore boolean + * @return {{data: {shouldIgnore: boolean}, type: string}} + */ +export const ignoreFileChange = (shouldIgnore) => { + return { + type: "IGNORE_FILE_CHANGE", + data: {shouldIgnore: shouldIgnore} + }; }; +/** + * @param shouldDisplay boolean + * @return {{data: {shouldDisplay: boolean}, type: string}} + */ export const updateDisplayEditTutorial = (shouldDisplay) => { - return {type: "UPDATE_DISPLAY_EDIT_TUTORIAL", shouldDisplay: shouldDisplay}; + return { + type: "UPDATE_DISPLAY_EDIT_TUTORIAL", + data: {shouldDisplay: shouldDisplay} + }; }; - +/** + * @param filePath + * @return {{data: {openFilePath: string}, type: string}} + */ export const updateFilePath = (filePath) => { - return {type: "FILE_PATH", value: filePath}; + return { + type: "FILE_PATH_UPDATED", + data: {openFilePath: filePath} + }; }; +/* + nav-bar navigation + */ + export const clickedOnForward = () => { return {type: "CLICKED_ON_FORWARD"}; @@ -55,117 +148,206 @@ export const clickedOnBack = () => { return {type: "CLICKED_ON_BACK"}; }; +/* + RulePad + */ -export const submitNewRule = (newRuleProps) => { - return {type: "SUBMIT_NEW_RULE", value: newRuleProps} -}; - -export const submitNewTag = (newTagProps) => { - return {type: "SUBMIT_NEW_TAG", value: newTagProps} -}; export const clearNewRuleForm = () => { return {type: "CLEAR_NEW_RULE_FORM"} }; +/** + * @param ruleIndex number + * @param title string + * @param description string + * @param ruleTags array[string] + * @param folderConstraint string + * @param filesFolders array[string] + * @return {{data: {ruleIndex: *, ruleTags: *, filesFolders: *, description: *, title: *, folderConstraint: *}, type: string}} + */ export const editRuleForm = (ruleIndex, title, description, ruleTags, folderConstraint, filesFolders) => { return { type: "EDIT_RULE_FORM", - ruleIndex: ruleIndex, - title: title, - description: description, - ruleTags: ruleTags, - folderConstraint: folderConstraint, - filesFolders: filesFolders + data: { + ruleIndex: ruleIndex, + title: title, + description: description, + ruleTags: ruleTags, + folderConstraint: folderConstraint, + filesFolders: filesFolders + } } }; +/** + * @param ruleIndex number + * @param newEditMode boolean + * @return {{data: {ruleIndex: *, newEditMode: *}, type: string}} + */ export const changeEditMode = (ruleIndex, newEditMode) => { - return {type: "CHANGE_EDIT_MODE", ruleIndex: ruleIndex, newEditMode: newEditMode} + return { + type: "CHANGE_EDIT_MODE", + data: {ruleIndex: ruleIndex, newEditMode: newEditMode} + } }; +/** + * @param ruleIndex number + * @param newTreeData * + * @param autoCompleteArray array[{id: "", word: ""}] + * @param quantifierXPath string + * @param constraintXPath string + * @return {{data: {ruleIndex: *, newTreeData: *, quantifierXPath: *, constraintXPath: *, autoCompleteArray: *}, type: string}} + */ export const receiveGuiTree = (ruleIndex, newTreeData, autoCompleteArray, quantifierXPath, constraintXPath) => { return { type: "RECEIVE_GUI_TREE", - ruleIndex: ruleIndex, - newTreeData: newTreeData, - autoCompleteArray: autoCompleteArray, - quantifierXPath: quantifierXPath, - constraintXPath: constraintXPath + data: { + ruleIndex: ruleIndex, + newTreeData: newTreeData, + autoCompleteArray: autoCompleteArray, + quantifierXPath: quantifierXPath, + constraintXPath: constraintXPath + } }; }; export const sendExpressionStatementXML = (codeTextAndIDData) => { - return {type: "SEND_EXPR_STMT_XML", codeTextAndID: codeTextAndIDData} + return { + type: "SEND_EXPR_STMT_XML", + data: {codeTextAndID: codeTextAndIDData} + } }; export const receiveExpressionStatementXML = (xmlData) => { - return {type: "RECEIVE_EXPR_STMT_XML", xmlData: xmlData} + return { + type: "RECEIVE_EXPR_STMT_XML", + data: {xmlData: xmlData} + } }; -// messages are matched and XPaths are modified based on the received messages +/** + * messages are matched and XPaths are modified based on the received messages + * @param ruleIndex number + * @param sentMessages array[**] + * @param receivedMessages array[**] + * @param quantifierXPath string + * @param constraintXPath string + * @return {{data: {ruleIndex: *, receivedMessages: *, quantifierXPath: *, constraintXPath: *, sentMessages: *}, type: string}} + */ export const matchMessages = (ruleIndex, sentMessages, receivedMessages, quantifierXPath, constraintXPath) => { return { type: "MATCHED_MESSAGES", - ruleIndex: ruleIndex, - sentMessages: sentMessages, - receivedMessages: receivedMessages, - quantifierXPath: quantifierXPath, - constraintXPath: constraintXPath + data: { + ruleIndex: ruleIndex, + sentMessages: sentMessages, + receivedMessages: receivedMessages, + quantifierXPath: quantifierXPath, + constraintXPath: constraintXPath + } } }; -// tasks is an array of form [{elementId: "", task: "ADD_EXTRA/REMOVE_EXTRA/UPDATE_ELEMENT", value}] -// for add/remove we have the children group name as value -// for update we have an object {prop: newValue} + +/** + * tasks is an array of form [{elementId: "", task: "ADD_EXTRA/REMOVE_EXTRA/UPDATE_ELEMENT", value}] + * for add/remove we have the children group name as value + * for update we have an object {prop: newValue} + * @param ruleIndex number + * @param tasks array [**] + * @return {{ruleIndex: *, type: string, tasks: *}} + */ export const changeGuiElement = (ruleIndex, tasks) => { return { type: "CHANGE_GUI_ELEMENT", - ruleIndex: ruleIndex, - tasks: tasks + data: { + ruleIndex: ruleIndex, + tasks: tasks + } }; }; +/** + * @param ruleIndex number + * @param newAutoCompleteArray array[{id: "", word: ""}] + * @return {{data: {newAutoCompleteArray: *, ruleIndex: *}, type: string}} + */ export const changeAutoCompleteTextFromGUI = (ruleIndex, newAutoCompleteArray) => { return { type: "CHANGE_AUTOCOMPLETE_TEXT_FROM_GUI", - ruleIndex: ruleIndex, - newAutoCompleteArray: newAutoCompleteArray + data: { + ruleIndex: ruleIndex, + newAutoCompleteArray: newAutoCompleteArray + } }; }; export const updateXPaths = (ruleIndex, quantifierXPath, constraintXPath) => { return { type: "UPDATE_XPATHS", - ruleIndex: ruleIndex, - quantifierXPath: quantifierXPath, - constraintXPath: constraintXPath + data: { + ruleIndex: ruleIndex, + quantifierXPath: quantifierXPath, + constraintXPath: constraintXPath + } } }; +/* + Mining Rules + */ + +/** + * @param metaData ** + * @return {{data: {metaData: *}, type: string}} + */ export const updateMetaData = (metaData) => { return { type: "UPDATE_META_DATA", - metaData: metaData + data: {metaData: metaData} } }; +/** + * @param minedRules ** + * @return {{data: {minedRules: *}, type: string}} + */ export const updatedMinedRules = (minedRules) => { return { type: "UPDATE_MINED_RULES", - minedRules: minedRules + data: {minedRules: minedRules} + } +}; + + +// not recommended +/** + * @param metaData ** + * @param minedRules ** + * @return {{data: {metaData: *, minedRules: *}, type: string}} + */ +export const updateDangerousMinedRules = (metaData, minedRules) => { + return { + type: "DANGEROUS_MINED_RULES", + data: { + metaData: metaData, + minedRules: minedRules + } } }; /** - * @param dataObject : filePath, startOffset, endOffset, startLineOffset, lineNumber, lineText, selectedText, + * + * @param dataObject filePath, startOffset, endOffset, startLineOffset, lineNumber, lineText, selectedText, * xpath, modifiedSelectedText, idMap, displayTextArray + * @return {{data, type: string}} */ export const updateFeatureSelection = (dataObject) => { return { type: "UPDATE_FEATURE_SELECTION", - ...dataObject + data: {...dataObject} } }; @@ -175,19 +357,15 @@ export const updateResetFeatureSelection = () => { } }; +/** + * @param featureDescription string + * @param featureXpath string + * @return {{data: {featureDescription: *, featureXpath: *}, type: string}} + */ export const updateSaveFeatureSelection = (featureDescription, featureXpath) => { return { type: "SAVE_FEATURE_SELECTION", - featureDescription, featureXpath + data: {featureDescription, featureXpath} } }; - -// not recommended -export const updateDangerousMinedRules = (metaData, minedRules) => { - return { - type: "DANGEROUS_MINED_RULES", - metaData: metaData, - minedRules: minedRules - } -}; \ No newline at end of file diff --git a/src/core/coreConstants.js b/src/core/coreConstants.js new file mode 100644 index 0000000..9a8c418 --- /dev/null +++ b/src/core/coreConstants.js @@ -0,0 +1,46 @@ +export const webSocketSendMessage = { + modified_rule_msg: "MODIFIED_RULE", + modified_tag_msg: "MODIFIED_TAG", + snippet_xml_msg: "XML_RESULT", + code_to_xml_msg: "EXPR_STMT", + new_rule_msg: "NEW_RULE", + new_tag_msg: "NEW_TAG", + + learn_rules_metadata_msg: "LEARN_RULES_META_DATA", + learn_rules_file_location_msg: "LEARN_RULES_FILE_LOCATIONS", + learn_rules_databases_msg: "LEARN_RULES_DATABASES", + execute_tnr_msg: "EXECUTE_TNR", + execute_fp_max_msg: "EXECUTE_FP_MAX", + open_file_mined_rules: "OPEN_FILE", + dangerous_read_mined_rules_msg: "DANGEROUS_READ_MINED_RULES" + +}; + +export const webSocketReceiveMessage = { + xml_files_msg: "XML", + rule_table_msg: "RULE_TABLE", + tag_table_msg: "TAG_TABLE", + project_hierarchy_msg: "PROJECT_HIERARCHY", + project_path_msg: "PROJECT_PATH", + verify_rules_msg: "VERIFY_RULES", + update_xml_file_msg: "UPDATE_XML", + check_rules_for_file_msg: "CHECK_RULES_FOR_FILE", + update_tag_msg: "UPDATE_TAG", + failed_update_tag_msg: "FAILED_UPDATE_TAG", + update_rule_msg: "UPDATE_RULE", + failed_update_rule_msg: "FAILED_UPDATE_RULE", + xml_from_code_msg: "EXPR_STMT_XML", + new_rule_msg: "NEW_RULE", + failed_new_rule_msg: "FAILED_NEW_RULE", + new_tag_msg: "NEW_TAG", + failed_new_tag_msg: "FAILED_NEW_TAG", + file_change_in_ide_msg: "FILE_CHANGE", + + tnr_output_msg: "", + fp_max_output_msg: "", + feature_selection_msg: "", + dangerous_read_mined_rules_msg: "DANGEROUS_READ_MINED_RULES", + + enter_chat_msg: "ENTER", + left_chat_msg: "LEFT" +}; \ No newline at end of file diff --git a/src/core/generateXpath.js b/src/core/generateXPath.js similarity index 99% rename from src/core/generateXpath.js rename to src/core/generateXPath.js index 8504005..271d27a 100644 --- a/src/core/generateXpath.js +++ b/src/core/generateXPath.js @@ -6,8 +6,9 @@ import {TerminalNodeImpl} from "antlr4/tree/Tree"; import Utilities from "./utilities"; import store from "../reduxStore"; import {sendExpressionStatementXML} from "../actions"; +import {webSocketSendMessage} from "./coreConstants"; -class GenerateXpath { +class GenerateXPath { /** * @param Tree: tree produced by ANTLR parser @@ -905,7 +906,7 @@ class GenerateXpath { } - Utilities.sendToServer(this.ws, "EXPR_STMT", {"codeText": code, "messageID": messageID}); + Utilities.sendToServer(this.ws, webSocketSendMessage.code_to_xml_msg, {"codeText": code, "messageID": messageID}); store.dispatch(sendExpressionStatementXML({ "codeText": code, "messageID": messageID, @@ -916,4 +917,4 @@ class GenerateXpath { } } -export default GenerateXpath; \ No newline at end of file +export default GenerateXPath; \ No newline at end of file diff --git a/src/core/languageProcessing.js b/src/core/languageProcessing.js index 2988735..d1af77b 100644 --- a/src/core/languageProcessing.js +++ b/src/core/languageProcessing.js @@ -1,7 +1,7 @@ import antlr4 from "antlr4/index"; import posTagger from "wink-pos-tagger"; -import Traverse from "./generateXpath"; +import Traverse from "./generateXPath"; /** diff --git a/src/core/ruleExecutor.js b/src/core/ruleExecutor.js index 2313f50..fead576 100644 --- a/src/core/ruleExecutor.js +++ b/src/core/ruleExecutor.js @@ -80,7 +80,7 @@ export const checkRulesForFile = (xmlFiles, ruleTable, filePath) => { /** * find relevant xml files based on the rule "checkFor" property - * and call respective methods based on "ruleType" property of the rule. + * and call respective methods based on "processFilesFolders" property of the rule. * @param xmlFiles * @param ruleI * @returns ruleI @@ -88,87 +88,46 @@ export const checkRulesForFile = (xmlFiles, ruleTable, filePath) => { export const runRulesByTypes = (xmlFiles, ruleI) => { let xmlFilesToVerify = []; - let checkForFiles = ruleI["ruleType"]["checkFor"].slice(0); // deep copy + let checkForFilesFolders = ruleI["checkForFilesFolders"].slice(0); // deep copy - switch (ruleI["ruleType"]["constraint"]) { + switch (ruleI["checkForFilesFoldersConstraints"]) { case "NONE": xmlFilesToVerify = xmlFiles.slice(0); // deep copy break; - case "SOME": - for (let j = 0; j < checkForFiles.length; j++) - // Warning - // This can lead to error if fileName is saved as X.java in ruleJson.txt and there exists also aX.java - xmlFilesToVerify = xmlFilesToVerify.concat(xmlFiles.filter((d) => d["filePath"].endsWith(checkForFiles[j]))); - break; - - case "EXCEPT": - xmlFilesToVerify = xmlFiles.filter((d) => { - for (let j = 0; j < checkForFiles.length; j++) - // Warning - // This can lead to error if fileName is saved as X.java in ruleJson.txt and there exists also aX.java - if (d["filePath"].endsWith(checkForFiles[j])) { - checkForFiles.splice(j, 1); - return false; - } - return true; - }); - break; - - case "FOLDER": - for (let j = 0; j < checkForFiles.length; j++) + case "INCLUDE": + for (let j = 0; j < checkForFilesFolders.length; j++) // Warning // This can lead to error if the target folder is X in ruleJson.txt and there exists also a folder Xy - xmlFilesToVerify = xmlFilesToVerify.concat(xmlFiles.filter((d) => d["filePath"].indexOf(checkForFiles[j]) !== -1)); + xmlFilesToVerify = xmlFilesToVerify.concat(xmlFiles.filter((d) => d["filePath"].indexOf(checkForFilesFolders[j]) !== -1)); break; - case "FOLDER EXCEPT": - for (let j = 0; j < checkForFiles[0].length; j++) - // Warning - // This can lead to error if the target folder is X in ruleJson.txt and there exists also a folder Xy - xmlFilesToVerify = xmlFilesToVerify.concat(xmlFiles.filter((d) => d["filePath"].indexOf(checkForFiles[0][j]) !== -1)); - + case "EXCLUDE": xmlFilesToVerify = xmlFilesToVerify.filter((d) => { - for (let j = 0; j < checkForFiles[1].length; j++) + for (let j = 0; j < checkForFilesFolders.length; j++) // Warning // This can lead to error if fileName is saved as X.java in ruleJson.txt and there exists also aX.java - if (d["filePath"].endsWith(checkForFiles[1][j])) + if (d["filePath"].endsWith(checkForFilesFolders[j])) return false; return true; }); break; - case "FOLDER SOME": - for (let j = 0; j < checkForFiles[0].length; j++) - // Warning - // This can lead to error if the target folder is X in ruleJson.txt and there exists also a folder Xy - xmlFilesToVerify = xmlFilesToVerify.concat(xmlFiles.filter((d) => d["filePath"].indexOf(checkForFiles[0][j]) !== -1)); - - xmlFilesToVerify = xmlFilesToVerify.filter((d) => { - for (let j = 0; j < checkForFiles[1].length; j++) - // Warning - // This can lead to error if fileName is saved as X.java in ruleJson.txt and there exists also aX.java - if (d["filePath"].endsWith(checkForFiles[1][j])) - return true; - return false; - }); - break; - default: console.log("error in XML: ruleTable[index=" + ruleI["index"] + "]['constraint']"); return ruleI; } - if (ruleI["ruleType"]["type"] === "WITHIN") { + if (ruleI["processFilesFolders"] === "WITHIN") { for (let j = 0; j < xmlFilesToVerify.length; j++) ruleI = runXPathQueryWithin(xmlFilesToVerify[j], ruleI); } - else if (ruleI["ruleType"]["type"] === "BETWEEN") { + else if (ruleI["processFilesFolders"] === "BETWEEN") { ruleI = runXpathQueryBetween(xmlFilesToVerify, ruleI); } - else if (ruleI["ruleType"]["type"] === "MIXED") { + else if (ruleI["processFilesFolders"] === "MIXED") { ruleI = runXpathQueryMixed(xmlFilesToVerify, ruleI); } @@ -187,8 +146,8 @@ export const runRulesByTypes = (xmlFiles, ruleI) => { */ const runXPathQueryWithin = (xmlFile, ruleI) => { - let quantifierResult = runXPathQuery(xmlFile, ruleI, "quantifier"); - let satisfiedResult = runXPathQuery(xmlFile, ruleI, "constraint"); + let quantifierResult = runXPathQuery(xmlFile, ruleI.quantifierXPathQuery[0]); + let satisfiedResult = runXPathQuery(xmlFile, ruleI.constraintXPathQuery[0]); // compare results let violatedResult = violatedResults(quantifierResult, satisfiedResult); @@ -236,8 +195,8 @@ const runXpathQueryBetween = (xmlFiles, ruleI) => { let quantifierResult = []; let constraintResult = []; for (let j = 0; j < xmlFiles.length; j++) { - quantifierResult = quantifierResult.concat(runXPathQuery(xmlFiles[j], ruleI, "quantifier")); - constraintResult = constraintResult.concat(runXPathQuery(xmlFiles[j], ruleI, "constraint")); + quantifierResult = quantifierResult.concat(runXPathQuery(xmlFiles[j], ruleI.quantifierXPathQuery[0])); + constraintResult = constraintResult.concat(runXPathQuery(xmlFiles[j], ruleI.constraintXPathQuery[0])); } // compare results let violatedResult = violatedResults(quantifierResult, constraintResult); @@ -261,7 +220,7 @@ const runXpathQueryBetween = (xmlFiles, ruleI) => { /** - * run Xpath query when a group has multiple commands + * run Xpath query when a group has multiple XPath queries * @param xmlFiles * @param ruleI * @returns {*} @@ -271,26 +230,22 @@ const runXpathQueryMixed = (xmlFiles, ruleI) => { let quantifierResult = []; let constraintResult = []; - if (ruleI["quantifier"].hasOwnProperty("type") && ruleI["quantifier"]["type"] === "FIND_FROM_TEXT") - quantifierResult = findFromText(xmlFiles, ruleI, "quantifier"); - else if (ruleI["quantifier"].hasOwnProperty("type") && ruleI["quantifier"]["type"] === "RETURN_TO_BASE") - quantifierResult = findAndReturnToBase(xmlFiles, ruleI, "quantifier"); + if (ruleI.hasOwnProperty("quantifierQueryType") && ruleI["quantifierQueryType"] === "FIND_FROM_TEXT") + quantifierResult = findFromText(xmlFiles, ruleI.quantifierXPathQuery); + else if (ruleI.hasOwnProperty("quantifierQueryType") && ruleI["quantifierQueryType"] === "RETURN_TO_BASE") + quantifierResult = findAndReturnToBase(xmlFiles, ruleI.quantifierXPathQuery); else for (let j = 0; j < xmlFiles.length; j++) - quantifierResult = quantifierResult.concat(runXPathQuery(xmlFiles[j], ruleI, "quantifier")); + quantifierResult = quantifierResult.concat(runXPathQuery(xmlFiles[j], ruleI.quantifierXPathQuery[0])); - if (ruleI["constraint"].hasOwnProperty("type") && ruleI["constraint"]["type"] === "FIND_FROM_TEXT") - constraintResult = findFromText(xmlFiles, ruleI, "constraint"); - else if (ruleI["constraint"].hasOwnProperty("type") && ruleI["constraint"]["type"] === "RETURN_TO_BASE") - constraintResult = findAndReturnToBase(xmlFiles, ruleI, "constraint"); + if (ruleI.hasOwnProperty("constraintQueryType") && ruleI["constraintQueryType"] === "FIND_FROM_TEXT") + constraintResult = findFromText(xmlFiles, ruleI.constraintXPathQuery); + else if (ruleI.hasOwnProperty("constraintQueryType") && ruleI["constraintQueryType"] === "RETURN_TO_BASE") + constraintResult = findAndReturnToBase(xmlFiles, ruleI.constraintXPathQuery); else for (let j = 0; j < xmlFiles.length; j++) - constraintResult = constraintResult.concat(runXPathQuery(xmlFiles[j], ruleI, "constraint")); - - - // console.log(ruleI["quantifier"], quantifierResult); - // console.log(ruleI["constraint"], constraintResult); + constraintResult = constraintResult.concat(runXPathQuery(xmlFiles[j], ruleI.constraintXPathQuery[0])); // compare results @@ -315,54 +270,51 @@ const runXpathQueryMixed = (xmlFiles, ruleI) => { /** - * When a group consists of two commands, the first command + * When a group consists of two XPath queries, the first query * @param xmlFiles - * @param ruleIOrg - * @param group + * @param xpathQueries * @returns {Array} */ -const findFromText = (xmlFiles, ruleIOrg, group) => { +const findFromText = (xmlFiles, xpathQueries) => { let result1 = [], result2 = []; - let ruleI = Utilities.cloneJSON(ruleIOrg); - ruleI[group]["command"] = ruleI[group]["command1"]; + let xpathQuery = xpathQueries[0]; for (let j = 0; j < xmlFiles.length; j++) { - result1 = result1.concat(runXPathQuery(xmlFiles[j], ruleI, group)); + result1 = result1.concat(runXPathQuery(xmlFiles[j], xpathQuery)); } for (let i = 0; i < result1.length; i++) { - ruleI[group]["command"] = ruleI[group]["command2"].replace("", result1[i].snippet); + xpathQuery = xpathQueries[1].replace("", result1[i].snippet); for (let j = 0; j < xmlFiles.length; j++) { - result2 = result2.concat(runXPathQuery(xmlFiles[j], ruleI, group)); + result2 = result2.concat(runXPathQuery(xmlFiles[j], xpathQuery)); } } return result2; }; + /** - * When a group consists of tree commands, the first and last command is on the same file + * When a group consists of 3 queries, the first and last queries are executed on the same file * @param xmlFiles - * @param ruleIOrg - * @param group + * @param xpathQueries * @returns {Array} */ -const findAndReturnToBase = (xmlFiles, ruleIOrg, group) => { +const findAndReturnToBase = (xmlFiles, xpathQueries) => { let result1, result2, result3 = []; - let ruleI = Utilities.cloneJSON(ruleIOrg); for (let base = 0; base < xmlFiles.length; base++) { - ruleI[group]["command"] = ruleI[group]["command1"]; - result1 = runXPathQuery(xmlFiles[base], ruleI, group); + let xpathQuery = xpathQueries[0]; + result1 = runXPathQuery(xmlFiles[base], xpathQuery); for (let i = 0; i < result1.length; i++) { for (let j = 0; j < xmlFiles.length; j++) { - ruleI[group]["command"] = ruleI[group]["command2"].replace(new RegExp("", "g"), result1[i].snippet); - result2 = runXPathQuery(xmlFiles[j], ruleI, group); + xpathQuery = xpathQueries[1].replace(new RegExp("", "g"), result1[i].snippet); + result2 = runXPathQuery(xmlFiles[j], xpathQuery); for (let k = 0; k < result2.length; k++) { - ruleI[group]["command"] = ruleI[group]["command3"].replace("", result2[k].snippet); - result3 = result3.concat(runXPathQuery(xmlFiles[base], ruleI, group)); + xpathQuery = xpathQueries[2].replace("", result2[k].snippet); + result3 = result3.concat(runXPathQuery(xmlFiles[base], xpathQuery)); } } @@ -375,10 +327,9 @@ const findAndReturnToBase = (xmlFiles, ruleIOrg, group) => { /** * runs the XPath query and compare results * @param xmlFile - * @param ruleI - * @param group either "quantifier" or "constraint" + * @param xpathQuery */ -const runXPathQuery = (xmlFile, ruleI, group) => { +const runXPathQuery = (xmlFile, xpathQuery) => { let parser = new DOMParser(); let result = []; @@ -395,23 +346,17 @@ const runXPathQuery = (xmlFile, ruleI, group) => { } // run xpath queries - let quantifierNodes = xml.evaluate(ruleI[group]["command"], xml, nsResolver, XPathResult.ANY_TYPE, null); - // let quantifierNameNodes = xml.evaluate(ruleI[group]["command"], xml, nsResolver, XPathResult.ANY_TYPE, null); - let resultQNode = quantifierNodes.iterateNext(); - // let resultQNameNode = quantifierNameNodes.iterateNext(); + let foundNodes = xml.evaluate(xpathQuery, xml, nsResolver, XPathResult.ANY_TYPE, null); + let node = foundNodes.iterateNext(); let index = 0; - while (resultQNode) { - let xmlAndText = getXmlData(xml, ruleI[group]["command"], index); + while (node) { + let xmlAndText = getXmlData(xml, xpathQuery, index); result.push({ "filePath": xmlFile["filePath"], - // "result": new XMLSerializer().serializeToString(resultQNode), "xml": xmlAndText.xmlJson, - // "xmlText": xmlAndText.xmlText, - // "name": resultQNameNode ? new XMLSerializer().serializeToString(resultQNameNode) : "error in xpath", "snippet": xmlAndText.snippet }); - resultQNode = quantifierNodes.iterateNext(); - // resultQNameNode = quantifierNameNodes.iterateNext(); + node = foundNodes.iterateNext(); index += 1; } @@ -578,13 +523,11 @@ const isValidXPathQueries = (ruleI) => { return ns[prefix] || null; } try { - let listOfCommandsQ = Object.keys(ruleI["quantifier"]).filter(d => d.startsWith("command")); - for (let li of listOfCommandsQ) - xml.evaluate(ruleI["quantifier"][li], xml, nsResolver, XPathResult.ANY_TYPE, null); + for (let i=0; i< ruleI.quantifierXPathQuery.length; i++) + xml.evaluate(ruleI.quantifierXPathQuery[i], xml, nsResolver, XPathResult.ANY_TYPE, null); - let listOfCommandsC = Object.keys(ruleI["quantifier"]).filter(d => d.startsWith("command")); - for (let li of listOfCommandsC) - xml.evaluate(ruleI["constraint"][li], xml, nsResolver, XPathResult.ANY_TYPE, null); + for (let i=0; i< ruleI.constraintXPathQuery.length; i++) + xml.evaluate(ruleI.constraintXPathQuery[i], xml, nsResolver, XPathResult.ANY_TYPE, null); } catch (XPathException) { return false; diff --git a/src/core/utilities.js b/src/core/utilities.js index ec48d84..5642714 100644 --- a/src/core/utilities.js +++ b/src/core/utilities.js @@ -1,6 +1,7 @@ /** * Created by saharmehrpour on 9/8/17. */ +import {webSocketSendMessage} from "./coreConstants"; class Utilities { @@ -12,94 +13,97 @@ class Utilities { * @param data */ static sendToServer(ws, command, data) { - let messageJson = {"source": "WEB", "destination": "IDEA", "command": command}; + let messageJson = {source: "WEB", destination: "IDEA", command: command}; if (ws) { switch (command) { - case "MODIFIED_RULE": - messageJson["data"] = { - "index": data.index, - "ruleText": data + case webSocketSendMessage.modified_rule_msg: + messageJson.data = { + ruleID: data.index, + ruleInfo: data }; break; - case "MODIFIED_TAG": - messageJson["data"] = { - "tagName": data.tagName, - "tagText": data + case webSocketSendMessage.modified_tag_msg: + messageJson.data = { + tagID: data.ID, + tagInfo: data }; break; - case "XML_RESULT": - messageJson["data"] = data; - break; - - case "EXPR_STMT": - messageJson["data"] = data; // {codeText: "", messageID: ""} + case webSocketSendMessage.snippet_xml_msg: + messageJson.data = { + fileName: data.fileName, + xml: data.xml + }; break; - case "DECL_STMT": - messageJson["data"] = data; + case webSocketSendMessage.code_to_xml_msg: + messageJson.data = { + codeText: data.codeText, + messageID: data.messageID + }; break; - case "NEW_RULE": - messageJson["data"] = { - "index": data.index, - "ruleText": data + case webSocketSendMessage.new_rule_msg: + messageJson.data = { + ruleID: data.index, + ruleInfo: data }; break; - case "NEW_TAG": - messageJson["data"] = { - "tagName": data.tagName, - "tagText": data + case webSocketSendMessage.new_tag_msg: + messageJson.data = { + tagID: data.ID, + tagInfo: data }; break; - case "LEARN_RULES_META_DATA": + /* mining rules */ + + case webSocketSendMessage.learn_rules_metadata_msg: if (data.content.length > this.BREAK_LINE) { this.sendChunkedData(messageJson, data.content.slice(0), data.fileName, ws); return; } - messageJson["data"] = [[data.fileName, data.content]]; + messageJson.data = [[data.fileName, data.content]]; break; - case "LEARN_RULES_FILE_LOCATIONS": + case webSocketSendMessage.learn_rules_file_location_msg: if (data.content.length > this.BREAK_LINE) { this.sendChunkedData(messageJson, data.content.slice(0), data.fileName, ws); return; } - messageJson["data"] = [[data.fileName, data.content]]; + messageJson.data = [[data.fileName, data.content]]; break; - case "LEARN_RULES_DATABASES": + case webSocketSendMessage.learn_rules_databases_msg: if (data[0][1].length > this.BREAK_LINE) { this.sendChunkedData(messageJson, data[0][1].slice(0), data[0][0], ws); return; } - messageJson["data"] = data; // array of arrays: [["file_name.txt", "data to be written"]] + messageJson.data = data; // array of arrays: [["file_name.txt", "data to be written"]] break; - case "EXECUTE_TNR": - messageJson["data"] = { + case webSocketSendMessage.execute_tnr_msg: + messageJson.data = { confidence: data.tnrConfidence, // double k: data.tnrK, //int delta: data.tnrDelta // int }; break; - case "EXECUTE_FP_MAX": - messageJson["data"] = data.fpMaxSupport; // support + case webSocketSendMessage.execute_fp_max_msg: + messageJson.data = data.fpMaxSupport; // support break; - case "OPEN_FILE": - messageJson["command"] = "XML_RESULT"; // there is no separate command in the server - messageJson["data"] = { + case webSocketSendMessage.open_file_mined_rules: + messageJson.command = webSocketSendMessage.snippet_xml_msg; // there is no separate command in the server + messageJson.data = { fileName: data, xml: "\n" + "" }; break; - case "DANGEROUS_READ_MINED_RULES": - messageJson["command"] = "DANGEROUS_READ_MINED_RULES"; + case webSocketSendMessage.dangerous_read_mined_rules_msg: break; default: @@ -122,7 +126,7 @@ class Utilities { messageJson["command"] += "_APPEND"; let start = 0; let cnt = 0; while (start < initData.length) { - messageJson["data"] = [[fileName, initData.substring(start, Math.min(start + this.BREAK_LINE, initData.length))]]; + messageJson.data = [[fileName, initData.substring(start, Math.min(start + this.BREAK_LINE, initData.length))]]; messageJson["part"] = cnt; // only for debugging ws.send(JSON.stringify(messageJson)); start += this.BREAK_LINE; @@ -163,7 +167,7 @@ class Utilities { } /** - * deep copy of an xml variable + * deep copy of an xml data * @param xml * @returns {Document} */ @@ -183,7 +187,7 @@ class Utilities { } /** - * deep copy of a JSON variable + * deep copy of a JSON data * @param json * @returns */ @@ -197,7 +201,7 @@ class Utilities { } /** - * check whether one arrays contains all elements of the other array + * check whether one array contains all elements of the other array * @param container * @param arr * @returns {boolean} diff --git a/src/core/webSocketManager.js b/src/core/webSocketManager.js index c341e67..14f3ed7 100644 --- a/src/core/webSocketManager.js +++ b/src/core/webSocketManager.js @@ -6,35 +6,30 @@ import {Component} from "react"; import {connect} from "react-redux"; import { - receiveExpressionStatementXML, ignoreFile, updateFilePath, updateRuleTable, updateTagTable, + receiveExpressionStatementXML, ignoreFileChange, updateFilePath, updateRuleTable, updateTagTable, updateWS, updateXmlFiles, updateProjectHierarchyData, updatedMinedRules, updateFeatureSelection, - updateDangerousMinedRules + updateDangerousMinedRules, updateProjectPath } from "../actions"; import {checkRulesForAll, checkRulesForFile, runRulesByTypes} from "./ruleExecutor"; import {parseGrouping} from "../miningRulesCore/parseGrouping"; import {getXpathForFeature} from "../miningRulesCore/findingFeature"; import {dangerousParseMetaDataFile} from "../miningRulesCore/miningRules"; +import {webSocketReceiveMessage} from "./coreConstants"; class WebSocketManager extends Component { constructor(props) { super(props); - - let xml = []; // object of `filePath` and `xml` - let ruleTable = []; // retrieved from ruleJson.txt - let tagTable = []; // retrieved from tagJson.txt + let xml = []; // [{filePath: "", xml: ""}] + let ruleTable = []; + let tagTable = []; let ws = new WebSocket("ws://localhost:8887"); - let filtered; let projectPath = ""; - // PubSub.publish("NEW_WS", [ws]); this.props.onUpdateWS(ws); - ws.onopen = function () { - // PubSub.publish("NEW_CONNECTION", []); - }; - + ws.onopen = function () {}; if (!window.WebSocket) { alert("FATAL: WebSocket not natively supported. This demo will not work!"); @@ -44,76 +39,81 @@ class WebSocketManager extends Component { let message = JSON.parse(e.data); - // if (message.command !== "XML") - // console.log(message); + // if (message.command !== "XML") console.log(message); switch (message.command) { - // send initially on open - case "XML": + case webSocketReceiveMessage.xml_files_msg: + // data: {filePath: "", xml: ""} xml.push(message.data); break; - // send initially on open, when the ruleJson.txt is changed, followed by VERIFY_RULES - case "RULE_TABLE": + case webSocketReceiveMessage.rule_table_msg: + // data: [ruleTable] ruleTable = JSON.parse(message.data); this.props.onUpdateXmlFiles(xml); break; - // send initially on open, when the tagJson.txt is changed, followed by VERIFY_RULES - case "TAG_TABLE": + case webSocketReceiveMessage.tag_table_msg: + // data: [tagTable] tagTable = JSON.parse(message.data); this.props.onUpdateTagTable(tagTable); break; - case "PROJECT_HIERARCHY": - // received by projectHierarchy + case webSocketReceiveMessage.project_hierarchy_msg: + // data: {projectHierarchy} this.props.onProjectHierarchy(message.data); - projectPath = message.data.properties["canonicalPath"]; break; - case "VERIFY_RULES": - // received by RuleExecutor + case webSocketReceiveMessage.project_path_msg: + // data: projectPath + projectPath = message.data; + this.props.onProjectPathUpdate(projectPath); + break; + + case webSocketReceiveMessage.verify_rules_msg: + // data: "" ruleTable = checkRulesForAll(xml, ruleTable); this.props.onUpdateRuleTable(ruleTable); break; - // followed by CHECK_RULES_FOR_FILE - case "UPDATE_XML": - filtered = xml.filter((d) => d.filePath === message.data["filePath"]); - if (filtered.length === 0) + case webSocketReceiveMessage.update_xml_file_msg: + // data: {filePath: "", xml: ""} + let filteredXML = xml.filter((d) => d.filePath === message.data["filePath"]); + if (filteredXML.length === 0) xml.push({"filePath": message.data["filePath"], "xml": message.data["xml"]}); else - filtered[0].xml = message.data["xml"]; + filteredXML[0].xml = message.data["xml"]; this.props.onUpdateXmlFiles(xml); break; - // when the code changes, after UPDATE_XML - case "CHECK_RULES_FOR_FILE": + case webSocketReceiveMessage.check_rules_for_file_msg: + // data: "filePath" let filePath = message.data; - // received by RuleExecutor ruleTable = checkRulesForFile(xml, ruleTable, filePath); this.props.onFilePathChange(filePath.replace(projectPath, "")); this.props.onUpdateRuleTable(ruleTable); window.location.hash = "#/codeChanged"; break; - // tagName and tag - case "UPDATE_TAG": - let newTag = JSON.parse(message.data); - filtered = tagTable.filter((d) => d.tagName === newTag["tagName"]); - if (filtered.length === 0) + case webSocketReceiveMessage.update_tag_msg: + // data: {tagID: longNumber, tagInfo: {...}} + let newTag = message.data["tagInfo"]; + let filteredTag = tagTable.filter((d) => d.tagName === newTag["tagName"]); + if (filteredTag.length === 0) tagTable.push(newTag); else tagTable.filter((d) => d.tagName === newTag["tagName"])[0].detail = newTag["detail"]; window.location.hash = "#/tag/" + newTag["tagName"]; break; + case webSocketReceiveMessage.failed_update_tag_msg: + // data: {tagID: longNumber, tagInfo: {...}} + break; - // Followed after sending MODIFIED_RULE - // ruleIndex and rule - case "UPDATE_RULE": - let updatedRule = JSON.parse(message.data["rule"]); + case webSocketReceiveMessage.update_rule_msg: console.log(message.data); + // data: {ruleID: longNumber, ruleInfo: {...}} + let updatedRule = message.data["ruleInfo"]; try { let ruleIndex = -1; ruleTable.forEach((d, i) => +d.index === +updatedRule.index ? ruleIndex = i : ""); @@ -124,23 +124,17 @@ class WebSocketManager extends Component { } break; - // when the tagJson.txt changes, after TAG_TABLE - case "UPDATE_TAG_TABLE": - this.props.onUpdateTagTable(tagTable); - window.location.hash = "#/tagJsonChanged"; - break; - - // when the ruleJson.txt changes, after RULE_TABLE - case "UPDATE_RULE_TABLE": - window.location.hash = "#/ruleJsonChanged"; + case webSocketReceiveMessage.failed_update_rule_msg: + // data: {ruleID: longNumber, ruleInfo: {...}} break; - // after sending a piece of code EXPR_STMT - case "EXPR_STMT_XML": - this.props.onReceiveExprStmtXML(message.data); // {xmlText: "", messageID: ""} + case webSocketReceiveMessage.xml_from_code_msg: + // data: {xmlText: "", messageID: ""} + this.props.onReceiveExprStmtXML(message.data); break; - case "NEW_RULE": + case webSocketReceiveMessage.new_rule_msg: + // data: {ruleID: longNumber, rule: {...}} let newAddedRule = JSON.parse(message.data["rule"]); ruleTable.push(newAddedRule); // received by RuleExecutor @@ -148,39 +142,44 @@ class WebSocketManager extends Component { this.props.onUpdateRuleTable(ruleTable); break; + case webSocketReceiveMessage.failed_new_rule_msg: + // data: {ruleID: longNumber, rule: {...}} + break; - case "NEW_TAG": + case webSocketReceiveMessage.new_tag_msg: + // data: {tagID: longNumber, tag: {...}} let newAddedTag = JSON.parse(message.data["tag"]); tagTable.push(newAddedTag); this.props.onUpdateTagTable(tagTable); break; - // after sending a piece of code DECL_STMT - case "SHOW_RULES_FOR_FILE": + case webSocketReceiveMessage.failed_new_tag_msg: + // data: {tagID: longNumber, tag: {...}} + break; + + case webSocketReceiveMessage.file_change_in_ide_msg: + // data: "filePath" let focusedFilePath = message.data.replace(projectPath, ""); - if (!this.props.ignoreFile) { + if (!this.props.ignoreFileChange) { this.props.onFilePathChange(focusedFilePath); window.location.hash = "#/rulesForFile/" + focusedFilePath.replace(/\//g, "%2F"); } else this.props.onFalsifyIgnoreFile(); - break; - case "TNR_OUTPUT": + /* Mining Rules */ + + case webSocketReceiveMessage.tnr_output_msg: console.log(message.data); break; - case "FP_MAX_OUTPUT": + case webSocketReceiveMessage.fp_max_output_msg: // message.data = {"fpMaxOutput" : {0: "content of output0", ...}} let modifiedOutput = parseGrouping(Object.values(message.data["fpMaxOutput"]), this.props.minedRuleMetaData); this.props.onUpdateMinedRules(modifiedOutput); break; - case "PROJECT": - // console.log(message); - break; - - case "FEATURE_SELECTION": + case webSocketReceiveMessage.feature_selection_msg: console.log(message.data); let selected = xml.filter(d => d.filePath === message.data["path"]); if (selected.length > 0) { @@ -204,24 +203,20 @@ class WebSocketManager extends Component { break; // dangerously read output files and meta data. - case "DANGEROUS_READ_MINED_RULES": + case webSocketReceiveMessage.dangerous_read_mined_rules_msg: let metaData = dangerousParseMetaDataFile(JSON.parse(message.data["metaData"])); let outputFiles = Object.values(JSON.parse(JSON.parse(message.data["outputFiles"]))); let output = parseGrouping(outputFiles, metaData); this.props.onUpdateDangerousMinedRules(metaData, output); break; - case "ENTER": - case "LEFT": default: } }; } - render() { return null; - } } @@ -230,8 +225,8 @@ class WebSocketManager extends Component { // map state to props function mapStateToProps(state) { return { - ignoreFile: state.ignoreFile, - message: state.message, + ignoreFileChange: state.ignoreFileChange, + minedRuleMetaData: state.minedRulesState.metaData }; } @@ -240,12 +235,14 @@ function mapDispatchToProps(dispatch) { return { onUpdateWS: (ws) => dispatch(updateWS(ws)), onProjectHierarchy: (hierarchyData) => dispatch(updateProjectHierarchyData(hierarchyData)), + onProjectPathUpdate: (projectPath) => dispatch(updateProjectPath(projectPath)), onUpdateRuleTable: (ruleTable) => dispatch(updateRuleTable(ruleTable)), onUpdateTagTable: (tagTable) => dispatch(updateTagTable(tagTable)), onFilePathChange: (filePath) => dispatch(updateFilePath(filePath)), - onFalsifyIgnoreFile: () => dispatch(ignoreFile(false)), + onFalsifyIgnoreFile: () => dispatch(ignoreFileChange(false)), onReceiveExprStmtXML: (data) => dispatch(receiveExpressionStatementXML(data)), onUpdateXmlFiles: (xmlFiles) => dispatch(updateXmlFiles(xmlFiles)), + onUpdateMinedRules: (modifiedOutput) => dispatch(updatedMinedRules(modifiedOutput)), onUpdateFeatureSelection: (dataObject) => dispatch(updateFeatureSelection(dataObject)), onUpdateDangerousMinedRules: (metaData, minedRules) => dispatch(updateDangerousMinedRules(metaData, minedRules)) diff --git a/src/index.css b/src/index.css index bc5102d..80d8c37 100644 --- a/src/index.css +++ b/src/index.css @@ -138,7 +138,7 @@ body { color: rgb(173, 171, 0) !important; } -/*** table of content ***/ +/*** table of contents ***/ .bottomBorder { margin-top: 5px !important; diff --git a/src/index.js b/src/index.js index 278998e..671b439 100644 --- a/src/index.js +++ b/src/index.js @@ -7,7 +7,6 @@ import { Provider } from "react-redux" import store from "./reduxStore"; import configureMonaco from "./configureMonaco"; -// import {generateInitialElements, generateInitialElementTreeNodes} from "./ui/ruleGenerationGUI/guiConstants"; configureMonaco(); @@ -18,6 +17,3 @@ ReactDOM.render( document.getElementById("root") ); registerServiceWorker(); - -// generateInitialElements("class_el", "0"); -// generateInitialElementTreeNodes("class_el", "0", ""); \ No newline at end of file diff --git a/src/initialState.js b/src/initialState.js index 308bb09..61a37f6 100644 --- a/src/initialState.js +++ b/src/initialState.js @@ -1,69 +1,69 @@ -const element_attributes = { +// the attributes of each element in the Graphical Editor of RulePad +const graphicalElementAttributes = { activeElement: false, // if the element has at least one child selectedElement: false, // if the element is the root of the XPath (unique) isConstraint: false // if the element is for the constraint query - // text: string (for storing values) }; -export const initial_guiElements = { - "0": {conditionName: "class_el", ...element_attributes}, - "0-0-0": {conditionName: "annotation", ...element_attributes}, - "0-1-0": {conditionName: "visibility", ...element_attributes}, - "0-2-0": {conditionName: "specifier", ...element_attributes}, - "0-4-0": {conditionName: "class_name", ...element_attributes}, - "0-5-0": {conditionName: "class_implements", ...element_attributes}, - "0-6-0": {conditionName: "class_extends", ...element_attributes}, - "0-7-0": {conditionName: "declaration_statement_el", ...element_attributes}, - "0-7-0-0-0": {conditionName: "annotation", ...element_attributes}, - "0-7-0-1-0": {conditionName: "visibility", ...element_attributes}, - "0-7-0-2-0": {conditionName: "specifier", ...element_attributes}, - "0-7-0-3-0": {conditionName: "declaration_statement_type", ...element_attributes}, - "0-7-0-4-0": {conditionName: "declaration_statement_name", ...element_attributes}, - "0-7-0-5-0": {conditionName: "declaration_statement_initialization", ...element_attributes}, - "0-7-1": {conditionName: "constructor_el", ...element_attributes}, - "0-7-1-0-0": {conditionName: "annotation", ...element_attributes}, - "0-7-1-2-0": {conditionName: "visibility", ...element_attributes}, - "0-7-1-5-0": {conditionName: "parameter_el", ...element_attributes}, - "0-7-1-5-0-1-0": {conditionName: "parameter_type", ...element_attributes}, - "0-7-1-5-0-4-0": {conditionName: "parameter_name", ...element_attributes}, - "0-7-1-7-0": {conditionName: "constructor_expression_statement", ...element_attributes}, - "0-7-1-7-1": {conditionName: "declaration_statement_el", ...element_attributes}, - "0-7-1-7-1-0-0": {conditionName: "annotation", ...element_attributes}, - "0-7-1-7-1-1-0": {conditionName: "visibility", ...element_attributes}, - "0-7-1-7-1-2-0": {conditionName: "specifier", ...element_attributes}, - "0-7-1-7-1-3-0": {conditionName: "declaration_statement_type", ...element_attributes}, - "0-7-1-7-1-4-0": {conditionName: "declaration_statement_name", ...element_attributes}, - "0-7-1-7-1-5-0": {conditionName: "declaration_statement_initialization", ...element_attributes}, - "0-7-2": {conditionName: "function_el", ...element_attributes}, - "0-7-2-0-0": {conditionName: "annotation", ...element_attributes}, - "0-7-2-1-0": {conditionName: "visibility", ...element_attributes}, - "0-7-2-2-0": {conditionName: "specifier", ...element_attributes}, - "0-7-2-3-0": {conditionName: "function_return_type", ...element_attributes}, - "0-7-2-4-0": {conditionName: "function_name", ...element_attributes}, - "0-7-2-5-0": {conditionName: "parameter_el", ...element_attributes}, - "0-7-2-5-0-1-0": {conditionName: "parameter_type", ...element_attributes}, - "0-7-2-5-0-4-0": {conditionName: "parameter_name", ...element_attributes}, - "0-7-2-7-0": {conditionName: "declaration_statement_el", ...element_attributes}, - "0-7-2-7-0-0-0": {conditionName: "annotation", ...element_attributes}, - "0-7-2-7-0-1-0": {conditionName: "visibility", ...element_attributes}, - "0-7-2-7-0-2-0": {conditionName: "specifier", ...element_attributes}, - "0-7-2-7-0-3-0": {conditionName: "declaration_statement_type", ...element_attributes}, - "0-7-2-7-0-4-0": {conditionName: "declaration_statement_name", ...element_attributes}, - "0-7-2-7-0-5-0": {conditionName: "declaration_statement_initialization", ...element_attributes}, - "0-7-2-7-1": {conditionName: "function_expression_statement", ...element_attributes}, - "0-7-2-7-2": {conditionName: "function_return_value", ...element_attributes}, - "0-7-3": {conditionName: "abstract_function_el", ...element_attributes}, - "0-7-3-0-0": {conditionName: "annotation", ...element_attributes}, - "0-7-3-1-0": {conditionName: "visibility", ...element_attributes}, - "0-7-3-2-0": {conditionName: "specifier", ...element_attributes}, - "0-7-3-3-0": {conditionName: "abstract_function_return_type", ...element_attributes}, - "0-7-3-4-0": {conditionName: "abstract_function_name", ...element_attributes}, - "0-7-3-5-0": {conditionName: "parameter_el", ...element_attributes}, - "0-7-3-5-0-1-0": {conditionName: "parameter_type", ...element_attributes}, - "0-7-3-5-0-4-0": {conditionName: "parameter_name", ...element_attributes} +export const initial_graphicalElements = { + "0": {conditionName: "class_el", ...graphicalElementAttributes}, + "0-0-0": {conditionName: "annotation", ...graphicalElementAttributes}, + "0-1-0": {conditionName: "visibility", ...graphicalElementAttributes}, + "0-2-0": {conditionName: "specifier", ...graphicalElementAttributes}, + "0-4-0": {conditionName: "class_name", ...graphicalElementAttributes}, + "0-5-0": {conditionName: "class_implements", ...graphicalElementAttributes}, + "0-6-0": {conditionName: "class_extends", ...graphicalElementAttributes}, + "0-7-0": {conditionName: "declaration_statement_el", ...graphicalElementAttributes}, + "0-7-0-0-0": {conditionName: "annotation", ...graphicalElementAttributes}, + "0-7-0-1-0": {conditionName: "visibility", ...graphicalElementAttributes}, + "0-7-0-2-0": {conditionName: "specifier", ...graphicalElementAttributes}, + "0-7-0-3-0": {conditionName: "declaration_statement_type", ...graphicalElementAttributes}, + "0-7-0-4-0": {conditionName: "declaration_statement_name", ...graphicalElementAttributes}, + "0-7-0-5-0": {conditionName: "declaration_statement_initialization", ...graphicalElementAttributes}, + "0-7-1": {conditionName: "constructor_el", ...graphicalElementAttributes}, + "0-7-1-0-0": {conditionName: "annotation", ...graphicalElementAttributes}, + "0-7-1-2-0": {conditionName: "visibility", ...graphicalElementAttributes}, + "0-7-1-5-0": {conditionName: "parameter_el", ...graphicalElementAttributes}, + "0-7-1-5-0-1-0": {conditionName: "parameter_type", ...graphicalElementAttributes}, + "0-7-1-5-0-4-0": {conditionName: "parameter_name", ...graphicalElementAttributes}, + "0-7-1-7-0": {conditionName: "constructor_expression_statement", ...graphicalElementAttributes}, + "0-7-1-7-1": {conditionName: "declaration_statement_el", ...graphicalElementAttributes}, + "0-7-1-7-1-0-0": {conditionName: "annotation", ...graphicalElementAttributes}, + "0-7-1-7-1-1-0": {conditionName: "visibility", ...graphicalElementAttributes}, + "0-7-1-7-1-2-0": {conditionName: "specifier", ...graphicalElementAttributes}, + "0-7-1-7-1-3-0": {conditionName: "declaration_statement_type", ...graphicalElementAttributes}, + "0-7-1-7-1-4-0": {conditionName: "declaration_statement_name", ...graphicalElementAttributes}, + "0-7-1-7-1-5-0": {conditionName: "declaration_statement_initialization", ...graphicalElementAttributes}, + "0-7-2": {conditionName: "function_el", ...graphicalElementAttributes}, + "0-7-2-0-0": {conditionName: "annotation", ...graphicalElementAttributes}, + "0-7-2-1-0": {conditionName: "visibility", ...graphicalElementAttributes}, + "0-7-2-2-0": {conditionName: "specifier", ...graphicalElementAttributes}, + "0-7-2-3-0": {conditionName: "function_return_type", ...graphicalElementAttributes}, + "0-7-2-4-0": {conditionName: "function_name", ...graphicalElementAttributes}, + "0-7-2-5-0": {conditionName: "parameter_el", ...graphicalElementAttributes}, + "0-7-2-5-0-1-0": {conditionName: "parameter_type", ...graphicalElementAttributes}, + "0-7-2-5-0-4-0": {conditionName: "parameter_name", ...graphicalElementAttributes}, + "0-7-2-7-0": {conditionName: "declaration_statement_el", ...graphicalElementAttributes}, + "0-7-2-7-0-0-0": {conditionName: "annotation", ...graphicalElementAttributes}, + "0-7-2-7-0-1-0": {conditionName: "visibility", ...graphicalElementAttributes}, + "0-7-2-7-0-2-0": {conditionName: "specifier", ...graphicalElementAttributes}, + "0-7-2-7-0-3-0": {conditionName: "declaration_statement_type", ...graphicalElementAttributes}, + "0-7-2-7-0-4-0": {conditionName: "declaration_statement_name", ...graphicalElementAttributes}, + "0-7-2-7-0-5-0": {conditionName: "declaration_statement_initialization", ...graphicalElementAttributes}, + "0-7-2-7-1": {conditionName: "function_expression_statement", ...graphicalElementAttributes}, + "0-7-2-7-2": {conditionName: "function_return_value", ...graphicalElementAttributes}, + "0-7-3": {conditionName: "abstract_function_el", ...graphicalElementAttributes}, + "0-7-3-0-0": {conditionName: "annotation", ...graphicalElementAttributes}, + "0-7-3-1-0": {conditionName: "visibility", ...graphicalElementAttributes}, + "0-7-3-2-0": {conditionName: "specifier", ...graphicalElementAttributes}, + "0-7-3-3-0": {conditionName: "abstract_function_return_type", ...graphicalElementAttributes}, + "0-7-3-4-0": {conditionName: "abstract_function_name", ...graphicalElementAttributes}, + "0-7-3-5-0": {conditionName: "parameter_el", ...graphicalElementAttributes}, + "0-7-3-5-0-1-0": {conditionName: "parameter_type", ...graphicalElementAttributes}, + "0-7-3-5-0-4-0": {conditionName: "parameter_name", ...graphicalElementAttributes} }; -export const initial_elementTree = { +export const initial_graphicalElementTree = { selectedElementID: "", "0": { parentId: "", @@ -246,47 +246,62 @@ export const initial_state = { ws: null, /* - index: 1545798262 - title: "" - description: "" - tags: [] - grammar: "" - ruleType: {constraint: "NONE", checkFor: [], type: "WITHIN"} - quantifier: {detail: "", command: ""} - constraint: {detail: "", command: ""} + index: 1545798262, + title: "", + description: "", + tags: [], + grammar: "", + checkForFilesFolders: [""], + checkForFilesFoldersConstraints: "INCLUDE", // or EXCLUDE + processFilesFolders: "WITHIN", + quantifierXPathQuery: [], + constraintXPathQuery: [], + + quantifierQueryType: "", + constraintQueryType: "", + rulePanelState: { - editMode: false - title: "" - description: "" - ruleTags: [] - folderConstraint: "" - filesFolders: [] - constraintXPath: "" - quantifierXPath: "" - autoCompleteArray: [] - activeTab: 0 - guiState: {guiTree: {...initial_elementTree}, guiElements: {...initial_guiElements}, ruleType: ""} + editMode: false, + title: "", + description: "", + ruleTags: [], + folderConstraint: "", + filesFolders: [], + constraintXPath: "", + quantifierXPath: "", + autoCompleteArray: [], + graphicalEditorState: {guiTree: {...initial_graphicalElementTree}, guiElements: {...initial_graphicalElements}, ruleType: ""} } - xPathQueryResult: [] + xPathQueryResult: [ + data: { + quantifierResult: [{filePath: "", snippet: "", xml: {fileName: "", xml: ""}}] + satisfied: 0 + satisfiedResult: [] + violated: 0 + violatedResult: [] + } + filePath: "" + ] */ ruleTable: [], tagTable: [], xmlFiles: [], projectHierarchy: {}, - hash: ["index"], - ignoreFile: false, + projectPath: "", + currentHash: ["index"], + ignoreFileChange: false, // ignore the file switching in the IDE displayEditRuleTutorial: true, // display the tour guide for edit rule message: "init", - filePath: "", + openFilePath: "", hashManager: { history: ["#/index"], - clicked: false, - activeHash: 0, + activeHashIndex: 0, forwardDisable: "disabled", - backDisable: "disabled" + backDisable: "disabled", + clickedOnButtons: false }, - // used for new rule form - newOrEditRule: { + + rulePadState: { isEditMode: false, title: "", description: "", @@ -300,12 +315,14 @@ export const initial_state = { sentMessages: [], receivedMessages: [], - guiState: { + graphicalEditorState: { ruleType: "", // "Must" or "MustBeEqualTo" - guiTree: {...initial_elementTree}, - guiElements: {...initial_guiElements} + guiTree: {...initial_graphicalElementTree}, + guiElements: {...initial_graphicalElements} } }, + + // mining Rules minedRulesState: { metaData: {}, minedRules: [] @@ -340,9 +357,9 @@ export const default_rulePanelState = { quantifierXPath: "", // only produced by autoComplete grammar constraintXPath: "", // only produced by autoComplete grammar - guiState: { + graphicalEditorState: { ruleType: "", // "Must" or "MustBeEqualTo" - guiTree: {...initial_elementTree}, - guiElements: {...initial_guiElements} + guiTree: {...initial_graphicalElementTree}, + guiElements: {...initial_graphicalElements} } }; diff --git a/src/miningRulesCore/miningRules.js b/src/miningRulesCore/miningRules.js index c1c9266..66cd679 100644 --- a/src/miningRulesCore/miningRules.js +++ b/src/miningRulesCore/miningRules.js @@ -60,6 +60,7 @@ import {addChildren, addParentChildRelations, findParentChildRelations, import et from 'elementtree'; import Utilities from "../core/utilities"; +import {webSocketSendMessage} from "../core/coreConstants"; /** * @@ -235,9 +236,9 @@ export const mineRulesFromXmlFiles = (xmlFiles, metaData, ws, outputFileAnalysisData(fileAnalysisMap, ws); if (algorithm === "FP_MAX") - Utilities.sendToServer(ws, "EXECUTE_FP_MAX", {fpMaxSupport}); + Utilities.sendToServer(ws, webSocketSendMessage.execute_fp_max_msg, {fpMaxSupport}); else if (algorithm === "TNR") - Utilities.sendToServer(ws, "EXECUTE_TNR", {tnrConfidence, tnrK, tnrDelta}); + Utilities.sendToServer(ws, webSocketSendMessage.execute_tnr_msg, {tnrConfidence, tnrK, tnrDelta}); }; @@ -256,7 +257,7 @@ const outputMetaData = (allAttributes, queryMap, metaData, ws) => { metaData[entries[x][1]] = {attr: entries[x][0], query: queries[x][0]}; } - Utilities.sendToServer(ws, "LEARN_RULES_META_DATA", {fileName: "attribute_META_data.txt", content: data}) + Utilities.sendToServer(ws, webSocketSendMessage.learn_rules_metadata_msg, {fileName: "attribute_META_data.txt", content: data}) }; @@ -271,7 +272,7 @@ const outputFileAnalysisData = (fileAnalysisMap, ws) => { stream += entries[x][0] + "\n" + entries[x][1] + "\n"; } - Utilities.sendToServer(ws, "LEARN_RULES_FILE_LOCATIONS", {fileName: "fileLocations.txt", content: stream}) + Utilities.sendToServer(ws, webSocketSendMessage.learn_rules_file_location_msg, {fileName: "fileLocations.txt", content: stream}) }; @@ -284,7 +285,7 @@ const outputDataBases = (dataMap, ws) => { let finalFormat = formatDatabases(databases); // websocket seems to fail in sending large messages. Instead of sending the database as a whole, we send messages in patches. finalFormat.forEach((d => { - Utilities.sendToServer(ws, "LEARN_RULES_DATABASES", [d]) + Utilities.sendToServer(ws, webSocketSendMessage.learn_rules_databases_msg, [d]) })) }; diff --git a/src/reducers.js b/src/reducers.js index 6952076..3fccae7 100644 --- a/src/reducers.js +++ b/src/reducers.js @@ -1,59 +1,6 @@ import {initial_state, default_rulePanelState} from "./initialState"; -import {generateTreeForElement} from "./ui/ruleGenerationGUI/guiConstants"; - - -/* - - List of messages: - - - HASH - NEW_WS - UPDATE_XML_FILES - UPDATE_TAG_TABLE - UPDATE_RULE_TABLE - UPDATE_RULE - - NEW_RULE - NEW_TAG - - IGNORE_FILE - - UPDATE_DISPLAY_EDIT_TUTORIAL - - FILE_PATH_UPDATED - - CLICKED_ON_FORWARD - CLICKED_ON_BACK - - CLEAR_NEW_RULE_FORM - EDIT_RULE_FORM - CHANGE_EDIT_MODE - - RECEIVE_GUI_TREE - - SEND_EXPR_STMT_XML - RECEIVE_EXPR_STMT_XML - MATCHED_MESSAGES - - CHANGE_GUI_ELEMENT - ADD_EXTRA - REMOVE_EXTRA - UPDATE_ELEMENT - REMOVE_ELEMENT - SELECT_ELEMENT - - CHANGE_AUTOCOMPLETE_TEXT_FROM_GUI - UPDATE_XPATHS - - UPDATE_META_DATA - UPDATE_MINED_RULES - - UPDATE_FEATURE_SELECTION - DANGEROUS_MINED_RULES - - */ - +import {generateTreeForElement} from "./ui/RulePad/rulePadGraphicalEditor/graphicalEditorConstants"; +import {reduxStoreMessages} from "./reduxStoreConstants"; /** @@ -70,45 +17,46 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { // Using Object.assign({}, state) has a flaw that it only does a shallow copy. // It means that nested properties are still going to be copied by reference. let copiedState = JSON.parse(JSON.stringify(state)); + let rules = []; switch (action.type) { case "HASH": - if (!state.hashManager.clicked) { + if (!state.hashManager.clickedOnButtons) { return Object.assign({}, state, { - hash: action["value"], - message: "HASH", + currentHash: action.data["currentHash"], + message: reduxStoreMessages.hash_msg, hashManager: { - history: [...state.hashManager.history, "#/" + action["value"].join("/")], - clicked: false, - activeHash: state.hashManager.activeHash + 1, + history: [...state.hashManager.history, "#/" + action.data["currentHash"].join("/")], + activeHashIndex: state.hashManager.activeHashIndex + 1, forwardDisable: "disabled", - backDisable: state.hashManager.activeHash === 0 + backDisable: state.hashManager.activeHashIndex === 0 ? "disabled" : "", + clickedOnButtons: false } }); } return Object.assign({}, state, { - hash: action["value"], - message: "HASH", + currentHash: action.data["currentHash"], + message: reduxStoreMessages.hash_msg, hashManager: { history: state.hashManager.history, - clicked: false, - activeHash: state.hashManager.activeHash, + activeHashIndex: state.hashManager.activeHashIndex, forwardDisable: state.hashManager.forwardDisable, - backDisable: state.hashManager.backDisable + backDisable: state.hashManager.backDisable, + clickedOnButtons: false } }); case "NEW_WS": - return Object.assign({}, state, {ws: action["value"], message: "NEW_WS"}); + return Object.assign({}, state, {ws: action.data["ws"], message: reduxStoreMessages.ws_msg}); case "UPDATE_XML_FILES": - return Object.assign({}, state, {xmlFiles: action["xmlFiles"], message: "UPDATE_XML_FILES"}); + return Object.assign({}, state, {xmlFiles: action.data["xmlFiles"], message: reduxStoreMessages.update_xml_files_msg}); case "UPDATE_TAG_TABLE": - return Object.assign({}, state, {tagTable: action["value"], message: "UPDATE_TAG_TABLE"}); + return Object.assign({}, state, {tagTable: action.data["tagTable"], message: reduxStoreMessages.update_tag_table_msg}); case "UPDATE_RULE_TABLE": - let rules = JSON.parse(JSON.stringify(action["ruleTable"])); + rules = JSON.parse(JSON.stringify(action.data["ruleTable"])); rules = rules.map(rule => Object.assign({}, rule, { rulePanelState: { @@ -117,10 +65,10 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { title: rule.title, description: rule.description, ruleTags: rule.tags, - folderConstraint: rule.ruleType.constraint, - filesFolders: rule.ruleType.checkFor, - quantifierXPath: rule.quantifier.command, - constraintXPath: rule.constraint.command, + folderConstraint: rule.checkForFilesFoldersConstraints, + filesFolders: rule.checkForFilesFolders, + quantifierXPath: rule.quantifierXPathQuery[0], + constraintXPath: rule.constraintXPathQuery[0], // autoCompleteText: rule.grammar, autoCompleteArray: rule.grammar && rule.grammar !== "" ? rule.grammar.split(" ").map(word => { return {id: "", text: word} @@ -130,52 +78,58 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { ); return Object.assign({}, state, { ruleTable: rules, - message: "UPDATE_RULE_TABLE" + message: reduxStoreMessages.update_rule_table_msg }); case "UPDATE_RULE": return Object.assign({}, state, { - message: "UPDATE_RULE" + message: reduxStoreMessages.update_rule_msg }); case "SUBMIT_NEW_RULE": return Object.assign({}, state, { - newOrEditRule: { - ...JSON.parse(JSON.stringify(initial_state.newOrEditRule)), + rulePadState: { + ...JSON.parse(JSON.stringify(initial_state.rulePadState)), isEditMode: false }, - message: "NEW_RULE" + message: reduxStoreMessages.new_rule_msg }); case "SUBMIT_NEW_TAG": return Object.assign({}, state, { - message: "NEW_TAG" + message: reduxStoreMessages.new_tag_msg }); case "HIERARCHY_DATA": return Object.assign({}, state, { - projectHierarchy: action["hierarchyData"], - message: "HIERARCHY_DATA" + projectHierarchy: action.data["hierarchyData"], + message: reduxStoreMessages.hierarchy_data_msg + }); + + case "PROJECT_PATH": + return Object.assign({}, state, { + projectPath: action.data["projectPath"], + message: reduxStoreMessages.project_path_msg }); /* file handling */ - case "IGNORE_FILE": + case "IGNORE_FILE_CHANGE": let editCount = state.ruleTable.reduce((count, element) => count + element.rulePanelState.editMode ? 1 : 0, 0); - if (state.newOrEditRule.isEditMode || editCount > 0) return Object.assign({}, state); - return Object.assign({}, state, {ignoreFile: action["shouldIgnore"], message: "IGNORE_FILE"}); + if (state.rulePadState.isEditMode || editCount > 0) return Object.assign({}, state); + return Object.assign({}, state, {ignoreFileChange: action.data["shouldIgnore"], message: reduxStoreMessages.ignore_file_msg}); case "UPDATE_DISPLAY_EDIT_TUTORIAL": return Object.assign({}, state, { - displayEditRuleTutorial: action["shouldDisplay"], - message: "UPDATE_DISPLAY_EDIT_TUTORIAL" + displayEditRuleTutorial: action.data["shouldDisplay"], + message: reduxStoreMessages.update_display_edit_tutorial_msg }); - case "FILE_PATH": - if (state.ignoreFile) return Object.assign({}, state, {message: "FILE_PATH_UPDATED"}); - return Object.assign({}, state, {filePath: action["value"], message: "FILE_PATH_UPDATED"}); + case "FILE_PATH_UPDATED": + if (state.ignoreFileChange) return Object.assign({}, state, {message: reduxStoreMessages.file_path_update_msg}); + return Object.assign({}, state, {openFilePath: action.data["openFilePath"], message: reduxStoreMessages.file_path_update_msg}); /* nav-bar navigation @@ -185,93 +139,93 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { return Object.assign({}, state, { hashManager: { history: state.hashManager.history, - clicked: true, - activeHash: state.hashManager.activeHash + 1, - forwardDisable: state.hashManager.activeHash === state.hashManager.history.length - 2 ? "disabled" : "", - backDisable: "" + activeHashIndex: state.hashManager.activeHashIndex + 1, + forwardDisable: state.hashManager.activeHashIndex === state.hashManager.history.length - 2 ? "disabled" : "", + backDisable: "", + clickedOnButtons: true }, - message: "CLICKED_ON_FORWARD" + message: reduxStoreMessages.click_forward_msg }); case "CLICKED_ON_BACK": return Object.assign({}, state, { hashManager: { history: state.hashManager.history, - clicked: true, - activeHash: state.hashManager.activeHash - 1, + activeHashIndex: state.hashManager.activeHashIndex - 1, forwardDisable: "", - backDisable: state.hashManager.activeHash === 1 ? "disabled" : "" + backDisable: state.hashManager.activeHashIndex === 1 ? "disabled" : "", + clickedOnButtons: true }, - message: "CLICKED_ON_BACK" + message: reduxStoreMessages.click_back_msg }); /* - generate rule form - */ + RulePad + */ case "CLEAR_NEW_RULE_FORM": return Object.assign({}, state, { - newOrEditRule: { - ...JSON.parse(JSON.stringify(initial_state.newOrEditRule)), + rulePadState: { + ...JSON.parse(JSON.stringify(initial_state.rulePadState)), isEditMode: true }, - message: "CLEAR_NEW_RULE_FORM" + message: reduxStoreMessages.clear_new_rule_form_msg }); case "EDIT_RULE_FORM": - if (action["ruleIndex"] !== -1) { - let rules = JSON.parse(JSON.stringify(state.ruleTable)); + if (action.data["ruleIndex"] !== -1) { + rules = JSON.parse(JSON.stringify(state.ruleTable)); rules = rules.map(d => { let a = Object.assign({}, d); - if (a.index !== action["ruleIndex"]) return a; - a.rulePanelState.title = action["title"]; - a.rulePanelState.description = action["description"]; - a.rulePanelState.ruleTags = action["ruleTags"]; - a.rulePanelState.folderConstraint = action["folderConstraint"]; - a.rulePanelState.filesFolders = action["filesFolders"]; + if (a.index !== action.data["ruleIndex"]) return a; + a.rulePanelState.title = action.data["title"]; + a.rulePanelState.description = action.data["description"]; + a.rulePanelState.ruleTags = action.data["ruleTags"]; + a.rulePanelState.folderConstraint = action.data["folderConstraint"]; + a.rulePanelState.filesFolders = action.data["filesFolders"]; return a; }); return Object.assign({}, state, { ruleTable: rules, - message: "EDIT_RULE_FORM" + message: reduxStoreMessages.edit_rule_form_msg }); } else return Object.assign({}, state, { - newOrEditRule: { - ...state.newOrEditRule, - title: action["title"], - description: action["description"], - ruleTags: action["ruleTags"], - folderConstraint: action["folderConstraint"], - filesFolders: action["filesFolders"] + rulePadState: { + ...state.rulePadState, + title: action.data["title"], + description: action.data["description"], + ruleTags: action.data["ruleTags"], + folderConstraint: action.data["folderConstraint"], + filesFolders: action.data["filesFolders"] }, - message: "EDIT_RULE_FORM" + message: reduxStoreMessages.edit_rule_form_msg }); case "CHANGE_EDIT_MODE": - if (action["ruleIndex"] !== -1) { - let editCount = copiedState.ruleTable.reduce((count, element) => { - if (element.index !== action["ruleIndex"]) return count + element.rulePanelState.editMode ? 1 : 0; - return count + action["newEditMode"] ? 1 : 0; + if (action.data["ruleIndex"] !== -1) { + let editCount_ = copiedState.ruleTable.reduce((count, element) => { + if (element.index !== action.data["ruleIndex"]) return count + element.rulePanelState.editMode ? 1 : 0; + return count + action.data["newEditMode"] ? 1 : 0; }, 0); - let rules = copiedState.ruleTable.map(d => { + rules = copiedState.ruleTable.map(d => { let a = Object.assign({}, d); - if (a.index === action["ruleIndex"]) { - a.rulePanelState.editMode = action["newEditMode"]; + if (a.index === action.data["ruleIndex"]) { + a.rulePanelState.editMode = action.data["newEditMode"]; // reset fields of the form after cancel editing - if (!action["newEditMode"]) + if (!action.data["newEditMode"]) a.rulePanelState = { ...JSON.parse(JSON.stringify(default_rulePanelState)), title: d.title, description: d.description, ruleTags: d.tags, - folderConstraint: d.ruleType.constraint, - filesFolders: d.ruleType.checkFor, - quantifierXPath: d.quantifier.command, - constraintXPath: d.constraint.command, + folderConstraint: d.checkForFilesFoldersConstraints, + filesFolders: d.checkForFilesFolders, + quantifierXPath: d.quantifierXPathQuery[0], + constraintXPath: d.constraintXPathQuery[0], // autoCompleteText: d.grammar, autoCompleteArray: d.grammar && d.grammar !== "" ? d.grammar.split(" ").map(word => { return {id: "", text: word} @@ -281,104 +235,104 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { return a; }); return Object.assign({}, state, { - ignoreFile: (state.newOrEditRule.isEditMode || editCount > 0), + ignoreFileChange: (state.rulePadState.isEditMode || editCount_ > 0), ruleTable: rules, - message: "CHANGE_EDIT_MODE" + message: reduxStoreMessages.change_edit_mode_msg }); } else return Object.assign({}, state, { - ignoreFile: (action["newEditMode"] || state.ruleTable.reduce((count, element) => count + element.rulePanelState.editMode ? 1 : 0, 0) > 0), - newOrEditRule: { - ...state.newOrEditRule, - isEditMode: action["newEditMode"] + ignoreFileChange: (action.data["newEditMode"] || state.ruleTable.reduce((count, element) => count + element.rulePanelState.editMode ? 1 : 0, 0) > 0), + rulePadState: { + ...state.rulePadState, + isEditMode: action.data["newEditMode"] }, - message: "CHANGE_EDIT_MODE" + message: reduxStoreMessages.change_edit_mode_msg }); case "RECEIVE_GUI_TREE": - if (action["ruleIndex"] !== -1) { + if (action.data["ruleIndex"] !== -1) { let rules = JSON.parse(JSON.stringify(state.ruleTable)); rules = rules.map(d => { let a = Object.assign({}, d); - if (a.index !== action["ruleIndex"]) return a; - a.rulePanelState.quantifierXPath = action["quantifierXPath"]; - a.rulePanelState.constraintXPath = action["constraintXPath"]; - a.rulePanelState.autoCompleteArray = action["autoCompleteArray"]; - a.rulePanelState.guiState = { - ...a.rulePanelState.guiState, - ...action["newTreeData"] + if (a.index !== action.data["ruleIndex"]) return a; + a.rulePanelState.quantifierXPath = action.data["quantifierXPath"]; + a.rulePanelState.constraintXPath = action.data["constraintXPath"]; + a.rulePanelState.autoCompleteArray = action.data["autoCompleteArray"]; + a.rulePanelState.graphicalEditorState = { + ...a.rulePanelState.graphicalEditorState, + ...action.data["newTreeData"] }; return a; }); return Object.assign({}, state, { - message: "RECEIVE_GUI_TREE", + message: reduxStoreMessages.receive_gui_tree_msg, ruleTable: rules }); } else return Object.assign({}, state, { - message: "RECEIVE_GUI_TREE", - newOrEditRule: { - ...state.newOrEditRule, - quantifierXPath: action["quantifierXPath"], - constraintXPath: action["constraintXPath"], - autoCompleteArray: action["autoCompleteArray"], - guiState: { - ...state.newOrEditRule.guiState, - ...action["newTreeData"] + message: reduxStoreMessages.receive_gui_tree_msg, + rulePadState: { + ...state.rulePadState, + quantifierXPath: action.data["quantifierXPath"], + constraintXPath: action.data["constraintXPath"], + autoCompleteArray: action.data["autoCompleteArray"], + graphicalEditorState: { + ...state.rulePadState.graphicalEditorState, + ...action.data["newTreeData"] } } }); case "SEND_EXPR_STMT_XML": return Object.assign({}, state, { - newOrEditRule: { - ...state.newOrEditRule, - sentMessages: state.newOrEditRule.sentMessages.concat([action["codeTextAndID"]]) + rulePadState: { + ...state.rulePadState, + sentMessages: state.rulePadState.sentMessages.concat([action.data["codeTextAndID"]]) }, - message: "SEND_EXPR_STMT_XML" + message: reduxStoreMessages.send_expr_stmt_xml_msg }); case "RECEIVE_EXPR_STMT_XML": return Object.assign({}, state, { - newOrEditRule: { - ...state.newOrEditRule, - receivedMessages: state.newOrEditRule.receivedMessages.concat([action["xmlData"]]) + rulePadState: { + ...state.rulePadState, + receivedMessages: state.rulePadState.receivedMessages.concat([action.data["xmlData"]]) }, - message: "RECEIVE_EXPR_STMT_XML" + message: reduxStoreMessages.receive_expr_stmt_xml_msg }); case "MATCHED_MESSAGES": - if (action["ruleIndex"] !== -1) { - let rules = JSON.parse(JSON.stringify(state.ruleTable)); + if (action.data["ruleIndex"] !== -1) { + rules = JSON.parse(JSON.stringify(state.ruleTable)); rules = rules.map(d => { let a = Object.assign({}, d); - if (a.index !== action["ruleIndex"]) return a; - a.rulePanelState.quantifierXPath = action["quantifierXPath"]; - a.rulePanelState.constraintXPath = action["constraintXPath"]; + if (a.index !== action.data["ruleIndex"]) return a; + a.rulePanelState.quantifierXPath = action.data["quantifierXPath"]; + a.rulePanelState.constraintXPath = action.data["constraintXPath"]; return a; }); return Object.assign({}, state, { - message: "MATCHED_MESSAGES", + message: reduxStoreMessages.matched_messages_msg, ruleTable: rules, - newOrEditRule: { - ...state.newOrEditRule, - sentMessages: action["sentMessages"], - receivedMessages: action["receivedMessages"] + rulePadState: { + ...state.rulePadState, + sentMessages: action.data["sentMessages"], + receivedMessages: action.data["receivedMessages"] }, }); } else return Object.assign({}, state, { - newOrEditRule: { - ...state.newOrEditRule, - quantifierXPath: action["quantifierXPath"], - constraintXPath: action["constraintXPath"], - sentMessages: action["sentMessages"], - receivedMessages: action["receivedMessages"] + rulePadState: { + ...state.rulePadState, + quantifierXPath: action.data["quantifierXPath"], + constraintXPath: action.data["constraintXPath"], + sentMessages: action.data["sentMessages"], + receivedMessages: action.data["receivedMessages"] }, - message: "MATCHED_MESSAGES" + message: reduxStoreMessages.matched_messages_msg }); /* @@ -392,7 +346,7 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { case "CHANGE_GUI_ELEMENT": // There can be several jobs. // All changes are done on a copy - action["tasks"].forEach(job => { + action.data["tasks"].forEach(job => { switch (job["task"]) { // job = {elementId: "", task: "", value: `${childGroupName}`} case "ADD_EXTRA": @@ -443,24 +397,24 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { }; - if (action["ruleIndex"] !== -1) + if (action.data["ruleIndex"] !== -1) copiedState.ruleTable = copiedState.ruleTable.map(rule => { - if (rule.index !== action["ruleIndex"]) return rule; - rule.rulePanelState.guiState = processFunc(rule.rulePanelState.guiState); + if (rule.index !== action.data["ruleIndex"]) return rule; + rule.rulePanelState.graphicalEditorState = processFunc(rule.rulePanelState.graphicalEditorState); return rule; }); else - copiedState.newOrEditRule.guiState = processFunc(copiedState.newOrEditRule.guiState); + copiedState.rulePadState.graphicalEditorState = processFunc(copiedState.rulePadState.graphicalEditorState); break; // job = {elementId: "", task: "UPDATE_ELEMENT", value: {props: newValues}} case "UPDATE_ELEMENT": - if (action["ruleIndex"] !== -1) { + if (action.data["ruleIndex"] !== -1) { copiedState.ruleTable = copiedState.ruleTable.map(rule => { - if (rule.index !== action["ruleIndex"]) return rule; - rule.rulePanelState.guiState.guiElements[job["elementId"]] = { - ...rule.rulePanelState.guiState.guiElements[job["elementId"]], + if (rule.index !== action.data["ruleIndex"]) return rule; + rule.rulePanelState.graphicalEditorState.guiElements[job["elementId"]] = { + ...rule.rulePanelState.graphicalEditorState.guiElements[job["elementId"]], ...job["value"] }; @@ -468,8 +422,8 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { }); } else { - copiedState.newOrEditRule.guiState.guiElements[job["elementId"]] = { - ...copiedState.newOrEditRule.guiState.guiElements[job["elementId"]], + copiedState.rulePadState.graphicalEditorState.guiElements[job["elementId"]] = { + ...copiedState.rulePadState.graphicalEditorState.guiElements[job["elementId"]], ...job["value"] }; } @@ -479,12 +433,12 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { case "REMOVE_ELEMENT": // search in parent children and remove elementId - // toBeDeletedIDs=[] to be removed from ...guiState.${group}.guiElements and ....guiState["quantifier/constraint"] + // toBeDeletedIDs=[] to be removed from ...graphicalEditorState.${group}.guiElements and ....graphicalEditorState["quantifier/constraint"] // build a stack=[elementId] for going through tree of elementId // while stack.size()>0 // pop one newId, add it to storeIDs // add ids of children of the popped id tree to the stack - // delete toBeDeletedIDs from ...guiState.${group}.guiElements and ....guiState["quantifier/constraint"] + // delete toBeDeletedIDs from ...graphicalEditorState.${group}.guiElements and ....graphicalEditorState["quantifier/constraint"] let processRemoveElement = (array) => { let parentTree = array.guiTree[job["value"]["parentId"]]; Object.keys(parentTree.children).forEach(childGroup => { @@ -526,14 +480,14 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { return array; }; - if (action["ruleIndex"] !== -1) + if (action.data["ruleIndex"] !== -1) copiedState.ruleTable = copiedState.ruleTable.map(rule => { - if (rule.index !== action["ruleIndex"]) return rule; - rule.rulePanelState.guiState = processRemoveElement(rule.rulePanelState.guiState); + if (rule.index !== action.data["ruleIndex"]) return rule; + rule.rulePanelState.graphicalEditorState = processRemoveElement(rule.rulePanelState.graphicalEditorState); return rule; }); else - copiedState.newOrEditRule.guiState = processRemoveElement(copiedState.newOrEditRule.guiState); + copiedState.rulePadState.graphicalEditorState = processRemoveElement(copiedState.rulePadState.graphicalEditorState); break; @@ -556,15 +510,15 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { return array; }; - if (action["ruleIndex"] !== -1) { + if (action.data["ruleIndex"] !== -1) { copiedState.ruleTable = copiedState.ruleTable.map(rule => { - if (rule.index !== action["ruleIndex"]) return rule; - rule.rulePanelState.guiState = processSelectElement(rule.rulePanelState.guiState); + if (rule.index !== action.data["ruleIndex"]) return rule; + rule.rulePanelState.graphicalEditorState = processSelectElement(rule.rulePanelState.graphicalEditorState); return rule; }); } else - copiedState.newOrEditRule.guiState = processSelectElement(copiedState.newOrEditRule.guiState); + copiedState.rulePadState.graphicalEditorState = processSelectElement(copiedState.rulePadState.graphicalEditorState); break; @@ -575,100 +529,113 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { return Object.assign({}, state, { ruleTable: copiedState.ruleTable, - newOrEditRule: copiedState.newOrEditRule, - message: "CHANGE_GUI_ELEMENT" + rulePadState: copiedState.rulePadState, + message: reduxStoreMessages.change_gui_element_msg }); case "CHANGE_AUTOCOMPLETE_TEXT_FROM_GUI": - if (action["ruleIndex"] !== -1) { + if (action.data["ruleIndex"] !== -1) { let rules = JSON.parse(JSON.stringify(state.ruleTable)); rules = rules.map(d => { - if (d.index !== action["ruleIndex"]) return d; + if (d.index !== action.data["ruleIndex"]) return d; return Object.assign({}, d, { rulePanelState: { ...d.rulePanelState, - autoCompleteArray: action["newAutoCompleteArray"] + autoCompleteArray: action.data["newAutoCompleteArray"] } }); }); return Object.assign({}, state, { ruleTable: rules, - message: "CHANGE_AUTOCOMPLETE_TEXT_FROM_GUI" + message: reduxStoreMessages.change_autocomplete_text_msg }); } else return Object.assign({}, state, { - newOrEditRule: { - ...state.newOrEditRule, - autoCompleteArray: action["newAutoCompleteArray"] + rulePadState: { + ...state.rulePadState, + autoCompleteArray: action.data["newAutoCompleteArray"] }, - message: "CHANGE_AUTOCOMPLETE_TEXT_FROM_GUI" + message: reduxStoreMessages.change_autocomplete_text_msg }); case "UPDATE_XPATHS": - if (action["ruleIndex"] !== -1) { + if (action.data["ruleIndex"] !== -1) { let rules = JSON.parse(JSON.stringify(state.ruleTable)); rules = rules.map(d => { let a = Object.assign({}, d); - if (a.index !== action["ruleIndex"]) return a; - a.rulePanelState.quantifierXPath = action["quantifierXPath"]; - a.rulePanelState.constraintXPath = action["constraintXPath"]; + if (a.index !== action.data["ruleIndex"]) return a; + a.rulePanelState.quantifierXPath = action.data["quantifierXPath"]; + a.rulePanelState.constraintXPath = action.data["constraintXPath"]; return a; }); return Object.assign({}, state, { - message: "UPDATE_XPATHS", + message: reduxStoreMessages.update_xpath_msg, ruleTable: rules }); } else return Object.assign({}, state, { - newOrEditRule: { - ...state.newOrEditRule, - quantifierXPath: action["quantifierXPath"], - constraintXPath: action["constraintXPath"] + rulePadState: { + ...state.rulePadState, + quantifierXPath: action.data["quantifierXPath"], + constraintXPath: action.data["constraintXPath"] }, - message: "UPDATE_XPATHS" + message: reduxStoreMessages.update_xpath_msg }); + /* + Mining Rules + */ + case "UPDATE_META_DATA": return Object.assign({}, state, { - message: "UPDATE_META_DATA", + message: reduxStoreMessages.update_metadata_msg, minedRulesState: { - metaData: action["metaData"], + metaData: action.data["metaData"], minedRules: [] } }); case "UPDATE_MINED_RULES": return Object.assign({}, state, { - message: "UPDATE_MINED_RULES", + message: reduxStoreMessages.update_mined_rules_msg, minedRulesState: { ...JSON.parse(JSON.stringify(state.minedRulesState)), - minedRules: action["minedRules"] + minedRules: action.data["minedRules"] } }); case "UPDATE_FEATURE_SELECTION" : return Object.assign({}, state, { - message: "UPDATE_FEATURE_SELECTION", + message: reduxStoreMessages.update_feature_selection_msg, featureSelection: { - filePath: action["filePath"], - startOffset: action["startOffset"], - endOffset: action["endOffset"], - startLineOffset: action["startLineOffset"], - lineNumber: action["lineNumber"], - lineText: action["lineText"], - selectedText: action["selectedText"], - xpath: action["xpath"], - modifiedSelectedText: action["modifiedSelectedText"], - idMap: action["idMap"], - displayTextArray: action["displayTextArray"] + filePath: action.data["filePath"], + startOffset: action.data["startOffset"], + endOffset: action.data["endOffset"], + startLineOffset: action.data["startLineOffset"], + lineNumber: action.data["lineNumber"], + lineText: action.data["lineText"], + selectedText: action.data["selectedText"], + xpath: action.data["xpath"], + modifiedSelectedText: action.data["modifiedSelectedText"], + idMap: action.data["idMap"], + displayTextArray: action.data["displayTextArray"] + } + }); + + case "DANGEROUS_MINED_RULES": + return Object.assign({}, state, { + message: reduxStoreMessages.update_mined_rules_msg, + minedRulesState: { + metaData: action.data["metaData"], + minedRules: action.data["minedRules"] } }); case "RESET_FEATURE_SELECTION": return Object.assign({}, state, { - message: "RESET_FEATURE_SELECTION", + message: reduxStoreMessages.reset_feature_selection_msg, featureSelection: { ...JSON.parse(JSON.stringify(initial_state.featureSelection)) } @@ -676,25 +643,16 @@ const reducer = (state = JSON.parse(JSON.stringify(initial_state)), action) => { case "SAVE_FEATURE_SELECTION": return Object.assign({}, state, { - message: "SAVE_FEATURE_SELECTION", + message: reduxStoreMessages.save_feature_selection_msg, featureSelection: { ...JSON.parse(JSON.stringify(initial_state.featureSelection)) }, customFeatures: state.customFeatures.concat([{ - featureDescription: action["featureDescription"], - featureXpath: action["featureXpath"] + featureDescription: action.data["featureDescription"], + featureXpath: action.data["featureXpath"] }]) }); - case "DANGEROUS_MINED_RULES": - return Object.assign({}, state, { - message: "UPDATE_MINED_RULES", - minedRulesState: { - metaData: action["metaData"], - minedRules: action["minedRules"] - } - }); - default: return Object.assign({}, state); } diff --git a/src/reduxStoreConstants.js b/src/reduxStoreConstants.js new file mode 100644 index 0000000..a0de9db --- /dev/null +++ b/src/reduxStoreConstants.js @@ -0,0 +1,40 @@ +/* +created by @saharmehrpour Jun 5, 2020 + */ + + + +export const reduxStoreMessages = { + hash_msg: "HASH", + ws_msg: "NEW_WS", + update_xml_files_msg: "UPDATE_XML_FILES", + update_tag_table_msg: "UPDATE_TAG_TABLE", + update_rule_table_msg: "UPDATE_RULE_TABLE", + update_rule_msg: "UPDATE_RULE", + new_rule_msg: "NEW_RULE", + new_tag_msg: "NEW_TAG", + hierarchy_data_msg: "HIERARCHY_DATA", + project_path_msg: "PROJECT_PATH", + ignore_file_msg: "IGNORE_FILE_CHANGE", + file_path_update_msg: "FILE_PATH_UPDATED", + click_forward_msg: "CLICKED_ON_FORWARD", + click_back_msg: "CLICKED_ON_BACK", + + update_display_edit_tutorial_msg: "UPDATE_DISPLAY_EDIT_TUTORIAL", + clear_new_rule_form_msg: "CLEAR_NEW_RULE_FORM", + edit_rule_form_msg: "EDIT_RULE_FORM", + change_edit_mode_msg: "CHANGE_EDIT_MODE", + receive_gui_tree_msg: "RECEIVE_GUI_TREE", + send_expr_stmt_xml_msg: "SEND_EXPR_STMT_XML", + receive_expr_stmt_xml_msg: "RECEIVE_EXPR_STMT_XML", + matched_messages_msg: "MATCHED_MESSAGES", + change_gui_element_msg: "CHANGE_GUI_ELEMENT", + change_autocomplete_text_msg: "CHANGE_AUTOCOMPLETE_TEXT_FROM_GUI", + update_xpath_msg: "UPDATE_XPATHS", + + update_metadata_msg: "UPDATE_META_DATA", + update_mined_rules_msg: "UPDATE_MINED_RULES", + update_feature_selection_msg: "UPDATE_FEATURE_SELECTION", + reset_feature_selection_msg: "RESET_FEATURE_SELECTION", + save_feature_selection_msg: "SAVE_FEATURE_SELECTION" +}; \ No newline at end of file diff --git a/src/ui/FeatureSelection.js b/src/ui/MiningRules/featureSelection.js similarity index 96% rename from src/ui/FeatureSelection.js rename to src/ui/MiningRules/featureSelection.js index c4aeff7..641310a 100644 --- a/src/ui/FeatureSelection.js +++ b/src/ui/MiningRules/featureSelection.js @@ -3,12 +3,12 @@ */ import React, {Component} from "react"; -import "../App.css"; +import "../../App.css"; import {connect} from "react-redux"; import {ButtonToolbar, Button} from "react-bootstrap"; -import {computeXPath} from "../miningRulesCore/findingFeature"; -import {updateResetFeatureSelection, updateSaveFeatureSelection} from "../actions"; +import {computeXPath} from "../../miningRulesCore/findingFeature"; +import {updateResetFeatureSelection, updateSaveFeatureSelection} from "../../actions"; class FeatureSelection extends Component { @@ -187,12 +187,6 @@ class FeatureSelection extends Component { } function mapStateToProps(state) { - // copied from headerBar.js - let path = ""; - try { - path = state["projectHierarchy"]["properties"]["canonicalPath"]; - } catch (e) { - } return { message: state.message, filePath: state.featureSelection.filePath, @@ -206,7 +200,7 @@ function mapStateToProps(state) { modifiedSelectedText: state.featureSelection.modifiedSelectedText, idMap: state.featureSelection.idMap, displayTextArray: state.featureSelection.displayTextArray, - projectPath: path + projectPath: state.projectPath } } diff --git a/src/ui/minedRulePad.js b/src/ui/MiningRules/minedRulePad.js similarity index 98% rename from src/ui/minedRulePad.js rename to src/ui/MiningRules/minedRulePad.js index 6b65f27..966cfcb 100644 --- a/src/ui/minedRulePad.js +++ b/src/ui/MiningRules/minedRulePad.js @@ -1,12 +1,12 @@ /** * Created by saharmehrpour on 1/14/20. - * Copied from src/ui/ruleGenerationGUI/guiComponent.js + * Copied from src/ui/rulePadGraphicalEditor/graphicalComponent.js * */ import React, {Component, Fragment} from "react"; -import {getConditionByName} from "./ruleGenerationGUI/guiConstants"; +import {getConditionByName} from "../RulePad/rulePadGraphicalEditor/graphicalEditorConstants"; class MinedRulePad extends Component { diff --git a/src/ui/minedRulesComponent.js b/src/ui/MiningRules/minedRulesComponent.js similarity index 97% rename from src/ui/minedRulesComponent.js rename to src/ui/MiningRules/minedRulesComponent.js index 207492d..4c091b8 100644 --- a/src/ui/minedRulesComponent.js +++ b/src/ui/MiningRules/minedRulesComponent.js @@ -3,7 +3,7 @@ */ import React, {Component, Fragment} from "react"; -import "../App.css"; +import "../../App.css"; import {connect} from "react-redux"; import {Button, Row, Col, ButtonGroup} from "react-bootstrap"; import Slider from "rc-slider"; @@ -12,12 +12,13 @@ import "rc-slider/assets/index.css"; import "three-dots" -import {mineRulesFromXmlFiles} from "../miningRulesCore/miningRules"; -import {ignoreFile, updateMetaData} from "../actions"; +import {mineRulesFromXmlFiles} from "../../miningRulesCore/miningRules"; +import {ignoreFileChange, updateMetaData} from "../../actions"; import MinedRulePad from "./minedRulePad"; -import {verifyPartialTextBasedOnGrammar} from "../core/languageProcessing"; -import {generateGuiTrees} from "./ruleGenerationText/generateGuiTree"; -import Utilities from "../core/utilities"; +import {verifyPartialTextBasedOnGrammar} from "../../core/languageProcessing"; +import {generateGuiTrees} from "../RulePad/rulePadTextualEditor/generateGuiTree"; +import Utilities from "../../core/utilities"; +import {webSocketSendMessage} from "../../core/coreConstants"; class MinedRulesComponent extends Component { @@ -433,7 +434,7 @@ class MinedRulesComponent extends Component {
{ this.props.onIgnoreFile(true); - Utilities.sendToServer(this.props.ws, "OPEN_FILE", fileName) + Utilities.sendToServer(this.props.ws, webSocketSendMessage.open_file_mined_rules, fileName) }}> {fileName .replace(this.props.projectPath.slice, "") @@ -469,7 +470,7 @@ class MinedRulesComponent extends Component { */ ShowMinedRules() { this.setState({minedRules: [], displayedMinedRules: [], loading: true}); - Utilities.sendToServer(this.props.ws, "DANGEROUS_READ_MINED_RULES"); + Utilities.sendToServer(this.props.ws, webSocketSendMessage.dangerous_read_mined_rules_msg); } /** @@ -569,26 +570,20 @@ class MinedRulesComponent extends Component { } function mapStateToProps(state) { - // copied from headerBar.js - let path = ""; - try { - path = state["projectHierarchy"]["properties"]["canonicalPath"]; - } catch (e) { - } return { message: state.message, ws: state.ws, xmlFiles: state.xmlFiles, metaData: state.minedRulesState.metaData, minedRules: state.minedRulesState.minedRules, - projectPath: path, + projectPath: state.projectPath, customFeatures: state.customFeatures // custom features received from feature selection } } function mapDispatchToProps(dispatch) { return { - onIgnoreFile: (shouldIgnore) => dispatch(ignoreFile(shouldIgnore)), + onIgnoreFile: (shouldIgnore) => dispatch(ignoreFileChange(shouldIgnore)), onUpdateMetaData: (metaData) => dispatch(updateMetaData(metaData)) } } diff --git a/src/ui/projectHierarchy.js b/src/ui/RulePad/projectHierarchy.js similarity index 99% rename from src/ui/projectHierarchy.js rename to src/ui/RulePad/projectHierarchy.js index 65c3ad3..ae57bcd 100644 --- a/src/ui/projectHierarchy.js +++ b/src/ui/RulePad/projectHierarchy.js @@ -7,7 +7,7 @@ import React, {Component} from "react"; import {MdSave} from "react-icons/lib/md/index"; import ReactToolTip from "react-tooltip"; -import "../App.css"; +import "../../App.css"; import {SplitButton, MenuItem, Button} from "react-bootstrap"; diff --git a/src/resources/EoI_GUI_example_1.png b/src/ui/RulePad/resources/EoI_GUI_example_1.png similarity index 100% rename from src/resources/EoI_GUI_example_1.png rename to src/ui/RulePad/resources/EoI_GUI_example_1.png diff --git a/src/resources/EoI_GUI_example_2.png b/src/ui/RulePad/resources/EoI_GUI_example_2.png similarity index 100% rename from src/resources/EoI_GUI_example_2.png rename to src/ui/RulePad/resources/EoI_GUI_example_2.png diff --git a/src/resources/EoI_TE_example_1.png b/src/ui/RulePad/resources/EoI_TE_example_1.png similarity index 100% rename from src/resources/EoI_TE_example_1.png rename to src/ui/RulePad/resources/EoI_TE_example_1.png diff --git a/src/resources/EoI_TE_example_2.png b/src/ui/RulePad/resources/EoI_TE_example_2.png similarity index 100% rename from src/resources/EoI_TE_example_2.png rename to src/ui/RulePad/resources/EoI_TE_example_2.png diff --git a/src/resources/auto_complete_example.png b/src/ui/RulePad/resources/auto_complete_example.png similarity index 100% rename from src/resources/auto_complete_example.png rename to src/ui/RulePad/resources/auto_complete_example.png diff --git a/src/resources/auto_complete_filled.png b/src/ui/RulePad/resources/auto_complete_filled.png similarity index 100% rename from src/resources/auto_complete_filled.png rename to src/ui/RulePad/resources/auto_complete_filled.png diff --git a/src/resources/auto_complete_info.png b/src/ui/RulePad/resources/auto_complete_info.png similarity index 100% rename from src/resources/auto_complete_info.png rename to src/ui/RulePad/resources/auto_complete_info.png diff --git a/src/resources/auto_complete_info_icon.png b/src/ui/RulePad/resources/auto_complete_info_icon.png similarity index 100% rename from src/resources/auto_complete_info_icon.png rename to src/ui/RulePad/resources/auto_complete_info_icon.png diff --git a/src/resources/constraint_example.png b/src/ui/RulePad/resources/constraint_example.png similarity index 100% rename from src/resources/constraint_example.png rename to src/ui/RulePad/resources/constraint_example.png diff --git a/src/resources/editor_error.png b/src/ui/RulePad/resources/editor_error.png similarity index 100% rename from src/resources/editor_error.png rename to src/ui/RulePad/resources/editor_error.png diff --git a/src/resources/editor_error_close_icon.png b/src/ui/RulePad/resources/editor_error_close_icon.png similarity index 100% rename from src/resources/editor_error_close_icon.png rename to src/ui/RulePad/resources/editor_error_close_icon.png diff --git a/src/resources/editor_error_maximize_icon.png b/src/ui/RulePad/resources/editor_error_maximize_icon.png similarity index 100% rename from src/resources/editor_error_maximize_icon.png rename to src/ui/RulePad/resources/editor_error_maximize_icon.png diff --git a/src/resources/editor_error_minimize_icon.png b/src/ui/RulePad/resources/editor_error_minimize_icon.png similarity index 100% rename from src/resources/editor_error_minimize_icon.png rename to src/ui/RulePad/resources/editor_error_minimize_icon.png diff --git a/src/resources/feedback_snippet_1.png b/src/ui/RulePad/resources/feedback_snippet_1.png similarity index 100% rename from src/resources/feedback_snippet_1.png rename to src/ui/RulePad/resources/feedback_snippet_1.png diff --git a/src/resources/feedback_snippet_2.png b/src/ui/RulePad/resources/feedback_snippet_2.png similarity index 100% rename from src/resources/feedback_snippet_2.png rename to src/ui/RulePad/resources/feedback_snippet_2.png diff --git a/src/resources/files_folders.png b/src/ui/RulePad/resources/files_folders.png similarity index 100% rename from src/resources/files_folders.png rename to src/ui/RulePad/resources/files_folders.png diff --git a/src/resources/hidden_element_interaction.png b/src/ui/RulePad/resources/hidden_element_interaction.png similarity index 100% rename from src/resources/hidden_element_interaction.png rename to src/ui/RulePad/resources/hidden_element_interaction.png diff --git a/src/resources/matching_code.png b/src/ui/RulePad/resources/matching_code.png similarity index 100% rename from src/resources/matching_code.png rename to src/ui/RulePad/resources/matching_code.png diff --git a/src/resources/new_tag.png b/src/ui/RulePad/resources/new_tag.png similarity index 100% rename from src/resources/new_tag.png rename to src/ui/RulePad/resources/new_tag.png diff --git a/src/resources/stars_toolbar.png b/src/ui/RulePad/resources/stars_toolbar.png similarity index 100% rename from src/resources/stars_toolbar.png rename to src/ui/RulePad/resources/stars_toolbar.png diff --git a/src/resources/tags.png b/src/ui/RulePad/resources/tags.png similarity index 100% rename from src/resources/tags.png rename to src/ui/RulePad/resources/tags.png diff --git a/src/resources/title_description_filled.png b/src/ui/RulePad/resources/title_description_filled.png similarity index 100% rename from src/resources/title_description_filled.png rename to src/ui/RulePad/resources/title_description_filled.png diff --git a/src/resources/visibility_class_declaration.png b/src/ui/RulePad/resources/visibility_class_declaration.png similarity index 100% rename from src/resources/visibility_class_declaration.png rename to src/ui/RulePad/resources/visibility_class_declaration.png diff --git a/src/resources/visibility_class_declaration_code.png b/src/ui/RulePad/resources/visibility_class_declaration_code.png similarity index 100% rename from src/resources/visibility_class_declaration_code.png rename to src/ui/RulePad/resources/visibility_class_declaration_code.png diff --git a/src/ui/editRuleForm.js b/src/ui/RulePad/rulePad.js similarity index 91% rename from src/ui/editRuleForm.js rename to src/ui/RulePad/rulePad.js index f66c7d5..6e50982 100644 --- a/src/ui/editRuleForm.js +++ b/src/ui/RulePad/rulePad.js @@ -4,7 +4,7 @@ import React, {Component, Fragment} from "react"; import {connect} from "react-redux"; -import "../App.css"; +import "../../App.css"; import { Alert, MenuItem, Button, FormGroup, ButtonToolbar, Label, FormControl, Modal, Dropdown, Tabs, Tab, Badge @@ -27,41 +27,42 @@ import marked from "marked"; import Joyride, {ACTIONS, EVENTS} from "react-joyride"; import ReactToolTip from "react-tooltip"; -import RuleGeneratorGui from "./ruleGenerationGUI/ruleGeneratorGui"; -import verifyTextBasedOnGrammar from "../core/languageProcessing"; +import GraphicalEditor from "../RulePad/rulePadGraphicalEditor/graphicalEditor"; +import verifyTextBasedOnGrammar from "../../core/languageProcessing"; import { matchMessages, receiveGuiTree, clearNewRuleForm, - editRuleForm, submitNewRule, submitNewTag, updateRule, updateXPaths, updateDisplayEditTutorial, ignoreFile -} from "../actions"; -import {generateGuiTrees} from "./ruleGenerationText/generateGuiTree"; -import RuleGeneratorText from "./ruleGenerationText/ruleGeneratorText"; -import Utilities from "../core/utilities"; -import {error_messages_IMarkdownString} from "./ruleGenerationText/textConstant"; - -import title_description_filled from "../resources/title_description_filled.png"; -import visibility_class_declaration from "../resources/visibility_class_declaration.png"; -import visibility_class_declaration_code from "../resources/visibility_class_declaration_code.png"; -import hidden_element_interaction from "../resources/hidden_element_interaction.png"; -import constraint_example from "../resources/constraint_example.png"; -import EoI_GUI_example_1 from "../resources/EoI_GUI_example_1.png"; -import EoI_GUI_example_2 from "../resources/EoI_GUI_example_2.png"; -import EoI_TE_example_1 from "../resources/EoI_TE_example_1.png"; -import EoI_TE_example_2 from "../resources/EoI_TE_example_2.png"; -import auto_complete_filled from "../resources/auto_complete_filled.png"; -import auto_complete_info_icon from "../resources/auto_complete_info_icon.png"; -import auto_complete_info from "../resources/auto_complete_info.png"; -import auto_complete_example from "../resources/auto_complete_example.png"; -import files_folders from "../resources/files_folders.png"; -import tags from "../resources/tags.png"; -import new_tag from "../resources/new_tag.png"; -import feedback_snippet_1 from "../resources/feedback_snippet_1.png"; -import matching_code from "../resources/matching_code.png"; - -import {checkRulesForAll} from "../core/ruleExecutor"; + editRuleForm, submitNewRule, submitNewTag, updateRule, updateXPaths, updateDisplayEditTutorial, ignoreFileChange +} from "../../actions"; +import {generateGuiTrees} from "../RulePad/rulePadTextualEditor/generateGuiTree"; +import TextualEditor from "../RulePad/rulePadTextualEditor/textualEditor"; +import Utilities from "../../core/utilities"; +import {error_messages_IMarkdownString} from "../RulePad/rulePadTextualEditor/textualEditorConstant"; + +import title_description_filled from "./resources/title_description_filled.png"; +import visibility_class_declaration from "./resources/visibility_class_declaration.png"; +import visibility_class_declaration_code from "./resources/visibility_class_declaration_code.png"; +import hidden_element_interaction from "./resources/hidden_element_interaction.png"; +import constraint_example from "./resources/constraint_example.png"; +import EoI_GUI_example_1 from "./resources/EoI_GUI_example_1.png"; +import EoI_GUI_example_2 from "./resources/EoI_GUI_example_2.png"; +import EoI_TE_example_1 from "./resources/EoI_TE_example_1.png"; +import EoI_TE_example_2 from "./resources/EoI_TE_example_2.png"; +import auto_complete_filled from "./resources/auto_complete_filled.png"; +import auto_complete_info_icon from "./resources/auto_complete_info_icon.png"; +import auto_complete_info from "./resources/auto_complete_info.png"; +import auto_complete_example from "./resources/auto_complete_example.png"; +import files_folders from "./resources/files_folders.png"; +import tags from "./resources/tags.png"; +import new_tag from "./resources/new_tag.png"; +import feedback_snippet_1 from "./resources/feedback_snippet_1.png"; +import matching_code from "./resources/matching_code.png"; + +import {checkRulesForAll} from "../../core/ruleExecutor"; import ProjectHierarchy from "./projectHierarchy"; +import {webSocketSendMessage} from "../../core/coreConstants"; -class EditRuleForm extends Component { +class RulePad extends Component { constructor(props) { super(props); @@ -309,7 +310,7 @@ class EditRuleForm extends Component { title: props.title, description: props.description, ruleTags: props.ruleTags, - folderConstraint: props.folderConstraint ? props.folderConstraint : "FOLDER", + folderConstraint: props.folderConstraint ? props.folderConstraint : "INCLUDE", filesFolders: props.filesFolders, tags: props.tags, projectHierarchy: props.projectHierarchy, @@ -365,7 +366,7 @@ class EditRuleForm extends Component { this.state.title = this.ruleI.rulePanelState.title; this.state.description = this.ruleI.rulePanelState.description; this.state.ruleTags = this.ruleI.rulePanelState.ruleTags; - this.state.folderConstraint = this.ruleI.rulePanelState.folderConstraint ? this.ruleI.rulePanelState.folderConstraint : "FOLDER"; + this.state.folderConstraint = this.ruleI.rulePanelState.folderConstraint ? this.ruleI.rulePanelState.folderConstraint : "INCLUDE"; this.state.filesFolders = this.ruleI.rulePanelState.filesFolders; this.state.tags = props.tags; // updating the rule @@ -381,7 +382,7 @@ class EditRuleForm extends Component { this.state.title = props.title; this.state.description = props.description; this.state.ruleTags = props.ruleTags; - this.state.folderConstraint = props.folderConstraint ? props.folderConstraint : "FOLDER"; + this.state.folderConstraint = props.folderConstraint ? props.folderConstraint : "INCLUDE"; this.state.filesFolders = props.filesFolders; this.state.tags = props.tags; @@ -536,7 +537,7 @@ class EditRuleForm extends Component { ) })} {Object.entries(this.state.projectHierarchy).length !== 0 ? ( -
+
{ const filesFolders = this.state.filesFolders; @@ -624,11 +625,11 @@ class EditRuleForm extends Component { renderTextUI() { return (
- { + { verifyTextBasedOnGrammar(newAutoCompleteText) .then((data) => { if (this._mounted) @@ -655,7 +656,7 @@ class EditRuleForm extends Component { }) }); }} - onUpdate={(newAutoCompleteText) => { + onUpdate={(newAutoCompleteText) => { if (this.state.autoCompleteArray.map(d => d.text).join(" ") !== newAutoCompleteText || this.state.constraintXPath === "" || this.state.quantifierXPath === "" || this.state.shouldUpdateSnippets) verifyTextBasedOnGrammar(newAutoCompleteText) @@ -683,7 +684,7 @@ class EditRuleForm extends Component { }) }); }} - onError={(errorIndex) => this.processLanguageProcessingError("ERROR_INDEX", errorIndex)} + onError={(errorIndex) => this.processLanguageProcessingError("ERROR_INDEX", errorIndex)} /> {this.renderAutoCompleteError()}
@@ -697,7 +698,7 @@ class EditRuleForm extends Component { return (
- error !== this.state.guiError ? this.setState({guiError: error}) : {}} onFilledGUI={(isFilled) => isFilled !== this.state.isFilledGUI ? this.setState({isFilledGUI: isFilled}) : {}}/>
@@ -964,7 +965,7 @@ class EditRuleForm extends Component {
 {
                                 this.props.onIgnoreFile(true);
-                                Utilities.sendToServer(this.props.ws, "XML_RESULT", d["xml"])
+                                Utilities.sendToServer(this.props.ws, webSocketSendMessage.snippet_xml_msg, d["xml"])
                             }}>
                                 
@@ -1008,7 +1009,7 @@ class EditRuleForm extends Component { title: this.ruleI.rulePanelState.title, description: this.ruleI.rulePanelState.description, ruleTags: this.ruleI.rulePanelState.ruleTags, - folderConstraint: this.ruleI.rulePanelState.folderConstraint ? this.ruleI.rulePanelState.folderConstraint : "FOLDER", + folderConstraint: this.ruleI.rulePanelState.folderConstraint ? this.ruleI.rulePanelState.folderConstraint : "INCLUDE", filesFolders: this.ruleI.rulePanelState.filesFolders, tags: this.ruleI.rulePanelState.tags, @@ -1027,13 +1028,13 @@ class EditRuleForm extends Component { // new rule else { let xPathQueryResult = this.updateFeedbackSnippet(nextProps.quantifierXPath, nextProps.constraintXPath, - nextProps.folderConstraint ? nextProps.folderConstraint : "FOLDER", nextProps.filesFolders); + nextProps.folderConstraint ? nextProps.folderConstraint : "INCLUDE", nextProps.filesFolders); this.setState({ title: nextProps.title, description: nextProps.description, ruleTags: nextProps.ruleTags, - folderConstraint: nextProps.folderConstraint ? nextProps.folderConstraint : "FOLDER", + folderConstraint: nextProps.folderConstraint ? nextProps.folderConstraint : "INCLUDE", filesFolders: nextProps.filesFolders, tags: nextProps.tags, @@ -1300,19 +1301,17 @@ class EditRuleForm extends Component { updateFeedbackSnippet(quantifierXPath, constraintXPath, folderConstraint, filesFolders) { if (quantifierXPath === "" || constraintXPath === "" || folderConstraint === "" - || (folderConstraint === "FOLDER" && filesFolders.filter((d) => d !== "").length === 0)) + || (folderConstraint === "INCLUDE" && filesFolders.filter((d) => d !== "").length === 0)) return []; let ruleInArray = [ { index: "000", - ruleType: { - constraint: folderConstraint, - checkFor: filesFolders.filter((d) => d !== ""), - type: "WITHIN" - }, - quantifier: {command: quantifierXPath.startsWith("src:unit/") ? quantifierXPath: "src:unit/" + quantifierXPath}, - constraint: {command: constraintXPath.startsWith("src:unit/") ? constraintXPath: "src:unit/" + constraintXPath}, + checkForFilesFoldersConstraints: folderConstraint, + checkForFilesFolders: filesFolders.filter((d) => d !== ""), + processFilesFolders: "WITHIN", + quantifierXPathQuery: [quantifierXPath.startsWith("src:unit/") ? quantifierXPath: "src:unit/" + quantifierXPath], + constraintXPathQuery: [constraintXPath.startsWith("src:unit/") ? constraintXPath: "src:unit/" + constraintXPath] } ]; try { @@ -1334,13 +1333,11 @@ class EditRuleForm extends Component { title: this.state.title, description: this.state.description, tags: this.state.ruleTags, - ruleType: { - constraint: this.state.folderConstraint, - checkFor: this.state.filesFolders.filter((d) => d !== ""), - type: "WITHIN" - }, - quantifier: {detail: "", command: "src:unit/" + this.state.quantifierXPath}, - constraint: {detail: "", command: "src:unit/" + this.state.constraintXPath}, + checkForFilesFoldersConstraints: this.state.folderConstraint, + checkForFilesFolders: this.state.filesFolders.filter((d) => d !== ""), + processFilesFolders: "WITHIN", + quantifierXPathQuery: ["src:unit/" + this.state.quantifierXPath], + constraintXPathQuery: ["src:unit/" + this.state.constraintXPath], grammar: this.ruleI.rulePanelState.autoCompleteArray.map(d => d.text).join(" ") }; @@ -1362,7 +1359,7 @@ class EditRuleForm extends Component { return; } - if (rule.ruleType.constraint === "" || (rule.ruleType.constraint === "FOLDER" && rule.ruleType.checkFor.length === 0)) { + if (rule.checkForFilesFoldersConstraints === "" || (rule.checkForFilesFoldersConstraints === "INCLUDE" && rule.checkForFilesFolders.length === 0)) { this.setState({ errorTitle: "Error in Submitting the updated Rule", errorMessage: "Make sure to specify the folders/files on which the rule is applied on.", @@ -1383,15 +1380,15 @@ class EditRuleForm extends Component { let isChanged = (rule.title !== this.ruleI.title) || (rule.description !== this.ruleI.description) || (JSON.stringify(rule.tags) !== JSON.stringify(this.ruleI.tags)) || - (rule.ruleType.constraint !== this.ruleI.ruleType.constraint) || - (JSON.stringify(rule.ruleType.checkFor) !== JSON.stringify(this.ruleI.ruleType.checkFor)) || + (rule.checkForFilesFoldersConstraints !== this.ruleI.checkForFilesFoldersConstraints) || + (JSON.stringify(rule.checkForFilesFolders) !== JSON.stringify(this.ruleI.checkForFilesFolders)) || (rule.grammar !== this.ruleI.grammar) || - (rule.constraint.command !== this.ruleI.constraint.command) || - (rule.quantifier.command !== this.ruleI.quantifier.command); + (rule.constraintXPathQuery[0] !== this.ruleI.constraintXPathQuery[0]) || + (rule.quantifierXPathQuery[0] !== this.ruleI.quantifierXPathQuery[0]); if (isChanged) { - this.props.onUpdateRule(rule); - Utilities.sendToServer(this.props.ws, "MODIFIED_RULE", rule); + this.props.onUpdateRule(); + Utilities.sendToServer(this.props.ws, webSocketSendMessage.modified_rule_msg, rule); } this.changeEditMode(); } @@ -1405,13 +1402,11 @@ class EditRuleForm extends Component { title: this.state.title, description: this.state.description, tags: this.state.ruleTags, - ruleType: { - constraint: this.state.folderConstraint, - checkFor: this.state.filesFolders.filter((d) => d !== ""), - type: "WITHIN" - }, - quantifier: {detail: "", command: "src:unit/" + this.state.quantifierXPath}, - constraint: {detail: "", command: "src:unit/" + this.state.constraintXPath}, + checkForFilesFoldersConstraints: this.state.folderConstraint, + checkForFilesFolders: this.state.filesFolders.filter((d) => d !== ""), + processFilesFolders: "WITHIN", + quantifierXPathQuery: ["src:unit/" + this.state.quantifierXPath], + constraintXPathQuery: ["src:unit/" + this.state.constraintXPath], grammar: this.props.autoCompleteArray.map(d => d.text).join(" ") }; @@ -1433,7 +1428,7 @@ class EditRuleForm extends Component { return; } - if (rule.ruleType.constraint === "" || (rule.ruleType.constraint === "FOLDER" && rule.ruleType.checkFor.length === 0)) { + if (rule.checkForFilesFoldersConstraints === "" || (rule.checkForFilesFoldersConstraints === "INCLUDE" && rule.checkForFilesFolders.length === 0)) { this.setState({ errorTitle: "Error in Submitting the new Rule", errorMessage: "Make sure to specify the folders/files on which the rule is applied on.", @@ -1451,8 +1446,8 @@ class EditRuleForm extends Component { return; } - this.props.onSubmitNewRule(rule); - Utilities.sendToServer(this.props.ws, "NEW_RULE", rule); + this.props.onSubmitNewRule(); + Utilities.sendToServer(this.props.ws, webSocketSendMessage.new_rule_msg, rule); this.changeEditMode(); } @@ -1485,9 +1480,10 @@ class EditRuleForm extends Component { return; } - let tag = {tagName: this.state.tagName, detail: this.state.tagDetail}; - this.props.onSubmitNewTag(tag); - Utilities.sendToServer(this.props.ws, "NEW_TAG", tag); + let tag = {ID: Math.floor(new Date().getTime() / 10).toString(), tagName: this.state.tagName, detail: this.state.tagDetail}; + this.props.onSubmitNewTag(); + Utilities.sendToServer(this.props.ws, webSocketSendMessage.new_tag_msg, tag); + this.setState({showNewTagModal: false}); } /*** @@ -1516,21 +1512,21 @@ function mapStateToProps(state) { projectHierarchy: state.projectHierarchy, // for new rule - title: state.newOrEditRule.title, - description: state.newOrEditRule.description, - ruleTags: state.newOrEditRule.ruleTags, - folderConstraint: state.newOrEditRule.folderConstraint, - filesFolders: state.newOrEditRule.filesFolders, - - autoCompleteArray: state.newOrEditRule.autoCompleteArray, - quantifierXPath: state.newOrEditRule.quantifierXPath, - constraintXPath: state.newOrEditRule.constraintXPath, + title: state.rulePadState.title, + description: state.rulePadState.description, + ruleTags: state.rulePadState.ruleTags, + folderConstraint: state.rulePadState.folderConstraint, + filesFolders: state.rulePadState.filesFolders, + + autoCompleteArray: state.rulePadState.autoCompleteArray, + quantifierXPath: state.rulePadState.quantifierXPath, + constraintXPath: state.rulePadState.constraintXPath, message: state.message, - sentMessages: state.newOrEditRule.sentMessages, - receivedMessages: state.newOrEditRule.receivedMessages, + sentMessages: state.rulePadState.sentMessages, + receivedMessages: state.rulePadState.receivedMessages, // for submitting the rule - numberOfSentMessages: state.newOrEditRule.sentMessages.length, + numberOfSentMessages: state.rulePadState.sentMessages.length, displayEditRuleTutorial: state.displayEditRuleTutorial }; @@ -1538,10 +1534,10 @@ function mapStateToProps(state) { function mapDispatchToProps(dispatch) { return { - onIgnoreFile: (shouldIgnore) => dispatch(ignoreFile(shouldIgnore)), - onSubmitNewRule: (newRule) => dispatch(submitNewRule(newRule)), - onUpdateRule: (updatedRule) => dispatch(updateRule(updatedRule)), - onSubmitNewTag: (newTag) => dispatch(submitNewTag(newTag)), + onIgnoreFile: (shouldIgnore) => dispatch(ignoreFileChange(shouldIgnore)), + onSubmitNewRule: () => dispatch(submitNewRule()), + onUpdateRule: () => dispatch(updateRule()), + onSubmitNewTag: () => dispatch(submitNewTag()), onClearForm: () => dispatch(clearNewRuleForm()), onEditForm: (ruleIndex, title, description, ruleTags, folderConstraint, filesFolders) => dispatch(editRuleForm(ruleIndex, title, description, ruleTags, folderConstraint, filesFolders)), @@ -1554,7 +1550,7 @@ function mapDispatchToProps(dispatch) { } } -export default connect(mapStateToProps, mapDispatchToProps)(EditRuleForm); +export default connect(mapStateToProps, mapDispatchToProps)(RulePad); /* custom dropdown for tags */ diff --git a/src/ui/ruleGenerationGUI/guiComponent.js b/src/ui/RulePad/rulePadGraphicalEditor/graphicalComponent.js similarity index 98% rename from src/ui/ruleGenerationGUI/guiComponent.js rename to src/ui/RulePad/rulePadGraphicalEditor/graphicalComponent.js index fe4d087..567422c 100644 --- a/src/ui/ruleGenerationGUI/guiComponent.js +++ b/src/ui/RulePad/rulePadGraphicalEditor/graphicalComponent.js @@ -14,11 +14,11 @@ import {RootCloseWrapper} from "react-overlays"; import * as marked from "marked"; import ReactToolTip from "react-tooltip"; -import {getConditionByName} from "./guiConstants"; -import {documentations_IMarkdownString} from "../ruleGenerationText/textConstant"; +import {getConditionByName} from "./graphicalEditorConstants"; +import {documentations_IMarkdownString} from "../rulePadTextualEditor/textualEditorConstant"; -class GuiComponent extends Component { +class GraphicalComponent extends Component { constructor(props) { super(props); @@ -458,10 +458,10 @@ class GuiComponent extends Component { return (
-
{(index === array.length - 1 && this.state.guiElements[childId].activeElement) ? ( @@ -1007,7 +1007,7 @@ class GuiComponent extends Component { } -export default GuiComponent; +export default GraphicalComponent; class CustomDropDown extends Component { diff --git a/src/ui/ruleGenerationGUI/ruleGeneratorGui.js b/src/ui/RulePad/rulePadGraphicalEditor/graphicalEditor.js similarity index 96% rename from src/ui/ruleGenerationGUI/ruleGeneratorGui.js rename to src/ui/RulePad/rulePadGraphicalEditor/graphicalEditor.js index 77b04e8..95b8ad7 100644 --- a/src/ui/ruleGenerationGUI/ruleGeneratorGui.js +++ b/src/ui/RulePad/rulePadGraphicalEditor/graphicalEditor.js @@ -3,17 +3,17 @@ */ import React, {Component} from "react"; -import "../../App.css"; +import "../../../App.css"; import {connect} from "react-redux"; -import GuiComponent from "./guiComponent"; -import {changeAutoCompleteTextFromGUI, changeGuiElement} from "../../actions"; -import {generateTreeForElement, getConditionByName} from "./guiConstants"; -import {autoComplete_suggestion} from "../ruleGenerationText/textConstant"; +import GraphicalComponent from "./graphicalComponent"; +import {changeAutoCompleteTextFromGUI, changeGuiElement} from "../../../actions"; +import {generateTreeForElement, getConditionByName} from "./graphicalEditorConstants"; +import {autoComplete_suggestion} from "../rulePadTextualEditor/textualEditorConstant"; -class RuleGeneratorGui extends Component { +class GraphicalEditor extends Component { constructor(props) { super(props); @@ -42,8 +42,8 @@ class RuleGeneratorGui extends Component { else { this.ruleI = props.rules[arrayIndex]; // updating the rule - this.state.guiTree = this.ruleI.rulePanelState.guiState.guiTree; - this.state.guiElements = this.ruleI.rulePanelState.guiState.guiElements; + this.state.guiTree = this.ruleI.rulePanelState.graphicalEditorState.guiTree; + this.state.guiElements = this.ruleI.rulePanelState.graphicalEditorState.guiElements; this.state.autoCompleteArray = this.ruleI.rulePanelState.autoCompleteArray; } } @@ -53,11 +53,11 @@ class RuleGeneratorGui extends Component { render() { return (
- this.processJobsBeforeSubmit(jobs)} + this.processJobsBeforeSubmit(jobs)} />
); @@ -77,8 +77,8 @@ class RuleGeneratorGui extends Component { this.setState( { ws: nextProps.ws, - guiTree: this.ruleI.rulePanelState.guiState.guiTree, - guiElements: this.ruleI.rulePanelState.guiState.guiElements, + guiTree: this.ruleI.rulePanelState.graphicalEditorState.guiTree, + guiElements: this.ruleI.rulePanelState.graphicalEditorState.guiElements, autoCompleteArray: this.ruleI.rulePanelState.autoCompleteArray }, this.receiveStateData); } @@ -731,12 +731,12 @@ class RuleGeneratorGui extends Component { case "REMOVE_ELEMENT": // search in parent children and remove elementId - // toBeDeletedIDs=[] to be removed from ...guiState.${group}.guiElements and ....guiState["quantifier/constraint"] + // toBeDeletedIDs=[] to be removed from ...graphicalEditorState.${group}.guiElements and ....graphicalEditorState["quantifier/constraint"] // build a stack=[elementId] for going through tree of elementId // while stack.size()>0 // pop one newId, add it to storeIDs // add ids of children of the popped id tree to the stack - // delete toBeDeletedIDs from ...guiState.${group}.guiElements and ....guiState["quantifier/constraint"] + // delete toBeDeletedIDs from ...graphicalEditorState.${group}.guiElements and ....graphicalEditorState["quantifier/constraint"] let parentTree = guiTree[job["value"]["parentId"]]; Object.keys(parentTree.children).forEach(childGroup => { @@ -825,9 +825,9 @@ function mapStateToProps(state) { rules: state.ruleTable, ws: state.ws, - guiTree: state.newOrEditRule.guiState.guiTree, - guiElements: state.newOrEditRule.guiState.guiElements, - autoCompleteArray: state.newOrEditRule.autoCompleteArray, + guiTree: state.rulePadState.graphicalEditorState.guiTree, + guiElements: state.rulePadState.graphicalEditorState.guiElements, + autoCompleteArray: state.rulePadState.autoCompleteArray, }; } @@ -838,4 +838,4 @@ function mapDispatchToProps(dispatch) { } } -export default connect(mapStateToProps, mapDispatchToProps)(RuleGeneratorGui); +export default connect(mapStateToProps, mapDispatchToProps)(GraphicalEditor); diff --git a/src/ui/ruleGenerationGUI/guiConstants.js b/src/ui/RulePad/rulePadGraphicalEditor/graphicalEditorConstants.js similarity index 100% rename from src/ui/ruleGenerationGUI/guiConstants.js rename to src/ui/RulePad/rulePadGraphicalEditor/graphicalEditorConstants.js diff --git a/src/ui/ruleGenerationText/generateGuiTree.js b/src/ui/RulePad/rulePadTextualEditor/generateGuiTree.js similarity index 96% rename from src/ui/ruleGenerationText/generateGuiTree.js rename to src/ui/RulePad/rulePadTextualEditor/generateGuiTree.js index 3ea22aa..dcc17bd 100644 --- a/src/ui/ruleGenerationText/generateGuiTree.js +++ b/src/ui/RulePad/rulePadTextualEditor/generateGuiTree.js @@ -4,9 +4,9 @@ import pluralize from "pluralize"; -import {generateTreeForElement, getConditionByName} from "../ruleGenerationGUI/guiConstants"; -import {grammar_keywords, special_word} from "./textConstant"; -import {initial_elementTree, initial_guiElements} from "../../initialState"; +import {generateTreeForElement, getConditionByName} from "../rulePadGraphicalEditor/graphicalEditorConstants"; +import {grammar_keywords, special_word} from "./textualEditorConstant"; +import {initial_graphicalElementTree, initial_graphicalElements} from "../../../initialState"; /** * create the quantifier and the constraint guiTree based on the grammar parse tree @@ -18,7 +18,7 @@ export async function generateGuiTrees(grammarTree) { // console.log(trees); if (Object.entries(trees).length === 0) return null; - // // match with redux state: newOrEditRule.guiState + // // match with redux state: rulePadState.graphicalEditorState return { guiTree: trees.newElementTree, guiElements: trees.newGuiElements @@ -307,12 +307,12 @@ const reverseParentChildOrder = (node) => { /** * build a tree from GUI element IDs * @param parseTree - * @return false/a tree of ids corresponding to the input tree + * return false or a tree of ids corresponding to the input tree */ const createGuiElementTree = (parseTree) => { - let newGuiElements = JSON.parse(JSON.stringify(initial_guiElements)); - let newElementTree = JSON.parse(JSON.stringify(initial_elementTree)); + let newGuiElements = JSON.parse(JSON.stringify(initial_graphicalElements)); + let newElementTree = JSON.parse(JSON.stringify(initial_graphicalElementTree)); let visitedIDs = []; @@ -431,8 +431,8 @@ const createGuiElementTree = (parseTree) => { */ const updateGuiElements = (grammarTree, guiTree) => { if (!guiTree) return {}; - let newGuiElements = JSON.parse(JSON.stringify(initial_guiElements)); - let newElementTree = JSON.parse(JSON.stringify(initial_elementTree)); + let newGuiElements = JSON.parse(JSON.stringify(initial_graphicalElements)); + let newElementTree = JSON.parse(JSON.stringify(initial_graphicalElementTree)); let checkNode = (grammarNode, guiNode) => { diff --git a/src/ui/ruleGenerationText/monacoEditorConfig.js b/src/ui/RulePad/rulePadTextualEditor/monacoEditorConfig.js similarity index 100% rename from src/ui/ruleGenerationText/monacoEditorConfig.js rename to src/ui/RulePad/rulePadTextualEditor/monacoEditorConfig.js diff --git a/src/ui/ruleGenerationText/ruleGeneratorText.js b/src/ui/RulePad/rulePadTextualEditor/textualEditor.js similarity index 92% rename from src/ui/ruleGenerationText/ruleGeneratorText.js rename to src/ui/RulePad/rulePadTextualEditor/textualEditor.js index 4114b79..8627a6f 100644 --- a/src/ui/ruleGenerationText/ruleGeneratorText.js +++ b/src/ui/RulePad/rulePadTextualEditor/textualEditor.js @@ -16,10 +16,10 @@ import { grammar_keywords, sample_phrases, sample_phrase_hash -} from "./textConstant"; +} from "./textualEditorConstant"; import {LANGUAGE_FORMAT, LANGUAGE_THEME, EDITOR_OPTION} from "./monacoEditorConfig"; -class RuleGeneratorText extends Component { +class TextualEditor extends Component { constructor(props) { super(props); @@ -541,23 +541,23 @@ class RuleGeneratorText extends Component { if (isWord || isSpecialWord) { // "someWord["] if (!lastWord.endsWith("\"") && isWord) - return [RuleGeneratorText.createGrammarSuggestion(lastWord + "\"", "", "QUOTES")]; + return [TextualEditor.createGrammarSuggestion(lastWord + "\"", "", "QUOTES")]; // … [X] with name/annotation/etc. "someWord" xWord = selectXWord(lastWithIndex - 1); let space = isMiddleOfWord ? " " : ""; - results.push(RuleGeneratorText.createGrammarSuggestion(space + "and", xWord, "AND_OR_PAREN")); - results.push(RuleGeneratorText.createGrammarSuggestion(space + "or", xWord, "AND_OR_PAREN")); - results.push(RuleGeneratorText.createGrammarSuggestion(space + "of", xWord, "OF")); + results.push(TextualEditor.createGrammarSuggestion(space + "and", xWord, "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(space + "or", xWord, "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(space + "of", xWord, "OF")); if (findUnResolvedParenthesis(wordsArray) > 0) { xWord = selectXWord(lastWithIndex - 1); if (xWord === "") return errorGenerator(303); - results.push(RuleGeneratorText.createGrammarSuggestion(space + ")", xWord + " (...", "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(space + ")", xWord + " (...", "AND_OR_PAREN")); } else if (wordsArray.indexOf("must") === -1) { xWord = selectXWord(0); if (xWord === "") return errorGenerator(303); - results.push(RuleGeneratorText.createGrammarSuggestion(space + "must have", xWord, "MUST_HAVE")); + results.push(TextualEditor.createGrammarSuggestion(space + "must have", xWord, "MUST_HAVE")); } return results; } @@ -579,7 +579,7 @@ class RuleGeneratorText extends Component { // … [X] with ( suggText = (!isSecondWord && isMiddleOfWord ? "with " : "") + "("; infoText = xWord + (!isSecondWord && isMiddleOfWord ? "" : " with"); - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); // … [X] with … beforeSuggText = !isSecondWord && isMiddleOfWord ? "with" : ""; @@ -669,7 +669,7 @@ class RuleGeneratorText extends Component { suggText = "have"; infoText = xWord + " must"; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "MUST_HAVE")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "MUST_HAVE")); beforeSuggText = (isConnectorWord && isMiddleOfWord ? lastWord + " " : "") + "("; infoText = xWord + " must have" + (isConnectorWord && isMiddleOfWord ? "" : " " + lastWord); @@ -694,13 +694,13 @@ class RuleGeneratorText extends Component { if (xWord !== "") { suggText = "and ("; infoText = xWord + " with ..."; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); suggText = "or ("; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); // [X] with (…) of suggText = "of"; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "OF")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "OF")); } // [X] … must have ( ) else if (corrOpenParanIndex > 1 && wordsArray[corrOpenParanIndex - 2] === "must") { @@ -709,9 +709,9 @@ class RuleGeneratorText extends Component { suggText = "and ("; infoText = xWord + " must have ... "; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); suggText = "or ("; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); } else return errorGenerator(302); @@ -723,7 +723,7 @@ class RuleGeneratorText extends Component { suggText = "must have"; infoText = xWord + " ..."; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "MUST_HAVE")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "MUST_HAVE")); } break; @@ -737,11 +737,11 @@ class RuleGeneratorText extends Component { if (xWord !== "" && autoComplete_suggestion[xWord].preWord && autoComplete_suggestion[xWord].preWord === "of") { suggText = (!isSecondWord && isMiddleOfWord ? "of " : "") + autoComplete_suggestion[xWord].placeholder; infoText = xWord + (!isSecondWord && isMiddleOfWord ? "" : " of"); - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, xWord)); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, xWord)); suggText = (!isSecondWord && isMiddleOfWord ? "of " : "") + "\"SOME_TEXT\""; infoText = xWord + (!isSecondWord && isMiddleOfWord ? "" : " of"); - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, xWord)); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, xWord)); break; } @@ -760,7 +760,7 @@ class RuleGeneratorText extends Component { case "": // not displayed // results = results.concat(grammar_keywords - // .map(d => RuleGeneratorText.createGrammarSuggestion(d, "", 100))); + // .map(d => TextualEditor.createGrammarSuggestion(d, "", 100))); break; default: @@ -774,7 +774,7 @@ class RuleGeneratorText extends Component { || autoComplete_suggestion[xWord].preWord !== wordsArray[lastWordIndex - 1]) break; suggText = autoComplete_suggestion[xWord].placeholder; infoText = xWord + " " + autoComplete_suggestion[xWord].preWord; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, xWord)); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, xWord)); } // after special word @@ -792,46 +792,46 @@ class RuleGeneratorText extends Component { if (lastWordIndex > 1 && findUnResolvedParenthesis(wordsArray) > 0) { suggText = ")"; infoText = ""; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); suggText = "and"; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); suggText = "or"; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "AND_OR_PAREN")); } // still typing the keyword if (isMiddleOfWord && !isSecondWord) - results.push(RuleGeneratorText.createGrammarSuggestion(d, "", d)); + results.push(TextualEditor.createGrammarSuggestion(d, "", d)); else { if (!!autoComplete_suggestion[d].withClause) { suggText = (isMiddleOfWord && !isSecondWord ? d + " " : "" ) + "with"; infoText = isMiddleOfWord && !isSecondWord ? "" : d; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "WITH")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "WITH")); } else { if (!!autoComplete_suggestion[d].preWord) { suggText = (isMiddleOfWord && !isSecondWord ? d + " " : "" ) + autoComplete_suggestion[d].preWord + " " + autoComplete_suggestion[d].placeholder; infoText = isMiddleOfWord && !isSecondWord ? "" : d; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, d)); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, d)); } suggText = (isMiddleOfWord && !isSecondWord ? d + " " : "" ) + (autoComplete_suggestion[d].preWord ? autoComplete_suggestion[d].preWord + " " : "") + "\"SOME_TEXT\""; infoText = isMiddleOfWord && !isSecondWord ? "" : d; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "QUOTES")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "QUOTES")); } if (autoComplete_suggestion[d].ofClause.length > 0) { suggText = (isMiddleOfWord && !isSecondWord ? d + " " : "") + "of"; infoText = isMiddleOfWord && !isSecondWord ? "" : d; - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "OF")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "OF")); } if (findUnResolvedParenthesis(wordsArray) === 0 && !isSecondWord && wordsArray.indexOf("must") === -1) { suggText = (!isMiddleOfWord ? "" : d + " ") + "must have"; infoText = lastWordIndex !== 0 ? xWord : (isMiddleOfWord ? "" : d); - results.push(RuleGeneratorText.createGrammarSuggestion(suggText, infoText, "MUST_HAVE")); + results.push(TextualEditor.createGrammarSuggestion(suggText, infoText, "MUST_HAVE")); } } }); @@ -841,9 +841,9 @@ class RuleGeneratorText extends Component { if (specialCase !== "") { // special case for a and and if (specialCase === "a" || specialCase === "an") - results.push(RuleGeneratorText.createGrammarSuggestion("and", "and", "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion("and", "and", "AND_OR_PAREN")); if (specialCase === "o") - results.push(RuleGeneratorText.createGrammarSuggestion("or", "or", "AND_OR_PAREN")); + results.push(TextualEditor.createGrammarSuggestion("or", "or", "AND_OR_PAREN")); } else return errorGenerator(400); } @@ -884,7 +884,7 @@ class RuleGeneratorText extends Component { if (intersection.length === 0) continue; /* eslint-disable */ results = sample_phrases.filter((d, i) => intersection.includes(i)) - .map(d => RuleGeneratorText.createPhraseSuggestion(d["replaceWordWith"], cnt)); + .map(d => TextualEditor.createPhraseSuggestion(d["replaceWordWith"], cnt)); /* eslint-enable */ } return results; @@ -908,7 +908,7 @@ class RuleGeneratorText extends Component { // check if filtering makes no result, ignore it if (result.filter(d => !doFilter ? true : d.startsWith(filterLetters)).length !== 0) result = result.filter(d => !doFilter ? true : d.startsWith(filterLetters)); - return result.map(d => RuleGeneratorText.createGrammarSuggestion(beforeSugText + (beforeSugText !== "" ? " " : "") + d, infoText, word)); + return result.map(d => TextualEditor.createGrammarSuggestion(beforeSugText + (beforeSugText !== "" ? " " : "") + d, infoText, word)); } return []; }; @@ -926,7 +926,7 @@ class RuleGeneratorText extends Component { if (grammar_keywords.includes(word)) { return autoComplete_suggestion[word].ofClause .filter(d => !doFilter ? true : d.startsWith(filterLetters)) - .map(d => RuleGeneratorText.createGrammarSuggestion(beforeSugText + (beforeSugText !== "" ? " " : "") + d, infoText, word)); + .map(d => TextualEditor.createGrammarSuggestion(beforeSugText + (beforeSugText !== "" ? " " : "") + d, infoText, word)); } return []; }; @@ -963,4 +963,4 @@ class RuleGeneratorText extends Component { } -export default RuleGeneratorText; \ No newline at end of file +export default TextualEditor; \ No newline at end of file diff --git a/src/ui/ruleGenerationText/textConstant.js b/src/ui/RulePad/rulePadTextualEditor/textualEditorConstant.js similarity index 100% rename from src/ui/ruleGenerationText/textConstant.js rename to src/ui/RulePad/rulePadTextualEditor/textualEditorConstant.js diff --git a/src/ui/headerBar.js b/src/ui/headerBar.js index 5a7e6f5..a2539f8 100644 --- a/src/ui/headerBar.js +++ b/src/ui/headerBar.js @@ -2,7 +2,6 @@ * Created by saharmehrpour on 9/7/17. */ - import React, {Component} from "react"; import "../App.css"; import Utilities from "../core/utilities"; @@ -10,8 +9,7 @@ import Utilities from "../core/utilities"; import {FormControl} from "react-bootstrap"; import {connect} from "react-redux"; import GoAlert from "react-icons/lib/go/alert"; -import {updateTagTable} from "../actions"; - +import {webSocketSendMessage} from "../core/coreConstants"; export class HeaderBar extends Component { @@ -28,16 +26,24 @@ export class HeaderBar extends Component { ) } - renderHeader() { - switch (this.props.hash[0]) { + switch (this.props.currentHash[0]) { case "tag": return (
Rules related to tag:
{this.props.title} this.props.onUpdateTag(this.props, e.target.value)} key={new Date()} + onBlur={(e) => { + if (e.target.value !== this.props.tag["detail"]) { + let filtered = this.props.tagTable.filter((d) => d["tagName"] === this.props.tag["tagName"]); + if (filtered.length === 1) { + filtered[0]["detail"] = e.target.value; + Utilities.sendToServer(this.props.ws, webSocketSendMessage.modified_tag_msg, filtered[0]); + } + } + }} + key={new Date()} placeholder="Information about tag" onClick={(e) => { e.target.style.cssText = "height:0"; @@ -95,76 +101,55 @@ export class HeaderBar extends Component { // map state to props function mapStateToProps(state) { - let path = ""; - try { - path = state["projectHierarchy"]["properties"]["canonicalPath"]; - } catch (e) { - } let props = { - tags: state["tagTable"], - hash: state["hash"], - ws: state["ws"], - ignoreFile: state["ignoreFile"], - projectPath: path + tagTable: state.tagTable, + currentHash: state.currentHash, + ws: state.ws, + projectPath: state.projectPath, + tag: "", + title: "", + content: "" }; - switch (state["hash"][0]) { + switch (state.currentHash[0]) { case "tag": - props["tag"] = state["tagTable"].filter((d) => d["tagName"] === state["hash"][1])[0]; // can throw errors - props["title"] = state["hash"][1]; - props["content"] = props["tag"]["detail"]; - break; - case "rule": - props["title"] = state["hash"][1]; - props["content"] = ""; + try { + props.tag = state.tagTable.filter((d) => d["tagName"] === state.currentHash[1])[0]; + } catch { + } + props.title = state.currentHash[1]; + props.content = props["tag"]["detail"]; break; case "rules": - props["title"] = "All Rules"; - props["content"] = ""; + props.title = "All Rules"; break; case "tagJsonChanged": - props["title"] = "tagJson.txt is changed."; - props["content"] = ""; + props.title = "tagTable.json is changed."; break; case "ruleJsonChanged": - props["title"] = "ruleJson.txt is changed."; - props["content"] = ""; - break; - case "hierarchy": - props["title"] = "Project Hierarchy"; - props["content"] = ""; + props.title = "ruleTable.json is changed."; break; case "index": - props["title"] = "Active Documentation"; - props["content"] = ""; - break; - case "genRule": - props["title"] = "New Rule"; - props["content"] = ""; + props.title = "Active Documentation"; break; case "violatedRules": - props["title"] = "Violated Rules"; - props["content"] = ""; + props.title = "Violated Rules"; break; case "rulesForFile": - props["title"] = ""; - props["content"] = state["filePath"]; + props.content = state.openFilePath; break; case "codeChanged": - props["title"] = "Code changed in"; - props["content"] = state["filePath"]; + props.title = "Code changed in"; + props.content = state.openFilePath; break; case "minedRules": - props["title"] = "Mining Rules"; - props["content"] = ""; + props.title = "Mining Rules"; break; case "featureSelection": - props["title"] = "Feature Selection"; - props["content"] = ""; + props.title = "Feature Selection"; break; default: - props["title"] = ""; - props["content"] = "Error no page is found for: " + state["hash"][0]; + props.content = "Error no page is found for: " + state.currentHash[0]; break; } @@ -172,16 +157,4 @@ function mapStateToProps(state) { } -function mapDispatchToProps(dispatch) { - return { - onUpdateTag: (props, newValue) => { - if (newValue !== props["tag"]["detail"]) { - props["tags"].filter((d) => d["tagName"] === props["hash"][1])[0]["detail"] = newValue; // can throw errors - Utilities.sendToServer(props["ws"], "MODIFIED_TAG", props["tag"]); - dispatch(updateTagTable(props["tags"])); - } - } - } -} - -export default connect(mapStateToProps, mapDispatchToProps)(HeaderBar); \ No newline at end of file +export default connect(mapStateToProps, null)(HeaderBar); \ No newline at end of file diff --git a/src/ui/navBar.js b/src/ui/navBar.js index a203a28..684de04 100644 --- a/src/ui/navBar.js +++ b/src/ui/navBar.js @@ -56,25 +56,25 @@ export class NavBar extends Component { // map state to props function mapStateToProps(state) { return { - history: state["hashManager"]["history"], - activeHash: state["hashManager"]["activeHash"], - forwardDisable: state["hashManager"]["forwardDisable"], - backDisable: state["hashManager"]["backDisable"] + history: state.hashManager.history, + activeHashIndex: state.hashManager.activeHashIndex, + forwardDisable: state.hashManager.forwardDisable, + backDisable: state.hashManager.backDisable }; } function mapDispatchToProps(dispatch) { return { backClick: (props) => { - if (props.activeHash > 0) { + if (props.activeHashIndex > 0) { dispatch(clickedOnBack()); - window.location.hash = props.history[props.activeHash - 1]; + window.location.hash = props.history[props.activeHashIndex - 1]; } }, forwardClick: (props) => { - if (props.activeHash < props.history.length - 1) { + if (props.activeHashIndex < props.history.length - 1) { dispatch(clickedOnForward()); - window.location.hash = props.history[props.activeHash + 1]; + window.location.hash = props.history[props.activeHashIndex + 1]; } } } diff --git a/src/ui/rulePanel.js b/src/ui/rulePanel.js index 521d41c..f16e884 100644 --- a/src/ui/rulePanel.js +++ b/src/ui/rulePanel.js @@ -12,9 +12,11 @@ import FaCaretDown from "react-icons/lib/fa/caret-down"; import FaCaretUp from "react-icons/lib/fa/caret-up"; import MdEdit from "react-icons/lib/md/edit"; -import {changeEditMode, ignoreFile} from "../actions"; +import {changeEditMode, ignoreFileChange} from "../actions"; import Utilities from "../core/utilities"; -import EditRuleForm from "./editRuleForm"; +import RulePad from "./RulePad/rulePad"; +import {reduxStoreMessages} from "../reduxStoreConstants"; +import {webSocketSendMessage} from "../core/coreConstants"; class RulePanel extends Component { @@ -42,7 +44,6 @@ class RulePanel extends Component { filePath: "none" }; - // existing rule if (!this.newRuleRequest && this.ruleIndex !== -1) { let indices = props.rules.map(d => d.index); @@ -55,8 +56,8 @@ class RulePanel extends Component { this.state.title = this.ruleI.title; this.state.description = this.ruleI.description; this.state.ruleTags = this.ruleI.tags; - this.state.folderConstraint = this.ruleI.ruleType.constraint; - this.state.filesFolders = this.ruleI.ruleType.checkFor; + this.state.folderConstraint = this.ruleI.checkForFilesFoldersConstraints; + this.state.filesFolders = this.ruleI.checkForFilesFolders; this.state.tags = props.tags; this.state.editMode = this.ruleI.rulePanelState.editMode; @@ -78,7 +79,7 @@ class RulePanel extends Component { if (!this.ruleI && !this.state.editMode) return null; if (this.state.editMode) return ( - this.changeEditMode()}/>); return (
@@ -121,19 +122,17 @@ class RulePanel extends Component { ); } - //componentDidUpdate doesn"t work UNSAFE_componentWillReceiveProps(nextProps) { - if (nextProps.message === "HASH") - { + if (nextProps.message === reduxStoreMessages.hash_msg) { let panelState = this.newUpdateStateUponCodeChange(nextProps.codeChanged); this.setState(panelState); } - else if (nextProps.message === "FILE_PATH_UPDATED") + else if (nextProps.message === reduxStoreMessages.file_path_update_msg) this.setState({filePath: nextProps.filePath}); - else if (nextProps.message === "CHANGE_EDIT_MODE") { + else if (nextProps.message === reduxStoreMessages.change_edit_mode_msg) { let indices = nextProps.rules.map(d => d.index); let arrayIndex = indices.indexOf(this.ruleIndex); if (this.ruleIndex !== -1) { @@ -148,7 +147,7 @@ class RulePanel extends Component { } // existing rule - else if (nextProps.message === "UPDATE_RULE_TABLE" && this.ruleIndex !== -1) { + else if (nextProps.message === reduxStoreMessages.update_rule_table_msg && this.ruleIndex !== -1) { let indices = nextProps.rules.map(d => d.index); let arrayIndex = indices.indexOf(this.ruleIndex); if (arrayIndex === -1) @@ -166,8 +165,8 @@ class RulePanel extends Component { title: this.ruleI.title, description: this.ruleI.description, ruleTags: this.ruleI.tags, - folderConstraint: this.ruleI.ruleType.constraint, - filesFolders: this.ruleI.ruleType.checkFor, + folderConstraint: this.ruleI.checkForFilesFoldersConstraints, + filesFolders: this.ruleI.checkForFilesFolders, editMode: false, className: panelState.className, @@ -190,7 +189,6 @@ class RulePanel extends Component { this.setState(panelState); } - /** * render the tab headers * @param group @@ -323,8 +321,7 @@ class RulePanel extends Component {
 {
                                     this.props.onIgnoreFile(true);
-                                    // PubSub.publish("IGNORE_FILE", [true]);
-                                    Utilities.sendToServer(this.props.ws, "XML_RESULT", d["xml"])
+                                    Utilities.sendToServer(this.props.ws, webSocketSendMessage.snippet_xml_msg, d["xml"])
                                 }}>
                                     
@@ -361,16 +358,14 @@ class RulePanel extends Component { if (this.state.filePath === "none") open = true; else - open = this.ruleI["xPathQueryResult"].filter(d => d["filePath"] === this.state.filePath).length > 0; - - + open = this.ruleI["xPathQueryResult"].filter(d => d["filePath"] === (this.props.projectPath + this.state.filePath)).length > 0; return { className: "rulePanelDiv" + (this.newRuleRequest ? " edit-bg" : ""), openPanel: open }; } - let file = this.ruleI["xPathQueryResult"].filter(d => d["filePath"] === this.state.filePath); + let file = this.ruleI["xPathQueryResult"].filter(d => d["filePath"] === (this.props.projectPath + this.state.filePath)); let ruleIfile = file.length !== 0 ? file[0]["data"] : {}; if (ruleIfile["allChanged"] === "greater" && ruleIfile["satisfiedChanged"] === ruleIfile["violatedChanged"] === "none") { return {openPanel: true, className: "rulePanelDiv blue-bg"}; @@ -403,16 +398,17 @@ function mapStateToProps(state) { return { rules: state.ruleTable, tags: state.tagTable, - codeChanged: state.hash[0] === "codeChanged", - filePath: ["rulesForFile", "codeChanged"].indexOf(state.hash[0]) !== -1 ? state.filePath : "none", + codeChanged: state.currentHash[0] === "codeChanged", + filePath: ["rulesForFile", "codeChanged"].indexOf(state.currentHash[0]) !== -1 ? state.openFilePath : "none", ws: state.ws, + projectPath: state.projectPath, message: state.message }; } function mapDispatchToProps(dispatch) { return { - onIgnoreFile: (shouldIgnore) => dispatch(ignoreFile(shouldIgnore)), + onIgnoreFile: (shouldIgnore) => dispatch(ignoreFileChange(shouldIgnore)), onChangeEditMode: (ruleIndex, newEditMode) => dispatch(changeEditMode(ruleIndex, newEditMode)) } } diff --git a/src/ui/ruleTable.js b/src/ui/ruleTable.js index 3bd9d4f..a518e2b 100644 --- a/src/ui/ruleTable.js +++ b/src/ui/ruleTable.js @@ -55,7 +55,7 @@ class RuleTable extends Component { ); } - //componentDidUpdate doesn"t work + //componentDidUpdate doesn't work UNSAFE_componentWillReceiveProps(nextProps) { this.setState(nextProps); } @@ -66,18 +66,18 @@ class RuleTable extends Component { function mapStateToProps(state) { let props = { - newRule: state.newOrEditRule.isEditMode, + newRule: state.rulePadState.isEditMode, indicesOfRulesToDisplay: state.ruleTable.map(d => d.index), - hash0: state.hash[0] + hash0: state.currentHash[0] }; - if (state.hash[0] === "tag") + if (state.currentHash[0] === "tag") props.indicesOfRulesToDisplay = state.ruleTable - .filter((d) => d["tags"].indexOf(state.hash[1]) !== -1) + .filter((d) => d["tags"].indexOf(state.currentHash[1]) !== -1) .map(d => d.index); - else if (state.hash[0] === "violatedRules") + else if (state.currentHash[0] === "violatedRules") props.indicesOfRulesToDisplay = state.ruleTable .filter(d => d["xPathQueryResult"].map(dd => dd["data"].violated).reduce((a, b) => { return a + b }, 0) !== 0) .map(d => d.index); diff --git a/src/ui/tableOfContent.js b/src/ui/tableOfContents.js similarity index 58% rename from src/ui/tableOfContent.js rename to src/ui/tableOfContents.js index 330558d..cc3ca90 100644 --- a/src/ui/tableOfContent.js +++ b/src/ui/tableOfContents.js @@ -10,31 +10,18 @@ import {MdPlaylistAdd} from "react-icons/lib/md/index"; import {changeEditMode} from "../actions"; -class TableOfContent extends Component { - - constructor() { - super(); - - this.state = { - selectedAlphabet: "All" - }; - - this.setWrapperRef = this.setWrapperRef.bind(this); - } +class TableOfContents extends Component { render() { return ( -
+

Tags

- {/*
{this.createAlphabetIndex()}
*/} - {/*
*/}
    {this.props.tags.map((tag, i) => (
  • + onClick={() => window.location.hash = "#/tag/" + tag["tagName"] }>{tag["tagName"]}
  • ) )} @@ -68,48 +55,13 @@ class TableOfContent extends Component { ) } - setWrapperRef(node) { - this.thisNode = node; - } - - selectAlphabet(tag) { - if (this.state.selectedAlphabet === "All") { - return "block"; - } - if (tag["tagName"].charAt(0).toUpperCase() === this.state.selectedAlphabet) - return "block"; - return "none"; - } - - - /** - * This function creates an alphabet list on top - */ - createAlphabetIndex() { - - let alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".split(""); - alphabet.push("All"); - - return alphabet.map((d, i) => { - return ( -
  • this.setState({selectedAlphabet: d})}> - {d} -
  • - ) - }); - - }; - - } function mapStateToProps(state) { return { - rules: state["ruleTable"], - tags: state["tagTable"], - hash: state["hash"] + rules: state.ruleTable, + tags: state.tagTable, + currentHash: state.currentHash } } @@ -119,4 +71,4 @@ function mapDispatchToProps(dispatch) { } } -export default connect(mapStateToProps, mapDispatchToProps)(TableOfContent); \ No newline at end of file +export default connect(mapStateToProps, mapDispatchToProps)(TableOfContents); \ No newline at end of file