Skip to content

Commit

Permalink
lumen: 👥 Add 'book for someone' feature
Browse files Browse the repository at this point in the history
GitOrigin-RevId: 09a608ea6b00898f8ae6e8966a4a3f88c9ad8ef7
  • Loading branch information
p-bizouard committed Mar 4, 2024
1 parent 1e209bf commit 1b6fab0
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 114 deletions.
3 changes: 1 addition & 2 deletions back/src/routes/book.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ router.post("/add/", requireAgendaAnnuaire, async (
/!\ startDate and endDate must be in ISO 8601 string format.
*/

try {
// Sanity check of inputs
validate.input(validate.schema.addEvent, req.body);
Expand All @@ -61,7 +60,7 @@ router.post("/add/", requireAgendaAnnuaire, async (
);
if (!room.allowBookings) {
if (room.belongsTo.length === 0) {
// ? Room need to belongs to a group that has some members
logger.error("Room need to belongs to a group that has some members");
res.sendStatus(500);
return;
}
Expand Down
7 changes: 1 addition & 6 deletions front/src/actions/bookings/modify/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,6 @@ export function sendModifRequest(event, newAttr) {

// Do nothing if eventName is empty
if (!newAttr.eventName) return;
if (newAttr.forUserName) {
newAttr.eventName = `<${newAttr.forUserName}> ${newAttr.eventName}`;
}
dispatch(requestModif());

// Format dates
Expand Down Expand Up @@ -110,9 +107,7 @@ export function sendModifRequest(event, newAttr) {
},
body: JSON.stringify({
eventId: event.id,
newEventName: newAttr.forUserName
? `<${newAttr.forUserName}> ${newAttr.eventName}`
: newAttr.eventName,
newEventName: newAttr.eventName,
newStartDate,
newEndDate,
newRoomId: newAttr.roomId,
Expand Down
2 changes: 1 addition & 1 deletion front/src/actions/rooms/book/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export function sendBookRequest() {
'Content-Type': 'application/json',
},
body: JSON.stringify({
eventName: forUserName ? `<${forUserName}> ${eventName}` : eventName,
eventName: forUserName ? `${forUserName} - ${eventName}` : eventName,
videoProvider,
startDate: formattedDate.start,
endDate: formattedDate.end,
Expand Down
29 changes: 9 additions & 20 deletions front/src/components/partials/EventList.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,6 @@ const EventList = ({
<div className="list-group mt-3">
{events.map((event) => {
const isHighlighted = event.id === highlightedEvent;
const matchForUserNameAndEventName = event.name.match(/<(.*?)>(.*)/);
let forUserName = null;
let eventName = event.name;
if (matchForUserNameAndEventName) {
forUserName = matchForUserNameAndEventName[1].trim();
eventName = matchForUserNameAndEventName[2].trim();
}
return (
<div
className={`list-group-item flex-column align-items-start ${
Expand All @@ -57,7 +50,7 @@ const EventList = ({
key={event.id}
>
<div className="d-flex w-100 justify-content-between">
<h5 className="mb-1">{eventName}</h5>
<h5 className="mb-1">{event.name}</h5>
<span className={!isHighlighted ? 'text-muted' : ''}>
de&nbsp;
{moment(event.startDate).utc().format('H[h]mm')}
Expand All @@ -67,18 +60,14 @@ const EventList = ({
</div>
<span className={!isHighlighted ? 'text-muted' : ''}>
Réservé par &nbsp;
{forUserName ? (
<span>{recapitalize(forUserName)}</span>
) : (
<a
className={!isHighlighted ? 'text-secondary' : 'text-white'}
href={`mailto:${event.author.email}`}
>
{recapitalize(event.author.firstName)}
&nbsp;
{recapitalize(event.author.lastName)}
</a>
)}
<a
className={!isHighlighted ? 'text-secondary' : 'text-white'}
href={`mailto:${event.author.email}`}
>
{recapitalize(event.author.firstName)}
&nbsp;
{recapitalize(event.author.lastName)}
</a>
</span>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import 'moment/locale/fr';
import RoomResource from 'containers/partials/RoomResource';
import extractResources from 'services/extractResources';

const Booking = ({
event, handleCancelEvent, handleModifyEvent, isFuture,
}) => (
const Booking = ({ event, handleCancelEvent, handleModifyEvent, isFuture }) => (
<div className="card mb-3">
<div className="card-body">
<div className="row align-items-center justify-content-between">
Expand All @@ -23,8 +21,8 @@ const Booking = ({
</div>
<div className="col-lg-4">
<ul>
{event.room
&& extractResources(event.room, true).map((res) => (
{event.room &&
extractResources(event.room, true).map((res) => (
<RoomResource
key={`${event.room.id}#${res.type}`}
resource={res}
Expand All @@ -35,19 +33,13 @@ const Booking = ({
</div>
<div className="col-lg-3 my-4 custom-info-text-color">
<h5>{event.name}</h5>
{moment(event.startDate)
.utc()
.format('dddd D MMMM YYYY')}
{moment(event.startDate).utc().format('dddd D MMMM YYYY')}
<br />
{moment(event.startDate)
.utc()
.format('H[h]mm')}
{moment(event.startDate).utc().format('H[h]mm')}
&nbsp;
<FontAwesomeIcon icon={faAngleRight} />
&nbsp;
{moment(event.endDate)
.utc()
.format('H[h]mm')}
{moment(event.endDate).utc().format('H[h]mm')}
</div>
<div className="col-lg-3 custom-text-right-above-lg custom-text-center-under-lg">
{isFuture && !event.local && (
Expand Down Expand Up @@ -77,17 +69,6 @@ const Booking = ({
>
Modifier le titre
</button>
<button
type="button"
className="dropdown-item"
data-toggle="modal"
data-target="#modifyEventModal"
onClick={() => {
handleModifyEvent(event, 'forUserName');
}}
>
Modifier pour le compte de
</button>
{event.room.allowBooking && (
<button
type="button"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,33 @@ import PropTypes from 'prop-types';
import ConfirmModal from 'components/partials/Modals/ConfirmModal';
import TimeChangeBody from './TimeChangeBody';
import NameChangeBody from './NameChangeBody';
import ForUserNameChangeBody from './ForUserNameChangeBody';

const ConfirmModify = ({
event,
modifType,
sendUpdatedBooking,
handleNameInputChange,
handleForUserNameInputChange,
handleDateInputChange,
newAttributes,
detectEnter,
attemptedConfirm,
}) => {
let body;
const matchForUserNameAndEventName =
newAttributes.eventName.match(/<(.*?)>(.*)/);
if (matchForUserNameAndEventName) {
newAttributes.forUserName = matchForUserNameAndEventName[1].trim();
newAttributes.eventName = matchForUserNameAndEventName[2].trim();
}
if (modifType === 'name') {
body = (
const body =
modifType === 'name' ? (
<NameChangeBody
event={event}
handleNameInputChange={handleNameInputChange}
eventName={newAttributes.eventName}
detectEnter={detectEnter}
attemptedConfirm={attemptedConfirm}
/>
);
} else if (modifType === 'forUserName') {
body = (
<ForUserNameChangeBody
event={event}
handleForUserNameInputChange={handleForUserNameInputChange}
forUserName={newAttributes.forUserName}
detectEnter={detectEnter}
attemptedConfirm={attemptedConfirm}
/>
);
} else {
body = (
) : (
<TimeChangeBody
event={event}
handleDateInputChange={handleDateInputChange}
newAttributes={newAttributes}
/>
);
}

return (
<ConfirmModal
Expand All @@ -76,7 +54,6 @@ ConfirmModify.propTypes = {
modifType: PropTypes.string.isRequired,
sendUpdatedBooking: PropTypes.func.isRequired,
handleNameInputChange: PropTypes.func.isRequired,
handleForUserNameInputChange: PropTypes.func.isRequired,
handleDateInputChange: PropTypes.object.isRequired,
newAttributes: PropTypes.object.isRequired,
detectEnter: PropTypes.func.isRequired,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ export default class extends React.PureComponent {
newAttributes: PropTypes.object.isRequired,
handleNameInputChange: PropTypes.func.isRequired,
handleDateInputChange: PropTypes.object.isRequired,
handleForUserNameInputChange: PropTypes.object.isRequired,
};

static defaultProps = {
Expand All @@ -41,7 +40,6 @@ export default class extends React.PureComponent {
newAttributes,
handleNameInputChange,
handleDateInputChange,
handleForUserNameInputChange,
} = this.props;

return (
Expand All @@ -61,7 +59,6 @@ export default class extends React.PureComponent {
sendUpdatedBooking={this.sendUpdatedBooking}
handleNameInputChange={handleNameInputChange}
handleDateInputChange={handleDateInputChange}
handleForUserNameInputChange={handleForUserNameInputChange}
newAttributes={newAttributes}
detectEnter={this.detectEnter}
attemptedConfirm={status.attemptedConfirm}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import React, { useState, useEffect } from 'react';
import PropTypes from 'prop-types';
import OptionalImage from 'react-image';
import { connect } from 'react-redux';

// src
import config from 'config';
import ConfirmModal from 'components/partials/Modals/ConfirmModal';
Expand All @@ -11,7 +13,11 @@ import EventNameInput from './EventNameInput';
import VideoProviderInput from './VideoProviderInput';
import ForUserNameInput from './ForUserNameInput';

const { CAMPUS_SACLAY } = require('../../../../../config/index');
const {
CAMPUS_SACLAY,
LUMEN_GROUP_ID,
BUILDING_LUMEN,
} = require('../../../../../config/index');

const imageExtension = 'jpg';

Expand All @@ -29,20 +35,18 @@ const ConfirmBooking = ({
handleVideoProviderInputChange,
attemptedConfirm,
detectEnter,
memberOf,
}) => {
const [tooLongTimes, setTooLongTimes] = useState(false);

useEffect(() => {
const checkTimeCoherence = () => {
setTooLongTimes(false);
if (room.campus === CAMPUS_SACLAY) {
const diffTime = endTime - startTime;
if (diffTime / 3600000 > 2) {
setTooLongTimes(true);
}
setTooLongTimes(false);
if (room.campus === CAMPUS_SACLAY) {
const diffTime = endTime - startTime;
if (diffTime / 3600000 > 2) {
setTooLongTimes(true);
}
};
checkTimeCoherence();
}
}, [room.campus, endTime, startTime]);

const body = [
Expand Down Expand Up @@ -72,8 +76,7 @@ const ConfirmBooking = ({
) : null,
tooLongTimes === true ? (
<div className="alert alert-danger" role="alert">
Pour un créneau supérieur à 2h, contacter
{' '}
Pour un créneau supérieur à 2h, contacter{' '}
<a href="mailto:[email protected]">
[email protected]
</a>
Expand All @@ -87,14 +90,16 @@ const ConfirmBooking = ({
attemptedConfirm={attemptedConfirm}
key="eventNameInput"
/>,
<ForUserNameInput
available={room.available}
forUserName={forUserName}
handleForUserNameInputChange={handleForUserNameInputChange}
detectEnter={detectEnter}
attemptedConfirm={attemptedConfirm}
key="forUserNameInput"
/>,
memberOf.includes(LUMEN_GROUP_ID) && room.building === BUILDING_LUMEN ? (
<ForUserNameInput
available={room.available}
forUserName={forUserName}
handleForUserNameInputChange={handleForUserNameInputChange}
detectEnter={detectEnter}
attemptedConfirm={attemptedConfirm}
key="forUserNameInput"
/>
) : null,
<VideoProviderInput
enabled={room.videoConference}
providers={room.videoProviders}
Expand All @@ -111,12 +116,12 @@ const ConfirmBooking = ({
<ConfirmModal
title={`Réservation de ${room.name}`}
body={body}
confirmButtonText={(
confirmButtonText={
<span>
Confirmer
<span className="d-none d-sm-inline"> la réservation</span>
</span>
)}
}
confirmButtonFunction={confirmBooking}
showConfirmButton={room.available && !tooLongTimes}
cancelActionText={room.available ? 'Annuler' : 'OK'}
Expand All @@ -139,6 +144,9 @@ ConfirmBooking.propTypes = {
handleVideoProviderInputChange: PropTypes.func.isRequired,
attemptedConfirm: PropTypes.bool.isRequired,
detectEnter: PropTypes.func.isRequired,
memberOf: PropTypes.array.isRequired,
};

export default ConfirmBooking;
const mapStateToProps = (state) => ({ ...state.user });

export default connect(mapStateToProps)(ConfirmBooking);
3 changes: 2 additions & 1 deletion front/src/components/scenes/Search/RoomBookModal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ RoomBookModal.propTypes = {
selectedStartTime: PropTypes.object.isRequired,
selectedEndTime: PropTypes.object.isRequired,
eventName: PropTypes.string.isRequired,
forUserName: PropTypes.string.isRequired,
forUserName: PropTypes.string,
videoProvider: PropTypes.string.isRequired,
attemptedConfirm: PropTypes.bool.isRequired,
failedBecauseAlreadyBooked: PropTypes.bool.isRequired,
Expand All @@ -111,6 +111,7 @@ RoomBookModal.defaultProps = {
errorStatus: null,
room: null,
directLinkRoom: null,
forUserName: '',
};

export default RoomBookModal;
4 changes: 3 additions & 1 deletion front/src/config/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ const loginQuery = querystring.stringify({
export const loginRequest = `${config.cas.loginUrl}?${loginQuery}`;
export const CAMPUSES = ['Saclay', 'Metz', 'Rennes'];
export const CAMPUS_SACLAY = 'Saclay';
export const BUILDINGS = ['Falguière', 'IBM'];
export const BUILDING_LUMEN = 'Lumen';
export const LUMEN_GROUP_ID = 204;
export const BUILDINGS = ['Falguière', 'IBM', BUILDING_LUMEN];

export default config;
Loading

0 comments on commit 1b6fab0

Please sign in to comment.