feat: add create command modal
This commit is contained in:
parent
dbaa7a768c
commit
9a59326afa
@ -14,6 +14,7 @@
|
||||
href="./src/lib/bootstrap-icons-1.11.3/font/bootstrap-icons.css"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<script src="./lib/popper.min.js"></script>
|
||||
<script src="./lib/bootstrap-5.3.3-dist/js/bootstrap.bundle.min.js"></script>
|
||||
<title>Playback Device Server</title>
|
||||
</head>
|
||||
|
||||
@ -1,9 +1,16 @@
|
||||
function Command({ id, protocol, command, device, command_type, title } = {}) {
|
||||
function Command({
|
||||
id,
|
||||
protocol,
|
||||
command: commandNumber,
|
||||
device,
|
||||
commandType,
|
||||
title,
|
||||
} = {}) {
|
||||
let _id = id;
|
||||
let _protocol = protocol;
|
||||
let _command = command;
|
||||
let _commandNumber = commandNumber;
|
||||
let _device = device;
|
||||
let _command_type = command_type;
|
||||
let _commandType = commandType;
|
||||
let _title = title;
|
||||
|
||||
function getId() {
|
||||
@ -22,12 +29,12 @@ function Command({ id, protocol, command, device, command_type, title } = {}) {
|
||||
_protocol = protocol;
|
||||
}
|
||||
|
||||
function getCommand() {
|
||||
return _command;
|
||||
function getCommandNumber() {
|
||||
return _commandNumber;
|
||||
}
|
||||
|
||||
function setCommand(command) {
|
||||
_command = command;
|
||||
function setCommandNumber(commandNumber) {
|
||||
_commandNumber = commandNumber;
|
||||
}
|
||||
|
||||
function getDevice() {
|
||||
@ -39,11 +46,11 @@ function Command({ id, protocol, command, device, command_type, title } = {}) {
|
||||
}
|
||||
|
||||
function getCommandType() {
|
||||
return _command_type;
|
||||
return _commandType;
|
||||
}
|
||||
|
||||
function setCommandType(command_type) {
|
||||
_command_type = command_type;
|
||||
function setCommandType(commandType) {
|
||||
_commandType = commandType;
|
||||
}
|
||||
|
||||
function getTitle() {
|
||||
@ -59,8 +66,8 @@ function Command({ id, protocol, command, device, command_type, title } = {}) {
|
||||
setId,
|
||||
getProtocol,
|
||||
setProtocol,
|
||||
getCommand,
|
||||
setCommand,
|
||||
getCommandNumber,
|
||||
setCommandNumber,
|
||||
getDevice,
|
||||
setDevice,
|
||||
getCommandType,
|
||||
@ -70,4 +77,73 @@ function Command({ id, protocol, command, device, command_type, title } = {}) {
|
||||
};
|
||||
}
|
||||
|
||||
Command.Protocols = {
|
||||
samsung: "Samsung",
|
||||
nec: "NEC",
|
||||
onkyo: "Onkyo",
|
||||
apple: "Apple",
|
||||
denon: "Denon",
|
||||
sharp: "Sharp",
|
||||
panasonic: "Panasonic",
|
||||
kaseikyo: "Kaseikyo",
|
||||
jvc: "JVC",
|
||||
lg: "LG",
|
||||
sony: "Sony",
|
||||
rc5: "RC5",
|
||||
rc6: "RC6",
|
||||
universal_pulse_distance: "Universal Pulse Distance",
|
||||
universal_pulse_width: "Universal Pulse Width",
|
||||
universal_pulse_distance_width: "Universal Pulse Distance Width",
|
||||
hash: "Hash",
|
||||
pronto: "Pronto",
|
||||
bose_wave: "BoseWave",
|
||||
bang_olufsen: "Bang & Olufsen",
|
||||
lego: "Lego",
|
||||
fast: "FAST",
|
||||
whynter: "Whynter",
|
||||
magiquest: "MagiQuest",
|
||||
}
|
||||
|
||||
Command.CommandTypes = {
|
||||
power: "Power",
|
||||
input: "Input",
|
||||
one: "1",
|
||||
two: "2",
|
||||
three: "3",
|
||||
four: "4",
|
||||
five: "5",
|
||||
six: "6",
|
||||
seven: "7",
|
||||
eight: "8",
|
||||
nine: "9",
|
||||
zero: "0",
|
||||
volume_up: "Volume Up",
|
||||
volume_down: "Volume Down",
|
||||
mute: "Mute",
|
||||
channel_up: "Channel Up",
|
||||
channel_down: "Channel Down",
|
||||
menu: "Menu",
|
||||
home: "Home",
|
||||
settings: "Settings",
|
||||
options: "Options",
|
||||
up_arrow: "Up Arrow",
|
||||
down_arrow: "Down Arrow",
|
||||
left_arrow: "Left Arrow",
|
||||
right_arrow: "Right Arrow",
|
||||
select: "Select",
|
||||
info: "Info",
|
||||
back: "Back",
|
||||
exit: "Exit",
|
||||
red: "Red",
|
||||
green: "Green",
|
||||
yellow: "Yellow",
|
||||
blue: "Blue",
|
||||
rewind: "Rewind",
|
||||
play: "Play",
|
||||
pause: "Pause",
|
||||
stop: "Stop",
|
||||
forward: "Forward",
|
||||
other: "Other",
|
||||
}
|
||||
|
||||
export default Command;
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import PlaybackDevice from "./playback-device.js";
|
||||
import User from "./user.js";
|
||||
import Integration from "./integration.js";
|
||||
import Command from "./command.js";
|
||||
|
||||
const Serializer = (function () {
|
||||
function deserializeUser(object) {
|
||||
@ -29,6 +30,15 @@ const Serializer = (function () {
|
||||
if (!objects) return [];
|
||||
return objects.map((object) => deserializeIntegration(object));
|
||||
}
|
||||
|
||||
function deserializeCommand(object) {
|
||||
return new Command(object);
|
||||
}
|
||||
|
||||
function deserializeCommands(objects) {
|
||||
if (!objects) return [];
|
||||
return objects.map((object) => deserializeCommand(object));
|
||||
}
|
||||
|
||||
return {
|
||||
deserializeUser,
|
||||
@ -37,6 +47,8 @@ const Serializer = (function () {
|
||||
deserializeDevices,
|
||||
deserializeIntegration,
|
||||
deserializeIntegrations,
|
||||
deserializeCommand,
|
||||
deserializeCommands,
|
||||
};
|
||||
})();
|
||||
|
||||
|
||||
6
www/src/lib/popper.min.js
vendored
Normal file
6
www/src/lib/popper.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
215
www/src/modals/create-command-modal.jsx
Normal file
215
www/src/modals/create-command-modal.jsx
Normal file
@ -0,0 +1,215 @@
|
||||
import { createEffect, createMemo, createSignal } from "solid-js";
|
||||
import ValidatedTextInput from "../modules/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_CREATED_EVENT = "success";
|
||||
const MIN_TITLE_LENGTH = 3;
|
||||
|
||||
function CreateCommandModal(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().length >= MIN_TITLE_LENGTH);
|
||||
|
||||
createEffect(() => {
|
||||
let commandString = commandType() ? Command.CommandTypes[commandType()] : "";
|
||||
let protocolString = protocol() ? Command.Protocols[protocol()] : "";
|
||||
setTitle(commandString + " " + protocolString);
|
||||
});
|
||||
|
||||
const isFormValid = createMemo(
|
||||
() =>
|
||||
isProtocolValid() &&
|
||||
isCommandNumberValid() &&
|
||||
isDeviceValid() &&
|
||||
isCommandTypeValid() &&
|
||||
isTitleValid()
|
||||
);
|
||||
|
||||
async function handleCreateCommand() {
|
||||
let command;
|
||||
try {
|
||||
command = await RemotesService.createCommand({
|
||||
protocol: protocol(),
|
||||
commandNumber: commandNumber(),
|
||||
device: device(),
|
||||
commandType: commandType(),
|
||||
title: title(),
|
||||
});
|
||||
} catch (e) {
|
||||
setError(e.message);
|
||||
return;
|
||||
}
|
||||
resetFields();
|
||||
CreateCommandModal.Handler.hide();
|
||||
eventEmitter.dispatchEvent(COMMAND_CREATED_EVENT, command);
|
||||
}
|
||||
|
||||
function resetFields() {
|
||||
setProtocol("");
|
||||
setCommandNumber("");
|
||||
setDevice("");
|
||||
setCommandType("");
|
||||
setTitle("");
|
||||
setError("");
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal
|
||||
ref={props.ref}
|
||||
id="createCommandModal"
|
||||
modalTitle="New 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="new_command_protocol" class="col-form-label col-sm-3">
|
||||
Protocol
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary dropdown-toggle"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
{protocol() ? Command.Protocols[protocol()] : "Please select"}
|
||||
</button>
|
||||
<ul
|
||||
class="dropdown-menu"
|
||||
style="max-height: 10em; overflow-y: auto;"
|
||||
>
|
||||
{Object.keys(Command.Protocols).map((protocol) => (
|
||||
<li>
|
||||
<a
|
||||
class="dropdown-item pe-auto"
|
||||
onClick={() => setProtocol(protocol)}
|
||||
>
|
||||
{Command.Protocols[protocol]}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label for="new_command_number" class="col-form-label col-sm-3">
|
||||
Command Number
|
||||
</label>
|
||||
<ValidatedTextInput
|
||||
class="col-sm-9"
|
||||
id="new_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="new_command_device_number"
|
||||
class="col-form-label col-sm-3"
|
||||
>
|
||||
Device Number
|
||||
</label>
|
||||
<ValidatedTextInput
|
||||
class="col-sm-9"
|
||||
id="new_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="new_command_protocol" class="col-form-label col-sm-3">
|
||||
Command Type
|
||||
</label>
|
||||
<div class="col-sm-9">
|
||||
<div class="btn-group">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-secondary dropdown-toggle"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
{commandType()
|
||||
? Command.CommandTypes[commandType()]
|
||||
: "Please select"}
|
||||
</button>
|
||||
<ul
|
||||
class="dropdown-menu"
|
||||
style="max-height: 10em; overflow-y: auto;"
|
||||
>
|
||||
{Object.keys(Command.CommandTypes).map((commandType) => (
|
||||
<li>
|
||||
<a
|
||||
class="dropdown-item pe-auto"
|
||||
onClick={() => setCommandType(commandType)}
|
||||
>
|
||||
{Command.CommandTypes[commandType]}
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3 row">
|
||||
<label for="new_command_title" class="col-form-label col-sm-3">
|
||||
Title
|
||||
</label>
|
||||
<ValidatedTextInput
|
||||
class="col-sm-9"
|
||||
id="new_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={handleCreateCommand}
|
||||
class="btn btn-primary"
|
||||
disabled={!isFormValid()}
|
||||
>
|
||||
Create
|
||||
</button>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
||||
CreateCommandModal.Handler = new ModalHandler();
|
||||
CreateCommandModal.onCommandCreated = (callback) =>
|
||||
eventEmitter.on(COMMAND_CREATED_EVENT, callback);
|
||||
|
||||
export default CreateCommandModal;
|
||||
@ -6,6 +6,7 @@ import UserSettingsModal from "./user-settings-modal.jsx";
|
||||
import CreateDeviceModal from "./create-device-modal.jsx";
|
||||
import ShowRegistrationCodeModal from "./show-registration-code-modal.jsx";
|
||||
import DeleteIntegrationModal from "./delete-integration-modal.jsx";
|
||||
import CreateCommandModal from "./create-command-modal.jsx";
|
||||
|
||||
const ModalRegistry = (function () {
|
||||
const modals = [
|
||||
@ -39,6 +40,11 @@ const ModalRegistry = (function () {
|
||||
component: DeleteIntegrationModal,
|
||||
ref: null,
|
||||
},
|
||||
{
|
||||
id: "newCommandModal",
|
||||
component: CreateCommandModal,
|
||||
ref: null,
|
||||
},
|
||||
];
|
||||
|
||||
function getModals(props) {
|
||||
|
||||
@ -1,15 +1,26 @@
|
||||
import Serializer from "../data/serializer";
|
||||
|
||||
function RemotesService() {
|
||||
let commands = [];
|
||||
|
||||
async function getRemotes() {
|
||||
return [];
|
||||
}
|
||||
|
||||
async function getCommands() {
|
||||
return [];
|
||||
return [].concat(commands);
|
||||
}
|
||||
|
||||
async function createCommand(commandObject) {
|
||||
let command = Serializer.deserializeCommand(commandObject);
|
||||
commands.push(command);
|
||||
return command;
|
||||
}
|
||||
|
||||
return {
|
||||
getRemotes,
|
||||
getCommands,
|
||||
createCommand,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import { createResource, onMount } from "solid-js";
|
||||
import List from "../../modules/list";
|
||||
import RemotesService from "../../services/remotes-service";
|
||||
import CreateCommandModal from "../../modals/create-command-modal";
|
||||
|
||||
function CommandsList(props) {
|
||||
const [commands, { refetch: refetchCommands }] = createResource(
|
||||
@ -11,7 +12,18 @@ function CommandsList(props) {
|
||||
refetchCommands();
|
||||
});
|
||||
|
||||
function handleNewCommand() {}
|
||||
CreateCommandModal.onCommandCreated(() => {
|
||||
console.log("CREATED");
|
||||
refetchCommands();
|
||||
});
|
||||
|
||||
function handleNewCommand() {
|
||||
refetchCommands();
|
||||
CreateCommandModal.Handler.show();
|
||||
}
|
||||
|
||||
function handleDeleteCommand(command) {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user