6.5 KiB
| title |
|---|
| 3.2. Data model |
Penpot Data Model
This is the conceptual data model. The actual representations of those entities slightly differ, depending on the environment (frontend app, backend RPC calls or the SQL database, for example). But the concepts are always the same.
The diagrams use basic UML notation with PlantUML.
Users, teams and projects
@startuml TeamModel
hide members
class Profile class Team class Project class File class StorageObject class CommentThread class Comment class ShareLink
Profile "" -right- "" Team Team --> "" Project Profile "" -- "" Project Project --> "" File Profile "" -- "" File File "" <-- "" File : libraries File --> "" StorageObject : media_objects File --> "" CommentThread : comment_threads CommentThread --> "" Comment File --> "" ShareLink : share_links
@enduml
A Profile holds the personal info of any user of the system. Users belongs to
Teams and may create Projects inside them.
Inside the projects, there are Files. All users of a team may see the projects
and files inside the team. Also, any project and file has at least one user that
is the owner, but may have more relationships with users with other roles.
Files may use other files as shared libraries.
The main content of the file is in the "file data" attribute (see next section). But there are some objects that reside in separate entities:
-
A
StorageObjectrepresents a file in an external storage, that is embedded into a file (currently images and SVG icons, but we may add other media types in the future). -
CommentThreadsandCommentsare the comments that any user may add to a file. -
A
ShareLinkcontains a token, an URL and some permissions to share the file with external users.
File data
@startuml FileModel
hide members
class File class Page class Component class Color class MediaItem class Typography
File --> "" Page : pages (File, Page) .. PagesList
File --> "" Component : components (File, Component) .. ComponentsList
File --> "" Color : colors (File, Color) .. ColorsList
File --> "" MediaItem : colors (File, MediaItem) .. MediaItemsList
File --> "" Typography : colors (File, Typography) .. TypographiesList
@enduml
The data attribute contains the Pages and the library assets in the file
(Components, MediaItems, Colors and Typographies).
The lists of pages and assets are modelled also as entities because they have a lot of functions and business logic.
Pages and components
@startuml PageModel
hide members
class Container class Page class Component class Shape
Container <|-left- Page Container <|-right- Component
Container --> "" Shape : objects (Container, Shape) .. ShapeTree
Shape <-- Shape : parent
@enduml
Both Pages and Components contains a tree of shapes, and share many
functions and logic. So, we have modelled a Container entity, that is an
abstraction that represents both a page or a component, to use it whenever we
have code that fits the two.
A ShapeTree represents a set of shapes that are hierarchically related: the top
frame contains top-level shapes (frames and other shapes). Frames and groups may
contain any non frame shape.
Shapes
@startuml ShapeModel
hide members
class Shape class Selrect class Transform class Constraints class Interactions class Fill class Stroke class Shadow class Blur class Font class Content class Exports
Shape o--> Selrect Shape o--> Transform Shape o--> Constraints Shape o--> Interactions Shape o--> Fill Shape o--> Stroke Shape o--> Shadow Shape o--> Blur Shape o--> Font Shape o--> Content Shape o--> Exports
Shape <-- Shape : parent
@enduml
A Shape is the most important entity of the model. Represents one of the
layers of our design, and it
corresponds with one SVG node, augmented with Penpot special features.
We have code to render a Shape into a SVG tag, with more or less additions
depending on the environment (editable in the workspace, interactive in the
viewer, minimal in the shape exporter or the handoff, or with metadata in the
file export).
Also have code that imports any SVG file and convert elements back into shapes. If it's a SVG exported by Penpot, it reads the metadata to reconstruct the shapes exactly as they were. If not, it infers the atributes with a best effort approach.
In addition to the identifier ones (the id, the name and the type of element), a shape has a lot of attributes. We tend to group them in related clusters. Those are the main ones:
Selrectand other geometric attributes (x, y, width, height...) define the position in the diagram and the bounding box.Transformis a 2D transformation matrix to rotate or stretch the shape.Constraintsexplains how the shape changes when the container shape resizes (kind of "responsive" behavior).Interactionsdescribe the interactive behavior when the shape is displayed in the viewer.Fillcontains the shape fill color and options.Strokecontains the shape stroke color and options.Shadowcontains the shape shadow options.Blurcontains the shape blur options.Fontcontains the font options for a shape of type text.Contentcontains the text blocks for a shape of type text.Exportsare the defined export settings for the shape.
Also a shape contains a reference to its containing shape (parent) and of all the children.