Commit to dev branch includes

- Due date on Todos
- Dailies segragation to not include non-due Dailies
- Checklist-items are now working
- Made a completely new wrapper for markdown+emojis, can render emojis in description as well as task name
This commit is contained in:
SuperChamp234 2022-01-14 17:55:47 +05:30
parent 88fdde519d
commit 22616cbed9
13 changed files with 110 additions and 17 deletions

View file

@ -36,6 +36,7 @@
"dependencies": { "dependencies": {
"markdown-it": "^12.3.2", "markdown-it": "^12.3.2",
"markdown-it-emoji": "^2.0.0", "markdown-it-emoji": "^2.0.0",
"moment": "^2.29.1",
"node": "^16.10.0", "node": "^16.10.0",
"node-emoji": "^1.11.0", "node-emoji": "^1.11.0",
"node-fetch": "^3.0.0", "node-fetch": "^3.0.0",

View file

@ -7,10 +7,14 @@ interface HabiticaSyncSettings {
apiToken: string apiToken: string
showTaskDescription: boolean showTaskDescription: boolean
showSubTasks: boolean showSubTasks: boolean
dueDateFormat: string
} }
const DEFAULT_SETTINGS: Partial<HabiticaSyncSettings> = { const DEFAULT_SETTINGS: Partial<HabiticaSyncSettings> = {
userID: "", userID: "",
apiToken: "" apiToken: "",
showTaskDescription: true,
showSubTasks: true,
dueDateFormat: "DD-MM-YYYY"
} }
export default class HabiticaSync extends Plugin { export default class HabiticaSync extends Plugin {
settings: HabiticaSyncSettings; settings: HabiticaSyncSettings;

View file

@ -1,5 +1,6 @@
import HabiticaSync from "./main"; import HabiticaSync from "./main";
import { App, PluginSettingTab, Setting } from "obsidian"; import { App, PluginSettingTab, Setting } from "obsidian";
import moment from "moment";
export class HabiticaSyncSettingsTab extends PluginSettingTab { export class HabiticaSyncSettingsTab extends PluginSettingTab {
plugin: HabiticaSync; plugin: HabiticaSync;
@ -62,6 +63,18 @@ export class HabiticaSyncSettingsTab extends PluginSettingTab {
await this.plugin.saveSettings(); await this.plugin.saveSettings();
}) })
}); });
new Setting(containerEl)
.setName("Due Date Format")
.setDesc("Update requires pane re-opening, check moment.js docs for formatting. Current Format: " + moment().format(this.plugin.settings.dueDateFormat))
.addText((text) =>
text
.setPlaceholder("DD-MM-YYYY")
.setValue(this.plugin.settings.dueDateFormat)
.onChange(async (value) => {
this.plugin.settings.dueDateFormat = value;
await this.plugin.saveSettings();
})
);
} }
} }

View file

@ -1,8 +1,9 @@
import * as React from "react"; import * as React from "react";
import { Notice } from "obsidian"; import { Notice } from "obsidian";
import { getStats, scoreTask, makeCronReq, costReward } from "./habiticaAPI" import { getStats, scoreTask, makeCronReq, costReward, scoreChecklistItem } from "./habiticaAPI"
import Statsview from "./Components/Statsview" import Statsview from "./Components/Statsview"
import Taskview from "./Components/Taskview" import Taskview from "./Components/Taskview"
import ReactDOM from "react-dom";
class App extends React.Component<any, any> { class App extends React.Component<any, any> {
private _username = ""; private _username = "";
@ -44,6 +45,7 @@ class App extends React.Component<any, any> {
this.handleChangeDailys = this.handleChangeDailys.bind(this); this.handleChangeDailys = this.handleChangeDailys.bind(this);
this.handleChangeHabits = this.handleChangeHabits.bind(this); this.handleChangeHabits = this.handleChangeHabits.bind(this);
this.handleChangeRewards = this.handleChangeRewards.bind(this); this.handleChangeRewards = this.handleChangeRewards.bind(this);
this.handleChangeChecklistItem = this.handleChangeChecklistItem.bind(this);
this.runCron = this.runCron.bind(this); this.runCron = this.runCron.bind(this);
} }
@ -144,8 +146,6 @@ class App extends React.Component<any, any> {
} }
}) })
} }
handleChangeDailys(event: any) { handleChangeDailys(event: any) {
this.state.tasks.dailys.forEach((element: any) => { this.state.tasks.dailys.forEach((element: any) => {
if (element.id == event.target.id) { if (element.id == event.target.id) {
@ -186,6 +186,26 @@ class App extends React.Component<any, any> {
} }
}) })
} }
async handleChangeChecklistItem(event: any){
let parentID = event.target.parentNode.parentNode.parentNode.getAttribute("id")
let targetID = event.target.id
console.log(parentID+ " , " + targetID)
try{
let response = await scoreChecklistItem(this.username, this.credentials, targetID, parentID);
let result = await response.json();
if (result.success === true) {
new Notice("Checked!");
this.reloadData();
} else {
new Notice("Resyncing, please try again");
this.reloadData();
}
} catch (e) {
console.log(e);
new Notice("API Error: Please check credentials")
}
}
render() { render() {
let content = this.CheckCron(this.state.user_data.lastCron); let content = this.CheckCron(this.state.user_data.lastCron);
if (this.state.error) if (this.state.error)
@ -197,7 +217,7 @@ class App extends React.Component<any, any> {
{content} {content}
<Statsview className ="stats-view" user_data={this.state.user_data} /> <Statsview className ="stats-view" user_data={this.state.user_data} />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" /> <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<Taskview data={this.state.tasks} handleChangeTodos={this.handleChangeTodos} settings = {this.props.plugin.settings} handleChangeDailys={this.handleChangeDailys} handleChangeHabits={this.handleChangeHabits} handleChangeRewards={this.handleChangeRewards}/> <Taskview data={this.state.tasks} handleChangeTodos={this.handleChangeTodos} settings = {this.props.plugin.settings} handleChangeDailys={this.handleChangeDailys} handleChangeHabits={this.handleChangeHabits} handleChangeRewards={this.handleChangeRewards} handleChangeChecklistItem={this.handleChangeChecklistItem}/>
</div> </div>
); );

View file

@ -11,8 +11,8 @@ function DailyItem(props: any) {
<div> <div>
<p><span dangerouslySetInnerHTML={{__html: text_html}}></span></p> <p><span dangerouslySetInnerHTML={{__html: text_html}}></span></p>
<div className="description" dangerouslySetInnerHTML={{__html: note_html}}></div> <div className="description" dangerouslySetInnerHTML={{__html: note_html}}></div>
{console.log(props.checklist)} {/* {console.log(props.checklist)} */}
<DailySubTasks subtasks={props.daily_subtasks} onChange={props.onChange}></DailySubTasks> <DailySubTasks subtasks={props.daily_subtasks} onChangeChecklistItem={props.onChangeChecklistItem}></DailySubTasks>
</div> </div>
</div> </div>

View file

@ -8,7 +8,7 @@ function DailySubTasks(props: any) {
let subtask_text = renderMarkdown(subtask.text); let subtask_text = renderMarkdown(subtask.text);
return ( return (
<div className="subtask" id={subtask.id}> <div className="subtask" id={subtask.id}>
<input type="checkbox" className="checkbox" onChange={props.onChange} checked={subtask.completed} /> <input id={subtask.id} type="checkbox" className="checkbox-checklist" onChange={props.onChangeChecklistItem} checked={subtask.completed} />
<p id={subtask.id}><span dangerouslySetInnerHTML={{__html: subtask_text}}></span></p> <p id={subtask.id}><span dangerouslySetInnerHTML={{__html: subtask_text}}></span></p>
</div> </div>
) )

View file

@ -7,8 +7,24 @@ export default function Index(props: any){
return <div id="classDisplay">No Dailies Present</div> return <div id="classDisplay">No Dailies Present</div>
} }
else { else {
const notDueDailies = props.dailys.map((daily: any) => {
if (!daily.isDue) {
let daily_notes = '';
let daily_subtasks = '';
if (props.settings.showTaskDescription) {
daily_notes = daily.notes;
}
if (props.settings.showSubTasks) {
daily_subtasks = daily.checklist;
}
return <DailyItem key={daily.id} id={daily.id} daily_text={daily.text}
daily_notes={daily_notes} daily_subtasks={daily_subtasks}
onChange={props.onChange} completed={daily.completed} onChangeChecklistItem={props.onChangeChecklistItem}/>
}
})
const incompleteDailies = props.dailys.map((daily: any) => { const incompleteDailies = props.dailys.map((daily: any) => {
if (!daily.completed) { if (!daily.completed&&daily.isDue) {
let daily_notes = ''; let daily_notes = '';
let daily_subtasks = ''; let daily_subtasks = '';
if (props.settings.showTaskDescription) { if (props.settings.showTaskDescription) {
@ -20,18 +36,33 @@ export default function Index(props: any){
} }
return <DailyItem key={daily.id} id={daily.id} daily_text={daily.text} return <DailyItem key={daily.id} id={daily.id} daily_text={daily.text}
daily_notes={daily_notes} daily_subtasks={daily_subtasks} daily_notes={daily_notes} daily_subtasks={daily_subtasks}
onChange={props.onChange} completed={daily.completed}/> onChange={props.onChange} completed={daily.completed} onChangeChecklistItem={props.onChangeChecklistItem}/>
} }
}) })
const completedDailies = props.dailys.map((daily: any) => { const completedDailies = props.dailys.map((daily: any) => {
if(daily.completed) // if(daily.completed)
return <DailyItem key={daily.id} id={daily.id} daily_text={daily.text} daily_notes={daily.notes} onChange={props.onChange} completed={daily.completed}/> // return <DailyItem key={daily.id} id={daily.id} daily_text={daily.text} daily_notes={daily.notes} onChange={props.onChange} completed={daily.completed}/>
if (!daily.completed) {
let daily_notes = '';
let daily_subtasks = '';
if (props.settings.showTaskDescription) {
daily_notes = daily.notes;
}
if (props.settings.showSubTasks) {
daily_subtasks = daily.checklist;
}
return <DailyItem key={daily.id} id={daily.id} daily_text={daily.text}
daily_notes={daily_notes} daily_subtasks={daily_subtasks}
onChange={props.onChange} completed={daily.completed} onChangeChecklistItem={props.onChangeChecklistItem}/>
}
}) })
const display = <div id="classDisplay"> const display = <div id="classDisplay">
<Tabs> <Tabs>
<TabList> <TabList>
<Tab>Active</Tab> <Tab>Active</Tab>
<Tab>Completed</Tab> <Tab>Completed</Tab>
<Tab>Not Due</Tab>
</TabList> </TabList>
<TabPanel> <TabPanel>
<ul>{incompleteDailies}</ul> <ul>{incompleteDailies}</ul>
@ -39,6 +70,9 @@ export default function Index(props: any){
<TabPanel> <TabPanel>
<ul>{completedDailies}</ul> <ul>{completedDailies}</ul>
</TabPanel> </TabPanel>
<TabPanel>
<ul>{notDueDailies}</ul>
</TabPanel>
</Tabs> </Tabs>
</div> </div>
return(display); return(display);

View file

@ -1,8 +1,10 @@
import * as React from "react"; import * as React from "react";
import TodoSubTasks from "./TodoSubTasks"; import TodoSubTasks from "./TodoSubTasks";
import renderMarkdown from "../markdownRender" import renderMarkdown from "../markdownRender"
import moment from "moment";
function TodoItem(props: any) { function TodoItem(props: any) {
var dueDate = (props.dueDate==null)?"":("Due Date:"+(moment(props.dueDate).format(props.dueDateFormat)));
var text_html = renderMarkdown(props.todo_text); var text_html = renderMarkdown(props.todo_text);
var note_html = renderMarkdown(props.todo_notes); var note_html = renderMarkdown(props.todo_notes);
return ( return (
@ -11,7 +13,8 @@ function TodoItem(props: any) {
<div> <div>
<p><span dangerouslySetInnerHTML={{__html: text_html}}></span></p> <p><span dangerouslySetInnerHTML={{__html: text_html}}></span></p>
<div className="description" dangerouslySetInnerHTML={{__html: note_html}}></div> <div className="description" dangerouslySetInnerHTML={{__html: note_html}}></div>
<TodoSubTasks subtasks={props.todo_subtasks} onChange={props.onChange}></TodoSubTasks> <TodoSubTasks todoID={props.id} subtasks={props.todo_subtasks} onChange={props.onChangeChecklistItem}></TodoSubTasks>
<div className="due-date">{dueDate}</div>
</div> </div>
</div> </div>
) )

View file

@ -7,7 +7,7 @@ function TodoSubTasks(props: any) {
let subtask_text = renderMarkdown(subtask.text); let subtask_text = renderMarkdown(subtask.text);
return ( return (
<div className="subtask" id={subtask.id}> <div className="subtask" id={subtask.id}>
<input type="checkbox" className="checkbox" onChange={props.onChange} checked={subtask.completed} /> <input type="checkbox" className="checkbox" onChange={props.onChange} checked={subtask.completed} id={subtask.id}/>
<p id={subtask.id}><span dangerouslySetInnerHTML={{__html: subtask_text}}></span></p> <p id={subtask.id}><span dangerouslySetInnerHTML={{__html: subtask_text}}></span></p>
</div> </div>
) )

View file

@ -21,7 +21,7 @@ export default function Index(props: any){
} }
return <TodoItem key={todo.id} id={todo.id} todo_text={todo.text} return <TodoItem key={todo.id} id={todo.id} todo_text={todo.text}
todo_notes={todo_notes} todo_subtasks={todo_subtasks} todo_notes={todo_notes} todo_subtasks={todo_subtasks}
onChange={props.onChange} completed={todo.completed}/> onChange={props.onChange} onChangeChecklistItem={props.onChangeChecklistItem} completed={todo.completed} dueDate={todo.date} dueDateFormat={props.settings.dueDateFormat}/>
} }
}) })

View file

@ -24,13 +24,13 @@ export default function Index(props: any){
</Tab> </Tab>
</TabList> </TabList>
<TabPanel> <TabPanel>
<Dailiesview dailys={props.data.dailys} settings = {props.settings} onChange={props.handleChangeDailys} /> <Dailiesview dailys={props.data.dailys} settings = {props.settings} onChange={props.handleChangeDailys} onChangeChecklistItem={props.handleChangeChecklistItem}/>
</TabPanel> </TabPanel>
<TabPanel> <TabPanel>
<Habitsview habits={props.data.habits} settings = {props.settings} onChange={props.handleChangeHabits}/> <Habitsview habits={props.data.habits} settings = {props.settings} onChange={props.handleChangeHabits}/>
</TabPanel> </TabPanel>
<TabPanel> <TabPanel>
<Todoview todos={props.data.todos} settings = {props.settings} onChange={props.handleChangeTodos} /> <Todoview todos={props.data.todos} settings = {props.settings} onChange={props.handleChangeTodos} onChangeChecklistItem={props.handleChangeChecklistItem}/>
</TabPanel> </TabPanel>
<TabPanel> <TabPanel>
<Rewardview rewards={props.data.rewards} settings = {props.settings} onChange={props.handleChangeRewards} /> <Rewardview rewards={props.data.rewards} settings = {props.settings} onChange={props.handleChangeRewards} />

View file

@ -54,3 +54,17 @@ export async function costReward(username: string, credentials: string, taskID:
}) })
return(response) return(response)
} }
export async function scoreChecklistItem(username: string, credentials: string, checklistItemID: string, taskID: string) {
const url = "https://habitica.com/api/v3/tasks/".concat(taskID).concat("/checklist/").concat(checklistItemID).concat("/score")
const response = fetch(url, {
method: 'POST',
headers: {
"Content-Type": "application/json",
"x-client": "278e719e-5f9c-43b1-9dba-8b73343dc062-HabiticaSync",
"x-api-user": username,
"x-api-key": credentials,
}
})
return(response)
}

View file

@ -305,3 +305,7 @@ button {
.emoji { .emoji {
height: 1em; height: 1em;
} }
.description>ul {
list-style-type: disc;
margin-left: 10% !important;
}