Minor UI fixes (#6117)

Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
Alexander Platov 2024-07-23 13:17:04 +03:00 committed by GitHub
parent 4962367182
commit 4d3561caf8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 65 additions and 73 deletions

View File

@ -20,8 +20,7 @@
import type { AnySvelteComponent } from '../types' import type { AnySvelteComponent } from '../types'
import { getTreeCollapsed, setTreeCollapsed } from '../location' import { getTreeCollapsed, setTreeCollapsed } from '../location'
import IconChevronRight from './icons/ChevronRight.svelte' import IconChevronRight from './icons/ChevronRight.svelte'
import Label from './Label.svelte' import { Label, Icon, formatDuration, themeStore } from '..'
import Icon from './Icon.svelte'
export let id: string export let id: string
export let label: IntlString | undefined = undefined export let label: IntlString | undefined = undefined
@ -52,6 +51,16 @@
if (disabled) return if (disabled) return
collapsed = !collapsed collapsed = !collapsed
} }
let durationLabel: string = ''
const updateDurationLabel = (dur: number | boolean): void => {
if (typeof dur === 'number') {
formatDuration(dur, $themeStore.language).then((res) => {
durationLabel = res
})
} else durationLabel = ''
}
$: updateDurationLabel(duration)
</script> </script>
<div class="hulyAccordionItem-container {kind}" class:nested> <div class="hulyAccordionItem-container {kind}" class:nested>
@ -95,17 +104,17 @@
{#if title}{title}{/if} {#if title}{title}{/if}
<slot name="title" /> <slot name="title" />
</div> </div>
{#if counter !== false || $$slots.counter} {#if counter !== false && ($$slots.counter || typeof counter === 'number')}
<span class="hulyAccordionItem-header__separator"></span> <span class="hulyAccordionItem-header__separator"></span>
<span class="hulyAccordionItem-header__counter"> <span class="hulyAccordionItem-header__counter">
{#if typeof counter === 'number'}{counter}{/if} {#if typeof counter === 'number'}{counter}{/if}
<slot name="counter" /> <slot name="counter" />
</span> </span>
{/if} {/if}
{#if duration !== false || $$slots.duration} {#if duration !== false && ($$slots.duration || duration !== 0)}
<span class="hulyAccordionItem-header__separator"></span> <span class="hulyAccordionItem-header__separator"></span>
<span class="hulyAccordionItem-header__duration"> <span class="hulyAccordionItem-header__duration">
{#if typeof duration === 'number'}{duration}{/if} {#if typeof duration === 'number' && durationLabel !== ''}{durationLabel}{/if}
<slot name="duration" /> <slot name="duration" />
</span> </span>
{/if} {/if}

View File

@ -103,10 +103,10 @@
on:keydown on:keydown
> >
{#if loading} {#if loading}
<div class="icon animate"><Spinner size={type === 'type-button' && !hasMenu ? 'medium' : 'small'} /></div> <div class="icon"><Spinner size={'small'} /></div>
{:else if icon}<div class="icon"> {:else if icon}
<Icon {icon} {iconProps} size={actualIconSize} /> <div class="icon"><Icon {icon} {iconProps} size={actualIconSize} /></div>
</div>{/if} {/if}
{#if label}<span><Label {label} params={labelParams} /></span>{/if} {#if label}<span><Label {label} params={labelParams} /></span>{/if}
{#if title}<span>{title}</span>{/if} {#if title}<span>{title}</span>{/if}
<slot /> <slot />
@ -136,10 +136,6 @@
justify-content: center; justify-content: center;
width: var(--spacing-2_5); width: var(--spacing-2_5);
height: var(--spacing-2_5); height: var(--spacing-2_5);
&.animate {
animation: rotate 2s linear infinite;
}
} }
span { span {
white-space: nowrap; white-space: nowrap;

View File

@ -262,6 +262,10 @@
// &:not(.type-anchor-link) .hulyNavItem-label:not(.description) { // &:not(.type-anchor-link) .hulyNavItem-label:not(.description) {
// font-weight: 700; // font-weight: 700;
// } // }
.hulyNavItem-actions {
order: 1;
margin-left: var(--spacing-0_5);
}
.hulyNavItem-count { .hulyNavItem-count {
color: var(--global-secondary-TextColor); color: var(--global-secondary-TextColor);
} }

View File

@ -15,11 +15,12 @@
import { generateId } from '@hcengineering/core' import { generateId } from '@hcengineering/core'
import type { IntlString, Metadata } from '@hcengineering/platform' import type { IntlString, Metadata } from '@hcengineering/platform'
import { setMetadata } from '@hcengineering/platform' import { setMetadata, translate } from '@hcengineering/platform'
import autolinker from 'autolinker' import autolinker from 'autolinker'
import { writable } from 'svelte/store' import { writable } from 'svelte/store'
import { NotificationPosition, NotificationSeverity, notificationsStore, type Notification } from '.' import { NotificationPosition, NotificationSeverity, notificationsStore, type Notification } from '.'
import { deviceSizes, type AnyComponent, type AnySvelteComponent, type WidthType } from './types' import { deviceSizes, type AnyComponent, type AnySvelteComponent, type WidthType } from './types'
import ui, { DAY, HOUR, MINUTE } from '..'
/** /**
* @public * @public
@ -297,3 +298,23 @@ export class ThrottledCaller {
export const testing = (localStorage.getItem('#platform.testing.enabled') ?? 'false') === 'true' export const testing = (localStorage.getItem('#platform.testing.enabled') ?? 'false') === 'true'
export const rootBarExtensions = writable<Array<['left' | 'right', AnyComponent]>>([]) export const rootBarExtensions = writable<Array<['left' | 'right', AnyComponent]>>([])
export async function formatDuration (duration: number, language: string): Promise<string> {
let text = ''
const days = Math.floor(duration / DAY)
if (days > 0) {
text += await translate(ui.string.DaysShort, { value: days }, language)
}
const hours = Math.floor((duration % DAY) / HOUR)
if (hours > 0) {
text += ' '
text += await translate(ui.string.HoursShort, { value: hours }, language)
}
const minutes = Math.floor((duration % HOUR) / MINUTE)
if (minutes > 0) {
text += ' '
text += await translate(ui.string.MinutesShort, { value: minutes }, language)
}
text = text.trim()
return text
}

View File

@ -109,7 +109,6 @@
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-shrink: 0; flex-shrink: 0;
margin-left: var(--spacing-1);
padding: var(--spacing-0_5); padding: var(--spacing-0_5);
color: var(--global-tertiary-TextColor); color: var(--global-tertiary-TextColor);
border: none; border: none;

View File

@ -21,9 +21,6 @@
"WorkItem": "Work Item", "WorkItem": "Work Item",
"Inbox": "Inbox", "Inbox": "Inbox",
"All": "All", "All": "All",
"Days": "{days}d",
"Hours": "{hours}h",
"Minutes": "{minutes}m",
"AddToDo": "Add Action Item", "AddToDo": "Add Action Item",
"CreateToDo": "Add Action Item, press Enter to save", "CreateToDo": "Add Action Item, press Enter to save",
"ToDos": "Action Items", "ToDos": "Action Items",

View File

@ -21,9 +21,6 @@
"WorkItem": "Elemento de trabajo", "WorkItem": "Elemento de trabajo",
"Inbox": "Bandeja de entrada", "Inbox": "Bandeja de entrada",
"All": "Todo", "All": "Todo",
"Days": "{days}d",
"Hours": "{hours}h",
"Minutes": "{minutes}m",
"AddToDo": "Agregar tarea", "AddToDo": "Agregar tarea",
"CreateToDo": "Agregar tarea, presiona Enter para guardar", "CreateToDo": "Agregar tarea, presiona Enter para guardar",
"ToDos": "Tareas pendientes", "ToDos": "Tareas pendientes",

View File

@ -21,9 +21,6 @@
"WorkItem": "Élément de travail", "WorkItem": "Élément de travail",
"Inbox": "Boîte de réception", "Inbox": "Boîte de réception",
"All": "Tout", "All": "Tout",
"Days": "{days}j",
"Hours": "{hours}h",
"Minutes": "{minutes}m",
"AddToDo": "Ajouter une tâche", "AddToDo": "Ajouter une tâche",
"CreateToDo": "Ajouter une tâche, appuyer sur Entrée pour enregistrer", "CreateToDo": "Ajouter une tâche, appuyer sur Entrée pour enregistrer",
"ToDos": "À faire", "ToDos": "À faire",

View File

@ -21,9 +21,6 @@
"WorkItem": "Item de trabalho", "WorkItem": "Item de trabalho",
"Inbox": "Caixa de entrada", "Inbox": "Caixa de entrada",
"All": "Tudo", "All": "Tudo",
"Days": "{days}d",
"Hours": "{hours}h",
"Minutes": "{minutes}m",
"AddToDo": "Adicionar tarefa", "AddToDo": "Adicionar tarefa",
"CreateToDo": "Adicionar tarefa, pressione Enter para guardar", "CreateToDo": "Adicionar tarefa, pressione Enter para guardar",
"ToDos": "Tarefas pendentes", "ToDos": "Tarefas pendentes",

View File

@ -21,9 +21,6 @@
"WorkItem": "Задача", "WorkItem": "Задача",
"Inbox": "Входящие", "Inbox": "Входящие",
"All": "Все", "All": "Все",
"Days": "{days}д",
"Hours": "{hours}ч",
"Minutes": "{minutes}м",
"AddToDo": "Добавить Действие", "AddToDo": "Добавить Действие",
"CreateToDo": "Добавьте Действие, нажмите Ввод, чтобы сохранить", "CreateToDo": "Добавьте Действие, нажмите Ввод, чтобы сохранить",
"ToDos": "Действия", "ToDos": "Действия",

View File

@ -21,9 +21,6 @@
"WorkItem": "工作项", "WorkItem": "工作项",
"Inbox": "收件箱", "Inbox": "收件箱",
"All": "全部", "All": "全部",
"Days": "{days}天",
"Hours": "{hours}小时",
"Minutes": "{minutes}分钟",
"AddToDo": "添加待办", "AddToDo": "添加待办",
"CreateToDo": "添加待办,按回车键保存", "CreateToDo": "添加待办,按回车键保存",
"ToDos": "待办事项", "ToDos": "待办事项",

View File

@ -1,12 +1,12 @@
<script lang="ts"> <script lang="ts">
import { themeStore } from '@hcengineering/ui' import { themeStore, formatDuration } from '@hcengineering/ui'
import { WorkSlot } from '@hcengineering/time' import { WorkSlot } from '@hcengineering/time'
import { calculateEventsDuration, formatEventsDuration } from '../utils' import { calculateEventsDuration } from '../utils'
export let events: WorkSlot[] export let events: WorkSlot[]
let duration: string let duration: string
$: formatEventsDuration(calculateEventsDuration(events), $themeStore.language).then((res) => { $: formatDuration(calculateEventsDuration(events), $themeStore.language).then((res) => {
duration = res duration = res
}) })
</script> </script>

View File

@ -24,10 +24,9 @@
import { makeRank } from '@hcengineering/task' import { makeRank } from '@hcengineering/task'
import ToDoProjectGroup from './ToDoProjectGroup.svelte' import ToDoProjectGroup from './ToDoProjectGroup.svelte'
import ToDoDraggable from './ToDoDraggable.svelte' import ToDoDraggable from './ToDoDraggable.svelte'
import ToDoDuration from './ToDoDuration.svelte'
import ToDoElement from './ToDoElement.svelte' import ToDoElement from './ToDoElement.svelte'
import { dragging } from '../dragging' import { dragging } from '../dragging'
import time from '../plugin' import { calculateEventsDuration } from '../utils'
export let mode: ToDosMode export let mode: ToDosMode
export let title: IntlString export let title: IntlString
@ -89,6 +88,9 @@
const newRank = makeRank(previousItem?.rank, nextItem?.rank) const newRank = makeRank(previousItem?.rank, nextItem?.rank)
await client.update(draggingItem, { rank: newRank }) await client.update(draggingItem, { rank: newRank })
} }
$: events = getAllWorkslots(todos)
$: duration = calculateEventsDuration(events)
</script> </script>
{#if showTitle} {#if showTitle}
@ -98,13 +100,10 @@
size={'large'} size={'large'}
bottomSpace={false} bottomSpace={false}
counter={todos.length} counter={todos.length}
duration={showDuration} duration={showDuration ? duration : false}
fixHeader fixHeader
background={'var(--theme-navpanel-color)'} background={'var(--theme-navpanel-color)'}
> >
<svelte:fragment slot="duration">
<ToDoDuration events={getAllWorkslots(todos)} />
</svelte:fragment>
{#if groups} {#if groups}
{#each groups as group} {#each groups as group}
<ToDoProjectGroup <ToDoProjectGroup

View File

@ -293,7 +293,6 @@
on:click={togglePlannerNav} on:click={togglePlannerNav}
/> />
<div class="heading-bold-20 ml-4"> <div class="heading-bold-20 ml-4">
<Label label={time.string.ToDoColon} />
{#if mode === 'date'} {#if mode === 'date'}
{getDateStr(currentDate)} {getDateStr(currentDate)}
{:else} {:else}

View File

@ -13,12 +13,21 @@
// limitations under the License. // limitations under the License.
--> -->
<script lang="ts"> <script lang="ts">
import { ButtonBase, ButtonIcon, IconDelete, themeStore, Hotkey, HotkeyGroup, Scroller } from '@hcengineering/ui' import {
ButtonBase,
ButtonIcon,
IconDelete,
themeStore,
Hotkey,
HotkeyGroup,
Scroller,
formatDuration
} from '@hcengineering/ui'
import { EventTimeEditor } from '@hcengineering/calendar-resources' import { EventTimeEditor } from '@hcengineering/calendar-resources'
import { WorkSlot } from '@hcengineering/time' import { WorkSlot } from '@hcengineering/time'
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import time from '../plugin' import time from '../plugin'
import { calculateEventsDuration, formatEventsDuration } from '../utils' import { calculateEventsDuration } from '../utils'
import Label from '@hcengineering/ui/src/components/Label.svelte' import Label from '@hcengineering/ui/src/components/Label.svelte'
export let slots: WorkSlot[] = [] export let slots: WorkSlot[] = []
@ -28,7 +37,7 @@
const dispatch = createEventDispatcher() const dispatch = createEventDispatcher()
let duration: string let duration: string
$: formatEventsDuration(calculateEventsDuration(slots), $themeStore.language).then((res) => { $: formatDuration(calculateEventsDuration(slots), $themeStore.language).then((res) => {
duration = res duration = res
}) })

View File

@ -39,9 +39,6 @@ export default mergeIds(timeId, time, {
WorkSlot: '' as IntlString, WorkSlot: '' as IntlString,
CreateToDo: '' as IntlString, CreateToDo: '' as IntlString,
Inbox: '' as IntlString, Inbox: '' as IntlString,
Days: '' as IntlString,
Hours: '' as IntlString,
Minutes: '' as IntlString,
All: '' as IntlString, All: '' as IntlString,
Done: '' as IntlString, Done: '' as IntlString,
ToDos: '' as IntlString, ToDos: '' as IntlString,

View File

@ -1,8 +1,6 @@
import type { WorkSlot, ToDo } from '@hcengineering/time' import type { WorkSlot, ToDo } from '@hcengineering/time'
import type { DefSeparators } from '@hcengineering/ui' import type { DefSeparators } from '@hcengineering/ui'
import core, { type Class, type Client, type Doc, type Ref, type Space } from '@hcengineering/core' import core, { type Class, type Client, type Doc, type Ref, type Space } from '@hcengineering/core'
import { DAY, HOUR, MINUTE } from '@hcengineering/ui'
import { translate } from '@hcengineering/platform'
import time from '@hcengineering/time' import time from '@hcengineering/time'
import { type TextEditorMode, type AnyExtension } from '@hcengineering/text-editor' import { type TextEditorMode, type AnyExtension } from '@hcengineering/text-editor'
import { SvelteNodeViewRenderer } from '@hcengineering/text-editor-resources' import { SvelteNodeViewRenderer } from '@hcengineering/text-editor-resources'
@ -11,7 +9,6 @@ import { getClient } from '@hcengineering/presentation'
import ToDoItemNodeView from './components/text-editor/node-view/ToDoItemNodeView.svelte' import ToDoItemNodeView from './components/text-editor/node-view/ToDoItemNodeView.svelte'
import ToDoListNodeView from './components/text-editor/node-view/ToDoListNodeView.svelte' import ToDoListNodeView from './components/text-editor/node-view/ToDoListNodeView.svelte'
import { TodoItemExtension, TodoListExtension } from './text-editor-extensions' import { TodoItemExtension, TodoListExtension } from './text-editor-extensions'
import timePlugin from './plugin'
export * from './types' export * from './types'
@ -135,23 +132,3 @@ export function calculateEventsDuration (events: WorkSlot[]): number {
return duration return duration
} }
export async function formatEventsDuration (duration: number, language: string): Promise<string> {
let text = ''
const days = Math.floor(duration / DAY)
if (days > 0) {
text += await translate(timePlugin.string.Days, { days }, language)
}
const hours = Math.floor((duration % DAY) / HOUR)
if (hours > 0) {
text += ' '
text += await translate(timePlugin.string.Hours, { hours }, language)
}
const minutes = Math.floor((duration % HOUR) / MINUTE)
if (minutes > 0) {
text += ' '
text += await translate(timePlugin.string.Minutes, { minutes }, language)
}
text = text.trim()
return text
}

View File

@ -32,7 +32,7 @@
{#await p then blobRef} {#await p then blobRef}
{#if loading} {#if loading}
<div class="flex justify-center"> <div class="flex-center w-full h-full clear-mins">
<Loading /> <Loading />
</div> </div>
{/if} {/if}