summaryrefslogtreecommitdiff
blob: fb015c33f71649f585f421025ed6c79783ced764 (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
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
( function ( $, mw ) {
	/**
	 * A notifications list organized and separated by dates
	 *
	 * @class
	 * @extends OO.ui.Widget
	 * @mixins OO.ui.mixin.PendingElement
	 *
	 * @constructor
	 * @param {mw.echo.Controller} controller Echo controller
	 * @param {mw.echo.dm.ModelManager} modelManager Model manager
	 * @param {Object} [config] Configuration object
	 * @cfg {boolean} [animateSorting=false] Animate the sorting of items
	 * @cfg {jQuery} [$overlay] An overlay for the popup menus
	 */
	mw.echo.ui.DatedNotificationsWidget = function MwEchoUiDatedNotificationsListWidget( controller, modelManager, config ) {
		config = config || {};

		// Parent constructor
		mw.echo.ui.DatedNotificationsWidget.parent.call( this, config );
		// Mixin constructors
		OO.ui.mixin.PendingElement.call( this, config );

		this.manager = modelManager;
		this.controller = controller;
		this.models = {};

		this.$overlay = config.$overlay || this.$element;
		this.animateSorting = !!config.animateSorting;

		this.listWidget = new mw.echo.ui.SortedListWidget(
			// Sorting callback
			function ( a, b ) {
				// Reverse sorting
				if ( b.getTimestamp() < a.getTimestamp() ) {
					return -1;
				} else if ( b.getTimestamp() > a.getTimestamp() ) {
					return 1;
				}
			},
			// Config
			{
				classes: [ 'mw-echo-ui-datedNotificationsWidget-group' ],
				$overlay: this.$overlay,
				animated: false
			}
		);

		// Events
		this.manager.connect( this, {
			update: 'populateFromModel',
			discard: 'onManagerDiscardModel'
		} );

		this.$element
			.addClass( 'mw-echo-ui-datedNotificationsWidget' )
			.append( this.listWidget.$element );

		// Initialization
		this.populateFromModel();
	};
	/* Initialization */

	OO.inheritClass( mw.echo.ui.DatedNotificationsWidget, OO.ui.Widget );
	OO.mixinClass( mw.echo.ui.DatedNotificationsWidget, OO.ui.mixin.PendingElement );

	mw.echo.ui.DatedNotificationsWidget.prototype.onManagerDiscardModel = function ( modelId ) {
		var group,
			model = this.models[ modelId ],
			list = this.getList();

		if ( model ) {
			group = list.getItemFromId( model.getName() );
			list.removeItems( [ group ] );
		}
	};
	/**
	 * Respond to model removing source group
	 *
	 * @param {string} source Symbolic name of the source group
	 */
	mw.echo.ui.DatedNotificationsWidget.prototype.onModelRemoveSource = function ( source ) {
		var list = this.getList(),
			group = list.getItemFromId( source );

		list.removeItems( [ group ] );
	};

	/**
	 * Respond to model manager update event.
	 * This event means we are repopulating the entire list and the
	 * associated models within it.
	 *
	 * @param {Object} models List models, indexed by ID
	 */
	mw.echo.ui.DatedNotificationsWidget.prototype.populateFromModel = function ( models ) {
		var modelId, model, subgroupWidget,
			groupWidgets = [];

		// Detach all attached models
		for ( modelId in this.models ) {
			this.detachModel( modelId );
		}

		for ( model in models ) {
			// Create SubGroup widgets
			subgroupWidget = new mw.echo.ui.DatedSubGroupListWidget(
				this.controller,
				models[ model ],
				{
					showTitle: true,
					showMarkAllRead: true,
					$overlay: this.$overlay,
					animated: this.animateSorting
				}
			);
			this.attachModel( model, models[ model ] );

			subgroupWidget.resetItemsFromModel();
			groupWidgets.push( subgroupWidget );
		}

		// Reset the list and re-add the items
		this.getList().clearItems();
		this.getList().addItems( groupWidgets );
	};

	/**
	 * Attach a model to the widget
	 *
	 * @param {string} modelId Symbolic name for the model
	 * @param {mw.echo.dm.SortedList} model Notifications list model
	 */
	mw.echo.ui.DatedNotificationsWidget.prototype.attachModel = function ( modelId, model ) {
		this.models[ modelId ] = model;
	};

	/**
	 * Detach a model from the widget
	 *
	 * @param {string} modelId Notifications list model
	 */
	mw.echo.ui.DatedNotificationsWidget.prototype.detachModel = function ( modelId ) {
		this.models[ modelId ].disconnect( this );
		delete this.models[ modelId ];
	};

	/**
	 * Get the list widget contained in this item
	 *
	 * @return {mw.echo.ui.SortedListWidget} List widget
	 */
	mw.echo.ui.DatedNotificationsWidget.prototype.getList = function () {
		return this.listWidget;
	};

	/**
	 * Get the number of all notifications in all sections of the widget
	 *
	 * @return {number} The number of all notifications
	 */
	mw.echo.ui.DatedNotificationsWidget.prototype.getAllNotificationCount = function () {
		var i,
			count = 0,
			groups = this.getList().getItems();

		for ( i = 0; i < groups.length; i++ ) {
			count += groups[ i ].getListWidget().getItemCount();
		}

		return count;
	};

}( jQuery, mediaWiki ) );