blob: 98021ca860ac19c665a358f6416bf484f642573e [file] [log] [blame]
/**
* @module modules/domain-picker-sk
* @description <h2><code>domain-picker-sk</code></h2>
*
* Allows picking either a date range for commits, or for
* picking a number of commits to show before a selected
* date.
*
* @attr {string} force_request_type - A value of 'dense' or 'range' will
* force the corresponding request_type to be always set.
*
* @evt domain-changed - The event detail.state will contain the updated 'state'.
*
*/
import { define } from 'elements-sk/define'
import { html, render } from 'lit-html'
import { ElementSk } from '../../../infra-sk/modules/ElementSk'
import dialogPolyfill from 'dialog-polyfill'
import 'elements-sk/radio-sk';
import 'elix/src/DateComboBox.js'
import 'elements-sk/styles/buttons'
const RANGE = 0;
const DENSE = 1;
const _description = (ele) => {
const begin = new Date(ele._stateBackup.begin*1000);
const end = new Date(ele._stateBackup.end*1000);
if (ele._stateBackup.request_type === RANGE) {
return `${begin.toLocaleDateString()} - ${end.toLocaleDateString()}`;
} else {
return `${ele._stateBackup.num_commits} commits ending at ${end.toLocaleDateString()}`;
}
}
const _toDate = (seconds) => {
return new Date(seconds*1000);
};
const _request_type = (ele) => {
if (ele._state.request_type === RANGE) {
return html`
<p>Display all points in the date range.</p>
<label>
<span>Begin:</span>
<elix-date-combo-box @date-changed=${ele._beginChange} date=${_toDate(ele._state.begin)}></elix-date-combo-box>
</label>
`;
} else {
return html`
<p>Display only the points that have data before the date.</p>
<label>
<span>Number of points</span>
<input @change=${ele._numChanged} type=number .value='${ele._state.num_commits}' min=1 max=5000 list=defaultNumbers>
</label>
<datalist id=defaultNumbers>
<option value=50>
<option value=100>
<option value=250>
<option value=500>
</datalist>
`;
}
};
const _showRadio = (ele) => {
if (!ele.force_request_type) {
return html`
<radiogroup>
<radio-sk @change=${ele._typeRange} ?checked=${ele._state.request_type === RANGE} label="Date Range"></radio-sk>
<radio-sk @change=${ele._typeDense} ?checked=${ele._state.request_type === DENSE} label="Dense" ></radio-sk>
</radiogroup>
`;
} else {
return html``;
}
};
const template = (ele) => html`
<dialog>
<h2>Graph Domain</h2>
${_showRadio(ele)}
<div class=ranges>
${_request_type(ele)}
<label>
<span>End:</span>
<elix-date-combo-box @date-changed=${ele._endChange} date=${_toDate(ele._state.end)}></elix-date-combo-box>
</label>
</div>
<div class=controls>
<button @click=${ele._cancel}>Cancel</button>
<button @click=${ele._ok} ?disabled=${ele._isInvalid(ele)}>OK</button>
</div>
</dialog>
<button class=description @click=${ele._edit}>${_description(ele)}</button>
`;
define('domain-picker-sk', class extends ElementSk {
constructor() {
super(template);
const now = Date.now();
// See the 'state' property setters below for the shape of this._state.
this._state = {
begin: Math.floor(now/1000 - 24*60*60),
end: Math.floor(now/1000),
num_commits: 50,
request_type: RANGE,
};
this._stateBackup = Object.assign({}, this._state);
this._description = '';
}
connectedCallback() {
super.connectedCallback();
this._render();
this._dialog = this.querySelector('dialog');
dialogPolyfill.registerDialog(this._dialog);
}
_typeRange() {
this._state.request_type = RANGE;
this._render();
}
_typeDense() {
this._state.request_type = DENSE;
this._render();
}
_ok() {
this._stateBackup = Object.assign({}, this._state);
this._dialog.close();
const detail = {
state: this._state,
}
this.dispatchEvent(new CustomEvent('domain-changed', {detail: detail, bubbles: true}));
this._render();
}
_beginChange(e) {
this._state.begin = Math.floor(e.detail.date/1000);
this._render();
}
_endChange(e) {
this._state.end = Math.floor(e.detail.date/1000);
this._render();
}
_numChanged(e) {
this._state.num_commits = +e.srcElement.value;
this._render();
}
_edit() {
this._dialog.showModal();
}
_cancel() {
this._state = Object.assign({}, this._stateBackup);
this._render();
this._dialog.close();
}
_isInvalid() {
if (this._state.request_type === RANGE && (this._state.end < this._state.begin)) {
return true;
}
return false;
}
static get observedAttributes() {
return ['force_request_type'];
}
/** @prop state {Object} An object that contains the following state:
*
* {
* begin: // unix timestamp in seconds.
* end: // unix timestamp in seconds.
* num_commits: // Number of commits.
* request_type: // 0 for date range, 1 for dense. See dataframe.RequestType.
* }
*/
get state() { return this._stateBackup }
set state(val) {
if (!val) {
return;
}
this._state = val;
this._stateBackup = Object.assign({}, this._state);
this._render();
}
/** @prop force_request_type {string} A value of 'dense' or 'range' will force the corresponding request_type to be always set.
*/
get force_request_type() { return this.getAttribute('force_request_type'); }
set force_request_type(val) { this.setAttribute('force_request_type', val); }
attributeChangedCallback(name, oldValue, newValue) {
this._render();
}
_render() {
if (this.force_request_type === 'dense') {
this._state.request_type = DENSE;
this._stateBackup.request_type = DENSE;
} else if (this.force_request_type === 'range') {
this._state.request_type = RANGE;
this._stateBackup.request_type = RANGE;
}
super._render();
}
});