TSK-812: Opening images in the center. Minor design corrections. (#2755)

Signed-off-by: Alexander Platov <sas_lord@mail.ru>
This commit is contained in:
Alexander Platov 2023-03-17 06:52:32 +03:00 committed by GitHub
parent 33b39ba594
commit a3a11310a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 257 additions and 152 deletions

View File

@ -563,7 +563,7 @@ export function createModel (builder: Builder): void {
presenter: tracker.component.StatusEditor,
props: { kind: 'list', size: 'small', justify: 'center' }
},
{ key: '', presenter: tracker.component.TitlePresenter, props: { shouldUseMargin: true } },
{ key: '', presenter: tracker.component.TitlePresenter, props: {} },
{ key: '', presenter: tracker.component.SubIssuesSelector, props: {} },
{ key: '', presenter: view.component.GrowPresenter, props: { type: 'grow' } },
{

View File

@ -43,14 +43,14 @@
align-items: center;
flex-shrink: 0;
color: var(--accent-color);
overflow: hidden;
// overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
cursor: pointer;
&.inline {
display: inline-flex;
align-items: baseline;
align-items: center;
}
&.noUnderline {

View File

@ -406,7 +406,7 @@
display: flex;
align-self: center;
align-items: center;
width: 100%;
width: calc(100% - 1.75rem);
height: 100%;
color: var(--content-color);
background-color: transparent;
@ -445,6 +445,7 @@
display: flex;
justify-content: center;
align-items: center;
flex-shrink: 0;
margin-left: 0.5rem;
padding: 0;
width: 1.25rem;

View File

@ -230,6 +230,7 @@
height: 100%;
}
.ap-menuItem {
flex-shrink: 0;
justify-content: flex-start;
padding: 0 .5rem;
height: 2rem;

View File

@ -68,7 +68,7 @@
}
const fitPopup = (modalHTML: HTMLElement, element: PopupAlignment | undefined): void => {
if ((fullSize || docSize) && element === 'float') {
if ((fullSize || docSize) && (element === 'float' || element === 'centered')) {
options = fitPopupElement(modalHTML, 'full')
options.props.maxHeight = '100vh'
if (!modalHTML.classList.contains('fullsize')) modalHTML.classList.add('fullsize')
@ -129,7 +129,7 @@
<div
class="popup {showing === undefined ? 'endShow' : showing === false ? 'preShow' : 'startShow'}"
class:anim={element === 'float'}
class:anim={element === 'float' || element === 'centered'}
bind:this={modalHTML}
style={`z-index: ${zIndex + 1};`}
style:top={options.props.top}

View File

@ -15,6 +15,7 @@
<script lang="ts">
import { getContext } from 'svelte'
import FontSize from './icons/FontSize.svelte'
import { popupstore } from '../../popups'
const { currentFontSize, setFontSize } = getContext('fontsize') as {
currentFontSize: string
@ -28,6 +29,7 @@
function changeFontSize () {
current++
setFontSize(fontsizes[current % fontsizes.length])
$popupstore = $popupstore
}
</script>

View File

@ -2,6 +2,7 @@
import { onDestroy } from 'svelte'
import { Notification } from './Notification'
import Component from '../Component.svelte'
import store from './store'
export let notification: Notification
@ -23,4 +24,8 @@
})
</script>
<svelte:component this={notification.component} {notification} onRemove={removeNotificationHandler} />
{#if typeof notification.component === 'string'}
<Component is={notification.component} props={{ notification, onRemove: removeNotificationHandler }} />
{:else}
<svelte:component this={notification.component} {notification} onRemove={removeNotificationHandler} />
{/if}

View File

@ -256,6 +256,10 @@ export function fitPopupElement (
newProps.left = '60%'
newProps.right = '4px'
show = true
} else if (element === 'centered') {
newProps.top = newProps.bottom = '15%'
newProps.left = newProps.right = '25%'
show = true
} else if (element === 'account') {
newProps.bottom = '2.75rem'
newProps.left = '5rem'

View File

@ -139,6 +139,7 @@ export type PopupPosAlignment =
| 'content'
| 'middle'
| 'help-center'
| 'centered'
export function isPopupPosAlignment (x: any): x is PopupPosAlignment {
return (
@ -150,7 +151,8 @@ export function isPopupPosAlignment (x: any): x is PopupPosAlignment {
x === 'full' ||
x === 'content' ||
x === 'middle' ||
x === 'help-center')
x === 'help-center' ||
x === 'centered')
)
}

View File

@ -42,7 +42,11 @@
function openAttachment () {
closeTooltip()
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'float')
showPopup(
PDFViewer,
{ file: value.file, name: value.name, contentType: value.type },
isImage(value.type) ? 'centered' : 'float'
)
}
</script>

View File

@ -34,7 +34,9 @@
const ext = parts[parts.length - 1]
return ext.substring(0, 4).toUpperCase()
}
function isImage (contentType: string) {
return contentType.startsWith('image/')
}
function openEmbedded (contentType: string) {
return (
contentType.includes('application/pdf') ||
@ -51,7 +53,11 @@
class="flex-center icon"
on:click={() => {
closeTooltip()
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type, value }, 'float')
showPopup(
PDFViewer,
{ file: value.file, name: value.name, contentType: value.type, value },
isImage(value.type) ? 'centered' : 'float'
)
}}
>
{iconLabel(value.name)}
@ -93,7 +99,11 @@
class="name"
on:click={() => {
closeTooltip()
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type, value }, 'float')
showPopup(
PDFViewer,
{ file: value.file, name: value.name, contentType: value.type, value },
isImage(value.type) ? 'centered' : 'float'
)
}}
>
{trimFilename(value.name)}

View File

@ -29,11 +29,16 @@
</script>
{#if type === 'image'}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="content flex-center buttonContainer cursor-pointer"
on:click={() => {
closeTooltip()
showPopup(PDFViewer, { file: value.file, name: value.name, contentType: value.type }, 'float')
showPopup(
PDFViewer,
{ file: value.file, name: value.name, contentType: value.type },
value.type.startsWith('image/') ? 'centered' : 'float'
)
}}
>
<img src={getFileUrl(value.file)} alt={value.name} />

View File

@ -87,7 +87,11 @@
const el: HTMLElement = ev.currentTarget as HTMLElement
el.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'center' })
if (item !== undefined) {
showPopup(PDFViewer, { file: item.file, name: item.name, contentType: item.type }, 'float')
showPopup(
PDFViewer,
{ file: item.file, name: item.name, contentType: item.type },
item.type.startsWith('image/') ? 'centered' : 'float'
)
} else {
inputFile.click()
}

View File

@ -232,7 +232,7 @@
<div class="message">
<div class="header">
{#if employee}
<EmployeePresenter value={employee} shouldShowAvatar={false} />
<EmployeePresenter value={employee} shouldShowAvatar={false} inline />
{/if}
<span>{getTime(message.createOn)}</span>
{#if message.editedOn}

View File

@ -23,6 +23,7 @@
import PersonPresenter from './PersonPresenter.svelte'
export let value: Contact
export let inline: boolean = false
export let isInteractive = true
function isPerson (value: Contact): boolean {
@ -40,9 +41,9 @@
</script>
{#if isEmployee(value)}
<EmployeePresenter {isInteractive} value={toEmployee(value)} />
<EmployeePresenter {isInteractive} value={toEmployee(value)} {inline} />
{:else if isPerson(value)}
<PersonPresenter {isInteractive} {value} />
<PersonPresenter {isInteractive} {value} {inline} />
{:else}
<OrganizationPresenter value={toOrg(value)} />
<OrganizationPresenter value={toOrg(value)} {inline} />
{/if}

View File

@ -2,7 +2,6 @@
import { Employee } from '@hcengineering/contact'
import { WithLookup } from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform'
import { Label } from '@hcengineering/ui'
import { PersonLabelTooltip } from '..'
import PersonPresenter from '../components/PersonPresenter.svelte'
import contact from '../plugin'
@ -21,30 +20,17 @@
export let element: HTMLElement | undefined = undefined
</script>
<span class="flex-presenter">
<PersonPresenter
bind:element
{value}
{tooltipLabels}
onEdit={onEmployeeEdit}
{shouldShowAvatar}
{shouldShowName}
{avatarSize}
{shouldShowPlaceholder}
isInteractive={isInteractive && !disableClick}
{inline}
{defaultName}
/>
{#if value?.active === false && shouldShowName}
<span class="status ml-1">
(<Label label={contact.string.Inactive} />)
</span>
{/if}
</span>
<style lang="scss">
.status {
font-weight: 400;
font-size: 0.875rem;
}
</style>
<PersonPresenter
bind:element
{value}
{tooltipLabels}
onEdit={onEmployeeEdit}
{shouldShowAvatar}
{shouldShowName}
{avatarSize}
{shouldShowPlaceholder}
isInteractive={isInteractive && !disableClick}
{inline}
{defaultName}
statusLabel={value?.active === false && shouldShowName ? contact.string.Inactive : undefined}
/>

View File

@ -20,14 +20,15 @@
import { ContactPresenter } from '..'
export let value: Member
export let inline: boolean = false
const contactRef = getClient().findOne(contact.class.Contact, { _id: value.contact })
</script>
<DocNavLink object={value}>
<DocNavLink object={value} {inline}>
{#await contactRef then ct}
{#if ct}
<ContactPresenter isInteractive={false} value={ct} />
<ContactPresenter isInteractive={false} value={ct} {inline} />
{/if}
{/await}
</DocNavLink>

View File

@ -26,7 +26,7 @@
{#if value}
<DocNavLink {inline} object={value}>
<div class="flex-presenter" use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
<div class="flex-presenter" class:inline-presenter={inline} use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
<div class="icon circle"><Company size={'small'} /></div>
<span class="label">{value.name}</span>
</div>

View File

@ -26,6 +26,7 @@
export let shouldShowName = true
export let shouldShowPlaceholder = false
export let defaultName: IntlString | undefined = undefined
export let statusLabel: IntlString | undefined = undefined
export let avatarSize: 'inline' | 'tiny' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large' = 'x-small'
export let onEdit: ((event: MouseEvent) => void) | undefined = undefined
export let showTooltip: LabelAndProps | undefined = undefined
@ -34,8 +35,13 @@
</script>
{#if value}
<DocNavLink object={value} onClick={onEdit} disableClick={!isInteractive}>
<span use:tooltip={showTooltip} class="contentPresenter" class:text-base={enlargedText}>
<DocNavLink object={value} onClick={onEdit} disableClick={!isInteractive} {inline}>
<span
use:tooltip={showTooltip}
class="contentPresenter"
class:text-base={enlargedText}
class:inline-presenter={inline}
>
{#if shouldShowAvatar}
<span
class="eContentPresenterIcon"
@ -50,6 +56,11 @@
{/if}
</span>
</DocNavLink>
{#if statusLabel}
<span class="status">
<Label label={statusLabel} />
</span>
{/if}
{:else if shouldShowPlaceholder}
<span use:tooltip={showTooltip} class="contentPresenter" class:text-base={enlargedText}>
{#if shouldShowAvatar}
@ -65,6 +76,11 @@
<span class="eContentPresenterLabel">
<Label label={defaultName} />
</span>
{#if statusLabel}
<span class="eContentStatusLabel">
<Label label={statusLabel} />
</span>
{/if}
{/if}
</span>
{/if}
@ -107,4 +123,13 @@
}
}
}
.status {
margin-left: 0.25rem;
padding: 0.125rem 0.25rem;
font-weight: 500;
font-size: 0.75rem;
color: var(--content-color);
background-color: var(--noborder-bg-color);
border-radius: 0.25rem;
}
</style>

View File

@ -28,6 +28,7 @@
export let shouldShowName = true
export let shouldShowPlaceholder = false
export let defaultName: IntlString | undefined = undefined
export let statusLabel: IntlString | undefined = undefined
export let tooltipLabels: PersonLabelTooltip | undefined = undefined
export let avatarSize: 'inline' | 'tiny' | 'x-small' | 'small' | 'medium' | 'large' | 'x-large' = 'x-small'
export let onEdit: ((event: MouseEvent) => void) | undefined = undefined
@ -73,6 +74,7 @@
{shouldShowName}
{shouldShowPlaceholder}
{enlargedText}
{statusLabel}
bind:element
/>
{/if}

View File

@ -732,7 +732,11 @@
focusIndex={103}
icon={FileIcon}
on:click={() => {
showPopup(PDFViewer, { file: resume.uuid, name: resume.name }, 'float')
showPopup(
PDFViewer,
{ file: resume.uuid, name: resume.name },
resume.type.startsWith('image/') ? 'centered' : 'float'
)
}}
>
<svelte:fragment slot="content">

View File

@ -27,12 +27,12 @@
</script>
{#if value}
<div class="flex-presenter" class:inline-presenter={inline} use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
<div class="icon">
<Icon icon={recruit.icon.Vacancy} size={'small'} />
</div>
<DocNavLink {disableClick} object={value} {inline} component={recruit.component.EditVacancy}>
<DocNavLink {disableClick} object={value} {inline} component={recruit.component.EditVacancy}>
<div class="flex-presenter" class:inline-presenter={inline} use:tooltip={{ label: getEmbeddedLabel(value.name) }}>
<div class="icon">
<Icon icon={recruit.icon.Vacancy} size={'small'} />
</div>
<span class="label">{value.name}</span>
</DocNavLink>
</div>
</div>
</DocNavLink>
{/if}

View File

@ -18,7 +18,7 @@
import { DateRangeMode, Doc, FindOptions, Ref } from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform'
import { Applicant, Review } from '@hcengineering/recruit'
import { Button, DatePresenter, IconAdd, Label, resizeObserver, showPopup } from '@hcengineering/ui'
import { Button, DatePresenter, IconAdd, Label, resizeObserver, showPopup, Scroller } from '@hcengineering/ui'
import { Table } from '@hcengineering/view-resources'
import recruit from '../../plugin'
import FileDuo from '../icons/FileDuo.svelte'
@ -58,34 +58,67 @@
<Button icon={IconAdd} kind={'transparent'} shape={'circle'} on:click={createApp} />
</div>
{#if reviews > 0}
<Table
_class={recruit.class.Review}
config={[
'',
'$lookup.application',
'company',
'verdict',
{
key: '',
presenter: recruit.component.OpinionsPresenter,
label: recruit.string.Opinions,
sortingKey: 'opinions'
},
{
key: 'date',
presenter: DatePresenter,
label: calendar.string.Date,
sortingKey: 'date',
props: {
editable: false,
mode: DateRangeMode.DATE
{#if wSection < 640}
<Scroller horizontal>
<Table
_class={recruit.class.Review}
config={[
'',
'$lookup.application',
'company',
'verdict',
{
key: '',
presenter: recruit.component.OpinionsPresenter,
label: recruit.string.Opinions,
sortingKey: 'opinions'
},
{
key: 'date',
presenter: DatePresenter,
label: calendar.string.Date,
sortingKey: 'date',
props: {
editable: false,
mode: DateRangeMode.DATE
}
}
]}
{options}
query={{ attachedTo: objectId }}
loadingProps={{ length: reviews }}
/>
</Scroller>
{:else}
<Table
_class={recruit.class.Review}
config={[
'',
'$lookup.application',
'company',
'verdict',
{
key: '',
presenter: recruit.component.OpinionsPresenter,
label: recruit.string.Opinions,
sortingKey: 'opinions'
},
{
key: 'date',
presenter: DatePresenter,
label: calendar.string.Date,
sortingKey: 'date',
props: {
editable: false,
mode: DateRangeMode.DATE
}
}
}
]}
{options}
query={{ attachedTo: objectId }}
loadingProps={{ length: reviews }}
/>
]}
{options}
query={{ attachedTo: objectId }}
loadingProps={{ length: reviews }}
/>
{/if}
{:else}
<div class="antiSection-empty solid flex-col-center mt-3">
<div class="caption-color">

View File

@ -32,9 +32,9 @@
<span class="names">
{#each value.parents as parentInfo}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<span class="name cursor-pointer" on:click={() => handleIssueEditorOpened(parentInfo)}
>{parentInfo.parentTitle}</span
>
<span class="name cursor-pointer" on:click={() => handleIssueEditorOpened(parentInfo)}>
{parentInfo.parentTitle}
</span>
{/each}
</span>
</div>
@ -46,6 +46,7 @@
min-width: 0;
.names {
display: inline-flex;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
@ -57,15 +58,13 @@
color: var(--caption-color);
text-decoration: underline;
}
&:active {
color: var(--accent-color);
}
}
.name::before {
content: '';
padding: 0 0.25rem;
&::before {
content: '';
padding: 0 0.25rem;
}
}
}
</style>

View File

@ -26,12 +26,14 @@
</script>
{#if value}
<DocNavLink object={value} {onClick} component={tracker.component.EditIssue}>
<DocNavLink object={value} {onClick} component={tracker.component.EditIssue} inline>
<span
class="name overflow-label select-text"
class:with-margin={shouldUseMargin}
style:max-width={showParent ? `${value.parents.length !== 0 ? 95 : 100}%` : '100%'}>{value.title}</span
style:max-width={showParent ? `${value.parents.length !== 0 ? 95 : 100}%` : '100%'}
>
{value.title}
</span>
{#if showParent}
<ParentNamesPresenter {value} />
{/if}

View File

@ -33,6 +33,10 @@
let href: string | undefined = '#' + getPanelURI(component, object._id, Hierarchy.mixinOrClass(object), 'content')
async function getHref (object: Doc): Promise<void> {
if (disableClick) {
href = undefined
return
}
href = `#${await getObjectLinkFragment(hierarchy, object, props, component)}`
}

View File

@ -15,14 +15,11 @@
-->
<script lang="ts">
import { MessageViewer } from '@hcengineering/presentation'
import { ShowMore, tooltip } from '@hcengineering/ui'
import MarkupPreviewPopup from './MarkupPreviewPopup.svelte'
import { ShowMore } from '@hcengineering/ui'
export let value: string | undefined
</script>
<div use:tooltip={value ? { component: MarkupPreviewPopup, props: { value } } : undefined}>
<ShowMore>
<MessageViewer message={value ?? ''} />
</ShowMore>
</div>
<ShowMore>
<MessageViewer message={value ?? ''} />
</ShowMore>

View File

@ -22,6 +22,7 @@
export let _class: Ref<Class<Doc>> | undefined = undefined
export let value: Doc | RelatedDocument | undefined = undefined
export let props: Record<string, any> = {}
export let inline: boolean = true
const client = getClient()
let presenter: AttributeModel | undefined
@ -56,5 +57,5 @@
</script>
{#if presenter}
<svelte:component this={presenter.presenter} value={doc} {...props} inline />
<svelte:component this={presenter.presenter} value={doc} {...props} {inline} />
{/if}

View File

@ -153,7 +153,8 @@
objectId={item._id}
_class={item._class}
value={item}
props={{ isInteractive: false, inline: true, size }}
inline={false}
props={{ isInteractive: false, inline: false, size }}
/>
</div>
</svelte:fragment>

View File

@ -493,7 +493,7 @@
notify={false}
/>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="thinButton {appsDirection}" class:shownMenu on:click={() => (shownMenu = !shownMenu)}>
<div class="thinButton" class:shownMenu on:click={() => (shownMenu = !shownMenu)}>
<Settings size={'small'} />
</div>
</div>
@ -648,6 +648,7 @@
height: 100%;
touch-action: none;
}
.hamburger-container {
display: flex;
align-items: center;
@ -655,17 +656,70 @@
&.portrait {
margin-left: 0.375rem;
.thinButton {
margin-left: 0.5rem;
padding: 0.25rem;
height: 2.5rem;
}
}
&.landscape {
flex-direction: column;
margin-top: 0.25rem;
.thinButton {
margin-top: 0.5rem;
padding: 0.25rem;
width: 2.5rem;
}
}
&.mini {
position: absolute;
position: fixed;
top: 4px;
left: 4px;
.thinButton {
margin-left: 0.25rem;
padding: 0;
width: 1.5rem;
height: 1.5rem;
}
}
.thinButton {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
background-color: transparent;
border-radius: 0.25rem;
opacity: 0.2;
cursor: pointer;
transition-property: opacity, color, background-color;
transition-timing-function: var(--timing-main);
transition-duration: 0.1s;
&:hover {
color: var(--accent-color);
background-color: var(--accent-bg-color);
opacity: 0.9;
}
&.shownMenu {
color: var(--accent-color);
background-color: var(--button-bg-color);
opacity: 0.8;
&:hover {
color: var(--caption-color);
background-color: var(--button-bg-hover);
opacity: 1;
}
}
}
}
.info-box {
display: flex;
align-items: center;
@ -727,47 +781,4 @@
}
}
}
.thinButton {
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
padding: 0.25rem;
background-color: transparent;
border-radius: 0.25rem;
opacity: 0.2;
cursor: pointer;
transition-property: opacity, color, background-color;
transition-timing-function: var(--timing-main);
transition-duration: 0.1s;
&.vertical {
margin-top: 0.5rem;
width: 2.5rem;
}
&.horizontal {
margin-left: 0.5rem;
height: 2.5rem;
}
&:hover {
color: var(--accent-color);
background-color: var(--accent-bg-color);
opacity: 0.9;
}
&.shownMenu {
color: var(--accent-color);
background-color: var(--button-bg-color);
opacity: 0.8;
&:hover {
color: var(--caption-color);
background-color: var(--button-bg-hover);
opacity: 1;
}
}
}
</style>