fix(activities): keep comment and postpone open for assignees under creator-only edit
Allow dueAt/description patches for collaborators when editPolicy is creator-only, and show the no-edit warning only when they try to change locked fields—not as a permanent banner. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -29,7 +29,7 @@ import type {
|
||||
TeamDto,
|
||||
} from '@mento/shared';
|
||||
import { useAuthStore } from '@/stores/auth';
|
||||
import { canMutateActivity } from '@/lib/activity-access';
|
||||
import { canCollaborateOnActivity, canMutateActivity } from '@/lib/activity-access';
|
||||
import { canAssignToOthers } from '@/lib/assign-access';
|
||||
import { apiError } from '@/lib/routines';
|
||||
import { activityTypeView, typeColorStyle, useActivityTypes } from '@/lib/activity-types';
|
||||
@@ -84,7 +84,20 @@ const saving = ref(false);
|
||||
const error = ref('');
|
||||
const activity = ref<ActivityDto | null>(null);
|
||||
const canMutate = computed(() => canMutateActivity(activity.value, auth.user));
|
||||
const canCollaborate = computed(() =>
|
||||
canCollaborateOnActivity(activity.value, auth.user),
|
||||
);
|
||||
const editLocked = computed(() => saving.value || !canMutate.value);
|
||||
const collabLocked = computed(() => saving.value || !canCollaborate.value);
|
||||
|
||||
function warnNoMutatePermission() {
|
||||
error.value = 'شما مجوز ویرایش یا حذف این فعالیت را ندارید.';
|
||||
}
|
||||
|
||||
/** کنترلهای disabled کلیک نمیگیرند؛ روی والد اخطار میدهیم */
|
||||
function onLockedEditAttempt() {
|
||||
if (!canMutate.value && !saving.value) warnNoMutatePermission();
|
||||
}
|
||||
const canReassign = computed(
|
||||
() => canMutate.value && canAssignToOthers(auth.user, 'activities'),
|
||||
);
|
||||
@@ -436,7 +449,10 @@ function clearNoteEdit() {
|
||||
|
||||
function canEditNote(entry: ActivityThreadEntry): boolean {
|
||||
return Boolean(
|
||||
canMutate.value && entry.dateLabel && meName.value && entry.author === meName.value,
|
||||
canCollaborate.value &&
|
||||
entry.dateLabel &&
|
||||
meName.value &&
|
||||
entry.author === meName.value,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -632,6 +648,10 @@ function onBeforeUnload(event: BeforeUnloadEvent) {
|
||||
async function toggleChecklistItem(key: string, itemId: string, done: boolean) {
|
||||
const a = activity.value;
|
||||
if (!a || fieldsBusy.value) return;
|
||||
if (!canMutate.value) {
|
||||
warnNoMutatePermission();
|
||||
return;
|
||||
}
|
||||
const list = (a.fields?.[key] as ActivityChecklistItem[] | undefined) ?? [];
|
||||
const nextFields = {
|
||||
...(a.fields ?? {}),
|
||||
@@ -839,6 +859,10 @@ async function complete(kind: 'share' | 'force' | 'undo' = 'share') {
|
||||
|
||||
async function setCompletionMode(mode: 'any' | 'all') {
|
||||
if (!id.value || activity.value?.completionMode === mode) return;
|
||||
if (!canMutate.value) {
|
||||
warnNoMutatePermission();
|
||||
return;
|
||||
}
|
||||
saving.value = true;
|
||||
error.value = '';
|
||||
try {
|
||||
@@ -856,7 +880,7 @@ async function setCompletionMode(mode: 'any' | 'all') {
|
||||
async function reopen() {
|
||||
if (!id.value || !activity.value || activity.value.status === 'open') return;
|
||||
if (!canMutate.value) {
|
||||
error.value = 'شما مجوز ویرایش این فعالیت را ندارید.';
|
||||
warnNoMutatePermission();
|
||||
return;
|
||||
}
|
||||
saving.value = true;
|
||||
@@ -1062,7 +1086,7 @@ onUnmounted(() => {
|
||||
<article class="card">
|
||||
<header class="hero">
|
||||
<div>
|
||||
<h2>
|
||||
<h2 @click.capture="onLockedEditAttempt">
|
||||
<input
|
||||
v-model="draftTitle"
|
||||
class="title-input"
|
||||
@@ -1072,9 +1096,6 @@ onUnmounted(() => {
|
||||
:disabled="editLocked"
|
||||
/>
|
||||
</h2>
|
||||
<p v-if="!canMutate" class="error" role="status">
|
||||
شما مجوز ویرایش یا حذف این فعالیت را ندارید.
|
||||
</p>
|
||||
<p v-if="subtitle" class="sub">
|
||||
<UiIcon name="building" :size="14" />
|
||||
{{ subtitle }}
|
||||
@@ -1106,7 +1127,7 @@ onUnmounted(() => {
|
||||
/>
|
||||
</div>
|
||||
|
||||
<dl class="meta">
|
||||
<dl class="meta" @click.capture="onLockedEditAttempt">
|
||||
<div>
|
||||
<dt>
|
||||
<UiIcon :name="draftTypeView!.icon" :size="15" />
|
||||
@@ -1646,7 +1667,7 @@ onUnmounted(() => {
|
||||
v-if="isDone || activity.status === 'canceled'"
|
||||
class="act primary"
|
||||
type="button"
|
||||
:disabled="editLocked"
|
||||
:disabled="saving"
|
||||
@click="reopen"
|
||||
>
|
||||
<UiIcon name="clock" :size="16" />
|
||||
@@ -1675,7 +1696,7 @@ onUnmounted(() => {
|
||||
<button
|
||||
class="act ghost"
|
||||
type="button"
|
||||
:disabled="editLocked || isDone"
|
||||
:disabled="collabLocked || isDone"
|
||||
@click="postponeOpen = true"
|
||||
>
|
||||
<UiIcon name="refresh" :size="16" />
|
||||
@@ -1684,7 +1705,7 @@ onUnmounted(() => {
|
||||
<button
|
||||
class="act ghost"
|
||||
type="button"
|
||||
:disabled="editLocked"
|
||||
:disabled="collabLocked"
|
||||
@click="commentOpen = true"
|
||||
>
|
||||
<UiIcon name="chat" :size="16" />
|
||||
|
||||
Reference in New Issue
Block a user