Skip to content

Commit

Permalink
Added new fields, todos, new filler from voyage#50 #181
Browse files Browse the repository at this point in the history
  • Loading branch information
RichardLitt committed May 25, 2015
1 parent efa4537 commit 05d7356
Showing 1 changed file with 257 additions and 16 deletions.
273 changes: 257 additions & 16 deletions js/data/schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,24 @@
// ID AccountID
// Name string // full name of the account
// Avatar string // a square picture for the account
// Email string // email associated with account
// PrimaryEmail string // email associated with account
// Emails []string // other email accounts (should include "primary email")
// }

module.exports.account = exports.account = {
'_id': 'hash1234',
'name': 'Richard Feynman',
'avatar': 'http://upload.wikimedia.org/wikipedia/en/4/42/Richard_Feynman_Nobel.jpg',
'email': '[email protected]'
'primaryEmail': '[email protected]',
'emails': [
'[email protected]',
'[email protected]'
]
}

// User is an individual user, a Person.
// type User struct {
// Account // it is an account.
// Account // it is an account. (this is "embedded here", Go uses composition instead of inheritance)

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 25, 2015

Author Member

I'm not sure what this comment means for me: should I look up Go's implementation of types? How should I structure the user account object? @jbenet

This comment has been minimized.

Copy link
@jbenet

jbenet May 27, 2015

Contributor

@RichardLitt it just means it's subclassed. so it's equivalent to something like:

class Foo
class Bar extends Foo

in some other language

or

var Foo = klass(...)
var Bar = Foo.extend(...)

in js. but we don't even need to do classes, it just means that the subclass objects should use the parent's fields and functions too.

// OAuthTokens []string
// }

Expand Down Expand Up @@ -81,39 +86,96 @@ module.exports.conversation = exports.conversation = {
]
}

// it would be nice to leverage some "media schema" that
// already exists rather than invent our own. It's likely
// something that the Linked Data community has already
// made
// var MediaTypes = []string{
// "publication", // paper
// "webpage",
// "image",
// ...
// }

// TODO Why is this an array, and not just a string?

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 25, 2015

Author Member

Note these three lines @jbenet

This comment has been minimized.

Copy link
@adammarblestone-zz

adammarblestone-zz May 25, 2015

Also are conversations / annotations / notes themselves a form of "media"?

This comment has been minimized.

Copy link
@jbenet

jbenet May 27, 2015

Contributor

Why is this an array, and not just a string?

it's an array of different strings. each string is a type of media.

Also are conversations / annotations / notes themselves a form of "media"?

yeah we can count them as such.

What is this for, exactly? When is this used?

to help disambiguate how to display things. the UI will change somewhat depending on whether we're looking at a publication or an image or a webpage, ...

// TODO Should we validate this using some sort of testing?
// TODO What is this for, exactly? When is this used?

module.exports.mediaTypes = exports.mediaTypes = [
'publication', 'webpage', 'image'
]

// // A MediaObject is a specific piece of media that's
// // able to be viewed, referenced, and linked to.
// // For example, a Paper, a webpage, or an image.
// type MediaObject struct {
// Entity // it is an entity

// // all media objects must have
// Title string
// Type string // one of MediaTypes
// Authors []string
// SourceURL string // the source URL of the object.

// // everything else (like DOI, etc) we can put in a big
// // "metadata" sub-object (this just means an arbitrary json object)
// Metadata map[string]interface{}
// // TODO What does map[string]interface{} mean?

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 25, 2015

Author Member

@jbenet What does this mean?

// }

module.exports.mediaObject = exports.mediaObject = {
'title': 'Boy with apple',
'type': 'image',
'authors': 'Johannes Van Hoyt The Younger', // ID?
'sourceURL': 'http://www.mrtaylor.co.uk/static/images/appleboy_c.jpg',
'metadata': {
'bleep': 'blorp'
}
}

// A Note is a piece of text related to a conversation.
// type Note struct {
// ID Entity

// Text string
// Owner []AccountID
// Participants Membership
// Author []AccountID
// Conversation EntityID // link
// }

module.exports.note = exports.note = {
'_id': 'hash4567',
'text': 'Ever since I was little, I have always loved the sound of my own voice.',
'owner': [
'author': [
'Richard Feynman'
],
'participants': [
'Richard Feynman',
'Noam Chompsky'
]
'conversation': 'asfjklsjglw'
}

// Type of permission.
// type PermType int
// An Annotation is a piece of media affixed to another piece of media.
// type Annotaton struct {
// Entity // it is an entity
//
// Source EntityID // a MediaObject
// Author AccountID // author of the annotation
// }

module.exports.annotation = exports.annotation = {
'_id': 'ranodmhash',
'source': 'asdfjlw',
'author': 'lksdjfsl'
}

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 25, 2015

Author Member

I don't understand when this is used, and it seems to only have a source, and not a destination. Or does entity mean more than just having an id? What are the fields for this?

This comment has been minimized.

Copy link
@adammarblestone-zz

adammarblestone-zz May 25, 2015

Source is just which paper it was first started on. When you start a conversation I think there should be the option for its source to be the currently viewed paper or just for it to have no particular source -- it could mention many papers but have none be the source. Imagine you're at buypizza.com and you start a beagle conversation about something, perhaps linking to various other conversations or something, then it doesn't have a source as such, since you were on a pizza website when you started it. I think you can make a note without it being associated formally with the present document in any way.
Sources in general are less important than links. Links are deliberate and content full. Sources just log where you happened to be when you did something... and a conversation might link to many things.

The exception is when you start from an annotation and build out a conversation from there. Then it very much has a single anchor point, at least at the beginning. So there are these various ways to start a conversation. But in the end most of what matters is the links. Kind of a link-based web on top of the web.

This comment has been minimized.

Copy link
@adammarblestone-zz

adammarblestone-zz May 25, 2015

Anyway there is no need for a "destination" in this context.

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 26, 2015

Author Member

Ok. That option needs to be worked into the UI. See #203 for a place to discuss this.

So, source should be bigger than just a url, then. It should also have metadata about the position, or just position, as well as srcDocumentType which could be either html or pdf.


// Type of permission. (this could be an int but may be )
// type PermType string

// var (
// ReadPerm PermType = iota
// WritePerm
// SharePerm
// ReadPerm PermType = "read"
// WritePerm PermType = "write"
// SharePerm PermType = "share"
// )

// This is read
module.exports.permission = exports.permission = 1
module.exports.permission = exports.permission = 'read'

// Membership is a group of users that belong to an entity,
// with associated permissions. For example, the participants
Expand All @@ -124,3 +186,182 @@ module.exports.permission = exports.permission = 1
// var (
// EntityPermissions map[AccountID][EntityID]PermType
// )

// Membership is a group of users that belong to an entity,
// with associated permissions. For example, the participants
// of a conversation, or the members of a group.
// type Membership map[AccountID]Permission

// // links
// type Link struct {
// Src EntityID
// Dst EntityID
// Type string
// }

// // set of lower level functions.

// // newID creates a new universal and uniformly distributed identifier.
// // we can't just use the hash of the data, because we'd like to link
// // to things even if the data changes.
// //
// // UUID is not secure: it is guessable, so since links may be used
// // in "anyone with the link" type permissions, we'd like an unguessable
// // identifier.
// //
// // So, we'll use hash functions. to preserve upgradeability, we'll use
// // multihash -- https://github.com/jbenet/multihash -- and settle on using
// // sha256-256 (i.e. 256 at 256 bits.
// func newID() string {

// // we first read some cryptographically secure randomness.
// // (node and browsers have ways to do this easily)
// randbuf := rand.Read(256) // read 256 bits of randomness

// // then hash that-- sometimes RNGs are owned.
// // (see https://github.com/jbenet/node-multihashing/)
// hash := multihashing.digest(randbuf, 'sha256')

// // store them as base32 for printability.
// id := base32.encode(hash)
// return id
// }

// // newUser makes and stores a new user account.
// func newUser(name, avatar, email string) (User, error) {
// // validate name
// // validate avatar
// // validate email

// // FIRST, check another user by that email doesn't exist.
// // WARNING: this requires consistency semantics. this is so
// // common that couchdb probably has a way of handling it.
// // (probably some sort of insert-or-query)
// users := db.query({
// Type: "User",
// Emails: []string{email}, // has email
// }) // check if user email in use
// if len(users) > 0 {
// return nil, "email already in use"
// }

// u := User{
// ID: newID(),
// Name: name,
// Avatar: avatar, // have some sane default
// PrimaryEmail: email,
// Emails: []string{email},
// }

// // let's talk about elsewhere how to put to the db, globals are not great,
// // we just do it here for simplicity.
// db.put(u) // save it.
// return u
// }

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 25, 2015

Author Member

@jbenet Want to open up an issue for this?


// // newConversation makes and stores a new conversation item.
// func newConversation(author User, title string) Conversation {
// // validate author
// // validate title

// c := Conversation{
// ID: newID(),
// Title: title,
// Owner: []string{author.ID},
// }

// db.put(c) // save it.
// return c
// }

// // newNote makes a new note and stores it.
// func newNote(author User, conv Conversation, text string) Note {
// // validate author
// // validate conv
// // validate text

// n := Note{
// ID: newID(),
// Text: text,
// Author: author.ID,
// Conversation: conv.ID,
// Participants: Membership{
// author.ID: SharePerm, // put the author as a participant too.

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 25, 2015

Author Member

@jbenet Who would other participants be?

This comment has been minimized.

Copy link
@adammarblestone-zz

adammarblestone-zz May 25, 2015

Participants are just people who are shared on the conversation.

For the purpose of knowing when to notify people of things, it may be helpful to maintain an easy-to-look-up log of who has actually added content to a conversation so far, or has been mentioned in a conversation so far, as opposed to being a purely passive bystander who happens to be shared on that thread.

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 26, 2015

Author Member

I'm still unsure of how you would know what notes are in a conversation, but it ought to be possible to cycle through related comments to find a list of contributors vs. sharers. I don't think there ought to be a difference between the two, though, as that may lead to confusion for users who are used to read-write-share models.

// },
// }
// db.put(n)
// return n
// }

// // StartBlankConversation is what we do when users want to start a conversation
// // from scratch, unassociated with media. that is, it's not coming from a paper,
// // or an anotation, or anything. it's just a conversation from scratch.

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 25, 2015

Author Member

@jbenet When would this happen in the UI?

This comment has been minimized.

Copy link
@adammarblestone-zz

adammarblestone-zz May 25, 2015

If you make a note, from the sidebar directly -- as opposed to by making a new annotation within a paper, or clicking on an existing annotation to add content to it. Many times, you would just have some thoughts, and start writing them down, and only during the course of that process -- or later on -- would you actually make annotations in paper(s) and then link to them in your new conversation. For example, this might be useful for starting trains of thought/discussion that bear on many papers, but are not primarily localized to one single paper or annotation within a paper.

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 26, 2015

Author Member

OK. Got it.

// //
// // we need to:
// // - user u1 provides title, and note text (we'll make a first note, too)
// // - create a new conversation c1 (with title, linked to u1)
// // - save the conversation
// // - create a new note n1 (linked to c1)
// func StartBlankConversation(author User, title string, noteText string) (Conversation) {

// // make new conversation, linked to author and with title.
// c := newConversation(author, title)

// // make a new note, linked to author, linked to conversation, and with noteText.
// n := newNote(author, conversation, noteText)

// return c, n
// }

// // GetConversationPosts returns all the Notes, and MediaObjects related to a given conversation
// // these should be sorted chronologically
// func GetConversationPosts(c Conversation) []*Entity {

This comment has been minimized.

Copy link
@RichardLitt

RichardLitt May 25, 2015

Author Member

@jbenet Shouldn't this just be called a conversation? It's the closest thing semantically to that word - a collection of notes, including the primary note (previously called conversation). Is this the best way to store these notes? The conversation object itself has no way of knowing what notes are inside of it.


// notes := db.query({
// Type: "Note",
// Conversation: c.ID,
// })

// // TODO: expand to include other media

// // TODO: order logically (chronologically)

// return notes
// }

// // GetConverationsForUser queries the database for all conversations that a user is a part of.
// // This includes conversations the user created
// func GetConversationsForUser(user User) ([]Conversation) {

// convs := db.query({
// Type: "Conversation",
// Membership: {
// author.ID: // any Perm.
// }
// })

// return convs
// }

// // PostToConversation adds a note to a conversation
// // TODO: generalize to include other things to link in (papers, etc)
// func PostToConversation(author User, conv Conversation, noteText string) (Note, error) {
// // validate author
// // validate conv
// // validate noteText

// if !permHigher(conv.Participants[User.ID], "write") {
// return nil, "no permission to post"
// }

// // make a new note, linked to author, linked to conversation, and with noteText.
// n := newNote(author, conv, noteText)

// // TODO: notifications to other participants

// return n
// }

// func permHigher(a, b PermType) bool {
// // check "read", "write", "share" matches.
// }

0 comments on commit 05d7356

Please sign in to comment.