Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add annotations model and relations #14

Merged
merged 3 commits into from
Oct 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions composites/00-profile.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ type Profile
owner: DID! @documentAccount
version: CommitID! @documentVersion
displayName: String! @string(maxLength: 256)
# Should probably be generic key-value pairs, but that won't work with indexing
# for filter and sort
orcid: String @string(maxLength: 256)
googleScholar: String @string(maxLength: 256)
publicKey: String @string(maxLength: 512)
Expand Down
16 changes: 0 additions & 16 deletions composites/03-profileAttestation.graphql

This file was deleted.

21 changes: 0 additions & 21 deletions composites/04-researchObjectAttestation.graphql

This file was deleted.

14 changes: 2 additions & 12 deletions composites/07-researchComponent.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,10 @@ type ResearchComponent
{
owner: DID! @documentAccount
name: String! @string(maxLength: 512)
type: ComponentType!
mimeType: String! @string(maxLength: 128)
dagNode: CID!

# The associated research object in which this component lives
researchObjectID: StreamID! @documentReference(model: "ResearchObject")
researchObject: ResearchObject! @relationDocument(property: "researchObjectID")
}

# Problematic to have hardcoded since extension will change the Component model
enum ComponentType {
DATA_BUCKET
UNKNOWN
PDF
CODE
VIDEO
DATA
LINK
}
24 changes: 24 additions & 0 deletions composites/11-annotation.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
type ResearchComponent @loadModel(id: "$RESEARCH_COMPONENT_ID") {
id: ID!
}

type Claim @loadModel(id: "$CLAIM_ID") {
id: ID!
}

type Annotation
@createModel(accountRelation: LIST, description: "Research component commentary")
{
owner: DID! @documentAccount
comment: String! @string(maxLength: 1024)

componentID: StreamID! @documentReference(model: "ResearchComponent")
component: ResearchComponent! @relationDocument(property: "componentID")

# A way to identify the location of the annotation in the target component
# payload, for example a JSON path, line number, or coordinates in a pdf
path: String @string(maxLength: 512)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps we should add more fields here like cid, dpidPath, jsonPath and a generic path

i think we also need a "subPath" field... one locator identifies the component and the other navigates to something inside of it.

it would be nice if mimeType is available (perhaps it's already part of ResearchComponent def?)

Copy link
Collaborator Author

@m0ar m0ar Oct 9, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hubsmoke there 0-n ResearchComponent per ResearchObject, and an annotation points to a single ResearchComponent. So this field does just the latter: navigation inside that component. Does that make sense?

There is a makeshift type field that I temporarily yanked from nodes, but I agree a generic string field for mimeType makes more sense though. I've been hesitant on this because of the hard-coded alternatives. Feels reasonable for the gateway app to have it's own rules for which subset of mime it consider which views :)

enum ComponentType {
  DATA_BUCKET
  UNKNOWN
  PDF
  CODE
  VIDEO
  DATA
  LINK
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CID is already available as field dagNode on the ResearchComponent, so this path on the annotation would be jsonPath if the mimetype is JSON, page:coordinates or smt if it's a pdf, et cetera :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed the component type to mimeType in the PR as well :)


claimID: StreamID @documentReference(model: "Claim")
claim: Claim @relationDocument(property: "claimID")
}
17 changes: 12 additions & 5 deletions composites/additional-relations.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ type Attestation @loadModel(id: "$ATTESTATION_ID") {
id: ID!
}

type ResearchComponent @loadModel(id: "$RESEARCH_COMPONENT_ID") {
id: ID!
}

type ReferenceRelation @loadModel(id: "$REFERENCE_RELATION_ID") {
id: ID!
}
Expand All @@ -25,9 +21,21 @@ type ResearchFieldRelation @loadModel(id: "$RESEARCH_FIELD_RELATION_ID") {
id: ID!
}

type Annotation @loadModel(id: "$ANNOTATION_ID") {
id: ID!
}

type ResearchComponent @loadModel(id: "$RESEARCH_COMPONENT_ID") {
annotations: [Annotation] @relationFrom(model: "Annotation", property: "componentID")
annotationCount: Int! @relationCountFrom(model: "Annotation", property: "componentID")
}

type Claim @loadModel(id: "$CLAIM_ID") {
attestations: [Attestation] @relationFrom(model: "Attestation", property: "claimID")
attestationCount: Int! @relationCountFrom(model: "Attestation", property: "claimID")

annotations: [Annotation] @relationFrom(model: "Annotation", property: "claimID")
annotationCount: Int! @relationCountFrom(model: "Annotation", property: "claimID")
}

type ResearchObject @loadModel(id: "$RESEARCH_OBJECT_ID") {
Expand Down Expand Up @@ -66,4 +74,3 @@ type ResearchField @loadModel(id: "$RESEARCH_FIELD_ID") {
researchObjects: [ResearchFieldRelation] @relationFrom(model: "ResearchFieldRelation", property: "fieldID")
researchObjectCount: Int! @relationCountFrom(model: "ResearchFieldRelation", property: "fieldID")
}

56 changes: 29 additions & 27 deletions scripts/composites.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { readFileSync } from "fs";
import { copyFileSync, readFileSync } from "fs";
import { CeramicClient } from "@ceramicnetwork/http-client";
import {
createComposite,
Expand Down Expand Up @@ -99,26 +99,16 @@ export const writeComposite = async (spinner) => {
schema: researchFieldRelationSchema
});

// const profAttestationSchema = readFileSync(
// "./composites/03-profileAttestation.graphql",
// { encoding: "utf-8" }
// ).replace("$CLAIM_ID", claimComposite.modelIDs[0]);

// const profAttestationComposite = await Composite.create({
// ceramic,
// schema: profAttestationSchema,
// });

// const researchAttestationSchema = readFileSync(
// "./composites/04-researchObjectAttestation.graphql",
// { encoding: "utf-8" }
// ).replace("$RESEARCH_OBJECT_ID", researchObj.modelIDs[0])
// .replace("$CLAIM_ID", claimComposite.modelIDs[0]);
const annotationSchema = readFileSync(
"./composites/11-annotation.graphql",
{ encoding: "utf-8"}
).replace("$RESEARCH_COMPONENT_ID", componentComposite.modelIDs[1])
.replace("$CLAIM_ID", researchFieldComposite.modelIDs[0]);

// const researchAttestationComposite = await Composite.create({
// ceramic,
// schema: researchAttestationSchema,
// });
const annotationComposite = await Composite.create({
ceramic,
schema: annotationSchema
});

const additionalRelationsSchema = readFileSync(
"./composites/additional-relations.graphql",
Expand All @@ -134,7 +124,8 @@ export const writeComposite = async (spinner) => {
.replace("$CONTRIBUTOR_RELATION_ID", contributorRelationComposite.modelIDs[2])
.replace("$REFERENCE_RELATION_ID", referenceRelationComposite.modelIDs[1])
.replace("$RESEARCH_FIELD_ID", researchFieldComposite.modelIDs[0])
.replace("$RESEARCH_FIELD_RELATION_ID", researchFieldRelationComposite.modelIDs[2]);
.replace("$RESEARCH_FIELD_RELATION_ID", researchFieldRelationComposite.modelIDs[2])
.replace("$ANNOTATION_ID", annotationComposite.modelIDs[2]);

const additionalRelationsComposite = await Composite.create({
ceramic,
Expand All @@ -152,9 +143,8 @@ export const writeComposite = async (spinner) => {
contributorRelationComposite,
referenceRelationComposite,
researchFieldComposite,
researchFieldRelationComposite
// profAttestationComposite,
// researchAttestationComposite,
researchFieldRelationComposite,
annotationComposite
]);

await writeEncodedComposite(composite, "./src/__generated__/definition.json");
Expand All @@ -170,12 +160,24 @@ export const writeComposite = async (spinner) => {
"./src/__generated__/definition.json"
);

await deployComposite.startIndexingOn(ceramic);
// This is rediculous but there is a combination of things forcing
// requirements on the filenames
copyFileSync(
'./src/__generated__/definition.js',
'./src/__generated__/definition.mjs'
);
const { definition } = await import('../src/__generated__/definition.mjs');
const aliases = Object.entries(definition.models)
.map(([name, model]) => [name, model.id]);
// console.log('ALIASES:', aliases)

const aliasedDeployComposite = deployComposite.setAliases(
Object.fromEntries(aliases)
);
await aliasedDeployComposite.startIndexingOn(ceramic);
spinner.succeed("composite deployed & ready for use");
};



/**
* Authenticating DID for publishing composite
* @return {Promise<void>} - return void when DID is authenticated.
Expand Down
31 changes: 26 additions & 5 deletions template_data.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"contributorRelations": [],
"referenceRelations": [],
"researchFieldRelations": [],
"attestations": []
"attestations": [],
"annotations": []
},
"dc0b1125d15f276c5e6fdaf2465ae9f25d5e9984a7cb062640345c941d3ed1e0": {
"profile": {
Expand All @@ -37,7 +38,7 @@
{
"name": "A fancy dataset",
"dagNode": "bafkreibtsll3aq2bynvlxnqh6nxafzdm4cpiovr3bcncbkzjcy32xaaaaa",
"type": "DATA"
"mimeType": "text/csv"
}
]
},
Expand Down Expand Up @@ -93,7 +94,8 @@
}
],
"claims": [],
"attestations": []
"attestations": [],
"annotations": []
},
"17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015": {
"profile": {
Expand All @@ -109,7 +111,7 @@
{
"name": "Some cool data I found",
"dagNode": "bafkreibtsll3aq2bynvlxnqh6nxafzdm4cpiovr3bcncbkzjcy32xaaaaa",
"type": "DATA"
"mimeType": "text/csv"
}
]
}
Expand Down Expand Up @@ -160,7 +162,8 @@
1
]
}
]
],
"annotations": []
},
"fdda86398d9559fdc448be872f8e69dc11d9a19ae4707c7903fad530aa165b2c": {
"profile": {
Expand Down Expand Up @@ -193,6 +196,24 @@
0
]
}
],
"annotations": [
{
"comment": "I viewed this dataset and it seems to check out!",
"path": ".",
"componentPath": [
"17cd4168d7f322ef17a01dde0ae0900cf9beebdf2c2edd39029041819cdb1015",
"researchObjects",
0,
"components",
0
],
"claimPath": [
"1a40e10dc4830864781716eab4f88c60d74d8718cc5ed9af268d338a2096833f",
"claims",
1
]
}
]
}
}
5 changes: 2 additions & 3 deletions test/root.spec.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
import { ComposeClient } from '@composedb/client'
import { definition } from '@/src/__generated__/definition'
import { RuntimeCompositeDefinition } from '@composedb/types'
import { test, describe, beforeAll, expect } from 'vitest'
import { test, describe, beforeAll } from 'vitest'
import {
mutationCreateAttestation, mutationCreateClaim, mutationCreateProfile,
mutationCreateResearchObject, mutationUpdateAttestation, mutationUpdateResearchObject, queryResearchObjects
mutationCreateResearchObject, mutationUpdateAttestation, mutationUpdateResearchObject
} from '../utils/queries'
import { randomDID } from './util'
import { CeramicClient } from '@ceramicnetwork/http-client'
import { writeComposite } from 'scripts/composites.mjs'
import { setTimeout } from "timers/promises";
import { ROProps } from '@/types'

const CERAMIC_API = 'http:/localhost:7007'
const TIMEOUT = 7000
Expand Down
47 changes: 26 additions & 21 deletions types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,48 +19,54 @@ export type ROProps = {
export type ResearchComponent = {
owner?: DID
name: string
type: ComponentType
mimeType: string
dagNode: string
researchObjectID: string
};

export type ComponentType =
"DATA_BUCKET" |
"UNKNOWN"

export type Claim = {
id?: string,
title: string,
description: string,
id?: string
title: string
description: string
badge?: string
};

export type Attestation = {
id?: string,
source?: DID,
targetID: string,
claimID: string,
claim?: Claim ,
id?: string
source?: DID
targetID: string
claimID: string
claim?: Claim
revoked: boolean
};

export type Annotation = {
id?: string
comment: string
path: string
componentID: string
component?: ResearchComponent
claimID: string
claim?: Claim
};

export type ContributorRelation = {
id?: string,
role: string,
id?: string
role: string
// info
contributorID: string,
contributorID: string
researchObjectID: string
};

export type ReferenceRelation = {
id?: string,
toID: string,
id?: string
toID: string
fromID: string
};

export type ResearchFieldRelation = {
id?: string,
fieldID: string,
id?: string
fieldID: string
researchObjectID: string
};

Expand All @@ -72,4 +78,3 @@ export type SidebarProps = {
export type RequiredKeys<T> = {
[K in keyof T as (undefined extends T[K] ? never : K)]: T[K]
};

Loading