v1.php 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. <?php
  2. namespace zin;
  3. class pivotTable extends wg
  4. {
  5. /**
  6. * @var mixed[]
  7. */
  8. protected static $defineProps = array(
  9. 'title?: string',
  10. 'class?: string',
  11. 'width?: string',
  12. 'cols?: array',
  13. 'data?: array',
  14. 'cellSpan?: array',
  15. 'filters?: array',
  16. 'onRenderCell?: function',
  17. 'onCellClick?: function'
  18. );
  19. /**
  20. * @var mixed[]
  21. */
  22. protected static $defineBlocks = array(
  23. 'heading' => array()
  24. );
  25. public static function getPageCSS()
  26. {
  27. return file_get_contents(__DIR__ . DS . 'css' . DS . 'v1.css');
  28. }
  29. public static function getPageJS()
  30. {
  31. return file_get_contents(__DIR__ . DS . 'js' . DS . 'v1.js');
  32. }
  33. protected function buildFilters()
  34. {
  35. global $lang;
  36. list($filters) = $this->prop(array('filters'));
  37. if(empty($filters)) return div(setID('conditions'), setClass('mb-4'));
  38. return div
  39. (
  40. setID('conditions'),
  41. setClass('flex justify-start bg-canvas mt-4 mb-2 w-full' . (count($filters) == 1 ? ' flex-wrap' : ' items-center')),
  42. count($filters) == 1 ? $filters : div
  43. (
  44. setClass('flex flex-wrap w-full'),
  45. $filters
  46. ),
  47. button(setClass('btn primary mb-2 load-custom-pivot'), $lang->pivot->query)
  48. );
  49. }
  50. protected function buildDTable()
  51. {
  52. global $lang;
  53. list($cols, $data, $cellSpan, $filters, $onRenderCell, $onCellClick) = $this->prop(array('cols', 'data', 'cellSpan', 'filters', 'onRenderCell', 'onCellClick'));
  54. $filterCount = count($filters);
  55. $filterAllEmpty = $filterCount ? empty(array_filter(array_column($filters, 'default'))) : false;
  56. $emptyTip = $filterAllEmpty ? $lang->pivot->filterEmptyVal : $lang->pivot->noPivotTip;
  57. if(empty($onRenderCell)) $onRenderCell = jsRaw(<<<JS
  58. function(result, {row, col})
  59. {
  60. if(result)
  61. {
  62. let values = result.shift();
  63. let isDrill = row.data.isDrill[col.name];
  64. let isTotal = row.data.isTotal;
  65. if(col.setting.colspan && typeof(values.type) != 'undefined' && values.type == 'a')
  66. {
  67. values = values.props['children'];
  68. result.push({className: 'gap-0 p-0.5'});
  69. values.forEach((value, index) =>
  70. result.push({
  71. html: value || !Number.isNaN(value) ? (isDrill && index == 0 ? "<a href='#'>" + `\${value}` + '</a>' : `\${value}`) : '&nbsp;',
  72. className: 'flex justify-center items-center h-full w-1/2' + (index == 0 ? ' border-r': ''),
  73. style: 'border-color: var(--dtable-border-color)' + (isTotal ? '; background-color: var(--color-surface-light);' : '')
  74. })
  75. );
  76. }
  77. else
  78. {
  79. if(!isDrill && values?.type == 'a') values = values.props.children;
  80. if(isTotal)
  81. {
  82. result.push({className: 'gap-0 p-0.5'});
  83. values = {
  84. html: values,
  85. className: 'flex justify-center items-center h-full w-full',
  86. style: 'border-color: var(--dtable-border-color)' + (isTotal ? '; background-color: var(--color-surface-light);' : '')
  87. };
  88. }
  89. result.push(values);
  90. }
  91. }
  92. return result;
  93. }
  94. JS
  95. );
  96. return dtable
  97. (
  98. setID('designTable'),
  99. set::bordered(true),
  100. set::height(jsRaw("() => getHeight(800, $filterCount)")),
  101. set::cols($cols),
  102. set::data($data),
  103. set::emptyTip($emptyTip),
  104. set::rowHover(false),
  105. set::colHover(false),
  106. set::onRenderCell($onRenderCell),
  107. set::onCellClick($onCellClick),
  108. set::rowKey('ROW_ID'),
  109. set::plugins(array('header-group', 'cellspan')),
  110. set::getCellSpan(jsRaw(<<<JS
  111. function(cell)
  112. {
  113. const options = this.options.cellSpanOptions[cell.col.name];
  114. if(options)
  115. {
  116. const rowSpan = cell.row.data[options.rowspan ?? 'rowspan'] ?? 1;
  117. const colSpan = cell.row.data[options.colspan ?? 'colspan'] ?? 1;
  118. return {rowSpan, colSpan};
  119. }
  120. console.log(options);
  121. }
  122. JS
  123. )),
  124. set::cellSpanOptions($cellSpan)
  125. );
  126. }
  127. protected function build()
  128. {
  129. global $lang;
  130. list($title, $class, $width) = $this->prop(array('title', 'class', 'width'));
  131. return div
  132. (
  133. setClass('dtable-content bg-canvas', $class),
  134. setStyle('width', $width),
  135. panel
  136. (
  137. set::title($title),
  138. set::shadow(false),
  139. set::bodyClass('pt-0 panel-body-height'),
  140. $this->buildFilters(),
  141. $this->buildDTable(),
  142. set::headingClass('h-12 border-b'),
  143. to::heading($this->block('heading'))
  144. )
  145. );
  146. }
  147. }