mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-08 00:17:51 +00:00
LOVE: scaling the floor (#8145)
Signed-off-by: Alexander Platov <alexander.platov@hardcoreeng.com>
This commit is contained in:
parent
d33f7ba28f
commit
618034e6fa
@ -39,6 +39,7 @@
|
||||
|
||||
& > span {
|
||||
color: var(--theme-caption-color);
|
||||
transition: font-size .15s ease-in-out;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
@ -46,12 +47,18 @@
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
max-width: 90%;
|
||||
max-height: 90%;
|
||||
transition-property: max-width, max-height;
|
||||
transition-duration: .15s;
|
||||
transition-timing-function: ease-in-out;
|
||||
min-width: .5rem;
|
||||
min-height: .5rem;
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
aspect-ratio: 1;
|
||||
transition: transform .15s ease-in-out;
|
||||
transform: scale(.9);
|
||||
|
||||
.preview & {
|
||||
min-width: .5rem;
|
||||
min-height: .5rem;
|
||||
}
|
||||
&.hovered:hover {
|
||||
background-color: transparent;
|
||||
|
||||
@ -64,8 +71,8 @@
|
||||
|
||||
&.hovered { background-color: var(--theme-popup-hover); }
|
||||
}
|
||||
&:not(.preview)::before { top: calc(100% / var(--huly-floor-roomHeight) / 3 * -1.6); }
|
||||
&.preview::before {
|
||||
:not(.preview) &::before { top: calc(100% / var(--huly-floor-roomHeight) / 3 * -1.6); }
|
||||
.preview &::before {
|
||||
top: calc(100% / var(--huly-floor-roomHeight) / 3 * -1);
|
||||
bottom: calc(100% / var(--huly-floor-roomHeight) / 3 * -1);
|
||||
left: calc(100% / var(--huly-floor-roomWidth) / 3 * -1);
|
||||
@ -80,8 +87,7 @@
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -95,8 +101,12 @@
|
||||
.floorGrid-configureRoom {
|
||||
&__header {
|
||||
top: calc(100% / var(--huly-floor-roomHeight) / 3 * -1.6 + .75rem - 1px);
|
||||
|
||||
& > .antiEditBox input { font-size: .8125rem; }
|
||||
// transition: top .15s ease-in-out;
|
||||
|
||||
& > .antiEditBox input {
|
||||
font-size: .8125rem;
|
||||
transition: font-size .15s ease-in-out;
|
||||
}
|
||||
}
|
||||
&__field {
|
||||
width: 90%;
|
||||
@ -139,6 +149,33 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Room conners and header
|
||||
@container floorGridContainer (max-width: 800px) {
|
||||
.floorGrid-room::before,
|
||||
.floorGrid-configureRoom::before { border-radius: 0.75rem; }
|
||||
.floorGrid-room .floorGrid-room__header {
|
||||
top: calc(100% / var(--huly-floor-roomHeight) / 3 * -1.6 + .125rem + 1px);
|
||||
span { font-size: .75rem; }
|
||||
svg { width: 0.75rem; }
|
||||
}
|
||||
.floorGrid-configureRoom .floorGrid-configureRoom__header {
|
||||
top: calc(100% / var(--huly-floor-roomHeight) / 3 * -1.6 + .25rem);
|
||||
& > .antiEditBox input { font-size: .75rem; }
|
||||
}
|
||||
}
|
||||
@container floorGridContainer (max-width: 600px) {
|
||||
.floorGrid-room::before,
|
||||
.floorGrid-configureRoom::before { border-radius: 0.5rem; }
|
||||
.floorGrid-room .floorGrid-room__header {
|
||||
top: calc(100% / var(--huly-floor-roomHeight) / 3 * -1.6 + .125rem);
|
||||
span { font-size: .7rem; }
|
||||
}
|
||||
.floorGrid-configureRoom .floorGrid-configureRoom__header {
|
||||
top: calc(100% / var(--huly-floor-roomHeight) / 3 * -1.6 + .125rem);
|
||||
& > .antiEditBox input { font-size: .7rem; }
|
||||
}
|
||||
}
|
||||
|
||||
// Room
|
||||
@media only screen and (max-width: 1024px) {
|
||||
.room-container + .bar > .bar__left-panel button span { display: none; }
|
||||
|
@ -41,6 +41,7 @@
|
||||
export let categoryHeader: boolean = false
|
||||
export let hiddenHeader: boolean = false
|
||||
export let background: string | undefined = undefined
|
||||
export let contentAlign: 'start' | 'center' | 'end' | 'stretch' = 'start'
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
@ -125,7 +126,7 @@
|
||||
<slot name="actions" />
|
||||
</div>
|
||||
</button>
|
||||
<div class="hulyAccordionItem-content">
|
||||
<div class="hulyAccordionItem-content" style:align-items={contentAlign}>
|
||||
<slot />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -14,15 +14,25 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { AccountRole, Ref, getCurrentAccount, hasAccountRole, WithLookup } from '@hcengineering/core'
|
||||
import { Breadcrumb, Header, IconEdit, ModernButton, Component } from '@hcengineering/ui'
|
||||
import ui, {
|
||||
Breadcrumb,
|
||||
Header,
|
||||
IconEdit,
|
||||
ModernButton,
|
||||
Component,
|
||||
IconMaxWidth,
|
||||
IconMinWidth,
|
||||
Button
|
||||
} from '@hcengineering/ui'
|
||||
import { Floor, Room } from '@hcengineering/love'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { ViewletSelector } from '@hcengineering/view-resources'
|
||||
import { Viewlet, ViewletPreference } from '@hcengineering/view'
|
||||
|
||||
import lovePlg from '../plugin'
|
||||
import { currentRoom, floors } from '../stores'
|
||||
import { currentRoom, floors, loveUseMaxWidth } from '../stores'
|
||||
import ControlBar from './ControlBar.svelte'
|
||||
import { toggleLoveUseMaxWidth } from '../utils'
|
||||
|
||||
export let rooms: Room[] = []
|
||||
export let floor: Ref<Floor>
|
||||
@ -48,6 +58,14 @@
|
||||
<ViewletSelector bind:viewlet bind:preference bind:loading viewletQuery={{ attachTo: lovePlg.class.Floor }} />
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="actions">
|
||||
<Button
|
||||
icon={$loveUseMaxWidth ? IconMaxWidth : IconMinWidth}
|
||||
kind={'regular'}
|
||||
pressed={$loveUseMaxWidth}
|
||||
size={'medium'}
|
||||
showTooltip={{ label: ui.string.UseMaxWidth }}
|
||||
on:click={toggleLoveUseMaxWidth}
|
||||
/>
|
||||
{#if editable}
|
||||
<ModernButton
|
||||
icon={IconEdit}
|
||||
|
@ -15,7 +15,10 @@
|
||||
<script lang="ts">
|
||||
import { DocumentUpdate, Ref } from '@hcengineering/core'
|
||||
import { getClient } from '@hcengineering/presentation'
|
||||
import {
|
||||
import ui, {
|
||||
Button,
|
||||
IconMaxWidth,
|
||||
IconMinWidth,
|
||||
Breadcrumb,
|
||||
ButtonIcon,
|
||||
ModernButton,
|
||||
@ -27,9 +30,9 @@
|
||||
} from '@hcengineering/ui'
|
||||
import { Floor, GRID_WIDTH, Room, getFreeSpace } from '@hcengineering/love'
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { floors, lockedRoom } from '../stores'
|
||||
import { floors, lockedRoom, loveUseMaxWidth } from '../stores'
|
||||
import { FloorSize, RGBAColor, ResizeInitParams, RoomSide, shadowError, shadowNormal } from '../types'
|
||||
import { calculateFloorSize } from '../utils'
|
||||
import { calculateFloorSize, toggleLoveUseMaxWidth } from '../utils'
|
||||
import AddRoomPopup from './AddRoomPopup.svelte'
|
||||
import FloorGrid from './FloorGrid.svelte'
|
||||
import RoomConfigure from './RoomConfigure.svelte'
|
||||
@ -295,6 +298,14 @@
|
||||
<svelte:fragment slot="actions">
|
||||
<ButtonIcon icon={IconAdd} size={'small'} on:click={addRoom} />
|
||||
<div class="hulyHeader-divider short" />
|
||||
<Button
|
||||
icon={$loveUseMaxWidth ? IconMaxWidth : IconMinWidth}
|
||||
kind={'regular'}
|
||||
pressed={$loveUseMaxWidth}
|
||||
size={'medium'}
|
||||
showTooltip={{ label: ui.string.UseMaxWidth }}
|
||||
on:click={toggleLoveUseMaxWidth}
|
||||
/>
|
||||
<ModernButton
|
||||
label={lovePlg.string.FinalizeEditing}
|
||||
kind={'primary'}
|
||||
@ -308,6 +319,7 @@
|
||||
<FloorGrid
|
||||
bind:floorContainer
|
||||
{rows}
|
||||
useResize
|
||||
on:resize={(event) => {
|
||||
if (event.detail === undefined) return
|
||||
const { width, height } = event.detail
|
||||
|
@ -16,24 +16,50 @@
|
||||
import { createEventDispatcher } from 'svelte'
|
||||
import { resizeObserver } from '@hcengineering/ui'
|
||||
import { GRID_WIDTH } from '@hcengineering/love'
|
||||
import { loveUseMaxWidth } from '../stores'
|
||||
|
||||
export let floorContainer: HTMLDivElement
|
||||
export let marginInline: string = 'auto'
|
||||
export let preview: boolean = false
|
||||
export let useResize: boolean = false
|
||||
export let rows: number = 5
|
||||
|
||||
const MAX_SIZE_REM = 2 // Maximum cell size in rems
|
||||
const MIN_SIZE_REM = 1.5
|
||||
const MAX_SIZE_UMW_REM = 4 // Maximum cell size in rems (Use max width)
|
||||
const MIN_SIZE_UMW_REM = 2
|
||||
const MAX_SIZE_PRE_REM = 2 // Maximum cell size in rems (preview mode)
|
||||
const MIN_SIZE_PRE_REM = 0.5
|
||||
const FULL_GW = GRID_WIDTH + 2
|
||||
$: minWidth = preview
|
||||
? `${FULL_GW * MIN_SIZE_PRE_REM}rem`
|
||||
: `${FULL_GW * ($loveUseMaxWidth ? MIN_SIZE_UMW_REM : MIN_SIZE_REM)}rem`
|
||||
$: minHeight = preview
|
||||
? `${rows * MIN_SIZE_PRE_REM}rem`
|
||||
: `${rows * ($loveUseMaxWidth ? MIN_SIZE_UMW_REM : MIN_SIZE_REM)}rem`
|
||||
$: maxWidth = preview
|
||||
? `${FULL_GW * MAX_SIZE_PRE_REM}rem`
|
||||
: `${FULL_GW * ($loveUseMaxWidth ? MAX_SIZE_UMW_REM : MAX_SIZE_REM)}rem`
|
||||
$: maxHeight = preview
|
||||
? `${rows * MAX_SIZE_PRE_REM}rem`
|
||||
: `${rows * ($loveUseMaxWidth ? MAX_SIZE_UMW_REM : MAX_SIZE_REM)}rem`
|
||||
$: style = `min-width: ${minWidth}; min-height: ${minHeight}; max-width: ${maxWidth}; max-height: ${maxHeight};`
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
</script>
|
||||
|
||||
{#if preview}
|
||||
{#if !useResize}
|
||||
<!-- svelte-ignore a11y-mouse-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-static-element-interactions -->
|
||||
<div
|
||||
bind:this={floorContainer}
|
||||
class="floorGrid"
|
||||
style:grid-template-columns={`repeat(${GRID_WIDTH + 2}, 1fr)`}
|
||||
style:grid-template-rows={rows ? `repeat(${rows}, 1fr)` : undefined}
|
||||
style:max-width={`${(GRID_WIDTH + 2) * 4}rem`}
|
||||
{style}
|
||||
style:grid-template-columns={`repeat(${FULL_GW}, ${preview ? `minmax(${MIN_SIZE_PRE_REM}rem, ${MAX_SIZE_PRE_REM}rem)` : '1fr'})`}
|
||||
style:grid-template-rows={rows
|
||||
? `repeat(${rows}, ${preview ? `minmax(${MIN_SIZE_PRE_REM}rem, ${MAX_SIZE_PRE_REM}rem)` : '1fr'})`
|
||||
: undefined}
|
||||
style:aspect-ratio={`${FULL_GW} / ${rows}`}
|
||||
style:margin-inline={marginInline}
|
||||
on:mouseover
|
||||
>
|
||||
@ -46,9 +72,10 @@
|
||||
dispatch('resize', { width: element.clientWidth, height: element.clientHeight })
|
||||
}}
|
||||
class="floorGrid"
|
||||
style:grid-template-columns={`repeat(${GRID_WIDTH + 2}, 1fr)`}
|
||||
{style}
|
||||
style:grid-template-columns={`repeat(${FULL_GW}, 1fr)`}
|
||||
style:grid-template-rows={rows ? `repeat(${rows}, 1fr)` : undefined}
|
||||
style:max-width={`${(GRID_WIDTH + 2) * 4}rem`}
|
||||
style:aspect-ratio={`${FULL_GW} / ${rows}`}
|
||||
style:margin-inline={marginInline}
|
||||
>
|
||||
<slot />
|
||||
@ -59,12 +86,13 @@
|
||||
.floorGrid {
|
||||
position: relative;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(17, 1fr);
|
||||
grid-auto-flow: row;
|
||||
grid-auto-rows: 1fr;
|
||||
place-items: stretch;
|
||||
place-content: center;
|
||||
place-content: start center;
|
||||
flex-shrink: 0;
|
||||
gap: 0;
|
||||
width: 100%;
|
||||
container: floorGridContainer / inline-size;
|
||||
}
|
||||
</style>
|
||||
|
@ -107,6 +107,7 @@
|
||||
{disabled}
|
||||
{kind}
|
||||
categoryHeader
|
||||
contentAlign={'center'}
|
||||
on:select
|
||||
>
|
||||
<svelte:fragment slot="actions">
|
||||
|
@ -32,8 +32,8 @@
|
||||
$: rows = calculateFloorSize(rooms) - 1
|
||||
</script>
|
||||
|
||||
<Scroller padding="1rem" bottomPadding="4rem" horizontal>
|
||||
<FloorGrid bind:floorContainer {rows} preview>
|
||||
<Scroller padding="1rem" bottomPadding="4rem" align={'center'} horizontal>
|
||||
<FloorGrid bind:floorContainer {rows}>
|
||||
{#each rooms as room}
|
||||
<RoomPreview {room} info={getInfo(room._id, $infos)} on:open />
|
||||
{/each}
|
||||
|
@ -139,14 +139,14 @@
|
||||
|
||||
.label {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
top: 0;
|
||||
left: 0;
|
||||
max-width: 100%;
|
||||
padding: 0.25rem 0.5rem 0.5rem 1rem;
|
||||
padding: 0.5rem 0.5rem 0.25rem 1rem;
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
background-color: rgba(0, 0, 0, 0.3);
|
||||
border-radius: 0 0.25rem 0 0.75rem;
|
||||
border-radius: 0.75rem 0 0.25rem 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
@ -158,8 +158,8 @@
|
||||
text-shadow: 0 0 0.25rem black;
|
||||
}
|
||||
&.filled {
|
||||
padding: 0.25rem 1rem 0.5rem 1rem;
|
||||
border-radius: 0 0 0.75rem 0.75rem;
|
||||
padding: 0.5rem 1rem 0.25rem 1rem;
|
||||
border-radius: 0.75rem 0.75rem 0 0;
|
||||
}
|
||||
}
|
||||
&.small .label {
|
||||
|
@ -144,7 +144,6 @@
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<div
|
||||
class="floorGrid-room"
|
||||
class:preview
|
||||
class:hovered
|
||||
class:disabled
|
||||
class:myOffice={$myInfo?.room === room._id}
|
||||
|
@ -17,6 +17,7 @@ import { aiBotEmailSocialId } from '@hcengineering/ai-bot'
|
||||
|
||||
import love from './plugin'
|
||||
import { personRefByPersonIdStore } from '@hcengineering/contact-resources'
|
||||
import { getLoveUseMaxWidth } from './utils'
|
||||
|
||||
export const rooms = writable<Room[]>([])
|
||||
export const myOffice = derived(rooms, (val) => {
|
||||
@ -141,3 +142,5 @@ onClient(() => {
|
||||
)
|
||||
})
|
||||
export const lockedRoom = writable<string>('')
|
||||
|
||||
export const loveUseMaxWidth = writable<boolean>(getLoveUseMaxWidth())
|
||||
|
@ -86,7 +86,14 @@ import { get, writable } from 'svelte/store'
|
||||
import { sendMessage } from './broadcast'
|
||||
import RoomSettingsPopup from './components/RoomSettingsPopup.svelte'
|
||||
import love from './plugin'
|
||||
import { $myPreferences, currentMeetingMinutes, currentRoom, myOffice, selectedRoomPlace } from './stores'
|
||||
import {
|
||||
$myPreferences,
|
||||
currentMeetingMinutes,
|
||||
currentRoom,
|
||||
myOffice,
|
||||
selectedRoomPlace,
|
||||
loveUseMaxWidth
|
||||
} from './stores'
|
||||
|
||||
export const selectedCamId = 'selectedDevice_cam'
|
||||
export const selectedMicId = 'selectedDevice_mic'
|
||||
@ -1158,3 +1165,18 @@ export async function getMeetingMinutesTitle (
|
||||
|
||||
return meeting?.title ?? ''
|
||||
}
|
||||
|
||||
// Floor Scaling (Max Width)
|
||||
const useMaxWidthKey = 'loveUseMaxWidth'
|
||||
export const saveLoveUseMaxWidth = (useMaxWidth: boolean): void => {
|
||||
if (useMaxWidth) localStorage.setItem(useMaxWidthKey, 'true')
|
||||
else localStorage.removeItem(useMaxWidthKey)
|
||||
}
|
||||
export const getLoveUseMaxWidth = (): boolean => {
|
||||
return localStorage.getItem(useMaxWidthKey) === 'true'
|
||||
}
|
||||
export const toggleLoveUseMaxWidth = (): void => {
|
||||
const value = !get(loveUseMaxWidth)
|
||||
loveUseMaxWidth.set(value)
|
||||
saveLoveUseMaxWidth(value)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user