Enhance DashboardWidget functionality: Integrate Vuex state management for socket connections, enabling real-time updates for Falukant widgets. Refactor computed properties and methods to handle socket events and improve data fetching logic. Update localization for age representation and adjust styles for better UI presentation.

This commit is contained in:
Torsten Schulz (local)
2026-01-30 08:18:50 +01:00
parent 4779a6e4af
commit 3b8e0573f2
3 changed files with 67 additions and 5 deletions

View File

@@ -56,6 +56,7 @@
</template>
<script>
import { mapState } from 'vuex';
import apiClient from '@/utils/axios.js';
export default {
@@ -75,10 +76,15 @@ export default {
data: null,
loading: false,
error: null,
isDragging: false
isDragging: false,
_daemonMessageHandler: null
};
},
computed: {
...mapState(['socket', 'daemonSocket']),
isFalukantWidget() {
return this.endpoint && String(this.endpoint).includes('falukant');
},
newsDataResults() {
const d = this.data;
if (d && typeof d === 'object' && Array.isArray(d.results)) return d.results;
@@ -119,7 +125,7 @@ export default {
const days = this.falukantData?.age;
if (days == null) return '—';
const years = Math.floor(Number(days) / 365);
return `${years} ${this.$t('admin.createNPC.years')}`;
return `${years} ${this.$t('falukant.overview.metadata.years')}`;
},
dataList() {
if (!Array.isArray(this.data) || this.data.length === 0) return [];
@@ -142,12 +148,54 @@ export default {
watch: {
endpoint: { handler: 'fetchData', immediate: false },
requestCounter: { handler: 'fetchData', immediate: false },
pauseFetch: { handler(now) { if (!now) this.fetchData(); } }
pauseFetch: { handler(now) { if (!now) this.fetchData(); } },
socket(newVal, oldVal) {
if (!this.isFalukantWidget) return;
if (oldVal) this.teardownSocketListeners();
if (newVal) this.setupSocketListeners();
},
daemonSocket(newVal, oldVal) {
if (!this.isFalukantWidget) return;
if (oldVal) this.teardownSocketListeners();
if (newVal) this.setupSocketListeners();
}
},
mounted() {
if (!this.pauseFetch && this.endpoint) this.fetchData();
if (this.isFalukantWidget) this.setupSocketListeners();
},
beforeUnmount() {
if (this.isFalukantWidget) this.teardownSocketListeners();
},
methods: {
setupSocketListeners() {
this.teardownSocketListeners();
const daemonEvents = ['falukantUpdateStatus', 'stock_change', 'familychanged'];
if (this.daemonSocket) {
this._daemonMessageHandler = (event) => {
if (event.data === 'ping') return;
try {
const data = JSON.parse(event.data);
if (daemonEvents.includes(data.event)) this.fetchData();
} catch (_) {}
};
this.daemonSocket.addEventListener('message', this._daemonMessageHandler);
}
if (this.socket) {
this.socket.on('falukantUpdateStatus', () => this.fetchData());
this.socket.on('falukantBranchUpdate', () => this.fetchData());
}
},
teardownSocketListeners() {
if (this.daemonSocket && this._daemonMessageHandler) {
this.daemonSocket.removeEventListener('message', this._daemonMessageHandler);
this._daemonMessageHandler = null;
}
if (this.socket) {
this.socket.off('falukantUpdateStatus');
this.socket.off('falukantBranchUpdate');
}
},
async fetchData() {
if (!this.endpoint || this.pauseFetch) return;
this.loading = true;
@@ -202,6 +250,7 @@ export default {
<style scoped>
.dashboard-widget {
min-height: 200px;
max-height: 420px;
display: flex;
flex-direction: column;
background: var(--dashboard-widget-bg, #fff);
@@ -249,9 +298,9 @@ export default {
.dashboard-widget__frame {
flex: 1;
min-height: 160px;
min-height: 0;
padding: 12px;
overflow: auto;
overflow-y: auto;
}
.dashboard-widget__state {