feat(ui): add integration delete optiofeat(ui): add integration delete

optionn
This commit is contained in:
Fritz Heiden 2025-03-20 19:22:36 +01:00
parent 1caac72771
commit a13a21a67d
6 changed files with 124 additions and 4 deletions

View File

@ -1,4 +1,4 @@
function Integration({ id, name }) {
function Integration({ id, name } = {}) {
let _id = id;
let _name = name;

View File

@ -25,6 +25,7 @@ const Serializer = (function () {
}
function deserializeIntegrations(objects) {
if (!objects) return [];
return objects.map((object) => deserializeIntegration(object));
}

View File

@ -0,0 +1,69 @@
import { createEffect, createSignal } from "solid-js";
import Modal from "./modal.jsx";
import UserService from "../services/user-service.js";
import EventEmitter from "../tools/event-emitter.js";
import User from "../data/user.js";
import ValidatedTextInput from "../modules/validated-text-input.jsx";
import ModalHandler from "./modal-handler.js";
import Integration from "../data/integration.js";
import DeviceService from "../services/device-service.js";
const [integration, setIntegration] = createSignal(new Integration());
const eventEmitter = new EventEmitter();
const INTEGRATION_DELETED_EVENT = "success";
function DeleteIntegrationModal(props) {
const [error, setError] = createSignal("");
async function handleDeleteIntegration() {
try {
await DeviceService.deleteIntegration(integration().getId());
} catch (e) {
setError(e.message);
throw e;
}
DeleteIntegrationModal.Handler.hide();
eventEmitter.dispatchEvent(INTEGRATION_DELETED_EVENT, integration);
}
return (
<Modal
ref={props.ref}
id="deleteIntegrationModal"
modalTitle="Delete integration"
centered={true}
>
<div class="modal-body">
<Show when={error() !== ""}>
<div class="alert alert-danger" role="alert">
{error()}
</div>
</Show>
<div class="mb-3 row">
<span>
Do you really want to delete the integration {integration().getName()}?
</span>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">
Cancel
</button>
<button
type="button"
onClick={handleDeleteIntegration}
class="btn btn-danger"
>
Delete
</button>
</div>
</Modal>
);
}
DeleteIntegrationModal.Handler = new ModalHandler();
DeleteIntegrationModal.setIntegration = setIntegration;
DeleteIntegrationModal.onIntegrationDeleted = (callback) =>
eventEmitter.on(INTEGRATION_DELETED_EVENT, callback);
export default DeleteIntegrationModal;

View File

@ -5,6 +5,7 @@ import DeleteUserModal from "./delete-user-modal.jsx";
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";
const ModalRegistry = (function () {
const modals = [
@ -33,6 +34,11 @@ const ModalRegistry = (function () {
component: ShowRegistrationCodeModal,
ref: null,
},
{
id: "deleteIntegrationModal",
component: DeleteIntegrationModal,
ref: null,
},
];
function getModals(props) {

View File

@ -93,6 +93,18 @@ function DeviceService() {
integrations = Serializer.deserializeIntegrations(integrations);
return integrations;
}
async function deleteIntegration(id) {
let response = await Net.sendJsonRequest({
method: "DELETE",
url: "/api/integrations/" + id,
});
if (response.status !== 200) {
let responseData = JSON.parse(response.data);
throw new Error(responseData.error);
}
}
return {
getDevices,
@ -101,6 +113,7 @@ function DeviceService() {
deleteDevice,
getRegistrationCode,
getIntegrations,
deleteIntegration,
};
}

View File

@ -4,6 +4,7 @@ import List from "../modules/list";
import CreateDeviceModal from "../modals/create-device-modal";
import DeviceService from "../services/device-service";
import ShowRegistrationCodeModal from "../modals/show-registration-code-modal";
import DeleteIntegrationModal from "../modals/delete-integration-modal";
function DevicesView(props) {
const DEVICES_LIST_TYPE = "devices";
@ -11,7 +12,9 @@ function DevicesView(props) {
const [listType, setListType] = createSignal(DEVICES_LIST_TYPE);
const [devices, setDevices] = createSignal([]);
const [integrations] = createResource(DeviceService.getIntegrations);
const [integrations, { refetch: refetchIntegrations }] = createResource(
DeviceService.getIntegrations
);
CreateDeviceModal.onDeviceCreated(() => {
handleRefreshDevices();
@ -19,6 +22,9 @@ function DevicesView(props) {
onMount(() => {
handleRefreshDevices();
DeleteIntegrationModal.onIntegrationDeleted(() => {
refetchIntegrations();
});
});
function handleNewDevice() {
@ -29,11 +35,16 @@ function DevicesView(props) {
let devices = await DeviceService.getDevices();
setDevices(devices);
}
function handleRegisterIntegration() {
ShowRegistrationCodeModal.Handler.show();
}
function handleDeleteIntegration(integration) {
DeleteIntegrationModal.setIntegration(integration);
DeleteIntegrationModal.Handler.show();
}
return (
<div
class={
@ -76,7 +87,10 @@ function DevicesView(props) {
</button>
</Show>
<Show when={listType() === INTEGRATION_LIST_TYPE}>
<button class="btn btn-dark me-2 mb-3" onClick={handleRegisterIntegration}>
<button
class="btn btn-dark me-2 mb-3"
onClick={handleRegisterIntegration}
>
<i class="bi bi-plus-square me-2"></i>
Register
</button>
@ -127,6 +141,18 @@ function DevicesView(props) {
name: {
text: integration.getName(),
},
options: {
html: (
<>
<button
class="btn btn-outline-secondary me-2"
onClick={() => handleDeleteIntegration(integration)}
>
<i class="bi bi-trash-fill"></i>
</button>
</>
),
},
integration: integration,
}))}
class={"flex-fill"}
@ -140,6 +166,11 @@ function DevicesView(props) {
id: "name",
name: "Name",
},
{
id: "options",
name: "",
width: 4,
},
]}
></List>
</Show>