You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

411 lines
11KB

  1. <template>
  2. <div id="app">
  3. <div class="calendar-controls">
  4. <div v-if="message" class="notification is-success">{{ message }}</div>
  5. <div class="box">
  6. <h4 class="title is-5">Play with the options!</h4>
  7. <div class="field">
  8. <label class="label">Period UOM</label>
  9. <div class="control">
  10. <div class="select">
  11. <select v-model="displayPeriodUom">
  12. <option>month</option>
  13. <option>week</option>
  14. <option>year</option>
  15. </select>
  16. </div>
  17. </div>
  18. </div>
  19. <div class="field">
  20. <label class="label">Period Count</label>
  21. <div class="control">
  22. <div class="select">
  23. <select v-model="displayPeriodCount">
  24. <option :value="1">1</option>
  25. <option :value="2">2</option>
  26. <option :value="3">3</option>
  27. </select>
  28. </div>
  29. </div>
  30. </div>
  31. <div class="field">
  32. <label class="label">Starting day of the week</label>
  33. <div class="control">
  34. <div class="select">
  35. <select v-model="startingDayOfWeek">
  36. <option v-for="(d, index) in dayNames" :key="index" :value="index">
  37. {{ d }}
  38. </option>
  39. </select>
  40. </div>
  41. </div>
  42. </div>
  43. <div class="field">
  44. <label class="checkbox">
  45. <input v-model="useTodayIcons" type="checkbox" />
  46. Use icon for today's period
  47. </label>
  48. </div>
  49. <div class="field">
  50. <label class="checkbox">
  51. <input v-model="displayWeekNumbers" type="checkbox" />
  52. Show week number
  53. </label>
  54. </div>
  55. <div class="field">
  56. <label class="checkbox">
  57. <input v-model="showTimes" type="checkbox" />
  58. Show times
  59. </label>
  60. </div>
  61. <div class="field">
  62. <label class="label">Themes</label>
  63. <label class="checkbox">
  64. <input v-model="useDefaultTheme" type="checkbox" />
  65. Default
  66. </label>
  67. </div>
  68. <div class="field">
  69. <label class="checkbox">
  70. <input v-model="useHolidayTheme" type="checkbox" />
  71. Holidays
  72. </label>
  73. </div>
  74. </div>
  75. <div class="box">
  76. <div class="field">
  77. <label class="label">Title</label>
  78. <div class="control">
  79. <input v-model="newItemTitle" class="input" type="text" />
  80. </div>
  81. </div>
  82. <div class="field">
  83. <label class="label">Start date</label>
  84. <div class="control">
  85. <input v-model="newItemStartDate" class="input" type="date" />
  86. </div>
  87. </div>
  88. <div class="field">
  89. <label class="label">End date</label>
  90. <div class="control">
  91. <input v-model="newItemEndDate" class="input" type="date" />
  92. </div>
  93. </div>
  94. <button class="button is-info" @click="clickTestAddItem">Add Item</button>
  95. </div>
  96. </div>
  97. <div class="calendar-parent">
  98. <calendar-view
  99. :items="items"
  100. :show-date="showDate"
  101. :time-format-options="{ hour: 'numeric', minute: '2-digit' }"
  102. :enable-drag-drop="true"
  103. :disable-past="disablePast"
  104. :disable-future="disableFuture"
  105. :show-times="showTimes"
  106. :date-classes="myDateClasses"
  107. :display-period-uom="displayPeriodUom"
  108. :display-period-count="displayPeriodCount"
  109. :starting-day-of-week="startingDayOfWeek"
  110. :class="themeClasses"
  111. :period-changed-callback="periodChanged"
  112. :current-period-label="useTodayIcons ? 'icons' : ''"
  113. :displayWeekNumbers="displayWeekNumbers"
  114. :enable-date-selection="true"
  115. :selection-start="selectionStart"
  116. :selection-end="selectionEnd"
  117. @date-selection-start="setSelection"
  118. @date-selection="setSelection"
  119. @date-selection-finish="finishSelection"
  120. @drop-on-date="onDrop"
  121. @click-date="onClickDay"
  122. @click-item="onClickItem"
  123. >
  124. <template #header="{ headerProps }">
  125. <calendar-view-header slot="header" :header-props="headerProps" @input="setShowDate" />
  126. </template>
  127. </calendar-view>
  128. </div>
  129. </div>
  130. </template>
  131. <script>
  132. import { CalendarView, CalendarViewHeader, CalendarMath } from "vue-simple-calendar";
  133. import 'vue-simple-calendar/dist/style.css'
  134. // The next two lines are optional themes
  135. import "vue-simple-calendar/static/css/default.css"
  136. import "vue-simple-calendar/static/css/holidays-us.css"
  137. export default {
  138. name: "App",
  139. components: {
  140. CalendarView,
  141. CalendarViewHeader,
  142. },
  143. data() {
  144. return {
  145. /* Show the current month, and give it some fake items to show */
  146. showDate: this.thisMonth(1),
  147. message: "",
  148. startingDayOfWeek: 0,
  149. disablePast: false,
  150. disableFuture: false,
  151. displayPeriodUom: "month",
  152. displayPeriodCount: 1,
  153. displayWeekNumbers: false,
  154. showTimes: true,
  155. selectionStart: null,
  156. selectionEnd: null,
  157. newItemTitle: "",
  158. newItemStartDate: "",
  159. newItemEndDate: "",
  160. useDefaultTheme: true,
  161. useHolidayTheme: true,
  162. useTodayIcons: false,
  163. items: [
  164. {
  165. id: "e0",
  166. startDate: "2018-01-05",
  167. },
  168. {
  169. id: "e1",
  170. startDate: this.thisMonth(15, 18, 30),
  171. },
  172. {
  173. id: "e2",
  174. startDate: this.thisMonth(15),
  175. title: "Single-day item with a long title",
  176. },
  177. {
  178. id: "e3",
  179. startDate: this.thisMonth(7, 9, 25),
  180. endDate: this.thisMonth(10, 16, 30),
  181. title: "Multi-day item with a long title and times",
  182. },
  183. {
  184. id: "e4",
  185. startDate: this.thisMonth(20),
  186. title: "My Birthday!",
  187. classes: "birthday",
  188. url: "https://en.wikipedia.org/wiki/Birthday",
  189. },
  190. {
  191. id: "e5",
  192. startDate: this.thisMonth(5),
  193. endDate: this.thisMonth(12),
  194. title: "Multi-day item",
  195. classes: "purple",
  196. },
  197. {
  198. id: "foo",
  199. startDate: this.thisMonth(29),
  200. title: "Same day 1",
  201. },
  202. {
  203. id: "e6",
  204. startDate: this.thisMonth(29),
  205. title: "Same day 2",
  206. classes: "orange",
  207. },
  208. {
  209. id: "e7",
  210. startDate: this.thisMonth(29),
  211. title: "Same day 3",
  212. },
  213. {
  214. id: "e8",
  215. startDate: this.thisMonth(29),
  216. title: "Same day 4",
  217. classes: "orange",
  218. },
  219. {
  220. id: "e9",
  221. startDate: this.thisMonth(29),
  222. title: "Same day 5",
  223. },
  224. {
  225. id: "e10",
  226. startDate: this.thisMonth(29),
  227. title: "Same day 6",
  228. classes: "orange",
  229. },
  230. {
  231. id: "e11",
  232. startDate: this.thisMonth(29),
  233. title: "Same day 7",
  234. },
  235. ],
  236. }
  237. },
  238. computed: {
  239. userLocale() {
  240. return CalendarMath.getDefaultBrowserLocale
  241. },
  242. dayNames() {
  243. return CalendarMath.getFormattedWeekdayNames(this.userLocale, "long", 0)
  244. },
  245. themeClasses() {
  246. return {
  247. "theme-default": this.useDefaultTheme,
  248. "holiday-us-traditional": this.useHolidayTheme,
  249. "holiday-us-official": this.useHolidayTheme,
  250. }
  251. },
  252. myDateClasses() {
  253. // This was added to demonstrate the dateClasses prop. Note in particular that the
  254. // keys of the object are `yyyy-mm-dd` ISO date strings (not dates), and the values
  255. // for those keys are strings or string arrays. Keep in mind that your CSS to style these
  256. // may need to be fairly specific to make it override your theme's styles. See the
  257. // CSS at the bottom of this component to see how these are styled.
  258. const o = {}
  259. const theFirst = this.thisMonth(1)
  260. const ides = [2, 4, 6, 9].includes(theFirst.getMonth()) ? 15 : 13
  261. const idesDate = this.thisMonth(ides)
  262. o[CalendarMath.isoYearMonthDay(idesDate)] = "ides"
  263. o[CalendarMath.isoYearMonthDay(this.thisMonth(21))] = ["do-you-remember", "the-21st"]
  264. return o
  265. },
  266. },
  267. mounted() {
  268. this.newItemStartDate = CalendarMath.isoYearMonthDay(CalendarMath.today())
  269. this.newItemEndDate = CalendarMath.isoYearMonthDay(CalendarMath.today())
  270. },
  271. methods: {
  272. periodChanged() {
  273. // range, eventSource) {
  274. // Demo does nothing with this information, just including the method to demonstrate how
  275. // you can listen for changes to the displayed range and react to them (by loading items, etc.)
  276. //console.log(eventSource)
  277. //console.log(range)
  278. },
  279. thisMonth(d, h, m) {
  280. const t = new Date()
  281. return new Date(t.getFullYear(), t.getMonth(), d, h || 0, m || 0)
  282. },
  283. onClickDay(d) {
  284. this.selectionStart = null
  285. this.selectionEnd = null
  286. this.message = `You clicked: ${d.toLocaleDateString()}`
  287. },
  288. onClickItem(e) {
  289. this.message = `You clicked: ${e.title}`
  290. },
  291. setShowDate(d) {
  292. this.message = `Changing calendar view to ${d.toLocaleDateString()}`
  293. this.showDate = d
  294. },
  295. setSelection(dateRange) {
  296. this.selectionEnd = dateRange[1]
  297. this.selectionStart = dateRange[0]
  298. },
  299. finishSelection(dateRange) {
  300. this.setSelection(dateRange)
  301. this.message = `You selected: ${this.selectionStart.toLocaleDateString()} -${this.selectionEnd.toLocaleDateString()}`
  302. },
  303. onDrop(item, date) {
  304. this.message = `You dropped ${item.id} on ${date.toLocaleDateString()}`
  305. // Determine the delta between the old start date and the date chosen,
  306. // and apply that delta to both the start and end date to move the item.
  307. const eLength = CalendarMath.dayDiff(item.startDate, date)
  308. item.originalItem.startDate = CalendarMath.addDays(item.startDate, eLength)
  309. item.originalItem.endDate = CalendarMath.addDays(item.endDate, eLength)
  310. },
  311. clickTestAddItem() {
  312. this.items.push({
  313. startDate: this.newItemStartDate,
  314. endDate: this.newItemEndDate,
  315. title: this.newItemTitle,
  316. id: "e" + Math.random().toString(36).substr(2, 10),
  317. })
  318. this.message = "You added a calendar item!"
  319. },
  320. },
  321. }
  322. </script>
  323. <style>
  324. html,
  325. body {
  326. height: 100%;
  327. margin: 0;
  328. background-color: #f7fcff;
  329. }
  330. #app {
  331. display: flex;
  332. flex-direction: row;
  333. font-family: Calibri, sans-serif;
  334. width: 95vw;
  335. min-width: 30rem;
  336. max-width: 100rem;
  337. min-height: 40rem;
  338. margin-left: auto;
  339. margin-right: auto;
  340. }
  341. .calendar-controls {
  342. margin-right: 1rem;
  343. min-width: 14rem;
  344. max-width: 14rem;
  345. }
  346. .calendar-parent {
  347. display: flex;
  348. flex-direction: column;
  349. flex-grow: 1;
  350. overflow-x: hidden;
  351. overflow-y: hidden;
  352. max-height: 80vh;
  353. background-color: white;
  354. }
  355. /* For long calendars, ensure each week gets sufficient height. The body of the calendar will scroll if needed */
  356. .cv-wrapper.period-month.periodCount-2 .cv-week,
  357. .cv-wrapper.period-month.periodCount-3 .cv-week,
  358. .cv-wrapper.period-year .cv-week {
  359. min-height: 6rem;
  360. }
  361. /* These styles are optional, to illustrate the flexbility of styling the calendar purely with CSS. */
  362. /* Add some styling for items tagged with the "birthday" class */
  363. .theme-default .cv-item.birthday {
  364. background-color: #e0f0e0;
  365. border-color: #d7e7d7;
  366. }
  367. .theme-default .cv-item.birthday::before {
  368. content: "\1F382"; /* Birthday cake */
  369. margin-right: 0.5em;
  370. }
  371. /* The following classes style the classes computed in myDateClasses and passed to the component's dateClasses prop. */
  372. .theme-default .cv-day.ides {
  373. background-color: #ffe0e0;
  374. }
  375. .ides .cv-day-number::before {
  376. content: "\271D";
  377. }
  378. .cv-day.do-you-remember.the-21st .cv-day-number::after {
  379. content: "\1F30D\1F32C\1F525";
  380. }
  381. </style>