mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-26 04:23:58 +03:00
Update IssuesList layout (#2317)
Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
parent
bcceb8b5b4
commit
5568eeba3c
@ -472,15 +472,37 @@ export function createModel (builder: Builder): void {
|
|||||||
{
|
{
|
||||||
key: '',
|
key: '',
|
||||||
presenter: tracker.component.ProjectEditor,
|
presenter: tracker.component.ProjectEditor,
|
||||||
props: { kind: 'list', size: 'small', shape: 'round', shouldShowPlaceholder: false }
|
props: {
|
||||||
|
kind: 'list',
|
||||||
|
size: 'small',
|
||||||
|
shape: 'round',
|
||||||
|
shouldShowPlaceholder: false,
|
||||||
|
excludeByKey: 'project',
|
||||||
|
optional: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: '',
|
key: '',
|
||||||
presenter: tracker.component.SprintEditor,
|
presenter: tracker.component.SprintEditor,
|
||||||
props: { kind: 'list', size: 'small', shape: 'round', shouldShowPlaceholder: false }
|
props: {
|
||||||
|
kind: 'list',
|
||||||
|
size: 'small',
|
||||||
|
shape: 'round',
|
||||||
|
shouldShowPlaceholder: false,
|
||||||
|
excludeByKey: 'sprint',
|
||||||
|
optional: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '',
|
||||||
|
presenter: tracker.component.EstimationEditor,
|
||||||
|
props: { kind: 'list', size: 'small', optional: true }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'modifiedOn',
|
||||||
|
presenter: tracker.component.ModificationDatePresenter,
|
||||||
|
props: { fixed: 'right', optional: true }
|
||||||
},
|
},
|
||||||
{ key: '', presenter: tracker.component.EstimationEditor, props: { kind: 'list', size: 'small' } },
|
|
||||||
{ key: 'modifiedOn', presenter: tracker.component.ModificationDatePresenter, props: { fixed: 'right' } },
|
|
||||||
{
|
{
|
||||||
key: '$lookup.assignee',
|
key: '$lookup.assignee',
|
||||||
presenter: tracker.component.AssigneePresenter,
|
presenter: tracker.component.AssigneePresenter,
|
||||||
|
@ -84,6 +84,7 @@
|
|||||||
--divider-color: #303236;
|
--divider-color: #303236;
|
||||||
--menu-bg-select: #2d2f36;
|
--menu-bg-select: #2d2f36;
|
||||||
--menu-icon-hover: #f3f3f8;
|
--menu-icon-hover: #f3f3f8;
|
||||||
|
--header-bg-color: linear-gradient(0deg, var(--accent-bg-color), #2d2e31);
|
||||||
--popup-bg-color: linear-gradient(136.61deg, var(--accent-bg-color) 13.72%, #2d2e31 74.3%);
|
--popup-bg-color: linear-gradient(136.61deg, var(--accent-bg-color) 13.72%, #2d2e31 74.3%);
|
||||||
--popup-bg-hover: #37373c;
|
--popup-bg-hover: #37373c;
|
||||||
--popup-divider: #313236;
|
--popup-divider: #313236;
|
||||||
@ -236,8 +237,9 @@
|
|||||||
--divider-color: #e0e0e0;
|
--divider-color: #e0e0e0;
|
||||||
--menu-bg-select: #f0f3f9;
|
--menu-bg-select: #f0f3f9;
|
||||||
--menu-icon-hover: #282a30;
|
--menu-icon-hover: #282a30;
|
||||||
--popup-bg-color: linear-gradient(136.61deg, rgb(255, 255, 255) 13.72%, rgb(255, 255, 255) 74.3%);
|
--header-bg-color: linear-gradient(0deg, #eee, #f6f6f6);
|
||||||
--popup-bg-hover: #f8f9fb;
|
--popup-bg-color: linear-gradient(136.61deg, #fff 13.72%, #fefefe 74.3%);
|
||||||
|
--popup-bg-hover: #f0f3f9;
|
||||||
--popup-divider: #eff1f4;
|
--popup-divider: #eff1f4;
|
||||||
--popup-shadow: rgb(0 0 0 / 20%) 0px 4px 24px; // Dark
|
--popup-shadow: rgb(0 0 0 / 20%) 0px 4px 24px; // Dark
|
||||||
--popup-panel-shadow: rgb(0 0 0 / 10%) 0px 4px 18px;
|
--popup-panel-shadow: rgb(0 0 0 / 10%) 0px 4px 18px;
|
||||||
|
@ -358,6 +358,7 @@ input.search {
|
|||||||
.step-lr75 + .step-lr75 { margin-left: .75rem; }
|
.step-lr75 + .step-lr75 { margin-left: .75rem; }
|
||||||
.step-tb75 + .step-tb75 { margin-top: .75rem; }
|
.step-tb75 + .step-tb75 { margin-top: .75rem; }
|
||||||
|
|
||||||
|
.ml-0-5 { margin-left: .125rem; }
|
||||||
.ml-1 { margin-left: .25rem; }
|
.ml-1 { margin-left: .25rem; }
|
||||||
.ml-1-5 { margin-left: .375rem; }
|
.ml-1-5 { margin-left: .375rem; }
|
||||||
.ml-2 { margin-left: .5rem; }
|
.ml-2 { margin-left: .5rem; }
|
||||||
@ -502,7 +503,9 @@ input.search {
|
|||||||
.w-85 { width: 21.25rem; }
|
.w-85 { width: 21.25rem; }
|
||||||
.w-165 { width: 41.25rem; }
|
.w-165 { width: 41.25rem; }
|
||||||
.min-w-0 { min-width: 0; }
|
.min-w-0 { min-width: 0; }
|
||||||
|
.min-w-2 { min-width: .5rem; }
|
||||||
.min-w-4 { min-width: 1rem; }
|
.min-w-4 { min-width: 1rem; }
|
||||||
|
.min-w-8 { min-width: 2rem; }
|
||||||
.min-w-9 { min-width: 2.25rem; }
|
.min-w-9 { min-width: 2.25rem; }
|
||||||
.min-w-80 { min-width: 20rem; }
|
.min-w-80 { min-width: 20rem; }
|
||||||
.min-w-min { min-width: min-content; }
|
.min-w-min { min-width: min-content; }
|
||||||
|
@ -127,7 +127,7 @@
|
|||||||
<Spinner />
|
<Spinner />
|
||||||
{/if}
|
{/if}
|
||||||
{#if label}
|
{#if label}
|
||||||
<span class="overflow-label disabled" class:ml-2={loading}>
|
<span class="overflow-label disabled pointer-events-none" class:ml-2={loading}>
|
||||||
<Label {label} params={labelParams} />
|
<Label {label} params={labelParams} />
|
||||||
</span>
|
</span>
|
||||||
{:else if $$slots.content}
|
{:else if $$slots.content}
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
let asideShown: boolean = false
|
let asideShown: boolean = false
|
||||||
let fullSize: boolean = false
|
let fullSize: boolean = false
|
||||||
let twoRows: boolean = false
|
let twoRows: boolean = false
|
||||||
$: twoRows = $deviceInfo.docWidth <= 480
|
$: twoRows = $deviceInfo.minWidth
|
||||||
|
|
||||||
const checkPanel = (): void => {
|
const checkPanel = (): void => {
|
||||||
if (panelWidth <= 900 && !asideFloat) asideFloat = true
|
if (panelWidth <= 900 && !asideFloat) asideFloat = true
|
||||||
|
@ -12,7 +12,9 @@
|
|||||||
<div class="flex-center container {status.severity}" class:overflow-label={overflow}>
|
<div class="flex-center container {status.severity}" class:overflow-label={overflow}>
|
||||||
{#if status.severity !== Severity.OK}
|
{#if status.severity !== Severity.OK}
|
||||||
<Info size={'small'} />
|
<Info size={'small'} />
|
||||||
<div class="text-sm ml-2" class:overflow-label={overflow}><Label label={status.code} params={status.params} /></div>
|
<span class="text-sm ml-2" class:overflow-label={overflow}
|
||||||
|
><Label label={status.code} params={status.params} /></span
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -70,6 +70,8 @@
|
|||||||
$: $deviceInfo.docHeight = docHeight
|
$: $deviceInfo.docHeight = docHeight
|
||||||
$: $deviceInfo.isPortrait = isPortrait
|
$: $deviceInfo.isPortrait = isPortrait
|
||||||
$: $deviceInfo.isMobile = isMobile
|
$: $deviceInfo.isMobile = isMobile
|
||||||
|
$: $deviceInfo.minWidth = docWidth <= 480
|
||||||
|
$: $deviceInfo.twoRows = docWidth <= 680
|
||||||
|
|
||||||
$: document.documentElement.style.setProperty('--app-height', `${docHeight}px`)
|
$: document.documentElement.style.setProperty('--app-height', `${docHeight}px`)
|
||||||
|
|
||||||
|
@ -180,7 +180,9 @@ export const deviceOptionsStore = writable<DeviceOptions>({
|
|||||||
docWidth: 0,
|
docWidth: 0,
|
||||||
docHeight: 0,
|
docHeight: 0,
|
||||||
isPortrait: false,
|
isPortrait: false,
|
||||||
isMobile: false
|
isMobile: false,
|
||||||
|
minWidth: false,
|
||||||
|
twoRows: false
|
||||||
})
|
})
|
||||||
|
|
||||||
export default uis
|
export default uis
|
||||||
|
@ -231,5 +231,7 @@ export interface DeviceOptions {
|
|||||||
docHeight: number
|
docHeight: number
|
||||||
isPortrait: boolean
|
isPortrait: boolean
|
||||||
isMobile: boolean
|
isMobile: boolean
|
||||||
|
minWidth: boolean
|
||||||
|
twoRows: boolean
|
||||||
theme?: any
|
theme?: any
|
||||||
}
|
}
|
||||||
|
@ -100,8 +100,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let twoRows: boolean
|
$: twoRows = $deviceInfo.twoRows
|
||||||
$: twoRows = $deviceInfo.docWidth <= 680
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
||||||
|
@ -63,8 +63,7 @@
|
|||||||
showPopup(CreateContact, { space: contact.space.Contacts, targetElement: ev.target }, ev.target as HTMLElement)
|
showPopup(CreateContact, { space: contact.space.Contacts, targetElement: ev.target }, ev.target as HTMLElement)
|
||||||
}
|
}
|
||||||
|
|
||||||
let twoRows: boolean
|
$: twoRows = $deviceInfo.twoRows
|
||||||
$: twoRows = $deviceInfo.docWidth <= 680
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ActionContext
|
<ActionContext
|
||||||
|
@ -65,8 +65,7 @@
|
|||||||
allEmployees = res
|
allEmployees = res
|
||||||
})
|
})
|
||||||
|
|
||||||
let twoRows: boolean
|
$: twoRows = $deviceInfo.twoRows
|
||||||
$: twoRows = $deviceInfo.docWidth <= 680
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ac-header withSettings divide" class:full={!twoRows} class:mini={twoRows}>
|
<div class="ac-header withSettings divide" class:full={!twoRows} class:mini={twoRows}>
|
||||||
|
@ -33,8 +33,7 @@
|
|||||||
showPopup(CreateCategory, { space: inventory.space.Category }, eventToHTMLElement(ev))
|
showPopup(CreateCategory, { space: inventory.space.Category }, eventToHTMLElement(ev))
|
||||||
}
|
}
|
||||||
|
|
||||||
let twoRows: boolean
|
$: twoRows = $deviceInfo.twoRows
|
||||||
$: twoRows = $deviceInfo.docWidth <= 680
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
||||||
|
@ -131,8 +131,7 @@
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
let twoRows: boolean
|
$: twoRows = $deviceInfo.twoRows
|
||||||
$: twoRows = $deviceInfo.docWidth <= 680
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
||||||
|
@ -86,8 +86,7 @@
|
|||||||
(tagElements?.get(b._id as Ref<TagElement>)?.count ?? 0) -
|
(tagElements?.get(b._id as Ref<TagElement>)?.count ?? 0) -
|
||||||
(tagElements?.get(a._id as Ref<TagElement>)?.count ?? 0) ?? 0
|
(tagElements?.get(a._id as Ref<TagElement>)?.count ?? 0) ?? 0
|
||||||
|
|
||||||
let twoRows: boolean
|
$: twoRows = $deviceInfo.twoRows
|
||||||
$: twoRows = $deviceInfo.docWidth <= 680
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
||||||
|
@ -116,7 +116,11 @@
|
|||||||
{loading}
|
{loading}
|
||||||
on:click={handleProjectEditorOpened}
|
on:click={handleProjectEditorOpened}
|
||||||
><svelte:fragment slot="content">
|
><svelte:fragment slot="content">
|
||||||
<span class="{enlargedText ? 'ml-1 text-base fs-bold' : 'text-md'} overflow-label content-accent-color">
|
<span
|
||||||
|
class="{enlargedText
|
||||||
|
? 'ml-1 text-base fs-bold'
|
||||||
|
: 'text-md'} overflow-label content-accent-color pointer-events-none"
|
||||||
|
>
|
||||||
<Label label={getEmbeddedLabel(projectText)} />
|
<Label label={getEmbeddedLabel(projectText)} />
|
||||||
</span>
|
</span>
|
||||||
</svelte:fragment></Button
|
</svelte:fragment></Button
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
const fill: string = 'var(--theme-caption-color)'
|
const fill: string = 'var(--caption-color)'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svg {fill} viewBox="0 0 6 16" xmlns="http://www.w3.org/2000/svg">
|
<svg {fill} viewBox="0 0 6 16" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
@ -20,8 +20,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let twoRows: boolean
|
$: twoRows = $deviceInfo.twoRows
|
||||||
$: twoRows = $deviceInfo.docWidth <= 680
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
||||||
|
@ -30,7 +30,8 @@
|
|||||||
IconMoreH,
|
IconMoreH,
|
||||||
showPopup,
|
showPopup,
|
||||||
Spinner,
|
Spinner,
|
||||||
tooltip
|
tooltip,
|
||||||
|
deviceOptionsStore as deviceInfo
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
import { AttributeModel, BuildModelKey } from '@hcengineering/view'
|
import { AttributeModel, BuildModelKey } from '@hcengineering/view'
|
||||||
import { buildModel, FixedColumn, getObjectPresenter, LoadingProps, Menu } from '@hcengineering/view-resources'
|
import { buildModel, FixedColumn, getObjectPresenter, LoadingProps, Menu } from '@hcengineering/view-resources'
|
||||||
@ -38,6 +39,7 @@
|
|||||||
import tracker from '../../plugin'
|
import tracker from '../../plugin'
|
||||||
import { IssuesGroupByKeys, issuesGroupEditorMap, IssuesOrderByKeys, issuesSortOrderMap } from '../../utils'
|
import { IssuesGroupByKeys, issuesGroupEditorMap, IssuesOrderByKeys, issuesSortOrderMap } from '../../utils'
|
||||||
import CreateIssue from '../CreateIssue.svelte'
|
import CreateIssue from '../CreateIssue.svelte'
|
||||||
|
import Circles from '../icons/Circles.svelte'
|
||||||
|
|
||||||
export let _class: Ref<Class<Doc>>
|
export let _class: Ref<Class<Doc>>
|
||||||
export let currentSpace: Ref<Team> | undefined = undefined
|
export let currentSpace: Ref<Team> | undefined = undefined
|
||||||
@ -237,7 +239,7 @@
|
|||||||
value: groupByKey ? { [groupByKey]: category } : {},
|
value: groupByKey ? { [groupByKey]: category } : {},
|
||||||
statuses: groupByKey === 'status' ? statuses : undefined,
|
statuses: groupByKey === 'status' ? statuses : undefined,
|
||||||
issues: groupedIssues[category],
|
issues: groupedIssues[category],
|
||||||
size: 'medium',
|
width: 'min-content',
|
||||||
kind: 'list-header',
|
kind: 'list-header',
|
||||||
enlargedText: true,
|
enlargedText: true,
|
||||||
currentSpace
|
currentSpace
|
||||||
@ -245,7 +247,11 @@
|
|||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
{#if limited.length < items.length}
|
{#if limited.length < items.length}
|
||||||
<span class="text-base content-dark-color ml-4"> {limited.length} / {items.length}</span>
|
<div class="counter">
|
||||||
|
{limited.length}
|
||||||
|
<div class="text-xs mx-1">/</div>
|
||||||
|
{items.length}
|
||||||
|
</div>
|
||||||
<ActionIcon
|
<ActionIcon
|
||||||
size={'small'}
|
size={'small'}
|
||||||
icon={IconMoreH}
|
icon={IconMoreH}
|
||||||
@ -255,12 +261,15 @@
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<span class="text-base content-dark-color ml-4">{items.length}</span>
|
<span class="counter">{items.length}</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="clear-mins" use:tooltip={{ label: tracker.string.AddIssueTooltip }}>
|
<Button
|
||||||
<Button icon={IconAdd} kind={'transparent'} on:click={(event) => handleNewIssueAdded(event, category)} />
|
icon={IconAdd}
|
||||||
</div>
|
kind={'transparent'}
|
||||||
|
showTooltip={{ label: tracker.string.AddIssueTooltip }}
|
||||||
|
on:click={(event) => handleNewIssueAdded(event, category)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<ExpandCollapse isExpanded={!isCollapsedMap[toCat(category)]} duration={400}>
|
<ExpandCollapse isExpanded={!isCollapsedMap[toCat(category)]} duration={400}>
|
||||||
@ -340,6 +349,7 @@
|
|||||||
{...attributeModel.props}
|
{...attributeModel.props}
|
||||||
/>
|
/>
|
||||||
{:else if attributeModel.props?.fixed}
|
{:else if attributeModel.props?.fixed}
|
||||||
|
{#if !(attributeModel.props?.optional && $deviceInfo.minWidth)}
|
||||||
<FixedColumn
|
<FixedColumn
|
||||||
width={propsWidth[attributeModel.key]}
|
width={propsWidth[attributeModel.key]}
|
||||||
key={attributeModel.key}
|
key={attributeModel.key}
|
||||||
@ -355,8 +365,9 @@
|
|||||||
{currentTeam}
|
{currentTeam}
|
||||||
/>
|
/>
|
||||||
</FixedColumn>
|
</FixedColumn>
|
||||||
{:else}
|
{/if}
|
||||||
<div class="gridElement">
|
{:else if attributeModel.props?.excludeByKey !== groupByKey}
|
||||||
|
{#if !(attributeModel.props?.optional && $deviceInfo.minWidth)}
|
||||||
<svelte:component
|
<svelte:component
|
||||||
this={attributeModel.presenter}
|
this={attributeModel.presenter}
|
||||||
value={getObjectValue(attributeModel.key, docObject) ?? ''}
|
value={getObjectValue(attributeModel.key, docObject) ?? ''}
|
||||||
@ -366,9 +377,36 @@
|
|||||||
{statuses}
|
{statuses}
|
||||||
{currentTeam}
|
{currentTeam}
|
||||||
/>
|
/>
|
||||||
</div>
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
{#if $deviceInfo.minWidth}
|
||||||
|
<div class="panel-trigger" tabindex="-1">
|
||||||
|
<Circles />
|
||||||
|
<div class="space" />
|
||||||
|
<Circles />
|
||||||
|
</div>
|
||||||
|
<div class="hidden-panel gap-2" tabindex="-1">
|
||||||
|
<div class="header">
|
||||||
|
<Circles />
|
||||||
|
<div class="space" />
|
||||||
|
<Circles />
|
||||||
|
</div>
|
||||||
|
{#each itemModels as attributeModel}
|
||||||
|
{#if attributeModel.props?.optional && attributeModel.props?.excludeByKey !== groupByKey}
|
||||||
|
<svelte:component
|
||||||
|
this={attributeModel.presenter}
|
||||||
|
value={getObjectValue(attributeModel.key, docObject) ?? ''}
|
||||||
|
issueId={docObject._id}
|
||||||
|
groupBy={groupByKey}
|
||||||
|
{...attributeModel.props}
|
||||||
|
{statuses}
|
||||||
|
{currentTeam}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
{:else if loadingProps !== undefined}
|
{:else if loadingProps !== undefined}
|
||||||
@ -403,11 +441,11 @@
|
|||||||
.categoryHeader {
|
.categoryHeader {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
padding: 0 1.5rem 0 2.25rem;
|
padding: 0 0.75rem 0 2.25rem;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
min-height: 3rem;
|
min-height: 3rem;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
background-color: var(--accent-bg-color);
|
background: var(--header-bg-color);
|
||||||
z-index: 5;
|
z-index: 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -415,10 +453,29 @@
|
|||||||
border-bottom: 1px solid var(--accent-bg-color);
|
border-bottom: 1px solid var(--accent-bg-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.listGrid {
|
.counter {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 1.5rem 0 0.875rem;
|
flex-wrap: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 1rem;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
min-width: 1.325rem;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: 500;
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: 1rem;
|
||||||
|
color: var(--accent-color);
|
||||||
|
background-color: var(--body-color);
|
||||||
|
border: 1px solid var(--divider-color);
|
||||||
|
border-radius: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.listGrid {
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0 0.75rem 0 0.875rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 2.75rem;
|
height: 2.75rem;
|
||||||
min-height: 2.75rem;
|
min-height: 2.75rem;
|
||||||
@ -437,6 +494,68 @@
|
|||||||
&.mListGridSelected {
|
&.mListGridSelected {
|
||||||
background-color: var(--highlight-hover);
|
background-color: var(--highlight-hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hidden-panel,
|
||||||
|
.panel-trigger {
|
||||||
|
position: absolute;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
top: 0;
|
||||||
|
bottom: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.hidden-panel {
|
||||||
|
overflow: hidden;
|
||||||
|
right: 0;
|
||||||
|
width: 80%;
|
||||||
|
background-color: var(--accent-bg-color);
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 2;
|
||||||
|
transition-property: opacity, width;
|
||||||
|
transition-duration: 0.15s;
|
||||||
|
transition-timing-function: var(--timing-main);
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
margin: 0 0.25rem;
|
||||||
|
width: 0.375rem;
|
||||||
|
min-width: 0.375rem;
|
||||||
|
height: 100%;
|
||||||
|
opacity: 0.25;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.panel-trigger {
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0 0.125rem;
|
||||||
|
right: 2.5rem;
|
||||||
|
width: 0.75rem;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 0.25rem;
|
||||||
|
opacity: 0.1;
|
||||||
|
z-index: 1;
|
||||||
|
transition: opacity 0.15s var(--timing-main);
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--primary-edit-border-color);
|
||||||
|
opacity: 0.25;
|
||||||
|
}
|
||||||
|
& > * {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.hidden-panel:focus-within,
|
||||||
|
.panel-trigger:focus + .hidden-panel {
|
||||||
|
width: 100%;
|
||||||
|
opacity: 1;
|
||||||
|
pointer-events: all;
|
||||||
|
}
|
||||||
|
.space {
|
||||||
|
min-height: 0.1075rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.priorityPresenter,
|
.priorityPresenter,
|
||||||
|
@ -27,20 +27,18 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if value}
|
{#if value}
|
||||||
<span class="root" class:with-margin={shouldUseMargin} title={value.title}>
|
<span class="titlePresenter-container" class:with-margin={shouldUseMargin} title={value.title}>
|
||||||
<span class="name cursor-pointer" on:click={handleIssueEditorOpened}>{value.title}</span>
|
<span class="name overflow-label cursor-pointer" on:click={handleIssueEditorOpened}>{value.title}</span>
|
||||||
<ParentNamesPresenter {value} />
|
<ParentNamesPresenter {value} />
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.root {
|
.titlePresenter-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-grow: 0;
|
flex-grow: 0;
|
||||||
min-width: 7rem;
|
min-width: 1.5rem;
|
||||||
white-space: nowrap;
|
// flex-shrink: 10;
|
||||||
overflow: hidden;
|
|
||||||
flex-shrink: 10;
|
|
||||||
|
|
||||||
.name {
|
.name {
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -99,7 +99,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if hasSubIssues}
|
{#if hasSubIssues}
|
||||||
<div class="flex-center clear-mins" bind:this={btn}>
|
<div class="flex-center flex-no-shrink" bind:this={btn}>
|
||||||
<Button
|
<Button
|
||||||
{width}
|
{width}
|
||||||
{kind}
|
{kind}
|
||||||
|
@ -49,7 +49,8 @@
|
|||||||
|
|
||||||
{#if (value.project && value.project !== $activeProject && groupBy !== 'project') || shouldShowPlaceholder}
|
{#if (value.project && value.project !== $activeProject && groupBy !== 'project') || shouldShowPlaceholder}
|
||||||
<div
|
<div
|
||||||
class="clear-mins"
|
class="min-w-8"
|
||||||
|
class:minus-margin={kind === 'list-header'}
|
||||||
use:tooltip={{ label: value.project ? tracker.string.MoveToProject : tracker.string.AddToProject }}
|
use:tooltip={{ label: value.project ? tracker.string.MoveToProject : tracker.string.AddToProject }}
|
||||||
>
|
>
|
||||||
<ProjectSelector
|
<ProjectSelector
|
||||||
@ -68,3 +69,9 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.minus-margin {
|
||||||
|
margin-left: -0.5rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
import { IntlString } from '@hcengineering/platform'
|
import { IntlString } from '@hcengineering/platform'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import { Issue, IssueStatus, IssueTemplate, Sprint } from '@hcengineering/tracker'
|
import { Issue, IssueStatus, IssueTemplate, Sprint } from '@hcengineering/tracker'
|
||||||
import { ButtonKind, ButtonShape, ButtonSize, Label, tooltip } from '@hcengineering/ui'
|
import type { ButtonKind, ButtonSize, ButtonShape } from '@hcengineering/ui'
|
||||||
|
import { Label, deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
||||||
import DatePresenter from '@hcengineering/ui/src/components/calendar/DatePresenter.svelte'
|
import DatePresenter from '@hcengineering/ui/src/components/calendar/DatePresenter.svelte'
|
||||||
import { activeSprint } from '../../issues'
|
import { activeSprint } from '../../issues'
|
||||||
import tracker from '../../plugin'
|
import tracker from '../../plugin'
|
||||||
@ -30,15 +31,15 @@
|
|||||||
export let shouldShowLabel: boolean = true
|
export let shouldShowLabel: boolean = true
|
||||||
export let popupPlaceholder: IntlString = tracker.string.MoveToSprint
|
export let popupPlaceholder: IntlString = tracker.string.MoveToSprint
|
||||||
export let shouldShowPlaceholder = true
|
export let shouldShowPlaceholder = true
|
||||||
export let kind: ButtonKind = 'link'
|
|
||||||
export let size: ButtonSize = 'large'
|
export let size: ButtonSize = 'large'
|
||||||
|
export let kind: ButtonKind = 'link'
|
||||||
export let shape: ButtonShape = undefined
|
export let shape: ButtonShape = undefined
|
||||||
export let justify: 'left' | 'center' = 'left'
|
export let justify: 'left' | 'center' = 'left'
|
||||||
export let width: string | undefined = '100%'
|
export let width: string | undefined = '100%'
|
||||||
export let onlyIcon: boolean = false
|
export let onlyIcon: boolean = false
|
||||||
export let issues: Issue[] | undefined = undefined
|
export let issues: Issue[] | undefined = undefined
|
||||||
export let groupBy: string | undefined = undefined
|
export let groupBy: string | undefined = undefined
|
||||||
export let enlargedText = false
|
export let enlargedText: boolean = false
|
||||||
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
|
|
||||||
@ -119,13 +120,17 @@
|
|||||||
sprint = res.shift()
|
sprint = res.shift()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$: twoRows = $deviceInfo.twoRows
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if (value.sprint && value.sprint !== $activeSprint && groupBy !== 'sprint') || shouldShowPlaceholder}
|
|
||||||
<div
|
<div
|
||||||
class="clear-mins"
|
class="flex flex-wrap min-w-8"
|
||||||
use:tooltip={{ label: value.sprint ? tracker.string.MoveToSprint : tracker.string.AddToSprint }}
|
class:minus-margin={kind === 'list-header'}
|
||||||
|
style:flex-direction={twoRows ? 'column' : 'row'}
|
||||||
>
|
>
|
||||||
|
{#if (value.sprint && value.sprint !== $activeSprint && groupBy !== 'sprint') || shouldShowPlaceholder}
|
||||||
|
<div class="flex-row-center" class:minus-margin-vSpace={kind === 'list-header'} style:width>
|
||||||
<SprintSelector
|
<SprintSelector
|
||||||
{kind}
|
{kind}
|
||||||
{size}
|
{size}
|
||||||
@ -137,19 +142,21 @@
|
|||||||
{popupPlaceholder}
|
{popupPlaceholder}
|
||||||
{onlyIcon}
|
{onlyIcon}
|
||||||
{enlargedText}
|
{enlargedText}
|
||||||
|
showTooltip={{ label: value.sprint ? tracker.string.MoveToSprint : tracker.string.AddToSprint }}
|
||||||
value={value.sprint}
|
value={value.sprint}
|
||||||
onChange={handleSprintIdChanged}
|
onChange={handleSprintIdChanged}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
{#if sprint || issues}
|
||||||
|
<div class="flex-row-center" class:minus-margin-space={kind === 'list-header'} class:text-sm={twoRows}>
|
||||||
{#if sprint}
|
{#if sprint}
|
||||||
{@const now = Date.now()}
|
{@const now = Date.now()}
|
||||||
<div class="flex-row-center">
|
|
||||||
<DatePresenter value={sprint.startDate} kind={'transparent'} />
|
<DatePresenter value={sprint.startDate} kind={'transparent'} />
|
||||||
<span class="p-1"> / </span><DatePresenter value={sprint.targetDate} kind={'transparent'} />
|
<span class="p-1"> / </span>
|
||||||
</div>
|
<DatePresenter value={sprint.targetDate} kind={'transparent'} />
|
||||||
<div class="flex-row-center ml-2">
|
<div class="w-2 min-w-2" />
|
||||||
<!-- Active sprint in time -->
|
<!-- Active sprint in time -->
|
||||||
<Label
|
<Label
|
||||||
label={tracker.string.SprintPassed}
|
label={tracker.string.SprintPassed}
|
||||||
@ -163,14 +170,17 @@
|
|||||||
to: getDayOfSprint(sprint.startDate, sprint.targetDate)
|
to: getDayOfSprint(sprint.startDate, sprint.targetDate)
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
{#if issues}
|
{#if issues}
|
||||||
<!-- <Label label={tracker.string.SprintDay} value={}/> -->
|
<!-- <Label label={tracker.string.SprintDay} value={}/> -->
|
||||||
<div class="ml-4 flex-row-center" class:showWarning={totalEstimation > (sprint?.capacity ?? 0)}>
|
<div
|
||||||
<div class="mr-2">
|
class="flex-row-center flex-no-shrink h-6"
|
||||||
|
class:ml-2={sprint}
|
||||||
|
class:ml-0-5={!sprint}
|
||||||
|
class:showWarning={totalEstimation > (sprint?.capacity ?? 0)}
|
||||||
|
>
|
||||||
<EstimationProgressCircle value={totalReported} max={totalEstimation} />
|
<EstimationProgressCircle value={totalReported} max={totalEstimation} />
|
||||||
</div>
|
<div class="w-2 min-w-2" />
|
||||||
{#if totalReported > 0}
|
{#if totalReported > 0}
|
||||||
<Label label={tracker.string.TimeSpendValue} params={{ value: totalReported }} />
|
<Label label={tracker.string.TimeSpendValue} params={{ value: totalReported }} />
|
||||||
/
|
/
|
||||||
@ -181,9 +191,21 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.showWarning {
|
.showWarning {
|
||||||
color: var(--warning-color) !important;
|
color: var(--warning-color) !important;
|
||||||
}
|
}
|
||||||
|
.minus-margin {
|
||||||
|
margin-left: -0.5rem;
|
||||||
|
&-vSpace {
|
||||||
|
margin: -0.25rem 0;
|
||||||
|
}
|
||||||
|
&-space {
|
||||||
|
margin: -0.25rem 0 -0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import { getEmbeddedLabel, IntlString, translate } from '@hcengineering/platform'
|
import { getEmbeddedLabel, IntlString, translate } from '@hcengineering/platform'
|
||||||
import { createQuery } from '@hcengineering/presentation'
|
import { createQuery } from '@hcengineering/presentation'
|
||||||
import { Project, Sprint } from '@hcengineering/tracker'
|
import { Project, Sprint } from '@hcengineering/tracker'
|
||||||
import type { ButtonKind, ButtonSize } from '@hcengineering/ui'
|
import type { ButtonKind, ButtonSize, LabelAndProps } from '@hcengineering/ui'
|
||||||
import { Button, ButtonShape, eventToHTMLElement, SelectPopup, showPopup, Label } from '@hcengineering/ui'
|
import { Button, ButtonShape, eventToHTMLElement, SelectPopup, showPopup, Label } from '@hcengineering/ui'
|
||||||
import tracker from '../../plugin'
|
import tracker from '../../plugin'
|
||||||
import { sprintStatusAssets } from '../../types'
|
import { sprintStatusAssets } from '../../types'
|
||||||
@ -36,6 +36,7 @@
|
|||||||
export let enlargedText = false
|
export let enlargedText = false
|
||||||
|
|
||||||
export let useProject: Ref<Project> | undefined = undefined
|
export let useProject: Ref<Project> | undefined = undefined
|
||||||
|
export let showTooltip: LabelAndProps | undefined = undefined
|
||||||
|
|
||||||
let selectedSprint: Sprint | undefined
|
let selectedSprint: Sprint | undefined
|
||||||
let defaultSprintLabel = ''
|
let defaultSprintLabel = ''
|
||||||
@ -101,6 +102,7 @@
|
|||||||
{shape}
|
{shape}
|
||||||
{width}
|
{width}
|
||||||
{justify}
|
{justify}
|
||||||
|
{showTooltip}
|
||||||
icon={sprintIcon}
|
icon={sprintIcon}
|
||||||
disabled={!isEditable}
|
disabled={!isEditable}
|
||||||
on:click={handleSprintEditorOpened}
|
on:click={handleSprintEditorOpened}
|
||||||
@ -112,13 +114,17 @@
|
|||||||
{shape}
|
{shape}
|
||||||
{width}
|
{width}
|
||||||
{justify}
|
{justify}
|
||||||
|
{showTooltip}
|
||||||
icon={sprintIcon}
|
icon={sprintIcon}
|
||||||
disabled={!isEditable}
|
disabled={!isEditable}
|
||||||
on:click={handleSprintEditorOpened}
|
on:click={handleSprintEditorOpened}
|
||||||
><svelte:fragment slot="content">
|
>
|
||||||
<span class="{enlargedText ? 'ml-1 text-base fs-bold' : 'text-md'} overflow-label content-accent-color">
|
<svelte:fragment slot="content">
|
||||||
|
<span
|
||||||
|
class="{enlargedText ? 'text-base' : 'text-md'} fs-bold overflow-label content-accent-color pointer-events-none"
|
||||||
|
>
|
||||||
<Label label={getEmbeddedLabel(sprintText)} />
|
<Label label={getEmbeddedLabel(sprintText)} />
|
||||||
</span>
|
</span>
|
||||||
</svelte:fragment></Button
|
</svelte:fragment>
|
||||||
>
|
</Button>
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -359,6 +359,8 @@ export interface AttributeModel {
|
|||||||
// Extra properties for component
|
// Extra properties for component
|
||||||
props?: Record<string, any>
|
props?: Record<string, any>
|
||||||
sortingKey: string | string[]
|
sortingKey: string | string[]
|
||||||
|
optional?: boolean
|
||||||
|
excludeByKey?: string
|
||||||
// Extra icon if applicable
|
// Extra icon if applicable
|
||||||
icon?: Asset
|
icon?: Asset
|
||||||
|
|
||||||
|
@ -82,8 +82,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
let twoRows: boolean
|
$: twoRows = $deviceInfo.twoRows
|
||||||
$: twoRows = $deviceInfo.docWidth <= 768
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
||||||
|
@ -75,8 +75,7 @@
|
|||||||
return search === '' ? baseQuery : { ...baseQuery, $search: search }
|
return search === '' ? baseQuery : { ...baseQuery, $search: search }
|
||||||
}
|
}
|
||||||
|
|
||||||
let twoRows: boolean
|
$: twoRows = $deviceInfo.twoRows
|
||||||
$: twoRows = $deviceInfo.docWidth <= 680
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
<div class="ac-header withSettings" class:full={!twoRows} class:mini={twoRows}>
|
||||||
|
@ -38,7 +38,8 @@
|
|||||||
showPopup,
|
showPopup,
|
||||||
TooltipInstance,
|
TooltipInstance,
|
||||||
PopupPosAlignment,
|
PopupPosAlignment,
|
||||||
checkMobile
|
checkMobile,
|
||||||
|
deviceOptionsStore as deviceInfo
|
||||||
} from '@hcengineering/ui'
|
} from '@hcengineering/ui'
|
||||||
import view from '@hcengineering/view'
|
import view from '@hcengineering/view'
|
||||||
import { ActionContext, ActionHandler } from '@hcengineering/view-resources'
|
import { ActionContext, ActionHandler } from '@hcengineering/view-resources'
|
||||||
@ -53,7 +54,6 @@
|
|||||||
import NavHeader from './NavHeader.svelte'
|
import NavHeader from './NavHeader.svelte'
|
||||||
import Navigator from './Navigator.svelte'
|
import Navigator from './Navigator.svelte'
|
||||||
import SpaceView from './SpaceView.svelte'
|
import SpaceView from './SpaceView.svelte'
|
||||||
import { deviceOptionsStore as deviceInfo } from '@hcengineering/ui'
|
|
||||||
|
|
||||||
export let client: Client
|
export let client: Client
|
||||||
let contentPanel: HTMLElement
|
let contentPanel: HTMLElement
|
||||||
|
Loading…
Reference in New Issue
Block a user