diff --git a/metrics/web/docs/features/storybook/01_metrics_storybook_design.md b/metrics/web/docs/features/storybook/01_metrics_storybook_design.md index de0a67896..a587461a0 100644 --- a/metrics/web/docs/features/storybook/01_metrics_storybook_design.md +++ b/metrics/web/docs/features/storybook/01_metrics_storybook_design.md @@ -18,6 +18,25 @@ The Storybook is a tool for UI development that allows building UI components in - [Decision](#decision) - [Prototyping](#prototyping) - [System modeling](#system-modeling) +- [**Design**](#design) + - [Architecture](#architecture) + - [Metrics Widgets package](#metrics-widgets-package) + - [Metrics Storybook package](#metrics-storybook-package) + - [User Interface](#user-interface) + - [Program](#program) + - [Package Structure](#package-structure) + - [widgets](#widgets) + - [Storybook](#storybook) + - [InjectionContainer](#injectioncontainer) + - [UI widgets](#ui-widgets) + - [Sidebar](#sidebar) + - [Preview](#preview) + - [Editing Panel](#editing-panel) + - [Chapter Control Field](#chapter-control-field) + - [state](#state) + - [mappers](#mappers) + - [stories](#stories) + - [How to add new widgets to the Metrics Storybook](#how-to-add-new-widgets-to-the-metrics-storybook) # Analysis > Describe a general analysis approach. @@ -220,4 +239,487 @@ The interaction of the `Metrics Widgets` and `Metrics Storybook`/`Metrics Web Ap The following diagram shows the described interaction: -![Metrics Storybook Web Relation Diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank-dashboard/master/metrics/web/docs/features/storybook/diagrams/metrics_storybook_web_relation_diagram.puml) +![Metrics Storybook Web Relation Diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank-dashboard/master/metrics/web/docs/features/storybook/diagrams/web_relation_diagram.puml) + +# Design + +The section provides a high-level structure of the feature, describes the UI for end-users, and shows class-level implementation details. + +### Architecture +> Fundamental structures of the feature and context (diagram). + +We can describe the structure of the feature through the following parts: + +- [Metrics Widgets package](#metrics-widgets-package) +- [Metrics Storybook package](#metrics-storybook-package) + +#### Metrics Widgets package + +Before talking about the [Metrics Storybook](#metrics-storybook), we need to extract a list of specific Metrics widgets from the `Metrics Web Application` into a separate package, to share them across the web application and the storybook. + +The following table lists specific widgets we need to extract: + +| | | | | +| :---: | :---: | :---: | :---: | +| ***BuildStatusView*** | ***Buttons*** | ***ColoredBar*** | ***Dropdown*** | +| ***GraphIndicator*** | ***InProgressAnimatedBar*** | ***MetricsCard*** | ***MetricsCheckbox*** | +| ***MetricsInputPlaceholder*** | ***MetricsTextFormField*** | ***MetricsThemeImage*** | ***PageTitle*** | +| ***TextPlaceholder*** | ***Toasts*** | ***Toggle*** | ***TooltipIcon*** | +| ***TooltipPopup*** | ***TooltipTitle*** | ***UserMenuButton*** | ***ValueNetworkImage*** | + +As these widgets use the `Metrics theme` to determine their appearance, the package should contain all models/configs/widgets that belong to the theme as well. + +The following diagram describes the structure of the `Metrics Widgets` package: + +![Metrics Widgets Structure Diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank-dashboard/metrics_storybook_design/metrics/web/docs/features/storybook/diagrams/widgets_structure_diagram.puml) + +#### Metrics Storybook package + +The `Metrics Storybook` is a package that responsible for showcasing widgets. + +In general, it consists of three main components: + +| Component | Description| +| :---: | :---: | +| **Chapter** | A class, that represents a specific widget we want to display within the storybook. It shows a state of a UI component. Each `Story` can contain multiple `Chapter`s (e.g., `Buttons` story contains `PositiveButton` chapter, `NegativeButton` chapter, etc.) | +| **Chapter Controls** | A class that holds a collection of properties that may be used to change the widget's appearance (e.g., `backgroundColor`, `label`). | +| **Story** | A class, that groups together a list of chapters (i.e., it's a common class for similar types of widgets - buttons, inputs, ect.). The `Storybook` can contain multiple `Stories`. | + +Consider the following diagram, that describes relations between the described parts: + +![Metrics Storybook Architecture Components Diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank-dashboard/metrics_storybook_design/metrics/web/docs/features/storybook/diagrams/architecture_components_diagram.puml) + +At this time, we want to show only Metrics-specific widgets within the `Metrics Storybook`. + +### User Interface +> How users will interact with the feature (API, CLI, Graphical interface, etc.). + +Metrics Storybook is a separate Flutter web project. Its UI consists of the following parts: + +- **Sidebar** - a left panel with the Metrics logo and a list of Metrics-specific widgets. + +- **Preview** - a zone in the middle of the screen, that displays an actual widget of the selected chapter. + +- **Editing Panel** - a list of inputs, that allows changing widget's appearance. + +- **Toggle theme** - a button that changes the theme between the dark and light variants. + +The following diagram shows all the described components together: + +![Metrics Storybook User Interface Diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank-dashboard/metrics_storybook_design/metrics/web/docs/features/storybook/diagrams/user_interface_diagram.puml) + +So with that, end-users will use the sidebar to choose a widget. Also, it will be able to change the chosen widget's appearance using the list of inputs in the editing panel and toggle the theme using the toggle theme button. The resulting widget will be displayed in the preview. + +### Program +> Detailed solution description to class/method level. + +Once we've chosen the desired implementation approach, let's review the packages we should create in a bit more detail. + +#### Metrics Widgets package + +According to the [Metrics widgets package](#metrics-widgets-package) architecture section, we can provide a structure of the package and an information about a list of classes/widgets that we've extracted from the `Metrics Web Applicaion`. + +#### Package Structure + +Consider the following structure of the `Metrics Widgets` package: + +> * `lib/src/` +> * `base/` +> * `base_popup.dart` +> * `circle_graph_indicator.dart` +> * `...` +> * `theme/` +> * `config/` +> * `dimensions_config.dart` +> * `metrics_colors.dart` +> * `text_field_config.dart` +> * `text_style_config.dart` +> * `model/` +> * `metrics_color/` +> * `metrics_color.dart` +> * `metrics_text/style/` +> * `metrics_text_style.dart` +> * `dark_metrics_theme_data.dart` +> * `light_metrics_theme_data.dart` +> * `metrics_theme_data.dart` +> * `metrics_widget_theme_data.dart` +> * `state/` +> * `theme_notifier.dart` +> * `attention_level_theme_data.dart` +> * `metrics_theme.dart` +> * `button/` +> * `theme/` +> * `attention_level/` +> * `metrics_button_attention_level.dart` +> * `style/` +> * `metrics_button_style.dart` +> * `theme_data/` +> * `metrics_button_theme_data.dart` +> * `widgets/` +> * `metrics_button.dart` +> * `metrics_inactive_button.dart` +> * `metrics_negative_button.dart` +> * `metrics_neutral_button.dart` +> * `metrics_positive_button.dart` +> * `colored_bar/` +> * `strategy/` +> * `metrics_colored_bar_appearance_strategy.dart` +> * `theme/` +> * `...` +> * `widgets/` +> * `...` +> * `...` +> * `metrics_widgets.dart` + + +Widgets under the `base` folder are widgets that are responsible for only displaying the given data. These widgets should be highly-configurable and usable out of the Metrics Web Application context. + +The `theme` folder contains models/config/widgets that provides and manipulates the `Metrics theme`. To get more information about the theme consider the following [link](https://github.com/Flank/flank-dashboard/blob/master/metrics/web/docs/03_widget_structure_organization.md#metrics-theme-guidelines). + +Other folders, such as `button/colored_bar` contains widgets/classes for a concrete Metrics widgets types. They are used in the Metrics Web Application context. To get more information about Metrics widgets consider the following [link](https://github.com/Flank/flank-dashboard/blob/master/metrics/web/docs/03_widget_structure_organization.md#metrics-widget-creation). + +The `metrics_widgets` file includes exports of all `Metrics widgets` required in the `Metrics Storybook` and `Metrics Web Application`. + +#### Metrics Storybook package + +Once we've defined a high-level architecture of the `Metrics Storybook` and its visual view, we can provide a package structure of the storybook and a list of classes/widgets that we should implement for this feature. + +#### Package Structure + +Consider the following structure of the `Metrics Storybook`: + +> * `lib/` +> * `page/` +> * `storybook.dart` +> * `widgets/` +> * `sidebar/` +> * `preview/` +> * `editing_panel/` +> * `control_fields/` +> * `chapter_control_field.dart` +> * `chapter_control_text_field.dart` +> * `chapter_control_checkbox_field.dart` +> * `chapter_control_color_field.dart` +> * `chapter_control_slider_field.dart` +> * `injection_container.dart` +> * `state/` +> * `stories_notifier.dart` +> * `chapters_notifier.dart` +> * `mappers` +> * `chapter_control_mapper.dart` +> * `stories` +> * `buttons/` +> * `chapters/` +> * `inactive_button_chapter.dart` +> * `controls/` +> * `buttons_chapter_control_name.dart` +> * `inactive_button_chapter_controls.dart` +> * `buttons_story.dart` +> * `...` +> * `chapter_controls.dart` +> * `chapter_control.dart` +> * `chapter.dart` +> * `story.dart` + +##### *Storybook* + +`Storybook` - is a root widget. The main purpose of the widget is to bootstrap an application with a list of `stories`. + +Consider the following example: + +```dart +main.dart + +void main() { + final storybook = Storybook( + stories: [ + ButtonsStory(), + AnotherStory(), + ], + ); + + runApp(storybook); +} +``` + +Then, the `Storybook` passes the given stories to the `InjectionContainer` as it responsible for creating the application state: + +```dart +class Storybook extends StatelessWidget { + final List stories; + + const Storybook({Key key, this.stories}) : super(key: key); + + @override + Widget build(BuildContext context) { + return InjectionContainer( + stories: stories, + child: ... + ); + } +} +``` + +##### ***widgets*** + +The folder contains a list of widgets, that bootstraps the application, creates `ChangeNotifier`s and responsible for the UI part of the storybook. + +###### *InjectionContainer* + +As we want to use the [provider](https://pub.dev/packages/provider) package to manage the application state, we should create the `Injection Container` that is responsible for registering all needed `ChangeNotifier`s, so in fact - for creating the [state](#state). + +###### *UI widgets* + +Once we've defined classes that set up and prepare the list of [stories](#story) with their [chapters](#chapter), we can describe a list of widgets, that represents the UI part of the storybook: + +- [Sidebar](#sidebar) +- [Preview](#preview) +- [Editing Panel](#editing-panel) + +Let's take a closer look at them: + +###### *Sidebar* + +The `Sidebar` widget is responsible for building a left panel with a list of widgets, we want to display in the storybook. It uses the `StoriesNotifier` to get a list of `stories` with related `chapters`. + +###### *Preview* + +The main purpose of the `Preview` is to display a widget that we've selected in the [Sidebar](#sidebar) using the data from the `ChaptersNotifier`. + +###### *Editing Panel* + +The `EditingPanel` widget uses a [ChapterControlsMapper](#mappers) to provide a list of [controls](#chapter-control-field) to change the widgets' appearance. + +###### *Chapter Control Field* + +The `ChapterControlField` is a base widget that is a template for the more specific fields, such as: + +- `ChapterControlTextField` - displays a basic [text field](https://api.flutter.dev/flutter/material/TextField-class.html) to change the chapter's string property value. +- `ChapterControlCheckboxField` - displays a [checkbox](https://api.flutter.dev/flutter/material/Checkbox-class.html) to toggle the chapter's bool property value. +- `ChapterControlColorField` - displays a [color picker](https://pub.dev/packages/flutter_colorpicker) to change the chapter's property that accepts different color. +- `ChapterControlSliderField` - displays a [slider](https://api.flutter.dev/flutter/material/Slider-class.html) to change the chapter's property between the range of values. + +The purpose of these widgets is to provide the ability to edit a currently selected chapter (widget) appearance. + +##### ***state*** + +There are a few `ChangeNotifier`s, that is making up the storybook's global state: + +- `StoriesNotifier` - holds a list of stories and provides them to the application. + +- `ChaptersNotifier` - holds a [chapter](#chapter)'s data to show it in the [preview](#preview). + +##### ***mappers*** + +The `mappers` folder contains the `ChapterControlMapper` class, which maps the given `ChapterControl` into the corresponding [control widget](#chapter-control-field). + +##### ***stories*** + +This folder contains interfaces for stories and chapters, as well as chapter controls. There is, also, a list of stories, that represents specific `Metrics widgets`. + +The `Story` is a class that groups together a list of `Chapter`s. The main purpose of the stories is to visually separate chapters (i.e., widgets) in the [sidebar](#sidebar). + +The `Chapter` represents a specific widget we want to show in the storybook. The class contains a name of the specific chapter and a [ChapterControls](#chapter-controls). There is, also, the `build` method, which is responsible for building the widget, represented by the `Chapter` and applying the `ChapterControls`. + +The `ChapterControls` is an abstract class that contains controls property, that UI widgets can use to build the [editing panel](#editing-panel) for the widget. The `controls` is an `unmodifiable Map` with the name of the control as a key, and a `ChapterControl` class as a value. + +The is, also, the `getControlValueByName()` to get the `ChapterControl` value by the related name. + +The `ChapterControl` is deeply related to the `ChapterControls` and is used to build a single editing field for the storybook widget. + +It is a [generic](https://dart.dev/guides/language/language-tour#generics) class, and its actual type is used to build a corresponding type of input. + +For example, `ChapterControl` on the UI converts into the `TextField`, `ChapterControl` into `CheckboxField` and so on. The more information about these fields in the [Chapter Control Field section](#chapter-control-field). + +There `stories`, also, contains a list of folders, that represents specific stories according to the `Metrics widgets`(e.g., buttons, toasts). + +Consider the following diagram, that describes relations between `stories` classes: + +![Metrics Storybook stories class diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank-dashboard/metrics_storybook_design/metrics/web/docs/features/storybook/diagrams/stories_class_diagram.puml) + +The next diagram shows the relations between all described classes: + +![Metrics Storybook class diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank-dashboard/metrics_storybook_design/metrics/web/docs/features/storybook/diagrams/class_diagram.puml) + +Consider the following sequence diagram, which shows the general flow of displaying widgets and changing their appearance in the storybook application: + +![Metrics Storybook sequence diagram](http://www.plantuml.com/plantuml/proxy?cache=no&fmt=svg&src=https://raw.githubusercontent.com/Flank/flank-dashboard/metrics_storybook_design/metrics/web/docs/features/storybook/diagrams/sequence_diagram.puml) + +#### ***How to add new widgets to the Metrics Storybook*** + +Let's imagine, you want to add an `inactive button widget` to the storybook. + +So, you should follow the next steps: + +1. Create a new folder in the `stories` and name it according to the type of a new widget (e.g., buttons). + +For example, `lib/stories/buttons`. + +2. Create a new file, named `buttons_story.dart` in the `buttons` folder, that will represent a new story. + +3. In the `buttons_story.dart` file you should create a class, let's say we named it `ButtonsStory` that should implement the base `Story` interface. Give your story a name (it is the name of the group in the sidebar in the storybook UI). + +```dart +class ButtonsStory implements Story { + @override + String get name => 'Buttons'; + + @override + List get chapters => []; +} +``` + +4. Create a new folder in the `buttons` folder, name it `chapters`, and add a file with the name `inactive_button_chapter.dart`. + +In this file, you should create a class, that extends the `Chapter`. + +```dart +class InactiveButtonChapter extends Chapter { + @override + String get name => 'Inactive Button'; + + @override + Map get controls => null; + + @override + Widget build() { + return InactiveButton(label: 'label'); + } +} +``` + +The `name` property holds the name you want to display in the sidebar of the storybook. + +The `build` method should return the widget, you want to add to the storybook, so in this case - `InactiveButton`. + +_**Note**: If you want to see the widget within the different appearance state, you can perform some extra steps:_ + +1. Create the `ButtonsChapterControlName`, which is an `Enum` class and holds widget's properties' names, you want to control. + +For this purpose, create a new file `buttons_chapter_control_name.dart` in the `controls` folder (if it does not exist, create it under the `buttons` one). As we want to change the widget's *label*, we should add the `static const label` value to the class: + +```dart +class ButtonsChapterControlName extends Enum { + static const label = ButtonsChapterControlName._('label'); + + const ButtonsChapterControlName._(String value) : super(value); + + static const Set values = { + label, + }; + + @override + String toString() => value; +} +``` + +2. Next, create the `InactiveButtonChapterControls` class, that contains controls for the concrete `InactiveButton` widget. + +So, in the `controls` folder add a file with the name, let's say `inactive_button_chapter_controls.dart`. In this file you should create a class, that extends the `ChapterControls`: + +```dart +class InactiveButtonChapterControls extends ChapterControls { + static Map _controls = { + ButtonsChapterControlName.label.value: ChapterControl( + ButtonsChapterControlName.label.value, + 'default value', + ) + }; + + InactiveButtonChapterControls() : super(_controls); + + @override + Map get controls => _controls; +} +``` + +3. Now, you can concentrate on the `InactiveButtonChapter` and use the created above classes: + +```dart +class InactiveButtonChapter implements Chapter { + final ChapterControls _chapterControls = InactiveButtonChapterControls(); + + @override + String get name => 'Inactive Button'; + + @override + Map get controls => _chapterControls.controls; + + @override + Widget build() { + final label = _chapterControls.getControlValue( + ButtonsChapterControlName.label.value, + ) as String; + + return InactiveButton(label: label); + } +} +``` + +Using the `getControlValue()` method provided by the `ChapterControls` we are getting a value of the widget's control by its name. + +5. With that you can move on to add the created `Chapter` to the `ButtonsStory`. + +```dart +class ButtonsStory implements Story { + @override + String get name => 'Buttons'; + + @override + List get chapters => [ + InactiveButtonChapter() + ]; +} +``` + +5. Go to the `main.dart` file and add the `ButtonsStory` to the `stories` list of the `Storybook` widget: + +```dart +void main() { + final storybook = Storybook( + stories: [ + ButtonsStory(), + ], + ); + + runApp(storybook); +} +``` + +As a result, you will see an ***'Inactive Button'*** widget within the ***'Buttons'*** group in the sidebar of the storybook application. + + + + +A `Storybook` in general means a collection of a stories. So first of all we should understand `what is a story` in our case? + +A `Story` is an abstract class, that represents a collection of similar by type widgets. Each story should contain its name and a list of widgets, that are parts of the story(we named it `Chapter`s). + +Consider the following example: + +```dart +abstract class Story { + StoryName get name; + + List get chapters; +} +``` + +The `StoryName` is an `Enum`, that represents a concrete name of the widgets group(i.e. story). + +As we've described above, a story usually consist of multiple chapters. The `Chapter` is an abstract class, that represents a concrete widget, we want to display in the storybook. + +Consider the following example: + +```dart +abstract class Chapter { + StoryName get storyName; + + ChapterName get name; + + ChapterControls get controls; + + Widget toView(BaseViewModel viewModel); +} + +``` diff --git a/metrics/web/docs/features/storybook/diagrams/architecture_components_diagram.puml b/metrics/web/docs/features/storybook/diagrams/architecture_components_diagram.puml new file mode 100644 index 000000000..8b311ce62 --- /dev/null +++ b/metrics/web/docs/features/storybook/diagrams/architecture_components_diagram.puml @@ -0,0 +1,18 @@ +@startuml architecture_components_diagram + +skinparam componentStyle rectangle + +component "Metrics Storybook" as MS + +component "Story" as Story +component "Chapter" as Chapter + +component "Chapter Controls" as ChapterControls +component "Chapter Control (e.g., text input)" as ChapterControl + +MS "1" -down-o "1..*" Story +Story "1" -down-o "1..*" Chapter +Chapter "1" -right-o "1" ChapterControls +ChapterControls "1" -down-o "0..*" ChapterControl + +@enduml diff --git a/metrics/web/docs/features/storybook/diagrams/class_diagram.puml b/metrics/web/docs/features/storybook/diagrams/class_diagram.puml new file mode 100644 index 000000000..d97b650fe --- /dev/null +++ b/metrics/web/docs/features/storybook/diagrams/class_diagram.puml @@ -0,0 +1,188 @@ +@startuml class_diagram + +package widgets/theme { + class ThemeNotifier { + - _selectedTheme : ThemeType + + isDark : bool + + selectedTheme : ThemeType + + + changeTheme(ThemeType themeType) : void + + toggleTheme() : void + + setTheme(Brightness brightness) : void + - _isBrightnessDark(Brightness brightness) : bool + } +} + +package metrics/core/lib/src/domain/entities { + abstract class Enum { + + value : T + } +} + +package storybook { + package state { + class ChaptersNotifier { + + currentChapter : Chapter + + + selectChapter(Chapter chapter) : void + + refreshChapter() : void + } + + class StoriesNotifier { + + stories : List + } + } + + package stories { + package buttons { + package chapters { + class InactiveButtonChapter { + - _chapterControls : InactiveButtonChapterControls + + name : String + + controls : Map + + + build() : Widget + } + } + package controls { + class InactiveButtonChapterControls { + - {static} _controls : Map + + + controls : Map + } + class ButtonsChapterControlName { + + {static} const label : ButtonsChapterControlName + + {static} const values : Set + + toString() : String + } + } + class ButtonsStory { + + name : String + + chapters : List + } + } + + abstract class Story { + + name : String + + chapters : List + } + + abstract class Chapter { + + name : String + + controls : ChapterControls + + + build() : Widget + } + + abstract class ChapterControls { + - _controls : Map + + controls : Map + + + getControlValue(String name) : dynamic + } + + class ChapterControl { + + name : String + + value : T + } + } + + package mappers { + class ChapterControlMapper { + + map(ChapterControl control) : Widget + } + } + + package widgets { + class Storybook { + + stories : List + } + + class InjectionContainer { + + stories : List + } + + class Sidebar { + + build(BuildContext context) : Widget + } + + class Preview { + + build(BuildContext context) : Widget + } + + class EditingPanel { + - _widgets : List + + + build(BuildContext context) : Widget + } + + package control_fields { + class ChapterControlField { + + label : String + + child : Widget + } + + class ChapterControlTextField { + + property : ChapterControl + + + build(BuildContext context) : Widget + } + + class ChapterControlCheckboxField { + + property : ChapterControl + + + build(BuildContext context) : Widget + } + + class ChapterControlColorField { + + property : ChapterControl + + + build(BuildContext context) : Widget + } + + class ChapterControlSliderField { + + property : ChapterControl + + + build(BuildContext context) : Widget + } + } + } +} + +Storybook -up-> InjectionContainer : creates and provides a list of stories +Storybook -up-> EditingPanel : creates +Storybook -up-> Sidebar : creates +Storybook -up-> Preview : creates +InjectionContainer -up-> StoriesNotifier : creates +InjectionContainer -up-> ChaptersNotifier : creates +InjectionContainer -up-> ThemeNotifier : creates +Storybook -down-> ButtonsStory : uses +Story -right-> Chapter : uses +Chapter -right-> ChapterControls : creates +ChapterControls -> ChapterControl : creates + +ButtonsStory -down-|> Story : extends +ButtonsStory -> InactiveButtonChapter : creates +InactiveButtonChapter -down-|> Chapter : extends +InactiveButtonChapterControls -down-|> ChapterControls: extends +InactiveButtonChapter -right-> InactiveButtonChapterControls : creates +InactiveButtonChapterControls -right-> ButtonsChapterControlName : uses +ButtonsChapterControlName -right-|> Enum : extends + +EditingPanel -up-> ChaptersNotifier : uses +Sidebar -up-> StoriesNotifier : uses +Preview -up-> ChaptersNotifier : uses +EditingPanel -up-> ChapterControlMapper : uses +ChapterControlField -> ChaptersNotifier : uses + +ChapterControlMapper -> ChapterControlTextField : uses +ChapterControlMapper -> ChapterControlCheckboxField : uses +ChapterControlMapper -> ChapterControlColorField : uses +ChapterControlMapper -> ChapterControlSliderField : uses + +ChapterControlTextField -down-> ChapterControlField : uses +ChapterControlCheckboxField -down-> ChapterControlField : uses +ChapterControlColorField -down-> ChapterControlField : uses +ChapterControlSliderField -down-> ChapterControlField : uses + +@enduml diff --git a/metrics/web/docs/features/storybook/diagrams/metrics_widgets_structure_diagram.puml b/metrics/web/docs/features/storybook/diagrams/metrics_widgets_structure_diagram.puml new file mode 100644 index 000000000..5efd564d4 --- /dev/null +++ b/metrics/web/docs/features/storybook/diagrams/metrics_widgets_structure_diagram.puml @@ -0,0 +1,25 @@ +@startuml metrics_widgets_structure_diagram + +package "widgets" { + + package "theme" { + [Metrics Theme] + } + + package "base" { + [Base Widgets] + } + + package "button" { + [Metrics Button] --> [Base Widgets] : uses + [Metrics Button] --> [Metrics Theme] : uses + } + + package "toast" { + [Metrics Toast] -up-> [Base Widgets] : uses + [Metrics Toast] -up-> [Metrics Theme] : uses + } + +} + +@enduml diff --git a/metrics/web/docs/features/storybook/diagrams/sequence_diagram.puml b/metrics/web/docs/features/storybook/diagrams/sequence_diagram.puml new file mode 100644 index 000000000..efe43b38b --- /dev/null +++ b/metrics/web/docs/features/storybook/diagrams/sequence_diagram.puml @@ -0,0 +1,56 @@ +@startuml sequence_diagram + +skinparam ParticipantPadding 20 +skinparam BoxPadding 10 + +actor Bob + +box "Metrics Storybook" + participant UI + participant Storybook << (W,#ADD1B2) >> + participant InjectionContainer << (C,#ADD1B2) >> + participant StoriesNotifier << (C,#ADD1B2) >> + participant ChaptersNotifier << (C,#ADD1B2) >> + participant ThemeNotifier << (C,#ADD1B2) >> + participant Sidebar << (W,#ADD1B2) >> + participant Preview << (W,#ADD1B2) >> + participant "Editing Panel" as EP << (W,#ADD1B2) >> + participant ChapterControls << (W,#ADD1B2) >> +end box + +Bob -> UI : enters the application +UI -> Storybook : creates stories (with chapters) +Storybook -> InjectionContainer : provides stories +InjectionContainer -> StoriesNotifier : registers and provides stories +InjectionContainer -> ChaptersNotifier : registers +StoriesNotifier -> Sidebar : provides stories +Sidebar -> UI : displays a list of stories and chapters +UI -> Bob : shows a UI with a list of storybook widgets + +alt Bob clicks on the chapter (widget) in the Sidebar: + Bob -> UI : clicks on the menu item in the sidebar + UI -> ChaptersNotifier : selects a chapter + ChaptersNotifier -> Preview : provides a chapter + ChaptersNotifier -> EP : provides a chapter + EP -> ChapterControls : gets a chapter's controls + Preview -> UI : displays a selected chapter + EP -> UI : displays list of controls to change a chapter's appearance + UI -> Bob : shows a UI with the selected widget\n and a list of controls to change a chapter's appearance +end + +alt Bob changes a chapter's appearance using control: + Bob -> EP : changes a chapter's control value + EP -> ChaptersNotifier : refreshes a chapter + ChaptersNotifier -> Preview : notifies about changing chapter's appearance + Preview -> UI : displays changed chapter + UI -> Bob : shows a UI with the changed widget +end + +alt Bob clicks the toggle theme button: + Bob -> UI : clicks the toggle theme button + UI -> ThemeNotifier : toggle theme + ThemeNotifier -> UI : notifies about theme changes + UI -> Bob : shows UI in the toggled theme +end + +@enduml diff --git a/metrics/web/docs/features/storybook/diagrams/stories_class_diagram.puml b/metrics/web/docs/features/storybook/diagrams/stories_class_diagram.puml new file mode 100644 index 000000000..9188f7048 --- /dev/null +++ b/metrics/web/docs/features/storybook/diagrams/stories_class_diagram.puml @@ -0,0 +1,35 @@ +@startuml stories_class_diagram + +package storybook { + package stories { + abstract class Story { + + name : String + + chapters : List + } + + abstract class Chapter { + + name : String + + controls : ChapterControls + + + build() : Widget + } + + abstract class ChapterControls { + - _controls : Map + + controls : Map + + + getControlValue(String name) : dynamic + } + + class ChapterControl { + + name : String + + value : T + } + } +} + +Story -right-> Chapter : uses +Chapter -right-> ChapterControls : creates +ChapterControls -> ChapterControl : creates + +@enduml diff --git a/metrics/web/docs/features/storybook/diagrams/user_interface_diagram.puml b/metrics/web/docs/features/storybook/diagrams/user_interface_diagram.puml new file mode 100644 index 000000000..d483797bf --- /dev/null +++ b/metrics/web/docs/features/storybook/diagrams/user_interface_diagram.puml @@ -0,0 +1,70 @@ +@startsalt user_interface_diagram +{# + {- + Metrics Storybook + {! + {T + + + +Metrics Logo <&image> + + + + Buttons + ++ Inactive Button + ++ Neutral Button + ++ Positive Button + + Toasts + ++ Negative Graph Indicator + ++ Positive Graph Indicator + + Graph Indicators + ++ Inactive Graph Indicator + ++ Neutral Graph Indicator + ++ Positive Graph Indicator + + + + + + + + + + + Sidebar + } | {- + Toggle theme button <&sun> + {! + { + . + . + . + . + [Inactive button] + . + . + . + . + . + . + . + . + . + . + Preview field + } | { + . + . + . + . + Label + "Inactive Button " + . + . + . + . + . + . + . + . + . + Editing panel + } + } + } + } + } +} +@endsalt diff --git a/metrics/web/docs/features/storybook/diagrams/metrics_storybook_web_relation_diagram.puml b/metrics/web/docs/features/storybook/diagrams/web_relation_diagram.puml similarity index 83% rename from metrics/web/docs/features/storybook/diagrams/metrics_storybook_web_relation_diagram.puml rename to metrics/web/docs/features/storybook/diagrams/web_relation_diagram.puml index 3690fb6b4..1b5ac25ab 100644 --- a/metrics/web/docs/features/storybook/diagrams/metrics_storybook_web_relation_diagram.puml +++ b/metrics/web/docs/features/storybook/diagrams/web_relation_diagram.puml @@ -1,4 +1,4 @@ -@startuml metrics_storybook_web_relation_diagram +@startuml web_relation_diagram package "metrics" { package "widgets" {