Commit dc2cf095 authored by 20after4's avatar 20after4
Browse files

Move charts to separate yaml files and queries to separate sql files

parent 3ac87d43
This diff is collapsed.
...@@ -194,10 +194,13 @@ def map( ...@@ -194,10 +194,13 @@ def map(
else: else:
res = db.conn.execute('select after_id from conduit_cursor where name=:name', {"name": cursor_id}) res = db.conn.execute('select after_id from conduit_cursor where name=:name', {"name": cursor_id})
row = res.fetchone() row = res.fetchone()
after = row[0] if row and len(row):
after = row[0]
else:
after = 0
if after: if after:
arg['after'] = after arg['after'] = after
console.log('resuming after task id '+str(after)) console.log(f'Resuming after task id [bold blue]T{after}[/bold blue]')
r = phab.request("maniphest.search", arg) r = phab.request("maniphest.search", arg)
while len(r.data): while len(r.data):
task = r.data.popleft() task = r.data.popleft()
...@@ -205,15 +208,17 @@ def map( ...@@ -205,15 +208,17 @@ def map(
task.save() task.save()
if pages and pages > 1 and len(r.data) < 1: if pages and pages > 1 and len(r.data) < 1:
pages -= 1 pages -= 1
console.log("Fetching next page", r.cursor) # console.log("Fetching next page")
cursor_after = r.cursor.get("after", None) cursor_after = r.cursor.get("after", None)
if cursor_after: if cursor_after:
status.update(f'Fetching tasks after [bold blue]T{cursor_after}[/bold blue]. [bold blue]{pages}[/bold blue] pages remaining.')
r.next_page() r.next_page()
if cursor_id: if cursor_id:
cursor_after = r.cursor.get("after", None) cursor_after = r.cursor.get("after", None)
db.conn.execute(f'REPLACE INTO conduit_cursor values (?,?)', (cursor_id, cursor_after)) db.conn.execute(f'REPLACE INTO conduit_cursor values (?,?)', (cursor_id, cursor_after))
# status.update(f"Saved cursor position at [bold blue]{cursor_after}[/bold blue]")
else: else:
console.log("No more pages to fetch") status.update("Done")
if project_phid: if project_phid:
console.log( console.log(
...@@ -228,6 +233,7 @@ def map( ...@@ -228,6 +233,7 @@ def map(
) )
transactions = r.result transactions = r.result
elif task_ids: elif task_ids:
status.update('Fetching Transactions')
console.log( console.log(
f"Fetching transactions for [bold blue]{len(task_ids)}[/bold blue] tasks." f"Fetching transactions for [bold blue]{len(task_ids)}[/bold blue] tasks."
) )
...@@ -322,10 +328,10 @@ def load_data_with_progress( ...@@ -322,10 +328,10 @@ def load_data_with_progress(
cursor = conn.executemany(sql, chunk) cursor = conn.executemany(sql, chunk)
count += cursor.rowcount count += cursor.rowcount
sts.update( sts.update(
f"Updating [bold green]({count}/{total})[/bold green] {table_name}" f"Updating {table_name} [bold green]({count}/{total})[/bold green]"
) )
console.log( console.log(
f"Inserted [bold green]{count}/[/bold green] into {table_name} rows." f"Inserted [bold green]{count}[/bold green] rows into {table_name}."
) )
......
...@@ -9,9 +9,8 @@ plugins: ...@@ -9,9 +9,8 @@ plugins:
title: Project Metrics title: Project Metrics
description: "" description: ""
tabs: tabs:
projects: Phabricator Projects charts: Charts
columns: Columns & Milestones cycle: Report
cycle: "Lead & Cycle Time"
placeholder_text: placeholder_text:
To get started, please enter a project name or task ID at the top of the page. To get started, please enter a project name or task ID at the top of the page.
filters: filters:
...@@ -35,7 +34,7 @@ plugins: ...@@ -35,7 +34,7 @@ plugins:
task-details: task-details:
title: Task details title: Task details
db: metrics db: metrics
tab: task tab: charts
requires: task_id requires: task_id
query: task_details query: task_details
library: jinja library: jinja
...@@ -43,7 +42,7 @@ plugins: ...@@ -43,7 +42,7 @@ plugins:
task-projects: task-projects:
title: Task projects title: Task projects
db: metrics db: metrics
tab: task tab: charts
requires: task_id requires: task_id
query: task_projects query: task_projects
library: jinja library: jinja
...@@ -51,7 +50,7 @@ plugins: ...@@ -51,7 +50,7 @@ plugins:
task-users: task-users:
title: Task users title: Task users
db: metrics db: metrics
tab: task tab: charts
requires: task_id requires: task_id
query: task_users query: task_users
library: jinja library: jinja
...@@ -63,11 +62,11 @@ plugins: ...@@ -63,11 +62,11 @@ plugins:
library: jinja library: jinja
template: task_days_in_project.html template: task_days_in_project.html
requires: [ task_id, project ] requires: [ task_id, project ]
tab: task tab: charts
task-days-in-columns: task-days-in-columns:
title: Days in project columns title: Days in project columns
db: metrics db: metrics
tab: task tab: charts
requires: [ task_id, project ] requires: [ task_id, project ]
query: select *, next_ts - ts as duration, printf('%.0f', ((next_ts - ts) / 86400.0)) AS duration_days from (select events.*, columns.column_name, columns.project_name, columns.is_default, ifnull(LEAD(ts) OVER(ORDER BY ts), strftime('%s','now', 'localtime')) next_ts from events join columns on new = column_phid where new like '%PHID-PCOL-%' and task = :task_id and event = 'columns' and project_phid = :project order by ts); query: select *, next_ts - ts as duration, printf('%.0f', ((next_ts - ts) / 86400.0)) AS duration_days from (select events.*, columns.column_name, columns.project_name, columns.is_default, ifnull(LEAD(ts) OVER(ORDER BY ts), strftime('%s','now', 'localtime')) next_ts from events join columns on new = column_phid where new like '%PHID-PCOL-%' and task = :task_id and event = 'columns' and project_phid = :project order by ts);
library: vega library: vega
...@@ -78,24 +77,59 @@ plugins: ...@@ -78,24 +77,59 @@ plugins:
y: { field: column_name, type: nominal, title: 'Column' } y: { field: column_name, type: nominal, title: 'Column' }
databases: databases:
metrics: metrics:
tables: tables:
conduit_cursor:
description_html: |-
Each row in the cursors table is used to keep track of the last ID encountered when paging through conduit API responses.
When fetching the next page of results, we pass this ID as the 'after' argument to tell phabricator where the next page will begin.
Pagination enables us to transfer large amounts of data without overloading the server or exceeding request time limits.
phobjects: phobjects:
label_column: "name" label_column: "name"
description_html: |-
The name, url and basic metadata of every known phabricator object. Used mostly to look up the names of users, projects and columns efficiently. Especially convenient because you can join on the phid field even when you have multiple different PHID types to resolve.
Project: Project:
label_column: "name" label_column: "name"
description_html: |-
Bulk phabricator project data.
ProjectColumn: ProjectColumn:
label_column: "name" label_column: "name"
Task: Task:
label_column: "name" label_column: "name"
description_html: |-
The bulk phabricator task metadata as extracted from th maniphest.search api
Columns:
description_html: |-
Every column from every workboard, including archived projects and hidden columns.
column_metrics:
description_html: |-
This table organizes phabricator task data by the projects and workboard columns.
This is sometimes more useful when building a project-centric or milestone-centric
view of phabricator activity.
columns:
ts: unix epoch timestamp when the activity occurred.
project: This is either a project PHID, or one of 'global', empty for the events which do not belong to a project context.
column: either a column PHID or empty when the event is unrelated to a column or workboard.
task: the task id
type: the type of activity, for example, 'assign', 'mention-this', 'status'
value: eitehr +1 or -1, representing whether the given status was added or removed from the task
task_metrics:
description_html: |-
This table represents every state change that was
recorded on each phabricator task in the index. The data is organized by
"metric" and "state" where metric is the category and state is the value.
There are begining and ending timestamps, as well as a duration for each state.
units:
duration: day
columns:
task: Phabricator task that this metric applies to.
metric: The type or category of the state transition represented.
state: The specific value of the metric during this time period.
ts: The unix epoch timestamp when this state begins.
ts2: The unix epoch timestamp when this state ends.
duration: The number of days elapsed between ts and ts2.
queries: queries:
column_events: column_events:
title: Column movement events. title: Column movement events.
......
...@@ -64,6 +64,12 @@ async def ddd_view(datasette:Datasette, request, scope, send, receive): ...@@ -64,6 +64,12 @@ async def ddd_view(datasette:Datasette, request, scope, send, receive):
_models = {} _models = {}
page:str = request.url_vars["page"] page:str = request.url_vars["page"]
response_format = 'html'
if page.endswith('.json'):
page = page[:-5]
response_format = 'json'
views_path = Path(__file__).parent.parent / "templates" / "views" views_path = Path(__file__).parent.parent / "templates" / "views"
if page not in _models: if page not in _models:
model_page = page + '.py' model_page = page + '.py'
...@@ -86,6 +92,7 @@ async def ddd_view(datasette:Datasette, request, scope, send, receive): ...@@ -86,6 +92,7 @@ async def ddd_view(datasette:Datasette, request, scope, send, receive):
db = datasette.get_database('metrics') db = datasette.get_database('metrics')
context = { context = {
"response_format": response_format,
"base_url": datasette.urls.path('/'), "base_url": datasette.urls.path('/'),
"views_path": views_path, "views_path": views_path,
"console": console, "console": console,
...@@ -101,7 +108,7 @@ async def ddd_view(datasette:Datasette, request, scope, send, receive): ...@@ -101,7 +108,7 @@ async def ddd_view(datasette:Datasette, request, scope, send, receive):
if ('template_name' in context): if ('template_name' in context):
template_name = context['template_name'] template_name = context['template_name']
else: else:
template_name = f"views/{page}.html" template_name = f"views/{page}.{response_format}"
console.log('template name: ',template_name) console.log('template name: ',template_name)
try: try:
output = await datasette.render_template(template_name, context, request, page) output = await datasette.render_template(template_name, context, request, page)
...@@ -121,7 +128,7 @@ def register_routes(): ...@@ -121,7 +128,7 @@ def register_routes():
return prefix + "/".join(parts) + "/?$" return prefix + "/".join(parts) + "/?$"
def v(name): def v(name):
"""Compose regex fragment that captures one path level as a named variable""" """Compose regex fragment that captures one path level as a named variable"""
return f"(?P<{name}>[a-zA-Z0-9\\-]+)" return f"(?P<{name}>[a-zA-Z0-9\\-_]+(\\.json)?)"
def optional(part): def optional(part):
"""Mark a path segment as optional by wrapping it with ()?""" """Mark a path segment as optional by wrapping it with ()?"""
return f"?({part})?" return f"?({part})?"
......
...@@ -110,6 +110,8 @@ def extra_template_vars(datasette): ...@@ -110,6 +110,8 @@ def extra_template_vars(datasette):
def render_cell( def render_cell(
value, column: str, table: Union[str, None], database: str, datasette: Datasette value, column: str, table: Union[str, None], database: str, datasette: Datasette
) -> Union[str, None]: ) -> Union[str, None]:
if column == 'duration':
return str(int(int(value) / (60*60*24)))
if isinstance(value, int): if isinstance(value, int):
value = str(value) value = str(value)
if isinstance(value, bytes): if isinstance(value, bytes):
...@@ -122,6 +124,7 @@ def render_cell( ...@@ -122,6 +124,7 @@ def render_cell(
value = value.strip() value = value.strip()
if ( column in ['tid', 'task'] ): if ( column in ['tid', 'task'] ):
if value[0] == 'T' and value[1:].isdigit(): if value[0] == 'T' and value[1:].isdigit():
value = value[1:] value = value[1:]
......
...@@ -4,7 +4,8 @@ SELECT ...@@ -4,7 +4,8 @@ SELECT
ph.phid AS state_phid, ph.phid AS state_phid,
w.date AS week, w.date AS week,
max(date(m.ts, 'unixepoch')) AS ts, max(date(m.ts, 'unixepoch')) AS ts,
max(date(m.ts2, 'unixepoch')) AS ts2 max(date(m.ts2, 'unixepoch')) AS ts2,
group_concat(task) as task
FROM FROM
task_metrics m task_metrics m
JOIN enabled_columns_and_milestones ph ON (m.state = ph.phid) JOIN enabled_columns_and_milestones ph ON (m.state = ph.phid)
......
SELECT SELECT
MONTH, month,
column_name, column_name,
sum(value) AS total_tasks column_phid,
sum(value) AS total_tasks,
CASE WHEN value > 0 THEN 'added' ELSE 'removed' END as action
FROM FROM
( (
SELECT SELECT
printf('T%u', c.task) AS task, printf('T%u', c.task) AS task,
datetime(c.ts, 'unixepoch') AS ts, datetime(c.ts, 'unixepoch') AS ts,
date(c.ts, 'unixepoch', 'start of month') AS MONTH, date(c.ts, 'unixepoch', 'start of month') AS month,
date( date(
c.ts, c.ts,
'unixepoch', 'unixepoch',
...@@ -17,13 +19,11 @@ FROM ...@@ -17,13 +19,11 @@ FROM
p.column_name AS column_name, p.column_name AS column_name,
p.project_phid AS project_phid, p.project_phid AS project_phid,
p.project_name AS project_name, p.project_name AS project_name,
p.project_name || ':' || p.column_name AS qualified_name,
p.status AS column_hidden, p.status AS column_hidden,
c.value AS value c.value AS value
FROM FROM
column_metrics c column_metrics c
JOIN COLUMNS p ON c.column = p.column_phid JOIN COLUMNS p ON c.column = p.column_phid
AND column_phid = :column
WHERE WHERE
project_phid = :project project_phid = :project
ORDER BY ORDER BY
...@@ -35,5 +35,6 @@ WHERE ...@@ -35,5 +35,6 @@ WHERE
AND ts >= date(:date_start) AND ts >= date(:date_start)
AND ts <= date(:date_end) AND ts <= date(:date_end)
GROUP BY GROUP BY
MONTH, month,
column_phid column_phid,
\ No newline at end of file action
\ No newline at end of file
SELECT SELECT
date(ts, 'unixepoch') AS DAY, date(ts, 'unixepoch') AS DAY,
date(ts, 'unixepoch', 'start of month') AS month, date(ts, 'unixepoch', 'start of month') AS month,
task,
project, project,
user, user,
event, event,
......
...@@ -3,6 +3,7 @@ SELECT ...@@ -3,6 +3,7 @@ SELECT
date(ts, 'unixepoch') AS day, date(ts, 'unixepoch') AS day,
date(ts, 'unixepoch', 'start of month') AS month, date(ts, 'unixepoch', 'start of month') AS month,
count(task) AS count, count(task) AS count,
group_concat(task) as task,
c.name AS old, c.name AS old,
n.name AS new, n.name AS new,
c.phid || ':' || n.phid as phids, c.phid || ':' || n.phid as phids,
......
...@@ -6,7 +6,7 @@ import { InputFilter, DaterangeFilter, NavTabs, TabItem, AutocompleteFilter } fr ...@@ -6,7 +6,7 @@ import { InputFilter, DaterangeFilter, NavTabs, TabItem, AutocompleteFilter } fr
import { VegaChart } from './vega-tonic.js' import { VegaChart } from './vega-tonic.js'
import {DependableComponent, Query} from "./dom.js" import {DependableComponent, Query} from "./dom.js"
import { DateTime } from "luxon"; import { DateTime } from "luxon";
import { ModalDialog} from "./ui.js" import { TaskDialog} from "./ui.js"
function initApp() { function initApp() {
if (window['BASE_URL']) if (window['BASE_URL'])
...@@ -22,7 +22,7 @@ function initApp() { ...@@ -22,7 +22,7 @@ function initApp() {
Tonic.add(DashboardApp); Tonic.add(DashboardApp);
initDataSets(); initDataSets();
const app = <DashboardApp> <unknown>document.getElementsByTagName('dashboard-app')[0]; const app = <DashboardApp> <unknown>document.getElementsByTagName('dashboard-app')[0];
console.log(TaskDialog);
console.log('---------------- init ----------------') console.log('---------------- init ----------------')
} }
......
This diff is collapsed.
...@@ -486,6 +486,14 @@ class DaterangeFilter extends InputFilter { ...@@ -486,6 +486,14 @@ class DaterangeFilter extends InputFilter {
render() { render() {
const id = this.id; const id = this.id;
const dt = DateTime.now(); const dt = DateTime.now();
var fs, fe;
if (dt.month < 6) {
fe = dt.set({month: 6}).endOf('month');
fs = fe.minus({years: 1}).set({month:7, day:1});
} else {
fs = dt.set({month: 7, day: 1, hour: 0});
fe = fs.plus({years: 1}).minus({days: 1});
}
const yr = dt.startOf('year'); const yr = dt.startOf('year');
const qt = dt.startOf('quarter'); const qt = dt.startOf('quarter');
const pq = qt.minus({months: 3}); const pq = qt.minus({months: 3});
...@@ -500,6 +508,7 @@ class DaterangeFilter extends InputFilter { ...@@ -500,6 +508,7 @@ class DaterangeFilter extends InputFilter {
<li><a class="dropdown-item" href="#date_start=${qt.toISODate()}&date_end=${qt.endOf('quarter').toISODate()}">This Quarter ${qt.toISODate()}</a></li> <li><a class="dropdown-item" href="#date_start=${qt.toISODate()}&date_end=${qt.endOf('quarter').toISODate()}">This Quarter ${qt.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${pq.toISODate()}&date_end=${pq.endOf('quarter').toISODate()}">Last Quarter ${pq.toISODate()}</a></li> <li><a class="dropdown-item" href="#date_start=${pq.toISODate()}&date_end=${pq.endOf('quarter').toISODate()}">Last Quarter ${pq.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${yr.toISODate()}&date_end=${dt.endOf('year').toISODate()}">This Year ${yr.toISODate()}</a></li> <li><a class="dropdown-item" href="#date_start=${yr.toISODate()}&date_end=${dt.endOf('year').toISODate()}">This Year ${yr.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${fs.toISODate()}&date_end=${fe.toISODate()}">Fiscal Year ${fs.year.toString()}:${fe.year.toString()}</a></li>
</ul> </ul>
</div> </div>
<!--<span class="input-group-text">From:</span>--> <!--<span class="input-group-text">From:</span>-->
......
...@@ -6,6 +6,7 @@ import { InputFilter, DaterangeFilter, AutocompleteFilter } from './filter-input ...@@ -6,6 +6,7 @@ import { InputFilter, DaterangeFilter, AutocompleteFilter } from './filter-input
import { VegaChart } from './vega-tonic.js'; import { VegaChart } from './vega-tonic.js';
import { DependableComponent, Query } from "./dom.js"; import { DependableComponent, Query } from "./dom.js";
import { DateTime } from "luxon"; import { DateTime } from "luxon";
import { TaskDialog } from "./ui.js";
function initApp() { function initApp() {
if (window['BASE_URL']) if (window['BASE_URL'])
DependableComponent._base_url = window['BASE_URL']; DependableComponent._base_url = window['BASE_URL'];
...@@ -19,6 +20,7 @@ function initApp() { ...@@ -19,6 +20,7 @@ function initApp() {
Tonic.add(DashboardApp); Tonic.add(DashboardApp);
initDataSets(); initDataSets();
const app = document.getElementsByTagName('dashboard-app')[0]; const app = document.getElementsByTagName('dashboard-app')[0];
console.log(TaskDialog);
console.log('---------------- init ----------------'); console.log('---------------- init ----------------');
} }
class DashboardApp extends DependableComponent { class DashboardApp extends DependableComponent {
......
{"version":3,"file":"DashboardApp.js","sourceRoot":"","sources":["../DashboardApp.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,mBAAmB,CAAC;AACtC,OAAO,EAAC,SAAS,EAAC,MAAM,gBAAgB,CAAA;AACxC,OAAO,WAAW,MAAM,gCAAgC,CAAA;AACxD,OAAO,EAAoC,YAAY,EAAC,MAAM,iBAAiB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,eAAe,EAAoB,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvG,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAC,mBAAmB,EAAE,KAAK,EAAC,MAAM,UAAU,CAAA;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGjC,SAAS,OAAO;IACd,IAAI,MAAM,CAAC,UAAU,CAAC;QACpB,mBAAmB,CAAC,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACrD,YAAY,EAAE,CAAC;IACf,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACrB,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IACnD,KAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;IAC9B,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACvB,KAAK,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;IAC3B,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IAErB,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACxB,YAAY,EAAE,CAAC;IACf,MAAM,GAAG,GAA2B,QAAQ,CAAC,oBAAoB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IAGtF,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAA;AACvD,CAAC;AAGD,MAAM,YAAa,SAAQ,mBAAmB;IAK5C;QACE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;QAG1B,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAE7C,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QACxC,IAAI,CAAC,cAAc,GAAG,CAAC,CAAC,EAAE,EAAE;YAC1B,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACjB,CAAC,CAAA;QACD,IAAI,CAAC,gBAAgB,GAAG,CAAC,CAAC,EAAE,EAAE;YAC5B,MAAM,CAAC,UAAU,CAAC,GAAG,EAAE;gBACrB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACnB,CAAC,EAAE,CAAC,CAAC,CAAC;QACR,CAAC,CAAA;QACD,IAAI,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC;QACrD,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC3D,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE1B,MAAM,MAAM,GAAG,CAAC,KAAM,EAAE,EAAE;YACtB,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;YAC9B,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,gBAAgB,CAAC,YAAY,CAAC,EAAE;gBAC1D,KAA8B,CAAC,UAAU,EAAE,CAAC;aAC9C;YACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrC,CAAC,CAAC;QACF,IAAI,QAAQ,CAAC,UAAU,KAAK,SAAS,EAAE,EAAG,8BAA8B;YACtE,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,MAAM,CAAC,CAAC;SACvD;aAAM,EAAG,uCAAuC;YAC/C,MAAM,EAAE,CAAC;SACV;IACH,CAAC;IAED,sBAAsB;QACpB,IAAI,IAAI,CAAC,KAAK,CAAC,YAAY,EAAE;YAC3B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,gBAAgB,CAAC,kBAAkB,CAAqB,EAAE;gBAC/E,GAAG,CAAC,YAAY,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;aACvD;SACF;QACD,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,CAAC;QACN,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAC;YAClB,OAAO;SACR;QAED,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAC3C,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,sBAAsB,EAAE,CAAC;IAChC,CAAC;IAED,QAAQ,CAAC,CAAC;QACR,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAC1B,IAAI,CAAC,CAAC,KAAK,EAAE;YACX,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;YAClC,IAAI,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC;YACrB,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC;YAC3B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACvB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;SACvB;IACH,CAAC;IAED,QAAQ,CAAC,KAAK,GAAC,IAAI;QACjB,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QACxB,gCAAgC;QAChC,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAyB,EAAE;YAC1E,OAAO,CAAC,GAAG,CAAC,UAAU,EAAC,GAAG,EAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SAC1B;IACH,CAAC;IAED,MAAM,CAAC,CAAE;QACP,yBAAyB;QACzB,IAAI,CAAC,EAAE;YACL,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,CAAC,CAAC,eAAe,EAAE,CAAC;SACrB;QACD,KAAK,IAAI,KAAK,IAAI,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAyB,EAAE;YAC1E,IAAI,KAAK,CAAC,aAAa,CAAC,EAAE;gBACxB,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;aAC/B;SACF;QAED,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;QAEjD,MAAM,WAAW,GAAoB,IAAI,GAAG,EAAE,CAAC;QAC/C,KAAK,MAAM,CAAC,IAAI,aAAa,EAAE;YAC7B,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,sBAAsB,CAAqB,EAAE;gBACrG,GAAG,CAAC,YAAY,CAAC,CAAC,EAAE,aAAa,CAAC,CAAC;gBACnC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;aACtB;SACF;QAED,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAE3E,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE;YAC7B,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;YAC5B,GAAG,CAAC,QAAQ,EAAE,CAAC;SAChB;QAED,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACjC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,GAAO;QACvB,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QAEhC,8DAA8D;QAC9D,0CAA0C;QAC1C,mBAAmB;QACnB,IAAI;QAEJ,IAAI,SAAS,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,SAAS,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,0BAA0B,EAAE,YAAY,CAAC,CAAA;QACnF,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;QACzC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE;YAC3B,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;YAChD,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,IAAI,CAAC,SAAS,GAAC,IAAI,CAAC;YACpB,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,iBAAiB,CAAC,CAAC;YAC9D,MAAM,OAAO,GAAG,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACjD,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;SAClC;IACH,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,IAAI,CAAA;MACd,IAAI,CAAC,QAAQ;KACd,CAAC;IACJ,CAAC;CACF;AAID,OAAO,EAAE,CAAC;AAGV,OAAO,EAAC,YAAY,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAC,CAAC;AACnE,eAAe,YAAY,CAAC"} {"version":3,"file":"DashboardApp.js","sourceRoot":"","sources":["../DashboardApp.ts"],"names":[],"mappings":"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"}
\ No newline at end of file \ No newline at end of file
...@@ -447,6 +447,15 @@ class DaterangeFilter extends InputFilter { ...@@ -447,6 +447,15 @@ class DaterangeFilter extends InputFilter {
render() { render() {
const id = this.id; const id = this.id;
const dt = DateTime.now(); const dt = DateTime.now();
var fs, fe;
if (dt.month < 6) {
fe = dt.set({ month: 6 }).endOf('month');
fs = fe.minus({ years: 1 }).set({ month: 7, day: 1 });
}
else {
fs = dt.set({ month: 7, day: 1, hour: 0 });
fe = fs.plus({ years: 1 }).minus({ days: 1 });
}
const yr = dt.startOf('year'); const yr = dt.startOf('year');
const qt = dt.startOf('quarter'); const qt = dt.startOf('quarter');
const pq = qt.minus({ months: 3 }); const pq = qt.minus({ months: 3 });
...@@ -461,6 +470,7 @@ class DaterangeFilter extends InputFilter { ...@@ -461,6 +470,7 @@ class DaterangeFilter extends InputFilter {
<li><a class="dropdown-item" href="#date_start=${qt.toISODate()}&date_end=${qt.endOf('quarter').toISODate()}">This Quarter ${qt.toISODate()}</a></li> <li><a class="dropdown-item" href="#date_start=${qt.toISODate()}&date_end=${qt.endOf('quarter').toISODate()}">This Quarter ${qt.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${pq.toISODate()}&date_end=${pq.endOf('quarter').toISODate()}">Last Quarter ${pq.toISODate()}</a></li> <li><a class="dropdown-item" href="#date_start=${pq.toISODate()}&date_end=${pq.endOf('quarter').toISODate()}">Last Quarter ${pq.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${yr.toISODate()}&date_end=${dt.endOf('year').toISODate()}">This Year ${yr.toISODate()}</a></li> <li><a class="dropdown-item" href="#date_start=${yr.toISODate()}&date_end=${dt.endOf('year').toISODate()}">This Year ${yr.toISODate()}</a></li>
<li><a class="dropdown-item" href="#date_start=${fs.toISODate()}&date_end=${fe.toISODate()}">Fiscal Year ${fs.year.toString()}:${fe.year.toString()}</a></li>
</ul> </ul>
</div> </div>
<!--<span class="input-group-text">From:</span>--> <!--<span class="input-group-text">From:</span>-->
......
This diff is collapsed.
...@@ -11,6 +11,7 @@ class ModalDialog extends DependableComponent { ...@@ -11,6 +11,7 @@ class ModalDialog extends DependableComponent {
<h5 id="modal-${this.id}-title">${this.props.title}</h5> <h5 id="modal-${this.id}-title">${this.props.title}</h5>
</div> </div>
<div class="modal-body"> <div class="modal-body">
${this.renderBody()}
${this.elements} ${this.elements}
</div> </div>
</div> </div>
...@@ -18,10 +19,48 @@ class ModalDialog extends DependableComponent { ...@@ -18,10 +19,48 @@ class ModalDialog extends DependableComponent {
</div>