Skip to content

Commit

Permalink
Disabled overnight resource use in admin resources
Browse files Browse the repository at this point in the history
  • Loading branch information
SanttuA committed Apr 25, 2024
1 parent 3dc0ca0 commit d721e6e
Show file tree
Hide file tree
Showing 10 changed files with 124 additions and 20 deletions.
3 changes: 2 additions & 1 deletion app/i18n/messages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"AdminResourcesPage.favoriteTitle": "My favorites",
"AdminResourcesPage.external.toggle": "External resources",
"AdminResourcesPage.external.label": "External",
"AdminResourcesPage.label.notUsable": "Not usable on this page",
"AvailabilityViewDateSelector.nextDay": "next day",
"AvailabilityViewDateSelector.previousDay": "previous day",
"CommentForm.label": "Comments:",
Expand Down Expand Up @@ -550,4 +551,4 @@
"UserReservationsPage.regularEmptyMessage": "No standard reservations",
"UserReservationsPage.regularReservationsHeader": "Standard reservations",
"UserReservationsPage.title": "My reservations"
}
}
3 changes: 2 additions & 1 deletion app/i18n/messages/fi.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"AdminResourcesPage.favoriteTitle": "Suosikit",
"AdminResourcesPage.external.toggle": "Ulkoiset tilat",
"AdminResourcesPage.external.label": "Ulkoinen",
"AdminResourcesPage.label.notUsable": "Ei käytettävissä tällä sivulla",
"AvailabilityViewDateSelector.nextDay": "seuraava päivä",
"AvailabilityViewDateSelector.previousDay": "edellinen päivä",
"CommentForm.label": "Kommentit:",
Expand Down Expand Up @@ -550,4 +551,4 @@
"UserReservationsPage.regularEmptyMessage": "Ei tavallisia varauksia näytettäväksi.",
"UserReservationsPage.regularReservationsHeader": "Tavalliset varaukset",
"UserReservationsPage.title": "Omat varaukset"
}
}
3 changes: 2 additions & 1 deletion app/i18n/messages/sv.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"AdminResourcesPage.favoriteTitle": "Egna favoriter",
"AdminResourcesPage.external.toggle": "Externa utrymmen",
"AdminResourcesPage.external.label": "Extern",
"AdminResourcesPage.label.notUsable": "Kan inte användas på denna sida",
"AvailabilityViewDateSelector.nextDay": "följande dag",
"AvailabilityViewDateSelector.previousDay": "föregående dag",
"CommentForm.label": "Kommentarer:",
Expand Down Expand Up @@ -552,4 +553,4 @@
"UserReservationsPage.regularEmptyMessage": "Det finns inga vanliga bokningar att visa.",
"UserReservationsPage.regularReservationsHeader": "Vanliga bokningar",
"UserReservationsPage.title": "Mina bokningar"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,18 @@ ResourceInfo.propTypes = {
public: PropTypes.bool.isRequired,
hasStaffRights: PropTypes.bool,
t: PropTypes.func.isRequired,
overnightReservations: PropTypes.bool.isRequired,
};
export function ResourceInfo(props) {
const { overnightReservations } = props;
return (
<div
className={classNames(
'resource-info',
{
'resource-info-selected': props.isSelected,
'is-external': !props.hasStaffRights
'is-external': !props.hasStaffRights,
'is-overnight': props.overnightReservations,
})
}
title={props.name}
Expand All @@ -37,15 +40,24 @@ export function ResourceInfo(props) {
<Link to={`/resources/${props.id}?date=${props.date}`}>{props.name}</Link>
</div>
<div className="details">
<Glyphicon glyph="user" />
{' '}
{props.peopleCapacity}
{!props.public && (
<UnpublishedLabel />
{!overnightReservations && (
<React.Fragment>
<Glyphicon glyph="user" />
{' '}
{props.peopleCapacity}
{!props.public && (
<UnpublishedLabel />
)}
{!props.hasStaffRights && (
<Label bsStyle="default" className="unpublished-label">
{props.t('AdminResourcesPage.external.label')}
</Label>
)}
</React.Fragment>
)}
{!props.hasStaffRights && (
<Label bsStyle="default" className="unpublished-label">
{props.t('AdminResourcesPage.external.label')}
{overnightReservations && (
<Label bsStyle="default" className="unusable-label" title={props.t('AdminResourcesPage.label.notUsable')}>
{props.t('AdminResourcesPage.label.notUsable')}
</Label>
)}
</div>
Expand All @@ -70,7 +82,8 @@ export function selector() {
name: resource.name,
peopleCapacity: resource.peopleCapacity,
public: resource.public,
hasStaffRights: isAdmin || isManager || isViewer
hasStaffRights: isAdmin || isManager || isViewer,
overnightReservations: resource.overnightReservations,
};
}
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { Link } from 'react-router-dom';
import { Glyphicon } from 'react-bootstrap';

import { shallowWithIntl } from 'utils/testUtils';
import { UnconnectedResourceInfo as ResourceInfo, selector } from './ResourceInfoContainer';
Expand All @@ -21,7 +22,8 @@ function getState() {
isAdmin: false,
isManager: true,
isViewer: false
}
},
overnightReservations: false,
},
},
},
Expand All @@ -39,6 +41,7 @@ describe('shared/availability-view/ResourceInfoContainer', () => {
peopleCapacity: 19,
public: true,
hasStaffRights: true,
overnightReservations: false,
};
return shallowWithIntl(<ResourceInfo {...defaults} {...props} />);
}
Expand All @@ -53,6 +56,11 @@ describe('shared/availability-view/ResourceInfoContainer', () => {
expect(wrapper.is('.resource-info-selected')).toBe(true);
});

test('has overnight class if overnightReservations is true', () => {
const wrapper = getWrapper({ overnightReservations: true });
expect(wrapper.is('.is-overnight')).toBe(true);
});

test('renders the name and link to resource page', () => {
const date = '2017-02-03';
const link = getWrapper({ date, id: 'r-1', name: 'Room 1' }).find(Link);
Expand Down Expand Up @@ -87,6 +95,33 @@ describe('shared/availability-view/ResourceInfoContainer', () => {
expect(label).toHaveLength(0);
});

describe('when overnightReservations is true', () => {
test('renders unusable label', () => {
const label = getWrapper({ overnightReservations: true }).find(Label);
expect(label).toHaveLength(1);
expect(label.prop('bsStyle')).toBe('default');
expect(label.prop('className')).toBe('unusable-label');
expect(label.prop('title')).toBe('AdminResourcesPage.label.notUsable');
expect(label.prop('children')).toBe('AdminResourcesPage.label.notUsable');
});

test('does not render user icon', () => {
const icon = getWrapper({ overnightReservations: true }).find(Glyphicon);
expect(icon).toHaveLength(0);
});

test('does not render UnpublishedLabel', () => {
const label = getWrapper({ overnightReservations: true }).find(UnpublishedLabel);
expect(label).toHaveLength(0);
});

test('does not render external label', () => {
const label = getWrapper({ overnightReservations: true, hasStaffRights: false })
.find('.unpublished-label');
expect(label).toHaveLength(0);
});
});

describe('selector', () => {
function getSelected(props) {
const defaults = { id: '123456' };
Expand All @@ -100,6 +135,7 @@ describe('shared/availability-view/ResourceInfoContainer', () => {
peopleCapacity: 9,
public: true,
hasStaffRights: true,
overnightReservations: false,
});
});
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,12 @@ export function selector() {
const timeRestrictionsSelector = createSelector(
resourceSelector,
resource => {
const { minPeriod, maxPeriod, cooldown } = resource;
return { minPeriod, maxPeriod, cooldown };
const {
minPeriod, maxPeriod, cooldown, overnightReservations
} = resource;
return {
minPeriod, maxPeriod, cooldown, overnightReservations
};
}
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ function getState() {
'resource-1': {
id: 'resource-1',
userPermissions: {},
overnightReservations: false,
reservations: [
{
id: 111,
Expand Down Expand Up @@ -47,7 +48,11 @@ function getState() {
},
],
},
'resource-2': { id: 'resource-2', userPermissions: {}, },
'resource-2': {
id: 'resource-2',
userPermissions: {},
overnightReservations: false,
},
},
},
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ function getTimeSlotWidth({ startTime, endTime } = {}) {
}

function getTimelineItems(date, reservations, resourceId, timeRestrictions, hasStaffRights) {
const { cooldown, minPeriod, maxPeriod } = timeRestrictions;
const {
cooldown, minPeriod, maxPeriod, overnightReservations
} = timeRestrictions;
// skip getting cooldowns if user has perms
const cooldownRanges = hasStaffRights ? [] : getCooldownRanges(reservations, cooldown);
const items = [];
Expand All @@ -25,7 +27,7 @@ function getTimelineItems(date, reservations, resourceId, timeRestrictions, hasS
while (timePointer.isBefore(end)) {
const reservation = reservations && reservations[reservationPointer];
const isSlotReservation = reservation && timePointer.isSame(reservation.begin);
if (isSlotReservation) {
if (isSlotReservation && !overnightReservations) {
items.push({
key: String(items.length),
type: 'reservation',
Expand Down Expand Up @@ -93,6 +95,11 @@ function markItemsSelectable(items, isSelectable, openingHours, external, after)
function addSelectionData(selection, resource, items) {
const canIgnoreOpeningHours = resource.userPermissions.canIgnoreOpeningHours;
const reservableAfter = resource.reservableAfter;

if (resource.overnightReservations) {
return items;
}

if (!selection) {
return markItemsSelectable(
items, true, resource.openingHours, canIgnoreOpeningHours, reservableAfter);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,17 @@ describe('shared/availability-view/utils', () => {
expect(actual).toEqual(expected);
});

test('returns items as is when resource overnightReservations is true', () => {
const expected = getItems(false, false, false, false);
const resource = {
id: 'r1',
userPermissions,
overnightReservations: true,
};
const actual = utils.addSelectionData(null, resource, items);
expect(actual).toEqual(expected);
});

test('marks not selectable if outside available hours', () => {
const expected = getItems(false, true, false, true);
const resource = {
Expand Down Expand Up @@ -466,6 +477,25 @@ describe('shared/availability-view/utils', () => {
expect(actual).toEqual(expected);
});

test('returns only slots when overnightReservations is true', () => {
const reservations = [
{ id: 11, begin: '2016-01-01T02:00:00', end: '2016-01-01T10:00:00' },
{ id: 12, begin: '2016-01-01T12:30:00', end: '2016-01-01T20:00:00' },
{ id: 13, begin: '2016-01-01T20:00:00', end: '2016-01-01T20:30:00' },
];
const timeRestrictions2 = {
cooldown: '01:00:00',
minPeriod: '00:30:00',
maxPeriod: '01:00:00',
overnightReservations: true,
};
const items = utils.getTimelineItems(
moment('2016-01-01T00:00:00'), reservations, '1', timeRestrictions2, hasStaffRights);
items.forEach(item => {
expect(item.type).toBe('reservation-slot');
});
});

test.each([true, false])('returns slots and reservations correctly when there is cooldown and hasStaffRights is %p', hasRights => {
const timeRestrictions2 = { cooldown: '01:00:00', minPeriod: '00:30:00', maxPeriod: '01:00:00' };
const reservations = [
Expand Down
8 changes: 7 additions & 1 deletion app/shared/label/_label.scss
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,10 @@
color: #000;
}
}
}

&.unusable-label {
.label {
color: $black;
}
}
}

0 comments on commit d721e6e

Please sign in to comment.