Do not select space not accessible to the user (#10707)

Signed-off-by: Artem Savchenko <armisav@gmail.com>
This commit is contained in:
Artyom Savchenko
2026-03-30 22:44:00 +05:00
committed by GitHub
parent d09f05acb4
commit 2bb87bf441
4 changed files with 36 additions and 10 deletions
@@ -61,6 +61,7 @@
export let component: AnyComponent | AnySvelteComponent | undefined = undefined
export let componentProps: any | undefined = undefined
export let autoSelect = true
export let clearInvalidValue = false
export let readonly = false
export let ignoreFill = false
export let iconWithEmoji: AnySvelteComponent | Asset | ComponentType | undefined = view.ids.IconWithEmoji
@@ -87,12 +88,17 @@
value = selected._id ?? undefined
}
}
// If a value is provided but can't be resolved, optionally clear the bound value.
if (selected === undefined && clearInvalidValue && _value !== undefined && value === _value) {
value = undefined
}
dispatch('object', selected)
})
$: void updateSelected(value, spaceQuery)
const showSpacesPopup = (ev: MouseEvent) => {
const showSpacesPopup = (ev: MouseEvent): void => {
if (readonly) {
return
}
@@ -136,8 +142,8 @@
{shape}
disabled={readonly}
{focusIndex}
icon={selected?.icon === iconWithEmoji && iconWithEmoji ? IconWithEmoji : (selected?.icon ?? defaultIcon)}
iconProps={selected?.icon === iconWithEmoji && iconWithEmoji
icon={selected?.icon === iconWithEmoji && iconWithEmoji != null ? IconWithEmoji : (selected?.icon ?? defaultIcon)}
iconProps={selected?.icon === iconWithEmoji && iconWithEmoji != null
? { icon: selected?.color }
: ignoreFill
? undefined
@@ -35,6 +35,7 @@
export let component: AnyComponent | AnySvelteComponent | undefined = undefined
export let componentProps: any | undefined = undefined
export let autoSelect = true
export let clearInvalidValue = false
export let iconWithEmoji: AnySvelteComponent | Asset | ComponentType | undefined = undefined
export let defaultIcon: AnySvelteComponent | Asset | ComponentType | undefined = undefined
export let readonly: boolean = false
@@ -66,6 +67,7 @@
{component}
{componentProps}
{autoSelect}
{clearInvalidValue}
{readonly}
{iconWithEmoji}
{defaultIcon}
@@ -15,7 +15,7 @@
import card, { Card, CardSpace, MasterTag } from '@hcengineering/card'
import presentation, { getClient, getCommunicationClient, SpaceSelector } from '@hcengineering/presentation'
import { createEventDispatcher } from 'svelte'
import core, { Data, generateId, Ref, Markup, notEmpty } from '@hcengineering/core'
import core, { Data, generateId, Ref, Markup, notEmpty, getCurrentAccount } from '@hcengineering/core'
import { getResource, translate, getEmbeddedLabel } from '@hcengineering/platform'
import { Label, Modal, ModernEditbox, languageStore, showPopup, Component } from '@hcengineering/ui'
import { AttachmentStyledBox } from '@hcengineering/attachment-resources'
@@ -142,7 +142,7 @@
}
}
$: allowed = _space && canCreateObject(type, _space, $permissionsStore)
$: allowed = _space != null && canCreateObject(type, _space, $permissionsStore)
</script>
<Modal
@@ -194,10 +194,14 @@
<span class="label"><Label label={core.string.Space} /></span>
<SpaceSelector
_class={card.class.CardSpace}
query={{ archived: false }}
query={{
archived: false,
members: getCurrentAccount().uuid
}}
label={core.string.Space}
bind:space={_space}
focus={false}
clearInvalidValue={true}
kind={'regular'}
size={'large'}
/>
@@ -364,7 +364,7 @@
}
$: if (_space !== undefined) {
spaceQuery.query(tracker.class.Project, { _id: _space }, (res) => {
spaceQuery.query(tracker.class.Project, { _id: _space, members: getCurrentAccount().uuid }, (res) => {
resetDefaultAssigneeId()
currentProject = res[0]
})
@@ -689,6 +689,13 @@
let attachments: Map<Ref<Attachment>, Attachment> = new Map<Ref<Attachment>, Attachment>()
function isMemberOfProject (project: Project | undefined): boolean {
if (project == null) return false
const members = project.members
if (!Array.isArray(members)) return true
return members.includes(me.uuid)
}
async function findDefaultSpace (): Promise<Project | undefined> {
let targetRef: Ref<Project> | undefined
if (relatedTo !== undefined) {
@@ -733,12 +740,14 @@
}
})
if (projects.length > 0) {
return projects[0]
const candidate = projects[0]
return isMemberOfProject(candidate) ? candidate : undefined
}
}
if (targetRef !== undefined) {
return await client.findOne(tracker.class.Project, { _id: targetRef })
const candidate = await client.findOne(tracker.class.Project, { _id: targetRef })
return isMemberOfProject(candidate) ? candidate : undefined
}
}
@@ -773,6 +782,10 @@
<svelte:fragment slot="header">
<SpaceSelector
_class={tracker.class.Project}
query={{
archived: false,
members: getCurrentAccount().uuid
}}
label={tracker.string.Project}
bind:space={_space}
on:object={(evt) => {
@@ -782,6 +795,7 @@
size={'small'}
component={ProjectPresenter}
defaultIcon={tracker.icon.Home}
clearInvalidValue={true}
{findDefaultSpace}
/>
<ObjectBox
@@ -1054,7 +1068,7 @@
<Button
loading={okProcessing}
focusIndex={10001}
disabled={!canSave}
disabled={canSave !== true}
label={okLabel}
kind={'primary'}
size={'large'}