Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexanderWillner committed Apr 22, 2020
2 parents e4c11f5 + a699199 commit 984374c
Show file tree
Hide file tree
Showing 17 changed files with 115 additions and 40 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-include appstore/Makefile

VERSION=2.5.0.dev0
VERSION=2.5.0
MAIN=things3_kanban
APP=things3_app
SERVER=things3_api
Expand Down
Binary file modified doc/view-2020-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/view-2020-minutes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/view-2020-stats.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/view-2020-types.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/view-2020-universe.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified doc/view-2020.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 25 additions & 0 deletions resources/chartjs-plugin-labels.min.js

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

3 changes: 1 addition & 2 deletions resources/kanban.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ html,
body {
background: #fff;
border: 0;
font-family: helvetica, arial, sans-serif;
font-family: "SF Pro Display", helvetica, arial, sans-serif;
font-size: 76%;
height: 100%;
margin: 0;
Expand Down Expand Up @@ -126,7 +126,6 @@ body {
background-color: #fff;
border-radius: 3px;
box-shadow: 2px 2px #999;
font-family: Arial, Helvetica, sans-serif;
font-size: 12px;
margin: 15px;
padding: 10px;
Expand Down
1 change: 1 addition & 0 deletions resources/kanban.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
<link rel="shortcut icon" type="image/x-icon" href="favicon.ico">
<script type="text/javascript" src="kanban.js"></script>
<script type="text/javascript" src="chart.bundle.min.js"></script>
<script type="text/javascript" src="chartjs-plugin-labels.min.js"></script>
<title>KanbanView</title>
</head>
<body>
Expand Down
25 changes: 20 additions & 5 deletions resources/kanban.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ var mode = 'task'
function kanbanHide () { document.getElementById('content').style.display = 'none' }
function kanbanShow () { document.getElementById('content').style.display = '' }

const arrSum = arr => arr.reduce((a, b) => a + b, 0)

function kanbanUpdate () {
console.log('Updating kanban...')
view = kanbanUpdate
Expand Down Expand Up @@ -331,8 +333,18 @@ async function statsShowDistribution () { // eslint-disable-line no-unused-vars
})
new Chart(ctx, { // eslint-disable-line no-new
type: 'doughnut',
options: {
plugins: {
labels: {
render: 'percentage',
precision: 0,
position: 'outside',
arc: true
}
}
},
data: {
labels: ['Backlog', 'Upcoming', 'Inbox', 'Today', 'Next'],
labels: [`Backlog (${backlog})`, `Upcoming (${upcoming})`, `Inbox (${inbox})`, `Today (${today})`, `Next (${next})`],
datasets: [
{
label: '# of tasks',
Expand Down Expand Up @@ -506,28 +518,28 @@ async function statsShowHistory () { // eslint-disable-line no-unused-vars
labels: labels,
datasets: [
{
label: 'created',
label: 'created (' + arrSum(created) + ')',
data: created,
backgroundColor: 'rgba(0, 119, 204, 0.5)',
borderColor: 'rgba(0, 119, 204, 1)',
borderWidth: 1
},
{
label: 'completed',
label: 'completed (' + arrSum(completed) + ')',
data: completed,
backgroundColor: 'rgba(0, 204, 119, 0.5)',
borderColor: 'rgba(0, 204, 119, 1)',
borderWidth: 1
},
{
label: 'cancelled',
label: 'cancelled (' + arrSum(cancelled) + ')',
data: cancelled,
backgroundColor: 'rgba(204, 119, 0, 0.5)',
borderColor: 'rgba(204, 119, 0, 1)',
borderWidth: 1
},
{
label: 'trashed',
label: 'trashed (' + arrSum(trashed) + ')',
data: trashed,
backgroundColor: 'rgba(204, 0, 119, 0.5)',
borderColor: 'rgba(204, 0, 119, 1)',
Expand All @@ -536,6 +548,9 @@ async function statsShowHistory () { // eslint-disable-line no-unused-vars
]
},
options: {
plugins: {
labels: false
},
scales: {
xAxes: [
{
Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@
AUTHOR_MAIL = "[email protected]"
DESCRIPTON = "A simple read-only CLI, API and Web Service for Things 3"
URL = "https://github.com/alexanderwillner/kanbanview"
VERSION = "2.5.0.dev0"
VERSION = "2.5.0"
DATA_FILES = [('resources', ["resources/logo.png"]),
('resources', ["resources/logo-dark.png"]),
('resources', ["resources/kanban.js"]),
('resources', ["resources/kanban.css"]),
('resources', ["resources/kanban.html"]),
('resources', ["resources/demo.sqlite3"]),
('resources', ["resources/chart.css"]),
('resources', ["resources/chart.bundle.min.js"])
('resources', ["resources/chart.bundle.min.js"]),
('resources', ["resources/chartjs-plugin-labels.min.js"])
]
OPTIONS = {
'argv_emulation': False,
Expand Down
84 changes: 59 additions & 25 deletions things3/things3.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
__copyright__ = "2020 Alexander Willner"
__credits__ = ["Alexander Willner"]
__license__ = "Apache License 2.0"
__version__ = "2.5.0.dev0"
__version__ = "2.5.0"
__maintainer__ = "Alexander Willner"
__email__ = "[email protected]"
__status__ = "Development"
Expand All @@ -19,30 +19,18 @@
from random import shuffle
from os import environ
import getpass
import configparser
from pathlib import Path


# pylint: disable=R0904
class Things3():
"""Simple read-only API for Things 3."""
# Variables
debug = False
database = None
json = False
filter = ""
tag_waiting = "Waiting" if not environ.get('TAG_WAITING') \
else environ.get('TAG_WAITING')
tag_mit = "MIT" if not environ.get('TAG_MIT') \
else environ.get('TAG_MIT')
tag_cleanup = "Cleanup" if not environ.get('TAG_CLEANUP') \
else environ.get('TAG_CLEANUP')
anonymize = bool(environ.get('ANONYMIZE'))

# Database info
FILE_DB = '/Library/Containers/'\
'com.culturedcode.ThingsMac/Data/Library/'\
'Application Support/Cultured Code/Things/Things.sqlite3'
FILE_SQLITE = '/Users/' + getpass.getuser() + FILE_DB \
if not environ.get('THINGSDB') else environ.get('THINGSDB')

TABLE_TASK = "TMTask"
TABLE_AREA = "TMArea"
Expand Down Expand Up @@ -70,18 +58,57 @@ class Things3():
IS_OPEN = "status = 0"
IS_CANCELLED = "status = 2"
IS_DONE = "status = 3"
RECURRING_IS_NOT_PAUSED = "instanceCreationPaused = 0"
RECURRING_HAS_NEXT_STARTDATE = "nextInstanceStartDate IS NOT NULL"
MODE_TASK = "type = 0"
MODE_PROJECT = "type = 1"

# Variables
debug = False
user = getpass.getuser()
database = f"/Users/{user}/{FILE_DB}"
filter = ""
tag_waiting = "Waiting"
tag_mit = "MIT"
tag_cleanup = "Cleanup"
anonymize = False
config = configparser.ConfigParser()
config.read(str(Path.home()) + '/.kanbanviewrc')

# pylint: disable=R0913
def __init__(self,
database=FILE_SQLITE,
tag_waiting='Waiting',
tag_mit='MIT',
json=False):
self.database = database if database is not None else self.FILE_SQLITE
self.tag_mit = tag_mit
self.tag_waiting = tag_waiting
self.json = json
database=None,
tag_waiting=None,
tag_mit=None,
tag_cleanup=None,
anonymize=None):

cfg = self.get_from_config(self.config, tag_waiting, 'TAG_WAITING')
self.tag_waiting = cfg if cfg else self.tag_waiting

cfg = self.get_from_config(self.config, anonymize, 'ANONYMIZE')
self.anonymize = cfg if cfg else self.anonymize

cfg = self.get_from_config(self.config, tag_mit, 'TAG_MIT')
self.tag_mit = cfg if cfg else self.tag_mit

cfg = self.get_from_config(self.config, tag_cleanup, 'TAG_CLEANUP')
self.tag_cleanup = cfg if cfg else self.tag_cleanup

cfg = self.get_from_config(self.config, database, 'THINGSDB')
self.database = cfg if cfg else self.database

@staticmethod
def get_from_config(config, variable, preference):
"""Set variable. Priority: input, environment, config"""
result = None
if variable is not None:
result = variable
elif environ.get(preference):
result = environ.get(preference)
elif 'DATABASE' in config and preference in config['DATABASE']:
result = config['DATABASE'][preference]
return result

@staticmethod
def anonymize_string(string):
Expand Down Expand Up @@ -387,7 +414,7 @@ def get_empty_projects(self):
TASK.{self.IS_NOT_TRASHED} AND
TASK.{self.IS_OPEN} AND
TASK.{self.IS_PROJECT} AND
(TASK.{self.IS_ANYTIME} OR TASK.{self.IS_SCHEDULED})
TASK.{self.IS_ANYTIME}
GROUP BY TASK.uuid
HAVING
(SELECT COUNT(uuid)
Expand All @@ -396,7 +423,13 @@ def get_empty_projects(self):
PROJECT_TASK.project = TASK.uuid AND
PROJECT_TASK.{self.IS_NOT_TRASHED} AND
PROJECT_TASK.{self.IS_OPEN} AND
PROJECT_TASK.{self.IS_ANYTIME}
(PROJECT_TASK.{self.IS_ANYTIME} OR
PROJECT_TASK.{self.IS_SCHEDULED} OR
(PROJECT_TASK.{self.IS_RECURRING} AND
PROJECT_TASK.{self.RECURRING_IS_NOT_PAUSED} AND
PROJECT_TASK.{self.RECURRING_HAS_NEXT_STARTDATE}
)
)
) = 0
"""
return self.get_rows(query)
Expand Down Expand Up @@ -525,6 +558,7 @@ def get_cleanup(self):
result.extend(self.get_lint())
result.extend(self.get_empty_projects())
result.extend(self.get_tag(self.tag_cleanup))
result = [i for n, i in enumerate(result) if i not in result[n + 1:]]
return result

@staticmethod
Expand Down
2 changes: 1 addition & 1 deletion things3/things3_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
__copyright__ = "Copyright 2020 Alexander Willner"
__credits__ = ["Alexander Willner"]
__license__ = "Apache License 2.0"
__version__ = "2.5.0.dev0"
__version__ = "2.5.0"
__maintainer__ = "Alexander Willner"
__email__ = "[email protected]"
__status__ = "Development"
Expand Down
2 changes: 1 addition & 1 deletion things3/things3_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
__copyright__ = "Copyright 2020 Alexander Willner"
__credits__ = ["Luc Beaulieu", "Alexander Willner"]
__license__ = "Apache License 2.0"
__version__ = "2.5.0.dev0"
__version__ = "2.5.0"
__maintainer__ = "Alexander Willner"
__email__ = "[email protected]"
__status__ = "Development"
Expand Down
2 changes: 1 addition & 1 deletion things3/things3_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
__copyright__ = "2020 Alexander Willner"
__credits__ = ["Alexander Willner"]
__license__ = "Apache License 2.0"
__version__ = "2.5.0.dev0"
__version__ = "2.5.0"
__maintainer__ = "Alexander Willner"
__email__ = "[email protected]"
__status__ = "Development"
Expand Down
4 changes: 2 additions & 2 deletions things3/things3_kanban.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
__copyright__ = "Copyright 2020 Alexander Willner"
__credits__ = ["Luc Beaulieu", "Alexander Willner"]
__license__ = "Apache License 2.0"
__version__ = "2.5.0.dev0"
__version__ = "2.5.0"
__maintainer__ = "Alexander Willner"
__email__ = "[email protected]"
__status__ = "Development"
Expand All @@ -28,7 +28,7 @@ def write_html_column(cssclass, file, header, rows):
"""Create a column in the output."""

file.write("<div class='column'><div class=''>" +
"<h2 class='" + cssclass + "'>" + header +
"<h2 class='h2 " + cssclass + "'>" + header +
"<span class='size'>" + str(len(rows)) +
"</span></h2>")

Expand Down

0 comments on commit 984374c

Please sign in to comment.