Skip to content

Commit

Permalink
Slot settings on event creation
Browse files Browse the repository at this point in the history
  • Loading branch information
Alf-Melmac committed Jan 28, 2022
1 parent 45267df commit 3f1b572
Show file tree
Hide file tree
Showing 13 changed files with 218 additions and 30 deletions.
11 changes: 11 additions & 0 deletions src/main/java/de/webalf/slotbot/assembler/GuildAssembler.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
import de.webalf.slotbot.model.dtos.GuildDto;
import lombok.experimental.UtilityClass;

import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
* @author Alf
* @since 16.01.2022
Expand All @@ -27,6 +31,13 @@ public static GuildDto toDto(Guild guild) {

return GuildDto.builder()
.id(guild.getId())
.groupIdentifier(guild.getGroupIdentifier())
.build();
}

public static List<GuildDto> toDtoList(Iterable<? extends Guild> guilds) {
return StreamSupport.stream(guilds.spliterator(), false)
.map(GuildAssembler::toDto)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ private EventDetailsSlotDto toEventDetailsSlotDto(@NonNull Slot slot) {
.id(slot.getId())
.name(slot.getName())
.number(slot.getNumber())
.reservedFor(slot.getReservedFor() != null ? slot.getReservedFor().getId() : null)
.text(text)
.occupied(!(slot.getUser() == null || slot.getUser().isDefaultUser()))
.blocked(blocked)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package de.webalf.slotbot.controller.website;

import de.webalf.slotbot.assembler.GuildAssembler;
import de.webalf.slotbot.assembler.website.EventDetailsAssembler;
import de.webalf.slotbot.controller.EventController;
import de.webalf.slotbot.controller.FileController;
import de.webalf.slotbot.model.Event;
import de.webalf.slotbot.model.dtos.website.EventDetailsDto;
import de.webalf.slotbot.service.EventService;
import de.webalf.slotbot.service.EventTypeService;
import de.webalf.slotbot.service.GuildService;
import de.webalf.slotbot.util.DiscordMarkdown;
import de.webalf.slotbot.util.LongUtils;
import de.webalf.slotbot.util.StringUtils;
Expand Down Expand Up @@ -42,6 +44,7 @@ public class EventWebController {
private final EventService eventService;
private final EventDetailsAssembler eventDetailsAssembler;
private final EventTypeService eventTypeService;
private final GuildService guildService;

private static final String EVENTS_URL_STRING = "eventsUrl";
private static final String EVENTS_URL = linkTo(methodOn(EventWebController.class).getEventsHtml()).toUri().toString();
Expand Down Expand Up @@ -75,6 +78,7 @@ public ModelAndView getWizardHtml(@RequestParam(required = false) String date, @
mav.addObject("eventTypes", eventTypeService.findAll());
mav.addObject("eventFieldDefaultsUrl", linkTo(methodOn(EventController.class).getEventFieldDefaults(null)).toUri().toString());
mav.addObject("uploadSqmFileUrl", linkTo(methodOn(FileController.class).postSqmFile(null)).toUri().toString());
mav.addObject("guilds", GuildAssembler.toDtoList(guildService.findAllExceptDefault()));
mav.addObject("postEventUrl", linkTo(methodOn(EventController.class).postEvent(null)).toUri().toString());
mav.addObject("eventDetailsUrl", linkTo(methodOn(EventWebController.class)
.getEventDetailsHtml(Long.MIN_VALUE))
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/de/webalf/slotbot/model/dtos/GuildDto.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
import lombok.Value;
import lombok.experimental.SuperBuilder;

import javax.validation.constraints.Size;

import static de.webalf.slotbot.util.MaxLength.TEXT;

/**
* @author Alf
* @since 16.01.2022
Expand All @@ -15,4 +19,6 @@
@Value
@SuperBuilder
public class GuildDto extends AbstractIdEntityDto {
@Size(max = TEXT)
String groupIdentifier;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class EventDetailsSlotDto extends AbstractIdEntityDto {

int number;

Long reservedFor;

String text;

boolean occupied;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class EventDetailsSquadDto extends AbstractIdEntityDto {
@Size(max = TEXT)
String name;

Long reservedFor;

List<EventDetailsSlotDto> slotList;

boolean notEmpty;
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/de/webalf/slotbot/service/EventService.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Consumer;

import static de.webalf.slotbot.model.Guild.GUILD_PLACEHOLDER;
import static de.webalf.slotbot.util.permissions.BotPermissionHelper.hasEventManageRole;
Expand Down Expand Up @@ -58,12 +59,31 @@ public Event createEvent(@NonNull EventDto eventDto) {
Event event = eventAssembler.fromDto(eventDto);
event.setEventType(eventTypeService.find(eventDto.getEventType()));
event.setOwnerGuild(guildService.getOwnerGuild(eventDto));
setReservedFor(event);

event.validate();

return eventRepository.save(event);
}

private void setReservedFor(@NonNull Event event) {
event.getSquadList().forEach(squad -> {
evaluateReservedFor(squad.getReservedFor(), squad::setReservedFor);
squad.getSlotList().forEach(slot ->
evaluateReservedFor(slot.getReservedFor(), slot::setReservedFor));
});
}

private void evaluateReservedFor(Guild reservedFor, Consumer<Guild> consumer) {
if (reservedFor != null) {
if (reservedFor.getId() != GUILD_PLACEHOLDER) {
consumer.accept(guildService.find(reservedFor.getId()));
} else {
consumer.accept(null);
}
}
}

/**
* Returns an optional for the event associated with the given channelId
*
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/de/webalf/slotbot/service/GuildService.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import static de.webalf.slotbot.model.Guild.GUILD_PLACEHOLDER;

Expand All @@ -36,6 +37,10 @@ public List<Guild> findAll() {
return guildRepository.findAll();
}

public List<Guild> findAllExceptDefault() {
return findAll().stream().filter(guild -> guild.getId() != GUILD_PLACEHOLDER).collect(Collectors.toUnmodifiableList());
}

private List<Guild> findAllWithUrlPattern() {
return guildRepository.findByUrlPatternIsNotNull();
}
Expand Down
7 changes: 6 additions & 1 deletion src/main/resources/static/assets/js/eventSave.js
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,16 @@ function getSquads(update = false) {
name: $slot.find('.js-slot-name').val().trim(),
number: $slot.find('.js-slot-number').val()
};
if ($slot.find('.fa-lock').length !== 0) {
const $slotSettings = $slot.find('.js-settings');
slot.reservedFor = $slotSettings.attr('data-reservedfor');
const blocked = $slotSettings.attr('data-blocked') === "true";
slot.blocked = blocked;
if (blocked) {
slot.user = {
id: defaultUserId
}
}
slot.replacementText = $slotSettings.attr('data-replacementtext');
if (update) {
slot.id = $slot.data('slotid');
}
Expand Down
70 changes: 41 additions & 29 deletions src/main/resources/static/assets/js/slotList.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,41 @@ $(function () {

const newSlot =
`<div class="form-row align-items-center js-slot">
<div class="col-md-1">
<input class="form-control js-slot-number" type="number" min="1" value="{defaultSlotValue}" required>
</div>
<div class="col-md-10">
<input class="form-control js-slot-name" type="text" placeholder="Slot Name" required>
</div>
<div class="col-md-1 d-flex">
<div class="btn btn-xl btn-lock p-0 pr-1 js-lock" type="button" title="Blockierung">
<em class="fas fa-lock-open"></em>
</div>
<div class="btn btn-xl btn-wht p-0 js-trash" type="button">
<em class="far fa-trash-alt"></em>
<div class="col-md-1">
<input class="form-control js-slot-number" type="number" min="1" value="{defaultSlotValue}" required>
</div>
<div class="col-md-10">
<input class="form-control js-slot-name" type="text" placeholder="Slot Name" required>
</div>
<div class="col-md-1">
<div class="dropdown">
<div class="btn btn-xl btn-wht p-0 pr-1" type="button" data-toggle="dropdown" aria-expanded="false">
<em class="fas fa-ellipsis-h"></em>
</div>
<div class="dropdown-menu">
<button class="dropdown-item js-settings" type="button" data-toggle="modal" data-target="#slotSettings">
<div class="row">
<div class="col-3">
<em class="fas fa-user-cog"></em>
</div>
<div class="col-9">
<span>Regeln</span>
</div>
</div>
</button>
<button class="dropdown-item js-trash" type="button">
<div class="row">
<div class="col-3">
<em class="far fa-trash-alt"></em>
</div>
<div class="col-9">
<span>Löschen</span>
</div>
</div>
</button>
</div>
</div>
</div>
</div>
</div>`;

const newSquad =
Expand Down Expand Up @@ -66,19 +87,6 @@ $(function () {
$this.appendTo($slots);
});

$squads.on('click', '.js-lock:not(.js-blocked, .btn-denied)', function () {
$(this).find('.fas').toggleClass('fa-lock-open fa-lock');
});

$squads.on('click', '.js-trash', function () {
const $row = $(this).parents('.form-row');
if ($row.hasClass('js-squad')) {
$row.parent('.js-complete-squad').remove();
} else {
$row.remove();
}
});

function findFirstUnusedSlotNumber() {
const slotNumbers = getSlotNumbers().sort((a, b) => a - b);
let slotNumber = 1;
Expand Down Expand Up @@ -135,9 +143,13 @@ function fillSquad($squad, squad) {
if (slot.number !== 0) {
$slot.find('.js-slot-number').val(slot.number);
}
if (slot.blocked) {
$slot.find('.js-lock').trigger('click');
}
$slot.find('.js-slot-name').val(slot.name);
const $slotSettings = $slot.find('.js-setting');
$slotSettings.attr('data-reservedfor', slot.reservedFor);
const blocked = slot.blocked;
$slotSettings.attr('data-blocked', blocked);
if (blocked) {
$slotSettings.attr('data-replacementtext', slot.text);
}
}
}
82 changes: 82 additions & 0 deletions src/main/resources/static/assets/js/slotSettings.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
$(function ($) {
"use strict";

const $squads = $('#squads');

const $slotSettings = $('#slotSettings');
const slotSettingsModal = $slotSettings.find('.modal-body').prop('outerHTML');

$slotSettings.on('show.bs.modal', function (e) {
const $dropdownEl = $(e.relatedTarget);
$dropdownEl.addClass('js-active-modal');
const $modal = $(e.currentTarget);
$modal.find('#slotSettingsModalLabel').text(getHeaderForModal($dropdownEl.parents('.form-row')));

//Strangely JQuery doesn't update data fields, therefor using attr
const reservedFor = $dropdownEl.attr('data-reservedfor');
if (reservedFor && reservedFor !== 'null') {
$slotSettings.find(`#slotSettingReservation option[value="${reservedFor}"]`).prop('selected', true);
}
if ($dropdownEl.attr('data-blocked') === 'true') { //Bang Bang doesn't work?!
$slotSettings.find('#slotSettingBlocked').trigger('click');
}
$slotSettings.find('#slotReplacementText').val($dropdownEl.attr('data-replacementtext'));
});

$slotSettings.on('click', '#saveSlotSettings', function (e) {
const $modalContent = $(e.currentTarget).parents('.modal-content');
const $dropdownEl = $('.js-active-modal');
$modalContent.find('select,input').each(function (index, element) {
const $el = $(element);
const key = $el.data('key');

if (!key || key === '') {
console.error('empty key');
console.log($el);
return;
}

let value = $el.val();
if (typeof value == 'string') {
value = value.trim();
}
$dropdownEl.attr(`data-${key}`, value);
});
$dropdownEl.attr('data-blocked', $modalContent.find('#slotSettingBlocked').find('.fa-lock').length !== 0);
$slotSettings.modal('hide');
})

$slotSettings.on('hidden.bs.modal', function (e) {
$('.js-active-modal').removeClass('js-active-modal');
$slotSettings.find('.modal-body').replaceWith(slotSettingsModal);
})

$slotSettings.on('click', '#slotSettingBlocked', /*':not(.js-blocked, .btn-denied)',*/ function() {
$(this).find('.fas').toggleClass('fa-lock-open fa-lock');
$slotSettings.find('#slotReplacementText').toggle($(this).find('.fa-lock').length !== 0);
});

$squads.on('click', '.js-trash', function () {
const $row = $(this).parents('.form-row');
if ($row.hasClass('js-squad')) {
$row.parent('.js-complete-squad').remove();
} else {
$row.remove();
}
});
});

function getHeaderForModal($row) {
let header = 'Regeln für';
const slotNumber = $row.find('.js-slot-number').val();
if (!isNaN(slotNumber)) {
header += ` (${slotNumber})`;
}
const slotName = $row.find('.js-slot-name').val().trim();
if (slotName) {
header += ` ${slotName}`;
} else {
header += ' Slot';
}
return header;
}
2 changes: 2 additions & 0 deletions src/main/resources/templates/eventWizard.html
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ <h3>Teilnahmeplatzaufzählung</h3>
<!--Add modals-->
<div th:replace="fragments/modals.html :: addDefaultFieldsWarning"></div>
<div th:replace="fragments/modals.html :: uploadSlotlistModal"></div>
<div th:replace="fragments/modals.html :: slotSettings"></div>

<footer th:replace="fragments/general.html :: footer(false)"></footer>

Expand All @@ -238,6 +239,7 @@ <h3>Teilnahmeplatzaufzählung</h3>
<script th:src="@{/assets/js/eventFields.js}"></script>
<script th:src="@{/assets/js/slotList.js}"></script>
<script th:src="@{/assets/js/uploadSqmFile.js}"></script>
<script th:src="@{/assets/js/slotSettings.js}"></script>
<script th:src="@{/assets/js/eventWizard.js}"></script>

<script th:src="@{/assets/js/colorpicker.js}"></script>
Expand Down

0 comments on commit 3f1b572

Please sign in to comment.