summaryrefslogtreecommitdiff
blob: 3d7940eb1fa3eb4450894b8b1f40260dd1a237df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
( function () {
	/**
	 * A widget that displays wikis and their pages to choose a filter
	 *
	 * @class
	 * @extends OO.ui.SelectWidget
	 *
	 * @constructor
	 * @param {mw.echo.dm.FiltersModel} filterModel Filters model
	 * @param {string} source Symbolic name for the source
	 * @param {Object} [config] Configuration object
	 * @cfg {string} [title] The title of this page group, usually
	 *  the name of the wiki that the pages belong to
	 * @cfg {number} [unreadCount] Number of unread notifications
	 * @cfg {number} [initialSelection] The page title of the option to select initially
	 */
	mw.echo.ui.PageFilterWidget = function MwEchoUiPageFilterWidget( filterModel, source, config ) {
		config = config || {};

		// Parent constructor
		mw.echo.ui.PageFilterWidget.super.call( this, config );

		this.model = filterModel;
		this.source = source;
		// This is to be able to fetch and recognize this widget
		// according to its source. The source is, in this case,
		// unique per filter widget.
		this.data = this.source;
		this.totalCount = config.unreadCount || this.model.getSourceTotalCount( this.source );

		this.initialSelection = config.initialSelection;

		// Title option
		this.title = new mw.echo.ui.PageNotificationsOptionWidget( {
			label: config.title,
			title: config.title,
			count: this.totalCount,
			isCapped: true,
			data: null,
			classes: [ 'mw-echo-ui-pageFilterWidget-title' ]
		} );

		// Initialization
		this.populateDataFromModel();
		this.$element
			.addClass( 'mw-echo-ui-pageFilterWidget' )
			.attr( 'aria-label', mw.message( 'echo-specialpage-pagefilterwidget-aria-label' ).text() );
	};

	/* Initialization */

	OO.inheritClass( mw.echo.ui.PageFilterWidget, OO.ui.SelectWidget );

	/**
	 * Set the total count of this group
	 *
	 * @return {number} Total count
	 */
	mw.echo.ui.PageFilterWidget.prototype.getTotalCount = function () {
		return this.totalCount;
	};

	/**
	 * Populate the widget from the model
	 */
	mw.echo.ui.PageFilterWidget.prototype.populateDataFromModel = function () {
		var title, widget, isUserPage,
			optionWidgets = [],
			sourcePages = this.model.getSourcePages( this.source );

		for ( title in sourcePages ) {
			isUserPage = sourcePages[ title ].ns === mw.config.get( 'wgNamespaceIds' ).user;
			widget = new mw.echo.ui.PageNotificationsOptionWidget( {
				label: isUserPage ? sourcePages[ title ].unprefixed : title,
				title: isUserPage ? sourcePages[ title ].unprefixed : title,
				icon: isUserPage ? 'userAvatar' : 'article',
				count: sourcePages[ title ].count,
				data: title,
				classes: [ 'mw-echo-ui-pageFilterWidget-page' ]
			} );
			optionWidgets.push( widget );

			if ( this.initialSelection === title ) {
				widget.setSelected( true );
			}
		}

		this.setItems( optionWidgets );
	};

	/**
	 * Get the source associated with this filter
	 *
	 * @return {string} Source symbolic name
	 */
	mw.echo.ui.PageFilterWidget.prototype.getSource = function () {
		return this.source;
	};

	/**
	 * Get the title item
	 *
	 * @return {mw.echo.ui.PageNotificationsOptionWidget} Page title item
	 */
	mw.echo.ui.PageFilterWidget.prototype.getTitleItem = function () {
		return this.title;
	};

	/**
	 * Set the page items in this widget, in order
	 *
	 * @param {mw.echo.ui.PageNotificationsOptionWidget[]} items Item widgets to order and insert
	 */
	mw.echo.ui.PageFilterWidget.prototype.setItems = function ( items ) {
		var i, index;

		this.clearItems();
		for ( i = 0; i < items.length; i++ ) {
			index = this.findInsertionIndex( items[ i ] );
			this.addItems( [ items[ i ] ], index );
		}

		// Add the title on top
		this.addItems( [ this.title ], 0 );
	};

	/**
	 * Find the proper insertion index for ordering when inserting items
	 *
	 * @private
	 * @param {mw.echo.ui.PageNotificationsOptionWidget} item Item widget
	 * @return {number} Insertion index
	 */
	mw.echo.ui.PageFilterWidget.prototype.findInsertionIndex = function ( item ) {
		var widget = this;

		return OO.binarySearch(
			this.items,
			function ( otherItem ) {
				return widget.sortingFunction( item, otherItem );
			},
			true
		);
	};

	/**
	 * Sorting function for item insertion
	 *
	 * @private
	 * @param {mw.echo.ui.PageNotificationsOptionWidget} item Item widget
	 * @param {mw.echo.ui.PageNotificationsOptionWidget} otherItem Another item widget
	 * @return {number} Ordering value
	 */
	mw.echo.ui.PageFilterWidget.prototype.sortingFunction = function ( item, otherItem ) {
		return Number( otherItem.getCount() ) - Number( item.getCount() );
	};
}() );