diff --git a/www/index.html b/www/index.html index 05e9f74..4f0cf68 100644 --- a/www/index.html +++ b/www/index.html @@ -14,6 +14,7 @@ href="./src/lib/bootstrap-icons-1.11.3/font/bootstrap-icons.css" rel="stylesheet" /> + diff --git a/www/src/data/command.js b/www/src/data/command.js index 0900858..57679e8 100644 --- a/www/src/data/command.js +++ b/www/src/data/command.js @@ -1,7 +1,7 @@ function Command({ id, protocol, - command: commandNumber, + commandNumber, device, commandType, title, @@ -54,7 +54,8 @@ function Command({ } function getTitle() { - return _title; + if (_title) return _title; + return `${Command.CommandTypes[commandType]} (${Command.Protocols[protocol]})`; } function setTitle(title) { @@ -102,7 +103,7 @@ Command.Protocols = { fast: "FAST", whynter: "Whynter", magiquest: "MagiQuest", -} +}; Command.CommandTypes = { power: "Power", @@ -126,13 +127,13 @@ Command.CommandTypes = { home: "Home", settings: "Settings", options: "Options", - up_arrow: "Up Arrow", - down_arrow: "Down Arrow", - left_arrow: "Left Arrow", - right_arrow: "Right Arrow", - select: "Select", + up: "Up", + down: "Down", + left: "Left", + right: "Right", + enter: "Enter", info: "Info", - back: "Back", + return: "Return", exit: "Exit", red: "Red", green: "Green", @@ -144,6 +145,6 @@ Command.CommandTypes = { stop: "Stop", forward: "Forward", other: "Other", -} +}; export default Command; diff --git a/www/src/lib/papaparse-5.5.2.min.js b/www/src/lib/papaparse-5.5.2.min.js new file mode 100644 index 0000000..4284752 --- /dev/null +++ b/www/src/lib/papaparse-5.5.2.min.js @@ -0,0 +1,7 @@ +/* @license +Papa Parse +v5.5.2 +https://github.com/mholt/PapaParse +License: MIT +*/ +((e,t)=>{"function"==typeof define&&define.amd?define([],t):"object"==typeof module&&"undefined"!=typeof exports?module.exports=t():e.Papa=t()})(this,function r(){var n="undefined"!=typeof self?self:"undefined"!=typeof window?window:void 0!==n?n:{};var d,s=!n.document&&!!n.postMessage,a=n.IS_PAPA_WORKER||!1,o={},h=0,v={};function u(e){this._handle=null,this._finished=!1,this._completed=!1,this._halted=!1,this._input=null,this._baseIndex=0,this._partialLine="",this._rowCount=0,this._start=0,this._nextChunk=null,this.isFirstChunk=!0,this._completeResults={data:[],errors:[],meta:{}},function(e){var t=w(e);t.chunkSize=parseInt(t.chunkSize),e.step||e.chunk||(t.chunkSize=null);this._handle=new i(t),(this._handle.streamer=this)._config=t}.call(this,e),this.parseChunk=function(t,e){var i=parseInt(this._config.skipFirstNLines)||0;if(this.isFirstChunk&&0=this._config.preview);if(a)n.postMessage({results:r,workerId:v.WORKER_ID,finished:i});else if(U(this._config.chunk)&&!e){if(this._config.chunk(r,this._handle),this._handle.paused()||this._handle.aborted())return void(this._halted=!0);this._completeResults=r=void 0}return this._config.step||this._config.chunk||(this._completeResults.data=this._completeResults.data.concat(r.data),this._completeResults.errors=this._completeResults.errors.concat(r.errors),this._completeResults.meta=r.meta),this._completed||!i||!U(this._config.complete)||r&&r.meta.aborted||(this._config.complete(this._completeResults,this._input),this._completed=!0),i||r&&r.meta.paused||this._nextChunk(),r}this._halted=!0},this._sendError=function(e){U(this._config.error)?this._config.error(e):a&&this._config.error&&n.postMessage({workerId:v.WORKER_ID,error:e,finished:!1})}}function f(e){var r;(e=e||{}).chunkSize||(e.chunkSize=v.RemoteChunkSize),u.call(this,e),this._nextChunk=s?function(){this._readChunk(),this._chunkLoaded()}:function(){this._readChunk()},this.stream=function(e){this._input=e,this._nextChunk()},this._readChunk=function(){if(this._finished)this._chunkLoaded();else{if(r=new XMLHttpRequest,this._config.withCredentials&&(r.withCredentials=this._config.withCredentials),s||(r.onload=y(this._chunkLoaded,this),r.onerror=y(this._chunkError,this)),r.open(this._config.downloadRequestBody?"POST":"GET",this._input,!s),this._config.downloadRequestHeaders){var e,t=this._config.downloadRequestHeaders;for(e in t)r.setRequestHeader(e,t[e])}var i;this._config.chunkSize&&(i=this._start+this._config.chunkSize-1,r.setRequestHeader("Range","bytes="+this._start+"-"+i));try{r.send(this._config.downloadRequestBody)}catch(e){this._chunkError(e.message)}s&&0===r.status&&this._chunkError()}},this._chunkLoaded=function(){4===r.readyState&&(r.status<200||400<=r.status?this._chunkError():(this._start+=this._config.chunkSize||r.responseText.length,this._finished=!this._config.chunkSize||this._start>=(e=>null!==(e=e.getResponseHeader("Content-Range"))?parseInt(e.substring(e.lastIndexOf("/")+1)):-1)(r),this.parseChunk(r.responseText)))},this._chunkError=function(e){e=r.statusText||e;this._sendError(new Error(e))}}function l(e){(e=e||{}).chunkSize||(e.chunkSize=v.LocalChunkSize),u.call(this,e);var i,r,n="undefined"!=typeof FileReader;this.stream=function(e){this._input=e,r=e.slice||e.webkitSlice||e.mozSlice,n?((i=new FileReader).onload=y(this._chunkLoaded,this),i.onerror=y(this._chunkError,this)):i=new FileReaderSync,this._nextChunk()},this._nextChunk=function(){this._finished||this._config.preview&&!(this._rowCount=this._input.size,this.parseChunk(e.target.result)},this._chunkError=function(){this._sendError(i.error)}}function c(e){var i;u.call(this,e=e||{}),this.stream=function(e){return i=e,this._nextChunk()},this._nextChunk=function(){var e,t;if(!this._finished)return e=this._config.chunkSize,i=e?(t=i.substring(0,e),i.substring(e)):(t=i,""),this._finished=!i,this.parseChunk(t)}}function p(e){u.call(this,e=e||{});var t=[],i=!0,r=!1;this.pause=function(){u.prototype.pause.apply(this,arguments),this._input.pause()},this.resume=function(){u.prototype.resume.apply(this,arguments),this._input.resume()},this.stream=function(e){this._input=e,this._input.on("data",this._streamData),this._input.on("end",this._streamEnd),this._input.on("error",this._streamError)},this._checkIsFinished=function(){r&&1===t.length&&(this._finished=!0)},this._nextChunk=function(){this._checkIsFinished(),t.length?this.parseChunk(t.shift()):i=!0},this._streamData=y(function(e){try{t.push("string"==typeof e?e:e.toString(this._config.encoding)),i&&(i=!1,this._checkIsFinished(),this.parseChunk(t.shift()))}catch(e){this._streamError(e)}},this),this._streamError=y(function(e){this._streamCleanUp(),this._sendError(e)},this),this._streamEnd=y(function(){this._streamCleanUp(),r=!0,this._streamData("")},this),this._streamCleanUp=y(function(){this._input.removeListener("data",this._streamData),this._input.removeListener("end",this._streamEnd),this._input.removeListener("error",this._streamError)},this)}function i(m){var n,s,a,t,o=Math.pow(2,53),h=-o,u=/^\s*-?(\d+\.?|\.\d+|\d+\.\d+)([eE][-+]?\d+)?\s*$/,d=/^((\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z)))$/,i=this,r=0,f=0,l=!1,e=!1,c=[],p={data:[],errors:[],meta:{}};function y(e){return"greedy"===m.skipEmptyLines?""===e.join("").trim():1===e.length&&0===e[0].length}function g(){if(p&&a&&(k("Delimiter","UndetectableDelimiter","Unable to auto-detect delimiting character; defaulted to '"+v.DefaultDelimiter+"'"),a=!1),m.skipEmptyLines&&(p.data=p.data.filter(function(e){return!y(e)})),_()){if(p)if(Array.isArray(p.data[0])){for(var e=0;_()&&e(e=>(m.dynamicTypingFunction&&void 0===m.dynamicTyping[e]&&(m.dynamicTyping[e]=m.dynamicTypingFunction(e)),!0===(m.dynamicTyping[e]||m.dynamicTyping)))(e)?"true"===t||"TRUE"===t||"false"!==t&&"FALSE"!==t&&((e=>{if(u.test(e)){e=parseFloat(e);if(h=c.length?"__parsed_extra":c[r]:n,s=m.transform?m.transform(s,n):s);"__parsed_extra"===n?(i[n]=i[n]||[],i[n].push(s)):i[n]=s}return m.header&&(r>c.length?k("FieldMismatch","TooManyFields","Too many fields: expected "+c.length+" fields but parsed "+r,f+t):rm.preview?s.abort():(p.data=p.data[0],t(p,i))))}),this.parse=function(e,t,i){var r=m.quoteChar||'"',r=(m.newline||(m.newline=this.guessLineEndings(e,r)),a=!1,m.delimiter?U(m.delimiter)&&(m.delimiter=m.delimiter(e),p.meta.delimiter=m.delimiter):((r=((e,t,i,r,n)=>{var s,a,o,h;n=n||[",","\t","|",";",v.RECORD_SEP,v.UNIT_SEP];for(var u=0;u=i.length/2?"\r\n":"\r"}}function P(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function E(C){var S=(C=C||{}).delimiter,O=C.newline,x=C.comments,I=C.step,A=C.preview,T=C.fastMode,D=null,L=!1,F=null==C.quoteChar?'"':C.quoteChar,j=F;if(void 0!==C.escapeChar&&(j=C.escapeChar),("string"!=typeof S||-1=A)return b(!0);break}u.push({type:"Quotes",code:"InvalidQuotes",message:"Trailing quote on quoted field is malformed",row:h.length,index:z}),m++}}else if(x&&0===d.length&&i.substring(z,z+a)===x){if(-1===g)return b();z=g+s,g=i.indexOf(O,z),p=i.indexOf(S,z)}else if(-1!==p&&(p=A)return b(!0)}return E();function k(e){h.push(e),f=z}function v(e){var t=0;return t=-1!==e&&(e=i.substring(m+1,e))&&""===e.trim()?e.length:t}function E(e){return r||(void 0===e&&(e=i.substring(z)),d.push(e),z=n,k(d),o&&R()),b()}function w(e){z=e,k(d),d=[],g=i.indexOf(O,z)}function b(e){if(C.header&&!t&&h.length&&!L){var s=h[0],a={},o=new Set(s);let n=!1;for(let r=0;r65279!==e.charCodeAt(0)?e:e.slice(1))(e),i=new(t.download?f:c)(t)):!0===e.readable&&U(e.read)&&U(e.on)?i=new p(t):(n.File&&e instanceof File||e instanceof Object)&&(i=new l(t)),i.stream(e);(i=(()=>{var e;return!!v.WORKERS_SUPPORTED&&(e=(()=>{var e=n.URL||n.webkitURL||null,t=r.toString();return v.BLOB_URL||(v.BLOB_URL=e.createObjectURL(new Blob(["var global = (function() { if (typeof self !== 'undefined') { return self; } if (typeof window !== 'undefined') { return window; } if (typeof global !== 'undefined') { return global; } return {}; })(); global.IS_PAPA_WORKER=true; ","(",t,")();"],{type:"text/javascript"})))})(),(e=new n.Worker(e)).onmessage=g,e.id=h++,o[e.id]=e)})()).userStep=t.step,i.userChunk=t.chunk,i.userComplete=t.complete,i.userError=t.error,t.step=U(t.step),t.chunk=U(t.chunk),t.complete=U(t.complete),t.error=U(t.error),delete t.worker,i.postMessage({input:e,config:t,workerId:i.id})},v.unparse=function(e,t){var n=!1,_=!0,m=",",y="\r\n",s='"',a=s+s,i=!1,r=null,o=!1,h=((()=>{if("object"==typeof t){if("string"!=typeof t.delimiter||v.BAD_DELIMITERS.filter(function(e){return-1!==t.delimiter.indexOf(e)}).length||(m=t.delimiter),"boolean"!=typeof t.quotes&&"function"!=typeof t.quotes&&!Array.isArray(t.quotes)||(n=t.quotes),"boolean"!=typeof t.skipEmptyLines&&"string"!=typeof t.skipEmptyLines||(i=t.skipEmptyLines),"string"==typeof t.newline&&(y=t.newline),"string"==typeof t.quoteChar&&(s=t.quoteChar),"boolean"==typeof t.header&&(_=t.header),Array.isArray(t.columns)){if(0===t.columns.length)throw new Error("Option columns is empty");r=t.columns}void 0!==t.escapeChar&&(a=t.escapeChar+s),t.escapeFormulae instanceof RegExp?o=t.escapeFormulae:"boolean"==typeof t.escapeFormulae&&t.escapeFormulae&&(o=/^[=+\-@\t\r].*$/)}})(),new RegExp(P(s),"g"));"string"==typeof e&&(e=JSON.parse(e));if(Array.isArray(e)){if(!e.length||Array.isArray(e[0]))return u(null,e,i);if("object"==typeof e[0])return u(r||Object.keys(e[0]),e,i)}else if("object"==typeof e)return"string"==typeof e.data&&(e.data=JSON.parse(e.data)),Array.isArray(e.data)&&(e.fields||(e.fields=e.meta&&e.meta.fields||r),e.fields||(e.fields=Array.isArray(e.data[0])?e.fields:"object"==typeof e.data[0]?Object.keys(e.data[0]):[]),Array.isArray(e.data[0])||"object"==typeof e.data[0]||(e.data=[e.data])),u(e.fields||[],e.data||[],i);throw new Error("Unable to serialize unrecognized input");function u(e,t,i){var r="",n=("string"==typeof e&&(e=JSON.parse(e)),"string"==typeof t&&(t=JSON.parse(t)),Array.isArray(e)&&0{for(var i=0;i false } + ); + const [isComputingValueMapping, setComputingValueMapping] = + createSignal(false); + const [valueMapping, setValueMapping] = createSignal( + (() => { + let mapping = {}; + mapping[PROTOCOL_FIELD] = {}; + mapping[COMMAND_TYPE_FIELD] = {}; + return mapping; + })(), + { equals: () => false } + ); + + const canMakeNextStep = createMemo(() => { + switch (currentStep()) { + case ENTER_CSV_STEP: + return csvString() !== ""; + default: + return true; + } + }); + const fields = createMemo(() => + Object.keys(csvArray().find(() => true) || {}) + ); + + createEffect(() => { + switch (currentStep()) { + case MAP_VALUES_STEP: + onMapValuesStep(); + break; + } + }); + + function handleNextStep() { + switch (currentStep()) { + case ENTER_CSV_STEP: + handleEnterCsvStep(); + break; + case MAP_FIELDS_STEP: + handleMapFieldsStep(); + break; + case MAP_VALUES_STEP: + handleMapValuesStep(); + break; + case CONFIRM_STEP: + handleImportCommands(); + break; + default: + nextStep(); + } + } + + async function handleImportCommands() { + let newCommands = []; + try { + newCommands = await RemotesService.createCommands(commands()); + } catch (e) { + setError(e.message); + return; + } + resetFields(); + ImportCommandsModal.Handler.hide(); + eventEmitter.dispatchEvent(COMMANDS_IMPORTED_EVENT, newCommands); + } + + function EnterCsvStep() { + return ( + + + Enter CSV: + + setCsvString(e.target.value)} + > + + ); + } + + function handleEnterCsvStep() { + if (!csvString()) { + setError("Please enter a CSV string."); + return; + } + let result = Papa.parse(csvString(), { header: true }); + if (result.errors.length > 0) { + setError(result.errors[0].message); + return; + } + let csvArray = result.data; + setCsvArray(csvArray); + nextStep(); + } + + function MapFieldsStep() { + function setMapping(field, commandField) { + let mapping = fieldMapping(); + mapping[field] = commandField; + setFieldMapping(mapping); + } + return ( + + Map Fields: + + {fields().map((field) => ( + + + {field} + (e.g. {csvArray()[0][field]}) + + + + + + setMapping(field, e.target.value)} + > + + Please select + + {Object.keys(FieldTitles).map((commandField) => ( + + {FieldTitles[commandField]} + + ))} + + + + ))} + + + ); + } + + function handleMapFieldsStep() { + let usedCommandFields = []; + let mapping = fieldMapping(); + for (let field in mapping) { + if (usedCommandFields.includes(mapping[field])) { + setError("Duplicate mapping found."); + return false; + } + usedCommandFields.push(mapping[field]); + } + nextStep(); + } + + function MapValuesStep() { + function setMapping(field, value, commandValue) { + let mapping = valueMapping(); + if (!mapping[field]) mapping[field] = {}; + mapping[field][value] = commandValue; + setValueMapping(mapping); + } + return ( + + Map Values: + {Object.keys(fieldMapping()) + .filter((field) => + CommandFieldsRequiringValueMapping.includes(fieldMapping()[field]) + ) + .map((csvField) => { + let field = fieldMapping()[csvField]; + return ( + + {FieldTitles[field]}: + + {csvArray() + .map((row) => row[csvField]) + .filter( + (value, index, array) => array.indexOf(value) === index + ) + .map((value) => ( + + + {value} + + + + + + + + + setMapping(field, value, e.target.value) + } + > + + Please select + + {Object.keys(Command.Protocols).map( + (protocol) => ( + + {Command.Protocols[protocol]} + + ) + )} + + + + + setMapping(field, value, e.target.value) + } + > + + Please select + + {Object.keys(Command.CommandTypes).map( + (commandType) => ( + + {Command.CommandTypes[commandType]} + + ) + )} + + + + + + ))} + + + ); + })} + + ); + } + + function onMapValuesStep() { + setComputingValueMapping(true); + (async () => { + let valueMapping = {}; + valueMapping[PROTOCOL_FIELD] = {}; + valueMapping[COMMAND_TYPE_FIELD] = {}; + let protocolField = Object.keys(fieldMapping()).find( + (field) => fieldMapping()[field] === PROTOCOL_FIELD + ); + let commandTypeField = Object.keys(fieldMapping()).find( + (field) => fieldMapping()[field] === COMMAND_TYPE_FIELD + ); + csvArray().forEach((row) => { + let protocolValue = row[protocolField]; + let commandTypeValue = row[commandTypeField]; + if (!valueMapping[PROTOCOL_FIELD][protocolValue]) { + let result = protocolsFuse.search(protocolValue).shift(); + if (result) { + let protocol = Object.keys(Command.Protocols).find( + (protocol) => Command.Protocols[protocol] === result.item + ); + valueMapping[PROTOCOL_FIELD][protocolValue] = protocol; + } + } + if (!valueMapping[COMMAND_TYPE_FIELD][commandTypeValue]) { + let result = commandTypeFuse.search(commandTypeValue).shift(); + if (result) { + let commandType = Object.keys(Command.CommandTypes).find( + (commandType) => Command.CommandTypes[commandType] === result.item + ); + valueMapping[COMMAND_TYPE_FIELD][commandTypeValue] = commandType; + } + } + }); + setValueMapping(valueMapping); + setComputingValueMapping(false); + })(); + } + + function handleMapValuesStep() { + let protocolField = Object.keys(fieldMapping()).find( + (field) => fieldMapping()[field] === PROTOCOL_FIELD + ); + let commandNumberField = Object.keys(fieldMapping()).find( + (field) => fieldMapping()[field] === COMMAND_NUMBER_FIELD + ); + let deviceField = Object.keys(fieldMapping()).find( + (field) => fieldMapping()[field] === DEVICE_FIELD + ); + let commandTypeField = Object.keys(fieldMapping()).find( + (field) => fieldMapping()[field] === COMMAND_TYPE_FIELD + ); + let titleField = Object.keys(fieldMapping()).find( + (field) => fieldMapping()[field] === TITLE_FIELD + ); + let commands = csvArray() + .map((row) => { + let protocol = valueMapping()[PROTOCOL_FIELD][row[protocolField]]; + if (!protocol) return null; + let commandNumber = row[commandNumberField]; + let device = row[deviceField]; + let commandType = + valueMapping()[COMMAND_TYPE_FIELD][row[commandTypeField]]; + if (!commandType) return null; + let title = row[titleField]; + let command = new Command({ + protocol, + commandNumber, + device, + commandType, + title, + }); + return command; + }) + .filter((command) => command !== null); + setCommands(commands); + nextStep(); + } + + function ConfirmStep() { + return ( + + Confirm: + + {commands().map((command) => ( + + {command.getProtocol()} + {command.getCommandNumber()} + {command.getDevice()} + {command.getCommandType()} + {command.getTitle()} + + ))} + + + ); + } + + function nextStep() { + if (currentStep() >= TOTAL_STEPS) return; + setError(""); + setCurrentStep(currentStep() + 1); + } + + function previousStep() { + if (currentStep() <= 1) return; + setError(""); + setCurrentStep(currentStep() - 1); + } + + function resetFields() { + setCsvString(""); + setError(""); + } + + return ( + + + + + {error()} + + + + + + + + + + + + + + + + + + + + ); +} + +ImportCommandsModal.Handler = new ModalHandler(); +ImportCommandsModal.onCommandsImported = (callback) => + eventEmitter.on(COMMANDS_IMPORTED_EVENT, callback); + +export default ImportCommandsModal; diff --git a/www/src/modals/modal-registry.jsx b/www/src/modals/modal-registry.jsx index 84e81f6..5aae626 100644 --- a/www/src/modals/modal-registry.jsx +++ b/www/src/modals/modal-registry.jsx @@ -10,6 +10,7 @@ import CreateCommandModal from "./create-command-modal.jsx"; import DeleteCommandModal from "./delete-command-modal.jsx"; import CreateRemoteModal from "./create-remote-modal.jsx"; import DeleteRemoteModal from "./delete-remote-modal.jsx"; +import ImportCommandsModal from "./import-commands-modal.jsx"; const ModalRegistry = (function () { const modals = [ @@ -62,6 +63,11 @@ const ModalRegistry = (function () { id: "deleteRemoteModal", component: DeleteRemoteModal, ref: null, + }, + { + id: "importCommandsModal", + component: ImportCommandsModal, + ref: null, } ]; diff --git a/www/src/services/remotes-service.js b/www/src/services/remotes-service.js index 4061dbe..6712f5a 100644 --- a/www/src/services/remotes-service.js +++ b/www/src/services/remotes-service.js @@ -2,7 +2,7 @@ import Command from "../data/command"; import Serializer from "../data/serializer"; function RemotesService() { - let commands = [ + let _commands = [ new Command({ id: 1, protocol: "samsung", @@ -50,21 +50,31 @@ function RemotesService() { } async function getCommands() { - return [].concat(commands); + return [].concat(_commands); } async function createCommand(commandObject) { let command = Serializer.deserializeCommand(commandObject); let id = Math.random().toString(36).substr(2, 9); command.setId(id); - commands.push(command); + _commands.push(command); return command; } + async function createCommands(commands) { + if (!commands || commands.length === 0) return []; + commands.forEach((command) => { + let id = Math.random().toString(36).substr(2, 9); + command.setId(id); + _commands.push(command); + }); + return commands; + } + async function deleteCommand(commandId) { - let index = commands.findIndex((command) => command.getId() === commandId); + let index = _commands.findIndex((command) => command.getId() === commandId); if (index >= 0) { - commands.splice(index, 1); + _commands.splice(index, 1); } } @@ -74,6 +84,7 @@ function RemotesService() { deleteRemote, getCommands, createCommand, + createCommands, deleteCommand, }; } diff --git a/www/src/views/remotes/commands-list-view.jsx b/www/src/views/remotes/commands-list-view.jsx index 9501693..a7084ab 100644 --- a/www/src/views/remotes/commands-list-view.jsx +++ b/www/src/views/remotes/commands-list-view.jsx @@ -3,6 +3,7 @@ import List from "../../components/list"; import RemotesService from "../../services/remotes-service"; import CreateCommandModal from "../../modals/create-command-modal"; import DeleteCommandModal from "../../modals/delete-command-modal"; +import ImportCommandsModal from "../../modals/import-commands-modal"; function CommandsList(props) { const [commands, { refetch: refetchCommands }] = createResource( @@ -17,6 +18,10 @@ function CommandsList(props) { refetchCommands(); }); + ImportCommandsModal.onCommandsImported(() => { + refetchCommands(); + }); + DeleteCommandModal.onCommandDeleted(() => { refetchCommands(); }); @@ -25,11 +30,15 @@ function CommandsList(props) { refetchCommands(); CreateCommandModal.Handler.show(); } - + function handleDeleteCommand(command) { DeleteCommandModal.setCommand(command); DeleteCommandModal.Handler.show(); } + + function handleImportCommands() { + ImportCommandsModal.Handler.show(); + } return ( <> @@ -38,9 +47,13 @@ function CommandsList(props) { {props.navigation ? props.navigation : null} + + + Import + - New Command + New