feat(web): add prior archive promote actions

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-17 17:28:57 +03:30
co-authored by Cursor
parent 5069647f79
commit e86841fc60
5 changed files with 117 additions and 20 deletions
+52 -6
View File
@@ -231,6 +231,7 @@ const activityModal = ref<{
} | null>(null);
const menuId = ref<string | null>(null);
const boardMenuId = ref<string | null>(null);
const boardMenuActivity = ref<ActivityDto | null>(null);
const boardMenuStyle = ref<Record<string, string> | null>(null);
const deleteActivityIds = ref<string[]>([]);
const deleteSingleTitle = ref('');
@@ -572,6 +573,7 @@ function clearFacets() {
async function complete(id: string) {
menuId.value = null;
boardMenuId.value = null;
boardMenuActivity.value = null;
try {
await api.patch(`/activities/${id}/complete`);
await refreshAll();
@@ -585,6 +587,27 @@ function closePopovers() {
menuId.value = null;
}
function canPromotePrior(item: ActivityDto) {
const pa = auth.user?.priorArchive;
if (!pa || pa.lens !== 'archive' || !pa.cutoffAt) return false;
if (item.promotedFromPriorAt) return false;
return new Date(item.createdAt).getTime() < new Date(pa.cutoffAt).getTime();
}
async function promotePriorActivity(id: string) {
menuId.value = null;
boardMenuId.value = null;
boardMenuActivity.value = null;
error.value = '';
try {
await api.post(`/activities/${id}/promote-from-prior`);
kanbanReload.value += 1;
await refreshAll();
} catch {
error.value = 'انتقال فعالیت به کار جاری ناموفق بود.';
}
}
const deleteConfirmCopy = computed(() => {
const n = deleteActivityIds.value.length;
if (n <= 0) return '';
@@ -604,6 +627,7 @@ function activityTitle(id: string) {
function startSelect(id: string) {
menuId.value = null;
boardMenuId.value = null;
boardMenuActivity.value = null;
selectMode.value = true;
selectedIds.value = new Set([id]);
}
@@ -624,6 +648,7 @@ function clearSelect() {
function askDeleteActivity(id: string, title?: string) {
menuId.value = null;
boardMenuId.value = null;
boardMenuActivity.value = null;
deleteSingleTitle.value = title?.trim() || activityTitle(id);
deleteActivityIds.value = [id];
}
@@ -632,6 +657,7 @@ function askBulkDelete() {
if (!selectedIds.value.size) return;
menuId.value = null;
boardMenuId.value = null;
boardMenuActivity.value = null;
deleteSingleTitle.value = '';
deleteActivityIds.value = [...selectedIds.value];
}
@@ -659,12 +685,13 @@ async function confirmDeleteActivities() {
}
}
function onBoardMenu(activityId: string) {
boardMenuId.value = boardMenuId.value === activityId ? null : activityId;
function onBoardMenu(activity: ActivityDto) {
boardMenuId.value = boardMenuId.value === activity.id ? null : activity.id;
boardMenuActivity.value = boardMenuId.value ? activity : null;
boardMenuStyle.value = null;
if (!boardMenuId.value) return;
void nextTick(() => {
boardMenuStyle.value = cardMenuStyle(activityId);
boardMenuStyle.value = cardMenuStyle(activity.id);
});
}
@@ -672,6 +699,7 @@ const unbindBoardMenuDismiss = bindMenuDismiss(
() => boardMenuId.value != null,
() => {
boardMenuId.value = null;
boardMenuActivity.value = null;
},
);
@@ -783,6 +811,7 @@ onMounted(() => {
watch(viewMode, () => {
clearSelect();
boardMenuId.value = null;
boardMenuActivity.value = null;
menuId.value = null;
});
@@ -1213,6 +1242,9 @@ onUnmounted(() => {
<RouterLink :to="{ name: 'activity-edit', params: { id: item.id } }">
ویرایش
</RouterLink>
<button v-if="canPromotePrior(item)" type="button" @click="promotePriorActivity(item.id)">
انتقال به کار جاری
</button>
<button v-if="item.status === 'open'" type="button" @click="complete(item.id)">
انجام شد
</button>
@@ -1297,6 +1329,12 @@ onUnmounted(() => {
<RouterLink :to="{ name: 'activity-detail', params: { id: item.id } }">
مشاهده
</RouterLink>
<RouterLink :to="{ name: 'activity-edit', params: { id: item.id } }">
ویرایش
</RouterLink>
<button v-if="canPromotePrior(item)" type="button" @click="promotePriorActivity(item.id)">
انتقال به کار جاری
</button>
<button v-if="item.status === 'open'" type="button" @click="complete(item.id)">
انجام شد
</button>
@@ -1348,17 +1386,25 @@ onUnmounted(() => {
<RouterLink
role="menuitem"
:to="{ name: 'activity-detail', params: { id: boardMenuId } }"
@click="boardMenuId = null"
@click="boardMenuId = null; boardMenuActivity = null"
>
مشاهده
</RouterLink>
<RouterLink
role="menuitem"
:to="{ name: 'activity-edit', params: { id: boardMenuId } }"
@click="boardMenuId = null"
@click="boardMenuId = null; boardMenuActivity = null"
>
ویرایش
</RouterLink>
<button
v-if="boardMenuActivity && canPromotePrior(boardMenuActivity)"
type="button"
role="menuitem"
@click="promotePriorActivity(boardMenuActivity.id)"
>
انتقال به کار جاری
</button>
<button
type="button"
role="menuitem"
@@ -1367,7 +1413,7 @@ onUnmounted(() => {
>
حذف
</button>
<button type="button" role="menuitem" @click="boardMenuId = null">بستن</button>
<button type="button" role="menuitem" @click="boardMenuId = null; boardMenuActivity = null">بستن</button>
</div>
</Teleport>