Refactor code structure for improved readability and maintainability
This commit is contained in:
+2
-3
@@ -1,13 +1,12 @@
|
||||
FROM node:20-alpine
|
||||
FROM node:22-alpine
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package*.json ./
|
||||
RUN npm install
|
||||
RUN npm ci
|
||||
|
||||
COPY . .
|
||||
|
||||
EXPOSE 5173
|
||||
|
||||
CMD ["npm", "run", "dev"]
|
||||
|
||||
|
||||
+3
-2
@@ -6,7 +6,8 @@
|
||||
"scripts": {
|
||||
"dev": "vite --host 0.0.0.0 --port 5173",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview --host 0.0.0.0 --port 4173"
|
||||
"preview": "vite preview --host 0.0.0.0 --port 4173",
|
||||
"check": "vite build"
|
||||
},
|
||||
"dependencies": {
|
||||
"cors": "^2.8.6",
|
||||
@@ -20,4 +21,4 @@
|
||||
"@vitejs/plugin-react": "^4.4.1",
|
||||
"vite": "^6.0.7"
|
||||
}
|
||||
}
|
||||
}
|
||||
+38
-11
@@ -741,7 +741,8 @@ export default function App() {
|
||||
const [manualDatapointDraft, setManualDatapointDraft] = useState(emptyManualDatapointDraft());
|
||||
const [scanResults, setScanResults] = useState({ opcua: null, bacnet: null, ipsymcon: null });
|
||||
const [debugSnapshot, setDebugSnapshot] = useState(null);
|
||||
const [integrationSettings, setIntegrationSettings] = useState({ mailApiKey: "", whatsappApiKey: "", phoneApiKey: "" });
|
||||
const [integrationSettings, setIntegrationSettings] = useState({ mailUrl: "https://mailapi.se-inno.de", whatsappUrl: "https://whatsappapi.se-inno.de", voipUrl: "https://voipapi.se-inno.de", mailApiKey: "", whatsappApiKey: "", voipApiKey: "" });
|
||||
const [integrationStatus, setIntegrationStatus] = useState({ mailConfigured: false, whatsappConfigured: false, voipConfigured: false });
|
||||
const [runnerJobs, setRunnerJobs] = useState([]);
|
||||
const [runnerQueue, setRunnerQueue] = useState([]);
|
||||
const [runnerDraft, setRunnerDraft] = useState({ name: "", selectionId: "", enabled: true, time: "06:00", rangeHours: "24", delimiter: ";", mailEnabled: false, mailTo: "", mailSubject: "Trenddaten", mailMessage: "Automatischer Export aus SE Local Trenddata." });
|
||||
@@ -1137,12 +1138,16 @@ export default function App() {
|
||||
}, [canEditAliases, canManageSources, token]);
|
||||
useEffect(() => {
|
||||
if (!token || !canManageIntegrations) {
|
||||
setIntegrationSettings({ mailApiKey: "", whatsappApiKey: "", phoneApiKey: "" });
|
||||
setIntegrationSettings({ mailUrl: "https://mailapi.se-inno.de", whatsappUrl: "https://whatsappapi.se-inno.de", voipUrl: "https://voipapi.se-inno.de", mailApiKey: "", whatsappApiKey: "", voipApiKey: "" });
|
||||
setIntegrationStatus({ mailConfigured: false, whatsappConfigured: false, voipConfigured: false });
|
||||
return;
|
||||
}
|
||||
|
||||
api.getIntegrations(token)
|
||||
.then((result) => setIntegrationSettings(result.settings || { mailApiKey: "", whatsappApiKey: "", phoneApiKey: "" }))
|
||||
.then((result) => {
|
||||
setIntegrationSettings({ mailApiKey: "", whatsappApiKey: "", voipApiKey: "", ...(result.settings || {}) });
|
||||
setIntegrationStatus({ mailConfigured: Boolean(result.mailConfigured), whatsappConfigured: Boolean(result.whatsappConfigured), voipConfigured: Boolean(result.voipConfigured) });
|
||||
})
|
||||
.catch((error) => setBootError(error.message));
|
||||
}, [canManageIntegrations, token]);
|
||||
|
||||
@@ -2086,17 +2091,36 @@ export default function App() {
|
||||
}
|
||||
};
|
||||
|
||||
const applyIntegrationResult = (result) => {
|
||||
setIntegrationSettings({ mailApiKey: "", whatsappApiKey: "", voipApiKey: "", ...(result.settings || {}) });
|
||||
setIntegrationStatus({ mailConfigured: Boolean(result.mailConfigured), whatsappConfigured: Boolean(result.whatsappConfigured), voipConfigured: Boolean(result.voipConfigured) });
|
||||
};
|
||||
|
||||
const saveIntegrationSettings = async () => {
|
||||
resetFlash();
|
||||
try {
|
||||
const result = await api.saveIntegrations(token, integrationSettings);
|
||||
setIntegrationSettings(result.settings || integrationSettings);
|
||||
applyIntegrationResult(result);
|
||||
setSuccessMessage("API-Verbindungen gespeichert.");
|
||||
} catch (error) {
|
||||
setBootError(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
const clearIntegrationKey = async (channel) => {
|
||||
const labels = { mail: "Mail", whatsapp: "WhatsApp", voip: "Telefon" };
|
||||
if (!window.confirm(`${labels[channel]} API-Key wirklich entfernen?`)) return;
|
||||
resetFlash();
|
||||
try {
|
||||
const clearField = channel === "mail" ? "clearMailApiKey" : channel === "whatsapp" ? "clearWhatsappApiKey" : "clearVoipApiKey";
|
||||
const result = await api.saveIntegrations(token, { ...integrationSettings, [clearField]: true });
|
||||
applyIntegrationResult(result);
|
||||
setSuccessMessage(`${labels[channel]} API-Key entfernt.`);
|
||||
} catch (error) {
|
||||
setBootError(error.message);
|
||||
}
|
||||
};
|
||||
|
||||
const resetRunnerDraft = () => {
|
||||
setRunnerDraft({ name: "", selectionId: "", enabled: true, time: "06:00", rangeHours: "24", delimiter: ";", mailEnabled: false, mailTo: "", mailSubject: "Trenddaten", mailMessage: "Automatischer Export aus SE Local Trenddata." });
|
||||
};
|
||||
@@ -3484,18 +3508,21 @@ export default function App() {
|
||||
<div className="form-grid compact-forms">
|
||||
<label>
|
||||
<span>Mail API-Key</span>
|
||||
<input type="password" value={integrationSettings.mailApiKey || ""} onChange={(event) => setIntegrationSettings((current) => ({ ...current, mailApiKey: event.target.value }))} />
|
||||
<small className="muted">{integrationSettings.mailApiKey ? "Key gespeichert" : "Kein Key hinterlegt"}</small>
|
||||
<input type="password" autoComplete="new-password" value={integrationSettings.mailApiKey || ""} placeholder={integrationStatus.mailConfigured ? "Key gespeichert - nur zum Ersetzen eingeben" : "API-Key eingeben"} onChange={(event) => setIntegrationSettings((current) => ({ ...current, mailApiKey: event.target.value }))} />
|
||||
<small className="muted">{integrationStatus.mailConfigured ? "Key gespeichert" : "Kein Key hinterlegt"}</small>
|
||||
{integrationStatus.mailConfigured ? <button className="ghost-button compact-button danger" type="button" onClick={() => clearIntegrationKey("mail")}>Key entfernen</button> : null}
|
||||
</label>
|
||||
<label>
|
||||
<span>WhatsApp API-Key</span>
|
||||
<input type="password" value={integrationSettings.whatsappApiKey || ""} onChange={(event) => setIntegrationSettings((current) => ({ ...current, whatsappApiKey: event.target.value }))} />
|
||||
<small className="muted">{integrationSettings.whatsappApiKey ? "Key gespeichert" : "Kein Key hinterlegt"}</small>
|
||||
<input type="password" autoComplete="new-password" value={integrationSettings.whatsappApiKey || ""} placeholder={integrationStatus.whatsappConfigured ? "Key gespeichert - nur zum Ersetzen eingeben" : "API-Key eingeben"} onChange={(event) => setIntegrationSettings((current) => ({ ...current, whatsappApiKey: event.target.value }))} />
|
||||
<small className="muted">{integrationStatus.whatsappConfigured ? "Key gespeichert" : "Kein Key hinterlegt"}</small>
|
||||
{integrationStatus.whatsappConfigured ? <button className="ghost-button compact-button danger" type="button" onClick={() => clearIntegrationKey("whatsapp")}>Key entfernen</button> : null}
|
||||
</label>
|
||||
<label>
|
||||
<span>Telefon API-Key</span>
|
||||
<input type="password" value={integrationSettings.phoneApiKey || ""} onChange={(event) => setIntegrationSettings((current) => ({ ...current, phoneApiKey: event.target.value }))} />
|
||||
<small className="muted">{integrationSettings.phoneApiKey ? "Key gespeichert" : "Kein Key hinterlegt"}</small>
|
||||
<input type="password" autoComplete="new-password" value={integrationSettings.voipApiKey || ""} placeholder={integrationStatus.voipConfigured ? "Key gespeichert - nur zum Ersetzen eingeben" : "API-Key eingeben"} onChange={(event) => setIntegrationSettings((current) => ({ ...current, voipApiKey: event.target.value }))} />
|
||||
<small className="muted">{integrationStatus.voipConfigured ? "Key gespeichert" : "Kein Key hinterlegt"}</small>
|
||||
{integrationStatus.voipConfigured ? <button className="ghost-button compact-button danger" type="button" onClick={() => clearIntegrationKey("voip")}>Key entfernen</button> : null}
|
||||
</label>
|
||||
</div>
|
||||
<button className="primary-button compact-button" type="button" onClick={saveIntegrationSettings}>API-Keys speichern</button>
|
||||
@@ -3554,7 +3581,7 @@ export default function App() {
|
||||
<span>aktiv</span>
|
||||
</label>
|
||||
<label className="checkbox-field compact-check">
|
||||
<input type="checkbox" checked={runnerDraft.mailEnabled === true} onChange={(event) => setRunnerDraft((current) => ({ ...current, mailEnabled: event.target.checked }))} disabled={!integrationSettings.mailEnabled && !integrationSettings.mailApiKey} />
|
||||
<input type="checkbox" checked={runnerDraft.mailEnabled === true} onChange={(event) => setRunnerDraft((current) => ({ ...current, mailEnabled: event.target.checked }))} disabled={!integrationStatus.mailConfigured && !integrationSettings.mailApiKey} />
|
||||
<span>CSV per Mail verschicken</span>
|
||||
</label>
|
||||
<label>
|
||||
|
||||
Reference in New Issue
Block a user