import 'polymer/polymer-element.html'
import './ozone-localized-string/ozone-localized-string'
import './ozone-item-edit.html'
import { customElement, property, observe } from 'taktik-polymer-typescript'
import { Item, FieldDescriptor, GenericItem, FieldsPermissionUtility, Patch } from 'ozone-type'
import { getDefaultClient } from 'ozone-default-client'
import './ozone-edit-entry/ozone-edit-entry'
// tslint:disable-next-line no-duplicate-imports
import { OzoneEditEntry } from './ozone-edit-entry/ozone-edit-entry'
import './ozone-edit-set-entry/ozone-edit-set-entry'
import './ozone-edit-text-entry/ozone-edit-text-entry'
import './ozone-edit-number-entry/ozone-edit-number-entry'
import './ozone-edit-json-entry/ozone-edit-json-entry'
export type PartialItem = Partial
class TruePermission extends FieldsPermissionUtility {
isFieldEditable(fieldName: string): boolean {
return true
}
}
/**
* is an element that provide material design to edit an ozone Item.
*
* ```html
*
* ```
*
* Events:
* value-changed: Trigger when a value has changed
*/
@customElement('ozone-item-edit')
export class OzoneItemEdit extends Polymer.Element {
/**
* item to display
*/
@property({ type: Object, notify: true })
itemData: GenericItem | null = null
/**
* Returns true if the value is invalid.
*/
@property({
type: Boolean,
notify: true
})
invalid: boolean = false
$: {
editableList: Element,
elementView: HTMLElement
} | any
static editEntryClass = 'editEntry'
/**
* @private
*/
@observe('itemData')
async dataChange(data?: Item) {
this.$.elementView.style.visibility = 'hidden'
if (!data) {
return
}
if (!data.type) {
return
}
this.removeEntryIfExist()
const typeCache = await getDefaultClient().typeClient().getTypeCache()
const permissionClient = getDefaultClient().permissionClient()
const fields: Array = await(typeCache.getAllFields(data.type))
fields.sort((a, b) => { return a.fieldType.localeCompare(b.fieldType) })
let permission
if (data.id) {
permission = await(permissionClient.getPermissions(fields.map(field => field.identifier), data.id))
} else {
permission = new TruePermission({})
}
for (let description of fields) {
if (description && permission) {
await (this.addInputElement(description, data, permission))
}
}
this.$.elementView.style.visibility = 'visible'
}
private async addInputElement(description: FieldDescriptor, data: GenericItem, permission: FieldsPermissionUtility) {
const fieldType = description.fieldType || 'unknown'
const identifier = description.identifier
const fieldName = description.name || { strings: { en: identifier + '*' } }
const listEntry = document.createElement('div')
listEntry.className = 'ozoneEditItemContent'
const editableItemName = OzoneItemEdit.getEditableItemName(fieldType)
if (typeof(editableItemName) === 'string') {
const editableItem = document.createElement(editableItemName) as (OzoneEditEntry)
editableItem.className = OzoneItemEdit.editEntryClass
editableItem.id = identifier
editableItem.type = fieldType
editableItem.value = data[identifier]
editableItem.language = 'en'
editableItem.name = fieldName
editableItem.addEventListener('value-changed', (e) => {
if (this.itemData) {
this.itemData[identifier] = (e as CustomEvent).detail.value
}
})
editableItem.addEventListener('invalid-changed', () => {
this.updateInvalidValue()
})
const isEditAllow: boolean = permission.isFieldEditable(identifier)
editableItem.disabled = !isEditAllow
listEntry.appendChild(editableItem)
this.$.editableList.appendChild(listEntry)
editableItem.inputElement.addEventListener('value-changed', () => {
this.dispatchEvent(new CustomEvent('value-changed',
{
detail: this.getUpdatedData(),
bubbles: true
}))
})
}
}
private static getEditableItemName(type: string): string | undefined {
let editableItemName
switch (type) {
case 'string':
case 'uuid':
case 'blob':
case 'date':
editableItemName = 'ozone-edit-entry'
break
case 'set':
editableItemName = 'ozone-edit-set-entry'
break
case 'analyzed_string':
editableItemName = 'ozone-edit-text-entry'
break
case 'integer':
case 'float':
case 'double':
editableItemName = 'ozone-edit-number-entry'
break
case 'map[>':
editableItemName = 'ozone-edit-json-entry'
break
}
return editableItemName
}
/**
* get the item with it's modifies fields.
* @return {Item}
*/
getUpdatedData(): Patch]- {
if (!this.itemData) {
throw new Error()
}
const entryList = this.getEntryList()
const updatedItem: PartialItem = {
type: this.itemData.type,
id: this.itemData.id
}
for (let index = 0; index < entryList.length; index ++) {
let entry = entryList.item(index) as OzoneEditEntry
if (entry.isModify) {
updatedItem[entry.id] = entry.value
}
}
return updatedItem
}
updateInvalidValue() {
let invalid: boolean = false
const entryList = this.getEntryList()
for (let index = 0; index < entryList.length; index ++) {
invalid = entryList.item(index).invalid || invalid
}
this.set('invalid', invalid)
}
private getEntryList() {
return this.$.editableList.getElementsByClassName(OzoneItemEdit.editEntryClass)
}
private removeEntryIfExist() {
const entryList = this.$.editableList.getElementsByClassName('ozoneEditItemContent')
while (entryList.length > 0) {
entryList[0].remove()
}
}
}