Last active
January 10, 2019 16:51
-
-
Save MajesticPotatoe/45b980733a21e0491ec928c0026eb4bb to your computer and use it in GitHub Desktop.
Updated VCalendar Playground
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<v-app class="panes"> | |
<div class="left"> | |
<v-select | |
:items="typeOptions" | |
v-model="type" | |
label="Type" | |
/> | |
<v-checkbox | |
v-model="dark" | |
label="Dark" | |
/> | |
<v-select | |
:items="colorOptions" | |
v-model="color" | |
label="Color" | |
/> | |
<v-menu | |
ref="startMenu" | |
:close-on-content-click="false" | |
:nudge-right="40" | |
:return-value.sync="start" | |
v-model="startMenu" | |
lazy | |
transition="scale-transition" | |
offset-y | |
full-width | |
min-width="290px" | |
> | |
<v-text-field | |
slot="activator" | |
v-model="start" | |
label="Start Date" | |
prepend-icon="event" | |
readonly | |
/> | |
<v-date-picker | |
v-model="start" | |
no-title | |
scrollable | |
> | |
<v-spacer /> | |
<v-btn | |
flat | |
color="primary" | |
@click="startMenu = false" | |
>Cancel</v-btn> | |
<v-btn | |
flat | |
color="primary" | |
@click="$refs.startMenu.save(start)" | |
>OK</v-btn> | |
</v-date-picker> | |
</v-menu> | |
<v-menu | |
v-if="hasEnd" | |
ref="endMenu" | |
v-model="endMenu" | |
:close-on-content-click="false" | |
:nudge-right="40" | |
:return-value.sync="end" | |
lazy | |
transition="scale-transition" | |
offset-y | |
full-width | |
min-width="290px" | |
> | |
<v-text-field | |
slot="activator" | |
v-model="end" | |
label="End Date" | |
prepend-icon="event" | |
readonly | |
/> | |
<v-date-picker | |
v-model="end" | |
no-title | |
scrollable | |
> | |
<v-spacer /> | |
<v-btn | |
flat | |
color="primary" | |
@click="endMenu = false" | |
>Cancel</v-btn> | |
<v-btn | |
flat | |
color="primary" | |
@click="$refs.endMenu.save(end)" | |
>OK</v-btn> | |
</v-date-picker> | |
</v-menu> | |
<v-menu | |
ref="nowMenu" | |
:close-on-content-click="false" | |
:nudge-right="40" | |
:return-value.sync="now" | |
v-model="nowMenu" | |
lazy | |
transition="scale-transition" | |
offset-y | |
full-width | |
min-width="290px" | |
> | |
<v-text-field | |
slot="activator" | |
v-model="now" | |
label="Today" | |
prepend-icon="event" | |
readonly | |
/> | |
<v-date-picker | |
v-model="now" | |
no-title | |
scrollable | |
> | |
<v-spacer /> | |
<v-btn | |
flat | |
color="primary" | |
@click="nowMenu = false" | |
>Cancel</v-btn> | |
<v-btn | |
flat | |
color="primary" | |
@click="$refs.nowMenu.save(now)" | |
>OK</v-btn> | |
</v-date-picker> | |
</v-menu> | |
<v-select | |
:items="weekdaysOptions" | |
v-model="weekdays" | |
label="Weekdays" | |
/> | |
<v-text-field | |
v-if="type === 'custom-weekly'" | |
v-model="minWeeks" | |
label="Minimum Weeks" | |
type="number" | |
/> | |
<v-select | |
v-if="hasIntervals" | |
:items="intervalsOptions" | |
v-model="intervals" | |
label="Intervals" | |
/> | |
<v-select | |
v-if="type === 'custom-daily'" | |
:items="maxDaysOptions" | |
v-model="maxDays" | |
label="# of Days" | |
/> | |
<v-select | |
v-if="hasIntervals" | |
:items="styleIntervalOptions" | |
v-model="styleInterval" | |
label="Styling" | |
/> | |
<v-list | |
two-line | |
subheader | |
dense | |
> | |
<v-subheader inset>Last 5 Events</v-subheader> | |
<v-list-tile | |
v-for="ev in events" | |
:key="ev.id" | |
avatar | |
@click.stop | |
> | |
<v-list-tile-avatar> | |
<v-icon>{{ ev.icon }}</v-icon> | |
</v-list-tile-avatar> | |
<v-list-tile-content> | |
<v-list-tile-title>{{ ev.title }}</v-list-tile-title> | |
<v-list-tile-sub-title>{{ ev.subtitle }}</v-list-tile-sub-title> | |
</v-list-tile-content> | |
</v-list-tile> | |
</v-list> | |
</div> | |
<div class="right"> | |
<v-calendar | |
:type="type" | |
:value="start" | |
:start="start" | |
:end="end" | |
:min-weeks="minWeeks" | |
:max-days="maxDays" | |
:now="now" | |
:dark="dark" | |
:weekdays="weekdays" | |
:first-interval="intervals.first" | |
:interval-minutes="intervals.minutes" | |
:interval-count="intervals.count" | |
:interval-height="intervals.height" | |
:interval-style="intervalStyle" | |
:show-interval-label="showIntervalLabel" | |
:color="color" | |
v-on="listeners"> | |
<template | |
slot="day" | |
slot-scope="day" | |
> | |
<div | |
v-if="day.day % 3 === 0" | |
class="day" | |
@click.stop="addEvent(day, 'click', 'event')" | |
> | |
day slot {{ day.date }} | |
</div> | |
</template> | |
<template | |
slot="dayHeader" | |
slot-scope="day" | |
> | |
<div | |
v-if="day.weekday % 2" | |
class="dayHeader" | |
@click.stop="addEvent(day, 'click', 'event')" | |
> | |
dayHeader slot {{ day.date }} | |
</div> | |
</template> | |
<template | |
slot="dayBody" | |
slot-scope="day" | |
> | |
<div | |
v-if="day.weekday % 3 === 2" | |
class="dayBody" | |
@click.stop="addEvent(day, 'click', 'event')"> | |
dayBody slot {{ day.date }} | |
</div> | |
</template> | |
</v-calendar> | |
</div> | |
</v-app> | |
</template> | |
<script> | |
const weekdaysDefault = [0, 1, 2, 3, 4, 5, 6] | |
const intervalsDefault = { | |
first: 0, | |
minutes: 60, | |
count: 24, | |
height: 40 | |
} | |
const stylings = { | |
default (interval) { | |
return undefined | |
}, | |
workday (interval) { | |
var inactive = interval.weekday === 0 || | |
interval.weekday === 6 || | |
interval.hour < 9 || | |
interval.hour >= 17 | |
var startOfHour = interval.minute === 0 | |
var dark = this.dark | |
// const start = dark ? 'rgba(255,255,255,0.2)' : 'rgba(0,0,0,0.4)' | |
var mid = dark ? 'rgba(255,255,255,0.1)' : 'rgba(0,0,0,0.1)' | |
return { | |
backgroundColor: inactive ? (dark ? 'rgba(0,0,0,0.4)' : 'rgba(0,0,0,0.05)') : undefined, | |
borderTop: startOfHour ? undefined : '1px dashed ' + mid | |
} | |
}, | |
past (interval) { | |
return { | |
backgroundColor: interval.past ? (this.dark ? 'rgba(0,0,0,0.4)' : 'rgba(0,0,0,0.05)') : undefined | |
} | |
} | |
} | |
const eventTypes = ['click', 'contextmenu', 'mousedown', 'mousemove', 'mouseup', 'mouseenter', 'mouseleave', 'touchstart', 'touchmove', 'touchend'] | |
const eventSuffix = ['date', 'day', 'time', 'interval'] | |
export default { | |
data: () => ({ | |
dark: false, | |
startMenu: false, | |
start: '2018-09-12', | |
endMenu: false, | |
end: '2018-09-27', | |
nowMenu: false, | |
minWeeks: 1, | |
now: null, | |
listeners: {}, | |
events: [], | |
type: 'month', | |
typeOptions: [ | |
{ text: 'Day', value: 'day' }, | |
{ text: '4 Day', value: '4day' }, | |
{ text: 'Week', value: 'week' }, | |
{ text: 'Month', value: 'month' }, | |
{ text: 'Custom Daily', value: 'custom-daily' }, | |
{ text: 'Custom Weekly', value: 'custom-weekly' } | |
], | |
/* | |
typeOptions: [ | |
{ text: 'Daily', value: 'daily' }, | |
{ text: 'Weekly', value: 'weekly' }, | |
{ text: 'Monthly', value: 'monthly' } | |
], | |
*/ | |
weekdays: weekdaysDefault, | |
weekdaysOptions: [ | |
{ text: 'Sunday - Saturday', value: weekdaysDefault }, | |
{ text: 'Mon, Wed, Fri', value: [1, 3, 5] }, | |
{ text: 'Mon - Fri', value: [1, 2, 3, 4, 5] } | |
], | |
intervals: intervalsDefault, | |
intervalsOptions: [ | |
{ text: 'Default', value: intervalsDefault }, | |
{ text: 'Workday', value: { first: 16, minutes: 30, count: 20, height: 40 } } | |
], | |
maxDays: 7, | |
maxDaysOptions: [ | |
{ text: '7 days', value: 7 }, | |
{ text: '5 days', value: 5 }, | |
{ text: '4 days', value: 4 }, | |
{ text: '3 days', value: 3 } | |
], | |
styleInterval: 'default', | |
styleIntervalOptions: [ | |
{ text: 'Default', value: 'default' }, | |
{ text: 'Workday', value: 'workday' }, | |
{ text: 'Past', value: 'past' } | |
], | |
color: 'primary', | |
colorOptions: [ | |
{ text: 'Primary', value: 'primary' }, | |
{ text: 'Secondary', value: 'secondary' }, | |
{ text: 'Accent', value: 'accent' }, | |
{ text: 'Red', value: 'red' }, | |
{ text: 'Pink', value: 'pink' }, | |
{ text: 'Purple', value: 'purple' }, | |
{ text: 'Deep Purple', value: 'deep-purple' }, | |
{ text: 'Indigo', value: 'indigo' }, | |
{ text: 'Blue', value: 'blue' }, | |
{ text: 'Light Blue', value: 'light-blue' }, | |
{ text: 'Cyan', value: 'cyan' }, | |
{ text: 'Teal', value: 'teal' }, | |
{ text: 'Green', value: 'green' }, | |
{ text: 'Light Green', value: 'light-green' }, | |
{ text: 'Lime', value: 'lime' }, | |
{ text: 'Yellow', value: 'yellow' }, | |
{ text: 'Amber', value: 'amber' }, | |
{ text: 'Orange', value: 'orange' }, | |
{ text: 'Deep Orange', value: 'deep-orange' }, | |
{ text: 'Brown', value: 'brown' }, | |
{ text: 'Blue Gray', value: 'blue-gray' }, | |
{ text: 'Gray', value: 'gray' }, | |
{ text: 'Black', value: 'black' } | |
] | |
}), | |
computed: { | |
intervalStyle () { | |
return stylings[ this.styleInterval ].bind(this) | |
}, | |
hasIntervals () { | |
return this.type in { | |
'week': 1, 'day': 1, '4day': 1, 'custom-daily': 1 | |
} | |
}, | |
hasEnd () { | |
return this.type in { | |
'custom-weekly': 1, 'custom-daily': 1 | |
} | |
} | |
}, | |
created () { | |
eventTypes.forEach(e => { | |
eventSuffix.forEach(s => { | |
this.listeners[`${e}:${s}`] = day => { | |
this.addEvent(day, e, s) | |
} | |
}) | |
}) | |
}, | |
methods: { | |
addEvent (day, e, s) { | |
const lastEvent = this.events[0] | |
const eventInstance = { | |
id: Math.random(), | |
icon: s === 'day' ? 'calendar_today' : (s === 'time' ? 'access_time' : (s === 'interval' ? 'view_agenda' : 'event')), | |
title: e + ':' + s, | |
subtitle: s === 'interval' ? day.time : (day.date + (s === 'time' ? ' ' + day.time : '')) | |
} | |
if (!lastEvent || lastEvent.title !== eventInstance.title) { | |
if (this.events.length >= 5) { | |
this.events.pop() | |
} | |
} else { | |
this.events.shift() | |
} | |
this.events.unshift(eventInstance) | |
}, | |
showIntervalLabel (interval) { | |
return interval.minute === 0 | |
} | |
} | |
} | |
</script> | |
<style> | |
.panes { | |
position: fixed; | |
top: 0; | |
bottom: 0; | |
right: 0; | |
left: 0; | |
} | |
.left { | |
position: fixed; | |
left: 0; | |
width: 300px; | |
top: 0; | |
bottom: 0; | |
border-right: #bdbdbd 1px solid; | |
padding: 8px; | |
} | |
.right { | |
position: fixed; | |
left: 300px; | |
top: 0; | |
bottom: 0; | |
right: 0; | |
} | |
.dayHeader { | |
margin: 0px 2px 2px 2px; | |
padding: 2px 6px; | |
background-color: #1976D2; | |
color: white; | |
user-select: none; | |
white-space: nowrap; | |
text-overflow: ellipsis; | |
overflow: hidden; | |
} | |
.dayBody { | |
position: absolute; | |
top: 400px; | |
height: 36px; | |
margin: 2px; | |
padding: 2px 6px; | |
background-color: #1976D2; | |
color: white; | |
left: 0; | |
right: 0; | |
user-select: none; | |
white-space: nowrap; | |
text-overflow: ellipsis; | |
overflow: hidden; | |
} | |
.day { | |
position: relative; | |
height: 24px; | |
margin: 0px; | |
padding: 0px 6px; | |
background-color: #1976D2; | |
color: white; | |
left: 0; | |
right: 0; | |
user-select: none; | |
white-space: nowrap; | |
text-overflow: ellipsis; | |
overflow: hidden; | |
} | |
body, html, #app { | |
font-family: Roboto, sans-serif !important; | |
width: 100%; | |
height: 100%; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment