Skip to content
Snippets Groups Projects
Commit 8313185f authored by Timm Fitschen's avatar Timm Fitschen
Browse files

EHN: SELECT QUERY for properties of referenced entities.

parent 66026626
No related branches found
No related tags found
No related merge requests found
......@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added (for new features, dependecies etc.)
* Support for deeply nested selectors in SELECT queries.
* edit_mode supports reference properties when inserting/updating properties
(See [#83](https://gitlab.com/caosdb/caosdb-webui/-/issues/83) and
[#55](https://gitlab.com/caosdb/caosdb-webui/-/issues/55)).
......
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# ** header v3.0
# This file is a part of the CaosDB Project.
#
# Copyright (C) 2020 IndiScale GmbH <info@indiscale.com>
# Copyright (C) 2020 Timm Fitschen <t.fitschen@indiscale.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# ** end header
import caosdb
d = caosdb.execute_query("FIND Test*")
if len(d) > 0:
d.delete()
rt_house = caosdb.RecordType("TestHouse").insert()
rt_house.description = "A House"
caosdb.RecordType("TestWindow").insert()
rt_person = caosdb.RecordType("TestPerson").insert()
caosdb.RecordType("TestParty").insert()
caosdb.Property("TestHeight", datatype=caosdb.DOUBLE, unit="ft").insert()
caosdb.Property("TestDate", datatype=caosdb.DATETIME).insert()
window = caosdb.Record().add_parent("TestWindow")
window.add_property("TestHeight", 20.5, unit="ft")
window.insert()
owner = caosdb.Record("The Queen").add_parent("TestPerson").insert()
house = caosdb.Record("Buckingham Palace")
house.description = "A rather large house"
house.add_parent("TestHouse")
house.add_property(rt_person, name="TestOwner", value=owner)
house.add_property("TestWindow", window).insert()
g1 = caosdb.Record().add_parent("TestPerson").insert()
g2 = caosdb.Record().add_parent("TestPerson").insert()
g3 = caosdb.Record().add_parent("TestPerson").insert()
party = caosdb.Record("Diamond Jubilee of Elizabeth II").add_parent("TestParty")
party.add_property(rt_house, name="Location", value=house)
party.add_property("TestDate", "2012-02-06")
party.add_property(rt_person, datatype=caosdb.LIST(rt_person), name="Guests",
value = [g1, g2, g3])
party.insert()
......@@ -651,7 +651,7 @@ var resolve_references = new function () {
summary_field.dispatchEvent(
resolve_references
.summary_ready_event
); logger.error("here");})
);})
.catch((err) => {
logger.error(err);
})
......
......@@ -334,6 +334,19 @@
</xsl:with-param>
</xsl:call-template>
</xsl:for-each>
<xsl:for-each select="Record|RecordType|File|Property">
<xsl:call-template name="single-value">
<xsl:with-param name="reference">
<xsl:value-of select="'true'"/>
</xsl:with-param>
<xsl:with-param name="value">
<xsl:value-of select="@id"/>
</xsl:with-param>
<xsl:with-param name="boolean">
<xsl:value-of select="'false'"/>
</xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:element>
</div>
</xsl:template>
......@@ -377,17 +390,38 @@
</xsl:when>
<!-- hence, this is no collection -->
<xsl:otherwise>
<xsl:call-template name="single-value">
<xsl:with-param name="value">
<xsl:value-of select="text()"/>
</xsl:with-param>
<xsl:with-param name="reference">
<xsl:value-of select="not(contains('+INTEGER+DOUBLE+TEXT+BOOLEAN+DATETIME+',concat('+',@datatype,'+')))"/>
</xsl:with-param>
<xsl:with-param name="boolean">
<xsl:value-of select="@datatype='BOOLEAN'"/>
</xsl:with-param>
</xsl:call-template>
<xsl:choose>
<!-- the referenced entities have been returned. -->
<xsl:when test="*[@id]">
<xsl:for-each select="*[@id]">
<xsl:call-template name="single-value">
<xsl:with-param name="reference">
<xsl:value-of select="'true'"/>
</xsl:with-param>
<xsl:with-param name="value">
<xsl:value-of select="@id"/>
</xsl:with-param>
<xsl:with-param name="boolean">
<xsl:value-of select="'false'"/>
</xsl:with-param>
</xsl:call-template>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<!-- only the ids are available -->
<xsl:call-template name="single-value">
<xsl:with-param name="value">
<xsl:value-of select="text()"/>
</xsl:with-param>
<xsl:with-param name="reference">
<xsl:value-of select="not(contains('+INTEGER+DOUBLE+TEXT+BOOLEAN+DATETIME+',concat('+',@datatype,'+')))"/>
</xsl:with-param>
<xsl:with-param name="boolean">
<xsl:value-of select="@datatype='BOOLEAN'"/>
</xsl:with-param>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:otherwise>
</xsl:choose>
<!-- unit -->
......
......@@ -169,6 +169,7 @@
</span>
</a>
</xsl:template>
<xsl:template name="select-table-row">
<xsl:param name="entity-id"/>
<tr>
......@@ -180,7 +181,7 @@
<xsl:with-param name="entity-id" select="$entity-id"/>
</xsl:call-template>
</td>
<xsl:for-each select="/Response/Query/Selection/Selector[@name!='id']">
<xsl:for-each select="/Response/Query/Selection/Selector">
<xsl:call-template name="select-table-cell">
<xsl:with-param name="entity-id" select="$entity-id"/>
<xsl:with-param name="field-name" select="translate(@name, $uppercase, $lowercase)"/>
......@@ -188,6 +189,7 @@
</xsl:for-each>
</tr>
</xsl:template>
<xsl:template name="select-table-cell">
<xsl:param name="entity-id"/>
<xsl:param name="field-name"/>
......@@ -196,18 +198,90 @@
<xsl:value-of select="$field-name"/>
</xsl:attribute>
<div class="caosdb-f-property-value caosdb-v-property-value">
<xsl:choose>
<xsl:when test="/Response/*[@id=$entity-id]/@*[translate(name(),$uppercase, $lowercase)=$field-name]">
<xsl:value-of select="/Response/*[@id=$entity-id]/@*[translate(name(), $uppercase, $lowercase)=$field-name]"/>
</xsl:when>
<xsl:when test="/Response/*[@id=$entity-id]/Property[translate(@name, $uppercase, $lowercase)=$field-name]">
<xsl:apply-templates mode="property-value" select="/Response/*[@id=$entity-id]/Property[translate(@name, $uppercase, $lowercase)=$field-name]"/>
</xsl:when>
</xsl:choose>
<xsl:apply-templates select="/Response/*[@id=$entity-id]" mode="walk-select-segments">
<xsl:with-param name="first-segment">
<xsl:value-of select="substring-before(concat($field-name, '.'), '.')"/>
</xsl:with-param>
<xsl:with-param name="next-segments">
<xsl:value-of select="substring-after($field-name, '.')"/>
</xsl:with-param>
</xsl:apply-templates>
</div>
</td>
</xsl:template>
<xsl:template match="Property" mode="walk-select-segments">
<!-- handle properties -->
<xsl:param name="next-segments"/>
<xsl:choose>
<xsl:when test="$next-segments='value'">
<!--handle value-->
<xsl:apply-templates mode="property-value" select="."/>
</xsl:when>
<xsl:when test="translate($next-segments, $uppercase, $lowercase)='unit'">
<!--handle unit-->
<xsl:call-template name="single-value">
<xsl:with-param name="value">
<xsl:value-of select="@unit"/>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:when test="$next-segments!=''">
<!--walk to next level of nested entities-->
<xsl:apply-templates select="*[@id]" mode="walk-select-segments">
<xsl:with-param name="first-segment">
<xsl:value-of select="substring-before(concat($next-segments, '.'), '.')"/>
</xsl:with-param>
<xsl:with-param name="next-segments">
<xsl:value-of select="substring-after($next-segments, '.')"/>
</xsl:with-param>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<!--next is empty. handle complete property-->
<xsl:apply-templates mode="property-value" select="."/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="*" mode="walk-select-segments">
<!-- handle anything but attributes and properties -->
<xsl:param name="first-segment"/>
<xsl:param name="next-segments"/>
<xsl:choose>
<xsl:when test="@*[translate($first-segment, $uppercase, $lowercase)=name()]">
<!--handle attributes-->
<xsl:call-template name="single-value">
<xsl:with-param name="value">
<xsl:value-of select="@*[translate(name(), $uppercase, $lowercase)=$first-segment]"/>
</xsl:with-param>
</xsl:call-template>
</xsl:when>
<xsl:when test="$next-segments">
<!-- when there is a next-segmenst -->
<xsl:apply-templates select="Property[translate(@name, $uppercase, $lowercase)=$first-segment]" mode="walk-select-segments">
<xsl:with-param name="next-segments">
<xsl:value-of select="$next-segments"/>
</xsl:with-param>
</xsl:apply-templates>
</xsl:when>
<xsl:otherwise>
<!-- otherwise, this is the final segment and the reference can be printed. -->
<xsl:value-of select="@id"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="caosdb-query-panel">
<!-- query panel, this is the area which contains the query form and other related stuff (e.g. query short cuts). -->
<div class="container caosdb-query-panel">
<form class="panel" id="caosdb-query-form" method="GET">
<xsl:attribute name="action">
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment