From 5090cca98b9699212e8f991e6c6be4f2ec0a92e6 Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 28 Feb 2020 22:11:44 +0100 Subject: [PATCH] style(allocations): improve display of unset priorities --- frontend/src/app.sass | 7 +- .../src/utils/hide-columns/hide-columns.sass | 1 + frontend/src/utils/tooltips/tooltips.js | 67 +++++++++++-------- src/Handler/Allocation/Users.hs | 14 ++-- src/Handler/Utils/Table/Columns.hs | 17 +++-- 5 files changed, 63 insertions(+), 43 deletions(-) diff --git a/frontend/src/app.sass b/frontend/src/app.sass index fee98fe59..51a8c4062 100644 --- a/frontend/src/app.sass +++ b/frontend/src/app.sass @@ -358,6 +358,10 @@ input[type="button"].btn-info:hover, .table__td--overriden font-weight: bold +.table__td--center > .table__td-content + margin: auto + width: max-content + .table__th background-color: var(--color-dark) position: relative @@ -531,10 +535,9 @@ section .notification position: relative border-radius: 3px - padding: 10px 20px 20px + padding: 10px 20px 10px 100px margin: 40px auto box-shadow: 0 0 4px 2px inset currentColor - padding-left: 100px min-height: 100px max-width: 700px font-weight: 600 diff --git a/frontend/src/utils/hide-columns/hide-columns.sass b/frontend/src/utils/hide-columns/hide-columns.sass index e257b7045..dd4658954 100644 --- a/frontend/src/utils/hide-columns/hide-columns.sass +++ b/frontend/src/utils/hide-columns/hide-columns.sass @@ -9,6 +9,7 @@ transition: transform .2s ease transform: scaleY(0) transform-origin: top + z-index: 1 &:hover background-color: var(--color-grey-light) diff --git a/frontend/src/utils/tooltips/tooltips.js b/frontend/src/utils/tooltips/tooltips.js index bfe3ab3a7..846ae288f 100644 --- a/frontend/src/utils/tooltips/tooltips.js +++ b/frontend/src/utils/tooltips/tooltips.js @@ -5,12 +5,15 @@ import { MovementObserver } from '../../lib/movement-observer/movement-observer' var TOOLTIP_CLASS = 'tooltip'; var TOOLTIP_INITIALIZED_CLASS = 'tooltip--initialized'; var TOOLTIP_OPEN_CLASS = 'tooltip--active'; +var TOOLTIP_ORIENTATION_MARGIN = 10; +var TOOLTIP_CENTER_THRESHOLD = 20; @Utility({ selector: `.${TOOLTIP_CLASS}`, }) export class Tooltip { _element; + _handle; _content; _movementObserver; @@ -19,6 +22,8 @@ export class Tooltip { _xOffset = 3; _yOffset = -10; + + _xArrowOffset = 18; constructor(element) { if (!element) { @@ -38,8 +43,9 @@ export class Tooltip { this._content = content; this._element = element; + this._handle = element.querySelector('.tooltip__handle') || element; - this._movementObserver = new MovementObserver(this._element, { leadingCallback: this.close.bind(this) }); + this._movementObserver = new MovementObserver(this._handle, { leadingCallback: this.close.bind(this) }); element.classList.add(TOOLTIP_INITIALIZED_CLASS); } @@ -103,9 +109,9 @@ export class Tooltip { this.close(); } - _reposition() { - const doRight = this._decideRight(); - const doBottom = this._decideBottom(); + _reposition(forceRight, forceBottom) { + const doRight = forceRight === undefined ? this._decideRight() : !!forceRight; + const doBottom = forceBottom === undefined ? this._decideBottom() : !!forceBottom; // console.log('doRight', doRight); // console.log('doBottom', doBottom); @@ -120,34 +126,39 @@ export class Tooltip { else this._element.classList.remove('tooltip--right'); - const handleCoords = this._element.getBoundingClientRect(); + const handleCoords = this._handle.getBoundingClientRect(); - const left = doRight ? handleCoords.right - this._xOffset : handleCoords.left + this._xOffset; - const bottom = doBottom ? handleCoords.bottom - this._yOffset : handleCoords.top + this._yOffset; + for (let _i of [1,2]) { // eslint-disable-line no-unused-vars + const left = doRight ? handleCoords.right - this._getXOffset() - this._content.offsetWidth : handleCoords.left + this._getXOffset(); + const top = doBottom ? handleCoords.bottom - this._yOffset : handleCoords.top + this._yOffset - this._content.offsetHeight; - if (doRight) { - const right = left - this._content.offsetWidth; - this._content.style.left = `${right}px`; - } else this._content.style.left = `${left}px`; - - if (doBottom) - this._content.style.top = `${bottom}px`; - else { - const top = bottom - this._content.offsetHeight; this._content.style.top = `${top}px`; } } + _getXOffset() { + if (this._decideCenter()) + return this._handle.offsetWidth / 2 - this._xArrowOffset; + else + return this._xOffset; + } + + _decideCenter() { + return this._handle.offsetWidth <= TOOLTIP_CENTER_THRESHOLD; + } + _decideBottom() { - const handleCoords = this._element.getBoundingClientRect(); + const handleCoords = this._handle.getBoundingClientRect(); const windowHeight = window.innerHeight || document.documentElement.clientHeight; - const bottom = handleCoords.top + this._yOffset; - const bottomBottom = handleCoords.bottom - this._yOffset; + this._reposition(false, false); + const top = handleCoords.top + this._yOffset - this._content.offsetHeight - 2 * TOOLTIP_ORIENTATION_MARGIN; + const isHeight = Math.min(this._content.offsetHeight + 2 * TOOLTIP_ORIENTATION_MARGIN, Math.max(0, windowHeight - top)); - const isHeight = Math.min(windowHeight, bottom) - Math.max(0, bottom - this._content.offsetHeight); - const isHeightBottom = Math.min(windowHeight, bottomBottom) - Math.max(0, bottomBottom - this._content.offsetHeight); + this._reposition(false, true); + const topBottom = handleCoords.bottom - this._yOffset; + const isHeightBottom = Math.min(this._content.offsetHeight + 2 * TOOLTIP_ORIENTATION_MARGIN, Math.max(0, windowHeight - topBottom)); // console.log('_decideBottom', isHeight, isHeightBottom); @@ -155,14 +166,16 @@ export class Tooltip { } _decideRight() { - const handleCoords = this._element.getBoundingClientRect(); + const handleCoords = this._handle.getBoundingClientRect(); const windowWidth = window.innerWidth || document.documentElement.clientWidth; + + this._reposition(false, false); + const left = handleCoords.left + this._getXOffset(); + const isWidth = Math.min(this._content.offsetWidth + 2 * TOOLTIP_ORIENTATION_MARGIN, Math.max(0, windowWidth - left)); - const left = handleCoords.left + this._yOffset; - const leftRight = handleCoords.right - this._yOffset; - - const isWidth = Math.max(0, Math.min(windowWidth - left , this._content.offsetWidth)) + Math.min(0, left); - const isWidthRight = Math.max(0, Math.min(windowWidth - leftRight, this._content.offsetWidth)) + Math.min(0, leftRight); + this._reposition(true, false); + const leftRight = handleCoords.right - this._getXOffset() - this._content.offsetWidth - 2 * TOOLTIP_ORIENTATION_MARGIN; + const isWidthRight = Math.min(this._content.offsetWidth + 2 * TOOLTIP_ORIENTATION_MARGIN, Math.max(0, windowWidth - leftRight)); // console.log('_decideRight', isWidth, isWidthRight); diff --git a/src/Handler/Allocation/Users.hs b/src/Handler/Allocation/Users.hs index c714f6a33..829bc56f5 100644 --- a/src/Handler/Allocation/Users.hs +++ b/src/Handler/Allocation/Users.hs @@ -103,15 +103,11 @@ instance CsvColumnsExplained AllocationUserTableCsv where getAUsersR, postAUsersR :: TermId -> SchoolId -> AllocationShorthand -> Handler Html getAUsersR = postAUsersR postAUsersR tid ssh ash = do - (usersTable, missingPriorities) <- runDB $ do + usersTable <- runDB $ do Entity aId _ <- getBy404 $ TermSchoolAllocationShort tid ssh ash now <- liftIO getCurrentTime resultsDone <- (<= NTop (Just now)) . NTop <$> allocationDone aId - missingPriorities <- E.selectExists . E.from $ \allocationUser -> - E.where_ $ allocationUser E.^. AllocationUserAllocation E.==. E.val aId - E.&&. E.isNothing (allocationUser E.^. AllocationUserPriority) - csvName <- getMessageRender <*> pure (MsgAllocationUsersCsvName tid ssh ash) let @@ -147,9 +143,11 @@ postAUsersR tid ssh ash = do , coursesModalApplied $ colAllocationApplied resultAppliedCourses , coursesModalVetoed $ colAllocationVetoed resultVetoedCourses , coursesModalAssigned . assignedHeated $ colAllocationAssigned resultAssignedCourses - , emptyOpticColonnade (resultAllocationUser . _entityVal . _allocationUserPriority . _Just) colAllocationPriority + , emptyOpticColonnade' emptyPriorityCell (resultAllocationUser . _entityVal . _allocationUserPriority . _Just) colAllocationPriority ] where + emptyPriorityCell = addCellClass ("table__td--center" :: Text) . cell $ + messageTooltip =<< messageIconI Error IconMissingAllocationPriority MsgAllocationMissingPrioritiesIgnored assignedHeated | resultsDone = imapColonnade assignedHeated' | otherwise = id @@ -225,11 +223,9 @@ postAUsersR tid ssh ash = do & defaultPagesize PagesizeAll usersTable <- dbTableDB' allocationUsersDBTableValidator allocationUsersDBTable - return (usersTable, missingPriorities) + return usersTable siteLayoutMsg MsgMenuAllocationUsers $ do setTitleI $ MsgAllocationUsersTitle tid ssh ash - when missingPriorities $ - notification NotificationBroad =<< messageIconI Warning IconMissingAllocationPriority MsgAllocationMissingPrioritiesIgnored usersTable diff --git a/src/Handler/Utils/Table/Columns.hs b/src/Handler/Utils/Table/Columns.hs index fbc5886c9..61ed1ce07 100644 --- a/src/Handler/Utils/Table/Columns.hs +++ b/src/Handler/Utils/Table/Columns.hs @@ -902,15 +902,22 @@ maybeAnchorColonnadeM mkUrl = imapColonnade anchorColonnade' anchorColonnade' inp (view dbCell -> (attrs, act)) = review dbCell . (attrs,) $ view (dbCell . _2) . maybeAnchorCellM (mkUrl inp) =<< act - emptyOpticColonnade :: forall h r' focus c. - ( Monoid c - ) + Monoid c => Getting (Endo [focus]) r' focus -- ^ View on @focus@ within @r'@ that may produce any number of results -> ((forall focus'. Getting focus' r' focus) -> Colonnade h r' c) -- ^ `OpticColonnade focus` -> Colonnade h r' c -- ^ Generalize an `OpticColonnade` from `Getter` to `Fold` by defaulting results of zero values to `mempty` -emptyOpticColonnade l' c +emptyOpticColonnade = emptyOpticColonnade' mempty + + +emptyOpticColonnade' :: forall h r' focus c. + c + -> Getting (Endo [focus]) r' focus -- ^ View on @focus@ within @r'@ that may produce any number of results + -> ((forall focus'. Getting focus' r' focus) -> Colonnade h r' c) -- ^ `OpticColonnade focus` + -> Colonnade h r' c +-- ^ Generalize an `OpticColonnade` from `Getter` to `Fold` by defaulting results of zero values +emptyOpticColonnade' defC l' c = Colonnade $ oldColonnade <&> \column -> column { oneColonnadeEncode = \s -> defaultColumn s $ oneColonnadeEncode column } where l :: Fold r' focus @@ -925,7 +932,7 @@ emptyOpticColonnade l' c defaultColumn :: r' -> (r' -> c) -> c defaultColumn x f | has l x = f x - | otherwise = mempty + | otherwise = defC maybeOpticSortColumn :: OpticSortColumn (Maybe val) -> OpticSortColumn val maybeOpticSortColumn sortColumn = \queryFocus -> sortColumn $ queryFocus . to E.just