update
This commit is contained in:
@@ -535,10 +535,12 @@ export class FusionClockPortal extends Interaction {
|
||||
const reasonEl = document.getElementById("fclk-reason-text");
|
||||
const timeEl = document.getElementById("fclk-reason-time");
|
||||
const reason = reasonEl ? reasonEl.value.trim() : "";
|
||||
const depTime = timeEl ? timeEl.value.trim() : "";
|
||||
const rawTime = timeEl ? timeEl.value.trim() : "";
|
||||
const depTime = rawTime ? new Date(rawTime).toISOString() : "";
|
||||
|
||||
if (!reason) {
|
||||
this._showToast("Please provide a reason.", "error");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -356,9 +356,10 @@ export class FusionClockPortalFAB extends Interaction {
|
||||
const submitBtn = document.getElementById("fclk-pfab-reason-submit-btn");
|
||||
if (submitBtn) submitBtn.disabled = true;
|
||||
try {
|
||||
const rawTime = timeEl ? timeEl.value.trim() : "";
|
||||
await rpc("/fusion_clock/submit_reason", {
|
||||
reason: reason,
|
||||
departure_time: timeEl ? timeEl.value : "",
|
||||
departure_time: rawTime ? new Date(rawTime).toISOString() : "",
|
||||
});
|
||||
modal.style.display = "none";
|
||||
if (reasonEl) reasonEl.value = "";
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { Component, useState, onWillStart, onMounted, onWillUnmount } from "@odoo/owl";
|
||||
import { Dropdown } from "@web/core/dropdown/dropdown";
|
||||
import { DropdownItem } from "@web/core/dropdown/dropdown_item";
|
||||
import { useDropdownState } from "@web/core/dropdown/dropdown_hooks";
|
||||
import { rpc } from "@web/core/network/rpc";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { useService } from "@web/core/utils/hooks";
|
||||
|
||||
export class FusionClockFAB extends Component {
|
||||
static props = {};
|
||||
static template = "fusion_clock.ClockFAB";
|
||||
static template = "fusion_clock.ClockSystray";
|
||||
static components = { Dropdown, DropdownItem };
|
||||
|
||||
setup() {
|
||||
this.notification = useService("notification");
|
||||
this.dropdown = useDropdownState();
|
||||
|
||||
this.state = useState({
|
||||
isCheckedIn: false,
|
||||
isDisplayed: false,
|
||||
expanded: false,
|
||||
checkInTime: null,
|
||||
locationName: "",
|
||||
timerDisplay: "00:00:00",
|
||||
@@ -40,38 +44,22 @@ export class FusionClockFAB extends Component {
|
||||
if (this.state.isCheckedIn) {
|
||||
this._startTimer();
|
||||
}
|
||||
// Poll every 15s to stay in sync with portal clock-outs
|
||||
this._pollInterval = setInterval(() => this._fetchStatus(), 15000);
|
||||
|
||||
// Re-sync immediately when browser tab regains focus
|
||||
this._onFocus = () => this._fetchStatus();
|
||||
window.addEventListener("focus", this._onFocus);
|
||||
|
||||
// Close panel when clicking outside
|
||||
this._onDocClick = (ev) => {
|
||||
if (!this.state.expanded) return;
|
||||
const el = ev.target.closest(".fclk-fab-wrapper");
|
||||
if (!el) this.state.expanded = false;
|
||||
};
|
||||
document.addEventListener("click", this._onDocClick, true);
|
||||
});
|
||||
|
||||
onWillUnmount(() => {
|
||||
this._stopTimer();
|
||||
if (this._pollInterval) clearInterval(this._pollInterval);
|
||||
if (this._onDocClick) document.removeEventListener("click", this._onDocClick, true);
|
||||
if (this._onFocus) window.removeEventListener("focus", this._onFocus);
|
||||
});
|
||||
}
|
||||
|
||||
togglePanel() {
|
||||
this.state.expanded = !this.state.expanded;
|
||||
this.state.error = "";
|
||||
// Always re-fetch when opening the panel
|
||||
if (this.state.expanded) {
|
||||
this._fetchStatus();
|
||||
}
|
||||
}
|
||||
// =================================================================
|
||||
// Server sync
|
||||
// =================================================================
|
||||
|
||||
async _fetchStatus() {
|
||||
try {
|
||||
@@ -83,6 +71,10 @@ export class FusionClockFAB extends Component {
|
||||
this.state.todayHours = (result.today_hours || 0).toFixed(1);
|
||||
this.state.weekHours = (result.week_hours || 0).toFixed(1);
|
||||
|
||||
if (result.pending_reason) {
|
||||
this.state.showReasonDialog = true;
|
||||
}
|
||||
|
||||
if (result.is_checked_in && result.check_in) {
|
||||
const serverTime = new Date(result.check_in + "Z");
|
||||
const wasRunning = this.state.isCheckedIn;
|
||||
@@ -117,8 +109,13 @@ export class FusionClockFAB extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Clock actions
|
||||
// =================================================================
|
||||
|
||||
async onClockAction() {
|
||||
if (this.state.isCheckedIn) {
|
||||
this.dropdown.close();
|
||||
this.state.showClockoutConfirm = true;
|
||||
return;
|
||||
}
|
||||
@@ -181,6 +178,7 @@ export class FusionClockFAB extends Component {
|
||||
|
||||
if (result.requires_reason) {
|
||||
this.state.loading = false;
|
||||
this.dropdown.close();
|
||||
this.state.showReasonDialog = true;
|
||||
this.state.reasonText = "";
|
||||
this.state.reasonTime = "";
|
||||
@@ -214,6 +212,10 @@ export class FusionClockFAB extends Component {
|
||||
this.state.loading = false;
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Reason dialog
|
||||
// =================================================================
|
||||
|
||||
onReasonTextInput(ev) {
|
||||
this.state.reasonText = ev.target.value;
|
||||
}
|
||||
@@ -243,13 +245,17 @@ export class FusionClockFAB extends Component {
|
||||
this.state.reasonText = "";
|
||||
this.state.reasonTime = "";
|
||||
this.state.reasonSubmitting = false;
|
||||
await this._executeClockAction();
|
||||
this.notification.add("Reason submitted. You can now clock in.", { type: "success" });
|
||||
} catch (e) {
|
||||
this.state.error = "Failed to submit reason.";
|
||||
this.state.reasonSubmitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
// =================================================================
|
||||
// Timer
|
||||
// =================================================================
|
||||
|
||||
get confirmCheckinDisplay() {
|
||||
if (!this.state.checkInTime) return "--";
|
||||
const d = this.state.checkInTime;
|
||||
@@ -293,6 +299,11 @@ export class FusionClockFAB extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
registry.category("main_components").add("FusionClockFAB", {
|
||||
const systrayRegistry = registry.category("systray");
|
||||
if (systrayRegistry.contains("hr_attendance.attendance_menu")) {
|
||||
systrayRegistry.remove("hr_attendance.attendance_menu");
|
||||
}
|
||||
|
||||
registry.category("systray").add("fusion_clock.ClockSystray", {
|
||||
Component: FusionClockFAB,
|
||||
});
|
||||
}, { sequence: 101 });
|
||||
|
||||
Reference in New Issue
Block a user