Skip to content
Open
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
16 changes: 16 additions & 0 deletions dna/course/zomes/courses/code/src/anchor_trait.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use hdk::prelude::*;
use std::convert::TryFrom;

// thanks to @HedayatAbedijoo for this trait
pub trait AnchorTrait: TryFrom<JsonString> + Into<JsonString> + Clone {
fn entry_type() -> String;
fn link_to() -> String;
fn link_type() -> String;
fn entry(self) -> Entry {
Entry::App(Self::entry_type().into(), self.into())
}

fn address(&self) -> ZomeApiResult<Address> {
hdk::entry_address(&self.clone().entry())
}
}
114 changes: 114 additions & 0 deletions dna/course/zomes/courses/code/src/course/anchor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use hdk::prelude::*;
use holochain_entry_utils::HolochainEntry;

use super::entry::Course;
use crate::anchor_trait::AnchorTrait;

pub const TEACHER_TO_COURSE_ANCHOR_LINK: &str = "teacher->course_anchor";
pub const STUDENT_TO_COURSE_ANCHOR_LINK: &str = "student->course_anchor";
pub const COURSE_ANCHOR_TO_STUDENT_LINK: &str = "course_anchor->student";

#[derive(Serialize, Deserialize, Debug, self::DefaultJson, Clone)]
pub struct CourseAnchor {
// NOTE: these fields are here to ensure the uniqueness of every particular anchor
// and wouldn't be used to display data about course to a user
pub title: String,
pub teacher_address: Address,
pub timestamp: u64,
}

impl AnchorTrait for CourseAnchor {
fn entry_type() -> String {
String::from("course_anchor")
}
fn link_to() -> String {
Course::entry_type()
}
fn link_type() -> String {
"course_anchor->course".to_owned()
}
}

impl CourseAnchor {
pub fn new(title: String, teacher_address: Address, timestamp: u64) -> Self {
CourseAnchor {
title: title,
teacher_address: teacher_address,
timestamp: timestamp,
}
}
}

pub fn course_anchor_def() -> ValidatingEntryType {
entry!(
name: CourseAnchor::entry_type(),
description: "Anchor to the valid course",
sharing: Sharing::Public,
validation_package: || {
hdk::ValidationPackageDefinition::Entry
},
validation: | validation_data: hdk::EntryValidationData<CourseAnchor>| {
match validation_data{
EntryValidationData::Create { .. } => {
Ok(())
},
EntryValidationData::Modify { .. } => {
Ok(())
},
EntryValidationData::Delete { .. } => {
Ok(())
}
}
},
links:[
// link that connects CourseAnchor to the latest Course entry
// This is a necessary link that allows access to course data
to!(
CourseAnchor::link_to(),
link_type: CourseAnchor::link_type(),
validation_package:||{
hdk::ValidationPackageDefinition::Entry
},
validation:|_validation_data: hdk::LinkValidationData|{
Ok(())
}
),
// link from agent that is a teacher of this course
// This is for teacher to keep track of all the courses that they're teaching
from!(
"%agent_id", // this is a special string that would automatically expand to the hdk::AGENT_ADDRESS
link_type: TEACHER_TO_COURSE_ANCHOR_LINK,
validation_package: || {
hdk::ValidationPackageDefinition::Entry
} ,
validation: | _validation_data: hdk::LinkValidationData | {
Ok(())
}
),
// link from agent that is a student who enrolled in this course
// This is for student to keep track of all the courses they've enrolled in
from!(
"%agent_id", // this is a special string that would automatically expand to the hdk::AGENT_ADDRESS
link_type: STUDENT_TO_COURSE_ANCHOR_LINK,
validation_package: || {
hdk::ValidationPackageDefinition::Entry
} ,
validation: | _validation_data: hdk::LinkValidationData | {
Ok(())
}
),
// link to an agent who is a student enrolled in this course.
// This is to keep track of student list from the course perspective
to!(
"%agent_id", // this is a special string that would automatically expand to the hdk::AGENT_ADDRESS
link_type: COURSE_ANCHOR_TO_STUDENT_LINK,
validation_package: || {
hdk::ValidationPackageDefinition::Entry
},
validation: | _validation_data: hdk::LinkValidationData | {
Ok(())
}
)
]
)
}
59 changes: 59 additions & 0 deletions dna/course/zomes/courses/code/src/course/catalogue_anchor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
use hdk::prelude::*;
use hdk::{entry_definition::ValidatingEntryType, holochain_core_types::dna::entry_types::Sharing};

use super::anchor::CourseAnchor;
use crate::anchor_trait::AnchorTrait;

#[derive(Serialize, Deserialize, Debug, self::DefaultJson, Clone)]
pub struct CourseCatalogAnchor {
name: String,
}

impl AnchorTrait for CourseCatalogAnchor {
fn entry_type() -> String {
String::from("course_catalog_anchor")
}
fn link_to() -> String {
CourseAnchor::entry_type()
}
fn link_type() -> String {
// NOTE: ideas for a better name for this link are welcome!
// there'll be a single link per every course
"course_list".to_owned()
}
}

impl CourseCatalogAnchor {
pub fn new() -> Self {
CourseCatalogAnchor {
name: CourseCatalogAnchor::entry_type(),
}
}
}

//// Anchor Definition : This Anchor will be used to query all courses
pub fn catalog_anchor_entry_def() -> ValidatingEntryType {
entry!(
name: CourseCatalogAnchor::entry_type(),
description:"Anchor that serves as a catalog for all Course entries",
sharing: Sharing::Public,
validation_package:||{
hdk::ValidationPackageDefinition::Entry
},
validation:|_validation_data: hdk::EntryValidationData<CourseCatalogAnchor>|{
Ok(())
},
links:[
to!(
CourseCatalogAnchor::link_to(),
link_type: CourseCatalogAnchor::link_type(),
validation_package:||{
hdk::ValidationPackageDefinition::Entry
},
validation:|_validation_data: hdk::LinkValidationData|{
Ok(())
}
)
]
)
}
67 changes: 67 additions & 0 deletions dna/course/zomes/courses/code/src/course/entry.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use hdk::{
entry_definition::ValidatingEntryType,
holochain_core_types::{dna::entry_types::Sharing, validation::EntryValidationData},
holochain_json_api::{error::JsonError, json::JsonString},
holochain_persistence_api::cas::content::Address,
};
use holochain_entry_utils::HolochainEntry;

#[derive(Serialize, Deserialize, Debug, DefaultJson, Clone)]
pub struct Course {
pub title: String,
pub sections: Vec<Address>,
pub teacher_address: Address,
pub timestamp: u64,
pub anchor_address: Address,
}

impl HolochainEntry for Course {
fn entry_type() -> String {
String::from("course")
}
}

impl Course {
pub fn new(
title: String,
sections: Vec<Address>,
teacher_address: Address,
timestamp: u64,
anchor_address: Address,
) -> Self {
Course {
title: title,
sections: sections,
teacher_address: teacher_address,
timestamp: timestamp,
anchor_address: anchor_address,
}
}
}

// Holochain entry definition for Course
pub fn course_entry_def() -> ValidatingEntryType {
entry!(
name: Course::entry_type(),
description: "this is the definition of course",
sharing: Sharing::Public,
validation_package: || {
hdk::ValidationPackageDefinition::Entry
},
validation: | validation_data: hdk::EntryValidationData<Course>| {
match validation_data {
EntryValidationData::Create { .. } => {
Ok(())
},
EntryValidationData::Modify { .. } => {
Ok(())
},
EntryValidationData::Delete { .. } => {
Ok(())
}
}
},
// All links that course should have are defined for CoureAnchor and so this entry doesn't have any
links: []
)
}
3 changes: 3 additions & 0 deletions dna/course/zomes/courses/code/src/course/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod anchor;
pub mod catalog_anchor;
pub mod entry;
93 changes: 57 additions & 36 deletions dna/course/zomes/courses/code/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,55 +1,76 @@
// allowing for this Rust project to have dead code on a crate level
#![allow(dead_code)]
// unstable Rust feature
// See more at: https://doc.rust-lang.org/nightly/unstable-book/language-features/proc-macro-hygiene.html
#![feature(proc_macro_hygiene)]
// This isn't a mistake that there are multiple #[macro_use] below: each applies to a particular crate that follows it
// specifying that we want to import macros defined in this crate too.
// See more at: https://doc.rust-lang.org/reference/macros-by-example.html
#[macro_use]
extern crate hdk;
extern crate hdk_proc_macros;
extern crate serde;
#[macro_use]
extern crate serde_derive;
extern crate serde_json;
#[macro_use]
extern crate holochain_json_derive;

use hdk::prelude::*;
use hdk_proc_macros::zome;

// see https://developer.holochain.org/api/0.0.50-alpha4/hdk/ for info on using the hdk library

// This is a sample zome that defines an entry type "MyEntry" that can be committed to the
// agent's chain via the exposed function create_my_entry
use hdk_proc_macros::zome;

#[derive(Serialize, Deserialize, Debug, DefaultJson, Clone)]
pub struct MyEntry {
content: String,
}
mod anchor_trait;
mod course;

#[zome]
mod my_zome {
mod courses {

// Things to be done on an hApp init, we skip this for now
#[init]
fn init() {
Ok(())
}

// Things to be done to validate each agent in the network, we skip this for now
#[validate_agent]
pub fn validate_agent(validation_data: EntryValidationData<AgentId>) {
Ok(())
}

// ====================== Course definitions (methods!)
#[entry_def]
fn course_catalog_anchor_entry_definition() -> ValidatingEntryType {
course::catalog_anchor::catalog_anchor_entry_def()
}

#[entry_def]
fn my_entry_def() -> ValidatingEntryType {
entry!(
name: "my_entry",
description: "this is a same entry defintion",
sharing: Sharing::Public,
validation_package: || {
hdk::ValidationPackageDefinition::Entry
},
validation: | _validation_data: hdk::EntryValidationData<MyEntry>| {
Ok(())
}
)
}

#[zome_fn("hc_public")]
fn create_my_entry(entry: MyEntry) -> ZomeApiResult<Address> {
let entry = Entry::App("my_entry".into(), entry.into());
let address = hdk::commit_entry(&entry)?;
Ok(address)
}

#[zome_fn("hc_public")]
fn get_my_entry(address: Address) -> ZomeApiResult<Option<Entry>> {
hdk::get_entry(&address)
}
}
fn course_anchor_definition() -> ValidatingEntryType {
course::anchor::course_anchor_def()
}

#[entry_def]
fn course_entry_definition() -> ValidatingEntryType {
course::entry::course_entry_def()
}

// Section
// TODO: implement section entry definitions
#[entry_def]
fn section_entry_definition() -> ValidatingEntryType {
section::entry::section_entry_def()
}
//new
#[entry_def]
fn section_anchor_definition() -> ValidatingEntryType {
section::entry::section_anchor_def()
}

// Content
// TODO: implement content entry definition
#[entry_def]
fn content_entry_definition() -> ValidatingEntryType {
section::entry::content_entry_def()
}

}
Loading