Skip to content

What is a project data collection?

Project Data Collections are those data types build upon the IAbstractProject interface found here. This kind of data comes with the advantage of having a lot of existing code allowing it to be easily used in the Kyub frontend. Many objects you may find through the search are project data collections (e.g. models, materials, lasercutter...).

The disadvantage of creating your collection as a project data collection is that you may not need or use all features available to you, leading to more code and database fields than needed for your purpose. Additionally, the type you created has to be plugged in to many locations throughout the website-api and website-frontend to work as expected.

Creating a new project data collection

This section will only go through implementing your new collection on the website-api side, for the frontend please check out the corresponding README in the website-frontend repository.

General Definitions

The following keywords will be used throughout the following walkthrough:

Keyword What does it mean? Example
class name This describes what your collection will represent. All lowercase. Will commonly be used as string in code and later to search instances of your class by type. materialcategory, lasercutter, group
class Name of the mongoose Model you export at the end of your type definition. class name in CamelCase. MaterialCategory, LaserCutter, Group
interface Name of the data model interface you define in your type definition. Starts with I (i) and includes the class name and commonly a reference to its inheritance from the project concept. IMaterialCategory, ILaserCutterProject, IGroup
collection Name of the MongoDB collection created to hold your data. This is always the plural of your class name materialcategories, lasercutters, groups

Coding Process

  1. Define the interface and MongoDB Schema and Model. You do this in the src/models directory (here) in a new file named after the class you intend to export. For examples have a look at other files in that directory. The MaterialProject.ts definition is likely a good starting point as it doesn't include any very complex logic or fields.
  2. Define the controller used to create the API routes for your new collection. This is done in the src/controllers directory (here) in a new file named as classController.ts
    The controller can likely be fully boilerplate code just slightly adapted to your class and class name so you may simply copy and adapt a different one such as the MaterialProjectController.ts.
  3. Create default data for initialization of your object type. You may have noticed that the controller will pass a reference to defaultData/%class name%Projects to its parent during construction. You will need to create this directory and populate it with some default data which is used as a template when creating a new instance of your data class. For the beginning you may just want to copy and rename the groupProjects directory for this.
  4. Hook your interface, model class and controller into various different files as listed in the table below:
File Location Content
src/Server.ts imports import your controller
src/Server.ts Controller map (const controllers = new Map) insert a tuple ["%controller name%", new %controller%()]
src/index.ts Template map (const templateMap =) insert new tuple ["%class name%", process.env.%class name%]
src/index.ts Worker env setup (const env =) insert new mapping %class name%: templateMap.get("%class name%)
src/models/ActivityCache.ts Switch Case (in const getActionvalue =) insert new case delete "%class name" with fallthrough to return -1
src/search/Search.ts imports import your interface and class
src/search/Search.ts SearchResult definition (export type SearchResult) add a tuple (%interface% & { elementType: "%class name%" })
src/search/Search.ts Data Sources creation (this.dataSources =) add a new data source for your class new SearchDataSource(%class%, "%class name")
src/search/SearchDataSource.ts elementType definition (private readonly elementType:) add your class name to the list "%class name%"
src/search/filters/CapabilitiesFilter.ts imports import your class
src/search/filters/CapabilitiesFilter.ts Switch Case (in private _getCapabiliyFromModel(model)) insert a case with the capability to view instances of your classcase %class%: return "%capability%"
src/search/filters/CapabilitiesFilter.ts Switch Case (in private _getCapabiliyFromElementType(elementType: string)) insert a case with the capability to view instances of your class case "%class name%: "%capability%"
src/search/filters/KeywordFilter.ts Switch Case (in private static _getTitleStrings(searchResult: SearchResult)) insert a case case "%class name%:" with a fallthrough to return searchResult.name.split(" ")
src/search/filters/KeywordFilter.ts Switch Case (in private static _buildCorpus(searchResult: SearchResult)) insert a case case "%class name%": with a fallthrough to the block starting with corpus.push(searchResult.name);
src/utils/SearchResultFormatter.ts Switch Case (in public static async format(queryResultObject: SearchResult)) insert case for your class name formatting it to public json as seen in other cases