Skip to content

Learning Items

Stian Håklev edited this page May 10, 2018 · 7 revisions

liTypes

liTypes are the pieces of code that enable you to create, view, and edit different kinds of content, like text, images, spreadsheets, etc. They should provide the following properties:

export type learningItemT = {
  name: string,
  id: string,
  dataStructure?: any,
  Editor?: React.ComponentType<any>,
  Creator?: React.ComponentType<any>,
  ThumbViewer?: React.ComponentType<any>,
  Viewer?: React.ComponentType<any>
};

Every liType must define either a Viewer or a ThumbViewer, and can define both. If a user asks for a thumbnail view, and there is a ThumbView, it will be rendered, if not, an icon placeholder will be used. For the full view, either the Viewer or the ThumbViewer will be used. Thus, if you have only one view that can work both in thumbnail and regular, it should be defined as a ThumbView.

If the liType has a Creator, this component will be used to create new LIs, otherwise the liType must supply a dataStructure. When creating a new item, a new LI will be created with the dataStructure, and opened in the Editor component, with the 'draft' set to true (to hide from dashboards etc). Once the user clicks Submit, the draft status is withdrawn, and the onCreate callback is called. This means that all edits that happen also during creation (before posting) are recorded, and can also lead to a large amount of unfinished LIs left floating around.

Which liTypes are available is defined in imports/LearningItems/learningItemTypes.

Learning Items

Learning Items are the specific pieces of content authored or displayed with liTypes. They are data objects that have a an id, an li-type, and a payload which is opaque to the system, but understood by the corresponding liType code. They also have a set of metadata that are automatically attached upon creation, including:

createdAt: Date,
sessionId: string,
createdByUser: string // (userid),
createdByInstance: { [string]: string }, // (for example { group: '1' } )
createdInActivity: string

Currently these metadata are not available to the liType code or the activity runners, but will only be used in dashboards/data exports etc (can be discussed).

They are stored in the li collection in ShareDB.

Creating Learning Items

ActivityRunners have access to the dataFn.LearningItem component. They can display it either requesting a specific li-type, or letting the user choose, and they can choose to receive a callback with the new li-ID, or to automatically insert an object into the reactive data.

This shows a plus-button, which displays a list of available liTypes when clicked:

<dataFn.LearningItem type='create' onCreate={id => ...} />

This directly shows either the Creator component of the liType specified, or creates a new LI in draft mode, and opens the Editor component of the liType:

<dataFn.LearningItem type='create' liType='li-idea' onCreate={id => ...} />

This asks the engine to automatically insert one or more (Creator components can return multiple LIs, for example when dragging and dropping multiple files) into the ActivityRunner's reactive data, as a standard object with the metadata specified:

<dataFn.LearningItem type='create' liType='li-idea' meta={score: 0} autoInsert />

It is also possible to directly call the dataFn.createLearningItem(liType: string, item?: Object, meta? Object) function, which creates a new learning item with the payload specified in item, and the optional meta data. This is not usually recommended, since ActivityRunner's should not know about the internal data structures of liTypes.

Displaying Learning Items

To display LIs, we also use dataFn.LearningItem. We can choose between displaying an LI in the normal view, or in thumbView (thumbnail). Some liTypes only provide small versions, and this will be shown in both modes. Some liTypes only provide full views, and will have an icon in the thumbView. We can also choose to let the engine handle zooming for us, by providing the clickZoomable property - in this mode, any thumbnail that also has a full view is clickable, and will show a zoomed in view in a modal window.

The simple way of rendering is to simple call the component like this (type could also have been thumbView:

<LearningItem type='view' id={li.id} clickZoomable />

However, if we want access to some information about the liType and whether it supports editing, zooming, etc, we can provide a render prop, like so:

<LearningItem
  type="view"
  id={li.id}
  render={({ zoomable, editable, liType, children }) => (
    <div>
      <h1>Item</h1>
      {children}
    </div>
  )}
/>;

The render function will be called with the props listed above, and the content of the rendered learning item in children.

Editing Learning Items

Not all Learning Items support editing, and you should not try to call edit on an LI that does not support it. For Learning Items that do support it, you can supply type='edit', and the LI will be change to let the user synchronously modify it. There is no built-in support for completing editing, so you should supply a way for the user to signal that they are done, and then switch back to 'view'. Since all editing is synchronous, there is no need to "save" (there is also no way to abandon or undo editing).

Learning Items and activityData / operators

There is no change to how activities' activityData works, and activities can continue without worrying at all about Learning Items, or include LIs, and store their references anyway it wants in the reactiveData. Note that reactiveData is scoped to a single instance, whereas a given li-ID is global, so if an operator sends the same li-ID to two different groups, the result of one of them deleting the li, would only mean removing the reference to it from that instance's reactiveData, however any editing of the LI would be seen by all the different instances that are displaying that LI. (On can of course ask an operator to make a copy of an LI, rather than forwarding its reference).

Even though activities can manage their reactiveData any way they want, we suggest following a standard approach which will make interoperability easier: an object mapping IDs to objects that contain a reference to the li, as well as any activity-specific meta data. For ac-brainstorm for example, this looks like so:

{
  ckdfisjf988898: {
    id: 'ckdfisjf988898',
	li: 'cda43jkjfdfsdf',
    liType: 'li-idea',
    payload: { title: 'Hi', content: 'Hello' },
    createdAt: '2018-05-10T12:02:07.525Z',
    students: {},
    score: 0
  },
  lskffd049034094: {
    id: 'lskffd049034094',
	li: 'cda4sdf89sdfzz',
    liType: 'li-idea',
    payload: { title: 'Uber', content: 'AirBnB for taxis' },
    createdAt: '2018-05-10T12:02:07.525Z',
    students: {},
    score: 4
  }
}

It's important to distinguish between the id (both the object key, and the id property), which refers to this specific instance, and the li, which refers to the learning item ID. Thus, you could have the same LI shared between different instances, but with different metadata (one group might vote it up, another will vote it down).

In the future, ActivityPackages will supply a outputDefinition listing the types and descriptions of their added metadata, and operators will be able to operate in a generic fashion on these metadata items.