Skip to content
This repository was archived by the owner on Apr 27, 2021. It is now read-only.
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions src/components/shared/forms/Time.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<template>
<semantic-form-dropdown v-model="time" :options="timeOptions" @dropdown-selected="selected"></semantic-form-dropdown>
</template>

<script>
/**
* Time picker component
*
* @example ./croud-time.md
*/
export default {
name: 'croud-time',

props: {
/**
* v-model alias
*/
value: {
type: String,
required: true,
},
},

computed: {
time() {
return this.value
},

timeOptions() {
let value
const arr = []
for (let i = 0; i < 24; i += 1) {
for (let t = 0; t < 60; t += 15) {
value = `${this.pad(i)}:${this.pad(t)}`
arr.push({
id: value,
name: value,
})
}
}
arr.push({
id: '23:59',
name: '23:59',
})
return arr
},
},

methods: {
pad: value => (value < 10 ? `0${value}` : value),

selected(val) {
this.$emit('input', val)
},
},
}
</script>
3 changes: 3 additions & 0 deletions src/components/shared/forms/croud-time.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
### Basic usage

<croud-time v-model="time"/>
171 changes: 171 additions & 0 deletions src/components/shared/schedule/Editor.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<template>
<div class="ui segment basic">

<div class="ui two column grid">
<div class="ui column">
<strong>Date Range</strong>
</div>
<div class="ui column">
<croud-date-range :start.sync="baseSchedule.range.start" :end.sync="baseSchedule.range.end"></croud-date-range>
</div>
<div class="ui column">
<strong>Time</strong>
</div>
<div class="ui column">
<croud-time v-model="baseSchedule.time_of_day" />
</div>
<div class="ui column">
<strong>Occurs</strong>
</div>
<div class="ui column">
<semantic-form-dropdown v-model="baseSchedule.occurance" :options="occuranceOptions"></semantic-form-dropdown>
</div>
</div>

<component :is="baseSchedule.occurance" :schedule.sync="baseSchedule" @reset-schedule="scheduleReset"></component>

<div class="ui basic right aligned segment">
<slot name="actions">
<button class="ui mini button" @click="cancelSchedule">
Cancel
</button>
<button class="ui mini yellow button" @click="updateSchedule">
Set Schedule
</button>
</slot>
</div>
</div>
</template>

<script>
import { omit, pick } from 'lodash'
import moment from 'moment'

import Daily from './views/Daily'
import Weekly from './views/Weekly'
import SameDayEachMonth from './views/SameDayEachMonth'
import SameDayEachYear from './views/SameDayEachYear'
import SameWeekEachMonth from './views/SameWeekEachMonth'
import SameWeekEachYear from './views/SameWeekEachYear'

/**
* New schedule editor
*
* @example ./croud-schedule-editor.md
*/
export default {
name: 'croud-schedule-editor',

components: {
Daily,
Weekly,
SameDayEachMonth,
SameDayEachYear,
SameWeekEachMonth,
SameWeekEachYear,
},

props: {
/**
* Pre-populate the schedule object
*/
schedule: {
type: Object,
default() {
return {}
},
},

/**
* Timezone value
*/
timezone: {
type: String,
default: 'Europe/London',
},
},

data() {
return {
resetOmits: ['timezone', 'range', 'time_of_day', 'periodic'],
occurances: {
Daily: 'Daily',
Weekly: 'Weekly',
SameDayEachMonth: 'Same day each month',
SameWeekEachMonth: 'Same week each month',
SameDayEachYear: 'Same day each year',
SameWeekEachYear: 'Same week each year',
},

baseSchedule: {
timezone: this.timezone,
occurance: 'Daily',
type: 'periodic',
range: {
start: moment().format('YYYY-MM-DD'),
end: moment().add(3, 'months').endOf('month').format('YYYY-MM-DD'),
},
time_of_day: '09:00',
interval: 1,
period: 'days',
day_of_month: false,
week_of_month: false,
days: {},
months: {},
},
}
},

computed: {
occuranceOptions() {
return Object.keys(this.occurances).map(id => ({ id, name: this.occurances[id] }))
},
},

methods: {
scheduleUpdate(schedule) {
this.baseSchedule = schedule
},

scheduleReset(resets) {
this.baseSchedule = {
...pick(this.baseSchedule, this.resetOmits),
...omit(this.baseSchedule, this.resetOmits),
...resets,
}
},

/**
* Cancel changes to the schedule
*
* @public
* @returns void
*/
cancelSchedule() {
this.$emit('cancelled', this.baseSchedule)
this.baseSchedule = {
...this.baseSchedule,
...this.schedule,
}
},

/**
* Emit update:schedule event
*
* @public
* @returns void
*/
updateSchedule() {
this.baseSchedule.timezone = this.timezone
this.$emit('update:schedule', this.baseSchedule)
},
},

created() {
this.baseSchedule = {
...this.baseSchedule,
...this.schedule,
}
},
}
</script>
122 changes: 122 additions & 0 deletions src/components/shared/schedule/MonthView.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<template>
<div class="ui center aligned column">
{{ title }}
<table class="ui tiny very basic fixed table">
<thead>
<th v-for="day in dayOptions" class="center aligned" :key="day">{{ day }}</th>
</thead>

<tbody>
<tr v-for="week in weeks" :key="week">
<td class="center aligned" v-for="(day, i) in week.days" :key="i">
<span class="ui tiny yellow circular" :class="{label: day.highlight}">{{ day.day }}</span>
</td>
</tr>
</tbody>
</table>
</div>
</template>

<script>
import moment from 'moment'

/**
* Quick summary view of events in a month
*
* @example ./month-view.md
*/
export default {
name: 'month-view',

props: {

/**
* ISO string or Moment object of a date in the month
*/
month: {
type: [String, Object],
default: moment(),
},

/**
* Array of dates to highlight
*/
highlight: {
type: Array,
default: () => [],
},
},

computed: {
title() {
return moment(this.month).format('MMMM')
},

daysInMonth() {
return moment(this.month).daysInMonth()
},

firstWeekday() {
return moment(this.month).startOf('month').weekday()
},

dayOptions() {
return moment.weekdaysMin()
},

weeks() {
const month = moment(this.month).month()
const startWeek = moment(this.month).startOf('month').week()
let endWeek = moment(this.month).endOf('month').week()

if (endWeek === 1) endWeek = startWeek + 5

const calendar = []
for (let week = startWeek; week <= endWeek; week += 1) {
calendar.push({
week,
days: Array(7).fill(0).map((n, i) => {
const day = moment().week(week).startOf('week').add(n + i, 'day')
if (month !== day.month()) return {}
return {
day: day.format('D'),
highlight: this.highlightDates.indexOf(day.format('D')) !== -1,
}
}),
})
}

return calendar
},

highlightDates() {
const month = moment(this.month).month()
return this.highlight.filter(d => d.month() === month).map(d => d.format('D'))
},
},
}
</script>

<style lang="scss" scoped>
@import '../../../resources/sass/variables/_all.scss';

.ui.table tr td {
border-top: none;
font-size: $croud-font-size-tiny;
padding: 1px;
height: auto;
}

.ui.table th {
font-size: $croud-font-size-small;
height: auto;
}

.ui.table.basic td.highlight {
border-radius: 50%;
}

.ui.grid>.column:not(.row) {
padding-bottom: 0;
}
</style>
Loading