Переглянути джерело

re-write ui.timeline; add test and documentation

Falko Schindler 1 рік тому
батько
коміт
756ea00dc8

+ 0 - 31
nicegui/elements/timeline.js

@@ -1,31 +0,0 @@
-export default {
-    template: `
-    <div class="q-px-lg q-py-md">
-      <q-timeline :color="timelinecolor">
-        <q-timeline-entry v-for="item in items" :key="item.id" 
-                            :title="item.title"
-                            :subtitle="item.subtitle"
-                            :icon="item.icon">
-              <div v-if="item.body">
-                {{item.body}}
-              </div>
-            </q-timeline-entry>
-          </q-timeline>
-        </div>`,
-    props: {
-      initialItems: Array,
-      timelinecolor: String,
-    },
-    data() {
-      return {
-        items: []
-      };
-    },
-    
-    mounted() {
-      if (this.initialItems && this.initialItems.length > 0) {
-        this.items = this.initialItems;
-      }
-    },
-    };
-  

+ 63 - 19
nicegui/elements/timeline.py

@@ -1,29 +1,73 @@
-import uuid
+from typing import Literal, Optional
 
 
 from nicegui.element import Element
 from nicegui.element import Element
 
 
 
 
-class Timeline(Element, component='timeline.js'):
+class Timeline(Element):
 
 
-    def __init__(self, initial_items: list = None, timelinecolor: str = "secondary") -> None:
-        super().__init__()
-        if initial_items:
-            self._props['initialItems'] = initial_items
-            self._props['timelinecolor'] = timelinecolor
+    def __init__(self,
+                 *,
+                 side: Literal['left', 'right'] = 'left',
+                 layout: Literal['dense', 'comfortable', 'loose'] = 'dense',
+                 color: Optional[str] = None,
+                 ) -> None:
+        """Timeline
 
 
-    """Timeline
+        This element represents `Quasar's QTimeline <https://quasar.dev/vue-components/timeline#qtimeline-api>`_ component.
 
 
-    :param initialItems: Items of the timeline. Should be an Array of dictionarys and contain the id, title, subtitle, icon, body
-    :param timelinecolor: Color of the Icons. Should be an quasar color
+        :param side: Side ("left" or "right"; default: "left").
+        :param layout: Layout ("dense", "comfortable" or "loose"; default: "dense").
+        :param color: Color of the icons.
+        """
+        super().__init__('q-timeline')
+        self._props['side'] = side
+        self._props['layout'] = layout
+        if color is not None:
+            self._props['color'] = color
 
 
-    See `here <https://developer.mozilla.org/en-US/docs/Web/HTML/Element/audio#events>`_
-    for a list of events you can subscribe to using the generic event subscription `on()`.
-    """
 
 
-    def _generate_id(self):
-        """Generate a unique ID for each timeline item."""
-        return str(uuid.uuid4())
+class TimelineEntry(Element):
 
 
-# Example Usage:
-# timeline = Timeline()
-# timeline.add_item(heading="Timeline Heading", title="Event Title", subtitle="Date", body="Description")
+    def __init__(self,
+                 body: Optional[str] = None,
+                 *,
+                 side: Literal['left', 'right'] = 'left',
+                 heading: bool = False,
+                 tag: Optional[str] = None,
+                 icon: Optional[str] = None,
+                 avatar: Optional[str] = None,
+                 title: Optional[str] = None,
+                 subtitle: Optional[str] = None,
+                 color: Optional[str] = None,
+                 ) -> None:
+        """Timeline Entry
+
+        This element represents `Quasar's QTimelineEntry <https://quasar.dev/vue-components/timeline#qtimelineentry-api>`_ component.
+
+        :param body: Body text.
+        :param side: Side ("left" or "right"; default: "left").
+        :param heading: Whether the timeline entry is a heading.
+        :param tag: HTML tag name to be used if it is a heading.
+        :param icon: Icon name.
+        :param avatar: Avatar URL.
+        :param title: Title text.
+        :param subtitle: Subtitle text.
+        :param color: Color or the timeline.
+        """
+        super().__init__('q-timeline-entry')
+        if body is not None:
+            self._props['body'] = body
+        self._props['side'] = side
+        self._props['heading'] = heading
+        if tag is not None:
+            self._props['tag'] = tag
+        if color is not None:
+            self._props['color'] = color
+        if icon is not None:
+            self._props['icon'] = icon
+        if avatar is not None:
+            self._props['avatar'] = avatar
+        if title is not None:
+            self._props['title'] = title
+        if subtitle is not None:
+            self._props['subtitle'] = subtitle

+ 4 - 0
nicegui/static/nicegui.css

@@ -93,6 +93,10 @@
   padding: 0.5rem;
   padding: 0.5rem;
   border: 1px solid #8884;
   border: 1px solid #8884;
 }
 }
+h6.q-timeline__title {
+  font-size: 1.25rem;
+  font-weight: 500;
+}
 
 
 #popup {
 #popup {
   position: fixed;
   position: fixed;

+ 4 - 0
nicegui/ui.py

@@ -67,6 +67,8 @@ __all__ = [
     'tabs',
     'tabs',
     'textarea',
     'textarea',
     'time',
     'time',
+    'timeline',
+    'timeline_item',
     'toggle',
     'toggle',
     'tooltip',
     'tooltip',
     'tree',
     'tree',
@@ -160,6 +162,8 @@ from .elements.tabs import TabPanels as tab_panels
 from .elements.tabs import Tabs as tabs
 from .elements.tabs import Tabs as tabs
 from .elements.textarea import Textarea as textarea
 from .elements.textarea import Textarea as textarea
 from .elements.time import Time as time
 from .elements.time import Time as time
+from .elements.timeline import Timeline as timeline
+from .elements.timeline import TimelineEntry as timeline_entry
 from .elements.toggle import Toggle as toggle
 from .elements.toggle import Toggle as toggle
 from .elements.tooltip import Tooltip as tooltip
 from .elements.tooltip import Tooltip as tooltip
 from .elements.tree import Tree as tree
 from .elements.tree import Tree as tree

+ 16 - 0
tests/test_timeline.py

@@ -0,0 +1,16 @@
+from nicegui import ui
+
+from .screen import Screen
+
+
+def test_timeline(screen: Screen):
+    with ui.timeline():
+        ui.timeline_entry('Entry 1', title='Title 1', subtitle='Subtitle 1')
+        with ui.timeline():
+            ui.label('Entry 2')
+
+    screen.open('/')
+    screen.should_contain('Entry 1')
+    screen.should_contain('Title 1')
+    screen.should_contain('Subtitle 1')
+    screen.should_contain('Entry 2')

+ 1 - 0
website/documentation.py

@@ -182,6 +182,7 @@ def create_full() -> None:
     load_demo(ui.splitter)
     load_demo(ui.splitter)
     load_demo('tabs')
     load_demo('tabs')
     load_demo(ui.stepper)
     load_demo(ui.stepper)
+    load_demo(ui.timeline)
     load_demo(ui.carousel)
     load_demo(ui.carousel)
     load_demo(ui.menu)
     load_demo(ui.menu)
 
 

+ 16 - 0
website/more_documentation/timeline_documentation.py

@@ -0,0 +1,16 @@
+from nicegui import ui
+
+
+def main_demo() -> None:
+    with ui.timeline(side='right'):
+        ui.timeline_entry('Rodja and Falko start working on NiceGUI.',
+                          title='Initial commit',
+                          subtitle='May 07, 2021')
+        ui.timeline_entry('The first PyPI package is released.',
+                          title='Release of 0.1',
+                          subtitle='May 14, 2021')
+        ui.timeline_entry('Large parts are rewritten to remove JustPy '
+                          'and to upgrade to Vue 3 and Quasar 2.',
+                          title='Release of 1.0',
+                          subtitle='December 15, 2022',
+                          icon='rocket')