This commit is contained in:
gsinghpal
2026-03-16 08:14:56 -04:00
parent fdca9518ab
commit e56974d46f
196 changed files with 19739 additions and 3471 deletions

View File

@@ -0,0 +1,74 @@
/** @odoo-module */
import { AttendeeCalendarController } from "@calendar/views/attendee_calendar/attendee_calendar_controller";
import { patch } from "@web/core/utils/patch";
import { useService } from "@web/core/utils/hooks";
import { useState, onWillStart } from "@odoo/owl";
patch(AttendeeCalendarController.prototype, {
setup() {
super.setup(...arguments);
this.orm = useService("orm");
this.notification = useService("notification");
this.fusionState = useState({
accounts: [],
syncing: false,
});
onWillStart(async () => {
await this._loadFusionAccounts();
});
},
get fusionAccounts() {
return this.fusionState.accounts;
},
get fusionSyncing() {
return this.fusionState.syncing;
},
async _loadFusionAccounts() {
try {
const accounts = await this.orm.call(
"fusion.calendar.account",
"get_user_accounts_status",
[],
);
this.fusionState.accounts = accounts;
} catch {
this.fusionState.accounts = [];
}
},
async onFusionSyncNow() {
this.fusionState.syncing = true;
try {
const result = await this.orm.call(
"fusion.calendar.account",
"sync_current_user",
[],
);
if (result.success) {
this.notification.add(
result.message || "Calendar synced successfully.",
{ type: "success" },
);
await this._loadFusionAccounts();
await this.model.load();
this.render(true);
} else {
this.notification.add(
result.error || "Sync failed.",
{ type: "danger" },
);
}
} catch (e) {
this.notification.add(
"Sync error: " + (e.message || "Unknown error"),
{ type: "danger" },
);
} finally {
this.fusionState.syncing = false;
}
},
});

View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<!-- Hide the native sync area and add Fusion Schedule sync UI alongside -->
<t t-name="fusion_schedule.FusionCalendarController"
t-inherit="calendar.AttendeeCalendarController"
t-inherit-mode="extension">
<!-- Hide native sync buttons but keep the div so other modules' xpaths still work -->
<xpath expr="//div[@id='header_synchronization_settings']" position="attributes">
<attribute name="style">display: none !important;</attribute>
</xpath>
<!-- Add our own sync UI right after the hidden native one -->
<xpath expr="//div[@id='header_synchronization_settings']" position="after">
<div id="fusion_calendar_sync" class="mx-2 ms-lg-auto d-inline-flex align-items-center gap-2">
<t t-if="fusionAccounts and fusionAccounts.length">
<t t-foreach="fusionAccounts" t-as="acct" t-key="acct.id">
<span class="o_tag d-inline-flex align-items-center gap-1 rounded-pill px-2 py-1 small"
t-att-class="acct.status === 'active' ? 'bg-success-subtle text-success border border-success-subtle' : acct.status === 'error' ? 'bg-danger-subtle text-danger border border-danger-subtle' : 'bg-warning-subtle text-warning border border-warning-subtle'"
t-att-title="acct.email + ' (' + (acct.provider === 'google' ? 'Google' : 'Outlook') + ')' + (acct.last_sync ? ' — Last sync: ' + acct.last_sync : '')"
t-att-data-tooltip="acct.email + ' (' + (acct.provider === 'google' ? 'Google' : 'Outlook') + ')'"
data-tooltip-position="bottom">
<i t-att-class="acct.provider === 'google' ? 'fa fa-google' : 'fa fa-windows'" style="font-size: .85em;"/>
<t t-esc="acct.email.split('@')[1].split('.')[0]"/>
</span>
</t>
<button type="button" class="btn btn-sm o_button_icon text-nowrap"
t-on-click="onFusionSyncNow"
t-att-disabled="fusionSyncing"
title="Sync all calendars now"
data-tooltip="Sync all calendars now"
data-tooltip-position="bottom">
<i t-att-class="fusionSyncing ? 'fa fa-refresh fa-spin' : 'fa fa-refresh'"/>
</button>
</t>
<a t-att-href="'/my/schedule'"
class="btn btn-sm o_button_icon text-nowrap"
title="Manage connected calendars"
data-tooltip="Manage connected calendars"
data-tooltip-position="bottom">
<i class="fa fa-cog"/>
</a>
</div>
</xpath>
</t>
</templates>