import html import json import os from typing import List import scripts.mo.ui_format as ui_format from scripts.mo.data.storage import map_record_to_dict from scripts.mo.environment import env from scripts.mo.models import Record, ModelType from scripts.mo.utils import get_best_preview_url _NO_PREVIEW_DARK = 'file=extensions/sd-model-organizer/pic/no-preview-dark-blue.png' _NO_PREVIEW_LIGHT = 'file=extensions/sd-model-organizer/pic/no-preview-light.png' def alert_danger(value) -> str: if isinstance(value, list): text = "
".join([html.escape(s) for s in value]) else: text = html.escape(value) return f'
{text}
' def alert_primary(value) -> str: if isinstance(value, list): text = "
".join([html.escape(s) for s in value]) else: text = html.escape(value) return f'
{text}
' def alert_success(value) -> str: if isinstance(value, list): text = "
".join([html.escape(s) for s in value]) else: text = html.escape(value) return f'
{text}
' def alert_warning(value) -> str: if isinstance(value, list): text = "
".join([html.escape(s) for s in value]) else: text = html.escape(value) return f'
{text}
' def _limit_description(text): if text and len(text) > 600: return text[:600] + '...' else: return text def _limit_card_name(text): if text and len(text) > 150: return text[:150] + '...' else: return text def _model_type_css_class(model_type: ModelType) -> str: if model_type == ModelType.CHECKPOINT: css_class = 'mo-badge-checkpoint' elif model_type == ModelType.VAE: css_class = 'mo-badge-vae' elif model_type == ModelType.LORA: css_class = 'mo-badge-lora' elif model_type == ModelType.HYPER_NETWORK: css_class = 'mo-badge-hyper-network' elif model_type == ModelType.LYCORIS: css_class = 'mo-badge-lycoris' elif model_type == ModelType.EMBEDDING: css_class = 'mo-badge-embedding' elif model_type == ModelType.OTHER: css_class = 'mo-badge-other' else: raise ValueError(f'Unhandled model_type value: {model_type}') return css_class def _model_card_type_css_class(model_type: ModelType) -> str: if model_type == ModelType.CHECKPOINT: css_class = 'mo-card-checkpoint' elif model_type == ModelType.VAE: css_class = 'mo-card-vae' elif model_type == ModelType.LORA: css_class = 'mo-card-lora' elif model_type == ModelType.HYPER_NETWORK: css_class = 'mo-card-hyper-network' elif model_type == ModelType.LYCORIS: css_class = 'mo-card-lycoris' elif model_type == ModelType.EMBEDDING: css_class = 'mo-card-embedding' elif model_type == ModelType.OTHER: css_class = 'mo-card-other' else: raise ValueError(f'Unhandled model_type value: {model_type}') return css_class def _no_preview_image_url() -> str: if env.theme() == 'dark': return _NO_PREVIEW_DARK else: return _NO_PREVIEW_LIGHT def records_table(records: List) -> str: table_html = '
' table_html += '
' table_html += '
Preview
' table_html += '
Type
' table_html += '
Name
' table_html += '
Description
' table_html += '
Actions
' table_html += '
' nsfw_blur = env.nsfw_blur() for record in records: contains_nsfw = any('nsfw' in group.lower() for group in record.groups) and nsfw_blur name = html.escape(record.name) type_ = record.model_type.value preview_url = get_best_preview_url(record) description = _limit_description(record.description) # Add row table_html += '
' # Add preview URL column table_html += '
' isLocalFileRecord = record.is_local_file_record() img = f'{type_}
' # Add name column table_html += f'
' table_html += f'' table_html += '
' # Add description column table_html += f'
' table_html += f'{html.escape(description)}' table_html += '
' # Add actions column table_html += '
' if record.is_local_file_record(): json_record = html.escape(json.dumps(map_record_to_dict(record))) table_html += '
' table_html += '
' else: table_html += '
' if record.is_download_possible(): table_html += '
' table_html += '
' table_html += '
' table_html += '
' # Close row table_html += '
' # Close table table_html += '
' return table_html def _create_content_text(text: str) -> str: return f'{text}' def _create_content_model_type(model_type: ModelType) -> str: return f'{model_type.value}' def _create_content_hash(value: str) -> str: return f'{value}' def _create_content_link(link: str) -> str: return f'{link}' def _create_groups(groups: List) -> str: groups_html = '' for group in groups: groups_html += f'{html.escape(group)}' return groups_html def _create_top_fields_dict(record: Record) -> dict: result = { 'Name': _create_content_text(html.escape(record.name)), 'Type': _create_content_model_type(record.model_type) } if record.location and os.path.exists(record.location): size = os.path.getsize(record.location) result['Size'] = _create_content_hash(ui_format.format_bytes(size)) if record.sha256_hash: result['SHA256'] = _create_content_hash(record.sha256_hash) if record.location and os.path.exists(record.location): result['Location'] = _create_content_hash(record.location) if record.url: result['Model page'] = _create_content_link(record.url) if record.groups: result['Groups'] = _create_groups(record.groups) if record.download_url: result['Download URL'] = _create_content_link(record.download_url) if record.download_path: result['Download path'] = _create_content_text(record.download_path) if record.download_filename: result['Download filename'] = _create_content_text(record.download_filename) if record.subdir: result['Subdir'] = _create_content_text(record.subdir) if record.weight != 1: result['Prompt Weight']= _create_content_text(str(record.weight)) return result def _details_field_row(title: str, field: str, is_even: bool) -> str: highlight = 'mo-details-row-even' if is_even else 'mo-details-row-odd' content = f'
' content += '
' content += f'{title}:' content += '
' content += '
' content += field content += '
' content += '
' return content def _details_top(record: Record) -> str: preview_url = get_best_preview_url(record) content = '
' # Preview image content += '
' content += f'Preview Image' content += '
' # Details column content += '
' content += '
' fields = _create_top_fields_dict(record) counter = 0 for key, value in fields.items(): content += _details_field_row(key, value, counter % 2 == 0) counter += 1 # End Top Details column content += '
' content += '
' content += '
' if record.positive_prompts or record.negative_prompts: content += '
' content += '
' content += '
' content += '
' content += '
' if record.positive_prompts: content += '
' content += 'Positive Prompts:' content += '
' if record.negative_prompts: content += '
' content += 'Negative Prompts' content += '
' content += '
' content += '
' if record.positive_prompts: content += '
' content += '' content += html.escape(record.positive_prompts) content += '' content += '
' if record.negative_prompts: content += '
' content += '' content += html.escape(record.negative_prompts) content += '' content += '
' content += '
' content += '
' content += '
' content += '
' content += '
' content += '' return content def record_details(record: Record) -> str: content = '
' content += _details_top(record) content += '
' return content def records_cards(records: List) -> str: content = '
' nsfw_blur = env.nsfw_blur() for record in records: contains_nsfw = any('nsfw' in group.lower() for group in record.groups) and nsfw_blur isLocalFileRecord = record.is_local_file_record() # Taken from extra networks cards. cardStr = f'
' content += f'
{html.escape(_limit_card_name(record.name))}
' content += '
' content += f'
{record.model_type.value}
' content += '
' content += '
' content += '
' if isLocalFileRecord: json_record = html.escape(json.dumps(map_record_to_dict(record))) content += '
' location = record.location.replace("\\", "\\\\") content += '
' else: content += '
' if record.is_download_possible(): content += '
' content += '
' content += '
' content += '
' content += '
' content += '
' content += '
' return content def _downloads_header(record_id, title) -> str: content = '
' content += f'

{html.escape(title)}

' content += f'

Pending

' content += '
' return content def _download_url(record_id, url: str, is_preview: bool) -> str: preview = '-preview' if is_preview else '' hint = 'Preview URL' if is_preview else 'Model URL' content = f'

' \ f'[{hint}]: {url}

' return content def _download_info(record_id, is_preview: bool) -> str: preview = '-preview' if is_preview else '' content = f'
' content += f'

' content += f'

' content += f'

' content += '
' return content def _download_progress_bar(record_id, is_preview: bool) -> str: preview = '-preview' if is_preview else '' content = '' return content def download_cards(records: List, token) -> str: content = f'
' counter = 0 for record in records: id_ = record.id_ card_margin_top = '0' if counter == 0 else '2rem' content += f'
' content += _downloads_header(id_, record.name) content += _download_url(id_, record.download_url, False) content += _download_info(id_, False) content += _download_progress_bar(id_, False) if record.preview_url and env.download_preview(): content += _download_url(id_, record.preview_url, True) content += _download_info(id_, True) content += _download_progress_bar(id_, True) content += f'
' content += '
' content += '
' counter += 1 content += '
' return content