survey-analytics
Version:
SurveyJS analytics Library.
1 lines • 3.22 MB
Source Map (JSON)
{"version":3,"file":"survey.analytics.tabulator.mjs","sources":["../../src/tables/extensions/tableextensions.ts","../../src/tables/extensions/rowextensions.ts","../../src/tables/extensions/headerextensions.ts","../../src/tables/config.ts","../../src/tables/extensions/columnextensions.ts","../../src/tables/extensions/detailsextensions.ts","../../src/tables/columns.ts","../../src/tables/columnbuilder.ts","../../src/tables/table.ts","../../src/tables/custom_jspdf_font.ts","../../src/tables/tabulator.ts","../../src/entries/tabulator-es.ts"],"sourcesContent":["import { Table } from \"../table\";\n\nexport interface ITableExtension {\n location: string;\n name: string;\n visibleIndex: number;\n render: (table: Table, opt: any) => HTMLElement;\n destroy?: () => void;\n}\n\nexport class TableExtensions {\n constructor(private table: Table) {}\n private static extensions: { [location: string]: Array<ITableExtension> } = {};\n private renderedExtensions: Array<ITableExtension> = [];\n\n public render(targetNode: HTMLElement, location: string, options?: any) {\n var extensions = TableExtensions.extensions[location];\n if (!!extensions) {\n extensions = this.sortExtensions(extensions);\n extensions.forEach((extension) => {\n if (!!extension.render && this.table.allowExtension(extension)) {\n var action = extension.render(this.table, options);\n if (!!action) {\n targetNode.appendChild(action);\n this.renderedExtensions.push(extension);\n }\n }\n });\n }\n }\n\n public destroy() {\n this.renderedExtensions.forEach((extension) => {\n if (!!extension.destroy) extension.destroy();\n });\n this.renderedExtensions = [];\n }\n\n public static registerExtension(extension: ITableExtension) {\n if (!this.extensions[extension.location])\n this.extensions[extension.location] = [];\n this.extensions[extension.location].push(extension);\n }\n\n private static removeExtension(extension: ITableExtension) {\n if(!extension) {\n return;\n }\n const extensions = TableExtensions.extensions[extension.location];\n const index = extensions.indexOf(extension);\n if(index >= 0) {\n extensions.splice(index, 1);\n }\n }\n\n public static unregisterExtension(\n location: string,\n actionName: string\n ) {\n if(!actionName) {\n return;\n }\n if(!!location) {\n const extension = TableExtensions.findExtension(location, actionName);\n TableExtensions.removeExtension(extension);\n } else {\n Object.keys(this.extensions).forEach((location:string) => TableExtensions.unregisterExtension(location, actionName));\n }\n }\n\n public static findExtension(\n location: string,\n actionName: string\n ): ITableExtension {\n if (!this.extensions[location]) return null;\n var extension = this.extensions[location].filter(function (\n extension: ITableExtension\n ) {\n return extension.name == actionName;\n })[0];\n return extension || null;\n }\n\n private sortExtensions(extensions: Array<ITableExtension>) {\n if (!Array.isArray(extensions)) return;\n return []\n .concat(extensions.filter((extension) => extension.visibleIndex >= 0))\n .sort((firstExtension, secondExtension) => {\n return firstExtension.visibleIndex - secondExtension.visibleIndex;\n });\n }\n}\n","import { Table } from \"../table\";\nimport { localization } from \"../../localizationManager\";\nimport { DocumentHelper } from \"../../utils\";\nimport { TableExtensions } from \"./tableextensions\";\n\nTableExtensions.registerExtension({\n location: \"row\",\n name: \"details\",\n visibleIndex: 0,\n render: (_table: Table, options: any) => {\n const btn = DocumentHelper.createSvgButton(\"detail\");\n btn.title = localization.getString(\"showMinorColumns\");\n btn.className += \" sa-table__row-extension\";\n btn.onclick = () => {\n options.row.toggleDetails();\n };\n return btn;\n },\n});\n\nTableExtensions.registerExtension({\n location: \"row\",\n name: \"select\",\n visibleIndex: -1,\n render: function (_table, opt) {\n var row = opt.row;\n var checkbox = <HTMLInputElement>DocumentHelper.createElement(\n \"input\",\n \"sa-table__row-extension\",\n {\n type: \"checkbox\",\n }\n );\n checkbox.checked = row.getIsSelected();\n checkbox.onchange = function () {\n row.toggleSelect();\n };\n return checkbox;\n },\n});\n","import { localization } from \"../../localizationManager\";\nimport { Table } from \"../table\";\nimport { DocumentHelper } from \"../../utils\";\nimport { TableExtensions } from \"./tableextensions\";\n\nTableExtensions.registerExtension({\n location: \"header\",\n name: \"filter\",\n visibleIndex: 0,\n render: function (table: Table): HTMLElement {\n const input = DocumentHelper.createInput(\n \"sa-table__global-filter sa-table__header-extension\",\n localization.getString(\"filterPlaceholder\")\n );\n input.onchange = (event: any) => {\n table.applyFilter(event.target.value);\n };\n return input;\n },\n});\n\nTableExtensions.registerExtension({\n location: \"header\",\n name: \"showcolumn\",\n visibleIndex: 2,\n destroy: function () {\n this.onDestroy();\n },\n render: function (table: Table): HTMLElement {\n const dropdown = DocumentHelper.createElement(\n \"select\",\n \"sa-table__show-column sa-table__header-extension\"\n );\n\n function update() {\n var hiddenColumns = table.columns.filter(\n (column: any) => !column.isVisible\n );\n if (hiddenColumns.length == 0) {\n dropdown.style.display = \"none\";\n return;\n }\n dropdown.style.display = \"inline-block\";\n dropdown.innerHTML = \"\";\n var option = DocumentHelper.createElement(\"option\", \"\", {\n text: localization.getString(\"showColumn\"),\n disabled: true,\n selected: true,\n });\n dropdown.appendChild(option);\n\n hiddenColumns.forEach((column: any) => {\n var text = column.displayName || column.name;\n if (!!text && text.length > 20) {\n text = text.substring(0, 20) + \"...\";\n }\n var option = DocumentHelper.createElement(\"option\", \"\", {\n text: text,\n title: column.displayName,\n value: column.name,\n });\n dropdown.appendChild(option);\n });\n }\n\n dropdown.onchange = (e: any) => {\n const val = e.target.value;\n e.stopPropagation();\n if (!val) return;\n table.setColumnVisibility(val, true);\n };\n\n update();\n\n var onVisibilityChangedCallback = () => {\n update();\n };\n\n table.onColumnsVisibilityChanged.add(onVisibilityChangedCallback);\n\n this.onDestroy = () => {\n table.onColumnsVisibilityChanged.remove(onVisibilityChangedCallback);\n };\n return dropdown;\n },\n});\n\nTableExtensions.registerExtension({\n location: \"header\",\n name: \"showentries\",\n visibleIndex: 3,\n render: function (table: Table): HTMLElement {\n function getEntriesDropdown(table: Table): HTMLElement {\n const el = <HTMLSelectElement>DocumentHelper.createElement(\"select\");\n var optionsValues = table.paginationSizeSelector || [\"1\", \"5\", \"10\", \"25\", \"50\", \"75\", \"100\"];\n optionsValues.forEach(function (val) {\n var option = DocumentHelper.createElement(\"option\", \"\", {\n value: val,\n text: val,\n });\n el.appendChild(option);\n });\n el.value = String(table.getPageSize());\n\n el.onchange = () => {\n table.setPageSize(Number(el.value));\n };\n\n return el;\n }\n const selectorContainer = DocumentHelper.createElement(\n \"div\",\n \"sa-table__entries\"\n );\n const spaceSpan = DocumentHelper.createElement(\"span\", \"sa-table__header-space\");\n const showSpan = DocumentHelper.createElement(\n \"span\",\n \"sa-table__entries-label sa-table__entries-label--right\",\n {\n innerText: localization.getString(\"showLabel\"),\n }\n );\n const entriesSpan = DocumentHelper.createElement(\n \"span\",\n \"sa-table__entries-label sa-table__entries-label--left\",\n {\n innerText: localization.getString(\"entriesLabel\"),\n }\n );\n\n selectorContainer.appendChild(spaceSpan);\n selectorContainer.appendChild(showSpan);\n selectorContainer.appendChild(getEntriesDropdown(table));\n selectorContainer.appendChild(entriesSpan);\n return selectorContainer;\n },\n});\n\nTableExtensions.registerExtension({\n location: \"header\",\n name: \"removerows\",\n visibleIndex: -1,\n render: function (table) {\n var btn = DocumentHelper.createElement(\n \"button\",\n \"sa-table__btn sa-table__btn--green sa-table__header-extension \",\n { innerText: localization.getString(\"removeRows\") }\n );\n btn.onclick = function () {\n table.getCreatedRows().forEach(function (row) {\n if (row.getIsSelected()) {\n row.remove();\n }\n });\n };\n return btn;\n },\n});\n\nTableExtensions.registerExtension({\n location: \"header\",\n name: \"changelocale\",\n visibleIndex: 1,\n render: function (table) {\n var locales = table.getLocales();\n if (table.options.disableLocaleSwitch || locales.length < 2) return null;\n const el = <HTMLSelectElement>(\n DocumentHelper.createElement(\"select\", \"sa-table__header-extension\", {})\n );\n var optionsValues = [localization.getString(\"changeLocale\")].concat(\n locales\n );\n optionsValues.forEach(function (val) {\n var option = DocumentHelper.createElement(\"option\", \"\", {\n value: val,\n text: localization.localeNames[val] || localization.getString(val) || val,\n });\n el.appendChild(option);\n });\n el.onchange = () => {\n table.locale = el.value;\n };\n return el;\n },\n});\n\nexport var HeaderExtensions;","import { Question, SurveyModel } from \"survey-core\";\nimport { ITableOptions, Table } from \"./table\";\n\nexport enum QuestionLocation {\n Column,\n Row,\n}\nexport enum ColumnDataType {\n Text,\n FileLink,\n Image,\n}\n\nexport interface ICellData {\n question: Question;\n displayValue: any;\n}\n\nexport interface IColumnData {\n name: string;\n displayName: string;\n dataType: ColumnDataType;\n isVisible: boolean;\n isPublic: boolean;\n location: QuestionLocation;\n width?: string | number;\n isComment?: boolean;\n}\nexport interface IColumn extends IColumnData {\n visibleIndex?: number;\n fromJSON(json: any): void;\n getCellData(table: Table, data: any): ICellData;\n}\n\nexport interface ITableState {\n locale?: string;\n elements?: IColumnData[];\n pageSize?: number;\n}\n\nexport interface IPermission {\n name: string;\n isPublic: boolean;\n}\n","import { Table } from \"../table\";\nimport { DocumentHelper } from \"../../utils\";\nimport { localization } from \"../../localizationManager\";\nimport { TableExtensions } from \"./tableextensions\";\nimport { QuestionLocation, IColumn } from \"../config\";\n\nTableExtensions.registerExtension({\n location: \"column\",\n name: \"drag\",\n visibleIndex: 0,\n render: function (table: Table, options: any) {\n const btn = DocumentHelper.createElement(\n \"button\",\n \"sa-table__svg-button sa-table__drag-button\"\n );\n btn.appendChild(DocumentHelper.createSvgElement(\"drag\"));\n btn.onmousedown = (e) => {\n table.enableColumnReorder();\n };\n return btn;\n },\n});\n\nTableExtensions.registerExtension({\n location: \"column\",\n name: \"sort\",\n visibleIndex: 1,\n render: function (table: Table, options: any) {\n const descTitle = localization.getString(\"descOrder\");\n const ascTitle = localization.getString(\"ascOrder\");\n var btn = DocumentHelper.createSvgButton(\"sorting\");\n btn.title = \"\";\n var direction = \"asc\";\n btn.onclick = () => {\n if (direction == \"asc\") {\n btn.title = descTitle;\n direction = \"desc\";\n } else {\n btn.title = ascTitle;\n direction = \"asc\";\n }\n table.sortByColumn(options.columnName, direction);\n };\n btn.ondrag = (e) => {\n e.stopPropagation();\n };\n return btn;\n },\n});\n\nTableExtensions.registerExtension({\n location: \"column\",\n name: \"hide\",\n visibleIndex: 2,\n render: function (table: Table, options: any) {\n var btn = DocumentHelper.createSvgButton(\"hide\");\n btn.title = localization.getString(\"hideColumn\");\n btn.onclick = () => {\n table.setColumnVisibility(options.columnName, false);\n };\n return btn;\n },\n});\n\nTableExtensions.registerExtension({\n location: \"column\",\n name: \"movetodetails\",\n visibleIndex: 3,\n render: function (table: Table, options: any) {\n const button = DocumentHelper.createSvgButton(\"movetodetails\");\n button.title = localization.getString(\"moveToDetail\");\n button.onclick = (e) => {\n e.stopPropagation();\n table.setColumnLocation(options.columnName, QuestionLocation.Row);\n };\n return button;\n },\n});\n\nTableExtensions.registerExtension({\n location: \"column\",\n name: \"filter\",\n visibleIndex: 4,\n render: function (table: Table, options: any) {\n var el = DocumentHelper.createInput(\n \"sa-table__filter\",\n localization.getString(\"filterPlaceholder\")\n );\n el.onclick = (e) => e.stopPropagation();\n el.onchange = (e) => {\n table.applyColumnFilter(options.columnName, el.value);\n };\n return el;\n },\n});\n\nTableExtensions.registerExtension({\n location: \"column\",\n name: \"makepublic\",\n visibleIndex: -1,\n render: function (table: Table, options: any) {\n const button = DocumentHelper.createElement(\"button\");\n const makePrivateSvg = DocumentHelper.createSvgElement(\"makeprivate\");\n const makePublicSvg = DocumentHelper.createSvgElement(\"makepublic\");\n const column = table.getColumnByName(options.columnName);\n\n updateState(column);\n button.appendChild(makePrivateSvg);\n button.appendChild(makePublicSvg);\n button.onclick = (e) => {\n e.stopPropagation();\n column.isPublic = !column.isPublic;\n updateState(column);\n table.onPermissionsChangedCallback &&\n table.onPermissionsChangedCallback(table);\n };\n\n function updateState(column: IColumn) {\n if (column.isPublic) {\n button.className = \"sa-table__svg-button\";\n button.title = localization.getString(\"makePrivateColumn\");\n makePrivateSvg.style.display = \"none\";\n makePublicSvg.style.display = \"block\";\n } else {\n button.className = \"sa-table__svg-button sa-table__svg-button--active\";\n button.title = localization.getString(\"makePublicColumn\");\n makePrivateSvg.style.display = \"block\";\n makePublicSvg.style.display = \"none\";\n }\n }\n return button;\n },\n});\n","import { TableRow } from \"../table\";\nimport { Table } from \"../table\";\nimport { DocumentHelper } from \"../../utils\";\nimport { ColumnDataType, QuestionLocation } from \"../config\";\nimport { TableExtensions } from \"./tableextensions\";\nimport { localization } from \"../../localizationManager\";\n\nexport class Details {\n constructor(\n protected table: Table,\n private row: TableRow,\n protected targetNode: HTMLElement\n ) {\n this.detailsTable = DocumentHelper.createElement(\n \"table\",\n \"sa-table__detail-table\"\n );\n this.table.onColumnsLocationChanged.add(() => {\n this.close();\n });\n }\n private detailsTable: HTMLElement;\n protected location = \"details\";\n\n public open(): void {\n this.detailsTable.innerHTML = \"\";\n var rows: HTMLElement[] = [];\n this.table.columns\n .filter((column) => column.location === QuestionLocation.Row && column)\n .forEach((column) => {\n var row = DocumentHelper.createElement(\"tr\", \"sa-table__detail\");\n var td1 = DocumentHelper.createElement(\"td\");\n td1.appendChild(document.createTextNode(column.displayName));\n var td2 = DocumentHelper.createElement(\"td\");\n td2.textContent = this.row.getRowData()[column.name];\n if(column.dataType === ColumnDataType.Image) {\n td2.innerHTML = \"<image src='\" + td2.textContent + \"'/>\";\n }\n var td3 = DocumentHelper.createElement(\"td\");\n td3.appendChild(this.createShowAsColumnButton(column.name));\n row.appendChild(td1);\n row.appendChild(td2);\n row.appendChild(td3);\n rows.push(row);\n });\n var row = DocumentHelper.createElement(\"tr\", \"sa-table__detail\");\n var td = DocumentHelper.createElement(\"td\", \"\", { colSpan: 3 });\n var extensions = new TableExtensions(this.table);\n extensions.render(td, \"details\", { row: this.row });\n if (td.children.length != 0) {\n row.appendChild(td);\n rows.push(row);\n }\n\n rows.forEach((row) => {\n this.detailsTable.appendChild(row);\n });\n this.targetNode.appendChild(this.detailsTable);\n }\n\n protected createShowAsColumnButton = (columnName: string): HTMLElement => {\n const button = DocumentHelper.createElement(\n \"button\",\n \"sa-table__btn sa-table__btn--gray\"\n );\n button.appendChild(document.createTextNode(localization.getString(\"showAsColumn\")));\n button.onclick = (e) => {\n e.stopPropagation();\n this.table.setColumnLocation(columnName, QuestionLocation.Column);\n };\n\n return button;\n };\n\n public close() {\n if (!!this.detailsTable.parentNode) {\n this.detailsTable.parentNode.removeChild(this.detailsTable);\n }\n }\n}\n","import { ItemValue, MatrixRowModel, Question, QuestionCompositeModel, QuestionCustomModel, QuestionFileModel, QuestionMatrixDropdownModel, QuestionMatrixModel, QuestionSelectBase, settings } from \"survey-core\";\nimport { createImagesContainer, createLinksContainer } from \"../utils\";\nimport { ICellData, IColumn, ColumnDataType, QuestionLocation, IColumnData } from \"./config\";\nimport { ITableOptions, Table } from \"./table\";\nexport class BaseColumn<T extends Question = Question> implements IColumn {\n dataType: ColumnDataType;\n isVisible: boolean = true;\n isPublic: boolean = true;\n location: QuestionLocation = QuestionLocation.Column;\n width?: string | number;\n visibleIndex?: number;\n isComment?: boolean;\n private nameValue: string;\n private displayNameValue?: string;\n\n constructor(protected question: T, protected table: Table) {\n this.dataType = this.getDataType();\n }\n get name(): string {\n if(!this.nameValue) {\n this.name = this.getName();\n }\n return this.nameValue;\n }\n set name(val: string) {\n this.nameValue = val;\n }\n get displayName(): string {\n if(!this.displayNameValue) {\n this.displayName = this.getDisplayName();\n }\n return this.displayNameValue;\n }\n public set displayName(val: string) {\n this.displayNameValue = val;\n }\n\n protected getDisplayName(): string {\n return this.table.useNamesAsTitles\n ? this.question.name\n : (this.question.title || \"\").trim() || this.question.name;\n }\n protected getName(): string {\n return this.question.name;\n }\n protected getDataType(): ColumnDataType {\n return ColumnDataType.Text;\n }\n protected getDisplayValueCore(data: any) {\n return data[this.name];\n }\n\n protected setupReadyChangedCallback(table: Table, question: Question) {\n if(!!question) {\n const onReadyChangedCallback = (sender, options) => {\n if(options.isReady) {\n table.refresh(!table.isInitTableDataProcessing);\n sender.onReadyChanged.remove(onReadyChangedCallback);\n }\n };\n if(!question.isReady) {\n question.onReadyChanged.add(onReadyChangedCallback);\n }\n }\n }\n\n protected getDisplayValue(data: any, table: Table, options: ITableOptions): any {\n let displayValue = this.getDisplayValueCore(data);\n const question = this.question;\n\n if (!!question) {\n if (options.useValuesAsLabels) {\n displayValue = question.value;\n } else {\n displayValue = question.displayValue;\n }\n }\n return displayValue;\n }\n private formatDisplayValue(displayValue: any) {\n return typeof displayValue === \"string\"\n ? displayValue\n : JSON.stringify(displayValue) || \"\";\n }\n\n public getCellData(table: Table, data: any): ICellData {\n const displayValue = this.getDisplayValue(data, table, table.options);\n this.setupReadyChangedCallback(table, this.question);\n return { question: this.question, displayValue: this.formatDisplayValue(displayValue) };\n }\n public toJSON(): IColumnData {\n return {\n name: this.name,\n displayName: this.displayName,\n dataType: this.dataType,\n isVisible: this.isVisible,\n isPublic: this.isPublic,\n location: this.location\n };\n }\n public fromJSON(data: IColumnData) {\n Object.keys(data).forEach(key => {\n this[key] = data[key];\n });\n }\n}\n\nexport class DefaultColumn extends BaseColumn {\n protected getDisplayValue(data: any, table: Table, options: ITableOptions): any {\n return this.getDisplayValueCore(data);\n }\n}\n\nexport class CommentColumn<T extends Question = Question> extends BaseColumn<T> {\n protected getName(): string {\n return `${this.question.name}${settings.commentPrefix}`;\n }\n protected getDisplayName(): string {\n return this.question.commentText;\n }\n protected getDisplayValue(data: any, table: Table, options: ITableOptions): string {\n return this.question.comment;\n }\n}\nexport class OtherColumn extends CommentColumn<QuestionSelectBase> {\n protected getDisplayName(): string {\n return this.question.otherText;\n }\n}\n\nexport class MatrixColumn extends BaseColumn<QuestionMatrixModel> {\n private valueName: string;\n private valuePath: string;\n constructor(question: QuestionMatrixModel, private row: MatrixRowModel, table: Table) {\n super(question, table);\n this.valueName = this.question.name;\n this.valuePath = this.row?.value;\n }\n protected getName(): string {\n return this.question.name + \".\" + this.row?.value;\n }\n protected getDisplayName(): string {\n const table = this.table;\n const question = this.question;\n const row = this.row;\n return (table.useNamesAsTitles\n ? question.name\n : (question.title || \"\").trim() || question.name) + \" - \" + (table.useNamesAsTitles ? row?.value : row?.locText.textOrHtml);\n }\n\n protected getDisplayValue(data: any, table: Table, options: ITableOptions) {\n let displayValue = data[this.valueName];\n if(this.valuePath && typeof displayValue === \"object\") {\n displayValue = displayValue[this.valuePath];\n if(displayValue !== undefined) {\n const choiceValue = ItemValue.getItemByValue(this.question.columns, displayValue);\n if(!!choiceValue) {\n displayValue = options.useValuesAsLabels ? choiceValue.value : choiceValue.locText.textOrHtml;\n }\n }\n }\n return displayValue;\n }\n}\n\nexport class ImageColumn extends BaseColumn {\n protected getDataType(): ColumnDataType {\n return ColumnDataType.Image;\n }\n}\n\nexport class FileColumn extends BaseColumn<QuestionFileModel> {\n protected getDataType(): ColumnDataType {\n return ColumnDataType.FileLink;\n }\n protected getDisplayValue(data: any, table: Table, options: ITableOptions) {\n let displayValue = this.getDisplayValueCore(data);\n if (Array.isArray(displayValue)) {\n displayValue = Table.showFilesAsImages ? createImagesContainer(\n displayValue\n ).outerHTML : createLinksContainer(\n displayValue\n ).outerHTML;\n }\n return displayValue;\n }\n}\nexport class MatrixDropdownColumn extends BaseColumn<QuestionMatrixDropdownModel> {\n private rowValue: string;\n private colName: string;\n constructor(question: QuestionMatrixDropdownModel, protected row, protected col, table: Table) {\n super(question, table);\n this.rowValue = this.row.value;\n this.colName = this.col.name;\n }\n protected getName(): string {\n return this.question.name + \".\" + this.row.value + \".\" + this.col.name;\n }\n protected getDisplayName(): string {\n const table = this.table;\n const question = this.question;\n return (this.table.useNamesAsTitles\n ? question.name\n : (question.title || \"\").trim() || question.name) + \" - \" + (table.useNamesAsTitles ? this.row.value : this.row.locText.textOrHtml) + \" - \" + (table.useNamesAsTitles ? this.col.name : this.col.locTitle.textOrHtml);\n\n }\n protected getDisplayValue(data: any, table: Table, options: ITableOptions) {\n let displayValue = data[this.question.name];\n const question = this.question;\n if(this.rowValue && this.colName && typeof displayValue === \"object\") {\n let [rowId, colId] = [this.rowValue, this.colName];\n displayValue = question.value;\n if(!options.useValuesAsLabels) {\n displayValue = question.displayValue;\n rowId = question.rows.filter(row => row.value === this.rowValue)[0].text;\n colId = question.getColumnByName(this.colName).title;\n }\n displayValue = (displayValue[rowId] && displayValue[rowId][colId]) || \"\";\n }\n return displayValue;\n }\n}\n\nexport class CustomQuestionColumn extends BaseColumn<QuestionCustomModel> {\n public getCellData(table: Table, data: any): ICellData {\n this.setupReadyChangedCallback(table, this.question.contentQuestion);\n return super.getCellData(table, data);\n }\n}\n\nexport class CompositeQuestionColumn extends BaseColumn<QuestionCompositeModel> {\n public getCellData(table: Table, data: any): ICellData {\n const questionList: Question[] = [];\n this.question.contentPanel.addQuestionsToList(questionList);\n questionList.forEach((question: Question) => {\n this.setupReadyChangedCallback(table, question);\n });\n return super.getCellData(table, data);\n }\n}","import { Question, QuestionCompositeModel, QuestionCustomModel, QuestionFileModel, QuestionMatrixDropdownModel, QuestionMatrixModel, QuestionSelectBase } from \"survey-core\";\nimport { BaseColumn, CommentColumn, CompositeQuestionColumn, CustomQuestionColumn, FileColumn, ImageColumn, MatrixColumn, MatrixDropdownColumn, OtherColumn } from \"./columns\";\nimport { IColumn } from \"./config\";\nimport { Table } from \"./table\";\n\nexport interface IColumnsBuilder {\n buildColumns(question: Question, table: Table): Array<IColumn>;\n}\nexport class DefaultColumnsBuilder<T extends Question = Question> implements IColumnsBuilder {\n protected createColumn(question: T, table: Table) {\n return new BaseColumn(question, table);\n }\n\n protected buildColumnsCore(question: T, table: Table): Array<IColumn> {\n const columns: Array<IColumn> = [];\n columns.push(this.createColumn(question, table));\n return columns;\n }\n\n public buildColumns(question: T, table: Table): Array<IColumn> {\n const columns = this.buildColumnsCore(question, table);\n if(question.hasComment) {\n columns.push(new CommentColumn(question, table));\n }\n if(question.hasOther && (question as unknown as QuestionSelectBase)[\"getStoreOthersAsComment\"]()) {\n columns.push(new OtherColumn(question as unknown as QuestionSelectBase, table));\n }\n return columns;\n }\n}\n\nexport class ColumnsBuilderFactory {\n public static Instance: ColumnsBuilderFactory = new ColumnsBuilderFactory();\n private constructor() {}\n\n private readonly columnsBuilders: {[index: string]: IColumnsBuilder } = {};\n private readonly defaultColumnsBuilder: IColumnsBuilder = new DefaultColumnsBuilder();\n\n registerBuilderColumn(type: string, columnsBuilder: IColumnsBuilder) {\n this.columnsBuilders[type] = columnsBuilder;\n }\n getColumnsBuilder(type: string) {\n return this.columnsBuilders[type] || this.defaultColumnsBuilder;\n }\n}\n\nexport class MatrixColumnsBuilder extends DefaultColumnsBuilder<QuestionMatrixModel> {\n protected buildColumnsCore(questionBase: Question, table: Table): IColumn[] {\n const question = <QuestionMatrixModel>questionBase;\n const columns = [];\n question.rows.forEach(row => {\n columns.push(new MatrixColumn(question, row, table));\n });\n return columns;\n }\n}\nColumnsBuilderFactory.Instance.registerBuilderColumn(\"matrix\", new MatrixColumnsBuilder());\n\nexport class ImageColumnsBuilder extends DefaultColumnsBuilder {\n protected createColumn(question: Question, table: Table): ImageColumn {\n return new ImageColumn(question, table);\n }\n}\nColumnsBuilderFactory.Instance.registerBuilderColumn(\"signaturepad\", new ImageColumnsBuilder());\n\nexport class FileColumnsBuilder extends DefaultColumnsBuilder<QuestionFileModel> {\n protected createColumn(question: QuestionFileModel, table: Table): FileColumn {\n return new FileColumn(question, table);\n }\n}\nColumnsBuilderFactory.Instance.registerBuilderColumn(\"file\", new FileColumnsBuilder());\n\nexport class MatrixDropdownColumnBuilder extends DefaultColumnsBuilder {\n public buildColumns(questionBase: QuestionMatrixDropdownModel, table: Table): Array<IColumn> {\n const question = <QuestionMatrixDropdownModel>questionBase;\n const columns = [];\n question.rows.forEach(row => {\n question.columns.forEach(col => {\n columns.push(new MatrixDropdownColumn(question, row, col, table));\n });\n });\n return columns;\n }\n}\nColumnsBuilderFactory.Instance.registerBuilderColumn(\"matrixdropdown\", new MatrixDropdownColumnBuilder());\n\nexport class CustomColumnsBuilder extends DefaultColumnsBuilder<QuestionCustomModel> {\n protected createColumn(question: QuestionCustomModel, table: Table): CustomQuestionColumn {\n return new CustomQuestionColumn(question, table);\n }\n}\nColumnsBuilderFactory.Instance.registerBuilderColumn(\"custom\", new CustomColumnsBuilder());\n\nexport class CompositeColumnsBuilder extends DefaultColumnsBuilder<QuestionCompositeModel> {\n protected createColumn(question: QuestionCompositeModel, table: Table): CompositeQuestionColumn {\n return new CompositeQuestionColumn(question, table);\n }\n}\nColumnsBuilderFactory.Instance.registerBuilderColumn(\"composite\", new CompositeColumnsBuilder());","import { SurveyModel, Question, Event, Serializer, EventBase } from \"survey-core\";\nimport { hasLicense } from \"survey-core\";\nimport {\n IPermission,\n QuestionLocation,\n ITableState,\n IColumn,\n IColumnData,\n} from \"./config\";\nimport { Details } from \"./extensions/detailsextensions\";\nimport { localization } from \"../localizationManager\";\nimport { ITableExtension, TableExtensions } from \"./extensions/tableextensions\";\nimport { createCommercialLicenseLink, createImagesContainer, createLinksContainer, DocumentHelper } from \"../utils\";\nimport { ColumnsBuilderFactory } from \"./columnbuilder\";\nimport { DefaultColumn } from \"./columns\";\n\nexport interface ITableOptions {\n [index: string]: any;\n\n /**\n * Set this property to true to render column headings using question names\n */\n useNamesAsTitles?: boolean;\n /**\n * Use this event to change the display value of question in table.\n * <br/> `sender` - the table object that fires the event.\n * <br/> `options.question` - the question obect for which event is fired.\n * <br/> `options.displayValue` - the question display value. You can change this option before it is displayed in the table.\n */\n onGetQuestionValue?: (options: {\n question: Question,\n displayValue: any,\n }) => void;\n}\n\nexport type TabulatorFilter = { field: string, type: string, value: any };\nexport type TabulatorSortOrder = { field: string, direction: undefined | \"asc\" | \"desc\" };\nexport type GetDataUsingCallbackFn = (params: { filter?: Array<TabulatorFilter>, sort?: Array<TabulatorSortOrder>, offset?: number, limit?: number, callback?: (response: { data: Array<Object>, totalCount: number, error?: any }) => void }) => void;\nexport type GetDataUsingPromiseFn = (params: { filter?: Array<TabulatorFilter>, sort?: Array<TabulatorSortOrder>, offset?: number, limit?: number }) => Promise<{ data: Array<Object>, totalCount: number, error?: any }>;\nexport type GetDataFn = GetDataUsingCallbackFn | GetDataUsingPromiseFn;\n// export type GetDataFn = (params: { filter?: any, limit?: number, offset?: number, callback?: (response: { data: Array<Object>, total: number, error?: any }) => void }) => Promise<{ data: Array<Object>, total: number, error?: any }> | void;\n\nexport class TableEvent extends EventBase<Table> {}\n\nexport abstract class Table {\n public static showFilesAsImages = false;\n public static haveCommercialLicense: boolean = false;\n protected tableData: any;\n protected extensions: TableExtensions;\n private haveCommercialLicense = false;\n protected _columns: Array<IColumn>;\n constructor(\n protected _survey: SurveyModel,\n protected data: Array<Object> | GetDataFn,\n protected _options: ITableOptions = {},\n protected _columnsData: Array<IColumnData> = []\n ) {\n if(!this._options) {\n this._options = {};\n }\n\n this._columns = this.buildColumns(_survey);\n this.initTableData(data);\n localization.currentLocale = this._survey.locale;\n this._columns = this.buildColumns(_survey);\n\n if(_columnsData.length !== 0) {\n this.updateColumnsFromData(this._columnsData);\n }\n\n this.extensions = new TableExtensions(this);\n const f = hasLicense;\n this.haveCommercialLicense = (!!f && f(4)) ||\n Table.haveCommercialLicense ||\n (!!_options &&\n (typeof _options.haveCommercialLicense !== \"undefined\"\n ? _options.haveCommercialLicense\n : false));\n }\n protected renderResult: HTMLElement;\n protected currentPageSize: number = 5;\n protected currentPageNumber: number;\n protected _rows: TableRow[] = [];\n protected isColumnReorderEnabled: boolean;\n\n public getTableData(): Array<any> {\n return [].concat(this.tableData || []);\n }\n /**\n * Sets pagination selector content.\n */\n public paginationSizeSelector: number[] = [1, 5, 10, 25, 50, 100];\n\n public onColumnsVisibilityChanged = new TableEvent();\n\n public onColumnsLocationChanged = new TableEvent();\n\n public onRowRemoved =new TableEvent();\n\n public renderDetailActions: (\n container: HTMLElement,\n row: TableRow\n ) => HTMLElement;\n\n public getData() {\n return this.data;\n }\n public get survey() {\n return this._survey;\n }\n public get options() {\n return this._options;\n }\n\n public abstract applyFilter(value: string): void;\n public abstract applyColumnFilter(columnName: string, value: string): void;\n public abstract sortByColumn(columnName: string, direction: string): void;\n\n public render(targetNode: HTMLElement | string): void {\n if (typeof targetNode === \"string\") {\n targetNode = document.getElementById(targetNode);\n }\n targetNode.innerHTML = \"\";\n if (!this.haveCommercialLicense) {\n targetNode.appendChild(createCommercialLicenseLink());\n }\n }\n\n public enableColumnReorder() {\n this.isColumnReorderEnabled = true;\n }\n\n public disableColumnReorder(): void {\n this.isColumnReorderEnabled = false;\n }\n\n public getPageNumber(): number {\n return this.currentPageNumber;\n }\n\n public setPageNumber(value: number) {\n this.currentPageNumber = value;\n }\n\n /**\n * Returns current page size.\n */\n public getPageSize(): number {\n return this.currentPageSize;\n }\n\n /**\n * Sets current page size.\n */\n public setPageSize(value: number): void {\n this.currentPageSize = value;\n this.onStateChanged.fire(this, this.state);\n }\n\n public getCreatedRows(): TableRow[] {\n return [].concat(this._rows);\n }\n\n public clearCreatedRows(): void {\n this._rows.forEach((row) => {\n row.destroy();\n });\n this._rows = [];\n }\n\n public get useNamesAsTitles() {\n return this._options && this._options.useNamesAsTitles === true;\n }\n\n protected buildColumns = (survey: SurveyModel) => {\n let columns: Array<IColumn> = [];\n this._survey.getAllQuestions().forEach((question: Question) => {\n if(!this.isNonValueQuestion(question)) {\n const builder = ColumnsBuilderFactory.Instance.getColumnsBuilder(question.getTemplate());\n columns = columns.concat(builder.buildColumns(question, this));\n }\n });\n return columns;\n };\n private isNonValueQuestion(question: Question): boolean {\n return Serializer.isDescendantOf(question.getType(), \"nonvalue\");\n }\n\n public isColumnVisible(column: IColumn) {\n if (column.location !== QuestionLocation.Column) return false;\n return column.isVisible;\n }\n\n public get columns() {\n return [].concat(this._columns);\n }\n\n public set columns(columns: Array<IColumn>) {\n this._columns = columns;\n this.refresh(true);\n this.onStateChanged.fire(this, this.state);\n }\n\n private isInitTableDataProcessingValue: boolean;\n public get isInitTableDataProcessing(): boolean { return this.isInitTableDataProcessingValue; }\n protected initTableData(data: Object[] | GetDataFn): void {\n if(!Array.isArray(data)) {\n this.tableData = undefined;\n return;\n }\n this.isInitTableDataProcessingValue = true;\n this.tableData = (data || []).map((item) => this.processLoadedDataItem(item));\n this.isInitTableDataProcessingValue = false;\n }\n protected processLoadedDataItem(item: any): any {\n var dataItem: any = {};\n this._survey.data = item;\n this._columns.forEach((column) => {\n const opt = column.getCellData(this, item);\n if (typeof this._options.onGetQuestionValue === \"function\") {\n this._options.onGetQuestionValue(opt);\n }\n dataItem[column.name] = opt.displayValue;\n });\n return dataItem;\n }\n\n public moveColumn(from: number, to: number) {\n var deletedColumns = this._columns.splice(from, 1);\n this._columns.splice(to, 0, deletedColumns[0]);\n this.onStateChanged.fire(this, this.state);\n }\n\n public setColumnLocation(columnName: string, location: QuestionLocation) {\n this.getColumnByName(columnName).location = location;\n this.onColumnsLocationChanged.fire(this, {\n columnName: columnName,\n location: location,\n });\n this.onStateChanged.fire(this, this.state);\n }\n\n public getColumnByName(columnName: string): IColumn {\n return this._columns.filter((column) => column.name === columnName)[0];\n }\n\n public setColumnVisibility(columnName: string, isVisible: boolean) {\n var column = this.getColumnByName(columnName);\n column.isVisible = isVisible;\n this.onColumnsVisibilityChanged.fire(this, {\n columnName: columnName,\n columnVisibility: isVisible,\n });\n this.onStateChanged.fire(this, this.state);\n }\n\n public setColumnWidth(columnName: string, width: string | number) {\n var column = this.getColumnByName(columnName);\n column.width = width;\n this.onStateChanged.fire(this, this.state);\n }\n\n public removeRow(row: TableRow): void {\n var index = this._rows.indexOf(row);\n this._rows.splice(index, 1);\n this.onRowRemoved.fire(this, { row: row });\n }\n\n /**\n * Returns current locale of the table.\n * If locales more than one, the language selection dropdown will be added in the toolbar\n */\n public get locale() {\n return localization.currentLocale;\n }\n\n /**\n * Sets locale for table.\n */\n public set locale(newLocale: string) {\n this._survey.locale = newLocale;\n localization.currentLocale = newLocale;\n this.refresh(true);\n this.onStateChanged.fire(this, this.state);\n }\n\n public getLocales(): Array<string> {\n return [].concat(this._survey.getUsedLocales());\n }\n\n public refresh(hard: boolean = false) {\n if (hard) {\n this.initTableData(this.data);\n }\n if (this.isRendered) {\n this.currentPageNumber = this.getPageNumber();\n const targetNode = this.renderResult;\n this.destroy();\n this.render(targetNode);\n this.setPageSize(this.currentPageSize);\n this.setPageNumber(this.currentPageNumber);\n }\n }\n\n public destroy() {\n this.clearCreatedRows();\n this.extensions.destroy();\n this.renderResult.innerHTML = \"\";\n this.renderResult = undefined;\n }\n\n public get isRendered() {\n return !!this.renderResult;\n }\n\n /**\n * Vizualization panel state getter.\n */\n public get state(): ITableState {\n return {\n locale: localization.currentLocale,\n elements: JSON.parse(JSON.stringify(this._columns)),\n pageSize: this.currentPageSize,\n };\n }\n /**\n * Vizualization panel state setter.\n */\n public set state(newState: ITableState) {\n if (!newState) return;\n\n if (typeof newState.locale !== \"undefined\") {\n localization.currentLocale = newState.locale;\n this._survey.locale = newState.locale;\n this.initTableData(this.data);\n }\n\n if (typeof newState.elements !== \"undefined\")\n this.updateColumnsFromData(newState.elements);\n if (typeof newState.pageSize !== \"undefined\")\n this.currentPageSize = newState.pageSize;\n }\n\n private updateColumnsFromData(columnsData: Array<IColumnData>) {\n const columns = this._columns;\n columns.forEach(column => {\n const el = columnsData.filter(el => column.name === el.name)[0];\n if(!!el) {\n column.fromJSON(el);\n column.visibleIndex = columnsData.indexOf(el);\n }\n });\n columnsData.forEach(el => {\n let column = columns.filter(column => column.name === el.name)[0];\n if(!column) {\n column = new DefaultColumn(undefined, this);\n column.fromJSON(el);\n column.visibleIndex = columnsData.indexOf(el);\n columns.push(column);\n }\n });\n this._columns = this._columns.sort((col1, col2) => col1.visibleIndex - col2.visibleIndex);\n }\n\n /**\n * Fires when table state changed.\n */\n public onStateChanged = new TableEvent();\n\n /**\n * Gets table permissions.\n */\n public get permissions(): IPermission[] {\n return <any>this._columns.map((column: IColumn) => {\n return {\n name: column.name,\n isPublic: column.isPublic,\n };\n });\n }\n /**\n * Sets table permissions.\n */\n public set permissions(permissions: IPermission[]) {\n const updatedElements = this._columns.map((column: IColumn) => {\n permissions.forEach((permission) => {\n if (permission.name === column.name)\n column.isPublic = permission.isPublic;\n });\n\n return column;\n });\n this._columns = [].concat(updatedElements);\n this.onPermissionsChangedCallback &&\n this.onPermissionsChangedCallback(this);\n }\n\n /**\n * Fires when permissions changed\n */\n public onPermissionsChangedCallback: any;\n\n protected get allowSorting(): boolean {\n return this.options.allowSorting === undefined || this.options.allowSorting === true;\n }\n\n public allowExtension(extension: ITableExtension): boolean {\n if(extension.location === \"column\" && extension.name === \"sort\") {\n return this.allowSorting;\n }\n return true;\n }\n}\n\nexport abstract class TableRow {\n constructor(\n protected table: Table,\n protected extensionsContainer: HTMLElement,\n protected detailsContainer: HTMLElement\n ) {\n this.details = new Details(table, this, detailsContainer);\n this.extensions = new TableExtensions(table);\n table.onColumnsLocationChanged.add(this.onColumnLocationChangedCallback);\n }\n public details: Details;\n public extensions: TableExtensions;\n private detailedRowClass = \"sa-table__detail-row\";\n private isDetailsExpanded = false;\n public onToggleDetails: Event<\n (sender: TableRow, options: any) => any,\n TableRow,\n any\n > = new Event<(sender: TableRow, options: any) => any, TableRow, any>();\n\n /**\n * Returns row's html element\n */\n public abstract getElement(): HTMLElement;\n\n /**\n * Returns data, which is displayed in the row.\n */\n public abstract getRowData(): any;\n\n /**\n * Returns position of row in the table's data.\n */\n public abstract getDataPosition(): number;\n\n protected isSelected: boolean;\n\n public render() {\n this.extensions.render(this.extensionsContainer, \"row\", { row: this });\n }\n\n public openDetails() {\n this.details.open();\n this.getElement().className += \" \" + this.detailedRowClass;\n this.onToggleDetails.fire(this, { isExpanded: true });\n this.isDetailsExpanded = true;\n }\n\n public closeDetails() {\n this.details.close();\n this.getElement().classList.remove(this.detailedRowClass);\n this.onToggleDetails.fire(this, { isExpanded: false });\n this.isDetailsExpanded = false;\n }\n\n public toggleDetails() {\n if (this.isDetailsExpanded) {\n this.closeDetails();\n } else this.openDetails();\n }\n\n public getIsSelected(): boolean {\n return this.isSelected;\n }\n\n public toggleSelect(): void {\n this.isSelected = !this.isSelected;\n }\n\n public remove(): void {\n this.table.removeRow(this);\n this.destroy();\n }\n\n private onColumnLocationChangedCallback = () => {\n this.closeDetails();\n };\n\n public destroy(): void {\n this.table.onColumnsLocationChanged.remove(\n this.onColumnLocationChangedCallback\n );\n this.extensions.destroy();\n }\n}","export const ARIAL_FONT = \"AAEAAAAXAQAABABwRFNJRyQ9+ecABX+MAAAafEdERUZeI11yAAV1GAAAAKZHU1VC1fDdzAAFdcAAAAmqSlNURm0qaQYABX9sAAAAHkxUU0iAZfo8AAAceAAABo5PUy8yDN8yawAAAfgAAABWUENMVP17PkMABXTgAAAANlZETVhQkmr1AAAjCAAAEZRjbWFw50BqOgAA0cQAABdqY3Z0IJYq0nYAAPqgAAAGMGZwZ23MeVmaAADpMAAABm5nYXNwABgACQAFdNAAAAAQZ2x5Zg73j+wAARr8AAPnYmhkbXi+u8OXAAA0nAAAnShoZWFkzpgmkgAAAXwAAAA2aGhlYRIzEv8AAAG0AAAAJGhtdHgONFhAAAACUAAAGihrZXJuN2E5NgAFAmAAABVgbG9jYQ5haTIAAQDQAAAaLG1heHALRwyoAAAB2AAAACBuYW1lwPJlOwAFF8AAABsNcG9zdI/p134ABTLQAABB/3ByZXBS/sTpAADvoAAACv8AAQAAAAMAAObouupfDzz1CBsIAAAAAACi4ycqAAAAALnVtPb6r/1nEAAIDAAAAAkAAQABAAAAAAABAAAHPv5OAEMQAPqv/iYQAAABAAAAAAAAAAAAAAAAAAAGigABAAAGigEAAD8AdgAHAAIAEAAvAFYAAAQNCv8AAwACAAEDiAGQAAUAAAWaBTMAAAEbBZoFMwAAA9EAZgISCAUCCwYEAgICAgIEAAB6h4AAAAAAAAAIAAAAAE1vbm8AQAAg//wF0/5RATMHPgGyQAAB////AAAAAAYAAQAAAAAAAjkAAAI5AAACOQCwAtcAXgRzABUEcwBJBx0AdwVWAFgBhwBaAqoAfAKqAHwDHQBABKwAcgI5AKoCqgBBAjkAugI5AAAEcwBVBHMA3wRzADwEcwBWBHMAGgRzAFUEcwBNBHMAYQRzAFMEcwBVAjkAuQI5AKoErABwBKwAcgSsAHAEcwBaCB8AbwVW//0FVgCWBccAZgXHAJ4FVgCiBOMAqAY5AG0FxwCkAjkAvwQAADcFVgCWBHMAlgaqAJgFxwCcBjkAYwVWAJ4GOQBYBccAoQVWAFwE4wAwBccAoQVWAAkHjQAZBVYACQVWAAYE4wApAjkAiwI5AAACOQAnA8EANgRz/+ECqgBZBHMASgRzAIYEAABQBHMARgRzAEsCOQATBHMAQgRzAIcBxwCIAcf/ogQAAIgBxwCDBqoAhwRzAIcEcwBEBHMAhwRzAEgCqgCFBAAAPwI5ACQEcwCDBAAAGgXHAAYEAAAPBAAAIQQAACgCrAA5AhQAvAKsAC8ErABXBVb//QVW//0FxwBoBVYAogXHAJwGOQBjBccAoQRzAEoEcwBKBHMASgRzAEoEcwBKBHMASgQAAFAEcwBLBHMASwRzAEsEcwBLAjkAvQI5ACMCOf/lAjkACQRzAIcEcwBEBHMARARzAEQEcwBEBHMARARzAIMEcwCDBHMAgwRzAIMEcwBJAzMAgARzAGsEcwAbBHMAUQLNAG0ETAABBOMAmQXlAAMF5QADCAAA4QKqAN4CqgA9BGQATggAAAEGOQBTBbQAmgRkAE4EZABNBGQATQRz//0EnACgA/QAOAW0AHoGlgChBGQAAAIxAAAC9gAvAuwALQYlAH8HHQBEBOMAgQTjAJ4CqgDoBKwAcgRkAFQEcwAuBGQAMwTlABoEcwCGBHMAjAgAAO8FVv/9BVb//QY5AGMIAACBB40AUgRz//wIAAAAAqoAUwKqAEcBxwCAAccAbARkAE4D9AAvBAAAIQVWAAYBVv45BHP/5AKqAFwCqgBcBAAAFwQAABcEcwBJAjkAuQHHAGwCqgBHCAAAJQVW//0FVgCiBVb//QVWAKIFVgCiAjkAjQI5/+ACOQAEAjkAFQY5AGMGOQBjBjkAYwXHAKEFxwChBccAoQI5AMYCqgAZAqoABgKqAB0CqgAuAqoA5QKqAKICqgBrAqoAOgKqALcCqgAoBHMAAAHHAAMFVgBcBAAAPwTjACkEAAAoAhQAvAXH//0EcwBJBVYABgQAACEFVgCeBHMAhwSsAHIErAChAqoAawKqABkCqgAhBqwAawasAGsGrAAhBHMAAAY5AG0EcwBCAjkAsQVWAFwEAAA/BccAZgQAAFAFxwBmBAAAUARzAEYEa//hAqoB8QVW//0EcwBKBVb//QRzAEoFxwCeBOsARwXH//0FVgCiBHMASwVWAKIEcwBLBHMAlgHHAEIEcwCWAlUAiARzAJoCrACDBccAnARzAIcFxwCcBHMAhwY5AGMEcwBEBccAoQKqAIUFxwChAqoAPAVWAFwEAAA/BOMAMAI5ACQE4wAwAwAAIwXHAKEEcwCDBccAoQRzAIME4wApBAAAKATjACkEAAAoBGgApAY5AGAGYgBVBKAASAR0AEgDkQBiBPAARAMpAC4FMABIBGv/4QQAALAC6wBSCMAAMwgAAE8EAACZCAAATwQAAJkIAABPBAAAmAQAAJgH1QFqBcAAngSrAHIE1QCdBKwAcQTVAiIE1QEFBav/6QUAAckFqwJ+Bav/6QWrAn4Fq//pBasCfgWr/+kFq//pBav/6QWr/+kFq//pBasBwAWrAn4FqwHABasBwAWr/+kFq//pBav/6QWrAn4FqwHABasBwAWr/+kFq//pBav/6QWrAn4FqwHABasBwAWr/+kFq//pBav/6QWr/+kFq//pBav/6QWr/+kFq//pBav/6QWr/+kFq//pBav/6QWr/+kFq//pBav/6QWr/+kFqwLWBasAZgWr/+oF1f//BNUAkggAAAAH6wEwB+sBIAfrATAH6wEgBNUAsgTVAIAE1QAqCCsBmAhrAbgHVQAQBgAA9AYAAG8EQAA6BUAANwTAAD8EFQBABAAAJQYAAFUF4QC/A40AiQTV/9kBgACAAtUAhgcVAGEClgAPBNUAkgLWAIMC1gCDBNUAsgLWAHAFVv/9BHMASgXHAGYEAABQBccAZgQAAFAFVgCiBHMASwVWAKIEcwBLBVYAogRzAEsGOQBtBHMAQgY5AG0EcwBCBjkAbQRzAEIFxwCkBHMAhwXHAB8EcwAGAjn/zgI5/84COf/kAjn/5AI5//YCOf/1AjkAowHHAGYEAAA3Acf/ogVWAJYEAACIBAAAhgRzAJYBx//6BccAnARzAIcFyQClBHMAiwY5AGMEcwBEBjkAYwRzAEQFxwChAqoAawVWAFwEAAA/BOMAMAI5AAwFxwChBHMAgwXHAKEEcwCDBccAoQRzAIMFxwChBHMAgweNABkFxwAGBVYABgQAACEBxwCJBVb//QRzAEoIAAABBx0ARAY5AFME4wCBAjkAuQeNABkFxwAGB40AGQXHAAYHjQAZBccABgVWAAYEAAAhAccAigKq/+EEcwAbBM0AWgasAGsGrAAiBqwAIgasAEoCqgDiAqoAawKqAN4Cqv/qBVf//wZG/6cGtP+oAxL/qAYy/6cG2P+nBgX/pwHH/3gFVv/9BVYAlgVY//4FVgCiBOMAKQXHAKQCOQC/BVYAlgVYAAsGqgCYBccAnAUzAG0GOQBjBccApAVWAJ4E8gCUBOMAMAVWAAYFVgAJBq8AfwX7AGECOQAEBVYABgSgAEgDkQBiBHMAiwHHAGsEYACIBJoAjAQAABkDhwBIBHMAiwRzAFwBxwCJBAAAhgQAAB