Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature Request] Add more scheduling features to calendar #11080

Closed
nquinn721 opened this issue Apr 10, 2020 · 2 comments · Fixed by #11198
Closed

[Feature Request] Add more scheduling features to calendar #11080

nquinn721 opened this issue Apr 10, 2020 · 2 comments · Fixed by #11198
Assignees
Labels
C: VCalendar VCalendar T: feature A new feature
Milestone

Comments

@nquinn721
Copy link
Contributor

Problem to solve

I would love it if we could add more scheduling features in the calendar. Honestly just two features would suffice.

  1. Add resource view with daily appointments, something vertical like
    Resource1 Resource2
    10am
    11am
    12pm

  2. Then the ability to click into a cell and get the context of the resource as well as the date/time

Proposed solution

This solution isn't too far off from the week view, but instead of incrementing days, you would loop over resources and show the same day for each one. Then you would just add a click on cells and pass context. Honestly this shouldn't be a huge addon. The reason I'm asking for this is cause I've tried so many other schedulers, there's nothing really good out there for vue. There is syncfusion and bryntum but these are plain javascript libraries that wrap themselves in in popular frameworks like vue and angular, however these cause tons of issues when trying to customize them since they are not component based at core.

@ghost ghost added the S: triage label Apr 10, 2020
@Leespiker Leespiker added C: VCalendar VCalendar T: feature A new feature and removed S: triage labels Apr 12, 2020
@ClickerMonkey
Copy link
Contributor

ClickerMonkey commented Apr 23, 2020

Playground.vue for this feature:

<template>
  <v-container>
    <div>
      
      <v-checkbox v-model="categoryShowAll" label="Always show Phil, John (uses category-show-all)" hide-details></v-checkbox>
      <v-checkbox v-model="categoryHideDynamic" label="Hide other categories (uses category-hide-dynamic)" hide-details></v-checkbox>
      <v-checkbox v-model="google" label="Render like google (uses category slot)" hide-details></v-checkbox>
      <v-checkbox v-model="categoryDays" label="Test 2 days (uses category-days)" :true-value="2" :false-value="1"></v-checkbox>

      <v-sheet
        tile
        height="54"
        color="grey lighten-3"
        class="d-flex"
      >
        <v-btn
          icon
          class="ma-2"
          @click="$refs.calendar.prev()"
        >
          <v-icon>mdi-chevron-left</v-icon>
        </v-btn>
        <h4 v-if="$refs.calendar" class="pa-4">
          {{ $refs.calendar.title }}
        </h4>
        <v-spacer></v-spacer>
        <v-btn
          icon
          class="ma-2"
          @click="$refs.calendar.next()"
        >
          <v-icon>mdi-chevron-right</v-icon>
        </v-btn>
      </v-sheet>
      <v-sheet height="600">
        <v-calendar
          :class="{ google }"
          ref="calendar"
          v-model="value"
          type="category"
          category-for-invalid="(undefined)"
          :categories="categoriesAlways"
          :category-days="categoryDays"
          :category-show-all="categoryShowAll"
          :category-hide-dynamic="categoryHideDynamic"
          :events="events"
          :event-color="getEventColor"
          @change="getEvents"
          @mousedown:time-category="startDrag"
          @mouseup:time="endDrag"
          @mouseleave.native="cancelDrag"
        >
          <template v-if="google" #category="{ category }">
            <div class="google-category">
              <div class="google-category-name">{{ category }}</div>
              <v-btn v-if="categoryVisuals[category]"
                class="google-category-avatar" 
                fab
                small
                :color="categoryVisuals[category].color">
                {{ categoryVisuals[category].avatar }}
              </v-btn>
            </div>
          </template>
        </v-calendar>
      </v-sheet>
    </div>
  </v-container>
</template>

<script>
  export default {
    data: () => ({
      mode: 'stack',
      value: '',
      events: [],
      colors: ['blue', 'indigo', 'deep-purple', 'cyan', 'green', 'orange', 'grey darken-1'],
      names: ['Meeting', 'Holiday', 'PTO', 'Travel', 'Event', 'Birthday', 'Conference', 'Party'],
      categories: ['Philip Diffenderfer', 'John Leider', 'Thomas Smith'],
      categoriesAlways: ['Philip Diffenderfer', 'John Leider'],
      categoryVisuals: {
        'Philip Diffenderfer': { avatar: 'P', color: 'primary' },
        'John Leider': { avatar: 'J', color: 'secondary' },
      },
      categoryShowAll: false,
      categoryHideDynamic: false,
      categoryDays: 1,
      google: false,
      start: null,
    }),
    mounted () {
      window.app = this
    },
    methods: {
      getEvents ({ start, end }) {
        const events = []

        const min = new Date(`${start.date}T00:00:00`)
        const max = new Date(`${end.date}T23:59:59`)
        const days = (max.getTime() - min.getTime()) / 86400000
        const eventCount = this.rnd(days, days + 20)

        for (let i = 0; i < eventCount; i++) {
          const allDay = this.rnd(0, 3) === 0
          const firstTimestamp = this.rnd(min.getTime(), max.getTime())
          const first = new Date(firstTimestamp - (firstTimestamp % 900000))
          const secondTimestamp = this.rnd(2, allDay ? 288 : 8) * 900000
          const second = new Date(first.getTime() + secondTimestamp)
          const type = this.rnd(0, this.names.length - 1)

          events.push({
            name: this.names[type],
            start: first,
            end: second,
            color: this.colors[this.rnd(0, this.colors.length - 1)],
            category: this.categories[this.rnd(0, this.categories.length - 1)],
            timed: !allDay,
          })
        }

        this.events = events
      },
      getEventColor (event) {
        return event.color
      },
      rnd (a, b) {
        return Math.floor((b - a + 1) * Math.random()) + a
      },
      startDrag (ev) {
        this.start = ev
      },
      endDrag (ev) {
        if (this.start) {
          this.events.push({
            name: `Event #${this.events.length}`,
            start: `${this.start.date} ${this.start.time}`,
            end: `${ev.date} ${ev.time}`,
            timed: true,
            color: this.colors[this.rnd(0, this.colors.length - 1)],
            category: this.start.category,
          })
          this.start = null
        }
      },
      cancelDrag () {
        this.start = null
      },
    },
  }
</script>

<style scoped lang="scss">
.google {
   ::v-deep .v-calendar-daily_head-weekday {
    display: inline-block;
    position: absolute;
    width: 56px;
  }

  ::v-deep .v-calendar-daily_head-day-label {
    display: inline-block;
    position: absolute;
    top: 20px;
    z-index: 1;
  }

  ::v-deep .google-category {
    height: 80px;
    position: relative;
    
    .google-category-name {
      text-align: right;
      padding: 8px;
      font-size: 11px;
    }

    .google-category-avatar {
      background-color: rgba(0,0,0,0.3);
      width: 40px;
      height: 40px;
      position: absolute;
      border-radius: 20px;
      right: 8px;
      top: 30px;
    }
  }
}
</style>

CategoryPreview

@johnleider johnleider linked a pull request Apr 24, 2020 that will close this issue
8 tasks
johnleider added a commit that referenced this issue May 20, 2020
resolves #8667
resolves #11080
resolves #11093
resolves #11133
resolves #11182

* feat(VCalendar): allow seconds and Date in props and events

* feat(VCalendar): improve event slot

* feat(VCalendar): added title computed value

* feat(VCalendar): add first-time prop

* feat(VCalendar): add category type, props, and slot

* docs: more calendar examples, fix warnings

* Update packages/vuetify/src/components/VCalendar/VCalendar.ts

Co-authored-by: John Leider <john@vuetifyjs.com>

* Update packages/vuetify/src/components/VCalendar/VCalendar.ts

Co-authored-by: John Leider <john@vuetifyjs.com>

* chore(VCalendar): code style changes

Co-authored-by: John Leider <john@vuetifyjs.com>
@johnleider johnleider added this to the v2.3.0 milestone May 20, 2020
@johnleider
Copy link
Member

resolved in #11198

If you have any additional questions, please reach out to us in our Discord community.

johnleider added a commit that referenced this issue Jun 2, 2020
resolves #8667
resolves #11080
resolves #11093
resolves #11133
resolves #11182

* feat(VCalendar): allow seconds and Date in props and events

* feat(VCalendar): improve event slot

* feat(VCalendar): added title computed value

* feat(VCalendar): add first-time prop

* feat(VCalendar): add category type, props, and slot

* docs: more calendar examples, fix warnings

* Update packages/vuetify/src/components/VCalendar/VCalendar.ts

Co-authored-by: John Leider <john@vuetifyjs.com>

* Update packages/vuetify/src/components/VCalendar/VCalendar.ts

Co-authored-by: John Leider <john@vuetifyjs.com>

* chore(VCalendar): code style changes

Co-authored-by: John Leider <john@vuetifyjs.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C: VCalendar VCalendar T: feature A new feature
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants