Skip to content

Commit

Permalink
feat: add basic filtering and exporting
Browse files Browse the repository at this point in the history
  • Loading branch information
Tiim committed May 12, 2022
1 parent ad3aeae commit 0b0eb65
Show file tree
Hide file tree
Showing 12 changed files with 341 additions and 33 deletions.
34 changes: 32 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,8 @@
"ts-jest": "^28.0.2",
"tslib": "2.4.0",
"typescript": "4.6.4"
},
"dependencies": {
"svelte-flatpickr": "^3.2.6"
}
}
4 changes: 2 additions & 2 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const DEFAULT_SETTINGS: AttendancePluginSettings = {
export default class AttendancePlugin extends Plugin {
settings: AttendancePluginSettings;
events: Events = new Events();
private queryResolver: QueryResolver;
queryResolver: QueryResolver;


async onload() {
Expand All @@ -43,7 +43,7 @@ export default class AttendancePlugin extends Plugin {

this.addSettingTab(new AttendanceSettingsTab(this.app, this));
this.registerView(VIEW_TYPE_ATTENDANCE,
(leaf) => new AttendanceOverviewView(leaf, this.queryResolver, this.events));
(leaf) => new AttendanceOverviewView(leaf, this));


this.addCommand({
Expand Down
54 changes: 47 additions & 7 deletions src/ui/view/AttendanceOverview.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,62 @@
import Footer from "./Footer.svelte";
import ListView from "./ListView.svelte";
import Searchbar from "./Searchbar.svelte";
import { filterCodeblocks, type Search } from "src/util/filter-codeblocks";
import type { QueryResolver } from "src/resolver/query-resolver";
import { filterCodeblocks, type Search } from "../../util/filter-codeblocks";
import type { QueryResolver } from "../../resolver/query-resolver";
import { exportAttendance } from "../../util/export";
import type { App } from "obsidian";
import type AttendancePlugin from "../../main";
export let resolver: QueryResolver;
export let plugin: AttendancePlugin;
let resolver = plugin.queryResolver;
export function update(cb: AttendanceCodeblock[]) {
codeblocks = cb;
}
export let app: App;
let codeblocks: AttendanceCodeblock[] = [];
let search: Search = {};
async function onExport() {
const cb = filterCodeblocks(codeblocks, search);
await exportAttendance(cb, plugin);
}
</script>

<div>
<Searchbar bind:search />
<div class="attendance-overview">
<Searchbar {app} on:export={onExport} bind:search />
<span class="search-string">
{#if search.from}
from {search.from.format("YYYY-MM-DD")}
{/if}
{#if search.to}
to {search.to.format("YYYY-MM-DD")}
{/if}
</span>
<div class="content">
<ListView resolver={resolver} attendance={filterCodeblocks(codeblocks, search)} />
<ListView
{resolver}
attendance={filterCodeblocks(codeblocks, search)}
/>
</div>
<Footer />
</div>

<style>
.attendance-overview {
display: flex;
flex-direction: column;
height: 100%;
}
.content {
flex-grow: 1;
flex-shrink: 1;
overflow-y: auto;
}
.search-string {
color: var(--text-faint);
display: block;
width: 100%;
text-align: center;
margin-bottom: 10px;
}
</style>
22 changes: 15 additions & 7 deletions src/ui/view/AttendanceOverviewView.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { Events, ItemView, WorkspaceLeaf } from "obsidian";
import { EVENT_CACHE_UPDATE, type QueryResolver } from "src/resolver/query-resolver";
import { ItemView, WorkspaceLeaf } from "obsidian";
import { EVENT_CACHE_UPDATE } from "src/resolver/query-resolver";
import {VIEW_TYPE_ATTENDANCE} from "src/globals";
import AttendanceOverview from "./AttendanceOverview.svelte";
import type AttendancePlugin from "src/main";

export class AttendanceOverviewView extends ItemView {
private attendanceOverview: AttendanceOverview;

constructor(leaf: WorkspaceLeaf, private readonly resolver: QueryResolver, eventBus: Events) {
constructor(leaf: WorkspaceLeaf, private readonly plugin: AttendancePlugin) {
super(leaf);

eventBus.on(EVENT_CACHE_UPDATE, () => {
plugin.events.on(EVENT_CACHE_UPDATE, () => {
if (this.attendanceOverview) {
this.attendanceOverview.update([...this.resolver.getCodeblocks()])
this.attendanceOverview.update([...this.plugin.queryResolver.getCodeblocks()])
}
})
}
Expand All @@ -23,15 +24,22 @@ export class AttendanceOverviewView extends ItemView {
return "Attendance";
}

override getIcon(): string {
return "user-check";
}

protected onOpen(): Promise<void> {
this.attendanceOverview = new AttendanceOverview({
target: this.contentEl,
props: {
resolver: this.resolver,
plugin: this.plugin,
app: this.plugin.app,
},
});

this.attendanceOverview.update([...this.resolver.getCodeblocks()]);
this.attendanceOverview.update([
...this.plugin.queryResolver.getCodeblocks(),
]);
return Promise.resolve();
}

Expand Down
9 changes: 8 additions & 1 deletion src/ui/view/Footer.svelte
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
<span>Buy me a coffee ♥ </span>
<div class="footer">Made with ♥ by <a href="https://tiim.ch">@Tiim</a></div>
<style>
.footer {
width: 100%;
text-align: center;
color: var(--text-faint);
}
</style>
7 changes: 6 additions & 1 deletion src/ui/view/ListView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

<div class="list-view">
{#each attendance as a}
<span>TODO: duplicate entries when modifying</span>
<article>
<div>
<span class="date">{a.date.format("YYYY-MM-DD")}</span>
Expand Down Expand Up @@ -47,4 +46,10 @@
border-radius: 4px;
background-color: var(--background-primary-alt);
}
.date {
color: var(--text-muted);
}
.summary {
color: var(--text-faint);
}
</style>
69 changes: 60 additions & 9 deletions src/ui/view/Searchbar.svelte
Original file line number Diff line number Diff line change
@@ -1,24 +1,75 @@
<script lang="ts">
import type { Search } from "src/util/filter-codeblocks";
import { onMount } from "svelte";
import { App, setIcon } from "obsidian";
import { createEventDispatcher } from "svelte";
import type { Search } from "../../util/filter-codeblocks";
import { SelectDatesModalView } from "./SelectDatesModalView";
export let app: App;
export let search: Search;
let btnCalendar: HTMLElement;
let dispatch = createEventDispatcher();
onMount(() => {
setIcon(btnCalendar, "calendar");
});
async function openDateModal() {
const sdmv = new SelectDatesModalView(app, search.from, search.to)
sdmv.open();
const dateRange = await sdmv.wait();
search.from = dateRange.startDate;
search.to = dateRange.endDate;
}
function onExport() {
dispatch("export");
}
</script>

<div class="searchbar">
<span class="searchinput">
<input type="text" bind:value={search.title} />
<input type="date" bind:value={search.from} />
<input type="date" bind:value={search.to} />
<input placeholder="Search..." type="text" bind:value={search.title} />
<button
bind:this={btnCalendar}
on:click={openDateModal}
title="Start Date"
/>
</span>
<button>Export</button>
<button class="export-btn" on:click={onExport}>Export</button>
</div>

<style>
.searchinput {
display: flex;
}
.searchinput {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
gap: 5px;
}
.searchinput input {
flex-grow: 1;
flex-shrink: 1;
min-width: 50px;
}
.export-btn {
width: 100%;
}
.searchinput button {
margin: 0px;
flex-shrink: 1;
color: var(--text-faint);
padding: 6px;
}
.searchinput button:hover {
color: var(--text-accent);
}
.searchbar {
position: relative;
display: flex;
flex-direction: column;
gap: 5px;
margin: 10px 0px;
}
</style>
50 changes: 50 additions & 0 deletions src/ui/view/SelectDatesModal.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<script lang="ts">
import {moment} from "obsidian";
import { createEventDispatcher } from "svelte";
import Flatpickr from "svelte-flatpickr";
import "flatpickr/dist/flatpickr.css";
let dispatch = createEventDispatcher();
let selected = false;
const options = {
mode: "range" as "range",
inline: true,
weekNumbers: true,
onChange(dates: (Date|undefined)[]) {
if (dates.length === 2 && dates[0] && dates[1]) {
dispatch("value", {
startDate: moment(dates[0]),
endDate: moment(dates[1])
});
selected = true;
} else {
selected = false;
}
},
};
function close() {
dispatch("close");
}
</script>

<div class="flatpickr-container">
<Flatpickr {options} />
{#if selected}
<button on:click={close}>Ok</button>
{/if}
</div>

<style>
.flatpickr-container {
display: flex;
flex-direction: column;
align-items: center;
gap: 10px;
padding: 2rem;
}
.flatpickr-container :global(.flatpickr-input) {
display: none;
}
</style>
Loading

0 comments on commit 0b0eb65

Please sign in to comment.