style(allocations): improve display of unset priorities

This commit is contained in:
Gregor Kleen 2020-02-28 22:11:44 +01:00
parent ee2e504ffa
commit 5090cca98b
5 changed files with 63 additions and 43 deletions

View File

@ -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

View File

@ -9,6 +9,7 @@
transition: transform .2s ease
transform: scaleY(0)
transform-origin: top
z-index: 1
&:hover
background-color: var(--color-grey-light)

View File

@ -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);

View File

@ -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

View File

@ -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