Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2892723
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
21 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/resources/sql/20230427.semistructured.1.objecttype.sql b/resources/sql/20230427.semistructured.1.objecttype.sql
new file mode 100644
index 0000000..6e9fbc0
--- /dev/null
+++ b/resources/sql/20230427.semistructured.1.objecttype.sql
@@ -0,0 +1,24 @@
+CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objecttype (
+ id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
+ phid VARBINARY(64) NOT NULL,
+ dateCreated INT UNSIGNED NOT NULL,
+ dateModified INT UNSIGNED NOT NULL,
+
+ name VARCHAR(255) NOT NULL COLLATE {$COLLATE_SORT},
+ description LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
+ status VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
+
+ UNIQUE KEY `key_phid` (phid)
+) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
+
+-- CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objecttypetransaction
+-- LIKE {$NAMESPACE}_file.file_transaction;
+
+CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objecttype_ffield
+ LIKE {$NAMESPACE}_dashboard.dashboard_dashboard_ffield;
+CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objecttype_fdocument
+ LIKE {$NAMESPACE}_dashboard.dashboard_dashboard_fdocument;
+CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objecttype_fngrams
+ LIKE {$NAMESPACE}_dashboard.dashboard_dashboard_fngrams;
+CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objecttype_fngrams_common
+ LIKE {$NAMESPACE}_dashboard.dashboard_dashboard_fngrams_common;
diff --git a/resources/sql/20230427.semistructured.1.objectinstance.sql b/resources/sql/20230427.semistructured.2.objectinstance.sql
similarity index 78%
rename from resources/sql/20230427.semistructured.1.objectinstance.sql
rename to resources/sql/20230427.semistructured.2.objectinstance.sql
index c3ada15..f935943 100644
--- a/resources/sql/20230427.semistructured.1.objectinstance.sql
+++ b/resources/sql/20230427.semistructured.2.objectinstance.sql
@@ -1,16 +1,16 @@
CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objectinstance (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
phid VARBINARY(64) NOT NULL,
dateCreated INT UNSIGNED NOT NULL,
dateModified INT UNSIGNED NOT NULL,
classPHID VARBINARY(64) NOT NULL,
status VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
rawData LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
UNIQUE KEY `key_phid` (phid),
KEY `classPHID` (classPHID)
) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
-CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objectinstancetransaction
- LIKE {$NAMESPACE}_file.file_transaction;
+-- CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objectinstancetransaction
+-- LIKE {$NAMESPACE}_file.file_transaction;
diff --git a/resources/sql/20230427.semistructured.2.objecttype.sql b/resources/sql/20230427.semistructured.2.objecttype.sql
deleted file mode 100644
index 232ec94..0000000
--- a/resources/sql/20230427.semistructured.2.objecttype.sql
+++ /dev/null
@@ -1,15 +0,0 @@
-CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objecttype (
- id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
- phid VARBINARY(64) NOT NULL,
- dateCreated INT UNSIGNED NOT NULL,
- dateModified INT UNSIGNED NOT NULL,
-
- name VARCHAR(255) NOT NULL COLLATE {$COLLATE_SORT},
- description LONGTEXT NOT NULL COLLATE {$COLLATE_TEXT},
- status VARCHAR(32) NOT NULL COLLATE {$COLLATE_TEXT},
-
- UNIQUE KEY `key_phid` (phid)
-) ENGINE=InnoDB, COLLATE {$COLLATE_TEXT};
-
-CREATE TABLE {$NAMESPACE}_semistructured.semistructured_objecttypetransaction
- LIKE {$NAMESPACE}_file.file_transaction;
diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php
index 0baa48d..872b200 100644
--- a/src/__phutil_library_map__.php
+++ b/src/__phutil_library_map__.php
@@ -1,44 +1,55 @@
<?php
/**
* This file is automatically generated. Use 'arc liberate' to rebuild it.
*
* @generated
* @phutil-library-version 2
*/
phutil_register_library_map(array(
'__library_version__' => 2,
'class' => array(
'SemiStructuredBaseController' => 'applications/semistruct/controller/SemiStructuredBaseController.php',
'SemiStructuredDAO' => 'applications/semistruct/storage/SemiStructuredDAO.php',
'SemiStructuredDataApplication' => 'applications/semistruct/application/SemiStructuredDataApplication.php',
'SemiStructuredObjectInstance' => 'applications/semistruct/storage/SemiStructuredObjectInstance.php',
'SemiStructuredObjectInstancePHIDType' => 'applications/semistruct/phid/SemiStructuredObjectInstancePHIDType.php',
+ 'SemiStructuredObjectInstanceQuery' => 'applications/semistruct/query/SemiStructuredObjectInstanceQuery.php',
'SemiStructuredObjectType' => 'applications/semistruct/storage/SemiStructuredObjectType.php',
+ 'SemiStructuredObjectTypeFerretEngine' => 'applications/semistruct/engine/SemiStructuredObjectTypeFerretEngine.php',
+ 'SemiStructuredObjectTypeListController' => 'applications/semistruct/controller/SemiStructuredObjectTypeListController.php',
'SemiStructuredObjectTypePHIDType' => 'applications/semistruct/phid/SemiStructuredObjectTypePHIDType.php',
+ 'SemiStructuredObjectTypeQuery' => 'applications/semistruct/query/SemiStructuredObjectTypeQuery.php',
+ 'SemiStructuredObjectTypeSearchEngine' => 'applications/semistruct/query/SemiStructuredObjectTypeSearchEngine.php',
'SemiStructuredPatchList' => 'applications/semistruct/storage/SemiStructuredPatchList.php',
),
'function' => array(),
'xmap' => array(
'SemiStructuredBaseController' => 'PhabricatorController',
'SemiStructuredDAO' => 'PhabricatorLiskDAO',
'SemiStructuredDataApplication' => 'PhabricatorApplication',
'SemiStructuredObjectInstance' => array(
'SemiStructuredDAO',
'PhabricatorPolicyInterface',
'PhabricatorApplicationTransactionInterface',
'PhabricatorFlaggableInterface',
'PhabricatorDestructibleInterface',
),
'SemiStructuredObjectInstancePHIDType' => 'PhabricatorPHIDType',
+ 'SemiStructuredObjectInstanceQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
'SemiStructuredObjectType' => array(
'SemiStructuredDAO',
'PhabricatorPolicyInterface',
'PhabricatorApplicationTransactionInterface',
'PhabricatorFlaggableInterface',
'PhabricatorDestructibleInterface',
+ 'PhabricatorFerretInterface',
),
+ 'SemiStructuredObjectTypeFerretEngine' => 'PhabricatorFerretEngine',
+ 'SemiStructuredObjectTypeListController' => 'SemiStructuredBaseController',
'SemiStructuredObjectTypePHIDType' => 'PhabricatorPHIDType',
+ 'SemiStructuredObjectTypeQuery' => 'PhabricatorCursorPagedPolicyAwareQuery',
+ 'SemiStructuredObjectTypeSearchEngine' => 'PhabricatorApplicationSearchEngine',
'SemiStructuredPatchList' => 'PhabricatorSQLPatchList',
),
));
diff --git a/src/application/SemiStructuredDataApplication.php b/src/application/SemiStructuredDataApplication.php
index 873b6b1..4c0022f 100644
--- a/src/application/SemiStructuredDataApplication.php
+++ b/src/application/SemiStructuredDataApplication.php
@@ -1,23 +1,25 @@
<?php
final class SemiStructuredDataApplication extends PhabricatorApplication {
public function getName() {
return pht('Semi-Structured');
}
public function getShortDescription() {
- return 'TBD';
+ return pht('Work with evolving data sets.');
}
public function getBaseURI() {
return '/semistruct/';
}
public function getRoutes() {
return array(
'/semistruct/' => array(
+ '(?:query/(?P<queryKey>[^/]+)/)?' =>
+ 'SemiStructuredObjectTypeListController',
),
);
}
}
diff --git a/src/controller/SemiStructuredBaseController.php b/src/controller/SemiStructuredBaseController.php
index 4ad8018..ab83928 100644
--- a/src/controller/SemiStructuredBaseController.php
+++ b/src/controller/SemiStructuredBaseController.php
@@ -1,11 +1,16 @@
<?php
abstract class SemiStructuredBaseController extends PhabricatorController {
public function buildApplicationMenu() {
return $this->newApplicationMenu()
// ->setSearchEngine(new PhabricatorBadgesSearchEngine());
;
}
+ public function shouldAllowPublic() {
+ return true;
+ }
+
+
}
diff --git a/src/controller/SemiStructuredObjectTypeListController.php b/src/controller/SemiStructuredObjectTypeListController.php
new file mode 100644
index 0000000..f9d30fa
--- /dev/null
+++ b/src/controller/SemiStructuredObjectTypeListController.php
@@ -0,0 +1,41 @@
+<?php
+
+final class SemiStructuredObjectTypeListController
+ extends SemiStructuredBaseController {
+
+ public function handleRequest(AphrontRequest $request) {
+ $viewer = $request->getViewer();
+ $query_key = $request->getURIData('queryKey');
+
+ $controller = id(new PhabricatorApplicationSearchController())
+ ->setQueryKey($query_key)
+ ->setSearchEngine(new SemiStructuredObjectTypeSearchEngine())
+ ->setNavigation($this->buildSideNavView());
+ return $this->delegateToController($controller);
+ }
+
+ public function buildSideNavView() {
+ $user = $this->getRequest()->getUser();
+
+ $nav = new AphrontSideNavFilterView();
+ $nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
+
+ id(new SemiStructuredObjectTypeSearchEngine())
+ ->setViewer($user)
+ ->addNavigationItems($nav->getMenu());
+
+ $nav->selectFilter(null);
+
+ return $nav;
+ }
+
+ protected function buildApplicationCrumbs() {
+ $crumbs = parent::buildApplicationCrumbs();
+
+// id(new SemiStructuredObjectTypeEditEngine()) // TODO
+ // ->setViewer($this->getViewer())
+ // ->addActionToCrumbs($crumbs);
+
+ return $crumbs;
+ }
+}
diff --git a/src/engine/SemiStructuredObjectTypeFerretEngine.php b/src/engine/SemiStructuredObjectTypeFerretEngine.php
new file mode 100644
index 0000000..20510df
--- /dev/null
+++ b/src/engine/SemiStructuredObjectTypeFerretEngine.php
@@ -0,0 +1,18 @@
+<?php
+
+final class SemiStructuredObjectTypeFerretEngine
+ extends PhabricatorFerretEngine {
+
+ public function getApplicationName() {
+ return 'semistructured';
+ }
+
+ public function getScopeName() {
+ return 'objecttype';
+ }
+
+ public function newSearchEngine() {
+ return new SemiStructuredObjectTypeSearchEngine();
+ }
+
+}
diff --git a/src/query/SemiStructuredObjectInstanceQuery.php b/src/query/SemiStructuredObjectInstanceQuery.php
new file mode 100644
index 0000000..233322e
--- /dev/null
+++ b/src/query/SemiStructuredObjectInstanceQuery.php
@@ -0,0 +1,100 @@
+<?php
+
+final class SemiStructuredObjectInstanceQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+ private $classPHIDs;
+ private $statuses;
+ private $canEdit;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withClassPHIDs(array $classPHIDs) {
+ $this->classPHIDs = $classPHIDs;
+ return $this;
+ }
+
+ public function withStatuses(array $statuses) {
+ $this->statuses = $statuses;
+ return $this;
+ }
+
+
+ public function withCanEdit($can_edit) {
+ $this->canEdit = $can_edit;
+ return $this;
+ }
+
+ public function newResultObject() {
+ return new SemiStructuredObjectInstance();
+ }
+
+ protected function didFilterPage(array $items) {
+
+ $phids = mpull($items, 'getPHID');
+
+ if ($this->canEdit) {
+ $items = id(new PhabricatorPolicyFilter())
+ ->setViewer($this->getViewer())
+ ->requireCapabilities(array(
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->apply($items);
+ }
+
+ return $items;
+ }
+
+ protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
+ $where = parent::buildWhereClauseParts($conn);
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'instances.id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'instances.phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->classPHIDs !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'instances.classPHID IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->statuses !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'instances.status IN (%Ls)',
+ $this->statuses);
+ }
+
+ return $where;
+ }
+
+ public function getQueryApplicationClass() {
+ return 'SemiStructuredDataApplication';
+ }
+
+ protected function getPrimaryTableAlias() {
+ return 'instances';
+ }
+
+}
diff --git a/src/query/SemiStructuredObjectTypeQuery.php b/src/query/SemiStructuredObjectTypeQuery.php
new file mode 100644
index 0000000..4fade63
--- /dev/null
+++ b/src/query/SemiStructuredObjectTypeQuery.php
@@ -0,0 +1,87 @@
+<?php
+
+final class SemiStructuredObjectTypeQuery
+ extends PhabricatorCursorPagedPolicyAwareQuery {
+
+ private $ids;
+ private $phids;
+ private $statuses;
+ private $canEdit;
+
+ public function withIDs(array $ids) {
+ $this->ids = $ids;
+ return $this;
+ }
+
+ public function withPHIDs(array $phids) {
+ $this->phids = $phids;
+ return $this;
+ }
+
+ public function withStatuses(array $statuses) {
+ $this->statuses = $statuses;
+ return $this;
+ }
+
+
+ public function withCanEdit($can_edit) {
+ $this->canEdit = $can_edit;
+ return $this;
+ }
+
+ public function newResultObject() {
+ return new SemiStructuredObjectType();
+ }
+
+ protected function didFilterPage(array $items) {
+
+ $phids = mpull($items, 'getPHID');
+
+ if ($this->canEdit) {
+ $items = id(new PhabricatorPolicyFilter())
+ ->setViewer($this->getViewer())
+ ->requireCapabilities(array(
+ PhabricatorPolicyCapability::CAN_EDIT,
+ ))
+ ->apply($items);
+ }
+
+ return $items;
+ }
+
+ protected function buildWhereClauseParts(AphrontDatabaseConnection $conn) {
+ $where = parent::buildWhereClauseParts($conn);
+
+ if ($this->ids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'classes.id IN (%Ld)',
+ $this->ids);
+ }
+
+ if ($this->phids !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'classes.phid IN (%Ls)',
+ $this->phids);
+ }
+
+ if ($this->statuses !== null) {
+ $where[] = qsprintf(
+ $conn,
+ 'classes.status IN (%Ls)',
+ $this->statuses);
+ }
+
+ return $where;
+ }
+
+ public function getQueryApplicationClass() {
+ return 'SemiStructuredDataApplication';
+ }
+
+ protected function getPrimaryTableAlias() {
+ return 'classes';
+ }
+
+}
diff --git a/src/query/SemiStructuredObjectTypeSearchEngine.php b/src/query/SemiStructuredObjectTypeSearchEngine.php
new file mode 100644
index 0000000..82b09a9
--- /dev/null
+++ b/src/query/SemiStructuredObjectTypeSearchEngine.php
@@ -0,0 +1,153 @@
+<?php
+
+final class SemiStructuredObjectTypeSearchEngine
+ extends PhabricatorApplicationSearchEngine {
+
+ public function getResultTypeDescription() {
+ return pht('Object Types');
+ }
+
+ public function getApplicationClassName() {
+ return 'SemiStructuredDataApplication';
+ }
+
+ public function newQuery() {
+ return id(new SemiStructuredObjectTypeQuery());
+ }
+
+ protected function buildCustomSearchFields() {
+ return array(
+ id(new PhabricatorSearchCheckboxesField())
+ ->setKey('statuses')
+ ->setLabel(pht('Status'))
+ ->setOptions(PhabricatorDashboard::getStatusNameMap()),
+ id(new PhabricatorSearchCheckboxesField())
+ ->setKey('editable')
+ ->setLabel(pht('Editable'))
+ ->setOptions(array('editable' => null)),
+ );
+ }
+
+ protected function getURI($path) {
+ return '/semistruct/'.$path;
+ }
+
+ protected function getBuiltinQueryNames() {
+ $names = array();
+
+ $names['all'] = pht('All Types');
+ $names['open'] = pht('Active Types');
+
+ return $names;
+ }
+
+ public function buildSavedQueryFromBuiltin($query_key) {
+ $query = $this->newSavedQuery();
+ $query->setQueryKey($query_key);
+ $viewer = $this->requireViewer();
+
+ switch ($query_key) {
+ case 'all':
+ return $query;
+ case 'open':
+ return $query->setParameter(
+ 'statuses',
+ array(
+ SemiStructuredObjectType::STATUS_ACTIVE,
+ ));
+ }
+
+ return parent::buildSavedQueryFromBuiltin($query_key);
+ }
+
+
+ protected function buildQueryFromParameters(array $map) {
+ $query = $this->newQuery();
+
+ if ($map['statuses']) {
+ $query->withStatuses($map['statuses']);
+ }
+
+ if ($map['editable'] !== null) {
+ $query->withCanEdit($map['editable']);
+ }
+
+ return $query;
+ }
+
+ protected function renderResultList(
+ array $items,
+ PhabricatorSavedQuery $query,
+ array $handles) {
+
+ $viewer = $this->requireViewer();
+
+ $phids = array();
+ foreach ($items as $item) {
+ // $author_phid = $dashboard->getAuthorPHID();
+ // if ($author_phid) {
+ // $phids[] = $author_phid;
+ // }
+ }
+
+ $handles = $viewer->loadHandles($phids);
+
+ if ($items) {
+ $edge_query = id(new PhabricatorEdgeQuery())
+ ->withSourcePHIDs(mpull($items, 'getPHID'))
+ ->withEdgeTypes(
+ array(
+ PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
+ ));
+
+ $edge_query->execute();
+ }
+
+ $list = id(new PHUIObjectItemListView())
+ ->setViewer($viewer);
+
+ foreach ($items as $item) {
+ $item = id(new PHUIObjectItemView())
+ ->setViewer($viewer)
+ ->setObjectName($item->getObjectName())
+ ->setHeader($item->getName())
+ ->setHref($item->getURI())
+ ->setObject($item);
+
+ if ($item->isArchived()) {
+ $item->setDisabled(true);
+ $bg_color = 'bg-grey';
+ } else {
+ $bg_color = 'bg-dark';
+ }
+
+ $icon = id(new PHUIIconView())
+ ->setIcon($item->getIcon())
+ ->setBackground($bg_color);
+ $item->setImageIcon($icon);
+ $item->setEpoch($item->getDateModified());
+
+
+ $phid = $item->getPHID();
+ $project_phids = $edge_query->getDestinationPHIDs(array($phid));
+ $project_handles = $viewer->loadHandles($project_phids);
+
+ $item->addAttribute(
+ id(new PHUIHandleTagListView())
+ ->setLimit(4)
+ ->setNoDataString(pht('No Tags'))
+ ->setSlim(true)
+ ->setHandles($project_handles));
+
+ $list->addItem($item);
+ }
+
+ $result = new PhabricatorApplicationSearchResultView();
+ $result->setObjectList($list);
+ $result->setNoDataString(pht('No object types found.'));
+
+ return $result;
+ }
+
+
+}
diff --git a/src/storage/SemiStructuredObjectType.php b/src/storage/SemiStructuredObjectType.php
index 356e0ba..fcf849d 100644
--- a/src/storage/SemiStructuredObjectType.php
+++ b/src/storage/SemiStructuredObjectType.php
@@ -1,99 +1,106 @@
<?php
final class SemiStructuredObjectType extends SemiStructuredDAO
implements
PhabricatorPolicyInterface,
PhabricatorApplicationTransactionInterface,
// PhabricatorSubscribableInterface,
PhabricatorFlaggableInterface,
- PhabricatorDestructibleInterface
+ PhabricatorDestructibleInterface,
+ PhabricatorFerretInterface
// PhabricatorConduitResultInterface
{
protected $name;
protected $status;
protected $description;
const STATUS_ACTIVE = 'active';
const STATUS_ARCHIVED = 'archived';
public static function initializeNewObjectType(PhabricatorUser $actor) {
return id(new self())
->setName('')
->setViewPolicy(PhabricatorPolicies::getMostOpenPolicy())
->setEditPolicy($actor->getPHID()) // TODO config for deflt
->setStatus(self::STATUS_ACTIVE);
}
public static function getStatusNameMap() {
return array(
self::STATUS_ACTIVE => pht('Active'),
self::STATUS_ARCHIVED => pht('Archived'),
);
}
protected function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
self::CONFIG_COLUMN_SCHEMA => array(
'name' => 'sort255',
'status' => 'text32',
'description' => 'text',
),
) + parent::getConfiguration();
}
/* -( PhabricatorApplicationTransactionInterface )------------------------- */
public function getApplicationTransactionEditor() {
return new PhabricatorDashboardPanelTransactionEditor();
}
public function getApplicationTransactionTemplate() {
return new PhabricatorDashboardPanelTransaction();
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public function getCapabilities() {
return array(
PhabricatorPolicyCapability::CAN_VIEW,
PhabricatorPolicyCapability::CAN_EDIT,
);
}
public function getPolicy($capability) {
switch ($capability) {
case PhabricatorPolicyCapability::CAN_VIEW:
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return $this->getEditPolicy();
}
}
public function hasAutomaticCapability($capability, PhabricatorUser $viewer) {
return false;
}
/* -( PhabricatorDestructibleInterface )----------------------------------- */
public function destroyObjectPermanently(
PhabricatorDestructionEngine $engine) {
$this->openTransaction();
$this->delete();
$this->saveTransaction();
}
+/* -( PhabricatorFerretInterface )----------------------------------------- */
+
+ public function newFerretEngine() {
+ return new SemiStructuredObjectTypeFerretEngine();
+ }
+
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 17:15 (1 w, 5 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1119699
Default Alt Text
(21 KB)
Attached To
Mode
R6 Semi Structured
Attached
Detach File
Event Timeline
Log In to Comment