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