feat: add edit command
This commit is contained in:
parent
8f3832657b
commit
6a9c69a535
@ -202,6 +202,15 @@ func (db *RemoteDatabase) GetCommands() ([]Command, error) {
|
||||
return commands, nil
|
||||
}
|
||||
|
||||
func (db *RemoteDatabase) UpdateCommand(command Command) error {
|
||||
queryString := "UPDATE Commands SET protocol = ?, commandNumber = ?, device = ?, commandType = ?, title = ? WHERE id = ?"
|
||||
_, error := db.Connection.Exec(queryString, command.Protocol, command.CommandNumber, command.Device, command.CommandType, command.Title, command.Id)
|
||||
if error != nil {
|
||||
return fmt.Errorf("error updating command %s: %s", command.Id, error)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (db *RemoteDatabase) DeleteCommand(commandId string) error {
|
||||
queryString := "DELETE FROM Commands WHERE id = ?"
|
||||
_, error := db.Connection.Exec(queryString, commandId)
|
||||
|
||||
@ -49,6 +49,10 @@ func (rm *RemoteManager) GetCommands() ([]d.Command, error) {
|
||||
return rm.remoteDatabase.GetCommands()
|
||||
}
|
||||
|
||||
func (rm *RemoteManager) UpdateCommand(command d.Command) error {
|
||||
return rm.remoteDatabase.UpdateCommand(command)
|
||||
}
|
||||
|
||||
func (rm *RemoteManager) SetRemoteDatabase(remoteDatabase *d.RemoteDatabase) {
|
||||
rm.remoteDatabase = remoteDatabase
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ func (r *RemoteApiHandler) Initialize(authenticator *Authenticator) {
|
||||
commandsApi := r.router.Group("/api/commands")
|
||||
commandsApi.GET("", r.handleGetCommands)
|
||||
commandsApi.POST("", r.handleCreateCommands)
|
||||
commandsApi.PUT("/:id", r.handleUpdateCommand)
|
||||
commandsApi.DELETE("/:id", r.handleDeleteCommand)
|
||||
|
||||
}
|
||||
@ -97,6 +98,20 @@ func (r *RemoteApiHandler) handleGetCommands(context echo.Context) error {
|
||||
return context.JSON(200, commands)
|
||||
}
|
||||
|
||||
func (r *RemoteApiHandler) handleUpdateCommand(context echo.Context) error {
|
||||
command := d.Command{}
|
||||
if err := context.Bind(&command); err != nil {
|
||||
SendError(400, context, err.Error())
|
||||
return nil
|
||||
}
|
||||
err := r.remoteManager.UpdateCommand(command)
|
||||
if err != nil {
|
||||
SendError(500, context, err.Error())
|
||||
return err
|
||||
}
|
||||
return context.JSON(200, "")
|
||||
}
|
||||
|
||||
func (r *RemoteApiHandler) handleDeleteCommand(context echo.Context) error {
|
||||
id := context.Param("id")
|
||||
err := r.remoteManager.DeleteCommand(id)
|
||||
|
||||
199
www/src/modals/edit-command-modal.jsx
Normal file
199
www/src/modals/edit-command-modal.jsx
Normal file
@ -0,0 +1,199 @@
|
||||
import { createEffect, createMemo, createSignal } from "solid-js";
|
||||
import ValidatedTextInput from "../components/validated-text-input.jsx";
|
||||
import EventEmitter from "../tools/event-emitter.js";
|
||||
import ModalHandler from "./modal-handler.js";
|
||||
import Modal from "./modal.jsx";
|
||||
import RemotesService from "../services/remotes-service.js";
|
||||
import Command from "../data/command.js";
|
||||
|
||||
const eventEmitter = new EventEmitter();
|
||||
const COMMAND_EDITED_EVENT = "success";
|
||||
const MIN_TITLE_LENGTH = 3;
|
||||
|
||||
const [command, setCommand] = createSignal(new Command());
|
||||
|
||||
function EditCommandModal(props) {
|
||||
const [protocol, setProtocol] = createSignal("");
|
||||
const [commandNumber, setCommandNumber] = createSignal("");
|
||||
const [device, setDevice] = createSignal("");
|
||||
const [commandType, setCommandType] = createSignal("");
|
||||
const [title, setTitle] = createSignal("");
|
||||
const [error, setError] = createSignal("");
|
||||
|
||||
const isProtocolValid = createMemo(() => protocol() !== "");
|
||||
const isCommandNumberValid = createMemo(
|
||||
() => commandNumber() !== "" && !isNaN(commandNumber())
|
||||
);
|
||||
const isDeviceValid = createMemo(() => device() !== "" && !isNaN(device()));
|
||||
const isCommandTypeValid = createMemo(() => commandType() !== "");
|
||||
const isTitleValid = createMemo(
|
||||
() => title() === "" || title().length >= MIN_TITLE_LENGTH
|
||||
);
|
||||
|
||||
createEffect(() => {
|
||||
setProtocol(command().getProtocol());
|
||||
setCommandNumber(command().getCommandNumber());
|
||||
setDevice(command().getDevice());
|
||||
setCommandType(command().getCommandType());
|
||||
setTitle(command().getTitle());
|
||||
});
|
||||
|
||||
const isFormValid = createMemo(
|
||||
() =>
|
||||
isProtocolValid() &&
|
||||
isCommandNumberValid() &&
|
||||
isDeviceValid() &&
|
||||
isCommandTypeValid() &&
|
||||
isTitleValid()
|
||||
);
|
||||
|
||||
async function handleEditCommand() {
|
||||
try {
|
||||
await RemotesService.updateCommand(
|
||||
new Command({
|
||||
id: command().getId(),
|
||||
protocol: protocol(),
|
||||
commandNumber: parseInt(commandNumber()),
|
||||
device: parseInt(device()),
|
||||
commandType: commandType(),
|
||||
title: title(),
|
||||
})
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
setError(e.message);
|
||||
return;
|
||||
}
|
||||
resetFields();
|
||||
EditCommandModal.Handler.hide();
|
||||
eventEmitter.dispatchEvent(COMMAND_EDITED_EVENT);
|
||||
}
|
||||
|
||||
function resetFields() {
|
||||
setProtocol("");
|
||||
setCommandNumber("");
|
||||
setDevice("");
|
||||
setCommandType("");
|
||||
setTitle("");
|
||||
setError("");
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
ref={props.ref}
|
||||
id="editCommandModal"
|
||||
modalTitle="Edit Command"
|
||||
centered={true}
|
||||
>
|
||||
<div class="modal-body" style="overflow-y:inherit !important;">
|
||||
<Show when={error() !== ""}>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
{error()}
|
||||
</div>
|
||||
</Show>
|
||||
<div class="mb-3 row">
|
||||
<label for="edit_command_protocol" class="col-form-label col-sm-3">
|
||||
Protocol
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<select
|
||||
class="form-select"
|
||||
onChange={(e) => setProtocol(e.target.value)}
|
||||
>
|
||||
{Object.values(Command.PROTOCOLS).map((protocol) => (
|
||||
<option
|
||||
value={protocol}
|
||||
selected={protocol === command().getProtocol()}
|
||||
>
|
||||
{Command.getProtocolString(protocol)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label for="edit_command_number" class="col-form-label col-sm-3">
|
||||
Command Number
|
||||
</label>
|
||||
<ValidatedTextInput
|
||||
class="col-sm-9"
|
||||
id="edit_command_number"
|
||||
valid={isCommandNumberValid()}
|
||||
value={commandNumber()}
|
||||
onInput={(e) => setCommandNumber(e.target.value)}
|
||||
errorText={"Command number must be a number"}
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label
|
||||
for="edit_command_device_number"
|
||||
class="col-form-label col-sm-3"
|
||||
>
|
||||
Device Number
|
||||
</label>
|
||||
<ValidatedTextInput
|
||||
class="col-sm-9"
|
||||
id="edit_command_device_number"
|
||||
valid={isDeviceValid()}
|
||||
value={device()}
|
||||
onInput={(e) => setDevice(e.target.value)}
|
||||
errorText={"Device number must be a number"}
|
||||
/>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label for="edit_command_protocol" class="col-form-label col-sm-3">
|
||||
Command Type
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<select
|
||||
class="form-select"
|
||||
onChange={(e) => setCommandType(e.target.value)}
|
||||
>
|
||||
{Object.values(Command.TYPES).map((commandType) => (
|
||||
<option
|
||||
value={commandType}
|
||||
selected={commandType === command().getCommandType()}
|
||||
>
|
||||
{Command.getTypeString(commandType)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label for="edit_command_title" class="col-form-label col-sm-3">
|
||||
Title
|
||||
</label>
|
||||
<ValidatedTextInput
|
||||
class="col-sm-9"
|
||||
id="edit_command_title"
|
||||
valid={isTitleValid()}
|
||||
value={title()}
|
||||
onInput={(e) => setTitle(e.target.value)}
|
||||
errorText={`Title must be at least ${MIN_TITLE_LENGTH} characters long`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleEditCommand}
|
||||
class="btn btn-primary"
|
||||
disabled={!isFormValid()}
|
||||
>
|
||||
Edit
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
EditCommandModal.Handler = new ModalHandler();
|
||||
EditCommandModal.onCommandEdited = (callback) =>
|
||||
eventEmitter.on(COMMAND_EDITED_EVENT, callback);
|
||||
EditCommandModal.setCommand = setCommand;
|
||||
|
||||
export default EditCommandModal;
|
||||
@ -11,6 +11,7 @@ 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";
|
||||
import EditCommandModal from "./edit-command-modal.jsx";
|
||||
|
||||
const ModalRegistry = (function () {
|
||||
const modals = [
|
||||
@ -68,7 +69,12 @@ const ModalRegistry = (function () {
|
||||
id: "importCommandsModal",
|
||||
component: ImportCommandsModal,
|
||||
ref: null,
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "editCommandModal",
|
||||
component: EditCommandModal,
|
||||
ref: null,
|
||||
},
|
||||
];
|
||||
|
||||
function getModals(props) {
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
import Command from "../data/command";
|
||||
import Serializer from "../data/serializer";
|
||||
import Net from "../tools/net";
|
||||
import WebRTCService from "./webrtc-service";
|
||||
@ -95,6 +94,20 @@ function RemoteService() {
|
||||
}
|
||||
}
|
||||
|
||||
async function updateCommand(command) {
|
||||
let commandObject = Serializer.serializeCommand(command);
|
||||
let response = await Net.sendJsonRequest({
|
||||
method: "PUT",
|
||||
url: "/api/commands/" + command.getId(),
|
||||
data: commandObject,
|
||||
});
|
||||
|
||||
if (response.status !== 200) {
|
||||
let responseData = JSON.parse(response.data);
|
||||
throw new Error(responseData.error);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteCommand(commandId) {
|
||||
let response = await Net.sendRequest({
|
||||
method: "DELETE",
|
||||
@ -109,7 +122,10 @@ function RemoteService() {
|
||||
|
||||
function sendCommand(command) {
|
||||
let commandObject = Serializer.serializeCommand(command);
|
||||
WebRTCService.sendDataJson({type: MESSAGE_TYPE_COMMAND, data: commandObject});
|
||||
WebRTCService.sendDataJson({
|
||||
type: MESSAGE_TYPE_COMMAND,
|
||||
data: commandObject,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
@ -120,6 +136,7 @@ function RemoteService() {
|
||||
getCommands,
|
||||
createCommand,
|
||||
createCommands,
|
||||
updateCommand,
|
||||
deleteCommand,
|
||||
sendCommand,
|
||||
};
|
||||
|
||||
@ -4,6 +4,7 @@ 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";
|
||||
import EditCommandModal from "../../modals/edit-command-modal";
|
||||
|
||||
function CommandsList(props) {
|
||||
const [commands, { refetch: refetchCommands }] = createResource(
|
||||
@ -17,7 +18,7 @@ function CommandsList(props) {
|
||||
CreateCommandModal.onCommandCreated(() => {
|
||||
refetchCommands();
|
||||
});
|
||||
|
||||
|
||||
ImportCommandsModal.onCommandsImported(() => {
|
||||
refetchCommands();
|
||||
});
|
||||
@ -26,6 +27,10 @@ function CommandsList(props) {
|
||||
refetchCommands();
|
||||
});
|
||||
|
||||
EditCommandModal.onCommandEdited(() => {
|
||||
refetchCommands();
|
||||
});
|
||||
|
||||
function handleNewCommand() {
|
||||
refetchCommands();
|
||||
CreateCommandModal.Handler.show();
|
||||
@ -35,11 +40,16 @@ function CommandsList(props) {
|
||||
DeleteCommandModal.setCommand(command);
|
||||
DeleteCommandModal.Handler.show();
|
||||
}
|
||||
|
||||
|
||||
function handleImportCommands() {
|
||||
ImportCommandsModal.Handler.show();
|
||||
}
|
||||
|
||||
function handleEditCommand(command) {
|
||||
EditCommandModal.setCommand(command);
|
||||
EditCommandModal.Handler.show();
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div class="d-flex flex-row">
|
||||
@ -72,7 +82,7 @@ function CommandsList(props) {
|
||||
{
|
||||
id: "protocol",
|
||||
name: "Protocol",
|
||||
width: 10,
|
||||
width: 8,
|
||||
},
|
||||
{
|
||||
id: "type",
|
||||
@ -82,7 +92,7 @@ function CommandsList(props) {
|
||||
{
|
||||
id: "options",
|
||||
name: "",
|
||||
width: 4,
|
||||
width: 6,
|
||||
},
|
||||
]}
|
||||
items={(commands() || []).map((command) => ({
|
||||
@ -101,6 +111,15 @@ function CommandsList(props) {
|
||||
options: {
|
||||
html: (
|
||||
<>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-secondary me-2"
|
||||
onClick={(event) => {
|
||||
event.stopPropagation();
|
||||
handleEditCommand(command);
|
||||
}}
|
||||
>
|
||||
<i class="bi bi-pencil-fill"></i>
|
||||
</button>
|
||||
<button
|
||||
class="btn btn-sm btn-outline-secondary me-2"
|
||||
onClick={(event) => {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user