refactor(review): rollback-only flow and compact change summary
This commit is contained in:
@@ -1624,7 +1624,6 @@ watchEffect(() => {
|
||||
const changeActionBusy = ref(false);
|
||||
const activeChangeSetId = ref("");
|
||||
const activeChangeStep = ref(0);
|
||||
const changeSelectionByItemId = ref<Record<string, boolean>>({});
|
||||
const focusedCalendarEventId = ref("");
|
||||
const uiPathSyncLocked = ref(false);
|
||||
let popstateHandler: (() => void) | null = null;
|
||||
@@ -1672,11 +1671,7 @@ const activeChangeItem = computed(() => {
|
||||
|
||||
const reviewActive = computed(() => Boolean(activeChangeSetId.value.trim() && activeChangeItems.value.length > 0));
|
||||
const activeChangeStepNumber = computed(() => activeChangeIndex.value + 1);
|
||||
const activeChangeApproved = computed(() => {
|
||||
const item = activeChangeItem.value;
|
||||
if (!item || item.rolledBack) return true;
|
||||
return changeSelectionByItemId.value[item.id] !== false;
|
||||
});
|
||||
const rollbackableCount = computed(() => activeChangeItems.value.filter((item) => !item.rolledBack).length);
|
||||
const activeReviewCalendarEventId = computed(() => {
|
||||
const item = activeChangeItem.value;
|
||||
if (!item || item.entity !== "calendar_event" || !item.entityId) return "";
|
||||
@@ -1706,21 +1701,6 @@ const activeReviewContactDiff = computed(() => {
|
||||
after: normalizeChangeText(item.after),
|
||||
};
|
||||
});
|
||||
const selectedRollbackItemIds = computed(() =>
|
||||
activeChangeItems.value
|
||||
.filter((item) => !item.rolledBack && changeSelectionByItemId.value[item.id] === false)
|
||||
.map((item) => item.id),
|
||||
);
|
||||
const selectedRollbackCount = computed(() => selectedRollbackItemIds.value.length);
|
||||
|
||||
function setReviewApprovalForAll(approved: boolean) {
|
||||
const next: Record<string, boolean> = {};
|
||||
for (const item of activeChangeItems.value) {
|
||||
next[item.id] = item.rolledBack ? true : approved;
|
||||
}
|
||||
changeSelectionByItemId.value = next;
|
||||
}
|
||||
|
||||
function normalizeChangeText(raw: string | null | undefined) {
|
||||
const text = String(raw ?? "").trim();
|
||||
if (!text) return "";
|
||||
@@ -1753,32 +1733,6 @@ function describeChangeAction(action: string) {
|
||||
return action || "changed";
|
||||
}
|
||||
|
||||
function isReviewItemApproved(item: PilotChangeItem | null | undefined) {
|
||||
if (!item || item.rolledBack) return true;
|
||||
return changeSelectionByItemId.value[item.id] !== false;
|
||||
}
|
||||
|
||||
function setReviewItemApproval(itemId: string, approved: boolean) {
|
||||
const target = activeChangeItems.value.find((item) => item.id === itemId);
|
||||
if (!target || target.rolledBack) return;
|
||||
changeSelectionByItemId.value = {
|
||||
...changeSelectionByItemId.value,
|
||||
[itemId]: approved,
|
||||
};
|
||||
}
|
||||
|
||||
function onReviewItemApprovalInput(itemId: string, event: Event) {
|
||||
const input = event.target as HTMLInputElement | null;
|
||||
setReviewItemApproval(itemId, Boolean(input?.checked));
|
||||
}
|
||||
|
||||
function onActiveReviewApprovalInput(event: Event) {
|
||||
const item = activeChangeItem.value;
|
||||
if (!item) return;
|
||||
const input = event.target as HTMLInputElement | null;
|
||||
setReviewItemApproval(item.id, Boolean(input?.checked));
|
||||
}
|
||||
|
||||
function calendarCursorToken(date: Date) {
|
||||
const y = date.getFullYear();
|
||||
const m = String(date.getMonth() + 1).padStart(2, "0");
|
||||
@@ -1880,19 +1834,6 @@ function syncPathFromUi(push = false) {
|
||||
}
|
||||
}
|
||||
|
||||
function ensureChangeSelectionSeeded(message: PilotMessage | null | undefined) {
|
||||
if (!message?.changeItems?.length) {
|
||||
changeSelectionByItemId.value = {};
|
||||
return;
|
||||
}
|
||||
const next: Record<string, boolean> = {};
|
||||
for (const item of message.changeItems) {
|
||||
const prev = changeSelectionByItemId.value[item.id];
|
||||
next[item.id] = typeof prev === "boolean" ? prev : true;
|
||||
}
|
||||
changeSelectionByItemId.value = next;
|
||||
}
|
||||
|
||||
function setPeopleLeftMode(mode: PeopleLeftMode, push = false) {
|
||||
selectedTab.value = "communications";
|
||||
peopleLeftMode.value = mode;
|
||||
@@ -1906,7 +1847,6 @@ function openChangeReview(changeSetId: string, step = 0, push = true) {
|
||||
activeChangeSetId.value = targetId;
|
||||
const items = activeChangeMessage.value?.changeItems ?? [];
|
||||
activeChangeStep.value = items.length ? Math.max(0, Math.min(step, items.length - 1)) : 0;
|
||||
ensureChangeSelectionSeeded(activeChangeMessage.value);
|
||||
applyReviewStepToUi(push);
|
||||
}
|
||||
|
||||
@@ -1922,7 +1862,6 @@ function applyPathToUi(pathname: string, search = "") {
|
||||
} else {
|
||||
activeChangeSetId.value = "";
|
||||
activeChangeStep.value = 0;
|
||||
changeSelectionByItemId.value = {};
|
||||
}
|
||||
|
||||
const calendarEventMatch = path.match(/^\/calendar\/event\/([^/]+)\/?$/i);
|
||||
@@ -2074,7 +2013,7 @@ async function rollbackLatestChangeSet() {
|
||||
|
||||
async function rollbackSelectedChangeItems() {
|
||||
const targetChangeSetId = activeChangeMessage.value?.changeSetId?.trim() || activeChangeSetId.value.trim();
|
||||
const itemIds = selectedRollbackItemIds.value;
|
||||
const itemIds = activeChangeItems.value.filter((item) => !item.rolledBack).map((item) => item.id);
|
||||
if (changeActionBusy.value || !targetChangeSetId || itemIds.length === 0) return;
|
||||
|
||||
changeActionBusy.value = true;
|
||||
@@ -2084,7 +2023,23 @@ async function rollbackSelectedChangeItems() {
|
||||
itemIds,
|
||||
});
|
||||
await Promise.all([loadPilotMessages(), refreshCrmData(), loadChatConversations()]);
|
||||
ensureChangeSelectionSeeded(activeChangeMessage.value);
|
||||
} finally {
|
||||
changeActionBusy.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function rollbackChangeItemById(itemId: string) {
|
||||
const item = activeChangeItems.value.find((entry) => entry.id === itemId);
|
||||
const targetChangeSetId = activeChangeMessage.value?.changeSetId?.trim() || activeChangeSetId.value.trim();
|
||||
if (!item || item.rolledBack || !targetChangeSetId || changeActionBusy.value) return;
|
||||
|
||||
changeActionBusy.value = true;
|
||||
try {
|
||||
await gqlFetch<{ rollbackChangeSetItems: { ok: boolean } }>(rollbackChangeSetItemsMutation, {
|
||||
changeSetId: targetChangeSetId,
|
||||
itemIds: [itemId],
|
||||
});
|
||||
await Promise.all([loadPilotMessages(), refreshCrmData(), loadChatConversations()]);
|
||||
} finally {
|
||||
changeActionBusy.value = false;
|
||||
}
|
||||
@@ -2206,7 +2161,6 @@ function applyReviewStepToUi(push = false) {
|
||||
function finishReview(push = true) {
|
||||
activeChangeSetId.value = "";
|
||||
activeChangeStep.value = 0;
|
||||
changeSelectionByItemId.value = {};
|
||||
syncPathFromUi(push);
|
||||
}
|
||||
|
||||
@@ -2214,7 +2168,6 @@ watch(
|
||||
() => activeChangeMessage.value?.changeSetId,
|
||||
() => {
|
||||
if (!activeChangeSetId.value.trim()) return;
|
||||
ensureChangeSelectionSeeded(activeChangeMessage.value);
|
||||
const maxIndex = Math.max(0, (activeChangeItems.value.length || 1) - 1);
|
||||
if (activeChangeStep.value > maxIndex) activeChangeStep.value = maxIndex;
|
||||
applyReviewStepToUi(false);
|
||||
@@ -5506,22 +5459,17 @@ async function decideFeedCard(card: FeedCard, decision: "accepted" | "rejected")
|
||||
:active-change-step-number="activeChangeStepNumber"
|
||||
:active-change-items="activeChangeItems"
|
||||
:active-change-item="activeChangeItem"
|
||||
:active-change-approved="activeChangeApproved"
|
||||
:active-change-index="activeChangeIndex"
|
||||
:selected-rollback-count="selectedRollbackCount"
|
||||
:rollbackable-count="rollbackableCount"
|
||||
:change-action-busy="changeActionBusy"
|
||||
:describe-change-entity="describeChangeEntity"
|
||||
:describe-change-action="describeChangeAction"
|
||||
:is-review-item-approved="isReviewItemApproved"
|
||||
@close="finishReview(true)"
|
||||
@active-approval-change="onActiveReviewApprovalInput"
|
||||
@item-approval-change="onReviewItemApprovalInput($event.itemId, $event.event)"
|
||||
@open-item-target="openChangeItemTarget"
|
||||
@rollback-item="rollbackChangeItemById"
|
||||
@rollback-all="rollbackSelectedChangeItems"
|
||||
@prev-step="goToPreviousChangeStep"
|
||||
@next-step="goToNextChangeStep"
|
||||
@approve-all="setReviewApprovalForAll(true)"
|
||||
@mark-all-rollback="setReviewApprovalForAll(false)"
|
||||
@rollback-selected="rollbackSelectedChangeItems"
|
||||
@done="finishReview(true)"
|
||||
/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user