User:Base/Scripts/ReadingListViewer.js

From Meta, a Wikimedia project coordination wiki

Note: After publishing, you may have to bypass your browser's cache to see the changes.

  • Firefox / Safari: Hold Shift while clicking Reload, or press either Ctrl-F5 or Ctrl-R (⌘-R on a Mac)
  • Google Chrome: Press Ctrl-Shift-R (⌘-Shift-R on a Mac)
  • Internet Explorer / Edge: Hold Ctrl while clicking Refresh, or press Ctrl-F5
  • Opera: Press Ctrl-F5.
/**
 * An attempt to make a viewer for [[mw:Reading/Reading Lists]] being made, 
 * until I found another script doing the same thing.
 * 
 * Use `mw.loader.load('//en.wikipedia.org/w/?title=User:Jdlrobson/script-reading-lists.js&action=raw&ctype=text/javascript');` instead
 * 
 * Saving here for the sake of code reuse for my future scripts (OOui is a pain)
 * 
 * @todo attach execution to some portlet link
 * @todo clean-up dependencies
 * @todo lazy-load entries of each of the lists
 * @todo implement parts of CRUD other than Read
 */
var ReadingListViewer = function () {
    mw.loader.using([
        'oojs-ui-core',
        'oojs-ui-windows',
        'mediawiki.widgets',
        'mediawiki.widgets.DateInputWidget',
    ]).done(function () {

        function ReadingListDialogue(config) {
            ReadingListDialogue.super.call(this, config);
        }

        OO.inheritClass(ReadingListDialogue, OO.ui.ProcessDialog);

        $.extend(ReadingListDialogue.static, {
            name: 'ReadingListDialogue',
            actions: [
                {
                    flags: ['close'],
                    action: 'save'
                },
            ],
            title: 'Your reading lists',
            size: 'large',
        });

        $.extend(ReadingListDialogue.prototype, {
            initialize: function () {
                var me = this;

                ReadingListDialogue.super.prototype.initialize.apply(this, arguments);
                var api = new mw.Api();
                var booklet = new OO.ui.BookletLayout({
                    outlined: true
                });

                var readingList = this.getReadingLists(api);
                readingList.done(function (readingListQuery) {
                    console.log(readingListQuery);
                    var ids = readingListQuery.query.readinglists.map(function (readingList) {
                        return readingList.id;
                    });
                    var readingListEntries = me.getReadingListEntries(api, ids);
                    readingListEntries.done(function (readingListEntriesQuery) {
                        console.log(readingListEntriesQuery);
                        var pages = me.generateReadingListPages(
                            readingListQuery.query.readinglists,
                            readingListEntriesQuery.query.readinglistentries
                        );
                        booklet.addPages(pages);
                        me.$body.append(booklet.$element);
                    });
                });
            },
            generateReadingListPages: function (readingLists, readingListEntries) {
                var pages = [];

                function ReadingListPageLayout(name, content, config) {
                    ReadingListPageLayout.super.call(this, name, config);
                    this.$element.append(content);
                }

                OO.inheritClass(ReadingListPageLayout, OO.ui.PageLayout);
                readingLists.forEach(function (readingList) {
                    var entryItems = readingListEntries
                        .filter(function (entry) {
                            return entry.listId === readingList.id;
                        })
                        .map(function (entry) {
                            var title = new mw.Title(entry.title);
                            var entryElement = new OO.ui.MenuOptionWidget({
                                data: {
                                    url: title.getUrl()
                                },
                                label: $('<a>')
                                    .attr('href', title.getUrl())
                                    .text(title.getNameText()),
                            });

                            return entryElement;
                        });
                    var entryItemsWrapper = new OO.ui.SelectWidget({
                        items: entryItems,
                    });

                    // console.log(listPageContent);
                    var readingListPage = new ReadingListPageLayout(readingList.name, entryItemsWrapper.$element);
                    readingListPage.setupOutlineItem = function () {
                        this.outlineItem.setLabel(readingList.name);
                    };

                    pages.push(readingListPage);
                });

                return pages;
            },
            getActionProcess: function (action) {
                var dialog = this;
                if (action) {
                    return new OO.ui.Process(function () {
                        dialog.close({action: action});
                    });
                }
                return ReadingListDialogue.super.prototype.getActionProcess.call(this, action);
            },
            getBodyHeight: function () {
                return 250;
            },
            getReadingLists: function (api) {
                return api.get({
                    action: 'query',
                    meta: 'readinglists'
                });
            },
            getReadingListEntries: function (api, ids) {
                // api.php?action=query&list=readinglistentries
                return api.get({
                    action: 'query',
                    list: 'readinglistentries',
                    rlelists: ids,
                });
            }
        });

        var windowManager = new OO.ui.WindowManager();
        $(document.body).append(windowManager.$element);

        var readingListDialogue = new ReadingListDialogue();

        windowManager.addWindows([readingListDialogue]);
        windowManager.openWindow(readingListDialogue, {});
    });
};

ReadingListViewer();