Vuejs-Vue meeting selector: vue-meeting-selector - A meeting selector inspired by doctolib, fast and fully custom made with Typescript.

This component is inspired from the meeting selector from doctolib with the power of Vuejs components.

Build status Coverage Status

vue-meeting-selector

Dependencies

  • required: Vuejs >= 2.6.x

Install

npm install vue-meeting-selector --save
yarn add vue-meeting-selector

Include the file in your app

import VueMeetingSelector from 'vue-meeting-selector';

Contributing

Issues and PR's are much appreciated. When you create a new PR please make it against the develop branch when adding new features and to the fix branch when fixing small issues instead of master.

Usage and Documentation

Fast exemple

<template>
  <vue-meeting-selector
    v-model="meeting"
    :date="date"
    :loading="loading"
    :meetings-days="meetingsDays"
    @next-date="nextDate"
    @previous-date="previousDate" />
</template>

<script>
import VueMeetingSelector from 'vueMeetingSelector';

export default {
  components: {
    VueMeetingSelector,
  },
  data() {
    return {
      date: new Date('2020-01-01:01:00'),
      meeting: null,
      loading: false,
      meetingsDays: [],
    };
  },
  methods: {
    getMeetings(date) {
      // methods who return the meetings
    },
    async nextDate() {
      this.loading = true;
      const date = new Date(this.date);
      date.setDate(date.getDate() + 7);
      this.meetingsDays = await this.getMeetings(date);
      this.date = date;
      this.loading = false;
    },
    async previousDate() {
      this.loading = true;
      const date = new Date(this.date);
      date.setDate(date.getDate() - 7);
      this.meetingsDays = await this.getMeetings(date);
      this.date = date;
      this.loading = false;
    },
  },
  async created() {
    this.loading = true;
    this.meetingsDays = await this.getMeetings(this.date);
    this.loading = false;
  },
};
</script>

Types

interface MeetingSlot {
  date: Date | string;
  [key: string]: any;
}
interface MeetingsDay {
  date: Date | string;
  slots: MeetingSlot[];
  [key: string]: any;
}
interface ClassNames {
  tabClass?: string,
  tabPaginationleft?: string,
  tabPaginationPreviousButton?: string,
  tabPaginationRight?: string,
  tabPaginationNextButton?: string,
  tabPaginationUpButton?: string,
  tabPaginationDownButton?: string,
  tabDays?: string,
  tabDayDisplay?: string,
  tabMeetings?: string,
  tabMeeting?: string,
  tabMeetingButton?: string,
  tabMeetingEmpty?: string,
  tabLoading?: string,
}
// defaults value are available in src/defaults/calendarOptions.ts
interface CalendarOptions {
  daysLabel: string[]; // Labels for days in title, start by sunday
  monthsLabel: string[]; // labels for months in title, start by january
  limit: number, // max nb meetings to display on a same column
  loadingLabel: string; // label to display when loading
  disabledDate: Function; // function to disable left button (date is passed as params)
}

Props

Params Type
v-model MeetingSlot
date Date | string
meetingsDays MeetingsDays[]
calendarOptions Object
classNames Object
loading boolean

Events

Name Params
meeting-slot-selected MeetingSlot
meeting-slot-unselected -
change MeetingSlot
next-date -
previous-date -

Slots/ScopedSlots available

To change head of every column, a meetings (MeetingsDay) is passed as slot-scope.

<template
  #header="{ meetings }">
  <div>{{ meetings.date }}</div>
</template>

To change the previous/next button.

<template #button-previous>
  <button
    @click="previous">
    previous
  </button>
</template>
<template #button-next>
  <button
    @click="next">
    next
  </button>
</template>

To change up/down button to change hours of meetings, you will have to trigger methods with refs

<template #button-up="{ isDisabled }">
  <button
    :disabled="isDisabled"
    @click="up">
    up
  </button>
</template>
<template
  #button-down="{ isDisabled }">
  <button
    :disabled="isDisabled"
    @click="down">
    down
  </button>
</template>


<script>
export default {
  methods: {
    up() {
      this.$refs.meetingSelector.previousMeetings();
      // (this.$refs.meetingSelector as Vue & { previousMeetings: () => void }).previousMeetings();
    },
    down() {
      this.$refs.meetingSelector.nextMeetings();
      // (this.$refs.meetingSelector as Vue & { nextMeetings: () => void }).nextMeetings();
    },
  },  
};
</script>

To change the display of a meeting. (you will have to manually change the v-model) if the meeting don't have date, it's because the is no meeting. (you will have to handle a different display)

<template
  #meeting="{ meeting }">
  <div>{{ meeting.date }}</div>
</template>

To change the display of loading

<template
  #loading>
  Loading ...
</template>

Project setup

npm install

Compiles and hot-reloads for development component

npm run dev

Compiles and hot-reloads for development doc

npm run doc

Compiles and minifies for production the lib

npm run build:lib

Compiles and minifies for production the doc

npm run build:doc

Run your unit tests

npm run test:unit

Lints and fixes files

npm run lint

Customize configuration

See Configuration Reference.

Comments

  • build(deps-dev): bump highlight.js from 9.18.3 to 10.4.1
    build(deps-dev): bump highlight.js from 9.18.3 to 10.4.1

    Dec 4, 2020

    Bumps highlight.js from 9.18.3 to 10.4.1.

    Release notes

    Sourced from highlight.js's releases.

    10.4.1

    Security fixes:

    • (fix) Exponential backtracking fixes for: Josh Goebel
      • cpp
      • handlebars
      • gams
      • perl
      • jboss-cli
      • r
      • erlang-repl
      • powershell
      • routeros
    • (fix) Polynomial backtracking fixes for: Josh Goebel
      • asciidoc
      • reasonml
      • latex
      • kotlin
      • gcode
      • d
      • aspectj
      • moonscript
      • coffeescript/livescript
      • csharp
      • scilab
      • crystal
      • elixir
      • basic
      • ebnf
      • ruby
      • fortran/irpf90
      • livecodeserver
      • yaml
      • x86asm
      • dsconfig
      • markdown
      • ruleslanguage
      • xquery
      • sqf

    Very grateful to Michael Schmidt for all the help.

    10.4.0 - November 2020

    A largish release with many improvements and fixes from quite a few different contributors. Enjoy!

    Deprecations:

    ... (truncated)

    Changelog

    Sourced from highlight.js's changelog.

    Version 10.4.1 (tentative)

    Security

    • (fix) Exponential backtracking fixes for: Josh Goebel
      • cpp
      • handlebars
      • gams
      • perl
      • jboss-cli
      • r
      • erlang-repl
      • powershell
      • routeros
    • (fix) Polynomial backtracking fixes for: Josh Goebel
      • asciidoc
      • reasonml
      • latex
      • kotlin
      • gcode
      • d
      • aspectj
      • moonscript
      • coffeescript/livescript
      • csharp
      • scilab
      • crystal
      • elixir
      • basic
      • ebnf
      • ruby
      • fortran/irpf90
      • livecodeserver
      • yaml
      • x86asm
      • dsconfig
      • markdown
      • ruleslanguage
      • xquery
      • sqf

    Very grateful to Michael Schmidt for all the help.

    Version 10.4.0

    A largish release with many improvements and fixes from quite a few different contributors. Enjoy!

    ... (truncated)

    Commits
    Maintainer changes

    This version was pushed to npm by joshgoebel, a new releaser for highlight.js since your current version.


    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies 
    Reply
  • Allow override of empty templates
    Allow override of empty templates

    Oct 18, 2021

    Hello iNeoO,

    i want to remove the button-previous and button-next button from the ui, but with the current approach (slot with if) it does not work.

    For example:

      <vue-meeting-selector :date="currentDate" :meetings-days="meetingsDays">
        <template #button-previous/>
        <template #button-next />
      </vue-meeting-selector>
    

    Current Output:

    <div class="tab__pagination" :class="cssClass.tabPaginationNext">
        <button type="button" class="tab__pagination__button tab__pagination__button--right" :disabled="loading"
            :class="cssClass.tabPaginationNextButton" @click="nextDate">
            <arrow-icon direction="right" />
        </button>
    </div>
    

    Expected Output:

    <div class="tab__pagination" :class="cssClass.tabPaginationNext">
    </div>
    

    Putting the button into the slot tag would solve this problem, but i did not check if something else would get broken. What is the reason to use <slot if.../> <button v-else /> instead of <slot> <button/> </slot>?

    Reply
  • Added namespace for icons that don't conflict with other app icons
    Added namespace for icons that don't conflict with other app icons

    May 16, 2020

    Custom icon class conflicts with other icons on the page. Renamed them to have vms (vue-meeting-selector) prefix to avoid this conflict.

    Reply
  • Are you planning to add select multiple time functionality?
    Are you planning to add select multiple time functionality?

    Oct 10, 2020

    Are you planning to add select multiple time functionality?

    enhancement 
    Reply
  • TypeError: Cannot read property 'length' of undefined
    TypeError: Cannot read property 'length' of undefined

    Jun 19, 2020

    I have followed the full process. But in browser shows TypeError: Cannot read property 'length' of undefined. Please help me.

    bug 
    Reply
  • Uncaught TypeError: Super expression must either be null or a function
    Uncaught TypeError: Super expression must either be null or a function

    Aug 27, 2021

    Hi, I really want to try out VueMeetingSelector's component but I can't manage to make it work. I have this error in the console : Uncaught TypeError: Super expression must either be null or a function

    I just copied the example codes to work from there, but this error is preventing me from doing this.

    I'm using Vue 3.0.0 with TypeScript. Did I do something wrong ?

    Reply
  • Uncaught (in promise) TypeError: Cannot read property '_init' of undefined
    Uncaught (in promise) TypeError: Cannot read property '_init' of undefined

    Sep 8, 2021

    Hello, When adding the example code I am getting error in my vite app

    vue.runtime.esm.js:5168 Uncaught (in promise) TypeError: Cannot read property '_init' of undefined at VueMeetingSelector (vue.runtime.esm.js:5168) at renderComponentRoot (runtime-core.esm-bundler.js:782) at ReactiveEffect.componentUpdateFn [as fn] (runtime-core.esm-bundler.js:4532) at ReactiveEffect.run (reactivity.esm-bundler.js:160) at setupRenderEffect (runtime-core.esm-bundler.js:4657) at mountComponent (runtime-core.esm-bundler.js:4443) at processComponent (runtime-core.esm-bundler.js:4401) at patch (runtime-core.esm-bundler.js:3995) at mountChildren (runtime-core.esm-bundler.js:4191) at mountElement (runtime-core.esm-bundler.js:4100)

    Reply
  • How to change data with getMeetings function
    How to change data with getMeetings function

    Feb 8, 2021

    After read this issue: https://github.com/iNeoO/vue-meeting-selector/issues/8 the codepen link doesn't work and it would maybe help me i guess.

    The component works great but I don't know how to edit the getMeetings(date) function.

    Actually I just receive every availabilities of a collaborator by props. But I don't know how to split the different available dates with that function. (create slots and return them)

    Actually my function has this, but It just return the entire data. In this case, when I click next page, I just have the same datas: getMeetings(date) { console.log(date) return this.available },

    Here my code https://gist.github.com/jervalles/38fd703a2634d3cd8489585e7bce89b2 I've also paster the test Data (availability of a collaborator)

    Reply