Commit bdfa2ab2 authored by jan.koester's avatar jan.koester
Browse files

test

parent b368c567
Loading
Loading
Loading
Loading
+65 −0
Original line number Diff line number Diff line
@@ -675,3 +675,68 @@ dialog label {
    margin-left: auto;
    font-weight: bold;
}

/* Media Browser */
#media-browser-dialog {
    width: 700px;
    max-width: 90vw;
    max-height: 80vh;
}

.media-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
    gap: 8px;
    max-height: 50vh;
    overflow-y: auto;
    padding: 8px 0;
}

.media-grid-item {
    border: 2px solid transparent;
    border-radius: 6px;
    cursor: pointer;
    overflow: hidden;
    background: var(--bg-secondary, #2a2a3a);
    display: flex;
    flex-direction: column;
    align-items: center;
}

.media-grid-item:hover {
    border-color: var(--accent, #89b4fa);
}

.media-grid-item.selected {
    border-color: var(--accent, #89b4fa);
    box-shadow: 0 0 0 2px var(--accent, #89b4fa);
}

.media-grid-item img {
    width: 100%;
    height: 100px;
    object-fit: cover;
}

.media-grid-item .media-name {
    font-size: 0.75rem;
    padding: 4px;
    text-align: center;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    width: 100%;
}

.media-browse-field {
    display: flex;
    gap: 4px;
}

.media-browse-field input {
    flex: 1;
}

.media-browse-field button {
    white-space: nowrap;
}
+19 −0
Original line number Diff line number Diff line
@@ -232,6 +232,24 @@
        </div>
    </dialog>

    <!-- Media Browser Dialog -->
    <dialog id="media-browser-dialog">
        <h3>Media Browser</h3>
        <div class="set-field">
            <label data-i18n="I18N_CONNECTION">Verbindung</label>
            <select id="media-conn-select"></select>
        </div>
        <div class="set-field">
            <label>Album</label>
            <select id="media-album-select"><option value="">-- Album --</option></select>
        </div>
        <div id="media-grid" class="media-grid"></div>
        <span id="media-status" class="set-status"></span>
        <div class="dialog-actions">
            <button id="btn-media-close" data-i18n="Close">Schlie&szlig;en</button>
        </div>
    </dialog>

    <dialog id="ai-dialog">
        <h3 data-i18n="I18N_AI">KI-Assistent</h3>
        <div class="set-field">
@@ -336,6 +354,7 @@
    <script src="js/tree.js"></script>
    <script src="js/properties.js"></script>
    <script src="js/preview.js"></script>
    <script src="js/media-browser.js"></script>
    <script src="js/editor.js"></script>
</body>
</html>
+14 −0
Original line number Diff line number Diff line
@@ -233,6 +233,20 @@ var EditorApi = (function() {
            });
        },

        // Media browse (via blog connection)
        mediaListAlbums: function(connId) {
            return request('POST', '/api/connection/media/' + connId, {
                command: 'media_list_albums'
            });
        },

        mediaListMedia: function(connId, albumId) {
            return request('POST', '/api/connection/media/' + connId, {
                command: 'media_list_media',
                album_id: albumId
            });
        },

        // HTML import/export
        importHtml: function(html) {
            return request('POST', '/api/document/import-html', { html: html });
+172 −0
Original line number Diff line number Diff line
/*******************************************************************************
 * blogi-webedit Media Browser
 * Lets the user browse media from connected blog servers (MediaDB).
 *******************************************************************************/

var MediaBrowser = (function() {
    'use strict';

    var _onSelect = null;    // callback(mediaItem)
    var _dialog = null;
    var _connSelect = null;
    var _albumSelect = null;
    var _grid = null;
    var _status = null;
    var _bound = false;

    function _ensureElements() {
        _dialog = document.getElementById('media-browser-dialog');
        _connSelect = document.getElementById('media-conn-select');
        _albumSelect = document.getElementById('media-album-select');
        _grid = document.getElementById('media-grid');
        _status = document.getElementById('media-status');
    }

    function _bind() {
        if (_bound) return;
        _bound = true;

        document.getElementById('btn-media-close').addEventListener('click', function() {
            _dialog.close();
        });

        _connSelect.addEventListener('change', function() {
            var connId = _connSelect.value;
            if (connId) _loadAlbums(connId);
        });

        _albumSelect.addEventListener('change', function() {
            var connId = _connSelect.value;
            var albumId = _albumSelect.value;
            if (connId && albumId) _loadMedia(connId, albumId);
        });
    }

    function open(onSelect) {
        _onSelect = onSelect;
        _ensureElements();
        _bind();

        _grid.innerHTML = '';
        _albumSelect.innerHTML = '<option value="">-- Album --</option>';
        _status.textContent = '';

        // Load connections
        _connSelect.innerHTML = '<option value="">...</option>';
        EditorApi.listConnections().then(function(resp) {
            var conns = resp.connections || [];
            _connSelect.innerHTML = '';
            if (conns.length === 0) {
                _connSelect.innerHTML = '<option value="">No connections</option>';
                return;
            }
            for (var i = 0; i < conns.length; i++) {
                var opt = document.createElement('option');
                opt.value = conns[i].id;
                var label = conns[i].name;
                if (conns[i].group) label = conns[i].group + ' / ' + label;
                opt.textContent = label;
                _connSelect.appendChild(opt);
            }
            // Auto-load albums for first connection
            if (conns.length > 0) {
                _connSelect.value = conns[0].id;
                _loadAlbums(conns[0].id);
            }
        });

        _dialog.showModal();
    }

    function _loadAlbums(connId) {
        _albumSelect.innerHTML = '<option value="">...</option>';
        _grid.innerHTML = '';
        _status.textContent = '';

        EditorApi.mediaListAlbums(connId).then(function(resp) {
            var albums = resp.albums || [];
            _albumSelect.innerHTML = '<option value="">-- Album --</option>';
            for (var i = 0; i < albums.length; i++) {
                var opt = document.createElement('option');
                opt.value = albums[i].id;
                var label = albums[i].name;
                if (albums[i].store) label += ' (' + albums[i].store + ')';
                if (albums[i].media_count !== undefined) label += ' [' + albums[i].media_count + ']';
                opt.textContent = label;
                _albumSelect.appendChild(opt);
            }
            if (albums.length === 0) {
                _status.textContent = 'No albums found';
            }
        }).catch(function(err) {
            _status.textContent = 'Error: ' + (err.error || 'Unknown');
            _status.className = 'set-status error';
        });
    }

    function _loadMedia(connId, albumId) {
        _grid.innerHTML = '';
        _status.textContent = 'Loading...';

        EditorApi.mediaListMedia(connId, albumId).then(function(resp) {
            var media = resp.media || [];
            _status.textContent = '';
            _grid.innerHTML = '';

            if (media.length === 0) {
                _status.textContent = 'No media in this album';
                return;
            }

            for (var i = 0; i < media.length; i++) {
                _grid.appendChild(_createMediaItem(media[i]));
            }
        }).catch(function(err) {
            _status.textContent = 'Error: ' + (err.error || 'Unknown');
            _status.className = 'set-status error';
        });
    }

    function _createMediaItem(item) {
        var div = document.createElement('div');
        div.className = 'media-grid-item';
        div.dataset.id = item.id;

        if (item.kind === 'image' || item.content_type.indexOf('image') === 0) {
            var img = document.createElement('img');
            img.src = item.url + '?w=150&h=150';
            img.alt = item.filename;
            img.loading = 'lazy';
            div.appendChild(img);
        } else {
            var icon = document.createElement('div');
            icon.style.cssText = 'width:100%;height:100px;display:flex;align-items:center;justify-content:center;font-size:2rem;';
            icon.textContent = item.kind === 'video' ? '\uD83C\uDFA5' : '\uD83D\uDCC4';
            div.appendChild(icon);
        }

        var name = document.createElement('div');
        name.className = 'media-name';
        name.textContent = item.filename;
        name.title = item.filename;
        div.appendChild(name);

        div.addEventListener('click', function() {
            // Remove selected from others
            var prev = _grid.querySelector('.selected');
            if (prev) prev.classList.remove('selected');
            div.classList.add('selected');

            if (_onSelect) {
                _onSelect(item);
            }
            _dialog.close();
        });

        return div;
    }

    return {
        open: open
    };
})();
+27 −0
Original line number Diff line number Diff line
@@ -113,6 +113,33 @@ var PropertiesPanel = (function() {
                    input.value = value;
                    input.rows = 6;
                    if (field.placeholder) input.placeholder = field.placeholder;
                } else if (field.type === 'media_browse') {
                    var wrapper = document.createElement('div');
                    wrapper.className = 'media-browse-field';
                    input = document.createElement('input');
                    input.type = 'text';
                    input.name = field.key;
                    input.value = value;
                    input.placeholder = 'Media ID';
                    var browseBtn = document.createElement('button');
                    browseBtn.type = 'button';
                    browseBtn.textContent = '\uD83D\uDDBC\uFE0F';
                    browseBtn.title = 'Browse media';
                    (function(inp) {
                        browseBtn.addEventListener('click', function() {
                            if (typeof MediaBrowser !== 'undefined') {
                                MediaBrowser.open(function(mediaItem) {
                                    inp.value = mediaItem.id;
                                    inp.dispatchEvent(new Event('change'));
                                });
                            }
                        });
                    })(input);
                    wrapper.appendChild(input);
                    wrapper.appendChild(browseBtn);
                    group.appendChild(wrapper);
                    form.appendChild(group);
                    continue;
                } else {
                    input = document.createElement('input');
                    input.type = 'text';
Loading