scrivito_content_browser 0.50.1 → 0.60.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  (function() {
2
- var ExpandableFilterNodeMixin, FilterMixin, InfiniteScrollMixin, InspectedItemMixin, OptionFilterLabelRenderMixin, OptionFilterMixin, classSet, models, ui,
2
+ var AddItemMixin, ExpandableFilterNodeMixin, FilterMixin, InfiniteScrollMixin, InspectedItemMixin, OptionFilterLabelRenderMixin, OptionFilterMixin, classSet, models, ui,
3
3
  __hasProp = {}.hasOwnProperty,
4
4
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
5
5
 
@@ -37,12 +37,18 @@
37
37
  }
38
38
  return _results;
39
39
  },
40
+ _showConfirm: function(props) {
41
+ props.mode = 'confirm';
42
+ return this._showAlert(props);
43
+ },
40
44
  _showAlert: function(props) {
41
45
  var alertContainer;
42
46
  alertContainer = document.createElement('DIV');
43
47
  document.body.appendChild(alertContainer);
48
+ props.promise = $.Deferred();
44
49
  props.container = alertContainer;
45
- return React.render(React.createElement(models.AlertApp, React.__spread({}, props)), alertContainer);
50
+ React.render(React.createElement(models.DialogApp, React.__spread({}, props)), alertContainer);
51
+ return props.promise;
46
52
  },
47
53
  _loadModal: function() {
48
54
  $('<div></div>').addClass('scrivito_overlay scrivito_show').appendTo($('body'));
@@ -113,6 +119,91 @@
113
119
 
114
120
  scrivito.register_public_api("content_browser", scrivito.content_browser);
115
121
 
122
+ AddItemMixin = {
123
+ itemClassName: function() {
124
+ var className;
125
+ className = "scrivito-content-browser-add";
126
+ if (!this.props.objCreation.isActive()) {
127
+ className += " disabled";
128
+ }
129
+ return className;
130
+ },
131
+ iconClassName: function() {
132
+ var iconClass;
133
+ iconClass = this.props.objCreation.isActive() ? "scrivito_icon_plus" : "scrivito_icon_disabled";
134
+ return "scrivito_icon " + iconClass;
135
+ },
136
+ creationNotPossibleBody: function(error) {
137
+ return React.createElement("ul", null, _.map(error.nodeTitles, function(title) {
138
+ return React.createElement("li", null, title);
139
+ }));
140
+ },
141
+ presetConflictBody: function(error) {
142
+ return React.createElement("div", null, "The selected filter options cannot be applied to the file(s)\nyou wanted to upload. Please select only one of the following options,\nthen try again:\n", _.map(error.fields, function(values, field) {
143
+ return React.createElement("div", null, React.createElement("h4", null, field), React.createElement("ul", null, _.map(values, function(value) {
144
+ return React.createElement("li", null, value);
145
+ })));
146
+ }));
147
+ },
148
+ showErrorAlert: function(error) {
149
+ var alertProps;
150
+ alertProps = (function() {
151
+ switch (error.type) {
152
+ case 'creation_not_possible':
153
+ return {
154
+ subtitle: 'Creation of items matching the selected filters has been disabled.',
155
+ body: this.creationNotPossibleBody(error)
156
+ };
157
+ case 'obj_class_not_provided':
158
+ return {
159
+ subtitle: "Configuration error: No '_obj_class' provided."
160
+ };
161
+ case 'preset_conflict':
162
+ return {
163
+ body: this.presetConflictBody(error)
164
+ };
165
+ }
166
+ }).call(this);
167
+ alertProps.title = "Creation not possible";
168
+ return scrivito.content_browser._showAlert(alertProps);
169
+ },
170
+ buildErrorMessage: function(error) {
171
+ var message, nodesString;
172
+ switch (error.type) {
173
+ case 'creation_not_possible':
174
+ nodesString = error.nodeTitles.join(', ');
175
+ return "The selected filter options " + nodesString + " prevent the creation";
176
+ case 'obj_class_not_provided':
177
+ return "Configuration error: No '_obj_class' provided";
178
+ case 'preset_conflict':
179
+ message = 'The selected filter options cannot be applied to the file(s) you wanted to upload. Please select only one of the following options, then try again:\n';
180
+ _.each(error.fields, function(value, field) {
181
+ return message += "" + field + ": " + (value.join(', ')) + "\n";
182
+ });
183
+ return message;
184
+ }
185
+ },
186
+ iconTitle: function() {
187
+ if (!this.props.objCreation.isActive()) {
188
+ return this.buildErrorMessage(this.props.objCreation.error());
189
+ }
190
+ },
191
+ textMessage: function() {
192
+ if (this.props.objCreation.isActive()) {
193
+ return "Create Item";
194
+ } else {
195
+ return "Item creation not possible";
196
+ }
197
+ },
198
+ createClick: function() {
199
+ if (this.props.objCreation.isActive()) {
200
+ return this.props.addedObjsCollection.createObj(this.props.objCreation.preset());
201
+ } else {
202
+ return this.showErrorAlert(this.props.objCreation.error());
203
+ }
204
+ }
205
+ };
206
+
116
207
  ExpandableFilterNodeMixin = {
117
208
  defaultExpansionState: function() {
118
209
  return {
@@ -744,6 +835,13 @@
744
835
  return this.changed();
745
836
  };
746
837
 
838
+ Filter.prototype.setSortCriteria = function(sortCriteria) {
839
+ if (!this.sortCriteria.equals(sortCriteria)) {
840
+ this.sortCriteria = sortCriteria;
841
+ return this.changed();
842
+ }
843
+ };
844
+
747
845
  Filter.prototype._deselectAdditionalFilters = function() {
748
846
  if (this.hasAdditionalFilters()) {
749
847
  return _.each(this.additionalFilters, function(filter) {
@@ -783,6 +881,7 @@
783
881
  Filter.prototype._initFilters = function(filter_definition) {
784
882
  this.treeFilters = [];
785
883
  this.additionalFilters = [];
884
+ this.sortCriteria = new models.SortCriteria();
786
885
  return _.each(filter_definition, (function(_this) {
787
886
  return function(definition, name) {
788
887
  var subFilters;
@@ -886,7 +985,9 @@
886
985
  }
887
986
 
888
987
  Obj.prototype.title = function() {
889
- return this._attr['title'] || '(No description)';
988
+ var rawTitle;
989
+ rawTitle = this._attr['title'] || '(No description)';
990
+ return rawTitle.trim();
890
991
  };
891
992
 
892
993
  Obj.prototype.subtitle = function() {
@@ -936,12 +1037,15 @@
936
1037
  models.ObjCollection = (function(_super) {
937
1038
  __extends(ObjCollection, _super);
938
1039
 
939
- function ObjCollection(selectedObjs, _selectionMode, objs) {
1040
+ function ObjCollection(selectedObjs, _selectionMode, objs, sortCriteria) {
940
1041
  this._selectionMode = _selectionMode;
941
1042
  ObjCollection.__super__.constructor.call(this);
942
1043
  this._selectionMode || (this._selectionMode = 'multi');
1044
+ sortCriteria || (sortCriteria = new models.SortCriteria());
1045
+ this._sortCriteria = sortCriteria;
943
1046
  this._selectedObjs = selectedObjs || [];
944
1047
  this._objs = objs || [];
1048
+ this._isAlreadyReversed = false;
945
1049
  this._curQueryNumber = 0;
946
1050
  }
947
1051
 
@@ -963,12 +1067,6 @@
963
1067
  }
964
1068
  };
965
1069
 
966
- ObjCollection.prototype._resetLoadingState = function() {
967
- var _ref;
968
- this._nextQuery = null;
969
- return (_ref = this._isLoadingPagePromise) != null ? _ref.resolve() : void 0;
970
- };
971
-
972
1070
  ObjCollection.prototype.loadFromBackend = function(query) {
973
1071
  var promise;
974
1072
  this._query = query;
@@ -985,10 +1083,6 @@
985
1083
  return promise;
986
1084
  };
987
1085
 
988
- ObjCollection.prototype._removeObjFromSelectedCollection = function(objId) {
989
- return this._selectedObjs = _.without(this._selectedObjs, objId);
990
- };
991
-
992
1086
  ObjCollection.prototype.toggleSelected = function(objId) {
993
1087
  if (this.isSelected(objId)) {
994
1088
  this._removeObjFromSelectedCollection(objId);
@@ -1006,20 +1100,14 @@
1006
1100
  return _.contains(this._selectedObjs, objId);
1007
1101
  };
1008
1102
 
1009
- ObjCollection.prototype.destroyById = function(objId) {
1010
- return scrivito.delete_obj(objId).done((function(_this) {
1011
- return function() {
1012
- return _this._removeObjFromSelectedCollection(objId);
1013
- };
1014
- })(this));
1015
- };
1016
-
1017
- ObjCollection.prototype._getLoadingPagePromise = function() {
1018
- return $.Deferred().always((function(_this) {
1103
+ ObjCollection.prototype.destroyObj = function(obj) {
1104
+ var promise;
1105
+ promise = this._destroyById(obj.id()).done((function(_this) {
1019
1106
  return function() {
1020
- return _this.trigger('end-page-load');
1107
+ return _this.reload();
1021
1108
  };
1022
1109
  })(this));
1110
+ return this.trigger('loading-obj', promise);
1023
1111
  };
1024
1112
 
1025
1113
  ObjCollection.prototype.loadNextPage = function() {
@@ -1042,22 +1130,52 @@
1042
1130
  };
1043
1131
 
1044
1132
  ObjCollection.prototype.destroySelectedObjs = function() {
1045
- var deferreds;
1133
+ var deferreds, promise;
1046
1134
  if (this._selectedObjs.length > 0) {
1047
1135
  deferreds = _.map(this._selectedObjs, (function(_this) {
1048
1136
  return function(objId) {
1049
- return _this.destroyById(objId);
1137
+ return _this._destroyById(objId);
1050
1138
  };
1051
1139
  })(this));
1052
- $.when.apply($, deferreds).done((function(_this) {
1140
+ promise = $.when.apply($, deferreds).done((function(_this) {
1053
1141
  return function() {
1054
1142
  return _this.reload();
1055
1143
  };
1056
1144
  })(this));
1057
- return this.trigger('loading-obj');
1145
+ return this.trigger('loading-obj', promise);
1058
1146
  }
1059
1147
  };
1060
1148
 
1149
+ ObjCollection.prototype.isSingleSelectionMode = function() {
1150
+ return this._selectionMode === 'single';
1151
+ };
1152
+
1153
+ ObjCollection.prototype._destroyById = function(objId) {
1154
+ return scrivito.delete_obj(objId).done((function(_this) {
1155
+ return function() {
1156
+ return _this._removeObjFromSelectedCollection(objId);
1157
+ };
1158
+ })(this));
1159
+ };
1160
+
1161
+ ObjCollection.prototype._removeObjFromSelectedCollection = function(objId) {
1162
+ return this._selectedObjs = _.without(this._selectedObjs, objId);
1163
+ };
1164
+
1165
+ ObjCollection.prototype._getLoadingPagePromise = function() {
1166
+ return $.Deferred().always((function(_this) {
1167
+ return function() {
1168
+ return _this.trigger('end-page-load');
1169
+ };
1170
+ })(this));
1171
+ };
1172
+
1173
+ ObjCollection.prototype._resetLoadingState = function() {
1174
+ var _ref;
1175
+ this._nextQuery = null;
1176
+ return (_ref = this._isLoadingPagePromise) != null ? _ref.resolve() : void 0;
1177
+ };
1178
+
1061
1179
  ObjCollection.prototype._initialLoadObjs = function(query, promise, queryNumber) {
1062
1180
  return query.load_batch().then((function(_this) {
1063
1181
  return function(results, next) {
@@ -1262,7 +1380,8 @@
1262
1380
  var query;
1263
1381
  query = this._baseQuery;
1264
1382
  query = this._addFilterQueries(query);
1265
- return query = this._addSearchTermQuery(query);
1383
+ query = this._addSearchTermQuery(query);
1384
+ return query = this._sortQuery(query);
1266
1385
  };
1267
1386
 
1268
1387
  QueryBuilder.prototype._addFilterQueries = function(baseQuery) {
@@ -1279,6 +1398,18 @@
1279
1398
  return combinedQuery;
1280
1399
  };
1281
1400
 
1401
+ QueryBuilder.prototype._sortQuery = function(query) {
1402
+ if (query != null) {
1403
+ query = query.order(this.filter.sortCriteria.type());
1404
+ if (this.filter.sortCriteria.isReverse()) {
1405
+ if (!query.orderReversed) {
1406
+ query.reverse_order();
1407
+ }
1408
+ }
1409
+ }
1410
+ return query;
1411
+ };
1412
+
1282
1413
  QueryBuilder.prototype._addSearchTermQuery = function(query) {
1283
1414
  var searchQuery;
1284
1415
  if (this.filter.searchTerm && this.filter.searchTerm.length > 0) {
@@ -1291,6 +1422,8 @@
1291
1422
 
1292
1423
  QueryBuilder.prototype._buildActiveChildrenSearchQuery = function(activeConfig) {
1293
1424
  if (activeConfig.hasQuery()) {
1425
+ activeConfig.query().query().order = void 0;
1426
+ activeConfig.query().query().reverse_order = void 0;
1294
1427
  return activeConfig.query();
1295
1428
  } else {
1296
1429
  return this._buildFOVQuery(activeConfig);
@@ -1316,7 +1449,7 @@
1316
1449
  })();
1317
1450
 
1318
1451
  models.QueryBuilder.prepareQuery = function(query) {
1319
- return query.clone().format('content_browser').order('_last_changed').reverse_order().batch_size(24);
1452
+ return query.clone().format('content_browser').batch_size(24);
1320
1453
  };
1321
1454
 
1322
1455
  models.QueryBuilder.byId = function(ids) {
@@ -1374,6 +1507,69 @@
1374
1507
 
1375
1508
  })(models.FilterNode);
1376
1509
 
1510
+ models.SortCriteria = (function() {
1511
+ function SortCriteria(type, reverse, activeElement, activeSortItemGroupTitle) {
1512
+ if (reverse == null) {
1513
+ reverse = true;
1514
+ }
1515
+ if (type == null) {
1516
+ type = "_last_changed";
1517
+ }
1518
+ if (activeElement == null) {
1519
+ activeElement = "Last change: latest first";
1520
+ }
1521
+ if (activeSortItemGroupTitle == null) {
1522
+ activeSortItemGroupTitle = "Sort by date";
1523
+ }
1524
+ this._activeSortItemGroupTitle = activeSortItemGroupTitle;
1525
+ this._activeElement = activeElement;
1526
+ this._isReverse = reverse;
1527
+ this._type = type;
1528
+ }
1529
+
1530
+ SortCriteria.prototype.isReverse = function() {
1531
+ return this._isReverse;
1532
+ };
1533
+
1534
+ SortCriteria.prototype.type = function() {
1535
+ return this._type;
1536
+ };
1537
+
1538
+ SortCriteria.prototype.activeElement = function() {
1539
+ return this._activeElement;
1540
+ };
1541
+
1542
+ SortCriteria.prototype.activeSortItemGroupTitle = function() {
1543
+ return this._activeSortItemGroupTitle;
1544
+ };
1545
+
1546
+ SortCriteria.prototype.equals = function(sortCriteria) {
1547
+ return sortCriteria.type() === this._type && sortCriteria.isReverse() === this._isReverse;
1548
+ };
1549
+
1550
+ return SortCriteria;
1551
+
1552
+ })();
1553
+
1554
+ models.SortMenuItem = (function(_super) {
1555
+ __extends(SortMenuItem, _super);
1556
+
1557
+ function SortMenuItem(group) {
1558
+ this.group = group;
1559
+ }
1560
+
1561
+ SortMenuItem.prototype.setActive = function() {
1562
+ return this.group.activate(this);
1563
+ };
1564
+
1565
+ SortMenuItem.prototype.isActive = function() {
1566
+ return !!this.active;
1567
+ };
1568
+
1569
+ return SortMenuItem;
1570
+
1571
+ })(models.Listenable);
1572
+
1377
1573
  models.TreeFilter = (function(_super) {
1378
1574
  __extends(TreeFilter, _super);
1379
1575
 
@@ -1456,65 +1652,6 @@
1456
1652
 
1457
1653
  })(models.Listenable);
1458
1654
 
1459
- models.AlertBody = React.createClass({
1460
- displayName: 'AlertBody',
1461
- render: function() {
1462
- return React.createElement("div", {
1463
- "className": "scrivito_modal_body"
1464
- }, this.props.body);
1465
- }
1466
- });
1467
-
1468
- models.AlertHeader = React.createClass({
1469
- displayName: 'AlertHeader',
1470
- render: function() {
1471
- return React.createElement("div", {
1472
- "className": "scrivito_modal_header"
1473
- }, React.createElement("i", {
1474
- "className": "scrivito_icon scrivito_icon_error"
1475
- }), React.createElement("h3", {
1476
- "className": "scrivito_title"
1477
- }, this.props.title), (this.props.subtitle ? React.createElement("p", {
1478
- "className": "scrivito_description"
1479
- }, this.props.subtitle) : void 0));
1480
- }
1481
- });
1482
-
1483
- models.AlertApp = React.createClass({
1484
- displayName: 'AlertApp',
1485
- alertClassName: function() {
1486
- return "scrivito_prompt_dialog scrivito_center_dialog scrivito_modal_prompt scrivito_show scrivito_red";
1487
- },
1488
- closeAlert: function(event) {
1489
- event.preventDefault();
1490
- React.unmountComponentAtNode(this.props.container);
1491
- return this.props.container.remove();
1492
- },
1493
- render: function() {
1494
- return React.createElement("div", null, React.createElement("div", {
1495
- "className": "scrivito_overlay two scrivito_show",
1496
- "style": {
1497
- zIndex: 4444444
1498
- }
1499
- }), React.createElement("div", {
1500
- "className": this.alertClassName(),
1501
- "style": {
1502
- zIndex: 4444444
1503
- }
1504
- }, React.createElement(models.AlertHeader, {
1505
- "title": this.props.title,
1506
- "subtitle": this.props.subtitle
1507
- }), React.createElement(models.AlertBody, {
1508
- "body": this.props.body
1509
- }), React.createElement("div", {
1510
- "className": "scrivito_modal_footer"
1511
- }, React.createElement("a", {
1512
- "className": "scrivito_button scrivito_cancel",
1513
- "onClick": this.closeAlert
1514
- }, "Close"))));
1515
- }
1516
- });
1517
-
1518
1655
  ui.App = React.createClass({
1519
1656
  displayName: 'App',
1520
1657
  updateFilter: function(filter) {
@@ -1536,7 +1673,7 @@
1536
1673
  this.refs.itemView.setState({
1537
1674
  loading: true
1538
1675
  });
1539
- return promise.then((function(_this) {
1676
+ return promise.always((function(_this) {
1540
1677
  return function() {
1541
1678
  return _this.refs.itemView.setState({
1542
1679
  loading: false
@@ -1583,6 +1720,7 @@
1583
1720
  filter: this.props.initialFilter,
1584
1721
  objs: [],
1585
1722
  viewMode: new models.ViewMode(),
1723
+ sortCriteria: this.props.initialFilter.sortCriteria,
1586
1724
  addedObjsCollection: new models.AddedObjsCollection(basePreset),
1587
1725
  objCollection: new models.ObjCollection(initialSelection, selectionMode),
1588
1726
  inspector: new models.Inspector()
@@ -1597,6 +1735,7 @@
1597
1735
  "className": "scrivito-content-browser-wrapper"
1598
1736
  }, React.createElement(ui.TopBar, {
1599
1737
  "filter": this.state.filter,
1738
+ "sortCriteria": this.state.sortCriteria,
1600
1739
  "viewMode": this.state.viewMode
1601
1740
  }), React.createElement(ui.Filter, {
1602
1741
  "ref": "filterView",
@@ -1613,7 +1752,8 @@
1613
1752
  }), React.createElement(ui.MoreItemsSpinner, {
1614
1753
  "objCollection": this.state.objCollection
1615
1754
  })), React.createElement(ui.Inspector, {
1616
- "inspector": this.state.inspector
1755
+ "inspector": this.state.inspector,
1756
+ "objCollection": this.state.objCollection
1617
1757
  })), React.createElement(ui.Footer, {
1618
1758
  "promise": this.props.promise,
1619
1759
  "objCollection": this.state.objCollection
@@ -1621,6 +1761,86 @@
1621
1761
  }
1622
1762
  });
1623
1763
 
1764
+ models.DialogBody = React.createClass({
1765
+ displayName: 'DialogBody',
1766
+ render: function() {
1767
+ return React.createElement("div", {
1768
+ "className": "scrivito_modal_body"
1769
+ }, this.props.body);
1770
+ }
1771
+ });
1772
+
1773
+ models.DialogHeader = React.createClass({
1774
+ displayName: 'DialogHeader',
1775
+ render: function() {
1776
+ return React.createElement("div", {
1777
+ "className": "scrivito_modal_header"
1778
+ }, React.createElement("i", {
1779
+ "className": "scrivito_icon scrivito_icon_error"
1780
+ }), React.createElement("h3", {
1781
+ "className": "scrivito_title"
1782
+ }, this.props.title), (this.props.subtitle ? React.createElement("p", {
1783
+ "className": "scrivito_description"
1784
+ }, this.props.subtitle) : void 0));
1785
+ }
1786
+ });
1787
+
1788
+ models.DialogApp = React.createClass({
1789
+ displayName: 'DialogApp',
1790
+ dialogClassName: function() {
1791
+ return "scrivito_prompt_dialog scrivito_center_dialog scrivito_modal_prompt scrivito_show scrivito_red";
1792
+ },
1793
+ showConfirmButton: function() {
1794
+ return this.props.mode === "confirm";
1795
+ },
1796
+ closeButtonText: function() {
1797
+ if (this.showConfirmButton()) {
1798
+ return "Cancel";
1799
+ } else {
1800
+ return "Close";
1801
+ }
1802
+ },
1803
+ resolveAndClose: function(event) {
1804
+ this.props.promise.resolve();
1805
+ return this.closeDialog(event);
1806
+ },
1807
+ rejectAndClose: function(event) {
1808
+ this.props.promise.reject();
1809
+ return this.closeDialog(event);
1810
+ },
1811
+ closeDialog: function(event) {
1812
+ event.preventDefault();
1813
+ React.unmountComponentAtNode(this.props.container);
1814
+ return this.props.container.remove();
1815
+ },
1816
+ render: function() {
1817
+ return React.createElement("div", null, React.createElement("div", {
1818
+ "className": "scrivito_overlay two scrivito_show",
1819
+ "style": {
1820
+ zIndex: 4444444
1821
+ }
1822
+ }), React.createElement("div", {
1823
+ "className": this.dialogClassName(),
1824
+ "style": {
1825
+ zIndex: 4444444
1826
+ }
1827
+ }, React.createElement(models.DialogHeader, {
1828
+ "title": this.props.title,
1829
+ "subtitle": this.props.subtitle
1830
+ }), React.createElement(models.DialogBody, {
1831
+ "body": this.props.body
1832
+ }), React.createElement("div", {
1833
+ "className": "scrivito_modal_footer"
1834
+ }, React.createElement("a", {
1835
+ "className": "scrivito_button scrivito_cancel",
1836
+ "onClick": this.rejectAndClose
1837
+ }, this.closeButtonText()), (this.showConfirmButton() ? React.createElement("a", {
1838
+ "className": "scrivito_button scrivito_red scrivito_confirm",
1839
+ "onClick": this.resolveAndClose
1840
+ }, "Confirm") : void 0))));
1841
+ }
1842
+ });
1843
+
1624
1844
  ui.Filter = React.createClass({
1625
1845
  displayName: 'Filter',
1626
1846
  mixins: [FilterMixin],
@@ -1877,6 +2097,14 @@
1877
2097
  currentSelectedCount: function() {
1878
2098
  return this.props.objCollection.selectedObjs().length;
1879
2099
  },
2100
+ deleteButtonClass: function() {
2101
+ var className;
2102
+ className = ' scrivito_button scrivito_lightgrey content-browser-delete scrivito_left';
2103
+ if (this.currentSelectedCount() === 0) {
2104
+ className += ' scrivito_disabled';
2105
+ }
2106
+ return className;
2107
+ },
1880
2108
  cancelClick: function() {
1881
2109
  return this.props.promise.reject();
1882
2110
  },
@@ -1884,13 +2112,24 @@
1884
2112
  return this.props.promise.resolve(this.props.objCollection.selectedObjs());
1885
2113
  },
1886
2114
  deleteClick: function() {
1887
- return this.props.objCollection.destroySelectedObjs();
2115
+ var objectsToBeDeleted;
2116
+ if (this.currentSelectedCount() > 0) {
2117
+ objectsToBeDeleted = this.currentSelectedCount() === 1 ? "one CMS object" : "" + (this.currentSelectedCount()) + " CMS objects";
2118
+ return scrivito.content_browser._showConfirm({
2119
+ title: 'Really delete the selected items?',
2120
+ subtitle: "This will delete " + objectsToBeDeleted + ". Objects that were created in this working copy cannot be restored."
2121
+ }).then((function(_this) {
2122
+ return function() {
2123
+ return _this.props.objCollection.destroySelectedObjs();
2124
+ };
2125
+ })(this));
2126
+ }
1888
2127
  },
1889
2128
  render: function() {
1890
2129
  return React.createElement("div", {
1891
2130
  "className": "scrivito-content-browser-footer"
1892
2131
  }, React.createElement("a", {
1893
- "className": "scrivito_button scrivito_lightgrey content-browser-delete",
2132
+ "className": this.deleteButtonClass(),
1894
2133
  "onClick": this.deleteClick
1895
2134
  }, "Delete", React.createElement("span", {
1896
2135
  "className": "scrivito-content-browser-counter selected-total"
@@ -1920,15 +2159,31 @@
1920
2159
  "className": "scrivito_icon scrivito_icon_generic"
1921
2160
  }), "No edit view available."));
1922
2161
  },
2162
+ _deleteInspectedObj: function() {
2163
+ return scrivito.content_browser._showConfirm({
2164
+ title: React.createElement("span", null, "Really delete ", React.createElement("q", null, this.props.inspector.fileDetail()), "?"),
2165
+ subtitle: 'Objects that were created in this working copy cannot be restored.'
2166
+ }).then((function(_this) {
2167
+ return function() {
2168
+ _this.props.objCollection.destroyObj(_this.props.inspector.getInspectedObj());
2169
+ return _this.props.inspector.setInspectedObj(void 0);
2170
+ };
2171
+ })(this));
2172
+ },
1923
2173
  render: function() {
1924
2174
  return React.createElement("div", {
1925
2175
  "className": "scrivito-content-browser-inspector"
1926
- }, (this.props.inspector.inspectorUrl() != null ? React.createElement("div", null, React.createElement("h3", null, React.createElement("span", {
2176
+ }, (this.props.inspector.inspectorUrl() != null ? React.createElement("div", null, React.createElement("h3", {
2177
+ "title": this.props.inspector.fileDetail()
2178
+ }, React.createElement("span", {
1927
2179
  "title": "Details",
1928
2180
  "className": this.getDetailsClassName()
1929
2181
  }), React.createElement("span", {
1930
2182
  "className": "title"
1931
- }, this.props.inspector.fileDetail())), React.createElement("div", {
2183
+ }, this.props.inspector.fileDetail()), React.createElement("span", {
2184
+ "className": "scrivito_icon scrivito_icon_trash scrivito_delete",
2185
+ "onClick": this._deleteInspectedObj
2186
+ })), React.createElement("div", {
1932
2187
  "className": "inspector-content"
1933
2188
  }, (this.props.inspector.getInspectedObj().hasDetailsView() ? React.createElement("iframe", {
1934
2189
  "src": this.props.inspector.inspectorUrl(),
@@ -1950,8 +2205,20 @@
1950
2205
  "uploader-drag-over": this.state.dragInProgres
1951
2206
  });
1952
2207
  },
2208
+ _showConflictingPresetsAlert: function(errors) {
2209
+ var message;
2210
+ message = React.createElement("div", null, "Please select only one of the following options,\nthen try again:", _.map(errors, function(values, field) {
2211
+ return React.createElement("div", null, React.createElement("h4", null, field), React.createElement("ul", null, _.map(values, function(value) {
2212
+ return React.createElement("li", null, value);
2213
+ })));
2214
+ }));
2215
+ return scrivito.content_browser._showAlert({
2216
+ title: 'The selected filter options cannot be applied to the file(s) you wanted to upload',
2217
+ body: React.createElement("div", null, message)
2218
+ });
2219
+ },
1953
2220
  uploadFiles: function(event) {
1954
- var dataTransfer, files, message, preset;
2221
+ var dataTransfer, files, preset;
1955
2222
  this.changeDragState(false)(event);
1956
2223
  dataTransfer = event.dataTransfer;
1957
2224
  if (dataTransfer == null) {
@@ -1963,11 +2230,7 @@
1963
2230
  if (preset.isValid()) {
1964
2231
  return this.props.addedObjsCollection.addFiles(files, preset.values());
1965
2232
  } else {
1966
- message = 'The selected filter options cannot be applied to the file(s) you wanted to upload. Please select only one of the following options, then try again:\n';
1967
- _.each(preset.errors(), function(values, field) {
1968
- return message += "\n" + field + ": " + (values.join(', '));
1969
- });
1970
- return alert(message);
2233
+ return this._showConflictingPresetsAlert(preset.errors());
1971
2234
  }
1972
2235
  }
1973
2236
  },
@@ -2002,7 +2265,9 @@
2002
2265
  }) : this.props.viewMode.isList() ? React.createElement(ui.TableView, {
2003
2266
  "objCollection": this.props.objCollection,
2004
2267
  "toggleSelected": this.props.toggleSelected,
2005
- "inspector": this.props.inspector
2268
+ "filter": this.props.filter,
2269
+ "inspector": this.props.inspector,
2270
+ "addedObjsCollection": this.props.addedObjsCollection
2006
2271
  }) : React.createElement(ui.ThumbnailItems, {
2007
2272
  "objCollection": this.props.objCollection,
2008
2273
  "viewMode": this.props.viewMode.getMode(),
@@ -2046,50 +2311,107 @@
2046
2311
  }
2047
2312
  });
2048
2313
 
2049
- ui.ResizeItem = React.createClass({
2050
- displayName: 'ResizeItem',
2051
- resizeButtonsData: {
2052
- "large": {
2053
- iconTitle: "Large thumbnails",
2054
- iconClassName: "scrivito_icon_th_large"
2055
- },
2056
- "big": {
2057
- iconTitle: "Big thumbnails",
2058
- iconClassName: "scrivito_icon_th"
2059
- },
2060
- "normal": {
2061
- iconTitle: "Thumbnails",
2062
- iconClassName: "scrivito_icon_th_medium"
2063
- },
2064
- "small": {
2065
- iconTitle: "Small thumbnails",
2066
- iconClassName: "scrivito_icon_th_small"
2314
+ ui.SortMenu = React.createClass({
2315
+ displayName: 'SortMenu',
2316
+ sortItemsData: {
2317
+ "date": {
2318
+ itemTitle: "Sort by date",
2319
+ descCriteriaTitle: "Last change: latest first",
2320
+ ascCriteriaTitle: "Last change: oldest first",
2321
+ sortItemType: "_last_changed"
2067
2322
  }
2068
2323
  },
2069
- getIconClassName: function(size) {
2070
- return "scrivito_icon " + this.resizeButtonsData[size].iconClassName;
2071
- },
2072
- getIconTitle: function(size) {
2073
- return this.resizeButtonsData[size].iconTitle;
2074
- },
2075
- getLabelClasses: function() {
2076
- return classSet({
2077
- 'active': this.props.viewMode.getMode() === this.props.size,
2078
- "editing-button-view": true
2079
- });
2324
+ toggleSortMenu: function() {
2325
+ return $('.scrivito_menu_box').fadeToggle();
2080
2326
  },
2081
- changeViewMode: function() {
2082
- return this.props.viewMode.setMode(this.props.size);
2327
+ getSortIconClassName: function() {
2328
+ var sortIcon;
2329
+ sortIcon = "scrivito_icon ";
2330
+ if (this.props.filter.sortCriteria.isReverse()) {
2331
+ sortIcon += "scrivito_icon_sort_up";
2332
+ } else {
2333
+ sortIcon += "scrivito_icon_sort_down";
2334
+ }
2335
+ return sortIcon;
2083
2336
  },
2084
2337
  render: function() {
2338
+ var sortItem;
2085
2339
  return React.createElement("span", {
2086
- "data-size": this.props.size,
2087
- "className": this.getLabelClasses(),
2088
- "onClick": this.changeViewMode
2340
+ "className": "scrivito_button scrivito_lightgrey scrivito_right",
2341
+ "onClick": this.toggleSortMenu
2089
2342
  }, React.createElement("i", {
2090
- "title": this.getIconTitle(this.props.size),
2091
- "className": this.getIconClassName(this.props.size)
2092
- }));
2343
+ "className": this.getSortIconClassName()
2344
+ }), this.props.filter.sortCriteria.activeElement(), React.createElement("i", {
2345
+ "className": "scrivito_icon scrivito-content-browser-menu-icon scrivito_icon_chevron_down"
2346
+ }), React.createElement("ul", {
2347
+ "className": "scrivito_menu_box scrivito_right"
2348
+ }, (function() {
2349
+ var _i, _len, _ref, _results;
2350
+ _ref = Object.keys(this.sortItemsData);
2351
+ _results = [];
2352
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
2353
+ sortItem = _ref[_i];
2354
+ _results.push(React.createElement(ui.SortMenuItem, {
2355
+ "filter": this.props.filter,
2356
+ "sortItem": this.sortItemsData[sortItem]
2357
+ }));
2358
+ }
2359
+ return _results;
2360
+ }).call(this)));
2361
+ }
2362
+ });
2363
+
2364
+ ui.SortMenuItem = React.createClass({
2365
+ displayName: 'SortMenuItem',
2366
+ basicIcon: "scrivito_icon ",
2367
+ _ascIconSortClass: function() {
2368
+ return this.basicIcon + "scrivito_icon_sort_down";
2369
+ },
2370
+ _descIconSortClass: function() {
2371
+ return this.basicIcon + "scrivito_icon_sort_up";
2372
+ },
2373
+ getSortLiClassName: function(activeElement) {
2374
+ var itemIcon;
2375
+ itemIcon = "scrivito_menu_item";
2376
+ if (this.props.filter.sortCriteria.activeElement() === activeElement) {
2377
+ itemIcon += " active";
2378
+ }
2379
+ return itemIcon;
2380
+ },
2381
+ _getAscSortLiClassName: function() {
2382
+ return this.getSortLiClassName(this.currentSortItem().ascCriteriaTitle);
2383
+ },
2384
+ _getDescSortLiClassName: function() {
2385
+ return this.getSortLiClassName(this.currentSortItem().descCriteriaTitle);
2386
+ },
2387
+ currentSortItem: function() {
2388
+ return this.props.sortItem;
2389
+ },
2390
+ _changeSortCriteria: function(reverse, activeItemElement) {
2391
+ var sortCriteria;
2392
+ sortCriteria = new models.SortCriteria(this.currentSortItem().sortItemType, reverse, activeItemElement, this.currentSortItem().itemTitle);
2393
+ return this.props.filter.setSortCriteria(sortCriteria);
2394
+ },
2395
+ _sortInAscOrder: function() {
2396
+ return this._changeSortCriteria(false, this.currentSortItem().ascCriteriaTitle);
2397
+ },
2398
+ _sortInDescOrder: function() {
2399
+ return this._changeSortCriteria(true, this.currentSortItem().descCriteriaTitle);
2400
+ },
2401
+ render: function() {
2402
+ return React.createElement("div", null, React.createElement("li", {
2403
+ "className": "scrivito_menu_separator"
2404
+ }, React.createElement("span", null, (this.currentSortItem().itemTitle))), React.createElement("li", {
2405
+ "className": this._getDescSortLiClassName(),
2406
+ "onClick": this._sortInDescOrder
2407
+ }, React.createElement("span", null, React.createElement("i", {
2408
+ "className": this._descIconSortClass()
2409
+ }, " "), (this.currentSortItem().descCriteriaTitle))), React.createElement("li", {
2410
+ "className": this._getAscSortLiClassName(),
2411
+ "onClick": this._sortInAscOrder
2412
+ }, React.createElement("span", null, React.createElement("i", {
2413
+ "className": this._ascIconSortClass()
2414
+ }, " "), (this.currentSortItem().ascCriteriaTitle))));
2093
2415
  }
2094
2416
  });
2095
2417
 
@@ -2103,6 +2425,24 @@
2103
2425
  }
2104
2426
  });
2105
2427
 
2428
+ ui.TableViewAddItem = React.createClass({
2429
+ mixins: [AddItemMixin],
2430
+ render: function() {
2431
+ return React.createElement("tr", {
2432
+ "onClick": this.createClick
2433
+ }, React.createElement("td", {
2434
+ "colSpan": "6"
2435
+ }, React.createElement("div", {
2436
+ "className": this.itemClassName()
2437
+ }, React.createElement("div", {
2438
+ "className": "scrivito-content-browser-text"
2439
+ }, React.createElement("span", {
2440
+ "className": this.iconClassName(),
2441
+ "title": this.iconTitle()
2442
+ }), React.createElement("span", null, this.textMessage())))));
2443
+ }
2444
+ });
2445
+
2106
2446
  ui.TableViewContent = React.createClass({
2107
2447
  mixins: [InfiniteScrollMixin],
2108
2448
  getTableViewItems: function() {
@@ -2121,10 +2461,16 @@
2121
2461
  getElementDOMNode: function() {
2122
2462
  return this.getDOMNode();
2123
2463
  },
2464
+ objCreation: function() {
2465
+ return new models.ObjCreation(this.props.filter);
2466
+ },
2124
2467
  render: function() {
2125
2468
  return React.createElement("div", {
2126
2469
  "className": "scrivito-content-browser-list-content"
2127
- }, React.createElement("table", null, React.createElement("tbody", null, this.getTableViewItems())));
2470
+ }, React.createElement("table", null, React.createElement("tbody", null, (this.objCreation().showCreationItem() ? React.createElement(ui.TableViewAddItem, {
2471
+ "objCreation": this.objCreation(),
2472
+ "addedObjsCollection": this.props.addedObjsCollection
2473
+ }) : void 0), this.getTableViewItems())));
2128
2474
  }
2129
2475
  });
2130
2476
 
@@ -2137,7 +2483,7 @@
2137
2483
  getLastChangedFormatedDate: function() {
2138
2484
  var result;
2139
2485
  if (this.props.obj.lastChanged() !== void 0) {
2140
- result = moment(this.props.obj.lastChanged()).zone(this.props.obj.lastChanged());
2486
+ result = moment(this.props.obj.lastChanged()).utcOffset(this.props.obj.lastChanged());
2141
2487
  return result.format("dddd, MMMM Do YYYY, h:mm A");
2142
2488
  }
2143
2489
  },
@@ -2168,92 +2514,11 @@
2168
2514
 
2169
2515
  ui.ThumbnailAddItem = React.createClass({
2170
2516
  displayName: 'ThumbnailAddItem',
2171
- itemClassName: function() {
2172
- var className;
2173
- className = "scrivito-content-browser-add";
2174
- if (!this.props.objCreation.isActive()) {
2175
- className += " disabled";
2176
- }
2177
- return className;
2178
- },
2179
- iconClassName: function() {
2180
- var iconClass;
2181
- iconClass = this.props.objCreation.isActive() ? "scrivito_icon_plus" : "scrivito_icon_disabled";
2182
- return "scrivito_icon " + iconClass;
2183
- },
2184
- creationNotPossibleBody: function(error) {
2185
- return React.createElement("ul", null, _.map(error.nodeTitles, function(title) {
2186
- return React.createElement("li", null, title);
2187
- }));
2188
- },
2189
- presetConflictBody: function(error) {
2190
- return React.createElement("div", null, "The selected filter options cannot be applied to the file(s)\nyou wanted to upload. Please select only one of the following options,\nthen try again:\n", _.map(error.fields, function(values, field) {
2191
- return React.createElement("div", null, React.createElement("h4", null, field), React.createElement("ul", null, _.map(values, function(value) {
2192
- return React.createElement("li", null, value);
2193
- })));
2194
- }));
2195
- },
2196
- showErrorAlert: function(error) {
2197
- var alertProps;
2198
- alertProps = (function() {
2199
- switch (error.type) {
2200
- case 'creation_not_possible':
2201
- return {
2202
- subtitle: 'Creation of items matching the selected filters has been disabled.',
2203
- body: this.creationNotPossibleBody(error)
2204
- };
2205
- case 'obj_class_not_provided':
2206
- return {
2207
- subtitle: "Configuration error: No '_obj_class' provided."
2208
- };
2209
- case 'preset_conflict':
2210
- return {
2211
- body: this.presetConflictBody(error)
2212
- };
2213
- }
2214
- }).call(this);
2215
- alertProps.title = "Creation not possible";
2216
- return scrivito.content_browser._showAlert(alertProps);
2217
- },
2218
- buildErrorMessage: function(error) {
2219
- var message, nodesString;
2220
- switch (error.type) {
2221
- case 'creation_not_possible':
2222
- nodesString = error.nodeTitles.join(', ');
2223
- return "The selected filter options " + nodesString + " prevent the creation";
2224
- case 'obj_class_not_provided':
2225
- return "Configuration error: No '_obj_class' provided";
2226
- case 'preset_conflict':
2227
- message = 'The selected filter options cannot be applied to the file(s) you wanted to upload. Please select only one of the following options, then try again:\n';
2228
- _.each(error.fields, function(value, field) {
2229
- return message += "" + field + ": " + (value.join(', ')) + "\n";
2230
- });
2231
- return message;
2232
- }
2233
- },
2234
- iconTitle: function() {
2235
- if (!this.props.objCreation.isActive()) {
2236
- return this.buildErrorMessage(this.props.objCreation.error());
2237
- }
2238
- },
2239
- textMessage: function() {
2240
- if (this.props.objCreation.isActive()) {
2241
- return "Create Item";
2242
- } else {
2243
- return "Item creation not possible";
2244
- }
2245
- },
2246
- handleClick: function() {
2247
- if (this.props.objCreation.isActive()) {
2248
- return this.props.addedObjsCollection.createObj(this.props.objCreation.preset());
2249
- } else {
2250
- return this.showErrorAlert(this.props.objCreation.error());
2251
- }
2252
- },
2517
+ mixins: [AddItemMixin],
2253
2518
  render: function() {
2254
2519
  return React.createElement("li", {
2255
2520
  "className": "content-browser-item",
2256
- "onClick": this.handleClick
2521
+ "onClick": this.createClick
2257
2522
  }, React.createElement("div", {
2258
2523
  "className": this.itemClassName()
2259
2524
  }, React.createElement("div", {
@@ -2412,6 +2677,8 @@
2412
2677
  "onClick": this.setSearchTerm
2413
2678
  }, "Search")), React.createElement(ui.ViewModeBar, {
2414
2679
  "viewMode": this.props.viewMode
2680
+ }), React.createElement(ui.SortMenu, {
2681
+ "filter": this.props.filter
2415
2682
  }));
2416
2683
  }
2417
2684
  });