diff --git a/.gitignore b/.gitignore index de7c3d1..f36d0a2 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,6 @@ node_modules package-lock.json -# yarn -yarn.lock - *.js.map diff --git a/.hotreload b/.hotreload deleted file mode 100644 index e69de29..0000000 diff --git a/README.md b/README.md index 43497e5..92fc6d4 100644 --- a/README.md +++ b/README.md @@ -1,46 +1,24 @@ # Habitica Sync in Obsidian This plugin for Obsidian incorporates a view to display and interact with the task management app Habitica. -Please open issues for any bugs/functionality requests :) - ## Usage -The plugin's view is enabled by clicking on the "Open Habitica Pane" option in the side ribbon (default hotkey is `Ctrl+Shift+H`). - -To sync your Habitica account, go to the settings page of the plugin and enter your user ID and API token credentials. +The plugin's view is enabled by clicking on the "Open Habitica Pane" option in the side ribbon. To sync your account, go to the settings page of the plugin and enter your user ID and API token credentials. ## Features -### Pane View -#### View stats (HP, XP, coins) -#### Views -Task Information: -- Title, description, subtasks - - Markdown and emoji support - -Tabs: -- To Do's - - Active/Completed -- Dailies - - Due/Not Due/Completed - - [![Image from Gyazo](https://i.gyazo.com/1966b17f954dcffa954922570e860a06.png)](https://gyazo.com/1966b17f954dcffa954922570e860a06) -- Habits - - [![Image from Gyazo](https://i.gyazo.com/280494e620fc91548838d5b29a62652b.png)](https://gyazo.com/280494e620fc91548838d5b29a62652b) -- Rewards -#### Interactivity -- Check off tasks/dailies in the view - - Can uncheck completed habits/todos - - [![Image from Gyazo](https://i.gyazo.com/efb858cd9d54f9d9df936da1bd5858ed.gif)](https://gyazo.com/efb858cd9d54f9d9df936da1bd5858ed) -- modify habit counters (+/-) - -### Settings - -The following two inputs help fetch your user data to be displayed in the Obsidian view: +- View current HP and XP +- View todos, dailies, and habits +- Check off tasks/dailies in the view, which sync to habitica website +- Modify habit counters (+/-) +## Settings - **Habitica User ID:** You can find this by clicking on the "User" icon in the top right of the Habitica webapp, "Settings", then "API" - **Habitica Token API:** You can find this by clicking on the "User" icon in the top right of the Habitica webapp, "Settings", then "API" -- **Show Task Descriptions:** Toggles whether description/notes for tasks will be shown or not -- **Show Subtasks:** Toggles whether subtasks for to do's/dailies will be shown or not + +The following two inputs help fetch your user data to be displayed in the Obsidian view. ## Roadmap +We will be implementing additional features including: +- Add/delete/customize tasks and habits +- View/claim rewards -*Feel free to support us and donate!* +Feeling generous? Buy Me a Coffee at ko-fi.com - diff --git a/manifest.json b/manifest.json index 2ae5bfe..8b6413f 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "obsidian-habitica-integration", "name": "Habitica Sync", - "version": "1.0.2", + "version": "0.9.5", "minAppVersion": "0.9.12", "description": "This plugin helps integrate Habitica user tasks and stats into Obsidian", "author": "Leoh and Ran", diff --git a/package.json b/package.json index 37371e6..4acb414 100644 --- a/package.json +++ b/package.json @@ -1,51 +1,36 @@ { "name": "obsidian-habitica-integration", - "version": "1.0.0", + "version": "0.12.0", "description": "This plugin allows for Habitica integration into Obsidian", "main": "main.js", "scripts": { - "dev": "rollup --config rollup.config.mjs -w", - "build": "rollup --config rollup.config.mjs --environment BUILD:production", - "dev2": "obsidian-plugin dev src/main.ts" + "dev": "rollup --config rollup.config.js -w", + "build": "rollup --config rollup.config.js --environment BUILD:production" }, "keywords": [], "author": "Leonard and Ran", "license": "MIT", "devDependencies": { - "@rollup/plugin-commonjs": "^25.0.7", - "@rollup/plugin-json": "^6.1.0", - "@rollup/plugin-node-resolve": "^15.2.3", - "@rollup/plugin-typescript": "^11.1.6", - "@types/markdown-it": "^13.0.7", - "@types/markdown-it-emoji": "^2.0.4", - "@types/node": "^20.11.0", - "@types/node-emoji": "^1.8.2", - "@types/react": "^18.2.47", - "@types/react-dom": "^18.2.18", - "@types/react-tabs": "^5.0.4", - "@types/twemoji": "^13.1.1", - "css-loader": "^6.9.0", - "mini-css-extract-plugin": "^2.7.7", - "obsidian": "^1.4.11", - "obsidian-plugin-cli": "^0.0.5", - "rollup": "^4.9.4", - "style-loader": "^3.3.4", - "tslib": "^2.6.2", - "typescript": "^5.3.3", - "webpack": "^5.89.0" + "@rollup/plugin-commonjs": "^18.0.0", + "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-typescript": "^8.2.1", + "@types/node": "^14.14.37", + "@types/react": "^17.0.27", + "@types/react-dom": "^17.0.9", + "@types/react-tabs": "^2.3.3", + "css-loader": "^6.4.0", + "extract-text-webpack-plugin": "^2.1.2", + "obsidian": "^0.12.0", + "rollup": "^2.32.1", + "style-loader": "^3.3.0", + "tslib": "^2.2.0", + "typescript": "^4.2.4" }, "dependencies": { - "markdown-it": "^14.0.0", - "markdown-it-emoji": "^2.0.2", - "moment": "^2.30.1", - "node": "^21.2.0", - "node-emoji": "^2.1.3", - "node-fetch": "^3.3.2", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-emoji-render": "^2.0.1", - "react-markdown": "^9.0.1", - "react-tabs": "^6.0.2", - "twemoji": "^14.0.2" + "node": "^16.10.0", + "node-fetch": "^3.0.0", + "react": "^17.0.2", + "react-dom": "^17.0.2", + "react-tabs": "^3.2.2" } } diff --git a/rollup.config.mjs b/rollup.config.js similarity index 92% rename from rollup.config.mjs rename to rollup.config.js index 1551460..8e28e8d 100644 --- a/rollup.config.mjs +++ b/rollup.config.js @@ -1,32 +1,30 @@ -import typescript from '@rollup/plugin-typescript'; -import {nodeResolve} from '@rollup/plugin-node-resolve'; -import commonjs from '@rollup/plugin-commonjs'; -import json from '@rollup/plugin-json'; - -const isProd = (process.env.BUILD === 'production'); - -const banner = -`/* -THIS IS A GENERATED/BUNDLED FILE BY ROLLUP -if you want to view the source visit the plugins github repository -*/ -`; - -export default { - input: 'src/main.ts', - output: { - dir: '.', - sourcemap: 'inline', - sourcemapExcludeSources: isProd, - format: 'cjs', - exports: 'default', - banner, - }, - external: ['obsidian'], - plugins: [ - typescript(), - nodeResolve({browser: true}), - commonjs(), - json(), - ] +import typescript from '@rollup/plugin-typescript'; +import {nodeResolve} from '@rollup/plugin-node-resolve'; +import commonjs from '@rollup/plugin-commonjs'; + +const isProd = (process.env.BUILD === 'production'); + +const banner = +`/* +THIS IS A GENERATED/BUNDLED FILE BY ROLLUP +if you want to view the source visit the plugins github repository +*/ +`; + +export default { + input: 'src/main.ts', + output: { + dir: '.', + sourcemap: 'inline', + sourcemapExcludeSources: isProd, + format: 'cjs', + exports: 'default', + banner, + }, + external: ['obsidian'], + plugins: [ + typescript(), + nodeResolve({browser: true}), + commonjs(), + ] }; \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index b8eaff4..bdf0312 100644 --- a/src/main.ts +++ b/src/main.ts @@ -5,30 +5,23 @@ import { HabiticaSyncView, VIEW_TYPE} from "./view" interface HabiticaSyncSettings { userID: string apiToken: string - showTaskDescription: boolean - showSubTasks: boolean - dueDateFormat: string } const DEFAULT_SETTINGS: Partial = { userID: "", - apiToken: "", - showTaskDescription: true, - showSubTasks: true, - dueDateFormat: "DD-MM-YYYY" + apiToken: "" } export default class HabiticaSync extends Plugin { settings: HabiticaSyncSettings; view: HabiticaSyncView; async onload() { - console.log("load plugin: habitica-sync") await this.loadSettings(); this.addSettingTab(new HabiticaSyncSettingsTab(this.app, this)); this.registerView( VIEW_TYPE, (leaf) => (new HabiticaSyncView(leaf, this)) ); - this.addRibbonIcon("popup-open", "Open Habitica Pane", () => { + this.addRibbonIcon("popup-open", "Open Habitica Pane", () => { //activate view this.activateView(); }); this.addCommand({ @@ -39,7 +32,6 @@ export default class HabiticaSync extends Plugin { this.activateView(); } }); - } async loadSettings() { this.settings = Object.assign(DEFAULT_SETTINGS, await this.loadData()) @@ -47,7 +39,6 @@ export default class HabiticaSync extends Plugin { async saveSettings() { await this.saveData(this.settings); } - async onunload() { await this.view.onClose(); @@ -57,15 +48,15 @@ export default class HabiticaSync extends Plugin { } async activateView() { this.app.workspace.detachLeavesOfType(VIEW_TYPE); - + await this.app.workspace.getRightLeaf(false).setViewState({ type: VIEW_TYPE, active: true, }); - + this.app.workspace.revealLeaf( this.app.workspace.getLeavesOfType(VIEW_TYPE)[0] ); } - + } diff --git a/src/settings.ts b/src/settings.ts index 974fe44..bd298e5 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -1,6 +1,5 @@ import HabiticaSync from "./main"; import { App, PluginSettingTab, Setting } from "obsidian"; -import moment from "moment"; export class HabiticaSyncSettingsTab extends PluginSettingTab { plugin: HabiticaSync; @@ -39,42 +38,5 @@ export class HabiticaSyncSettingsTab extends PluginSettingTab { await this.plugin.saveSettings(); }) ); - - new Setting(containerEl) - .setName("Show Task Descriptions") - .setDesc("Updates require pane re-opening") - .addToggle(cb => { - cb - .setValue(this.plugin.settings.showTaskDescription) - .onChange(async (isEnable) => { - this.plugin.settings.showTaskDescription = isEnable; - await this.plugin.saveSettings(); - }) - }); - - new Setting(containerEl) - .setName("Show Sub-Tasks") - .setDesc("Updates require pane re-opening") - .addToggle(cb => { - cb - .setValue(this.plugin.settings.showSubTasks) - .onChange(async (isEnable) => { - this.plugin.settings.showSubTasks = isEnable; - 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(); - }) - ); - } } \ No newline at end of file diff --git a/src/view.tsx b/src/view.tsx index be66720..e73dbb7 100644 --- a/src/view.tsx +++ b/src/view.tsx @@ -31,7 +31,8 @@ export class HabiticaSyncView extends ItemView { this.containerEl.children[1] ) } - async onClose(){ + + async onClose(){ ReactDOM.unmountComponentAtNode(this.containerEl.children[1]); } } \ No newline at end of file diff --git a/src/view/App.tsx b/src/view/App.tsx index 1406d23..fd8bdff 100644 --- a/src/view/App.tsx +++ b/src/view/App.tsx @@ -1,31 +1,18 @@ import * as React from "react"; import { Notice } from "obsidian"; -import { getStats, scoreTask, makeCronReq, costReward, scoreChecklistItem } from "./habiticaAPI" +import { getStats, scoreTask } from "./habiticaAPI" import Statsview from "./Components/Statsview" import Taskview from "./Components/Taskview" -import ReactDOM from "react-dom"; -class App extends React.Component { - private _username = ""; - public get username() { - return this._username; - } - public set username(value) { - this._username = value; - } - private _credentials = ""; - public get credentials() { - return this._credentials; - } - public set credentials(value) { - this._credentials = value; - } +let username = "" +let credentials = "" + +class App extends React.Component { constructor(props: any) { super(props) - this.username = this.props.plugin.settings.userID - this.credentials = this.props.plugin.settings.apiToken + username = this.props.plugin.settings.userID + credentials = this.props.plugin.settings.apiToken this.state = { - needCron: false, isLoaded: false, user_data: { profile: { @@ -34,192 +21,119 @@ class App extends React.Component { stats: { hp: 0, lvl: 0, - gold: 0, - }, - lastCron: "", + } }, todos: [], dailys: [], habits: [], } - this.handleChangeTodos = this.handleChangeTodos.bind(this); - this.handleChangeDailys = this.handleChangeDailys.bind(this); - this.handleChangeHabits = this.handleChangeHabits.bind(this); - this.handleChangeRewards = this.handleChangeRewards.bind(this); - this.handleChangeChecklistItem = this.handleChangeChecklistItem.bind(this); - this.runCron = this.runCron.bind(this); + this.handleChangeTodos = this.handleChangeTodos.bind(this) + this.handleChangeDailys = this.handleChangeDailys.bind(this) + this.handleChangeHabits = this.handleChangeHabits.bind(this) - } - CheckCron(lastCron: string) { - let cronDate = new Date(lastCron); - let now = new Date(); - if (cronDate.getDate() != now.getDate() || (cronDate.getMonth() != now.getMonth() || cronDate.getFullYear() != now.getFullYear())) { - return ( -
-
Welcome back! Please check your tasks for the last day and hit continue to get your daily rewards.
- -
- ); - } - else { - return null - }; - } - async runCron() { - console.log("running cron"); - try { - let response = await makeCronReq(this.username, this.credentials); - this.setState({ - needCron: false, - }) - } catch (error) { - console.log(error); - new Notice("There was an error running the cron. Please try again later."); - } - this.reloadData(); + + } + sendNotice(message: string){ + new Notice(message) } async reloadData() { - try { - let response = await getStats(this.username, this.credentials); - let result = await response.json(); - if (result.success === false) { - new Notice('Login Failed, Please check credentials and try again!'); + const result = (await getStats(username, credentials)).json() + result.then( + result => { + if(result.success === false){ + this.sendNotice("Login Failed, Please check credentials and try again!") + } else { + this.setState({ + isLoaded: true, + user_data: result, + tasks: result.tasks, + }) + } + }, + (error) => { + this.setState({ + isLoaded: true, + error + }) } - else { - this.setState({ - isLoaded: true, - user_data: result, - tasks: result.tasks, - }); - } - } catch (e) { - console.log(e); - new Notice("API Error: Please check credentials") - } + ) } componentDidMount() { this.reloadData() } - - async sendScore(id: string, score: string, message: string) { - try { - let response = await scoreTask(this.username, this.credentials, id, score); - let result = await response.json(); - if (result.success === true) { - new Notice(message); - this.reloadData(); - } else { - new Notice("Resyncing, please try again"); - this.reloadData(); - } - } catch (e) { - console.log(e); - new Notice("API Error: Please check credentials") - } - } - - async sendReward(id: string, score: string, message: string) { - try { - let response = await costReward(this.username, this.credentials, id, score); - let result = await response.json(); - if (result.success === true) { - new Notice(message); - this.reloadData(); - } else { - new Notice("Resyncing, please try again"); - this.reloadData(); - } - } catch (e) { - console.log(e); - new Notice("API Error: Please check credentials") - } - } - - handleChangeTodos(event: any) { - this.state.tasks.todos.forEach((element: any) => { - if (element.id == event.target.id) { - if (!element.completed) { - this.sendScore(event.target.id, "up", "Checked!") + + async sendScore(id:string , score: string, message: string){ + const result = (await scoreTask(username, credentials, id, score)).json() + result.then( + result => { + if(result.success) { + this.sendNotice(message) + this.reloadData() } else { - this.sendScore(event.target.id, "down", "Un-Checked!") + this.sendNotice("Resyncing, please try again") + this.reloadData() + } + }, + (error) => { + this.sendNotice("API Error: Please Check crendentials and try again") + console.log(error) + } + ) + } + + handleChangeTodos(event: any){ + this.state.tasks.todos.forEach((element: any) => { + if(element.id == event.target.id){ + if(!element.completed){ + this.sendScore(event.target.id,"up", "Checked!") + } else { + this.sendScore(event.target.id,"down", "Un-Checked!") } } }) } - handleChangeDailys(event: any) { + handleChangeDailys(event: any){ this.state.tasks.dailys.forEach((element: any) => { - if (element.id == event.target.id) { - if (element.id == event.target.id) { - if (!element.completed) { - this.sendScore(event.target.id, "up", "Checked!") + if(element.id == event.target.id){ + if(element.id == event.target.id){ + if(!element.completed){ + this.sendScore(event.target.id,"up", "Checked!") } else { - this.sendScore(event.target.id, "down", "Un-Checked!") + this.sendScore(event.target.id,"down", "Un-Checked!") } } } }) } - handleChangeHabits(event: any) { + handleChangeHabits(event: any){ const target_id = event.target.id.slice(4) - if (event.target.id.slice(0, 4) == "plus") { + if(event.target.id.slice(0,4) == "plus"){ this.state.tasks.habits.forEach((element: any) => { - if (element.id == target_id) { - this.sendScore(target_id, "up", "Plus!") + if(element.id == target_id){ + this.sendScore(target_id,"up", "Plus!") } }) } else { this.state.tasks.habits.forEach((element: any) => { - if (element.id == target_id) { - this.sendScore(target_id, "down", "Minus :(") + if(element.id == target_id){ + this.sendScore(target_id,"down", "Minus :(") } }) } } - handleChangeRewards(event: any) { - const target_id = event.target.id - this.state.tasks.rewards.forEach((element: any) => { - if (element.id == event.target.id) { - if (element.id == target_id) { - this.sendReward(target_id, "down", "Redeemed!") - } - } - }) - } - 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() { - let content = this.CheckCron(this.state.user_data.lastCron); - if (this.state.error) - return (
Loading....
) - else if (!this.state.isLoaded) + render(){ + if(this.state.error) + return(
Loading....
) + else if(!this.state.isLoaded) return
Loading....
else { return (
- {content} - - - -
+ + + ); } } diff --git a/src/view/Components/Statsview/index.tsx b/src/view/Components/Statsview/index.tsx index 506cae4..f15d886 100644 --- a/src/view/Components/Statsview/index.tsx +++ b/src/view/Components/Statsview/index.tsx @@ -3,13 +3,9 @@ import * as React from 'react'; export default function Index(props: any) { return(
- {/*
{props.user_data.profile.name}
*/} -
HP: {numberWithCommas((props.user_data.stats.hp).toFixed(0))}
-
LEVEL: {props.user_data.stats.lvl}
-
GOLD: {numberWithCommas(props.user_data.stats.gp.toFixed(2))}
+
{props.user_data.profile.name}
+
favoriteHP: {(props.user_data.stats.hp).toPrecision(3)}
+
starLVL: {props.user_data.stats.lvl}
); -} -function numberWithCommas(x: any) { - return x.toString().replace(/\B(? - -
-

-
- {/* {console.log(props.checklist)} */} - -
- + +

{props.daily_text}

) } diff --git a/src/view/Components/Taskview/Dailiesview/DailySubTasks.tsx b/src/view/Components/Taskview/Dailiesview/DailySubTasks.tsx deleted file mode 100644 index 09e4c99..0000000 --- a/src/view/Components/Taskview/Dailiesview/DailySubTasks.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import * as React from "react"; -import renderMarkdown from "../markdownRender"; - -function DailySubTasks(props: any) { - - if (props.subtasks) { - const subtasks = props.subtasks.map((subtask: any) => { - let subtask_text = renderMarkdown(subtask.text); - return ( -
- -

-
- ) - }); - return subtasks - } - else { - return
- } -} -export default DailySubTasks \ No newline at end of file diff --git a/src/view/Components/Taskview/Dailiesview/index.tsx b/src/view/Components/Taskview/Dailiesview/index.tsx index db5944b..0d0f192 100644 --- a/src/view/Components/Taskview/Dailiesview/index.tsx +++ b/src/view/Components/Taskview/Dailiesview/index.tsx @@ -3,89 +3,23 @@ import DailyItem from "./DailyItem" import { Tab, Tabs, TabList, TabPanel } from "react-tabs"; export default function Index(props: any){ - if(props.dailys == undefined) { return
No Dailies Present
} 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 - } - }) - const incompleteDailies = props.dailys.map((daily: any) => { - if (!daily.completed&&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 - } - }) + if(!daily.completed) + return + }) const completedDailies = props.dailys.map((daily: any) => { - // if(daily.completed) - // return - 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 - } + if(daily.completed) + return }) - - const allDailies = props.dailys.map((daily: any) => { - // if(daily.completed) - // return - let daily_notes = ''; - let daily_subtasks = ''; - if (props.settings.showTaskDescription) { - daily_notes = daily.notes; - } - - if (props.settings.showSubTasks) { - daily_subtasks = daily.checklist; - } - return - }) - const display =
Active Completed - Not Due - All
    {incompleteDailies}
@@ -93,15 +27,10 @@ export default function Index(props: any){
    {completedDailies}
- -
    {notDueDailies}
-
- -
    {allDailies}
-
return(display); } } + diff --git a/src/view/Components/Taskview/Habitsview/HabitItem.tsx b/src/view/Components/Taskview/Habitsview/HabitItem.tsx index 37d672c..faff665 100644 --- a/src/view/Components/Taskview/Habitsview/HabitItem.tsx +++ b/src/view/Components/Taskview/Habitsview/HabitItem.tsx @@ -1,23 +1,15 @@ -import * as React from "react"; -import renderMarkdown from "../markdownRender"; + import * as React from "react"; function HabitItem(props: any) { - let habit_text = renderMarkdown(props.habit_text); - let habit_notes = renderMarkdown(props.habit_notes); return (
-
- - -
-
-

-
-
+ +

{props.habit_text}

+
) } diff --git a/src/view/Components/Taskview/Habitsview/index.tsx b/src/view/Components/Taskview/Habitsview/index.tsx index 1d0107c..dc322bb 100644 --- a/src/view/Components/Taskview/Habitsview/index.tsx +++ b/src/view/Components/Taskview/Habitsview/index.tsx @@ -9,11 +9,7 @@ export default function Index(props: any){ } else { const allHabits = props.habits.map((habit: any) => { - if (props.settings.showTaskDescription) { - return - } else { - return - } + return }) const display =
    {allHabits}
diff --git a/src/view/Components/Taskview/Rewardview/RewardItem.tsx b/src/view/Components/Taskview/Rewardview/RewardItem.tsx deleted file mode 100644 index 5f331e2..0000000 --- a/src/view/Components/Taskview/Rewardview/RewardItem.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from "react"; -import renderMarkdown from "../markdownRender"; - -function RewardItem(props: any) { - let reward_text = renderMarkdown(props.reward_text); - let reward_notes = renderMarkdown(props.reward_notes); - return ( -
-
- -
-
-

-
-
- -
- ) -} - -export default RewardItem \ No newline at end of file diff --git a/src/view/Components/Taskview/Rewardview/index.tsx b/src/view/Components/Taskview/Rewardview/index.tsx deleted file mode 100644 index 4ddc21a..0000000 --- a/src/view/Components/Taskview/Rewardview/index.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as React from "react"; -import RewardItem from "./RewardItem" - -export default function Index(props: any){ - if(props.rewards == undefined) { - return (
- No Rewards present. -
) - } - else { - const allRewards = props.rewards.map((reward: any) => { - if (props.settings.showTaskDescription) { - return - } else { - return - } - }) - const display =
-
    {allRewards}
-
- - return(display); - } -} - diff --git a/src/view/Components/Taskview/TodoItem.tsx b/src/view/Components/Taskview/TodoItem.tsx new file mode 100644 index 0000000..4adc70f --- /dev/null +++ b/src/view/Components/Taskview/TodoItem.tsx @@ -0,0 +1,12 @@ + import * as React from "react"; + +function TodoItem(props: any) { + return ( +
+ +

{props.todo_text}

+
+ ) +} + +export default TodoItem \ No newline at end of file diff --git a/src/view/Components/Taskview/Todoview/TodoItem.tsx b/src/view/Components/Taskview/Todoview/TodoItem.tsx index 7c1653b..4adc70f 100644 --- a/src/view/Components/Taskview/Todoview/TodoItem.tsx +++ b/src/view/Components/Taskview/Todoview/TodoItem.tsx @@ -1,21 +1,10 @@ -import * as React from "react"; -import TodoSubTasks from "./TodoSubTasks"; -import renderMarkdown from "../markdownRender" -import moment from "moment"; + import * as React from "react"; 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 note_html = renderMarkdown(props.todo_notes); return (
-
-

-
- -
{dueDate}
-
+

{props.todo_text}

) } diff --git a/src/view/Components/Taskview/Todoview/TodoSubTasks.tsx b/src/view/Components/Taskview/Todoview/TodoSubTasks.tsx deleted file mode 100644 index 92ab97a..0000000 --- a/src/view/Components/Taskview/Todoview/TodoSubTasks.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import * as React from "react"; -import renderMarkdown from "../markdownRender"; - -function TodoSubTasks(props: any) { - if (props.subtasks) { - const subtasks = props.subtasks.map((subtask: any) => { - let subtask_text = renderMarkdown(subtask.text); - return ( -
- -

-
- ) - }); - return subtasks - } - else { - return
- } -} -export default TodoSubTasks \ No newline at end of file diff --git a/src/view/Components/Taskview/Todoview/index.tsx b/src/view/Components/Taskview/Todoview/index.tsx index 035b52e..7ce2edf 100644 --- a/src/view/Components/Taskview/Todoview/index.tsx +++ b/src/view/Components/Taskview/Todoview/index.tsx @@ -8,26 +8,12 @@ export default function Index(props: any){ } else { const incompleteTodos = props.todos.map((todo: any) => { - - if(!todo.completed) { - let todo_notes = ''; - let todo_subtasks = ''; - if (props.settings.showTaskDescription) { - todo_notes = todo.notes; - } - - if (props.settings.showSubTasks) { - todo_subtasks = todo.checklist; - } - return - } - + if(!todo.completed) + return }) const completedTodos = props.todos.map((todo: any) => { if(todo.completed) - return + return }) const display =
@@ -36,10 +22,10 @@ export default function Index(props: any){ Completed -
    {incompleteTodos}
+
    {incompleteTodos}
-
    {completedTodos}
+
    {completedTodos}
diff --git a/src/view/Components/Taskview/Todoview/tabs.ts b/src/view/Components/Taskview/Todoview/tabs.ts new file mode 100644 index 0000000..55153e7 --- /dev/null +++ b/src/view/Components/Taskview/Todoview/tabs.ts @@ -0,0 +1 @@ +import * as React from "react" diff --git a/src/view/Components/Taskview/index.tsx b/src/view/Components/Taskview/index.tsx index 06d2874..9546979 100644 --- a/src/view/Components/Taskview/index.tsx +++ b/src/view/Components/Taskview/index.tsx @@ -2,41 +2,33 @@ import * as React from "react"; import Dailiesview from "./Dailiesview" import Habitsview from "./Habitsview" import Todoview from "./Todoview" -import Rewardview from "./Rewardview" import { Tab, Tabs, TabList, TabPanel } from "react-tabs"; export default function Index(props: any){ const display =
- + + task_alt + today - - add_chart - - assignment_turned_in - - - account_balance + add_circle_outline - + - + - - - - +
return(display); -} +} //yes diff --git a/src/view/Components/Taskview/markdownRender.ts b/src/view/Components/Taskview/markdownRender.ts deleted file mode 100644 index e09aa1f..0000000 --- a/src/view/Components/Taskview/markdownRender.ts +++ /dev/null @@ -1,21 +0,0 @@ -import MarkdownIt from "markdown-it"; -import markdownitEmoji from "markdown-it-emoji" -import twemoji from "twemoji"; - -export default function renderMarkdown(markdown: string) { - //check if markdown is empty or not a string - if (markdown === "" || markdown === undefined) { - return ""; - } - const md = new MarkdownIt({ - html: true, - breaks: true, - linkify: true, - typographer: true - }); - md.use(markdownitEmoji); - md.renderer.rules.emoji = function(token, idx) { - return twemoji.parse(token[idx].content); - }; - return md.render(markdown); -} \ No newline at end of file diff --git a/src/view/habiticaAPI.ts b/src/view/habiticaAPI.ts index eae3ab8..36f2b25 100644 --- a/src/view/habiticaAPI.ts +++ b/src/view/habiticaAPI.ts @@ -6,7 +6,7 @@ export async function getStats(username: string, credentials: string){ method: 'GET', headers: { "Content-Type": "application/json", - "x-client": "278e719e-5f9c-43b1-9dba-8b73343dc062-HabiticaSync", + "x-client": username.concat("-testAPI"), "x-api-user": username, "x-api-key": credentials, }, @@ -20,48 +20,7 @@ export async function scoreTask(username: string, credentials: string, taskID: s 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) -} -export async function makeCronReq(username: string, credentials: string){ - const url = "https://habitica.com/api/v3/cron"; - 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) -} - -export async function costReward(username: string, credentials: string, taskID: string, direction: string) { - const url = "https://habitica.com/api/v4/tasks/".concat(taskID).concat("/score/").concat(direction) - 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) -} - -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-client": username.concat("-testAPI"), "x-api-user": username, "x-api-key": credentials, } diff --git a/styles.css b/styles.css index 90c9ec1..680c446 100644 --- a/styles.css +++ b/styles.css @@ -1,323 +1,151 @@ -@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@1,300&display=swap'); -@import url('https://fonts.googleapis.com/css2?family=Open Sans:ital,wght@0,400;1,100&family=Roboto&display=swap'); - -.add-task-input { - display: flex; -} - -#profile-name { - font-size: x-large; - font-weight: bold; - padding-bottom: 3%; -} -.stats { - width: 95%; - display: flex; - justify-content: space-between; - font-weight: bold; - padding-bottom: 5px; -} - -.stats-view { - border-bottom: 1px; -} -.modify-todo { - align-self: center; -} - -.delete-todo { - align-self: center; -} - -.todo-item { - display: grid; - grid-template-columns: 1fr 30fr 1fr 1fr; - justify-content: left; - align-items: flex-start; - padding-top: 5px; - padding-bottom: 5px; - width: 100%; - border-bottom: 1px solid #cecece; - font-family: Roboto, sans-serif; - font-weight: bold; - font-size: 16px; - padding-left: 0; -} - -.description { - font-family: Open Sans, sans-serif; - font-weight: 100; -} -.description > ul { - list-style-type: none; -} -p { - margin: 0; -} - -.habit-text { - text-align: left !important; - font-weight: bold; - padding-top: 5px; - width: 80%; - margin-right: 20px; -} - -.habit-button { - background-color: var(--interactive-accent); - border: none; - /* color: black; */ - text-align: center; - text-decoration: none; - font-size: 16px; - display: block; - width: 100%; - color: var(--text-on-accent); -} -/* habit-button on hover css selector */ -.habit-button:hover { - color: var(--text-on-accent); - background-color: var(--interactive-accent-hover); -} - -.habit-item { - display: flex; - grid-template-columns: 60px 1fr; - width: 100%; - gap: 5px; - border-bottom: 1px solid #cecece; - font-family: Open Sans, sans-serif; - font-weight: 100%; - font-size: 16px; - padding-top: 5px; - padding-bottom: 5px; -} - -.habit-button-grp { - display: flex; - flex-direction: column; - justify-content: flex-start; - align-content: stretch; - height: 100%; -} - -input[type=checkbox] { - margin-right: 10px; - margin-top: 5px; - align-self: start; -} - -.todo-content { - align-self: center; -} - -.submit-button { - /* padding: 5px 5px; */ - font-size: 15px; - border: 1px solid #aaa; - /* white-space: nowrap; */ - /* margin: 10px; */ - margin: 0; -} - -input[type=checkbox]:focus { - outline: 0; -} - -::-webkit-scrollbar { - display: none; /* Chrome Safari */ -} - -.plugin-root { - min-width: 260px; - display: flex; - flex-direction: column; - justify-content: flex-start; - align-items: stretch; -} - -#classDisplay { - height: 100%; - width: 100%; -} - - -.view-content { - margin-bottom: 0; -} - -.substats { - font-size: medium; -} - -ul { - margin: 0; -} - -/* react-tabs internal file :wink: */ -.material-icons { - font-size: 12px !important; - padding-top: 1px; - padding-right: 2px; - -} - -.material-icons.md-18 { font-size: 18px !important; } -.material-icons.md-24 { font-size: 24px !important; } -.material-icons.md-32 { font-size: 32px !important; } -.material-icons.md-48 { font-size: 48px !important; } - - -.react-tabs { - -webkit-tap-highlight-color: transparent; - height: 100%; -} - -.react-tabs__tab-list { - border-bottom: 1px solid #aaa; - margin: 0 0 5px; - padding: 0; -} - -.react-tabs__tab { - display: inline-block; - border: 1px solid transparent; - border-bottom: none; - bottom: -1px; - position: relative; - list-style: none; - padding: 1% 2%; - cursor: pointer; - font-size: medium; -} - -.react-tabs__tab--selected { - background: var(--interactive-accent); - color: white; - border-radius: 5px 5px 0 0; -} - -.react-tabs__tab--disabled { - color: GrayText; - cursor: default; -} - -.react-tabs__tab:focus { - box-shadow: 0 0 5px hsl(208, 99%, 50%); - border-color: hsl(208, 99%, 50%); - outline: none; -} - -.react-tabs__tab:focus:after { - content: ""; - position: absolute; - height: 5px; - left: -4px; - right: -4px; - bottom: -5px; - background: #fff; -} - -.react-tabs__tab-panel { - display: none; - left: 0px; - height: 88%; - /* overflow: scroll; */ -} - -.task-panel { - overflow: scroll; - height: 100%; -} - -.react-tabs__tab-panel--selected { - display: block; -} -ul li:not(.task-list-item)::before { - content: "•"; - color: transparent; - display: inline-block; - width: 1em; - margin-left: -1em; - padding: 0; - font-weight: bold; - text-shadow: 0 0 0.5em transparent; -} - -.task-operation { - align-self: center; - margin: 0; - padding: 0; -} - -.edit-item { - display: flex; - flex-direction: column; - width: 100%; -} - -.edit-button { - display: flex; - flex-direction: row; - justify-content: flex-end; -} - -.task-submit { - display: grid; - grid-template-columns: 10fr 5fr; -} - -.add-task-input { - display: block; - width: 100%; -} - -.task-input-box { - margin-right: 10px; -} - -button { - margin: auto; - margin-bottom: 5px; - white-space: nowrap; - padding: 5px 5px; - margin-right: 0; -} -.cron { - display: inline-grid; - justify-content: center; - text-align: center;; - margin-top: 5px; - margin-left: 10%; - margin-right: 10%; - margin-bottom: 10px; - border-radius: 10px; -} -#cronMessage { - margin: 20px; - margin-bottom: 10px; - color: var(--text-normal) -} -#cronButton { - margin: auto; - margin-bottom: 5px; - white-space: nowrap; - padding: 5px 5px; - background-color: var(--interactive-accent); - margin-right: auto; -} - -.subtask { - display: flex; - flex-direction: row; - font-weight: normal; - font-family: Roboto, sans-serif; - justify-content: flex-start; -} -.emoji { - height: 1em; -} -.description>ul { - list-style-type: disc; - margin-left: 10% !important; -} + +#profile-name { + font-size: x-large; + font-weight: bold; + padding-bottom: 3%; +} +.stats { + padding-bottom: 6px; +} + +.todo-item { + display: flex; + justify-content: flex-start; + align-items: center; + padding: 0px 0px 0; + width: 80%; + border-bottom: 1px solid #cecece; + font-family: Roboto, sans-serif; + font-weight: normal; + font-size: 16px; +} + +.habit-text { + text-align: center !important; + padding: 0px; + width: 80px; + margin-right: 20px; +} + +.habit-plus { + /* background-color: #fff; */ + border: none; + color: white; + padding: 7px 10px; + text-align: center; + text-decoration: none; + font-size: 16px; +} + +.habit-minus { + /* background-color: #fff; */ + /* border-radius: 50%; */ + border: none; + color: white; + padding: 7px 10px; + text-align: center; + text-decoration: none; + font-size: 16px; +} + +.habit-item { + display: flex; + /* justify-content: center; */ + align-content: space-between; + align-items: center; + padding: 0px 0px 0; + width: 100%; + border-bottom: 1px solid #cecece; + font-family: Roboto, sans-serif; + font-weight: 50%; + font-size: 16px; + +} + +input[type=checkbox] { + margin-right: 10px; +} + +input[type=checkbox]:focus { + outline: 0; +} + +.plugin-root { + min-width: 260px; +} + +.substats { + font-size: medium; +} + +/* react-tabs internal file :wink: */ +.material-icons { + font-size: 12px !important; + padding-top: 1px; + padding-right: 2px; + +} + +.material-icons.md-18 { font-size: 18px !important; } +.material-icons.md-24 { font-size: 24px !important; } +.material-icons.md-32 { font-size: 32px !important; } +.material-icons.md-48 { font-size: 48px !important; } + + +.react-tabs { + -webkit-tap-highlight-color: transparent; + +} + +.react-tabs__tab-list { + border-bottom: 1px solid #aaa; + margin: 0 0 10px; + padding: 0; +} + +.react-tabs__tab { + display: inline-block; + border: 1px solid transparent; + border-bottom: none; + bottom: -1px; + position: relative; + list-style: none; + padding: 1% 2%; + cursor: pointer; + font-size: medium; +} + +.react-tabs__tab--selected { + background: var(--interactive-accent); + color: white; + border-radius: 5px 5px 0 0; +} + +.react-tabs__tab--disabled { + color: GrayText; + cursor: default; +} + +.react-tabs__tab:focus { + box-shadow: 0 0 5px hsl(208, 99%, 50%); + border-color: hsl(208, 99%, 50%); + outline: none; +} + +.react-tabs__tab:focus:after { + content: ""; + position: absolute; + height: 5px; + left: -4px; + right: -4px; + bottom: -5px; + background: #fff; +} + +.react-tabs__tab-panel { + display: none; +} + +.react-tabs__tab-panel--selected { + display: block; +} diff --git a/tsconfig.json b/tsconfig.json index c6bbfcb..48f3cf9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,8 +9,6 @@ "noImplicitAny": true, "moduleResolution": "node", "importHelpers": true, - "allowSyntheticDefaultImports": true, - "esModuleInterop": true, "lib": [ "dom", "es5",