mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-11-04 07:01:31 +08:00 
			
		
		
		
	calendar widget implementation
This commit is contained in:
		
							parent
							
								
									d3f2b71803
								
							
						
					
					
						commit
						c82de8b6b2
					
				@ -51,6 +51,8 @@ const SORTABLE = {js: ["libraries/sortable.min.js"]};
 | 
			
		||||
 | 
			
		||||
const KNOCKOUT = {js: ["libraries/knockout.min.js"]};
 | 
			
		||||
 | 
			
		||||
const CALENDAR_WIDGET = {css: ["stylesheets/calendar.css"]};
 | 
			
		||||
 | 
			
		||||
async function requireLibrary(library) {
 | 
			
		||||
    if (library.css) {
 | 
			
		||||
        library.css.map(cssUrl => cssLoader.requireCss(cssUrl));
 | 
			
		||||
@ -88,5 +90,6 @@ export default {
 | 
			
		||||
    LINK_MAP,
 | 
			
		||||
    PRINT_THIS,
 | 
			
		||||
    SORTABLE,
 | 
			
		||||
    KNOCKOUT
 | 
			
		||||
    KNOCKOUT,
 | 
			
		||||
    CALENDAR_WIDGET
 | 
			
		||||
}
 | 
			
		||||
@ -60,6 +60,7 @@ class Sidebar {
 | 
			
		||||
            import("../widgets/what_links_here.js"),
 | 
			
		||||
            import("../widgets/similar_notes.js"),
 | 
			
		||||
            import("../widgets/edited_notes.js"),
 | 
			
		||||
            import("../widgets/calendar.js")
 | 
			
		||||
        ])).map(m => m.default);
 | 
			
		||||
 | 
			
		||||
        const options = await optionsService.waitForOptions();
 | 
			
		||||
 | 
			
		||||
@ -1,27 +1,34 @@
 | 
			
		||||
import StandardWidget from "./standard_widget.js";
 | 
			
		||||
import libraryLoader from "../services/library_loader.js";
 | 
			
		||||
import utils from "../services/utils.js";
 | 
			
		||||
import dateNoteService from "../services/date_notes.js";
 | 
			
		||||
import treeService from "../services/tree.js";
 | 
			
		||||
 | 
			
		||||
const TPL = `
 | 
			
		||||
<table class="note-info-table">
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th>Note ID:</th>
 | 
			
		||||
        <td colspan="3" class="note-info-note-id"></td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th>Created:</th>
 | 
			
		||||
        <td colspan="3" class="note-info-date-created"></td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th>Modified:</th>
 | 
			
		||||
        <td colspan="3" class="note-info-date-modified"></td>
 | 
			
		||||
    </tr>
 | 
			
		||||
    <tr>
 | 
			
		||||
        <th>Type:</th>
 | 
			
		||||
        <td class="note-info-type"></td>
 | 
			
		||||
<div class="calendar-widget">
 | 
			
		||||
  <div class="calendar-header">
 | 
			
		||||
    <button class="calendar-btn" data-calendar-toggle="previous">
 | 
			
		||||
      <svg height="24" version="1.1" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
        <path d="M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z"></path>
 | 
			
		||||
      </svg>
 | 
			
		||||
    </button>
 | 
			
		||||
 | 
			
		||||
        <th>MIME:</th>
 | 
			
		||||
        <td class="note-info-mime"></td>
 | 
			
		||||
    </tr>
 | 
			
		||||
</table>
 | 
			
		||||
    <div class="calendar-header__label" data-calendar-label="month">
 | 
			
		||||
      March 2017
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <button class="calendar-btn" data-calendar-toggle="next">
 | 
			
		||||
      <svg height="24" version="1.1" viewbox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
 | 
			
		||||
        <path d="M4,11V13H16L10.5,18.5L11.92,19.92L19.84,12L11.92,4.08L10.5,5.5L16,11H4Z"></path>
 | 
			
		||||
      </svg>
 | 
			
		||||
    </button>
 | 
			
		||||
  </div>
 | 
			
		||||
 | 
			
		||||
  <div class="calendar-week">
 | 
			
		||||
    <span>Mon</span> <span>Tue</span><span>Wed</span> <span>Thu</span> <span>Fri</span> <span>Sat</span> <span>Sun</span>
 | 
			
		||||
  </div>
 | 
			
		||||
  <div class="calendar-body" data-calendar-area="month"></div>
 | 
			
		||||
</div>
 | 
			
		||||
`;
 | 
			
		||||
 | 
			
		||||
class CalendarWidget extends StandardWidget {
 | 
			
		||||
@ -33,21 +40,122 @@ class CalendarWidget extends StandardWidget {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    async doRenderBody() {
 | 
			
		||||
        await libraryLoader.requireLibrary(libraryLoader.CALENDAR_WIDGET);
 | 
			
		||||
 | 
			
		||||
        this.$body.html(TPL);
 | 
			
		||||
 | 
			
		||||
        const $noteId = this.$body.find(".note-info-note-id");
 | 
			
		||||
        const $dateCreated = this.$body.find(".note-info-date-created");
 | 
			
		||||
        const $dateModified = this.$body.find(".note-info-date-modified");
 | 
			
		||||
        const $type = this.$body.find(".note-info-type");
 | 
			
		||||
        const $mime = this.$body.find(".note-info-mime");
 | 
			
		||||
        this.init(this.$body, await this.ctx.note.getLabelValue("dateNote"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
        const note = this.ctx.note;
 | 
			
		||||
    init($el, activeDate) {
 | 
			
		||||
        this.date = new Date();
 | 
			
		||||
        this.todaysDate = new Date();
 | 
			
		||||
        this.activeDate = new Date(Date.parse(activeDate));
 | 
			
		||||
 | 
			
		||||
        $noteId.text(note.noteId);
 | 
			
		||||
        $dateCreated.text(note.dateCreated);
 | 
			
		||||
        $dateModified.text(note.dateModified);
 | 
			
		||||
        $type.text(note.type);
 | 
			
		||||
        $mime.text(note.mime).attr("title", note.mime);
 | 
			
		||||
        this.$month = $el.find('[data-calendar-area="month"]');
 | 
			
		||||
        this.$next = $el.find('[data-calendar-toggle="next"]');
 | 
			
		||||
        this.$previous = $el.find('[data-calendar-toggle="previous"]');
 | 
			
		||||
 | 
			
		||||
        this.$next.click(() => {
 | 
			
		||||
            this.clearCalendar();
 | 
			
		||||
            this.date.setMonth(this.date.getMonth() + 1);
 | 
			
		||||
            this.createMonth();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.$previous.click(() => {
 | 
			
		||||
            this.clearCalendar();
 | 
			
		||||
            this.date.setMonth(this.date.getMonth() - 1);
 | 
			
		||||
            this.createMonth();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        this.$label = $el.find('[data-calendar-label="month"]');
 | 
			
		||||
 | 
			
		||||
        this.date.setDate(1);
 | 
			
		||||
        this.createMonth();
 | 
			
		||||
 | 
			
		||||
        this.$body.on('click', '.calendar-date', async ev => {
 | 
			
		||||
            const date = $(ev.target).closest('.calendar-date').attr('data-calendar-date');
 | 
			
		||||
 | 
			
		||||
            const note = await dateNoteService.getDateNote(date);
 | 
			
		||||
 | 
			
		||||
            if (note) {
 | 
			
		||||
                treeService.activateNote(note.noteId);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                alert("Cannot find day note");
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createDay(num, day) {
 | 
			
		||||
        const $newDay = $('<div>')
 | 
			
		||||
            .addClass("calendar-date")
 | 
			
		||||
            .attr('data-calendar-date', utils.formatDateISO(this.date));
 | 
			
		||||
        const $date = $('<span>').html(num);
 | 
			
		||||
 | 
			
		||||
        // if it's the first day of the month
 | 
			
		||||
        if (num === 1) {
 | 
			
		||||
            if (day === 0) {
 | 
			
		||||
                $newDay.css("marginLeft", (6 * 14.28) + '%');
 | 
			
		||||
            } else {
 | 
			
		||||
                $newDay.css("marginLeft", ((day - 1) * 14.28) + '%');
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.isEqual(this.date, this.activeDate)) {
 | 
			
		||||
            $newDay.addClass('calendar-date-active');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.isEqual(this.date, this.todaysDate)) {
 | 
			
		||||
            $newDay.addClass('calendar-date-today');
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $newDay.append($date);
 | 
			
		||||
        this.$month.append($newDay);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    isEqual(a, b) {
 | 
			
		||||
        return a.getFullYear() === b.getFullYear()
 | 
			
		||||
            && a.getMonth() === b.getMonth()
 | 
			
		||||
            && a.getDate() === b.getDate();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    createMonth() {
 | 
			
		||||
        const currentMonth = this.date.getMonth();
 | 
			
		||||
        while (this.date.getMonth() === currentMonth) {
 | 
			
		||||
            this.createDay(
 | 
			
		||||
                this.date.getDate(),
 | 
			
		||||
                this.date.getDay(),
 | 
			
		||||
                this.date.getFullYear()
 | 
			
		||||
            );
 | 
			
		||||
            this.date.setDate(this.date.getDate() + 1);
 | 
			
		||||
        }
 | 
			
		||||
        // while loop trips over and day is at 30/31, bring it back
 | 
			
		||||
        this.date.setDate(1);
 | 
			
		||||
        this.date.setMonth(this.date.getMonth() - 1);
 | 
			
		||||
 | 
			
		||||
        this.$label.html(this.monthsAsString(this.date.getMonth()) + ' ' + this.date.getFullYear());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    monthsAsString(monthIndex) {
 | 
			
		||||
        return [
 | 
			
		||||
            'January',
 | 
			
		||||
            'Febuary',
 | 
			
		||||
            'March',
 | 
			
		||||
            'April',
 | 
			
		||||
            'May',
 | 
			
		||||
            'June',
 | 
			
		||||
            'July',
 | 
			
		||||
            'August',
 | 
			
		||||
            'September',
 | 
			
		||||
            'October',
 | 
			
		||||
            'November',
 | 
			
		||||
            'December'
 | 
			
		||||
        ][monthIndex];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    clearCalendar() {
 | 
			
		||||
        this.$month.html('');
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										88
									
								
								src/public/stylesheets/calendar.css
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										88
									
								
								src/public/stylesheets/calendar.css
									
									
									
									
									
										Executable file
									
								
							@ -0,0 +1,88 @@
 | 
			
		||||
.calendar-widget *, .calendar-widget *:before, .calendar-widget *:after {
 | 
			
		||||
  box-sizing: border-box;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget {
 | 
			
		||||
  margin: 0 auto;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-btn {
 | 
			
		||||
  -moz-user-select: none;
 | 
			
		||||
  -ms-user-select: none;
 | 
			
		||||
  -webkit-appearance: button;
 | 
			
		||||
  background: none;
 | 
			
		||||
  border: 0;
 | 
			
		||||
  color: inherit;
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
  font: inherit;
 | 
			
		||||
  line-height: normal;
 | 
			
		||||
  min-width: 27px;
 | 
			
		||||
  outline: none;
 | 
			
		||||
  overflow: visible;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-header {
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  padding: 0 0.5rem 0.5rem 0.5rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-header__label {
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  width: 100%;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-week {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-wrap: wrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-week span {
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  flex: 0 0 14.28%;
 | 
			
		||||
  font-size: 1rem;
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
  max-width: 14.28%;
 | 
			
		||||
  padding-top: 5px;
 | 
			
		||||
  padding-bottom: 5px;
 | 
			
		||||
  text-align: center;
 | 
			
		||||
  text-transform: uppercase;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-body {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-wrap: wrap;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-date {
 | 
			
		||||
  align-items: center;
 | 
			
		||||
  background-color: #fff;
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: column;
 | 
			
		||||
  flex: 0 0 14.28%;
 | 
			
		||||
  max-width: 14.28%;
 | 
			
		||||
  padding: 0.6rem 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-date:hover {
 | 
			
		||||
  color: var(--hover-item-text-color);
 | 
			
		||||
  background-color: var(--hover-item-background-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-date-active {
 | 
			
		||||
  background-color: var(--active-item-background-color);
 | 
			
		||||
  color: var(--active-item-text-color);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-date-today {
 | 
			
		||||
  font-weight: bold;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.calendar-widget .calendar-date:not(.calendar-date-active) {
 | 
			
		||||
  cursor: pointer;
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user