feat(activities): remove an assignee from the share list
A team, role, or person can be taken off the activity from the progress chips, and ungrouped people use the same chip as grouped members. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -168,13 +168,24 @@ function commit(ids: string[]) {
|
|||||||
|
|
||||||
function onUpdate(value: unknown) {
|
function onUpdate(value: unknown) {
|
||||||
const tokens = Array.isArray(value) ? value.map(String) : [];
|
const tokens = Array.isArray(value) ? value.map(String) : [];
|
||||||
|
const tokenSet = new Set(tokens);
|
||||||
|
const removedMemberIds = new Set<string>();
|
||||||
|
for (const token of selectValue.value) {
|
||||||
|
if (tokenSet.has(token)) continue;
|
||||||
|
const dropped = catalogByToken.value.get(token);
|
||||||
|
if (!dropped) continue;
|
||||||
|
for (const id of dropped.userIds) removedMemberIds.add(id);
|
||||||
|
}
|
||||||
const ids = new Set<string>();
|
const ids = new Set<string>();
|
||||||
const pins = new Set<string>();
|
const pins = new Set<string>();
|
||||||
for (const token of tokens) {
|
for (const token of tokens) {
|
||||||
const group = catalogByToken.value.get(token);
|
const group = catalogByToken.value.get(token);
|
||||||
if (group) {
|
if (group) {
|
||||||
pins.add(token);
|
pins.add(token);
|
||||||
for (const id of group.userIds) ids.add(id);
|
for (const id of group.userIds) {
|
||||||
|
if (removedMemberIds.has(id)) continue;
|
||||||
|
ids.add(id);
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!token.startsWith('role:') && !token.startsWith('team:')) ids.add(token);
|
if (!token.startsWith('role:') && !token.startsWith('team:')) ids.add(token);
|
||||||
|
|||||||
@@ -323,6 +323,18 @@ function shareExpanded(group: ShareGroup) {
|
|||||||
function toggleShare(group: ShareGroup) {
|
function toggleShare(group: ShareGroup) {
|
||||||
shareOpen.value = { ...shareOpen.value, [group.key]: !shareExpanded(group) };
|
shareOpen.value = { ...shareOpen.value, [group.key]: !shareExpanded(group) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function removeAssignees(ids: string[]) {
|
||||||
|
if (!canReassign.value || saving.value) return;
|
||||||
|
const drop = new Set(ids);
|
||||||
|
const next = assignUserIds.value.filter((id) => !drop.has(id));
|
||||||
|
if (!next.length) {
|
||||||
|
error.value = 'حداقل یک مسئول لازم است.';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assignUserIds.value = next;
|
||||||
|
void reassign();
|
||||||
|
}
|
||||||
const myShareDone = computed(() => {
|
const myShareDone = computed(() => {
|
||||||
const mine = auth.user?.id;
|
const mine = auth.user?.id;
|
||||||
return Boolean(mine && completedIds.value.has(mine));
|
return Boolean(mine && completedIds.value.has(mine));
|
||||||
@@ -808,21 +820,33 @@ onMounted(() => {
|
|||||||
{{ toFaDigits(shareDoneTotal) }} از {{ toFaDigits(assigneePeople.length) }} انجام شده
|
{{ toFaDigits(shareDoneTotal) }} از {{ toFaDigits(assigneePeople.length) }} انجام شده
|
||||||
</p>
|
</p>
|
||||||
<div v-for="group in shareGroups" :key="group.key" class="share-group">
|
<div v-for="group in shareGroups" :key="group.key" class="share-group">
|
||||||
<button type="button" class="share-group-head" @click="toggleShare(group)">
|
<div class="share-group-bar">
|
||||||
<UiIcon
|
<button type="button" class="share-group-head" @click="toggleShare(group)">
|
||||||
name="chevron"
|
<UiIcon
|
||||||
:size="14"
|
name="chevron"
|
||||||
class="share-caret"
|
:size="14"
|
||||||
:class="{ open: shareExpanded(group) }"
|
class="share-caret"
|
||||||
/>
|
:class="{ open: shareExpanded(group) }"
|
||||||
<span class="share-group-name">
|
/>
|
||||||
<small v-if="shareKindLabel(group)">{{ shareKindLabel(group) }}</small>
|
<span class="share-group-name">
|
||||||
{{ group.name }}
|
<small v-if="shareKindLabel(group)">{{ shareKindLabel(group) }}</small>
|
||||||
</span>
|
{{ group.name }}
|
||||||
<em :class="{ done: shareDoneCount(group.members) === group.members.length }">
|
</span>
|
||||||
{{ toFaDigits(shareDoneCount(group.members)) }} از {{ toFaDigits(group.members.length) }}
|
<em :class="{ done: shareDoneCount(group.members) === group.members.length }">
|
||||||
</em>
|
{{ toFaDigits(shareDoneCount(group.members)) }} از {{ toFaDigits(group.members.length) }}
|
||||||
</button>
|
</em>
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
v-if="canReassign"
|
||||||
|
type="button"
|
||||||
|
class="share-remove"
|
||||||
|
:disabled="saving"
|
||||||
|
:aria-label="`برداشتن ${group.name}`"
|
||||||
|
@click="removeAssignees(group.members.map((person) => person.id))"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
<ul v-if="shareExpanded(group)" class="share-members">
|
<ul v-if="shareExpanded(group)" class="share-members">
|
||||||
<li
|
<li
|
||||||
v-for="person in group.members"
|
v-for="person in group.members"
|
||||||
@@ -831,11 +855,21 @@ onMounted(() => {
|
|||||||
>
|
>
|
||||||
<span>{{ person.fullName }}</span>
|
<span>{{ person.fullName }}</span>
|
||||||
<em>{{ completedIds.has(person.id) ? 'انجام شد' : 'مانده' }}</em>
|
<em>{{ completedIds.has(person.id) ? 'انجام شد' : 'مانده' }}</em>
|
||||||
|
<button
|
||||||
|
v-if="canReassign"
|
||||||
|
type="button"
|
||||||
|
class="share-remove"
|
||||||
|
:disabled="saving"
|
||||||
|
:aria-label="`برداشتن ${person.fullName}`"
|
||||||
|
@click="removeAssignees([person.id])"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ul v-else-if="needsEveryone && !isDone" class="share-list">
|
<ul v-else-if="needsEveryone && !isDone" class="share-members loose">
|
||||||
<li
|
<li
|
||||||
v-for="person in assigneePeople"
|
v-for="person in assigneePeople"
|
||||||
:key="person.id"
|
:key="person.id"
|
||||||
@@ -843,6 +877,16 @@ onMounted(() => {
|
|||||||
>
|
>
|
||||||
<span>{{ person.fullName }}</span>
|
<span>{{ person.fullName }}</span>
|
||||||
<em>{{ completedIds.has(person.id) ? 'انجام شد' : 'مانده' }}</em>
|
<em>{{ completedIds.has(person.id) ? 'انجام شد' : 'مانده' }}</em>
|
||||||
|
<button
|
||||||
|
v-if="canReassign"
|
||||||
|
type="button"
|
||||||
|
class="share-remove"
|
||||||
|
:disabled="saving"
|
||||||
|
:aria-label="`برداشتن ${person.fullName}`"
|
||||||
|
@click="removeAssignees([person.id])"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<button
|
<button
|
||||||
@@ -1452,31 +1496,19 @@ dd {
|
|||||||
color: #0f766e;
|
color: #0f766e;
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-list {
|
.share-group-bar {
|
||||||
list-style: none;
|
|
||||||
margin: 0.55rem 0 0;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
align-items: center;
|
||||||
gap: 0.25rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-list li {
|
.share-group-bar .share-group-head {
|
||||||
display: flex;
|
width: auto;
|
||||||
justify-content: space-between;
|
flex: 1;
|
||||||
gap: 0.75rem;
|
min-width: 0;
|
||||||
font-size: 0.86rem;
|
|
||||||
color: #334155;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-list em {
|
.share-group-bar > .share-remove {
|
||||||
font-style: normal;
|
margin-inline-end: 0.45rem;
|
||||||
color: #94a3b8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.share-list li.done em {
|
|
||||||
color: #0f766e;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.share-board {
|
.share-board {
|
||||||
@@ -1561,6 +1593,13 @@ dd {
|
|||||||
gap: 0.35rem;
|
gap: 0.35rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.share-members.loose {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 0.55rem;
|
||||||
|
padding: 0;
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
.share-members li {
|
.share-members li {
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1600,6 +1639,23 @@ dd {
|
|||||||
color: #0f766e;
|
color: #0f766e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.share-remove {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
border: 0;
|
||||||
|
background: transparent;
|
||||||
|
color: #94a3b8;
|
||||||
|
font: inherit;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
line-height: 1;
|
||||||
|
padding: 0 0.1rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-remove:disabled {
|
||||||
|
cursor: default;
|
||||||
|
opacity: 0.45;
|
||||||
|
}
|
||||||
|
|
||||||
.share-force {
|
.share-force {
|
||||||
margin-top: 0.45rem;
|
margin-top: 0.45rem;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user