feat(fusion_clock): Publish & Notify range + portal Schedule fold-in [A6-A7]

Generalise post_week into fclk_publish_range/fclk_email_posted_range +
planner Publish… panel + publish_range endpoint. Fold the /my/clock/schedule
controller+template+css from fusion_planning into fusion_clock (native
schedule only, role colour); inline Schedule nav across all portal pages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
gsinghpal
2026-06-04 20:54:59 -04:00
parent 734b3b94fd
commit 3376a32143
14 changed files with 641 additions and 31 deletions

View File

@@ -49,6 +49,7 @@ export class FusionClockShiftPlanner extends Component {
showRepeat: false,
repeat: { interval: 1, unit: "week", type: "forever", until: "", number: 4 },
},
publish: { open: false, from: "", to: "", message: "" },
});
onWillStart(async () => {
@@ -327,6 +328,46 @@ export class FusionClockShiftPlanner extends Component {
this.state.saving = false;
}
togglePublishPanel() {
this.state.publish.open = !this.state.publish.open;
if (this.state.publish.open && !this.state.publish.from) {
this.state.publish.from = this.state.weekStart;
this.state.publish.to = this.state.weekEnd;
}
}
onPublishField(field, ev) {
this.state.publish[field] = ev.target.value;
}
async publishRange() {
const publish = this.state.publish;
this.state.saving = true;
try {
const result = await rpc("/fusion_clock/shift_planner/publish_range", {
date_from: publish.from,
date_to: publish.to,
message: publish.message,
week_start: this.state.weekStart,
});
if (result.error || result.success === false) {
this.notification.add(result.error || result.message || "Could not publish.", {
type: "danger",
});
} else {
this._applyData(result.data);
this.state.publish.open = false;
this.notification.add(
`Published ${result.posted} shift(s); notified ${result.notified} employee(s).`,
{ type: "success" }
);
}
} catch (error) {
this.notification.add(error.message || "Could not publish.", { type: "danger" });
}
this.state.saving = false;
}
closeCellEditor() {
this.state.editor.open = false;
this.activeCellAnchor = null;