Merge branch 'flatpickr'

This commit is contained in:
Björn Fromme
2018-09-13 21:12:59 +02:00
12 changed files with 96 additions and 233 deletions
+5
View File
@@ -3176,6 +3176,11 @@
"locate-path": "^2.0.0" "locate-path": "^2.0.0"
} }
}, },
"flatpickr": {
"version": "4.5.2",
"resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.5.2.tgz",
"integrity": "sha512-jDy4QYGpmiy7+Qk8QvKJ4spjDdxcx9cxMydmq1x427HkKWBw0qizLYeYM2F6tMcvvqGjU5VpJS55j4LnsaBblA=="
},
"flatten": { "flatten": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz", "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.2.tgz",
+2 -1
View File
@@ -11,11 +11,12 @@
}, },
"dependencies": { "dependencies": {
"@fancyapps/fancybox": "^3.2.5", "@fancyapps/fancybox": "^3.2.5",
"@fengyuanchen/datepicker": "^0.6.4", "@fengyuanchen/datepicker": "^0.6.5",
"bootstrap-sass": "^3.3.7", "bootstrap-sass": "^3.3.7",
"bourbon": "^4.3.2", "bourbon": "^4.3.2",
"cookieconsent": "^3.1.0", "cookieconsent": "^3.1.0",
"dayjs": "^1.7.5", "dayjs": "^1.7.5",
"flatpickr": "^4.5.2",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"iframe-resizer": "^3.6.1", "iframe-resizer": "^3.6.1",
"jquery": "^2.2.4", "jquery": "^2.2.4",
@@ -91,31 +91,35 @@ class AjaxSearchController extends ActionController
{ {
$dateSelected = false; $dateSelected = false;
$organic = true; $organic = true;
$forcedConceptUid = (int) $this->settings['forcedConceptUid'];
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
if ($filterSettings === null) { if ($filterSettings === null) {
$forcedConceptUid = (int) $this->settings['forcedConceptUid'];
$filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUid); $filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUid);
} elseif ($filterSettings->getDateFrom() !== null || $filterSettings->getDateTo() !== null) { }
if ($filterSettings->getDateFrom() !== null || $filterSettings->getDateTo() !== null) {
$dateSelected = true; $dateSelected = true;
} }
$excludedConceptUids = GeneralUtility::trimExplode(',', $this->settings['excludedConceptUids']);
$filterOptions = $this->filterService->getFilterOptions($filterSettings, $excludedConceptUids);
if ($filterOptions === null) {
$filterSettings = $this->filterService->getDefaultFilterSettings();
$filterOptions = $this->filterService->getFilterOptions($filterSettings, $excludedConceptUids);
}
$searchResult = $this->searchResultService->getResult($filterSettings, $excludedConceptUids); $searchResult = $this->searchResultService->getResult($filterSettings, $excludedConceptUids);
if ($searchResult->getTotal() === 0) { if ($searchResult->getTotal() === 0) {
$filterSettings = $this->filterService->getDefaultFilterSettings(); $filterSettings = $this->filterService->getDefaultFilterSettings($forcedConceptUid);
$searchResult = $this->searchResultService->getResult($filterSettings, $excludedConceptUids); $searchResult = $this->searchResultService->getResult($filterSettings, $excludedConceptUids);
$organic = false; $organic = false;
} }
$filterOptions = $this->filterService->getFilterOptions($filterSettings, $excludedConceptUids);
$options = [ $options = [
'defaultDetailPageUid' => $this->settings['defaultDetailPageUid'], 'defaultDetailPageUid' => $this->settings['defaultDetailPageUid'],
'referringPageUid' => $referringPageUid, 'referringPageUid' => $referringPageUid,
'filterSettings' => $filterSettings, 'filterSettings' => $filterSettings,
]; ];
$this->searchResultUrlService->process($searchResult, $options); $this->searchResultUrlService->process($searchResult, $options);
return json_encode([ return json_encode([
'data' => $searchResult->getData(), 'data' => $searchResult->getData(),
'filterOptions' => $filterOptions, 'filterOptions' => $filterOptions,
@@ -91,7 +91,7 @@ class FilterService implements SingletonInterface
} }
$filterOptionsData = static::$cache['filterOptions'][$key]; $filterOptionsData = static::$cache['filterOptions'][$key];
if (count($filterOptionsData) === 0) { if (count($filterOptionsData) === 0) {
return null; return new FilterOptions();
} }
$dateRange = $this->constrainDateRange($this->getDateRange()); $dateRange = $this->constrainDateRange($this->getDateRange());
return $this->preprocessFilterOptions($filterOptionsData, $dateRange); return $this->preprocessFilterOptions($filterOptionsData, $dateRange);
@@ -5,3 +5,4 @@ require('cookieconsent/build/cookieconsent.min.css');
require('@fancyapps/fancybox/dist/jquery.fancybox.min.css'); require('@fancyapps/fancybox/dist/jquery.fancybox.min.css');
require('slick-carousel/slick/slick.css'); require('slick-carousel/slick/slick.css');
require('leaflet/dist/leaflet.css'); require('leaflet/dist/leaflet.css');
require('flatpickr/dist/flatpickr.css');
@@ -1,77 +0,0 @@
<template>
<input ref="field" type="text" :value="dateDisplayed" />
</template>
<script>
import Vue from 'vue'
import $ from 'jquery'
import dayjs from 'dayjs'
import 'dayjs/locale/de'
import datepicker from '@fengyuanchen/datepicker'
require('@fengyuanchen/datepicker/dist/datepicker.css');
export default {
props: {
date: {
default: null
},
minDate: {
type: Date,
default () {
return new Date()
}
},
maxDate: {
type: Date,
default () {
return new Date()
}
},
container: {
type: String,
required: true
}
},
computed: {
dateDisplayed () {
if (this.date === null) {
return '';
}
return dayjs(this.date).format('DD.MM.YYYY');
}
},
watch: {
date (value) {
this.date = value;
},
minDate (value) {
$(this.$refs.field).datepicker('setStartDate', value);
},
maxDate (value) {
$(this.$refs.field).datepicker('setEndDate', value);
}
},
mounted () {
const field = this.$refs.field;
Vue.nextTick(() => {
$(field).datepicker({
inline: true,
container: $(field).closest(this.container),
language: 'de-DE',
format: 'dd.mm.yyyy',
weekStart: 1,
days: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag'],
daysShort: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
daysMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September',
'Oktober', 'November', 'Dezember'],
monthsShort: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun', 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
startDate: this.minDate,
endDate: this.maxDate
}).on('pick.datepicker', (event) => {
this.$emit('picked', event.date);
});
});
}
}
</script>
@@ -4,13 +4,13 @@
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li class="dropdown" ref="dropdown"> <li class="dropdown" ref="dropdown">
<input type="text" class="form-control" placeholder="von... bis" <input type="text" class="form-control" placeholder="von... bis"
v-bind:value="selectedRange" v-on:click="togglePanel"/> :value="selectedRange" @click="togglePanel"/>
<ul class="dropdown-menu daterange"> <ul class="dropdown-menu daterange">
<li v-if="presets"> <li v-if="presets">
<div class="daterange__presets"> <div class="daterange__presets">
<template v-for="preset of presets"> <template v-for="preset of presets">
<a class="daterange__preset" href="#" <a class="daterange__preset" href="#"
v-on:click.prevent="selectPreset(preset)"> @click.prevent="selectPreset(preset)">
<i class="fa fa-calendar"></i> {{ preset.label }} <i class="fa fa-calendar"></i> {{ preset.label }}
</a> </a>
</template> </template>
@@ -18,44 +18,16 @@
</li> </li>
<li> <li>
<div class="daterange__panel"> <div class="daterange__panel">
<div class="daterange__column daterange--from"> <input ref="field" type="hidden">
<span class="headline headline--4 daterange__headline">Früheste Anreise</span>
<div class="daterange__picker">
<date-picker
class="daterange__input"
container=".daterange--from"
v-on:picked="updateFrom"
v-bind:date="range.from"
v-bind:min-date="dateFromMin"
v-bind:max-date="dateFromMax"
></date-picker>
<button class="daterange__button"
v-on:click.prevent="resetFrom">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
<div class="daterange__column daterange--to">
<span class="headline headline--4 daterange__headline">Späteste Abreise</span>
<div class="daterange__picker">
<date-picker
class="daterange__input"
container=".daterange--to"
v-on:picked="updateTo"
v-bind:date="range.to"
v-bind:min-date="dateToMin"
v-bind:max-date="dateToMax"
></date-picker>
<button class="daterange__button"
v-on:click.prevent="resetTo">
<i class="fa fa-trash-o"></i>
</button>
</div>
</div>
</div> </div>
</li> </li>
<li class="closebtn"> <li class="daterange__buttons">
<a class="btn btn-default btn-xs" href="#" v-on:click.prevent="togglePanel">schließen</a> <button class="daterange__button" @click.prevent="togglePanel">
<i class="fa fa-times"></i> schließen
</button>
<button class="daterange__button" @click.prevent="reset()">
<i class="fa fa-trash-o"></i> zurücksetzen
</button>
</li> </li>
</ul> </ul>
</li> </li>
@@ -64,25 +36,18 @@
</template> </template>
<script> <script>
import Vue from 'vue'
import $ from 'jquery' import $ from 'jquery'
import DatePicker from './Datepicker.vue'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import 'dayjs/locale/de' import 'dayjs/locale/de'
import flatpickr from 'flatpickr'
import { German } from 'flatpickr/dist/l10n/de'
import EventBus from '../_bus'
export default { export default {
components: {
DatePicker
},
data () { data () {
return { return {
dateFromMin: null, picker: null,
dateFromMax: null,
dateToMin: null,
dateToMax: null,
range: {
from: null,
to: null
},
selectedFrom: this.from, selectedFrom: this.from,
selectedTo: this.to selectedTo: this.to
} }
@@ -116,76 +81,58 @@
} }
}, },
created () { created () {
this.range.from = this.selectedFrom !== null ? new Date(this.selectedFrom) : null; Vue.nextTick(() => {
this.range.to = this.selectedTo !== null ? new Date(this.selectedTo) : null; this.picker = $(this.$refs.field).flatpickr({
this.dateFromMin = new Date(this.minDate); mode: 'range',
this.dateFromMax = new Date(this.maxDate); dateFormat: 'd.m.Y',
this.dateToMin = new Date(this.minDate); locale: German,
this.dateToMax = new Date(this.maxDate); inline: true,
}, minDate: new Date(this.minDate),
watch: { maxDate: new Date(this.maxDate),
from (value) { onChange: (selectedDates) => {
this.selectedFrom = value; if (selectedDates.length === 2) {
}, this.selectedFrom = selectedDates[0];
to (value) { this.selectedTo = selectedDates[1];
this.selectedTo = value; this.togglePanel();
}, this.$emit('selected', { from: this.selectedFrom, to: this.selectedTo });
minDate (date) { }
this.dateFromMin = new Date(date); }
this.dateToMin = new Date(date); });
}, if (this.from && this.to) {
maxDate (date) { this.picker.setDate([ new Date(this.from), new Date(this.to) ]);
this.dateFromMax = new Date(date); }
this.dateToMax = new Date(date); });
} EventBus.$on('filterSettingsReset', () => {
this.reset();
});
}, },
computed: { computed: {
selectedRange () { selectedRange () {
if (this.range.from == null && this.range.to == null) { if (this.selectedFrom == null && this.selectedTo == null) {
return ''; return '';
} }
if (this.range.from !== null && this.range.to === null) { return dayjs(this.selectedFrom).format('DD.MM.YYYY')
return 'ab ' + dayjs(this.range.from).format('DD.MM.YYYY'); + '-' + dayjs(this.selectedTo).format('DD.MM.YYYY');
}
if (this.range.from === null && this.range.to !== null) {
return 'bis ' + dayjs(this.range.to).format('DD.MM.YYYY');
}
return dayjs(this.range.from).format('DD.MM.YYYY') + '-' + dayjs(this.range.to).format('DD.MM.YYYY');
} }
}, },
methods: { methods: {
updateFrom (date) {
if (this.range.to !== null && dayjs(date).isAfter(this.range.to)) {
this.range.to = dayjs(date).add(1, 'd');
}
this.range.from = date;
this.dateToMin = date;
this.$emit('selected', this.range);
},
updateTo (date) {
if (this.range.from !== null && dayjs(date).isBefore(this.range.from)) {
date = dayjs(this.range.from).add(1, 'd');
}
this.range.to = date;
this.dateFromMax = date;
this.$emit('selected', this.range);
},
togglePanel () { togglePanel () {
$(this.$refs.dropdown).toggleClass('open'); $(this.$refs.dropdown).toggleClass('open');
}, },
resetFrom () {
this.range.from = null;
this.$emit('selected', this.range);
},
resetTo () {
this.range.to = null;
this.$emit('selected', this.range);
},
selectPreset (preset) { selectPreset (preset) {
this.range.from = new Date(preset.dateFrom); this.selectedFrom = new Date(preset.dateFrom);
this.range.to = new Date(preset.dateTo); this.selectedTo = new Date(preset.dateTo);
this.picker.setDate([ this.selectedFrom, this.selectedTo ]);
this.togglePanel(); this.togglePanel();
this.$emit('selected', this.range); this.$emit('selected', { from: this.selectedFrom, to: this.selectedTo });
},
reset () {
this.selectedFrom = null;
this.selectedTo = null;
this.picker.clear();
this.picker.jumpToDate();
this.togglePanel();
this.$emit('selected', { from: this.selectedFrom, to: this.selectedTo });
} }
} }
} }
@@ -16,13 +16,6 @@
}, },
data () { data () {
return { return {
lock: false,
dateRange () {
return {
dateFrom: null,
dateTo: null
}
},
searchParams: this.initialSearchParams, searchParams: this.initialSearchParams,
filterOptions: this.initialFilterOptions filterOptions: this.initialFilterOptions
} }
@@ -30,15 +23,10 @@
props: [ 'initialFilterOptions', 'initialSearchParams', 'optionsUri', 'resetUri', 'argumentPrefix', 'datePresets' ], props: [ 'initialFilterOptions', 'initialSearchParams', 'optionsUri', 'resetUri', 'argumentPrefix', 'datePresets' ],
methods: { methods: {
loadOptions () { loadOptions () {
if (this.lock) {
return;
}
this.lock = true;
const query = {}; const query = {};
query[this.argumentPrefix + '[searchParams]'] = this.searchParams; query[this.argumentPrefix + '[searchParams]'] = this.searchParams;
$.post(this.optionsUri, query, (json) => { $.post(this.optionsUri, query, (json) => {
this.applyOptions(json); this.applyOptions(json);
this.lock = false;
}, 'json'); }, 'json');
}, },
applyOptions (json) { applyOptions (json) {
@@ -10,7 +10,6 @@
}, },
data () { data () {
return { return {
lock: false,
searchParams: this.initialSearchParams, searchParams: this.initialSearchParams,
filterOptions: this.initialFilterOptions filterOptions: this.initialFilterOptions
} }
@@ -18,15 +17,10 @@
props: [ 'initialFilterOptions', 'initialSearchParams', 'optionsUri', 'resetUri', 'argumentPrefix', 'datePresets' ], props: [ 'initialFilterOptions', 'initialSearchParams', 'optionsUri', 'resetUri', 'argumentPrefix', 'datePresets' ],
methods: { methods: {
loadOptions () { loadOptions () {
if (this.lock) {
return;
}
this.lock = true;
const query = {}; const query = {};
query[this.argumentPrefix + '[searchParams]'] = this.searchParams; query[this.argumentPrefix + '[searchParams]'] = this.searchParams;
$.post(this.optionsUri, query, (json) => { $.post(this.optionsUri, query, (json) => {
this.applyOptions(json); this.applyOptions(json);
this.lock = false;
}, 'json'); }, 'json');
}, },
applyOptions (json) { applyOptions (json) {
@@ -142,6 +142,7 @@
}, },
resetFilterSettings () { resetFilterSettings () {
this.filterSettings = this.defaultFilterSettings; this.filterSettings = this.defaultFilterSettings;
EventBus.$emit('filterSettingsReset');
this.loadResults(); this.loadResults();
}, },
updateDestination (destination) { updateDestination (destination) {
@@ -12,16 +12,6 @@
text-align: center; text-align: center;
} }
.daterange__column {
flex: 1;
&:first-child {
border-right: 1px solid #c7c7c7;
margin-right: 10px;
}
}
.daterange__presets { .daterange__presets {
display: flex; display: flex;
padding: 8px 0; padding: 8px 0;
@@ -32,16 +22,9 @@
color: $color-font-base; color: $color-font-base;
} }
.daterange__picker { .daterange__buttons {
display: flex; display: flex;
flex-wrap: nowrap; justify-content: space-between;
}
.daterange__input {
text-align: center;
background-color: white;
border: 1px solid $color-grey-light;
color: $color-font-base;
} }
.daterange__button { .daterange__button {
@@ -49,4 +32,20 @@
border: none; border: none;
background: none; background: none;
outline: none; outline: none;
width: percentage(1/2);
}
.flatpickr-input {
display: none;
}
.flatpickr-calendar {
box-shadow: none;
}
.flatpickr-day.selected {
&.startRange, &.endRange {
background: $color-brand-secondary;
border-color: $color-brand-secondary;
}
} }
+1 -1
View File
@@ -11,7 +11,7 @@ Encore
.addEntry('unichamp', './web/typo3conf/ext/ep_theme/Resources/Private/Assets/js/unichamp.js') .addEntry('unichamp', './web/typo3conf/ext/ep_theme/Resources/Private/Assets/js/unichamp.js')
.addStyleEntry('rte', './web/typo3conf/ext/ep_theme/Resources/Private/Assets/css/rte.css') .addStyleEntry('rte', './web/typo3conf/ext/ep_theme/Resources/Private/Assets/css/rte.css')
.createSharedEntry('vendor', [ .createSharedEntry('vendor', [
'jquery', 'vue', 'vue-session', '@fengyuanchen/datepicker', 'jquery-lazy', 'jquery', 'vue', 'vue-session', 'flatpickr', 'jquery-lazy',
'bootstrap-sass/assets/javascripts/bootstrap', 'slick-carousel', 'bootstrap-sass/assets/javascripts/bootstrap', 'slick-carousel',
'dayjs', 'cookieconsent', 'picturefill', '@fancyapps/fancybox', 'leaflet' 'dayjs', 'cookieconsent', 'picturefill', '@fancyapps/fancybox', 'leaflet'
]) ])