# HG changeset patch
# User Noe Gaumont <ngaumont@logilab.fr>
# Date 1613147735 -3600
#      Fri Feb 12 17:35:35 2021 +0100
# Node ID 3f96e0b0f87b46c7ce7e791b2060cd664fe65c1e
# Parent  e3b1995cd03a832514e0a52ceb621b68a3f224a8
feat: add CityShow and display it in MuseumShow

diff --git a/packages/demo/src/App.tsx b/packages/demo/src/App.tsx
--- a/packages/demo/src/App.tsx
+++ b/packages/demo/src/App.tsx
@@ -7,20 +7,40 @@
   TextField,
   DateField,
   NumberField,
+  ReferenceField,
   ShowGuesser,
+  ListGuesser,
   Edit,
   SimpleForm,
   TextInput,
   NumberInput,
   DateInput,
   EditProps,
+  ShowProps,
   ListProps,
+  Show,
+  SimpleShowLayout,
   DataProvider,
 } from "react-admin";
 import { createDataProvider } from "ra-cubicweb/dist";
 
 import { schema } from "./schema";
 
+export const MuseumShow = (props: ShowProps) => (
+  <Show {...props}>
+    <SimpleShowLayout>
+      <TextField source="postal_address" />
+      <NumberField source="longitude" />
+      <NumberField source="latitude" />
+      <TextField source="name" />
+      <TextField source="id" />
+      <ReferenceField label="City" link="show" reference="City" source="is_in">
+        <TextField source="name" />
+      </ReferenceField>
+    </SimpleShowLayout>
+  </Show>
+);
+
 const MuseumEdit = (props: EditProps) => (
   <Edit {...props}>
     <SimpleForm>
@@ -45,6 +65,26 @@
   </List>
 );
 
+export const CityList = (props: ListProps) => (
+  <List {...props}>
+    <Datagrid rowClick="show">
+      <NumberField source="zip_code" />
+      <TextField source="name" />
+      <TextField source="id" />
+    </Datagrid>
+  </List>
+);
+
+export const CityShow = (props: ShowProps) => (
+  <Show {...props}>
+    <SimpleShowLayout>
+      <NumberField source="zip_code" />
+      <TextField source="name" />
+      <TextField source="id" />
+    </SimpleShowLayout>
+  </Show>
+);
+
 const dataProvider = createDataProvider("http://localhost:8080", schema);
 dataProvider.getList("toto", {
   pagination: { page: 1, perPage: 10 },
@@ -62,9 +102,10 @@
     <Resource
       name="Museum"
       list={MuseumList}
-      show={ShowGuesser}
+      show={MuseumShow}
       edit={MuseumEdit}
     />
+    <Resource name="City" list={CityList} show={CityShow} />
   </Admin>
 );
 
diff --git a/packages/ra-cubicweb/src/index.ts b/packages/ra-cubicweb/src/index.ts
--- a/packages/ra-cubicweb/src/index.ts
+++ b/packages/ra-cubicweb/src/index.ts
@@ -1,6 +1,6 @@
 import { client } from "@logilab/cwclientlibjs";
 import { AuthProvider, DataProvider } from "ra-core";
-import { Schema, ETypesNames } from "./Schema";
+import { Schema, ETypesNames, Relationships } from "./Schema";
 
 // import authProvider from './authProvider';
 // see https://marmelab.com/react-admin/Authentication.html
@@ -60,8 +60,10 @@
           };
         });
     },
-    getOne: async (resource: ETypesNames<S>, _params) => {
-      const attributesNames = ["eid", ...Object.keys(schema.etypes[resource])];
+    getOne: async (resource: ETypesNames<S>, params) => {
+      // FIXME  Retrieve object relation
+      // Getting attributes
+      const attributesNames = [...Object.keys(schema.etypes[resource])];
       const selection: string[] = [];
       const restrictions: string[] = [];
       attributesNames.forEach((key, idx) => {
@@ -69,21 +71,69 @@
         selection.push(variable);
         restrictions.push(`X ${key} ${variable}`);
       });
+
       const result = await rqlClient.queryRows(
-        `Any ${selection.join(",")} Where ${restrictions.join(",")}`
+        `Any ${selection.join(",")} Where ${restrictions.join(",")}, X eid ${
+          params.id
+        }`
       );
       const row = result[0];
-      return {
-        data: row.reduce(
-          (agg, attributeValue, idx) => ({
-            [attributesNames[idx]]: attributeValue,
-            ...agg,
-          }),
-          { id: row[0] }
-        ),
-      };
+      const entity = row.reduce(
+        (agg, attributeValue, idx) => ({
+          [attributesNames[idx]]: attributeValue,
+          ...agg,
+        }),
+        { id: params.id }
+      );
+
+      // Getting relations
+      const subjectRelations = Object.fromEntries(
+        Object.entries(schema.relationships).filter(
+          ([_relationName, definition]: [string, S["relationships"][string]]) =>
+            definition.subject === resource
+        )
+      );
+      for (const relationName in subjectRelations) {
+        const definition: S["relationships"][string] =
+          subjectRelations[relationName];
+
+        const result = await rqlClient.queryRows(
+          `Any TARGET Where TARGET is ${definition.object},X ${relationName} TARGET, X eid ${params.id}`
+        );
+        if (result.length !== 0) {
+          entity[relationName] = result.map((row) => row[0]);
+        }
+      }
+      return { data: entity };
     },
-    getMany: (_resource, _params) => Promise.reject("Not implemented"),
+    getMany: async (resource, params) => {
+      // FIXME handle several params id and refactor code to use GetOne
+      // Getting attributes
+      const attributesNames = [...Object.keys(schema.etypes[resource])];
+      const selection: string[] = [];
+      const restrictions: string[] = [];
+      attributesNames.forEach((key, idx) => {
+        const variable = `X${idx}`;
+        selection.push(variable);
+        restrictions.push(`X ${key} ${variable}`);
+      });
+
+      const result = await rqlClient.queryRows(
+        `Any ${selection.join(",")} Where ${restrictions.join(",")}, X eid ${
+          params.ids[0]
+        }`
+      );
+      const row = result[0];
+      const entity = row.reduce(
+        (agg, attributeValue, idx) => ({
+          [attributesNames[idx]]: attributeValue,
+          ...agg,
+        }),
+        { id: params.ids[0] }
+      );
+
+      return { data: [entity] };
+    },
     getManyReference: (_resource, _params) => Promise.reject("Not implemented"),
     update: (_resource, _params) => Promise.reject("Not implemented"),
     updateMany: (_resource, _params) => Promise.reject("Not implemented"),