holoviz / panel

Panel: The powerful data exploration & web app framework for Python
https://panel.holoviz.org
BSD 3-Clause "New" or "Revised" License
4.76k stars 517 forks source link

Docs issues to be fixed before 1.5.0 #7126

Open MarcSkovMadsen opened 2 months ago

MarcSkovMadsen commented 2 months ago

I will start reviewing the docs via https://holoviz-dev.github.io/panel.

I will use this issue to list things I can't or should not fix.

I will fix a lot of other things in https://github.com/holoviz/panel/pull/7127.

Todo (not for me)

The issues below are explained in more depth in comments below!

MarcSkovMadsen commented 2 months ago

1. Move Custom_Components to bottom of index

I believe Custom Components is the last thing your will be searching for as a new, basic or intermediate Panel user.

image

MarcSkovMadsen commented 2 months ago

2. Add Missing Images to Component Gallery.

image

You can add the missing ChatStep image while you are at it.

image

MarcSkovMadsen commented 2 months ago

4. Add missing logo_horizontal_light_theme.png

image

This is missing from other pages too

image

MarcSkovMadsen commented 2 months ago

5. Navigate to Custom Components when clicking Custom_Components.

When I click the Custom_Components link I don't navigate to it. Instead the Component Gallery reloads.

image

MarcSkovMadsen commented 2 months ago

6. Make Pyodide code blocks work (importShim is not defined, unsupported in polyfill mode)

When I check https://holoviz-dev.github.io/panel/reference/custom_components/AnyWidgetComponent.html, I see

image

MarcSkovMadsen commented 2 months ago

7. Consider enabling pn.custom.AnyWidgetComponent usage

I was trying to simplify and align the first AnyWidgetComponent example with the AnyWidget docs. But I cannot fully as

import panel as pn
import param

pn.extension()

class CounterButton(pn.custom.AnyWidgetComponent):

Yields

AttributeError: module 'panel' has no attribute 'custom'

Traceback (most recent call last):
  File "/home/jovyan/repos/private/panel/panel/io/handlers.py", line 405, in run
    exec(self._code, module.__dict__)
  File "/home/jovyan/repos/private/panel/script.py", line 6, in <module>
    class CounterButton(pn.custom.AnyWidgetComponent):
                        ^^^^^^^^^
AttributeError: module 'panel' has no attribute 'custom'

I'm used to always using the pn namespace and not seperately importing something. So I feel this is a change in the Panel way of working.

MarcSkovMadsen commented 2 months ago

8. Document how to not sync JSComponent parameters

With AnyWidget you have to actively sync paramter values between python and Javascript.

image

With Panel this is automatic. And we have no documented way to turn this of. We have seen use cases with ReactiveHTML where this is needed. The way to do it with ReactiveHTML is to set precedence<0. But this is a hack and we have not documented how to do this for JSComponent and similar.

Please find solution and document.

Would it be an idea to support a _sync_parameters or _dont_sync_parameters list on the class? Or a more general _esm_parameter_config attribute?

MarcSkovMadsen commented 2 months ago

9. Support css sharing between AnyWidget and AnyWidgetComponent

Just as sharing Javascript is a big benefit, It would be the same for css. But here the API is not the same:

image

The consequence is that its harder to co-develop and share widgets.

The developer can do it him/ her self though: el.classList.add("counter-widget");

import param
import panel as pn

from panel.custom import AnyWidgetComponent

pn.extension()

class CounterWidget(AnyWidgetComponent):
    _esm = """
    function render({ model, el }) {
      el.classList.add("counter-widget");
      let count = () => model.get("value");
      let btn = document.createElement("button");
      btn.innerHTML = `count is ${count()}`;
      btn.addEventListener("click", () => {
        model.set("value", count() + 1);
        model.save_changes();
      });
      model.on("change:value", () => {
        btn.innerHTML = `count is ${count()}`;
      });
      el.appendChild(btn);
    }
    export default { render };
    """
    _stylesheets = [
        """
        .counter-widget button { color: white; font-size: 1.75rem; background-color: #ea580c; padding: 0.5rem 1rem; border: none; border-radius: 0.25rem; }
        .counter-widget button:hover { background-color: #9a3412; }
        """
    ]
    value = param.Integer()

CounterWidget().servable()

For now I've added the comment below to the docs

image

MarcSkovMadsen commented 2 months ago

10. Update AnyWidget efficiency comment.

https://holoviz-dev.github.io/panel/how_to/migrate/anywidget/index.html

image

MarcSkovMadsen commented 2 months ago

11. Review https://holoviz-dev.github.io/panel/how_to/migrate/anywidget/index.html

Many things has changed since created. Please review the content such that its correct.

Please also consider the questions below

MarcSkovMadsen commented 2 months ago

12. Fix document did not publish any contents

The example in https://holoviz-dev.github.io/panel/how_to/custom_components/examples/esm_leaflet.html does mark some objects .servable(). They are also shown. But still you get error/ warning

import param
import pandas as pd
import panel as pn
import numpy as np

from panel.custom import JSComponent

class LeafletHeatMap(JSComponent):

    attribution = param.String(doc="Tile source attribution.")

    blur = param.Integer(default=18, bounds=(5, 50), doc="Amount of blur to apply to heatmap")

    center = param.XYCoordinates(default=(0, 0), doc="The center of the map.")

    data = param.DataFrame(doc="The heatmap data to plot, should have 'x', 'y' and 'value' columns.")

    tile_url = param.String(doc="Tile source URL with {x}, {y} and {z} parameter")

    min_alpha = param.Number(default=0.2, bounds=(0, 1), doc="Minimum alpha of the heatmap")

    radius = param.Integer(default=25, bounds=(5, 50), doc="The radius of heatmap values on the map")

    x = param.String(default='longitude', doc="Column in the data with longitude coordinates")

    y = param.String(default='latitude', doc="Column in the data with latitude coordinates")

    value = param.String(doc="Column in the data with the data values")

    zoom = param.Integer(default=13, bounds=(0, 21), doc="The plots zoom-level")

    _esm = """
    import L from "https://esm.sh/leaflet@1.7.1"
    import * as Lheat from "https://esm.sh/leaflet.heat@0.2.0"

    function get_records(model) {
      const records = []
      for (let i=0; i<model.data.index.length; i++)
        records.push([model.data[model.y][i], model.data[model.x][i], model.data[model.value][i]])
      return records
    }

    export function render({ model, el }) {
      const map = L.map(el).setView(model.center, model.zoom);

      map.on('change:zoom', () => { model.zoom = map.getZoom() })

      const tileLayer = L.tileLayer(model.tile_url, {
        attribution: model.attribution,
        maxZoom: 21,
        tileSize: 512,
        zoomOffset: -1,
      }).addTo(map)

      model.on("after_render", () => {
        console.log(Lheat)
        map.invalidateSize()
        const data = get_records(model)
        const heatLayer = L.heatLayer(
          data, {
            blur: model.blur,
            radius: model.radius,
            max: 10,
            minOpacity: model.min_alpha
        }).addTo(map)

        model.on(['blur', 'min_alpha', 'radius'], () => {
          heatLayer.setOptions({
            blur: model.blur,
            minOpacity: model.min_alpha,
            radius: model.radius,
          })
        })
        model.on('change:data', () => heatLayer.setLatLngs(get_records(model)))
      })
    }"""

    _stylesheets = ['https://unpkg.com/leaflet@1.7.1/dist/leaflet.css']

pn.extension(template='bootstrap')

url = "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_month.csv"

earthquakes = pd.read_csv(url)

heatmap = LeafletHeatMap(
    attribution='Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors',
    data=earthquakes[['longitude', 'latitude', 'mag']],
    min_height=500,
    tile_url='https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}.jpg',
    radius=30,
    sizing_mode='stretch_both',
    value='mag',
    zoom=2,
)

description=pn.pane.Markdown(f'## Earthquakes between {earthquakes.time.min()} and {earthquakes.time.max()}\n\n[Data Source]({url})', sizing_mode="stretch_width")

pn.Column(
    description,
    pn.Row(
        heatmap.controls(['blur', 'min_alpha', 'radius', 'zoom']).servable(target='sidebar'),
        heatmap.servable(),
        sizing_mode='stretch_both'
    ),
    sizing_mode='stretch_both'
)

image

The example in https://holoviz-dev.github.io/panel/how_to/custom_components/examples/esm_material_ui.html has the same problem.

MarcSkovMadsen commented 2 months ago

13. Add missing styles to Material UI examples

Trying to run the example https://holoviz-dev.github.io/panel/how_to/custom_components/examples/esm_material_ui.html I can see that it does not look anything like Material UI components. They are not styled.

image

You probably need to look at https://mui.com/material-ui/getting-started/installation/#cdn

MarcSkovMadsen commented 2 months ago

14. Fix errors and exceptions in docs build logs.

Looking at the logs of a docs build there are many. These should be fixed. And even better the build should fail if there are errors.

For an example look at https://github.com/holoviz/panel/actions/runs/10283240592/job/28456655577.

image

MarcSkovMadsen commented 2 months ago

15. DiscretePlayer broken

In doc/how_to/param/custom.md the example below is broken. Can't figure out why.

import panel as pn
import param

pn.extension()

class CustomExample(param.Parameterized):
    """An example Parameterized class"""

    select_string = param.Selector(objects=["red", "yellow", "green"])
    autocomplete_string = param.Selector(default='', objects=["red", "yellow", "green"], check_on_set=False)
    select_number = param.Selector(objects=[0, 1, 10, 100])

pn.Param(CustomExample.param, widgets={
    'select_string': pn.widgets.RadioButtonGroup,
    'autocomplete_string': pn.widgets.AutocompleteInput,
    'select_number': pn.widgets.DiscretePlayer}
).servable()

image

MarcSkovMadsen commented 2 months ago

16. Finalize Chat layout change

I tried out Panel 1.5.0b8 with the ChatInterface and to me the layout change seems unfinished. At least as a user I have a lot of questions.

I would suggestions aligning the time, copy icon and loading circle on the same line below the chat interface. And removing the vertical bar unless something is shown on the right of it.

image

As an alternative align the green circle left, right next to the name of the user. Might be better UX.

@ahuang11

ahuang11 commented 2 months ago

The green circle in the middle is definitely unintended; it's supposed to be next to the user name.

The vertical line is to divide the copy icon from the reaction icons.

The time and icon on separate lines is intended. Imo looks better that way

philippjfr commented 2 months ago

The green circle in the middle is definitely unintended; it's supposed to be next to the user name.

Haven't seen that but let's fix that asap.

The vertical line is to divide the copy icon from the reaction icons.

It shouldn't be there if there's no reaction icons though.

ahuang11 commented 2 months ago

How do you reproduce the green circle? It seems properly positioned for me. Perhaps need a hard refresh cache?

image
philippjfr commented 2 months ago

Have you tried different browsers? I think @MarcSkovMadsen uses Edge.

ahuang11 commented 2 months ago

On Edge

image
philippjfr commented 2 months ago

Maybe something is off with Marc's user string? Lots of spaces maybe?

ahuang11 commented 2 months ago

I think I was able to reproduce with pn.extension(sizing_mode="stretch_width"); fixed it by setting sizing_mode=None and setting width: fit-content for name/activity dot https://github.com/holoviz/panel/pull/7209

image
MarcSkovMadsen commented 2 months ago

Add missing FileDropper thumbnail.

When building the docs I see.

Used existing FileDownload thumbnail getting thumbnail code for /home/jovyan/repos/private/panel/examples/reference/widgets/FileDropper.ipynb Path exists True Traceback (most recent call last): File "/tmp/tmpgivt71lq", line 67, in from nbsite.gallery.thumbnailer import thumbnail;thumbnail(file_dropper, '/home/jovyan/repos/private/panel/doc/reference/widgets/thumbnails/FileDropper') ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/jovyan/repos/private/panel/.pixi/envs/docs/lib/python3.11/site-packages/nbsite/gallery/thumbnailer.py", line 133, in thumbnail obj.save(basename+'.png') File "/home/jovyan/repos/private/panel/panel/viewable.py", line 964, in save return save( ^^^^^ File "/home/jovyan/repos/private/panel/panel/io/save.py", line 272, in save return save_png( ^^^^^^^^^ File "/home/jovyan/repos/private/panel/panel/io/save.py", line 85, in save_png state.webdriver = webdriver_control.create() ^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/jovyan/repos/private/panel/.pixi/envs/docs/lib/python3.11/site-packages/bokeh/io/webdriver.py", line 180, in create driver = self._create(kind, scale_factor=scale_factor) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/home/jovyan/repos/private/panel/.pixi/envs/docs/lib/python3.11/site-packages/bokeh/io/webdriver.py", line 198, in _create raise RuntimeError("Neither firefox and geckodriver nor a variant of chromium browser and " \ RuntimeError: Neither firefox and geckodriver nor a variant of chromium browser and chromedriver are available on system PATH. You can install the former with 'conda install -c conda-forge firefox geckodriver'. FileDropper thumbnail export failed

MarcSkovMadsen commented 1 month ago

18. Enable Marc to create PY.CAFE Panel user and migrate examples to that user

See https://github.com/holoviz/panel/pull/7183

ahuang11 commented 1 month ago

Should https://github.com/holoviz/panel/pull/6819 go in for 1.5.0?

MarcSkovMadsen commented 1 month ago

19. Add missing Placeholder thumbnail

image

MarcSkovMadsen commented 1 month ago

20. Deprecate fastapi embed guide.

The guide at https://holoviz-dev.github.io/panel/how_to/integrations/FastAPI_Tornado.html is now superseeded by https://holoviz-dev.github.io/panel/how_to/integrations/FastAPI.html. We should delete the deprecated guide or make it very clear its deprecated.

MarcSkovMadsen commented 1 month ago

21. Update Custom Components Explanation

https://holoviz-dev.github.io/panel/explanation/components/reactive_html_components.html is marketed as custom components explanation. It no longer is a good explanation now that we have esm components.