import panel as pn import base64 from io import BytesIO from hipsterfy.hipsterfy import Hipsterfy, HipsterfyPlaylist, HipsterfyPlaylistItem pn.extension("filedownload", "notifications", "location") def create_panel_page(hipsterfy: Hipsterfy, playlist_uri: str=None) -> pn.Template: # create widgets playlist_uri = pn.widgets.TextInput(name='Playlist URI', value=playlist_uri or '', placeholder='Enter Spotify Playlist URI') primary_item = pn.widgets.Select(name='Primary Item', options=HipsterfyPlaylistItem.get_available_properties(), value="release_year") secondary_item = pn.widgets.Select(name='Secondary Item', options=HipsterfyPlaylistItem.get_available_properties(), value="title") additional_items = pn.widgets.MultiChoice(name='Additional Items', options=HipsterfyPlaylistItem.get_available_properties(), value=["artists", "album", "popularity"]) enable_album_art = pn.widgets.Checkbox(name='Enable Album Art', value=True) print_mode_in_preview = pn.widgets.Checkbox(name='Print Mode in preview', value=True) cards_per_row_widget = pn.widgets.IntSlider(name="Cards per Row in print", start=1, end=6, value=4, step=1) pn.state.location.sync(playlist_uri, {"value": "playlist_uri"}) pn.state.location.sync(primary_item, {"value": "primary_item"}) pn.state.location.sync(secondary_item, {"value": "secondary_item"}) pn.state.location.sync(additional_items, {"value": "additional_items"}) pn.state.location.sync(enable_album_art, {"value": "enable_album_art"}) create_preview_button = pn.widgets.Button(name='Create Preview', button_type='primary') front_cards_column = pn.Column(sizing_mode='stretch_width') back_cards_column = pn.Column(sizing_mode='stretch_width') # FileDownload-Buttons (werden erst nach Preview-Generierung angezeigt) download_front_html_button = pn.widgets.FileDownload( label="Download Front Cards (HTML)", button_type="success", visible=False, filename="hipsterfy_front_cards.html" ) download_back_html_button = pn.widgets.FileDownload( label="Download Back Cards (HTML)", button_type="success", visible=False, filename="hipsterfy_back_cards.html" ) print_instructions = pn.pane.HTML( """

Print Instructions

To print the cards:

  1. Click on the "Download Front Cards" and "Download Back Cards" buttons to download the HTML files.
  2. Open the downloaded files in your web browser.
  3. Use your browser's print function (usually Ctrl+P or Cmd+P) to print the cards.
  4. Make sure to first print all front cards, then all back cards on the back side of the paper.
  5. Adjust the print settings to ensure the cards fit well on the page.
""", sizing_mode='stretch_width' ) print_instructions.visible = False # Initially hidden, will be shown after preview generation def generate_html(cards, row_reverse=False): html = "Print Cards" html += """ """ html += "" cards_per_row = cards_per_row_widget.value # <-- Widget-Wert verwenden # Karten in Reihen zu je 3 anordnen for i in range(0, len(cards), cards_per_row): row = cards[i:i+cards_per_row] if row_reverse: row = row[::-1] html += '
' for card in row: html += f'
{card}
' html += '
' html += "" return html.encode() # FileDownload erwartet Bytes def update_download_buttons(): # Front Cards cards = [pane.object for pane in front_cards_column[1:]] download_front_html_button.callback = lambda: BytesIO(generate_html(cards, row_reverse=False)) download_front_html_button.visible = True # Back Cards cards_back = [pane.object for pane in back_cards_column[1:]] download_back_html_button.callback = lambda: BytesIO(generate_html(cards_back, row_reverse=True)) download_back_html_button.visible = True print_instructions.visible = True # Show print instructions after generating preview pn.state.notifications.success("Download buttons updated successfully!. Download and print them from the sidebar") def create_preview(event): pn.state.notifications.info("Generating preview for playlist...") # clear previous cards front_cards_column.clear() back_cards_column.clear() front_cards_column.append(pn.pane.HTML("

Front Cards

", sizing_mode='stretch_width')) back_cards_column.append(pn.pane.HTML("

Back Cards

", sizing_mode='stretch_width')) # get playlist URI uri = playlist_uri.value.strip() if not uri: pn.state.notifications.error("Please enter a valid Spotify Playlist URI.") return # create HipsterfyPlaylist instance hipsterfy_playlist = HipsterfyPlaylist(uri, hipsterfy) # generate front and back cards for each item in the playlist for item in hipsterfy_playlist.get_tracks_data(): front_card = item.generate_hipsterfy_front_card(include_preview=False, print_mode=print_mode_in_preview.value) back_card = item.generate_hipsterfy_back_card( primary_property=primary_item.value, secondary_property=secondary_item.value, additional_properties=additional_items.value, album_cover_gb=enable_album_art.value, print_mode=print_mode_in_preview.value ) front_cards_column.append(pn.pane.HTML(front_card, sizing_mode='stretch_width')) back_cards_column.append(pn.pane.HTML(back_card, sizing_mode='stretch_width')) pn.state.notifications.success("Preview generated successfully!") pn.state.notifications.info("Prepare to download the cards as HTML files...") update_download_buttons() create_preview_button.on_click(create_preview) template = pn.template.FastListTemplate( title='Hipsterfy Playlist Manager', sidebar=[ playlist_uri, primary_item, secondary_item, additional_items, enable_album_art, cards_per_row_widget, create_preview_button, print_instructions, download_front_html_button, download_back_html_button ], main=[pn.Row(front_cards_column, back_cards_column, sizing_mode='stretch_width')], accent_base_color='indigo', header_background='indigo', header_color='white' ) return template