nodecg
Version:
Dynamic broadcast graphics rendered in a browser
249 lines (213 loc) • 5.84 kB
text/typescript
import "@polymer/iron-flex-layout/iron-flex-layout.js";
import "@polymer/iron-icons/iron-icons.js";
import "@polymer/paper-card/paper-card.js";
import "@polymer/paper-dialog-scrollable/paper-dialog-scrollable.js";
import "@polymer/paper-dialog/paper-dialog.js";
import "@polymer/paper-toast/paper-toast.js";
import "@vaadin/vaadin-upload/vaadin-upload.js";
import "../util-scrollable";
import "./ncg-asset-file";
import * as Polymer from "@polymer/polymer";
import { MutableData } from "@polymer/polymer/lib/mixins/mutable-data";
class NcgAssetCategory extends MutableData(Polymer.PolymerElement) {
static get template(): HTMLTemplateElement {
return Polymer.html`
<style include="nodecg-theme">
:host {
display: block;
width: 100%;
box-sizing: border-box;
}
#add {
display: flex;
align-items: center;
}
paper-card {
width: 100%;
}
#header {
@apply --layout-vertical;
background-color: #525F78;
padding: 12px 0;
}
#header-main {
@apply --layout-center;
@apply --layout-horizontal;
@apply --layout-justified;
}
#title {
@apply --paper-font-headline;
}
#files {
background-color: #2F3A4F;
max-height: 400px;
margin: 0 -16px;
padding-left: 16px;
--util-scrollable: {
padding: 0;
};
@apply --layout-vertical;
}
vaadin-upload {
width: 400px;
margin: 16px;
--lumo-primary-text-color: var(--nodecg-brand-blue);
--lumo-secondary-text-color: darkgray;
}
#acceptsMsg {
margin-top: 8px;
text-align: center;
}
#add {
--nodecg-background-color: #00A651;
}
#add iron-icon {
position: relative;
top: -1px;
}
</style>
<paper-toast id="toast"></paper-toast>
<div id="header">
<div id="header-main">
<span id="title">[[category.title]]</span>
<paper-button id="add" on-click="openUploadDialog">
<iron-icon icon="add"></iron-icon>
Add File(s)
</paper-button>
</div>
<div id="empty">
There are no assets in this category.
</div>
</div>
<util-scrollable id="files">
<template is="dom-repeat" items="[[files]]" as="file" mutable-data="">
<ncg-asset-file file="[[file]]" on-deleted="_handleDeleted" on-deletion-failed="_handleDeletionFailed">
</ncg-asset-file>
</template>
</util-scrollable>
<!-- 2017/03/18: Had to remove with-backdrop during the dashboard re-write -->
<paper-dialog id="uploadDialog">
<paper-dialog-scrollable>
<vaadin-upload id="uploader" target="/assets/[[collectionName]]/[[category.name]]" on-upload-start="refitUploadDialog" on-file-reject="_onFileReject" on-upload-success="_onUploadSuccess">
<template is="dom-if" if="[[category.allowedTypes.length]]">
<div id="acceptsMsg">[[acceptsMsg]]</div>
</template>
</vaadin-upload>
</paper-dialog-scrollable>
<div class="buttons">
<paper-button dialog-dismiss="">Close</paper-button>
</div>
</paper-dialog>
`;
}
static get is(): string {
return "ncg-asset-category";
}
static get properties() {
return {
files: Array,
collectionName: {
type: String,
reflectToAttribute: true,
},
category: Object,
categoryName: {
type: String,
reflectToAttribute: true,
computed: "_computeCategoryName(category.name)",
},
acceptsMsg: {
type: String,
computed: "_computeAcceptsMsg(category.allowedTypes)",
},
_successfulUploads: {
type: Number,
value: 0,
},
_assetCategoryReplicant: {
type: Object,
},
};
}
static get observers(): string[] {
return [
"_onAllowedTypesChanged(category.allowedTypes)",
"_computeAssetCategoryReplicant(category.name, collectionName)",
];
}
override connectedCallback(): void {
super.connectedCallback();
this.$.uploadDialog.fitInto = document.body
.querySelector("ncg-dashboard")!
.shadowRoot!.getElementById("pages");
this.$.uploadDialog.resetFit();
}
refitUploadDialog(): void {
this.$.uploadDialog.refit();
}
_onAllowedTypesChanged(allowedTypes: string[]): void {
const prefixed = allowedTypes.map((type) => "." + type);
this.$.uploader.accept = prefixed.join(",");
}
_computeAcceptsMsg(allowedTypes: string[]): string {
let msg = "Accepts ";
allowedTypes.forEach((type, index) => {
type = type.toUpperCase();
if (index === 0) {
msg += type;
} else if (index === allowedTypes.length - 1) {
if (index === 1) {
msg += " and " + type;
} else {
msg += ", and " + type;
}
} else {
msg += ", " + type;
}
});
return msg;
}
_handleDeleted(e: any): void {
this.$.toast.text = `Deleted ${e.target.file.base}`;
this.$.toast.show();
}
_handleDeletionFailed(e: any): void {
this.$.toast.text = `Failed to delete ${e.target.file.base}`;
this.$.toast.show();
}
openUploadDialog(): void {
this.$.uploadDialog.open();
this.refitUploadDialog();
}
_onFileReject(event: any): void {
this.refitUploadDialog();
this.$.toast.text = `${event.detail.file.name} error: ${event.detail.error}`;
this.$.toast.open();
}
_onUploadSuccess(): void {
this._successfulUploads++;
}
_computeCategoryName(categoryName: string): string {
return categoryName;
}
_computeAssetCategoryReplicant(
categoryName: string,
collectionName: string,
): void {
const newRep = NodeCG.Replicant(`assets:${categoryName}`, collectionName);
const oldRep = this._assetCategoryReplicant;
if (oldRep) {
oldRep.removeEventListener("change");
}
newRep.on("change", (newVal) => {
this.files = newVal;
if (Array.isArray(newVal) && newVal.length > 0) {
this.$.empty.style.display = "none";
} else {
this.$.empty.style.display = "block";
}
});
this._assetCategoryReplicant = newRep;
}
}
customElements.define(NcgAssetCategory.is, NcgAssetCategory);