Procházet zdrojové kódy

fixed Storage Struktura link

Piotr Labudda před 8 roky
rodič
revize
b6a2753cf0

+ 1 - 2
SE/se-lib/Route/Storage.php

@@ -620,9 +620,8 @@ jQuery(document).on('p5UIBtnAjax:Storage:checkObjectInstallAjax:ajaxLoaded', fun
 							]),
 							UI::h('div', ['class' => "p5UI__dropdown-content"], [
 								UI::h('input', ['type' => "text", 'placeholder' => "Search..", 'class' => "p5UI__dropdown-input", 'onkeyup' => "p5_Storage_actions_filterInput(this)"], null),
+								UI::h('a', [ 'href' => Router::getRoute('Storage_AclStruct')->getLink('', [ 'namespace' => $item['namespace'] ]) ], "struktura"),
 								UI::h('a', [ 'href' => $item['reinstallLink'] ], "reinstall"),
-								UI::h('a', [ 'href' => Router::getRoute('Storage_AclStruct')->getLink('tableStruct', [ 'idStorage' => $idStorage, 'table' => $item['name'] ]) ], "struktura tabeli (TableAcl)"),
-								UI::h('a', [ 'href' => Router::getRoute('Storage_AclStruct')->getLink('', [ 'idStorage' => $idStorage, 'namespace' => $item['namespace'] ]) ], "struktura obiektu (AntAcl)"),
 								UI::h('a', [ 'href' => $this->getLink('rawInfo', [ 'idStorage' => $idStorage, 'table' => $item['name'] ]) ], "raw info"),
 								UI::h('a', [ 'href' => Router::getRoute('ViewTableAjax')->getLink('', ['namespace' => $item['namespace']]) ], "view table"),
 								UI::h('a', [ 'href' => Router::getRoute('ViewObject')->getLink('', ['namespace' => $item['namespace']]) ], "view object"),

+ 516 - 472
SE/se-lib/Route/Storage/AclStruct.php

@@ -14,7 +14,7 @@ class Route_Storage_AclStruct extends RouteBase {
 		}
 	}
 
-	public function defaultAction() { // objectStructAction
+	public function defaultAction() {
 		UI::gora();
 		UI::menu();
 		// Router::getRoute('Storage')->navView(); // TODO: header like in Storage_AclUsage
@@ -22,279 +22,25 @@ class Route_Storage_AclStruct extends RouteBase {
 		try {
 			$namespace = V::get('namespace', '', $_GET);
 			if (empty($namespace)) throw new Exception("Missing param namespace");
-
-			if ('setFieldRefConfig' === V::get('_postTask', '', $_POST)) {
-				$field = V::get('field', '', $_POST);
-				$source = V::get('source', '', $_POST);
-				switch ($source) {
-					case 'view':
-						$refSelect = ACL::generateRefSelectSqlByFlatRelationCache($namespace, $field);
-						ACL::setRefSource($namespace, $field, 'view', $refSelect);
-						break;
-					case 'table': ACL::setRefSource($namespace, $field, 'table'); break;
-				}
-			}
-			if ('preview' === V::get('_postTask', '', $_POST)) {
-				try {
-					$item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
-					$localFields = array_filter($item['field'], function ($field) {
-						return $field['isLocal'];
-					});
-					$refFields = array_filter($item['field'], function ($field) {
-						return 'ref:' === substr($field['xsdType'], 0, 4);
-					});
-					$activeRefFields = array_filter($refFields, function ($field) {
-						$refNamespace = str_replace(['__x3A__', ':'], '/', substr($field['xsdType'], strlen('ref:')));
-						return (1 == DB::getPDO()->fetchValue("
-							select t.isObjectActive
-							from `CRM_#CACHE_ACL_OBJECT` t
-							where t.`namespace` = '{$refNamespace}'
-						"));
-					});
-					$query = [ 'cols' => array_merge(
-						array_map(
-							function ($field) {
-								return $field['fieldNamespace'];
-							}, $localFields
-						),
-						array_map(
-							function ($field) {
-								return "{$field['fieldNamespace']}/*";
-							}, $activeRefFields
-						)
-					) ];
-					DBG::nicePrint($query, '$query');
-
-					$previewItems = ACL::getAclByNamespace($namespace)->buildQuery($query)->getItems([
-						'limit' => 3
-					]);
-					DBG::nicePrint($previewItems, 'items with ref limit 3');
-				} catch (Exception $e) {
-					DBG::log($e);
-					UI::alert('danger', $e->getMessage());
-				}
-			}
-
+			// [idZasob] => 25872
+	    // [idDatabase] => 36
+	    // [namespace] => default_db/CRM_PROCES/CRM_PROCES
+	    // [_rootTableName] => CRM_PROCES
+	    // [_type] => AntAcl
+	    // [hasStruct] => 1
+	    // [isStructInstalled] => 1
+	    // [isObjectActive] => 1
+	    // [description] =>
+	    // [name] => CRM_PROCES
+	    // [nsPrefix] => default_db__x3A__CRM_PROCES
+	    // [typeName] => default_db__x3A__CRM_PROCES:CRM_PROCES
+	    // [reinstallLink] => https://biuro.biall-net.pl/dev-pl/se-master/index.php?_route=Storage&_task=objectReinstall&namespace=default_db/CRM_PROCES/CRM_PROCES
 			$item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
-			usort($item['field'], function ($a, $b) {
-				if ($a['fieldNamespace'] > $b['fieldNamespace']) return 1;
-				if ($a['fieldNamespace'] < $b['fieldNamespace']) return -1;
-				return 0;
-			});
-
-			echo UI::h('details', ['style'=>"margin-bottom:24px; padding:0 10px; background-color:#eee", 'open' => "open"], [
-				UI::h('summary', ['style'=>"font-size:1.4em; line-height:2em; cursor:pointer; outline:none"], [
-					"Struktura obiektu '{$namespace}' ",
-					// UI::h('small', ['style'=>"font-size:0.8em; font-style:italic; color:#aaa"], " więcej...")
-				]),
-				UI::h('div', ['style'=>"padding:4px 24px; border-top:1px solid #fff"], [
-					UI::h('span', ['style'=>"margin-right:12px"], [
-						( ($item['idZasob'] > 0)
-						? UI::h('span', [ 'title' => "Nr zasobu '{$item['idZasob']}'" ], "Nr zasobu [{$item['idZasob']}]")
-						: UI::h('span', [ 'title' => "Brak nr zasobu - dodaj do zasobów" ], [
-								UI::hButtonAjax("+ do zasobów", 'addAclObjectToZasobyAjax', [
-									'class' => "btn btn-xs btn-primary",
-									'href' => Router::getRoute('Storage')->getLink('addAclObjectToZasobyAjax'),
-									'data' => [
-										'idStorage' => $item['idDatabase'],
-										'namespace' => $item['namespace'],
-									]
-								])
-							])
-						),
-					]),
-					UI::h('span', ['style'=>"margin:0 12px"], [
-						( ($item['isObjectActive'] > 0)
-							? UI::h('span', [ 'class' => "label label-success", 'title' => "Namespace active" ], "Active")
-							: UI::h('span', [ 'title' => "Namespace not active" ], [
-								($item['idZasob'] > 0)
-								? UI::hButtonAjax("Aktywuj", 'activateObjectAjax', [
-										'class' => "btn btn-xs btn-primary",
-										'href' => Router::getRoute('Storage')->getLink('activateObjectAjax'),
-										'data' => [
-											'namespace' => $item['namespace'],
-										]
-									])
-								: '',
-							])
-						),
-					]),
-					UI::h('a', [
-						'href' => "index.php?_route=ViewTableAjax&namespace={$item['namespace']}",
-						'class' => "btn btn-sm btn-link"
-					], "Przeglądaj tabelę"),
-					( ($item['idZasob'] > 0)
-						? UI::h('a', [
-								'href' => "procesy5.php?task=CRM_LISTA_ZASOBOW&filtr_id={$item['idZasob']}&filtr_ids=%2B&filtr_ob=%2B",
-								'class' => "btn btn-sm btn-link",
-								'title' => "Struktura tabeli w drzewie zasobów"
-							], "Zasoby")
-						: ''
-					),
-					( ($item['idZasob'] > 0)
-						? UI::h('a', [
-								'href' => "index.php?FUNCTION_INIT=PROCES_MENU&HEADER_NOT_INIT=YES&_task=PROCES_FOR_TABLE&tblId={$item['idZasob']}",
-								'class' => "btn btn-sm btn-link",
-								'title' => "Procesy dla aktualnie przeglądanej tabeli"
-							], "Procesy")
-						: ''
-					),
-					UI::h('a', [
-						'href' => Router::getRoute('Storage')->getLink('objectReinstall', ['namespace' => $item['namespace']]),
-						'class' => 'btn btn-sm btn-link', 'style' => "color:#f00",
-						'title' => "Zainstaluje ponownie obiekt"
-					], "reinstall object"),
-					UI::h('a', [
-						'href' => Router::getRoute('Storage_AclUsage')->getLink('', [ 'namespace' => $item['namespace'] ]),
-						'class' => "btn btn-sm btn-link",
-						'title' => "Uprawnienia - analiza użycia komórek w procesach"
-					], "Uprawnienia (analiza użycia)"),
-					UI::hButtonPost("(podgląd z relacjami)", [
-						'data' => [
-							'_postTask' => 'preview'
-						],
-						'class' => 'btn btn-sm btn-link', 'style' => "font-style:italic",
-						'title' => "Podgląd kilku ostatnich obiektów wraz z relacjami"
-					]),
-				])
-			]);
-
-			$thisGetLink = [Router::getRoute('Storage'), 'getLink'];
-			{ // not installed ref
-				$refFields = array_filter($item['field'], function ($field) {
-					return 'ref:' === substr($field['xsdType'], 0, 4);
-				});
-				UI::table([
-					'caption' => UI::h('span', [], "Obiekty powiązane (TODO backRef)"),
-					'rows' => array_map(function ($field) use ($thisGetLink) {
-						$refNamespace = str_replace(['__x3A__', ':'], '/', substr($field['xsdType'], strlen('ref:')));
-						$isInstalled = (1 == DB::getPDO()->fetchValue("
-							select t.isObjectActive
-							from `CRM_#CACHE_ACL_OBJECT` t
-							where t.`namespace` = '{$refNamespace}'
-						"));
-						$refSource = null;
-						if ($isInstalled) {
-							try {
-								$refTable = ACL::getRefTable($field['objectNamespace'], $field['fieldNamespace']);
-								DBG::log($refTable, 'array', "getRefTable('{$field['objectNamespace']}', '{$field['fieldNamespace']}')");
-								$refSource = ACL::getRefSource($field['objectNamespace'], $field['fieldNamespace']);
-								DBG::log($refSource, 'array', "ACL::getRefSource('{$field['objectNamespace']}', '{$field['fieldNamespace']}')");
-							} catch (Exception $e) {
-								DBG::log($e);
-							}
-						}
-						return [
-							'fieldName' => $field['fieldNamespace'],
-							// 'xsdType' => $field['xsdType'], // always === "ref:{$field['fieldNamespace']}"
-							'ref object' => UI::h('a', [
-								'class' => "btn btn-xs btn-link",
-								'href' => $thisGetLink('objectStruct', [ 'namespace' => $refNamespace ])
-							], "objectStruct ({$refNamespace})"),
-							'ref source' => UI::h('div', [],
-								(null === $refSource)
-								? [ "ref object not installed" ] // TODO: link to install? is table struct
-								: [
-										// UI::hButtonAjax("Tabela ref", "setFieldRefConfig", [
-										// 	'class' => "btn btn-xs btn-default" . ( 'table' === $refSource ? ' disabled' : '' ),
-										// 	'href' => $thisGetLink('setFieldRefConfig'),
-										// 	'data' => [ 'namespace' => $refNamespace, 'field' => $field['fieldNamespace'], 'do' => 'table' ]
-										// ]),
-										// UI::hButtonAjax("Widok (cache)", "setFieldRefConfig", [
-										// 	'title' => "Według flat_relation_cache",
-										// 	'class' => "btn btn-xs btn-default" . ( 'view' === $refSource ? ' disabled' : '' ),
-										// 	'href' => $thisGetLink('setFieldRefConfig'),
-										// 	'data' => [ 'namespace' => $refNamespace, 'field' => $field['fieldNamespace'], 'do' => 'view' ]
-										// ]),
-										UI::hButtonPost("Tabela ref", [
-											'title' => "Według wygenerowanej tabeli REF",
-											'class' => "btn btn-xs btn-default" . ( 'table' === $refSource ? ' disabled' : '' ),
-											// 'href' => $thisGetLink('setFieldRefConfig'),
-											'data' => [ 'namespace' => $refNamespace, 'field' => $field['fieldNamespace'], '_postTask' => 'setFieldRefConfig', 'source' => 'table' ]
-										]),
-										UI::hButtonPost("Widok (cache)", [
-											'title' => "Według flat_relation_cache",
-											'class' => "btn btn-xs btn-default" . ( 'view' === $refSource ? ' disabled' : '' ),
-											// 'href' => $thisGetLink('setFieldRefConfig'),
-											'data' => [ 'namespace' => $refNamespace, 'field' => $field['fieldNamespace'], '_postTask' => 'setFieldRefConfig', 'source' => 'view' ]
-										]),
-									]
-							),
-							'@class' => ($isInstalled) ? "success" : "danger",
-						]; // TODO: link to install object
-					}, $refFields)
-				]);
+			switch ($item['_type']) {
+				case 'TableAcl': $this->tableStructView($item, $item['name'], $item['idDatabase']); break;
+				case 'AntAcl': $this->objectStructView($item); break;
+				default: throw new Exception("Not implemented type"); break;
 			}
-			UI::table([
-				'caption' => UI::h('span', [], [
-					UI::h('span', [ 'style' => "margin-right:6px;color:#000" ], "Struktura obiektu '{$item['namespace']}'"),
-				]),
-				'rows' => array_map(function ($field) use ($item, $thisGetLink) {
-					$tblItem = []; foreach ($field as $k => $v) $tblItem[$k] = $v;
-					$tblItem['namespace'] = UI::h('span', [], [
-						UI::h('span', ['style' => "color:#aaa"], substr($field['namespace'], 0, strlen($field['objectNamespace']) + 1)),
-						UI::h('span', ['style' => "color:#000"], substr($field['namespace'], strlen($field['objectNamespace']) + 1)),
-					]);
-					$tblItem['idZasob'] = ($field['idZasob'] > 0)
-						? $field['idZasob']
-						: (
-								($item['idZasob'] > 0)
-								? UI::hButtonAjax("+ do zasobów", 'addFieldToZasobyAjax', [
-										'class' => "btn btn-xs btn-primary",
-										'href' => $thisGetLink('addFieldToZasobyAjax'),
-										'data' => [
-											'namespace' => $item['namespace'],
-											'fieldNamespace' => $field['namespace'],
-										]
-									])
-								: UI::h('span', ['title'=>"Brak Nr zasobu dla obiektu", 'class'=>"btn btn-xs btn-danger"], "Brak nr zasobu obiektu")
-							)
-					;
-					unset($tblItem['objectNamespace']);
-					unset($tblItem['fieldNamespace']);
-					return $tblItem;
-				}, $item['field'])
-			]);
-			UI::hButtonAjaxOnResponse('addFieldToZasobyAjax', /* payload, n */ "
-				if (!payload.type) return false
-				if (payload.body && payload.body.id && payload.body.id > 0) { // if ('success' == payload.type) {
-					n.parentNode.replaceChild(document.createTextNode(payload.body.id), n)
-				}
-				jQuery.notify(payload.msg, payload.type)
-			");
-			UI::hButtonAjaxOnResponse('addAclObjectToZasobyAjax', /* payload, n */ "
-				if (!payload.type) return false
-				if ('success' === payload.type || 'info' === payload.type) {
-					if (payload.body && payload.body.id && payload.body.id > 0) {
-						n.parentNode.replaceChild(document.createTextNode(payload.body.id), n)
-					} else {
-						console.log('TODO: addAclObjectToZasobyAjax unknown response', payload);
-					}
-					window.location.reload()
-				}
-			");
-			UI::hButtonAjaxOnResponse('activateObjectAjax', /* payload, n */ "
-				jQuery.notify(payload.msg, payload.type)
-				if (!payload.type) return false
-				if ('success' === payload.type || 'info' === payload.type) {
-					if (payload.body && payload.body.isObjectActive && payload.body.isObjectActive > 0) {
-						n.parentNode.replaceChild(document.createTextNode('Active'), n)
-					} else {
-						console.log('TODO: activateObjectAjax unknown response', payload);
-					}
-				}
-			");
-			if ($item['isObjectActive']) {
-				echo UI::hButtonAjax("Dodaj podstawowy proces dla obiektu '{$item['namespace']}' - read only (TODO)", 'addObjectBaseProcesAjax', [
-					'class' => "btn btn-xs btn-default",
-					'href' => Router::getRoute('Storage')->getLink('addObjectBaseProcesAjax'),
-					'data' => [ 'namespace' => $item['namespace'] ]
-				]);
-				UI::hButtonAjaxOnResponse('addObjectBaseProcesAjax', /* payload, n */ "
-					jQuery.notify(payload.msg, payload.type)
-				");
-			}
-			DBG::nicePrint($item, '$item');
 		} catch (Exception $e) {
 			UI::alert('danger', "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage());
 			DBG::log($e);
@@ -316,230 +62,528 @@ class Route_Storage_AclStruct extends RouteBase {
 			$tblName = V::get('table', '', $_REQUEST, 'word');
 			if (empty($tblName)) throw new Exception("No table name");
 
-			$storagePdo = DB::getStorage($idStorage);
-			$tblStruct = $storagePdo->getTableStruct($tblName);
+			$item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
+			$this->tableStructView($item, $tblName, $idStorage);
+		} catch (Exception $e) {
+			UI::alert('danger', "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage());
+		}
+		UI::dol();
+	}
 
-			$idTable = Router::getRoute('Storage')->fetchTableId($idStorage, $tblName);
-			if ($idTable <= 0) {
-				UI::alert('warning', "Zasob tabela '{$tblName}' nie istnieje");// TODO: add p5UI btn
-				DBG::table("tblStruct", $tblStruct, __CLASS__, __FUNCTION__, __LINE__);
-				throw new Exception("Zasob tabela '{$tblName}' nie istnieje");
-			}
+	public function objectStructureAction() { // objectStructAction
+		UI::gora();
+		UI::menu();
+		// Router::getRoute('Storage')->navView(); // TODO: header like in Storage_AclUsage
+		UI::startTag('div', [ 'class' => 'container-fluid' ]);
+		try {
+			$namespace = V::get('namespace', '', $_GET);
+			if (empty($namespace)) throw new Exception("Missing param namespace");
+			$item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
+			$this->objectStructView($item);
+		} catch (Exception $e) {
+			UI::alert('danger', "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage());
+			DBG::log($e);
+		}
+		UI::endTag('div'); // .container-fluid
+		UI::dol();
+	}
 
-			$cellZasobList = array();
-			foreach (DB::getPDO()->fetchAllByKey("
-					select z.ID, z.`DESC`, z.`TYPE` as ZASOB_TYPE, z.A_STATUS
-					from CRM_LISTA_ZASOBOW z
-					where z.PARENT_ID = '{$idTable}'
-				", $key = 'DESC') as $ind => $row) {
-				$cellZasobList[strtolower($ind)] = $row;
-			}
+	public function tableStructView($item, $tblName, $idStorage) {
+		$storagePdo = DB::getStorage($idStorage);
+		$tblStruct = $storagePdo->getTableStruct($tblName);
+
+		$idTable = Router::getRoute('Storage')->fetchTableId($idStorage, $tblName);
+		if ($idTable <= 0) {
+			UI::alert('warning', "Zasob tabela '{$tblName}' nie istnieje");// TODO: add p5UI btn
+			DBG::table("tblStruct", $tblStruct, __CLASS__, __FUNCTION__, __LINE__);
+			throw new Exception("Zasob tabela '{$tblName}' nie istnieje");
+		}
+
+		$cellZasobList = array();
+		foreach (DB::getPDO()->fetchAllByKey("
+				select z.ID, z.`DESC`, z.`TYPE` as ZASOB_TYPE, z.A_STATUS
+				from CRM_LISTA_ZASOBOW z
+				where z.PARENT_ID = '{$idTable}'
+			", $key = 'DESC') as $ind => $row) {
+			$cellZasobList[strtolower($ind)] = $row;
+		}
 
-			$emptyItem = array();
-			$emptyItem['name'] = '';
-			$emptyItem['id_zasob'] = '';
-			$emptyItem['zasob_type'] = '';
-			$emptyItem['uwagi'] = '';
+		$emptyItem = array();
+		$emptyItem['name'] = '';
+		$emptyItem['id_zasob'] = '';
+		$emptyItem['zasob_type'] = '';
+		$emptyItem['uwagi'] = '';
 
-			$emptyItem['type'] = '';
-			$emptyItem['is_nullable'] = '';
-			$emptyItem['default_value'] = '';
-			$emptyItem['default_is_null'] = '';
-			$emptyItem['max_length'] = '';
-			$emptyItem['num_precision'] = '';
-			$emptyItem['num_scale'] = '';
-			$emptyItem['char_encoding'] = '';
-			$emptyItem['char_collation'] = '';
-			$emptyItem['extra'] = '';
-			$emptyItem['raw_storage_type'] = '';
+		$emptyItem['type'] = '';
+		$emptyItem['is_nullable'] = '';
+		$emptyItem['default_value'] = '';
+		$emptyItem['default_is_null'] = '';
+		$emptyItem['max_length'] = '';
+		$emptyItem['num_precision'] = '';
+		$emptyItem['num_scale'] = '';
+		$emptyItem['char_encoding'] = '';
+		$emptyItem['char_collation'] = '';
+		$emptyItem['extra'] = '';
+		$emptyItem['raw_storage_type'] = '';
 
-			$tableList = array();
-			foreach ($tblStruct as $row) {
-				$cellName = $row['name'];
+		$tableList = array();
+		foreach ($tblStruct as $row) {
+			$cellName = $row['name'];
+			$tblItem = V::cloneArray($emptyItem);
+			$tblItem['name'] = $cellName;
+			foreach ($row as $fldName => $fldVal) {
+				if (array_key_exists($fldName, $tblItem)) $tblItem[$fldName] = $fldVal;
+			}
+			$tblItem['uwagi'] = '';
+			$lowerCellName = strtolower($cellName);
+			$tblZasob = V::get($lowerCellName, '', $cellZasobList);
+			if ($tblZasob) {
+				$cellZasobList[$lowerCellName]['_checked'] = true;
+				$tblItem['id_zasob'] = $tblZasob['ID'];
+				$tblItem['zasob_type'] = $tblZasob['ZASOB_TYPE'];
+			} else {
+				$tblItem['uwagi'] .= '!Zasob';//'TODO: ADD ZASOB';
+				$ajaxAddZasobLink = Router::getRoute('Storage')->getLink('addCellToZasoby', [ 'idStorage' => $idStorage, 'tblName' => $tblName, 'cellName' => $cellName]);
+				$onClick = "return p5UI__ButtonAjax(this, 'p5UIBtnAjax:Storage:addCellToZasoby', { href: '{$ajaxAddZasobLink}' })";
+				$tblItem['id_zasob'] = '<a onclick="'.$onClick.'" class="btn btn-xs btn-primary" href="#">TODO: ADD ZASOB</a>';
+			}
+			$tableList[] = $tblItem;
+		}
+		foreach ($cellZasobList as $cellName => $row) {
+			if ('URL_ACTION' == $row['ZASOB_TYPE']) continue;
+			if (!$row['_checked']) {
 				$tblItem = V::cloneArray($emptyItem);
 				$tblItem['name'] = $cellName;
-				foreach ($row as $fldName => $fldVal) {
-					if (array_key_exists($fldName, $tblItem)) $tblItem[$fldName] = $fldVal;
-				}
-				$tblItem['uwagi'] = '';
-				$lowerCellName = strtolower($cellName);
-				$tblZasob = V::get($lowerCellName, '', $cellZasobList);
-				if ($tblZasob) {
-					$cellZasobList[$lowerCellName]['_checked'] = true;
-					$tblItem['id_zasob'] = $tblZasob['ID'];
-					$tblItem['zasob_type'] = $tblZasob['ZASOB_TYPE'];
-				} else {
-					$tblItem['uwagi'] .= '!Zasob';//'TODO: ADD ZASOB';
-					$ajaxAddZasobLink = Router::getRoute('Storage')->getLink('addCellToZasoby', [ 'idStorage' => $idStorage, 'tblName' => $tblName, 'cellName' => $cellName]);
-					$onClick = "return p5UI__ButtonAjax(this, 'p5UIBtnAjax:Storage:addCellToZasoby', { href: '{$ajaxAddZasobLink}' })";
-					$tblItem['id_zasob'] = '<a onclick="'.$onClick.'" class="btn btn-xs btn-primary" href="#">TODO: ADD ZASOB</a>';
-				}
+				$tblItem['id_zasob'] = $row['ID'];
+				$tblItem['zasob_type'] = $row['ZASOB_TYPE'];
+				$tblItem['uwagi'] = '!DB';//'TODO: nie istnieje w bazie danych';
 				$tableList[] = $tblItem;
 			}
-			foreach ($cellZasobList as $cellName => $row) {
-				if ('URL_ACTION' == $row['ZASOB_TYPE']) continue;
-				if (!$row['_checked']) {
-					$tblItem = V::cloneArray($emptyItem);
-					$tblItem['name'] = $cellName;
-					$tblItem['id_zasob'] = $row['ID'];
-					$tblItem['zasob_type'] = $row['ZASOB_TYPE'];
-					$tblItem['uwagi'] = '!DB';//'TODO: nie istnieje w bazie danych';
-					$tableList[] = $tblItem;
-				}
+		}
+		usort($tableList, function($rowA, $rowB) {
+			$a = $rowA['name']; $b = $rowB['name'];
+			if ('ID' == $a) return -1;
+			if ('ID' == $b) return 1;
+			if ($a == $b) return 0;
+			$a1 = substr($a, 0, 1); $b1 = substr($b, 0, 1);
+			if (('_' == $a1 || '_' == $b1) && $a1 != $b1) {
+				return ($a1 < $b1) ? 1 : -1;
 			}
-			usort($tableList, function($rowA, $rowB) {
-				$a = $rowA['name']; $b = $rowB['name'];
-				if ('ID' == $a) return -1;
-				if ('ID' == $b) return 1;
-				if ($a == $b) return 0;
-				$a1 = substr($a, 0, 1); $b1 = substr($b, 0, 1);
-				if (('_' == $a1 || '_' == $b1) && $a1 != $b1) {
-					return ($a1 < $b1) ? 1 : -1;
+			return ($a < $b) ? -1 : 1;
+		});
+		UI::table([
+			'caption' => UI::h('span', [], [
+				"Komórki [{$idTable}] ",
+				UI::h('a', [
+					'href' => "index.php?_route=ViewTableAjax&namespace=default_db/{$tblName}",
+					'class' => "btn btn-md btn-link"
+				], "Przeglądaj tabelę"),
+				UI::h('a', [
+					'href' => "procesy5.php?task=CRM_LISTA_ZASOBOW&filtr_id={$idTable}&filtr_ids=%2B&filtr_ob=%2B",
+					'class' => "btn btn-md btn-link",
+					'title' => "Struktura aktualnie przeglądanej tabeli"
+				], "Zasoby"),
+				UI::h('a', [
+					'href' => "index.php?FUNCTION_INIT=PROCES_MENU&HEADER_NOT_INIT=YES&_task=PROCES_FOR_TABLE&tblId={$idTable}",
+					'class' => "btn btn-md btn-link",
+					'title' => "Procesy dla aktualnie przeglądanej tabeli"
+				], "Procesy"),
+				UI::h('a', [
+					'href' => Router::getRoute('Storage_AclUsage')->getLink('', [ 'namespace' => "default_db/{$tblName}" ]),
+					'class' => "btn btn-md btn-link",
+					'title' => "Uprawnienia - analiza użycia komórek w procesach"
+				], "Uprawnienia (analiza użycia)"),
+			]),
+			'cols' => array_keys($emptyItem),
+			'rows' => $tableList
+		]);
+		echo UI::h('script', [], "
+			jQuery(document).on('p5UIBtnAjax:Storage:addCellToZasoby:click', function(e, n, payload) {
+				console.log('event p5UIBtnAjax:Storage:addCellToZasoby:click', n, payload);
+			});
+			jQuery(document).on('p5UIBtnAjax:Storage:addCellToZasoby:ajaxLoaded', function(e, n, payload) {
+				console.log('event p5UIBtnAjax:Storage:addCellToZasoby:ajaxLoaded', n, payload);
+				if ('success' == payload.type && payload.body && payload.body.id > 0) {
+					var cellUwagiJQNode = jQuery(n).parents('td').next('td');
+					cellUwagiJQNode.text(cellUwagiJQNode.text().replace('!Zasob', ''))
+					jQuery(n).parents('td').text(payload.body.id);
+					jQuery(n).remove();
 				}
-				return ($a < $b) ? -1 : 1;
+				jQuery.notify(payload.msg, payload.type);
 			});
-			UI::table([
-				'caption' => UI::h('span', [], [
-					"Komórki [{$idTable}] ",
-					UI::h('a', [
-						'href' => "index.php?_route=ViewTableAjax&namespace=default_db/{$tblName}",
-						'class' => "btn btn-md btn-link"
-					], "Przeglądaj tabelę"),
-					UI::h('a', [
-						'href' => "procesy5.php?task=CRM_LISTA_ZASOBOW&filtr_id={$idTable}&filtr_ids=%2B&filtr_ob=%2B",
-						'class' => "btn btn-md btn-link",
-						'title' => "Struktura aktualnie przeglądanej tabeli"
-					], "Zasoby"),
-					UI::h('a', [
-						'href' => "index.php?FUNCTION_INIT=PROCES_MENU&HEADER_NOT_INIT=YES&_task=PROCES_FOR_TABLE&tblId={$idTable}",
-						'class' => "btn btn-md btn-link",
-						'title' => "Procesy dla aktualnie przeglądanej tabeli"
-					], "Procesy"),
-					UI::h('a', [
-						'href' => Router::getRoute('Storage_AclUsage')->getLink('', [ 'namespace' => "default_db/{$tblName}" ]),
-						'class' => "btn btn-md btn-link",
-						'title' => "Uprawnienia - analiza użycia komórek w procesach"
-					], "Uprawnienia (analiza użycia)"),
-				]),
-				'cols' => array_keys($emptyItem),
-				'rows' => $tableList
-			]);
-			echo UI::h('script', [], "
-				jQuery(document).on('p5UIBtnAjax:Storage:addCellToZasoby:click', function(e, n, payload) {
-					console.log('event p5UIBtnAjax:Storage:addCellToZasoby:click', n, payload);
+		");
+		$ajaxAddZasobLink = Router::getRoute('Storage')->getLink('addGeomEtykietaCells', [ 'idStorage' => $idStorage, 'tblName' => $tblName]);
+		$onClick = "return p5UI__ButtonAjax(this, 'p5UIBtnAjax:Storage:addGeomEtykietaCells', { href: '{$ajaxAddZasobLink}' })";
+		UI::tag('a', ['onclick'=>$onClick, 'class'=>"btn btn-xs btn-default", 'href'=>"#"], "Dodaj komórki etykiet", true);
+		echo "<i>(<code>`etykieta_x`</code>, <code>`etykieta_y`</code>, <code>`etykieta_obrot`</code>)</i>";
+		echo UI::h('script', [], "
+			jQuery(document).on('p5UIBtnAjax:Storage:addGeomEtykietaCells:ajaxLoaded', function(e, n, payload) {
+				console.log('event p5UIBtnAjax:Storage:addGeomEtykietaCells:ajaxLoaded', n, payload);
+				if ('success' == payload.type && payload.body && payload.body.id > 0) {
+					var cellUwagiJQNode = jQuery(n).parents('td').next('td');
+					cellUwagiJQNode.text(cellUwagiJQNode.text().replace('!Zasob', ''))
+					jQuery(n).parents('td').text(payload.body.id);
+					jQuery(n).remove();
+				}
+				jQuery.notify(payload.msg, payload.type);
+			});
+		");
+
+
+		$tableActions = array_filter($cellZasobList, function ($row) {
+			return ('URL_ACTION' == $row['ZASOB_TYPE']);
+		});
+		UI::table([
+			'caption' => "tableActions",
+			// 'cols' => array_keys($emptyItem),
+			'rows' => array_map(function ($item) {
+				$sqlIdAction = DB::getPDO()->quote($item['ID'], PDO::PARAM_INT);
+				$args = DB::getPDO()->fetchAll("
+					select z.`DESC`
+							, a.ID as ALIAS_ID, a.`DESC` as ALIAS_DESC, a.OPIS as ALIAS_OPIS
+					from CRM_LISTA_ZASOBOW z
+						left join CRM_LISTA_ZASOBOW a on(a.ID = z.ALIAS_ID)
+					where z.PARENT_ID = {$sqlIdAction}
+						and z.`TYPE` = 'PARAM_IN'
+				");
+				$definitionArgs = DB::getPDO()->fetchAll("
+					select p.ID, p.`DESC`
+					from CRM_LISTA_ZASOBOW z
+						join CRM_LISTA_ZASOBOW d on(d.ID = z.ALIAS_ID)
+						left join CRM_LISTA_ZASOBOW p on(p.PARENT_ID = d.ID)
+					where z.ID = {$sqlIdAction}
+						and p.`TYPE` = 'PARAM_IN'
+				");
+				$flatDefinitionArgs = implode(";", array_map(function ($arg) {
+					return "{$arg['ID']}={$arg['DESC']}";
+				}, $definitionArgs));
+				return [
+					'label' => DB::getPDO()->fetchValue(" select z.OPIS from CRM_LISTA_ZASOBOW z where z.ID = {$sqlIdAction} ") . " " .
+						UI::h('i', [
+							'class' => "glyphicon glyphicon-pencil",
+							'style' => "cursor:pointer",
+							'onClick' => "return Storage__tableStruct__editActionLabel(this, {$sqlIdAction})"], ''),
+					'args' => implode("<br>&", array_map(function ($item) {
+						return (NULL === $item['ALIAS_ID'])
+							? $item['DESC']
+							: "{$item['DESC']}=" . '{$row["' . $item['ALIAS_DESC'] . '"]}';// TODO: add rmParam btn
+					}, $args)) . " " .
+						UI::h('i', [
+							'class' => "glyphicon glyphicon-plus-sign",
+							'style' => "cursor:pointer",
+							'title' => "Dodaj PARAM_IN",
+							'onClick' => "return Storage__tableStruct__addParamAction(this, {$sqlIdAction}, '{$flatDefinitionArgs}')"], ''),
+					// 'args_info' => '<pre>' . var_export($args, true) . '</pre>',
+					'ID' => $item['ID'],
+					'DESC' => $item['DESC'],
+					'A_STATUS' => $item['A_STATUS'],
+					'definition args' => implode("", array_map(function ($item) {
+						return '<div style="white-space:nowrap">' . "[{$item['ID']}] {$item['DESC']}" . '</div>';
+					}, $definitionArgs)),
+				];
+			}, $tableActions)
+		]);
+		echo UI::h('button', [
+			'onClick'=>"Storage__tableStruct__addAction()",
+			'class'=>"btn btn-xs btn-default"
+		], "Dodaj Akcję");
+		echo UI::h('link', ['rel'=>"stylesheet", 'type'=>"text/css", 'href'=>"static/sweetalert2.min.css"]);
+		echo UI::h('script', ['src'=>"static/sweetalert2.min.js"]);
+		echo UI::h('style', [], "
+			.swal2-radio.p5-swal-radio-as-list { text-align:left }
+			.swal2-radio.p5-swal-radio-as-list > label { display:block; margin-left:20px }
+		");
+		UI::inlineJS(__FILE__ . '.tableActions.js', [
+			'ID_STORAGE' => $idStorage,
+			'TABLE_NAME' => $tblName,
+			'FETCH_URL' => Router::getRoute('Storage')->getLink('fetchActionListAjax'),
+			'ADD_ACTION_URL' => Router::getRoute('Storage')->getLink('addActionAjax')
+		]);
+		echo '<hr>';
+
+		$ajaxAddBaseProcesLink = Router::getRoute('Storage')->getLink('addTableBaseProces', [ 'idStorage' => $idStorage, 'tblName' => $tblName ]);
+		$onClick = "return p5UI__ButtonAjax(this, 'p5UIBtnAjax:Storage:addTableBaseProces', { href: '{$ajaxAddBaseProcesLink}' })";
+		UI::tag('a', ['onclick'=>$onClick, 'class'=>"btn btn-xs btn-default", 'href'=>"#"], "Dodaj podstawowy proces dla tabeli '{$tblName}' - read only", true);
+		echo UI::h('script', [], "
+			jQuery(document).on('p5UIBtnAjax:Storage:addTableBaseProces:ajaxLoaded', function(e, n, payload) {
+				jQuery.notify(payload.msg, payload.type);
+			});
+		");
+	}
+
+	public function objectStructView($item) {
+		$namespace = $item['namespace'];
+		usort($item['field'], function ($a, $b) {
+			if ($a['fieldNamespace'] > $b['fieldNamespace']) return 1;
+			if ($a['fieldNamespace'] < $b['fieldNamespace']) return -1;
+			return 0;
+		});
+
+		if ('setFieldRefConfig' === V::get('_postTask', '', $_POST)) {
+			$field = V::get('field', '', $_POST);
+			$source = V::get('source', '', $_POST);
+			switch ($source) {
+				case 'view':
+					$refSelect = ACL::generateRefSelectSqlByFlatRelationCache($namespace, $field);
+					ACL::setRefSource($namespace, $field, 'view', $refSelect);
+					break;
+				case 'table': ACL::setRefSource($namespace, $field, 'table'); break;
+			}
+		}
+		if ('preview' === V::get('_postTask', '', $_POST)) {
+			try {
+				$item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
+				$localFields = array_filter($item['field'], function ($field) {
+					return $field['isLocal'];
 				});
-				jQuery(document).on('p5UIBtnAjax:Storage:addCellToZasoby:ajaxLoaded', function(e, n, payload) {
-					console.log('event p5UIBtnAjax:Storage:addCellToZasoby:ajaxLoaded', n, payload);
-					if ('success' == payload.type && payload.body && payload.body.id > 0) {
-						var cellUwagiJQNode = jQuery(n).parents('td').next('td');
-						cellUwagiJQNode.text(cellUwagiJQNode.text().replace('!Zasob', ''))
-						jQuery(n).parents('td').text(payload.body.id);
-						jQuery(n).remove();
-					}
-					jQuery.notify(payload.msg, payload.type);
+				$refFields = array_filter($item['field'], function ($field) {
+					return 'ref:' === substr($field['xsdType'], 0, 4);
 				});
-			");
-			$ajaxAddZasobLink = Router::getRoute('Storage')->getLink('addGeomEtykietaCells', [ 'idStorage' => $idStorage, 'tblName' => $tblName]);
-			$onClick = "return p5UI__ButtonAjax(this, 'p5UIBtnAjax:Storage:addGeomEtykietaCells', { href: '{$ajaxAddZasobLink}' })";
-			UI::tag('a', ['onclick'=>$onClick, 'class'=>"btn btn-xs btn-default", 'href'=>"#"], "Dodaj komórki etykiet", true);
-			echo "<i>(<code>`etykieta_x`</code>, <code>`etykieta_y`</code>, <code>`etykieta_obrot`</code>)</i>";
-			echo UI::h('script', [], "
-				jQuery(document).on('p5UIBtnAjax:Storage:addGeomEtykietaCells:ajaxLoaded', function(e, n, payload) {
-					console.log('event p5UIBtnAjax:Storage:addGeomEtykietaCells:ajaxLoaded', n, payload);
-					if ('success' == payload.type && payload.body && payload.body.id > 0) {
-						var cellUwagiJQNode = jQuery(n).parents('td').next('td');
-						cellUwagiJQNode.text(cellUwagiJQNode.text().replace('!Zasob', ''))
-						jQuery(n).parents('td').text(payload.body.id);
-						jQuery(n).remove();
-					}
-					jQuery.notify(payload.msg, payload.type);
+				$activeRefFields = array_filter($refFields, function ($field) {
+					$refNamespace = str_replace(['__x3A__', ':'], '/', substr($field['xsdType'], strlen('ref:')));
+					return (1 == DB::getPDO()->fetchValue("
+						select t.isObjectActive
+						from `CRM_#CACHE_ACL_OBJECT` t
+						where t.`namespace` = '{$refNamespace}'
+					"));
 				});
-			");
+				$query = [ 'cols' => array_merge(
+					array_map(
+						function ($field) {
+							return $field['fieldNamespace'];
+						}, $localFields
+					),
+					array_map(
+						function ($field) {
+							return "{$field['fieldNamespace']}/*";
+						}, $activeRefFields
+					)
+				) ];
+				DBG::nicePrint($query, '$query');
 
+				$previewItems = ACL::getAclByNamespace($namespace)->buildQuery($query)->getItems([
+					'limit' => 3
+				]);
+				DBG::nicePrint($previewItems, 'items with ref limit 3');
+			} catch (Exception $e) {
+				DBG::log($e);
+				UI::alert('danger', $e->getMessage());
+			}
+		}
 
-			$tableActions = array_filter($cellZasobList, function ($row) {
-				return ('URL_ACTION' == $row['ZASOB_TYPE']);
+		echo UI::h('details', ['style'=>"margin-bottom:24px; padding:0 10px; background-color:#eee", 'open' => "open"], [
+			UI::h('summary', ['style'=>"font-size:1.4em; line-height:2em; cursor:pointer; outline:none"], [
+				"Struktura obiektu '{$namespace}' ",
+				// UI::h('small', ['style'=>"font-size:0.8em; font-style:italic; color:#aaa"], " więcej...")
+			]),
+			UI::h('div', ['style'=>"padding:4px 24px; border-top:1px solid #fff"], [
+				UI::h('span', ['style'=>"margin-right:12px"], [
+					( ($item['idZasob'] > 0)
+					? UI::h('span', [ 'title' => "Nr zasobu '{$item['idZasob']}'" ], "Nr zasobu [{$item['idZasob']}]")
+					: UI::h('span', [ 'title' => "Brak nr zasobu - dodaj do zasobów" ], [
+							UI::hButtonAjax("+ do zasobów", 'addAclObjectToZasobyAjax', [
+								'class' => "btn btn-xs btn-primary",
+								'href' => Router::getRoute('Storage')->getLink('addAclObjectToZasobyAjax'),
+								'data' => [
+									'idStorage' => $item['idDatabase'],
+									'namespace' => $item['namespace'],
+								]
+							])
+						])
+					),
+				]),
+				UI::h('span', ['style'=>"margin:0 12px"], [
+					( ($item['isObjectActive'] > 0)
+						? UI::h('span', [ 'class' => "label label-success", 'title' => "Namespace active" ], "Active")
+						: UI::h('span', [ 'title' => "Namespace not active" ], [
+							($item['idZasob'] > 0)
+							? UI::hButtonAjax("Aktywuj", 'activateObjectAjax', [
+									'class' => "btn btn-xs btn-primary",
+									'href' => Router::getRoute('Storage')->getLink('activateObjectAjax'),
+									'data' => [
+										'namespace' => $item['namespace'],
+									]
+								])
+							: '',
+						])
+					),
+				]),
+				UI::h('a', [
+					'href' => "index.php?_route=ViewTableAjax&namespace={$item['namespace']}",
+					'class' => "btn btn-sm btn-link"
+				], "Przeglądaj tabelę"),
+				( ($item['idZasob'] > 0)
+					? UI::h('a', [
+							'href' => "procesy5.php?task=CRM_LISTA_ZASOBOW&filtr_id={$item['idZasob']}&filtr_ids=%2B&filtr_ob=%2B",
+							'class' => "btn btn-sm btn-link",
+							'title' => "Struktura tabeli w drzewie zasobów"
+						], "Zasoby")
+					: ''
+				),
+				( ($item['idZasob'] > 0)
+					? UI::h('a', [
+							'href' => "index.php?FUNCTION_INIT=PROCES_MENU&HEADER_NOT_INIT=YES&_task=PROCES_FOR_TABLE&tblId={$item['idZasob']}",
+							'class' => "btn btn-sm btn-link",
+							'title' => "Procesy dla aktualnie przeglądanej tabeli"
+						], "Procesy")
+					: ''
+				),
+				UI::h('a', [
+					'href' => Router::getRoute('Storage')->getLink('objectReinstall', ['namespace' => $item['namespace']]),
+					'class' => 'btn btn-sm btn-link', 'style' => "color:#f00",
+					'title' => "Zainstaluje ponownie obiekt"
+				], "reinstall object"),
+				UI::h('a', [
+					'href' => Router::getRoute('Storage_AclUsage')->getLink('', [ 'namespace' => $item['namespace'] ]),
+					'class' => "btn btn-sm btn-link",
+					'title' => "Uprawnienia - analiza użycia komórek w procesach"
+				], "Uprawnienia (analiza użycia)"),
+				UI::hButtonPost("(podgląd z relacjami)", [
+					'data' => [
+						'_postTask' => 'preview'
+					],
+					'class' => 'btn btn-sm btn-link', 'style' => "font-style:italic",
+					'title' => "Podgląd kilku ostatnich obiektów wraz z relacjami"
+				]),
+			])
+		]);
+
+		$thisGetLink = [Router::getRoute('Storage'), 'getLink'];
+		{ // not installed ref
+			$refFields = array_filter($item['field'], function ($field) {
+				return 'ref:' === substr($field['xsdType'], 0, 4);
 			});
 			UI::table([
-				'caption' => "tableActions",
-				// 'cols' => array_keys($emptyItem),
-				'rows' => array_map(function ($item) {
-					$sqlIdAction = DB::getPDO()->quote($item['ID'], PDO::PARAM_INT);
-					$args = DB::getPDO()->fetchAll("
-						select z.`DESC`
-								, a.ID as ALIAS_ID, a.`DESC` as ALIAS_DESC, a.OPIS as ALIAS_OPIS
-						from CRM_LISTA_ZASOBOW z
-							left join CRM_LISTA_ZASOBOW a on(a.ID = z.ALIAS_ID)
-						where z.PARENT_ID = {$sqlIdAction}
-							and z.`TYPE` = 'PARAM_IN'
-					");
-					$definitionArgs = DB::getPDO()->fetchAll("
-						select p.ID, p.`DESC`
-						from CRM_LISTA_ZASOBOW z
-							join CRM_LISTA_ZASOBOW d on(d.ID = z.ALIAS_ID)
-							left join CRM_LISTA_ZASOBOW p on(p.PARENT_ID = d.ID)
-						where z.ID = {$sqlIdAction}
-							and p.`TYPE` = 'PARAM_IN'
-					");
-					$flatDefinitionArgs = implode(";", array_map(function ($arg) {
-						return "{$arg['ID']}={$arg['DESC']}";
-					}, $definitionArgs));
+				'caption' => UI::h('span', [], "Obiekty powiązane (TODO backRef)"),
+				'rows' => array_map(function ($field) use ($thisGetLink) {
+					$refNamespace = str_replace(['__x3A__', ':'], '/', substr($field['xsdType'], strlen('ref:')));
+					$isInstalled = (1 == DB::getPDO()->fetchValue("
+						select t.isObjectActive
+						from `CRM_#CACHE_ACL_OBJECT` t
+						where t.`namespace` = '{$refNamespace}'
+					"));
+					$refSource = null;
+					if ($isInstalled) {
+						try {
+							$refTable = ACL::getRefTable($field['objectNamespace'], $field['fieldNamespace']);
+							DBG::log($refTable, 'array', "getRefTable('{$field['objectNamespace']}', '{$field['fieldNamespace']}')");
+							$refSource = ACL::getRefSource($field['objectNamespace'], $field['fieldNamespace']);
+							DBG::log($refSource, 'array', "ACL::getRefSource('{$field['objectNamespace']}', '{$field['fieldNamespace']}')");
+						} catch (Exception $e) {
+							DBG::log($e);
+						}
+					}
 					return [
-						'label' => DB::getPDO()->fetchValue(" select z.OPIS from CRM_LISTA_ZASOBOW z where z.ID = {$sqlIdAction} ") . " " .
-							UI::h('i', [
-								'class' => "glyphicon glyphicon-pencil",
-								'style' => "cursor:pointer",
-								'onClick' => "return Storage__tableStruct__editActionLabel(this, {$sqlIdAction})"], ''),
-						'args' => implode("<br>&", array_map(function ($item) {
-							return (NULL === $item['ALIAS_ID'])
-								? $item['DESC']
-								: "{$item['DESC']}=" . '{$row["' . $item['ALIAS_DESC'] . '"]}';// TODO: add rmParam btn
-						}, $args)) . " " .
-							UI::h('i', [
-								'class' => "glyphicon glyphicon-plus-sign",
-								'style' => "cursor:pointer",
-								'title' => "Dodaj PARAM_IN",
-								'onClick' => "return Storage__tableStruct__addParamAction(this, {$sqlIdAction}, '{$flatDefinitionArgs}')"], ''),
-						// 'args_info' => '<pre>' . var_export($args, true) . '</pre>',
-						'ID' => $item['ID'],
-						'DESC' => $item['DESC'],
-						'A_STATUS' => $item['A_STATUS'],
-						'definition args' => implode("", array_map(function ($item) {
-							return '<div style="white-space:nowrap">' . "[{$item['ID']}] {$item['DESC']}" . '</div>';
-						}, $definitionArgs)),
-					];
-				}, $tableActions)
+						'fieldName' => $field['fieldNamespace'],
+						// 'xsdType' => $field['xsdType'], // always === "ref:{$field['fieldNamespace']}"
+						'ref object' => UI::h('a', [
+							'class' => "btn btn-xs btn-link",
+							'href' => $thisGetLink('objectStruct', [ 'namespace' => $refNamespace ])
+						], "objectStruct ({$refNamespace})"),
+						'ref source' => UI::h('div', [],
+							(null === $refSource)
+							? [ "ref object not installed" ] // TODO: link to install? is table struct
+							: [
+									// UI::hButtonAjax("Tabela ref", "setFieldRefConfig", [
+									// 	'class' => "btn btn-xs btn-default" . ( 'table' === $refSource ? ' disabled' : '' ),
+									// 	'href' => $thisGetLink('setFieldRefConfig'),
+									// 	'data' => [ 'namespace' => $refNamespace, 'field' => $field['fieldNamespace'], 'do' => 'table' ]
+									// ]),
+									// UI::hButtonAjax("Widok (cache)", "setFieldRefConfig", [
+									// 	'title' => "Według flat_relation_cache",
+									// 	'class' => "btn btn-xs btn-default" . ( 'view' === $refSource ? ' disabled' : '' ),
+									// 	'href' => $thisGetLink('setFieldRefConfig'),
+									// 	'data' => [ 'namespace' => $refNamespace, 'field' => $field['fieldNamespace'], 'do' => 'view' ]
+									// ]),
+									UI::hButtonPost("Tabela ref", [
+										'title' => "Według wygenerowanej tabeli REF",
+										'class' => "btn btn-xs btn-default" . ( 'table' === $refSource ? ' disabled' : '' ),
+										// 'href' => $thisGetLink('setFieldRefConfig'),
+										'data' => [ 'namespace' => $refNamespace, 'field' => $field['fieldNamespace'], '_postTask' => 'setFieldRefConfig', 'source' => 'table' ]
+									]),
+									UI::hButtonPost("Widok (cache)", [
+										'title' => "Według flat_relation_cache",
+										'class' => "btn btn-xs btn-default" . ( 'view' === $refSource ? ' disabled' : '' ),
+										// 'href' => $thisGetLink('setFieldRefConfig'),
+										'data' => [ 'namespace' => $refNamespace, 'field' => $field['fieldNamespace'], '_postTask' => 'setFieldRefConfig', 'source' => 'view' ]
+									]),
+								]
+						),
+						'@class' => ($isInstalled) ? "success" : "danger",
+					]; // TODO: link to install object
+				}, $refFields)
 			]);
-			echo UI::h('button', [
-				'onClick'=>"Storage__tableStruct__addAction()",
-				'class'=>"btn btn-xs btn-default"
-			], "Dodaj Akcję");
-			echo UI::h('link', ['rel'=>"stylesheet", 'type'=>"text/css", 'href'=>"static/sweetalert2.min.css"]);
-			echo UI::h('script', ['src'=>"static/sweetalert2.min.js"]);
-			echo UI::h('style', [], "
-				.swal2-radio.p5-swal-radio-as-list { text-align:left }
-				.swal2-radio.p5-swal-radio-as-list > label { display:block; margin-left:20px }
-			");
-			UI::inlineJS(__FILE__ . '.tableActions.js', [
-				'ID_STORAGE' => $idStorage,
-				'TABLE_NAME' => $tblName,
-				'FETCH_URL' => Router::getRoute('Storage')->getLink('fetchActionListAjax'),
-				'ADD_ACTION_URL' => Router::getRoute('Storage')->getLink('addActionAjax')
+		}
+		UI::table([
+			'caption' => UI::h('span', [], [
+				UI::h('span', [ 'style' => "margin-right:6px;color:#000" ], "Struktura obiektu '{$item['namespace']}'"),
+			]),
+			'rows' => array_map(function ($field) use ($item, $thisGetLink) {
+				$tblItem = []; foreach ($field as $k => $v) $tblItem[$k] = $v;
+				$tblItem['namespace'] = UI::h('span', [], [
+					UI::h('span', ['style' => "color:#aaa"], substr($field['namespace'], 0, strlen($field['objectNamespace']) + 1)),
+					UI::h('span', ['style' => "color:#000"], substr($field['namespace'], strlen($field['objectNamespace']) + 1)),
+				]);
+				$tblItem['idZasob'] = ($field['idZasob'] > 0)
+					? $field['idZasob']
+					: (
+							($item['idZasob'] > 0)
+							? UI::hButtonAjax("+ do zasobów", 'addFieldToZasobyAjax', [
+									'class' => "btn btn-xs btn-primary",
+									'href' => $thisGetLink('addFieldToZasobyAjax'),
+									'data' => [
+										'namespace' => $item['namespace'],
+										'fieldNamespace' => $field['namespace'],
+									]
+								])
+							: UI::h('span', ['title'=>"Brak Nr zasobu dla obiektu", 'class'=>"btn btn-xs btn-danger"], "Brak nr zasobu obiektu")
+						)
+				;
+				unset($tblItem['objectNamespace']);
+				unset($tblItem['fieldNamespace']);
+				return $tblItem;
+			}, $item['field'])
+		]);
+		UI::hButtonAjaxOnResponse('addFieldToZasobyAjax', /* payload, n */ "
+			if (!payload.type) return false
+			if (payload.body && payload.body.id && payload.body.id > 0) { // if ('success' == payload.type) {
+				n.parentNode.replaceChild(document.createTextNode(payload.body.id), n)
+			}
+			jQuery.notify(payload.msg, payload.type)
+		");
+		UI::hButtonAjaxOnResponse('addAclObjectToZasobyAjax', /* payload, n */ "
+			if (!payload.type) return false
+			if ('success' === payload.type || 'info' === payload.type) {
+				if (payload.body && payload.body.id && payload.body.id > 0) {
+					n.parentNode.replaceChild(document.createTextNode(payload.body.id), n)
+				} else {
+					console.log('TODO: addAclObjectToZasobyAjax unknown response', payload);
+				}
+				window.location.reload()
+			}
+		");
+		UI::hButtonAjaxOnResponse('activateObjectAjax', /* payload, n */ "
+			jQuery.notify(payload.msg, payload.type)
+			if (!payload.type) return false
+			if ('success' === payload.type || 'info' === payload.type) {
+				if (payload.body && payload.body.isObjectActive && payload.body.isObjectActive > 0) {
+					n.parentNode.replaceChild(document.createTextNode('Active'), n)
+				} else {
+					console.log('TODO: activateObjectAjax unknown response', payload);
+				}
+			}
+		");
+		if ($item['isObjectActive']) {
+			echo UI::hButtonAjax("Dodaj podstawowy proces dla obiektu '{$item['namespace']}' - read only (TODO)", 'addObjectBaseProcesAjax', [
+				'class' => "btn btn-xs btn-default",
+				'href' => Router::getRoute('Storage')->getLink('addObjectBaseProcesAjax'),
+				'data' => [ 'namespace' => $item['namespace'] ]
 			]);
-			echo '<hr>';
-
-			$ajaxAddBaseProcesLink = Router::getRoute('Storage')->getLink('addTableBaseProces', [ 'idStorage' => $idStorage, 'tblName' => $tblName ]);
-			$onClick = "return p5UI__ButtonAjax(this, 'p5UIBtnAjax:Storage:addTableBaseProces', { href: '{$ajaxAddBaseProcesLink}' })";
-			UI::tag('a', ['onclick'=>$onClick, 'class'=>"btn btn-xs btn-default", 'href'=>"#"], "Dodaj podstawowy proces dla tabeli '{$tblName}' - read only", true);
-			echo UI::h('script', [], "
-				jQuery(document).on('p5UIBtnAjax:Storage:addTableBaseProces:ajaxLoaded', function(e, n, payload) {
-					jQuery.notify(payload.msg, payload.type);
-				});
+			UI::hButtonAjaxOnResponse('addObjectBaseProcesAjax', /* payload, n */ "
+				jQuery.notify(payload.msg, payload.type)
 			");
-		} catch (Exception $e) {
-			UI::alert('danger', "Error #" . $e->getCode() .  "|" . $e->getLine() .  ": " . $e->getMessage());
 		}
-		UI::dol();
+		DBG::nicePrint($item, '$item');
 	}
 
 }

+ 0 - 0
SE/se-lib/Route/Storage.php.tableActions.js → SE/se-lib/Route/Storage/AclStruct.php.tableActions.js