فهرست منبع

Merge branch 'master' of ssh://biuro.biall-net.pl:2222/plabudda/se

Mariusz Muszyński 8 سال پیش
والد
کامیت
8acf1f44b4

+ 4 - 2
SE/se-lib/AntAclBase.php

@@ -106,9 +106,11 @@ class AntAclBase extends Core_AclBase {
 	}
 	public function getRealFieldListByIdZasob() {
 		$cols = array();
-		$fakeZasobId = 1000000;
+		$fakeZasobId = 1000000; // TODO: RMME
 		foreach ($this->getFields() as $field) {
-			$idZasobField = ($field['idZasob']) ? $field['idZasob'] : $fakeZasobId++;
+			$idZasobField = ($field['idZasob']) ? $field['idZasob'] : $fakeZasobId++; // TODO: RMME
+			if (!$field['isActive']) continue;
+			if (!$field['idZasob']) continue;
 			$cols[$idZasobField] = $field['fieldNamespace'];
 		}
 		return $cols;

+ 13 - 12
SE/se-lib/Api/Wfs/GetFeature.php

@@ -13,6 +13,7 @@ class Api_Wfs_GetFeature {
 	public static function parseGetFeatureArgsFromRequest() {
 		$rawArgs = $_GET;// $_REQUEST; ($_POST values not allowed, only xml in post body)
 		$args = array();
+		$args['root'] = ('0' === User::get('ADM_ADMIN_LEVEL') && 1 === V::get('root', 0, $rawArgs, 'int')); // NOTE: require Admin perms
 		$args['xsd:type'] = null;// @from: TYPENAME, typeName (typename)
 		$args['typePrefix'] = null;// @from: TYPENAME, typeName (typename)
 		$args['typeName'] = null;// @from: TYPENAME, typeName (typename)
@@ -195,10 +196,10 @@ class Api_Wfs_GetFeature {
 		throw new Exception("Not imeplemented multiple ogc:Query"); // multiple ogc:Query require ogc:Query/@typeName
 	}
 
-	public static function convertOgcPropertyListToFeatureQueryCols(&$schemaCache, $ogcPropertyList, $acl) {
-		return self::convertOgcPropsRecurse($schemaCache, $ogcPropertyList, $acl, $dbgLoopNr = 0, $dbgXpath = $acl->getNamespace());
+	public static function convertOgcPropertyListToFeatureQueryCols(&$schemaCache, $ogcPropertyList, $acl, $isRoot = false) {
+		return self::convertOgcPropsRecurse($schemaCache, $ogcPropertyList, $acl, $isRoot, $dbgLoopNr = 0, $dbgXpath = $acl->getNamespace());
 	}
-	public static function convertOgcPropsRecurse(&$schemaCache, $ogcPropertyList, $aclOrSchema, $dbgLoopNr = 0, $dbgXpath = '') {
+	public static function convertOgcPropsRecurse(&$schemaCache, $ogcPropertyList, $aclOrSchema, $isRoot = false, $dbgLoopNr = 0, $dbgXpath = '') {
 		if ($dbgLoopNr > 10) {
 			DBG::log($ogcPropertyList, 'array', 'convertOgcPropsRecurse: LOOP LIMIT 10! - return []');
 			return [];
@@ -212,8 +213,8 @@ class Api_Wfs_GetFeature {
 
 		if (empty($ogcPropertyList)) {
 			$ogcPropertyList = array_values($acl->getFieldListByIdZasob());
-			$ogcPropertyList = array_filter($ogcPropertyList, function ($fieldName) use ($acl) {
-				return $acl->canReadField($fieldName);
+			$ogcPropertyList = array_filter($ogcPropertyList, function ($fieldName) use ($acl, $isRoot) {
+				return ($isRoot || $acl->canReadField($fieldName));
 			});
 		}
 
@@ -237,10 +238,10 @@ class Api_Wfs_GetFeature {
 			if (array_key_exists('*', $nestedFields)) {
 				$nestedParts = $nestedFields['*'];
 				unset($nestedFields['*']);
-				DBG::log($nestedParts, 'array', "convertOgcPropsRecurse: TODO: '*' in \$nestedFields - \$nestedParts ns({$dbgXpath})");
+				DBG::log($nestedParts, 'array', "convertOgcPropsRecurse: '*' in \$nestedFields - \$nestedParts ns({$dbgXpath})");
 				$canReadRefs = array_values($acl->getFieldListByIdZasob());
-				$canReadRefs = array_filter($canReadRefs, function ($fieldName) use ($acl) {
-					return (false !== strpos($fieldName, ":") && $acl->canReadField($fieldName));
+				$canReadRefs = array_filter($canReadRefs, function ($fieldName) use ($acl, $isRoot) {
+					return (false !== strpos($fieldName, ":") && ($isRoot || $acl->canReadField($fieldName)));
 				});
 				foreach ($canReadRefs as $refField) {
 					foreach ($nestedParts as $nestedPart) {
@@ -255,15 +256,15 @@ class Api_Wfs_GetFeature {
 		if (in_array('*', $aclFields)) {
 			$aclFields = array_filter($aclFields, function ($fieldName) { return ( '*' !== $fieldName); });
 			$allAclFields = array_values($acl->getFieldListByIdZasob());
-			$allAclFields = array_filter($allAclFields, function ($fieldName) use ($acl) {
-				return $acl->canReadField($fieldName);
+			$allAclFields = array_filter($allAclFields, function ($fieldName) use ($acl, $isRoot) {
+				return ($isRoot || $acl->canReadField($fieldName));
 			});
 			if ($allAclFields) $aclFields = array_unique(array_merge($aclFields, $allAclFields));
 		}
-		DBG::log([$aclFields, $nestedFields], 'array', "convertOgcPropsRecurse: splited to acl fields and nested fields ns({$dbgXpath})");
+		DBG::log([$aclFields, $nestedFields, $acl->getFieldListByIdZasob()], 'array', "convertOgcPropsRecurse: splited to acl fields and nested fields ns({$dbgXpath})");
 
 		foreach ($aclFields as $fieldName) {
-			if (!$acl->canReadField($fieldName)) throw new Exception("Access Denied to read field '{$fieldName}' from '" . $acl->getNamespace() . "'");
+			if (!$isRoot && !$acl->canReadField($fieldName)) throw new Exception("Access Denied to read field '{$fieldName}' from '" . $acl->getNamespace() . "'");
 		}
 
 		foreach ($aclFields as $fieldName) {

+ 1 - 1
SE/se-lib/Api/WfsDataServer.php

@@ -190,7 +190,7 @@ class Api_WfsDataServer extends Api_WfsServerBase {
 		DBG::log($args, 'array', "\$args");
 		$schemaCache = array();
 		try {
-			$searchParams['cols'] = Api_Wfs_GetFeature::convertOgcPropertyListToFeatureQueryCols($schemaCache, $args['filterFields'], $acl); // convert $args['filterFields'] to field list
+			$searchParams['cols'] = Api_Wfs_GetFeature::convertOgcPropertyListToFeatureQueryCols($schemaCache, $args['filterFields'], $acl, $isRoot = $args['root']); // convert $args['filterFields'] to field list
 		} catch (Exception $e) {
 			DBG::log($e);
 			throw $e;

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

@@ -230,6 +230,7 @@ class Route_Storage extends RouteBase {
 								UI::h('a', [ 'href' => "wfs-data.php/default_db/?SERVICE=WFS&VERSION=1.0.0&SRSNAME=EPSG:3003&REQUEST=GetFeature&TYPENAME={$typeName}&MAXFEATURES=10" ], "wfs GetFeature (max: 10)"),
 								UI::h('a', [ 'href' => "wfs-data.php/default_db/?SERVICE=WFS&VERSION=1.0.0&SRSNAME=EPSG:3003&REQUEST=GetFeatureAdvanced&TYPENAME={$typeName}&MAXFEATURES=10" ], "wfs GetFeatureAdvanced (max: 10)"),
 								UI::h('a', [ 'href' => "wfs-data.php/default_db/?SERVICE=WFS&VERSION=1.0.0&SRSNAME=EPSG:3003&REQUEST=GetFeature&TYPENAME={$typeName}&MAXFEATURES=3&resolve=all&resolveDepth=3" ], "wfs GetFeature (max: 3, resolveDepth: 3)"),
+								UI::h('a', [ 'href' => "index.php?_route=WfsJsRequestPanel&namespace={$item['namespace']}" ], "JavaScript WFS Panel"),
 							])
 						]),
 					];

+ 167 - 7
SE/se-lib/Route/UrlAction/BiAuditRaport.php

@@ -9,10 +9,10 @@ class Route_UrlAction_BiAuditRaport extends RouteBase {
 
 	public function defaultAction() {
 		UI::topSection();
-		UI::startContainer();
+		//UI::startContainer();
 
 		echo '<div class="container-bi_audit_raport"></div>';
-		try {
+		/*try {
 
 			$items = ACL::getAclByNamespace('default_db/BI_audit_ENERGA_RUM_KONTRAHENCI_POWIAZANIA/BI_audit_ENERGA_RUM_KONTRAHENCI_POWIAZANIA')->buildQuery([
 				'cols' => [ // TODO:? propertyName = []
@@ -43,8 +43,18 @@ class Route_UrlAction_BiAuditRaport extends RouteBase {
 		} catch (Exception $e) {
 			DBG::log($e);
 			UI::alert('danger', $e->getMessage());
-		}
-		UI::endContainer();
+		}*/
+
+		UI::inlineJS(__FILE__ . '.view.js', [
+			'URL_FETCH_TEST' => $this->getLink('fetchEnergaRumKontrahenciPowiazaniaAjax'),
+			'URL_FETCH_TEST_KRS' => $this->getLink('fetchTestKrsAjax'),
+			'URL_FETCH_TEST_CEIDG' => $this->getLink('fetchTestCeidgAjax'),
+			'URL_FETCH_PRACOWNICY' => $this->getLink('fetchPracownicyAjax'),
+			'DBG' => V::get('DBG', 0, $_GET),
+		]);
+
+
+		//UI::endContainer();
 		UI::footerSection();
 	}
 
@@ -100,7 +110,7 @@ public function showPowiazaniaEnergaRumKontrahenciPowiazania($items) {
 	$view = '<form class="form-horizontal" method="post">
 						<table class="table table-bordered table-hover table-striped" height=5>
 									 <thead>
-										 <tr style="text-align:center; background-color:lightgray">
+										 <tr style="">
 										 		<td width=1><input type="checkbox" name="checkAll" id="checkAll" /></td>
 											 <td width=1>ID</td>
 											 <td>Adnotacje</td>
@@ -268,7 +278,7 @@ public function showPowiazaniaEnergaRumKontrahenciPowiazania($items) {
 			'__args' => $args,
 			'body' => [
 				'items' => $items,
-				'view' => $this->showPracownicy($items),
+				'view' => $this->htmlViewEmployees($items)
 			]
 		];
 	}
@@ -278,7 +288,7 @@ public function showPowiazaniaEnergaRumKontrahenciPowiazania($items) {
 	$view = '<form class="form-horizontal" method="post">
 						<table class="table table-bordered table-hover table-striped" height=5>
 									 <thead>
-										 <tr style="text-align:center; background-color:lightgray">
+										 <tr>
 										 		<td width=1><input type="checkbox" name="checkAll" id="checkAll" /></td>
 											 <td width=1>ID</td>
 											 <td>Imię/Imiona</td>
@@ -364,4 +374,154 @@ public function showPowiazaniaEnergaRumKontrahenciPowiazania($items) {
 		];
 	}
 
+	public function htmlViewEmployees($items) {
+
+		$viewEployees = '
+		<!-- start:employees-section-->
+<div id="smad-employees-section">
+		<div class="container-fluid">
+				<div class="row">
+						<div class="container padding-lr-0">
+								<div id="smad-menu-section">
+										<div class="col-sm-12 col-md-6 padding-lr-0">
+												<div class="menu-items">
+														<div class="smad-heder-title menu-item"><span class="smad-line-red">|</span> PRACOWNICY</div>
+												</div>
+										</div>
+										<div class="col-sm-12 col-md-6 padding-lr-0">
+												<div class="form-steps">
+														<!-- start:form steps wizard -->
+														<div class="row smad-wizard" style="border-bottom:0;">
+																<div class="col-xs-4 col-md-4 smad-wizard-step complete"><!-- complited line -->
+																		<div class="text-center smad-wizard-stepnum">&nbsp;</div>
+																		<div class="progress"><div class="progress-bar"></div></div>
+																		<a href="#" class="smad-wizard-dot"></a>
+																		<div class="smad-wizard-info complete text-center">
+																				<div class="step-item">Krok 1</div>
+																				<div class="step-title ">PRACOWNICY</div>
+																		</div>
+																</div>
+
+																<div class="col-xs-4 col-md-4 smad-wizard-step ">
+																		<div class="text-center smad-wizard-stepnum">&nbsp;</div>
+																		<div class="progress"><div class="progress-bar"></div></div>
+																		<a href="#" class="smad-wizard-dot"></a>
+																		<div class="smad-wizard-info  text-center">
+																				<div class="step ">Krok 2</div>
+																				<div class="step-title ">KONTRAHENCI</div>
+																		</div>
+																</div>
+
+																<div class="col-xs-4 col-md-4 smad-wizard-step ">
+																		<div class="text-center smad-wizard-stepnum">&nbsp;</div>
+																		<div class="progress"><div class="progress-bar"></div></div>
+																		<a href="#" class="smad-wizard-dot"></a>
+																		<div class="smad-wizard-info text-center">
+																				<div class="step ">Krok 3</div>
+																				<div class="step-title ">SZUKANIE POWIĄZAŃ</div>
+																		</div>
+																</div>
+														</div>
+														<!-- end:form steps wizard -->
+												</div>
+										</div>
+								</div>
+						</div>
+				</div>
+		</div>
+
+		<div class="container-fluid">
+				<div class="container padding-lr-0">
+						<div class="smad-divider"></div>
+				</div>
+		</div>
+		<!-- start:filters -->
+		<div class="container-fluid">
+				<div class="row">
+						<div class="container">
+								<div class="smad-employees-form-section" class="border-top-grey">
+										<div class="col-md-9 smad-border-col">
+												<div class="menu-items">
+														<div class="menu-item">
+																<ul class="padding-0">
+																		<li>
+																				<span class="button-checkbox">
+																						<button type="button" class="btn" data-color="grey-border">WSZYSCY</button>
+																						<input type="checkbox" class="hidden" checked />
+																				</span>
+																		</li>
+																		<li>
+																				 <span class="button-checkbox">
+																						<button type="button" class="btn btn-grey-border" data-color="grey-border">WYSOKIEGO RYZYKA</button>
+																						<input type="checkbox" class="hidden"  />
+																				</span>
+																		</li>
+																		<li><a href="#" title="STWÓRZ GRUPĘ" class="btn btn-default-red" data-color-noactive="">+ STWÓRZ GRUPĘ</a></li>
+																</ul>
+														</div>
+												</div>
+										</div>
+										<div class="col-md-3">
+												<div class="form-input">
+														<div class="form-item col-md-8 smad-heder-title">głębokość powiązań:</div>
+														<div class="form-item col-md-4">
+																<input type="depth" class="form-control" placeholder="1-16" />
+														</div>
+												</div>
+										</div>
+								</div>
+						</div>
+				</div>
+		</div>
+		<!-- end:filters -->
+
+		<!-- start:list employees -->
+		<div class="container-fluid">
+				<div class="row">
+						<div class="container padding-0 smad-employees-list-head">
+								<div class="col-md-6">
+										<header>
+												<h2 class="title">Wszyscy</h2>
+										</header>
+										<div class="desc">
+												Lorem Ipsum jest tekstem stosowanym jako przykładowy wypełniacz w przemyśle poligraficznym.
+										</div>
+								</div>
+								<div class="col-md-6">
+										<div class="menu-items">
+												<div class="menu-item">
+														<ul class="padding-0">
+																<li><a href="#" title="IMPORT PRACOWNIKÓW" class="btn btn-grey-border" data-color-noactive="">IMPORT PRACOWNIKÓW</a></li>
+																<li><a href="#" title="DODAJ PRACOWNIKÓW" class="btn btn-grey-border" data-color-noactive="">+ DODAJ PRACOWNIKÓW</a></li>
+														</ul>
+												</div>
+										</div>
+								</div>
+						</div>
+				</div>
+		</div>
+		<div class="container-fluid">
+				<div class="container  padding-0">
+						' . $this->showPracownicy($items)  . '
+				</div>
+		</div>
+		<!-- end:list employees -->
+
+		<!-- start:bottom buttons -->
+		<div class="container-fluid smad-employees-bottom-navigation">
+				<div class="container padding-0">
+						<div class="col-lg-6 ">
+								<a href="#" title="PRZENIEŚ DO GRUPY" class="btn btn-grey-border">PRZENIEŚ DO GRUPY</a>
+						</div>
+						<div class="col-lg-6 text-right">
+								<a href="#" title="DODAJ DO ANALIZY" class="btn btn-default">DODAJ DO ANALIZY</a>
+						</div>
+				</div>
+		</div>
+		<!-- end:bottom buttons -->
+</div>
+<!-- start:employees-section -->
+		';
+		return $viewEployees;
+	}
 }

+ 49 - 8
SE/se-lib/Route/WfsJsRequestPanel.php

@@ -7,6 +7,7 @@ Lib::loadClass('RouteBase');
 Lib::loadClass('P5');
 Lib::loadClass('Core_AclHelper');
 Lib::loadClass('ACL');
+Lib::loadClass('Api_WfsNs');
 
 class Route_WfsJsRequestPanel extends RouteBase {
 
@@ -195,9 +196,41 @@ class Route_WfsJsRequestPanel extends RouteBase {
 			// $securityLogger->pushHandler($stream);
 			// $securityLogger->addInfo('debug message / label', [ 'dbg-object' => [ 'x' => 'y', 'z' ] ]);
 
+			$namespace = V::get('namespace', '', $_GET);
+			$defaultTypeName = ($namespace)
+			?	Api_WfsNs::typeName($namespace)
+			:	$examples['Procesy']['lvl1']['typeName'];
+			$defaultNamespace = Api_WfsNs::namespaceFromTypeName($defaultTypeName);
+			$defaultRequestBody = ($namespace)
+			?	''
+			:	htmlspecialchars($examples['Procesy']['lvl1']['postBody']);
 			// 'wfsRequestFeatureTypeName' = 'default_db__x3A__CRM_PROCES:PROCES'
-			echo UI::h('input', [ 'id' => 'wfsRequestFeatureTypeName', 'class' => "form-control", 'value' => $examples['Procesy']['lvl1']['typeName'], 'title' => "Feature name" ]);
-			echo UI::h('textarea', [ 'id' => 'wfsRequestBody', 'style' => "width:100%; height:300px" ], htmlspecialchars($examples['Procesy']['lvl1']['postBody']));
+			echo UI::h('table', [ 'style' => "width:100%; margin:0", 'class' => "table" ], [
+				UI::h('tr', [], [
+					UI::h('td', [ 'style' => "padding:0; border:none" ], [
+						UI::h('input', [ 'id' => 'wfsRequestFeatureTypeName', 'class' => "form-control", 'value' => $defaultTypeName, 'title' => "Feature name" ]),
+					]),
+					UI::h('td', [ 'style' => "width:5%; line-height:18px; border:none" ], [
+						UI::h('a', [
+							'id' => "typeNameStorageStructLink",
+							'href' => "index.php?_route=Storage_AclStruct&namespace={$defaultNamespace}",
+						], "Struktura")
+					]),
+				])
+			]);
+			echo UI::h('label', [], [
+				" root ",
+				UI::h('input', [ 'type' => "checkbox", 'id' => 'wfsRequestParam.root', 'class' => "", 'value' => '1' ]),
+			]);
+			echo UI::h('label', [ 'style' => "margin-left:8px" ], [
+				" maxFeatures: ",
+				UI::h('input', [ 'type' => "number", 'id' => 'wfsRequestParam.maxFeatures', 'class' => "", 'value' => '3' ]),
+			]);
+			echo UI::h('label', [ 'style' => "margin-left:8px" ], [
+				" resolveDepth: ",
+				UI::h('input', [ 'type' => "number", 'id' => 'wfsRequestParam.resolveDepth', 'class' => "", 'value' => '' ]),
+			]);
+			echo UI::h('textarea', [ 'id' => 'wfsRequestBody', 'style' => "width:100%; height:300px" ], $defaultRequestBody);
 			echo UI::h('button', [ 'class' => "btn btn-primary", 'onClick' => "return sendWfsRequest(this)" ], "Wyslij");
 			echo UI::h('div', [ 'style' => "display:inline", 'id' => "wfs-example-btns" ]);
 			echo UI::h('details', [ 'style' => "padding:6px; background-color:#333; color:#fff", 'open' => "open" ], [
@@ -239,7 +272,9 @@ class Route_WfsJsRequestPanel extends RouteBase {
 				console.log('examples', examples)
 				function setWfsExample(groupName, label) {
 					console.log('groupName', groupName, 'label', label)
-					document.getElementById('wfsRequestFeatureTypeName').value = examples[groupName][label].typeName
+					var typeName = examples[groupName][label].typeName
+					document.getElementById('wfsRequestFeatureTypeName').value = typeName
+					document.getElementById('typeNameStorageStructLink').href = 'index.php?_route=Storage_AclStruct&namespace=' + typeName.replace('__x3A__', '/').replace(':', '/')
 					document.getElementById('wfsRequestBody').value = examples[groupName][label].postBody || ''
 					sendWfsRequest()
 				}
@@ -258,11 +293,17 @@ class Route_WfsJsRequestPanel extends RouteBase {
 					document.getElementById('wfsResponse').innerHTML = 'loading...'
 					var featureTypeName = document.getElementById('wfsRequestFeatureTypeName').value
 					var postBody = document.getElementById('wfsRequestBody').value.replace(/&lt;/g, '<').replace(/&gt;/g, '>')
-					console.log('wfsRequestBody:', postBody)
-					var wfsParams = Object.assign({
-						'maxFeatures': 3,
-					}, (!postBody) ? {} : { 'ogc:Filter': postBody }
-					)
+					var wfsParams = {
+						'maxFeatures': 3
+					}
+					if (document.getElementById('wfsRequestParam.root').checked) wfsParams['root'] = '1'
+					if (document.getElementById('wfsRequestParam.maxFeatures')) wfsParams['maxFeatures'] = parseInt(document.getElementById('wfsRequestParam.maxFeatures').value)
+					var resolveDepth = parseInt(document.getElementById('wfsRequestParam.resolveDepth').value)
+					if (resolveDepth > 0 && !isNaN(resolveDepth)) {
+						wfsParams['resolve'] = 'all'
+						wfsParams['resolveDepth'] = resolveDepth
+					}
+					if (postBody) wfsParams['ogc:Filter'] = postBody
 					console.log('p5WFS_GetFeature', featureTypeName, wfsParams)
 					p5WFS_GetFeature(featureTypeName, wfsParams).then(function (features) {
 						console.log('features', features)

+ 5 - 5
SE/se-lib/Schema/SystemObjectStorageAcl.php

@@ -378,16 +378,16 @@ class Schema_SystemObjectStorageAcl extends Core_AclSimpleSchemaBase {
 	public function getItem($pk, $params = []) {
 		// TODO: ceche query for: $pk = 'default_db/CRM_PROCES/PROCES', $params = [ 'propertyName' => "*,field" ]
 		if (!$this->_cache) $this->_cache = [];
-		if (!empty($this->_cache) && 1 === count($params) && "*,field" === V::get('propertyName', '', $params)) {
+		if (1 === count($params) && "*,field" === V::get('propertyName', '', $params)) {
 			if (array_key_exists($pk, $this->_cache)) return $this->_cache[$pk];
-			$this->_cache[$pk] = $this->_getItem($pk, $params);
+			$this->_cache[$pk] = $this->_fetchItem($pk, $params);
 		} else {
-			return $this->_getItem($pk, $params);
+			return $this->_fetchItem($pk, $params);
 		}
 		return $this->_cache[$pk];
 	}
 
-	public function _getItem($pk, $params = []) {
+	public function _fetchItem($pk, $params = []) {
 		if (!$pk) throw new Exception("Missing primary key '{$this->_namespace}'");
 		$pkField = $this->getSqlPrimaryKeyField();
 		if (!$pkField) throw new Exception("Missing primary key field defined in '{$this->_namespace}'");
@@ -436,7 +436,7 @@ class Schema_SystemObjectStorageAcl extends Core_AclSimpleSchemaBase {
 	}
 
 	public function buildFeatureFromSqlRow($item, $params = []) {
-		DBG::log($params, 'array', "buildFeatureFromSqlRow...");
+		DBG::log($params, 'array', "buildFeatureFromSqlRow... '{$item['namespace']}'");
 		$exNs = explode('/', $item['namespace']);
 		$item['name'] = array_pop($exNs);
 		$item['nsPrefix'] = implode('__x3A__', $exNs);

+ 4 - 1
SE/se-lib/SchemaFactory.php

@@ -3,9 +3,12 @@
 class SchemaFactory {
 
   public static function loadDefaultObject($name) {
+		static $_cache = [];
+		if (array_key_exists($name, $_cache)) return $_cache[$name];
     $objClassName = "Schema_{$name}StorageAcl";
     if (!Lib::tryLoadClass($objClassName)) throw new HttpException("Not implemented - storage object not found '{$name}'", 501);
-    return new $objClassName();
+    $_cache[$name] = new $objClassName();
+    return $_cache[$name];
   }
 
   public static function loadTableObject($tableName, $name) {

+ 1 - 0
SE/static/p5WFS/GetFeature.js

@@ -129,6 +129,7 @@ function p5WFS_GetFeature(typeName, query) { // @returns Promise
 	if ('resolve' in query) link += '&resolve=' + query['resolve']
 	if ('resolveDepth' in query) link += '&resolveDepth=' + query['resolveDepth']
 	if ('xlink' in query) link += '&xlink=' + query['xlink'] // NOTE: replace '#' to '/'
+	if ('root' in query) link += '&root=' + query['root'] // NOTE: require admin perms (admin level 0)
 	var method = (postData) ? 'POST' : 'GET'
 
 	return window.fetch(link, Object.assign({

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 0 - 0
SE/static/theme_bocian/assets/css/styles.css


+ 215 - 1
SE/static/theme_bocian/assets/less/styles.less

@@ -33,6 +33,12 @@ strong {
   color: @brand-primary;
 }
 
+.smad-divider {
+  margin: 20px 0;
+  height: 1px;
+  width: 100%;
+  background-color: @brand-grey;
+}
 .font-weight-700 {
   font-weight: 700;
 }
@@ -70,6 +76,9 @@ strong {
 }
 
 /** Bootstrap */
+.btn:focus,.btn:active {
+  outline: none !important;
+}
 .btn-primary {
   color: @brand-text;
   background-color: @brand-grey;
@@ -86,6 +95,7 @@ strong {
   border-color: @brand-primary;
 }
 
+
 .btn-default {
   color: @brand-primary;
   background-color: @brand-white;
@@ -103,6 +113,41 @@ strong {
   border-color: @brand-primary;
 }
 
+
+.btn-default-red {
+  color: @brand-white!important;
+  background-color: @brand-primary;
+  border-color: @brand-primary;
+}
+
+.btn-default-red.active.focus, .btn-default-red.active:focus, .btn-default-red.active:hover, .btn-default-red:active.focus, .btn-default-red:active:focus, .btn-default-red:active:hover, .open>.dropdown-toggle.btn-default-red.focus, .open>.dropdown-toggle.btn-default-red:focus, .open>.dropdown-toggle.btn-default-red:hover {
+  color: @brand-primary!important;
+  background-color: @brand-white;
+  border-color: @brand-primary;
+}
+.btn-default-red.active, .btn-default-red:active, .btn-default-red:hover, .open>.dropdown-toggle.btn-default-red {
+  color: @brand-primary!important;
+  background-color: @brand-white;
+  border-color: @brand-primary;
+}
+
+.btn-grey-border {
+  color: @brand-secondary!important;
+  background-color: @brand-white;
+  border-color: @brand-secondary;
+}
+
+.btn-grey-border.active.focus, .btn-grey-border.active:focus, .btn-grey-border.active:hover, .btn-grey-border:active.focus, .btn-grey-border:active:focus, .btn-grey-border:active:hover, .open>.dropdown-toggle.btn-grey-border.focus, .open>.dropdown-toggle.btn-grey-border:focus, .open>.dropdown-toggle.btn-grey-border:hover {
+  color: @brand-white!important;
+  background-color: @brand-secondary;
+  border-color: @brand-secondary;
+}
+.btn-grey-border.active, .btn-grey-border:active, .btn-grey-border:hover, .open>.dropdown-toggle.btn-grey-border {
+  color: @brand-white!important;
+  background-color: @brand-secondary;
+  border-color: @brand-secondary;
+}
+
 /** TOP */
 #smad-header-section {
   padding: 10px 10px;
@@ -252,7 +297,7 @@ strong {
 }
 
 /** Footer */
-#smad-footer-section{
+#smad-footer-section {
   padding: 28px 0 10px 0;
   background-color: @brand-secondary;
   text-align: center;
@@ -287,3 +332,172 @@ strong {
     }
   }
 }
+
+
+/**
+ * Employees
+ */
+#smad-employees-section {
+  /*Form Wizard*/
+  .smad-wizard {
+    margin-top: 0px;
+  }
+  .smad-wizard {
+    border-bottom: solid 1px #e0e0e0;
+    padding: 0 0 10px 0;
+  }
+  .smad-wizard > .smad-wizard-step {
+    padding: 0;
+    position: relative;
+  }
+  .smad-wizard > .smad-wizard-step + .smad-wizard-step {
+  }
+  .smad-wizard > .smad-wizard-step .smad-wizard-stepnum {
+    color: #595959;
+    font-size: 16px;
+    margin-bottom: 5px;
+  }
+  .smad-wizard-info {
+    color: #999;
+    font-size: 14px;
+
+    .step-item {
+
+      .step-title {
+        color: @brand-text-light;
+      }
+    }
+  }
+
+  .smad-wizard-info.complete {
+    .step-item {
+      color: @brand-primary;
+    }
+
+    .step-title {
+      color: @brand-text;
+    }
+  }
+
+  .smad-wizard > .smad-wizard-step > .smad-wizard-dot {
+    position: absolute;
+    width: 30px;
+    height: 30px;
+    display: block;
+    background: none;
+    top: 48px;
+    left: 50%;
+    margin-top: -15px;
+    margin-left: -15px;
+    border-radius: 50%;
+  }
+  .smad-wizard > .smad-wizard-step > .smad-wizard-dot:after {
+    content: ' ';
+    width: 14px;
+    height: 14px;
+    background: @brand-white;
+    border-radius: 50px;
+    position: absolute;
+    top: 8px;
+    left: 8px;
+    border: 2px solid @brand-primary;
+  }
+  .smad-wizard > .smad-wizard-step > .progress {
+    position: relative;
+    border-radius: 0px;
+    height: 3px;
+    box-shadow: none;
+    margin: 20px 0;
+  }
+  .smad-wizard > .smad-wizard-step > .progress > .progress-bar {
+    width: 0px;
+    box-shadow: none;
+    background: @brand-grey;
+  }
+  .smad-wizard > .smad-wizard-step.complete > .progress > .progress-bar {
+    width: 100%;
+  }
+  .smad-wizard > .smad-wizard-step.active > .progress > .progress-bar {
+    width: 50%;
+  }
+  .smad-wizard > .smad-wizard-step:first-child.active > .progress > .progress-bar {
+    width: 0%;
+  }
+  .smad-wizard > .smad-wizard-step:last-child.active > .progress > .progress-bar {
+    width: 100%;
+  }
+  .smad-wizard > .smad-wizard-step.disabled > .smad-wizard-dot {
+    background-color: @brand-grey;
+  }
+  .smad-wizard > .smad-wizard-step.disabled > .smad-wizard-dot:after {
+    opacity: 0;
+  }
+  .smad-wizard > .smad-wizard-step:first-child > .progress {
+    left: 50%;
+    width: 50%;
+  }
+  .smad-wizard > .smad-wizard-step:last-child > .progress {
+    width: 50%;
+  }
+  .smad-wizard > .smad-wizard-step.disabled a.smad-wizard-dot {
+    pointer-events: none;
+  }
+  /*END Form Wizard*/
+  /** Form employes */
+  .smad-employees-form-section {
+
+    .menu-items {
+      padding-top: 20px;
+      padding-bottom: 20px;
+
+      .menu-item {
+        display: inline-block;
+      }
+      ul {
+        list-style-type: none;
+        display: inline-block;
+
+        li {
+          padding: 0 10px;
+          display: inline-block;
+        }
+      }
+    }
+  }
+
+  /** form list employes */
+  .smad-employees-list-head {
+    padding: 15px 0px;
+    background-color: @brand-grey-light;
+    .title {
+
+    }
+    .desc {
+      font-size: 15px;
+      line-height: 20px;
+    }
+
+    .menu-items {
+      padding-top: 30px;
+      padding-bottom: 20px;
+      float: right;
+
+      .menu-item {
+        display: inline-block;
+      }
+      ul {
+        list-style-type: none;
+        display: inline-block;
+
+        li {
+          padding: 0 10px;
+          display: inline-block;
+        }
+      }
+    }
+  }
+
+  .smad-employees-bottom-navigation {
+    padding: 30px 0;
+  }
+}

برخی فایل ها در این مقایسه diff نمایش داده نمی شوند زیرا تعداد فایل ها بسیار زیاد است