@teipublisher/pb-components
Version:
Collection of webcomponents underlying TEI Publisher
364 lines (329 loc) • 13.7 kB
JavaScript
import { LitElement, html, css } from 'lit-element';
import '@polymer/paper-dialog';
import '@polymer/paper-dialog-scrollable';
import '@polymer/iron-ajax';
import '@polymer/paper-checkbox';
import '@polymer/paper-button';
import '@polymer/paper-icon-button';
import '@polymer/paper-input/paper-input.js';
import '@polymer/app-layout/app-toolbar/app-toolbar.js';
import { pbMixin, waitOnce } from './pb-mixin.js';
import { translate } from './pb-i18n.js';
import './pb-restricted.js';
import './pb-ajax.js';
import './pb-edit-xml.js';
import { cmpVersion } from './utils.js';
/**
* High-level component implementing the ODD management panel
* on the start page.
* @fires pb-start-update - Fired before the element updates its content
* @fires pb-end-update - Fired after the element has finished updating its content
* @fires pb-load - Sending the ODD to be used
* @fires pb-refresh-odds When received, refresh the list of ODDs
*/
export class PbManageOdds extends pbMixin(LitElement) {
static get properties() {
return {
...super.properties,
/**
* array of ODD-files to be listed
*/
odds: {
type: Array
},
target: {
type: String
},
_valid: {
type: Boolean
},
_current: {
type: String
}
};
}
constructor() {
super();
this.odds = [];
}
connectedCallback() {
super.connectedCallback();
this.subscribeTo('pb-refresh-odds', (ev) => {
this._refresh();
// regenerate newly uploaded ODDs
const regenAjax = this.shadowRoot.getElementById('regenerate');
const params = ev.detail.odds.map(odd => `odd=${odd}`).join('&');
if (this.minApiVersion('1.0.0')) {
regenAjax.url = `api/odd?${params}`;
} else {
regenAjax.url = `modules/lib/regenerate.xql?${params}`;
}
regenAjax.trigger();
});
}
firstUpdated() {
super.firstUpdated();
this._loader = this.shadowRoot.getElementById('load');
waitOnce('pb-page-ready', (options) => {
if (cmpVersion(options.apiVersion, '1.0.0') < 0) {
this._loader.url = `${options.endpoint}/modules/lib/components-odd.xql`;
} else {
this._loader.url = `${options.endpoint}/api/odd`;
}
this._refresh();
});
}
_refresh(params) {
this.emitTo('pb-start-update');
this._loader.params = params;
this._loader.generateRequest();
}
_update() {
this.emitTo('pb-end-update');
this.odds = this._loader.lastResponse;
this.requestUpdate();
}
_selectODD(ev) {
const selected = ev.model.itemsIndex;
this.odds.forEach((odd, index) => {
if (index !== selected && odd.current) {
this.set('odds.' + index + '.current', false);
this.set('odds.' + selected + '.current', true);
}
});
const params = { odd: ev.model.item.name + '.odd' };
console.log('<pb-manage-odds> selected ODD: %o', params);
this.emitTo('pb-load', {
"params": params
});
}
_createODD() {
const name = this.shadowRoot.querySelector('paper-input[name="new_odd"]').value;
const title = this.shadowRoot.querySelector('paper-input[name="title"]').value;
console.log('<pb-manage-odds> create ODD: %s, %s', name, title);
if (this.lessThanApiVersion('1.0.0')) {
this._refresh({ new_odd: name, title });
} else {
const createRequest = this.shadowRoot.getElementById('create');
createRequest.url = `${this.getEndpoint()}/api/odd/${name}`;
createRequest.params = {
title
};
this.emitTo('pb-start-update');
createRequest.generateRequest();
}
}
_created(ev) {
this.emitTo('pb-end-update');
if (ev.detail.status === 201) {
this._refresh();
} else {
console.log('<pb-manage-odds> unexpected response for create odd: %o', ev.detail);
}
}
_createByExample() {
const name = this.shadowRoot.querySelector('paper-input[name="new_odd"]').value;
const title = this.shadowRoot.querySelector('paper-input[name="title"]').value;
const params = { new_odd: name, title };
const fileBrowser = document.getElementById(this.target);
if (!(fileBrowser || fileBrowser.getSelected)) {
console.error('<pb-manage-odds> target %s not found', this.target);
}
const selected = fileBrowser.getSelected();
document.querySelectorAll('.document-select paper-checkbox[checked]').forEach((checkbox) => {
selected.push(checkbox.value);
});
console.log('<pb-manage-odds> create ODD by example: %o', selected);
params['byExample'] = selected;
this._refresh(params);
}
_delete(odd) {
this._current = odd;
this.shadowRoot.getElementById('deleteDialog').open();
}
_confirmDelete() {
if (this._current) {
console.log('<pb-manage-odds> deleting ODD: %s', this._current);
if (this.lessThanApiVersion('1.0.0')) {
this._refresh({ 'delete': this._current });
} else {
this.emitTo('pb-start-update');
const deleteRequest = this.shadowRoot.getElementById('delete');
deleteRequest.url = `${this.getEndpoint()}/api/odd/${this._current}`;
deleteRequest.generateRequest();
}
this._current = null;
} else {
console.error('<pb-manage-odds> no file marked for deletion');
}
}
_deleted() {
const deleteRequest = this.shadowRoot.getElementById('delete');
const error = deleteRequest.lastError;
if (error.status === 410) {
this._refresh();
} else {
console.error('<pb-manage-odds> failed to delete odd: %d %o', error.status, error.response);
this.emitTo('pb-end-update');
}
}
_validate() {
// Validate the entire form to see if we should enable the `Submit` button.
const valid = this.shadowRoot.getElementById('ironform').validate();
this.shadowRoot.getElementById('createBtn').disabled = !valid;
this.shadowRoot.getElementById('createByEx').disabled = !valid;
}
render() {
if (!this.odds) {
return null;
}
const regenUrl = this.lessThanApiVersion('1.0.0') ? 'modules/lib/regenerate.xql' : "api/odd";
return html`
<pb-restricted login="login">
<pb-ajax id="regenerateAll" url="${regenUrl}" method="post" title="${translate('odd.manage.regenerate-all')}"
emit="${this.emit ? this.emit : ''}" .emitConfig="${this.emitConfig}">
<h3 slot="title">${translate('odd.manage.regenerate-all')}</h3>
<paper-button raised="raised"><a href="#">${translate('odd.manage.regenerate-all')}</a></paper-button>
</pb-ajax>
</pb-restricted>
${this.odds.map((odd) =>
html`
<div class="odd">
<a href="odd-editor.html?odd=${odd.name}.odd" target="_blank"
title="edit ODD in graphical editor">${odd.label}</a>
<!-- TODO this toolbar should only appear once per ODD files papercard -->
<app-toolbar>
${
odd.canWrite ?
html`
<pb-restricted login="login">
<pb-ajax url="${regenUrl}?odd=${odd.name}.odd" method="post" class="editor-link"
emit="${this.emit ? this.emit : ''}" .emitConfig="${this.emitConfig}">
<h2 slot="title">${translate('menu.admin.recompile')}</h2>
<paper-icon-button title="Regenerate ODD" icon="update"></paper-icon-button>
</pb-ajax>
<paper-icon-button title="Delete ODD" icon="delete" @click="${() => this._delete(`${odd.name}.odd`)}"
class="editor-link"></paper-icon-button>
</pb-restricted>
` : null
}
<a href="odd-editor.html?odd=${odd.name}.odd" target="_blank" class="editor-link"
title="edit ODD in graphical editor"><iron-icon icon="reorder"></iron-icon></a>
<pb-edit-xml path="${odd.path}" class="editor-link">
<paper-icon-button title="Edit XML" icon="create"></paper-icon-button>
</pb-edit-xml>
</app-toolbar>
</div>
<div class="odd-description">${odd.description}</div>
`)}
<pb-restricted login="login">
<form action="" method="GET">
<paper-input name="new_odd" label="${translate('odd.manage.filename')}" required auto-validate pattern="[a-zA-Z0-9-_]+"
error-message="${translate('odd.manage.filename-error')}"></paper-input>
<paper-input name="title" label="${translate('odd.manage.title')}" auto-validate required minlength="1"
error-message="${translate('odd.manage.title-error')}"></paper-input>
<paper-button id="createBtn" @click="${this._createODD}">
<iron-icon icon="create"></iron-icon>${translate('odd.manage.create')}
</paper-button>
<!--paper-button id="createByEx" @click="${this._createByExample}">
<iron-icon icon="build"></iron-icon>
${translate('odd.manage.create-from-example')}
</paper-button-->
</form>
</pb-restricted>
<pb-ajax id="regenerate" url="${regenUrl}" method="post"></pb-ajax>
<iron-ajax
id="load"
verbose
handle-as="json"
method="get"
with-credentials
@response="${this._update}">
</iron-ajax>
<iron-ajax id="delete" method="delete" with-credentials @error="${this._deleted}"></iron-ajax>
<iron-ajax id="create" method="post" with-credentials @response="${this._created}" @error="${this._created}"></iron-ajax>
<paper-dialog id="deleteDialog">
<h2>${translate('browse.delete')}</h2>
<paper-dialog-scrollable>
<p>${translate('odd.manage.delete', { file: this.file })}</p>
</paper-dialog-scrollable>
<div class="buttons">
<paper-button dialog-confirm="dialog-confirm" autofocus @click="${this._confirmDelete}">
${translate('dialogs.yes')}
</paper-button>
<paper-button dialog-confirm="dialog-cancel">
${translate('dialogs.no')}
</paper-button>
</div>
</paper-dialog>
`;
}
static get styles() {
return css`
:host {
display: block;
}
.odd {
display: flex;
flex-direction: row;
align-items: center;
}
.odd paper-checkbox {
display: block;
flex: 0 0;
margin-right: 1em;
}
.odd a,
.odd a:link,
.odd a:visited{
display: block;
flex: 10 0;
color:var(--pb-manage-odds-link-color);
}
.odd app-toolbar {
flex: 1 0;
justify-content: flex-end;
padding: 0;
min-height:0.25rem;
}
pb-restricted {
display: flex;
}
.odd-description {
color: #888888;
font-size: 0.8em;
margin-bottom: 0.25rem;
}
#regenerateAll {
display: block;
width: 100%;
margin-top: 10px;
text-align: right;
}
#regenerateAll a{
text-decoration: none;
color: inherit;
}
[icon]{
color:var(--pb-manage-odds-icon-color);
}
[icon='reorder']
{
width:24px;
height: 24px;
}
/* @media (hover:hover) and (pointer: fine){
.odd app-toolbar .editor-link{
opacity: 0;
}
.odd:hover .editor-link{
opacity: 1;
transition: opacity 0.6s;
}
} */
`;
}
}
if(!customElements.get('pb-manage-odds')){
customElements.define('pb-manage-odds', PbManageOdds);
}