mirror of
https://github.com/flarum/core.git
synced 2025-07-19 15:51:16 +02:00
Big component restructure/overhaul
This commit is contained in:
@@ -1,18 +0,0 @@
|
|||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
export default Ember.View.extend({
|
|
||||||
title: '',
|
|
||||||
icon: '',
|
|
||||||
class: '',
|
|
||||||
action: null,
|
|
||||||
|
|
||||||
tagName: 'a',
|
|
||||||
classNames: ['btn'],
|
|
||||||
classNameBindings: ['class', 'disabled'],
|
|
||||||
|
|
||||||
layout: Ember.Handlebars.compile('{{#if view.icon}}{{fa-icon view.icon class="fa-fw"}} {{/if}}<span class="label">{{view.title}}</span>'),
|
|
||||||
|
|
||||||
click: function() {
|
|
||||||
this.action();
|
|
||||||
}
|
|
||||||
});
|
|
@@ -1,55 +0,0 @@
|
|||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
import Menu from '../utils/menu';
|
|
||||||
import MenuItem from '../components/menu-item';
|
|
||||||
|
|
||||||
export default Ember.View.extend({
|
|
||||||
tagName: 'article',
|
|
||||||
templateName: 'discussion-post',
|
|
||||||
|
|
||||||
controls: null,
|
|
||||||
|
|
||||||
contentComponent: function() {
|
|
||||||
return 'post-type-'+this.get('post.type');
|
|
||||||
}.property('post.type'),
|
|
||||||
|
|
||||||
classNames: ['post'],
|
|
||||||
classNameBindings: ['post.deleted', 'post.edited'],
|
|
||||||
|
|
||||||
construct: function() {
|
|
||||||
this.set('controls', Menu.create());
|
|
||||||
|
|
||||||
var post = this.get('post');
|
|
||||||
|
|
||||||
if (post.get('deleted')) {
|
|
||||||
this.addControl('restore', 'Restore', 'reply', 'canEdit');
|
|
||||||
this.addControl('delete', 'Delete', 'times', 'canDelete');
|
|
||||||
} else {
|
|
||||||
if (post.get('type') == 'comment') {
|
|
||||||
this.addControl('edit', 'Edit', 'pencil', 'canEdit');
|
|
||||||
this.addControl('hide', 'Delete', 'times', 'canEdit');
|
|
||||||
} else {
|
|
||||||
this.addControl('delete', 'Delete', 'times', 'canDelete');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.on('init'),
|
|
||||||
|
|
||||||
didInsertElement: function() {
|
|
||||||
this.$().hide().fadeIn('slow');
|
|
||||||
},
|
|
||||||
|
|
||||||
addControl: function(tag, title, icon, permissionAttribute) {
|
|
||||||
if (permissionAttribute && ! this.get('post').get(permissionAttribute)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var self = this;
|
|
||||||
var action = function(post) {
|
|
||||||
self.get('controller').send(actionName, post);
|
|
||||||
};
|
|
||||||
|
|
||||||
var item = MenuItem.extend({title: title, icon: icon, action: action});
|
|
||||||
this.get('controls').addItem(tag, item);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
@@ -1,12 +1,12 @@
|
|||||||
|
|
||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
import Menu from '../utils/menu';
|
|
||||||
import MenuItem from '../components/menu-item';
|
|
||||||
|
|
||||||
export default Ember.View.extend({
|
import TaggedArray from '../../utils/tagged-array';
|
||||||
|
import ActionButton from '../ui/controls/action-button';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
|
||||||
_init: function() {
|
_init: function() {
|
||||||
this.set('controls', Menu.create());
|
// this.set('controls', Menu.create());
|
||||||
}.on('init'),
|
}.on('init'),
|
||||||
|
|
||||||
tagName: 'li',
|
tagName: 'li',
|
||||||
@@ -18,7 +18,7 @@ export default Ember.View.extend({
|
|||||||
'discussion.following:following',
|
'discussion.following:following',
|
||||||
'active'
|
'active'
|
||||||
],
|
],
|
||||||
templateName: 'discussions-result',
|
templateName: 'components/discussions/discussion-listing',
|
||||||
|
|
||||||
active: function() {
|
active: function() {
|
||||||
return this.get('childViews').anyBy('active');
|
return this.get('childViews').anyBy('active');
|
55
framework/core/ember/app/components/discussions/post.js
Normal file
55
framework/core/ember/app/components/discussions/post.js
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
import TaggedArray from '../../utils/tagged-array';
|
||||||
|
import ActionButton from '../ui/controls/action-button';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
tagName: 'article',
|
||||||
|
templateName: 'components/discussions/post',
|
||||||
|
|
||||||
|
// controls: null,
|
||||||
|
|
||||||
|
contentComponent: function() {
|
||||||
|
return 'discussions/post-'+this.get('post.type');
|
||||||
|
}.property('post.type'),
|
||||||
|
|
||||||
|
classNames: ['post'],
|
||||||
|
classNameBindings: ['post.deleted', 'post.edited'],
|
||||||
|
|
||||||
|
construct: function() {
|
||||||
|
// this.set('controls', Menu.create());
|
||||||
|
|
||||||
|
// var post = this.get('post');
|
||||||
|
|
||||||
|
// if (post.get('deleted')) {
|
||||||
|
// this.addControl('restore', 'Restore', 'reply', 'canEdit');
|
||||||
|
// this.addControl('delete', 'Delete', 'times', 'canDelete');
|
||||||
|
// } else {
|
||||||
|
// if (post.get('type') == 'comment') {
|
||||||
|
// this.addControl('edit', 'Edit', 'pencil', 'canEdit');
|
||||||
|
// this.addControl('hide', 'Delete', 'times', 'canEdit');
|
||||||
|
// } else {
|
||||||
|
// this.addControl('delete', 'Delete', 'times', 'canDelete');
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}.on('init'),
|
||||||
|
|
||||||
|
didInsertElement: function() {
|
||||||
|
this.$().hide().fadeIn('slow');
|
||||||
|
},
|
||||||
|
|
||||||
|
addControl: function(tag, title, icon, permissionAttribute) {
|
||||||
|
if (permissionAttribute && ! this.get('post').get(permissionAttribute)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
var action = function(post) {
|
||||||
|
self.get('controller').send(actionName, post);
|
||||||
|
};
|
||||||
|
|
||||||
|
var item = MenuItem.extend({title: title, icon: icon, action: action});
|
||||||
|
this.get('controls').addItem(tag, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
@@ -4,7 +4,7 @@ import Ember from 'ember';
|
|||||||
// single item may represent a single post, or it may represent a gap of many
|
// single item may represent a single post, or it may represent a gap of many
|
||||||
// posts which have not been loaded.
|
// posts which have not been loaded.
|
||||||
|
|
||||||
export default Ember.View.extend({
|
export default Ember.Component.extend({
|
||||||
classNames: ['item'],
|
classNames: ['item'],
|
||||||
classNameBindings: ['item.gap:gap', 'loading', 'direction'],
|
classNameBindings: ['item.gap:gap', 'loading', 'direction'],
|
||||||
attributeBindings: [
|
attributeBindings: [
|
@@ -1,8 +1,7 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
import MenuItem from '../components/menu-item';
|
import Scrollbar from '../../utils/scrollbar';
|
||||||
import Scrollbar from '../utils/scrollbar';
|
import PostStreamMixin from '../../mixins/post-stream';
|
||||||
import PostStreamMixin from '../mixins/post-stream';
|
|
||||||
|
|
||||||
export default Ember.View.extend(PostStreamMixin, {
|
export default Ember.View.extend(PostStreamMixin, {
|
||||||
|
|
||||||
@@ -10,7 +9,7 @@ export default Ember.View.extend(PostStreamMixin, {
|
|||||||
@property templateName
|
@property templateName
|
||||||
@type String
|
@type String
|
||||||
*/
|
*/
|
||||||
templateName: 'components/discussion-scrollbar',
|
templateName: 'components/discussions/stream-scrollbar',
|
||||||
classNames: ['scrubber', 'discussion-scrubber'],
|
classNames: ['scrubber', 'discussion-scrubber'],
|
||||||
|
|
||||||
// An object which represents/ecapsulates the scrollbar.
|
// An object which represents/ecapsulates the scrollbar.
|
@@ -1,37 +0,0 @@
|
|||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
import MenuItemContainer from '../components/menu-item-container';
|
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
|
||||||
items: null, // NamedContainerView/Menu
|
|
||||||
layoutName: 'components/dropdown-button',
|
|
||||||
classNames: ['dropdown', 'btn-group'],
|
|
||||||
classNameBindings: ['itemCountClass'],
|
|
||||||
|
|
||||||
title: 'Controls',
|
|
||||||
icon: 'ellipsis-v',
|
|
||||||
buttonClass: 'btn-default',
|
|
||||||
menuClass: 'pull-right',
|
|
||||||
|
|
||||||
dropdownMenuClass: function() {
|
|
||||||
return 'dropdown-menu '+this.get('menuClass');
|
|
||||||
}.property('menuClass'),
|
|
||||||
|
|
||||||
itemCountClass: function() {
|
|
||||||
return 'item-count-'+this.get('items.length');
|
|
||||||
}.property('items'),
|
|
||||||
|
|
||||||
containedItems: function() {
|
|
||||||
var contained = [];
|
|
||||||
this.get('items').forEach(function(item) {
|
|
||||||
if (item.tagName != 'li') {
|
|
||||||
contained.push(MenuItemContainer.extend({
|
|
||||||
item: item
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
contained.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return contained;
|
|
||||||
}.property('items.[]')
|
|
||||||
});
|
|
@@ -1,40 +0,0 @@
|
|||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
import MenuItemContainer from '../components/menu-item-container';
|
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
|
||||||
items: null, // NamedContainerView/Menu
|
|
||||||
layoutName: 'components/dropdown-split',
|
|
||||||
classNames: ['dropdown', 'dropdown-split', 'btn-group'],
|
|
||||||
classNameBindings: ['itemCountClass'],
|
|
||||||
|
|
||||||
buttonClass: 'btn-default',
|
|
||||||
menuClass: 'pull-right',
|
|
||||||
icon: 'ellipsis-v',
|
|
||||||
|
|
||||||
mainButtonClass: function() {
|
|
||||||
return 'btn '+this.get('buttonClass');
|
|
||||||
}.property('buttonClass'),
|
|
||||||
|
|
||||||
dropdownMenuClass: function() {
|
|
||||||
return 'dropdown-menu '+this.get('menuClass');
|
|
||||||
}.property('menuClass'),
|
|
||||||
|
|
||||||
itemCountClass: function() {
|
|
||||||
return 'item-count-'+this.get('items.length');
|
|
||||||
}.property('items'),
|
|
||||||
|
|
||||||
containedItems: function() {
|
|
||||||
var contained = [];
|
|
||||||
this.get('items').forEach(function(item) {
|
|
||||||
if (item.tagName != 'li') {
|
|
||||||
contained.push(MenuItemContainer.extend({
|
|
||||||
item: item
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
contained.push(item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return contained;
|
|
||||||
}.property('items.[]')
|
|
||||||
});
|
|
@@ -1,6 +0,0 @@
|
|||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
|
||||||
tagName: 'ul',
|
|
||||||
layoutName: 'components/item-collection',
|
|
||||||
});
|
|
@@ -1,6 +0,0 @@
|
|||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
|
||||||
tagName: 'ul',
|
|
||||||
layoutName: 'components/menu-list'
|
|
||||||
});
|
|
@@ -1,6 +1,6 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
var MenuItem = Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
title: '',
|
title: '',
|
||||||
icon: '',
|
icon: '',
|
||||||
className: '',
|
className: '',
|
||||||
@@ -8,6 +8,8 @@ var MenuItem = Ember.Component.extend({
|
|||||||
divider: false,
|
divider: false,
|
||||||
active: false,
|
active: false,
|
||||||
|
|
||||||
|
classNames: ['btn', 'btn-default'],
|
||||||
|
|
||||||
tagName: 'a',
|
tagName: 'a',
|
||||||
attributeBindings: ['href'],
|
attributeBindings: ['href'],
|
||||||
classNameBindings: ['className'],
|
classNameBindings: ['className'],
|
||||||
@@ -20,13 +22,3 @@ var MenuItem = Ember.Component.extend({
|
|||||||
this.get('action')();
|
this.get('action')();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
MenuItem.reopenClass({
|
|
||||||
separator: function() {
|
|
||||||
return this.create({
|
|
||||||
divider: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
export default MenuItem;
|
|
@@ -0,0 +1,21 @@
|
|||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
items: null, // TaggedArray
|
||||||
|
layoutName: 'components/ui/controls/dropdown-button',
|
||||||
|
classNames: ['dropdown', 'btn-group'],
|
||||||
|
classNameBindings: ['itemCountClass'],
|
||||||
|
|
||||||
|
title: 'Controls',
|
||||||
|
icon: 'ellipsis-v',
|
||||||
|
buttonClass: 'btn-default',
|
||||||
|
menuClass: 'pull-right',
|
||||||
|
|
||||||
|
dropdownMenuClass: function() {
|
||||||
|
return 'dropdown-menu '+this.get('menuClass');
|
||||||
|
}.property('menuClass'),
|
||||||
|
|
||||||
|
itemCountClass: function() {
|
||||||
|
return 'item-count-'+this.get('items.length');
|
||||||
|
}.property('items.length')
|
||||||
|
});
|
@@ -1,10 +1,8 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
import Menu from '../utils/menu';
|
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
items: [],
|
items: [],
|
||||||
layoutName: 'components/dropdown-select',
|
layoutName: 'components/ui/controls/dropdown-select',
|
||||||
classNames: ['dropdown', 'dropdown-select', 'btn-group'],
|
classNames: ['dropdown', 'dropdown-select', 'btn-group'],
|
||||||
classNameBindings: ['itemCountClass'],
|
classNameBindings: ['itemCountClass'],
|
||||||
|
|
||||||
@@ -24,7 +22,12 @@ export default Ember.Component.extend({
|
|||||||
return 'item-count-'+this.get('items.length');
|
return 'item-count-'+this.get('items.length');
|
||||||
}.property('items.length'),
|
}.property('items.length'),
|
||||||
|
|
||||||
currentItem: function() {
|
activeItem: function() {
|
||||||
return this.get('menu.childViews').findBy('active');
|
return this.get('menu.childViews').findBy('active');
|
||||||
}.property('menu.childViews.@each.active')
|
}.property('menu.childViews.@each.active')
|
||||||
|
|
||||||
|
}).reopenClass({
|
||||||
|
createWithItems: function(items) {
|
||||||
|
return this.create({items: items});
|
||||||
|
}
|
||||||
});
|
});
|
@@ -0,0 +1,16 @@
|
|||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
import DropdownButton from './dropdown-button';
|
||||||
|
|
||||||
|
export default DropdownButton.extend({
|
||||||
|
layoutName: 'components/ui/controls/dropdown-split',
|
||||||
|
classNames: ['dropdown', 'dropdown-split', 'btn-group'],
|
||||||
|
|
||||||
|
mainButtonClass: function() {
|
||||||
|
return 'btn '+this.get('buttonClass');
|
||||||
|
}.property('buttonClass'),
|
||||||
|
|
||||||
|
firstItem: function() {
|
||||||
|
return this.get('items').objectAt(0);
|
||||||
|
}.property('items.[]')
|
||||||
|
});
|
20
framework/core/ember/app/components/ui/controls/item-list.js
Normal file
20
framework/core/ember/app/components/ui/controls/item-list.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
import ComponentItem from '../items/component-item';
|
||||||
|
|
||||||
|
export default Ember.Component.extend({
|
||||||
|
tagName: 'ul',
|
||||||
|
layoutName: 'components/ui/controls/item-list',
|
||||||
|
|
||||||
|
listItems: function() {
|
||||||
|
if (!this.get('items')) return [];
|
||||||
|
var listItems = [];
|
||||||
|
this.get('items').forEach(function(item) {
|
||||||
|
if (item.tagName != 'li') {
|
||||||
|
item = ComponentItem.extend({component: item});
|
||||||
|
}
|
||||||
|
listItems.push(item);
|
||||||
|
});
|
||||||
|
return listItems;
|
||||||
|
}.property('items.[]')
|
||||||
|
});
|
@@ -1,7 +1,6 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
|
|
||||||
classNames: ['loading'],
|
classNames: ['loading'],
|
||||||
|
|
||||||
layout: Ember.Handlebars.compile(' '),
|
layout: Ember.Handlebars.compile(' '),
|
||||||
@@ -9,5 +8,4 @@ export default Ember.Component.extend({
|
|||||||
didInsertElement: function() {
|
didInsertElement: function() {
|
||||||
this.$().spin(this.get('size'));
|
this.$().spin(this.get('size'));
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
@@ -1,9 +1,7 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
export default Ember.View.extend({
|
export default Ember.View.extend({
|
||||||
|
|
||||||
tagName: 'span',
|
tagName: 'span',
|
||||||
classNames: ['select'],
|
classNames: ['select'],
|
||||||
layout: Ember.Handlebars.compile('{{view "select" content=view.content optionValuePath=view.optionValuePath optionLabelPath=view.optionLabelPath value=view.value}} {{fa-icon "sort"}}')
|
layout: Ember.Handlebars.compile('{{view "select" content=view.content optionValuePath=view.optionValuePath optionLabelPath=view.optionLabelPath value=view.value}} {{fa-icon "sort"}}')
|
||||||
|
|
||||||
});
|
});
|
@@ -2,5 +2,5 @@ import Ember from 'ember';
|
|||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
tagName: 'li',
|
tagName: 'li',
|
||||||
layoutName: 'components/menu-item-container'
|
layoutName: 'components/ui/items/component-item'
|
||||||
});
|
});
|
@@ -1,6 +1,6 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
liClass: 'divider',
|
tagName: 'li',
|
||||||
active: false
|
classNames: ['divider']
|
||||||
});
|
});
|
@@ -23,17 +23,17 @@
|
|||||||
{{/link-to}}
|
{{/link-to}}
|
||||||
</h1>
|
</h1>
|
||||||
|
|
||||||
{{menu-list items=headerPrimaryControls class="nav"}}
|
{{ui/controls/item-list items=headerPrimaryControls class="nav"}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="header-secondary">
|
<div id="header-secondary">
|
||||||
|
|
||||||
<div class="search">
|
<div class="search">
|
||||||
{{search-input placeholder="Search forum" value=searchQuery active=searchActive action="search"}}
|
{{ui/controls/search-input placeholder="Search forum" value=searchQuery active=searchActive action="search"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{menu-list items=headerSecondaryControls}}
|
{{ui/controls/item-list items=headerSecondaryControls}}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer id="footer">
|
<footer id="footer">
|
||||||
{{menu-list items=footerControls}}
|
{{ui/controls/item-list items=footerControls}}
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,13 +0,0 @@
|
|||||||
{{#if view.controls}}
|
|
||||||
<div class="controls btn-group">
|
|
||||||
<button data-toggle="dropdown" class="dropdown-toggle btn btn-default btn-icon btn-xs">{{fa-icon "caret-down"}}</button>
|
|
||||||
{{menu-list items=view.controls class="dropdown-menu pull-right"}}
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#link-to "discussion" view.post.discussion (query-params start=view.post.number) class="time"}}
|
|
||||||
{{abbreviate-time view.post.time}}
|
|
||||||
{{!-- #{{view.post.number}} (ID: {{view.post.id}}) --}}
|
|
||||||
{{/link-to}}
|
|
||||||
|
|
||||||
{{dynamic-component type=view.contentComponent post=view.post}}
|
|
@@ -1,7 +1,4 @@
|
|||||||
<div class="contextual-controls btn-group">
|
{{ui/controls/dropdown-button items=controls class="contextual-controls"}}
|
||||||
<button class="dropdown-toggle btn btn-default btn-icon" data-toggle="dropdown">{{fa-icon "ellipsis-v"}}</button>
|
|
||||||
{{menu-list items=controls class="dropdown-menu pull-right"}}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="discussion-summary">
|
<div class="discussion-summary">
|
||||||
|
|
@@ -0,0 +1,12 @@
|
|||||||
|
{{!-- {{#if view.controls}}
|
||||||
|
<div class="controls btn-group">
|
||||||
|
<button data-toggle="dropdown" class="dropdown-toggle btn btn-default btn-icon btn-xs">{{fa-icon "caret-down"}}</button>
|
||||||
|
{{menu-list items=controls class="dropdown-menu pull-right"}}
|
||||||
|
</div>
|
||||||
|
{{/if}} --}}
|
||||||
|
|
||||||
|
{{#link-to "discussion" post.discussion (query-params start=post.number) class="time"}}
|
||||||
|
{{abbreviate-time post.time}}
|
||||||
|
{{/link-to}}
|
||||||
|
|
||||||
|
{{dynamic-component type=contentComponent post=post}}
|
@@ -1 +0,0 @@
|
|||||||
{{view item}}
|
|
@@ -1,3 +0,0 @@
|
|||||||
{{#each item in items}}
|
|
||||||
{{view item}}
|
|
||||||
{{/each}}
|
|
@@ -4,5 +4,5 @@
|
|||||||
<span class="label">{{title}}</span>
|
<span class="label">{{title}}</span>
|
||||||
{{fa-icon "caret-down" class="icon-caret"}}
|
{{fa-icon "caret-down" class="icon-caret"}}
|
||||||
</button>
|
</button>
|
||||||
{{menu-list items=containedItems class=dropdownMenuClass}}
|
{{ui/controls/item-list items=items class=dropdownMenuClass}}
|
||||||
{{/if}}
|
{{/if}}
|
@@ -1,7 +1,7 @@
|
|||||||
{{#if items}}
|
{{#if items}}
|
||||||
<button {{bind-attr class=":dropdown-toggle :btn buttonClass"}} data-toggle="dropdown">
|
<button {{bind-attr class=":dropdown-toggle :btn buttonClass"}} data-toggle="dropdown">
|
||||||
<span class="label">{{currentItem.title}}</span>
|
<span class="label">{{activeItem.title}}</span>
|
||||||
{{fa-icon "sort" class="icon-caret"}}
|
{{fa-icon "sort" class="icon-caret"}}
|
||||||
</button>
|
</button>
|
||||||
{{menu-list items=items class=dropdownMenuClass viewName="menu"}}
|
{{ui/controls/item-list items=items class=dropdownMenuClass viewName="menu"}}
|
||||||
{{/if}}
|
{{/if}}
|
@@ -1,8 +1,8 @@
|
|||||||
{{#if items}}
|
{{#if items}}
|
||||||
{{view items.firstItem class=mainButtonClass}}
|
{{view firstItem class=mainButtonClass}}
|
||||||
<button {{bind-attr class=":dropdown-toggle :btn buttonClass"}} data-toggle="dropdown">
|
<button {{bind-attr class=":dropdown-toggle :btn buttonClass"}} data-toggle="dropdown">
|
||||||
{{fa-icon "caret-down" class="icon-caret"}}
|
{{fa-icon "caret-down" class="icon-caret"}}
|
||||||
{{fa-icon icon class="icon-glyph"}}
|
{{fa-icon icon class="icon-glyph"}}
|
||||||
</button>
|
</button>
|
||||||
{{menu-list items=containedItems class=dropdownMenuClass}}
|
{{ui/controls/item-list items=items class=dropdownMenuClass}}
|
||||||
{{/if}}
|
{{/if}}
|
@@ -1,3 +1,3 @@
|
|||||||
{{#each item in items}}
|
{{#each item in listItems}}
|
||||||
{{view item}}
|
{{view item}}
|
||||||
{{/each}}
|
{{/each}}
|
@@ -0,0 +1 @@
|
|||||||
|
{{view component}}
|
@@ -11,7 +11,7 @@
|
|||||||
<h3>{{{title}}}</h3>
|
<h3>{{{title}}}</h3>
|
||||||
|
|
||||||
<div class="composer-editor">
|
<div class="composer-editor">
|
||||||
{{text-editor placeholder=""}}
|
{{ui/controls/text-editor placeholder=""}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,44 +1,40 @@
|
|||||||
<div class="discussions-area">
|
<div class="discussions-area">
|
||||||
|
|
||||||
<nav class="discussions-nav">
|
<nav class="discussions-nav">
|
||||||
{{view view.sidebarView viewName="sidebar"}}
|
{{ui/controls/item-list items=view.sidebarItems}}
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<div class="discussions-results">
|
<div class="discussions-results">
|
||||||
|
|
||||||
<div class="discussions-toolbar">
|
<div class="discussions-toolbar">
|
||||||
<div class="discussions-toolbar-view">
|
<div class="discussions-toolbar-view">
|
||||||
<span class="btn-group">
|
<span class="btn-group control-show">
|
||||||
{{#link-to (query-params show="discussions") class="btn btn-default btn-sm"}}{{fa-icon "bars"}}{{/link-to}}
|
{{#link-to (query-params show="discussions") class="btn btn-default"}}{{fa-icon "bars"}}{{/link-to}}
|
||||||
{{#link-to (query-params show="posts") class="btn btn-default btn-sm"}}{{fa-icon "square-o"}}{{/link-to}}
|
{{#link-to (query-params show="posts") class="btn btn-default"}}{{fa-icon "square-o"}}{{/link-to}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
{{select-input
|
{{ui/controls/select-input class="control-sort" content=sortOptions optionValuePath="content.sort" optionLabelPath="content.label" value=sort}}
|
||||||
content=sortOptions
|
|
||||||
optionValuePath="content.sort"
|
|
||||||
optionLabelPath="content.label"
|
|
||||||
value=sort}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="discussions-toolbar-action">
|
<div class="discussions-toolbar-action">
|
||||||
<button class="btn btn-default">{{fa-icon "check"}}</button>
|
{{#ui/controls/action-button class="control-markAsRead"}}{{fa-icon "check"}}{{/ui/controls/action-button}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if resultsLoading}}
|
{{#if resultsLoading}}
|
||||||
{{loading-indicator size="small"}}
|
{{ui/controls/loading-indicator size="small"}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<ul class="discussions-list">
|
<ul class="discussions-list">
|
||||||
{{#each discussion in content}}
|
{{#each discussion in content}}
|
||||||
{{discussions-list-item discussion=discussion}}
|
{{discussions/discussion-listing discussion=discussion}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
{{#if moreResults}}
|
{{#if moreResults}}
|
||||||
<div class="load-more">
|
<div class="load-more">
|
||||||
{{#if loadingMore}}
|
{{#if loadingMore}}
|
||||||
{{loading-indicator size="small"}}
|
{{ui/controls/loading-indicator size="small"}}
|
||||||
{{else}}
|
{{else}}
|
||||||
<button class="btn btn-default" {{action loadMore}}>Load More</button>
|
{{#ui/controls/action-button class="control-loadMore" action="loadMore"}}Load More{{/ui/controls/action-button}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
@@ -1,14 +0,0 @@
|
|||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
import NamedContainerView from './named-container-view';
|
|
||||||
import MenuItemSeparator from '../components/menu-item-separator';
|
|
||||||
|
|
||||||
export default NamedContainerView.extend({
|
|
||||||
|
|
||||||
i: 1,
|
|
||||||
addSeparator: function(index) {
|
|
||||||
var item = MenuItemSeparator;
|
|
||||||
this.addItem('separator'+(this.i++), item, index);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
@@ -1,56 +0,0 @@
|
|||||||
import Ember from 'ember';
|
|
||||||
|
|
||||||
export default Ember.ArrayProxy.extend({
|
|
||||||
|
|
||||||
content: null,
|
|
||||||
namedViews: null,
|
|
||||||
|
|
||||||
init: function() {
|
|
||||||
this.set('content', Ember.A()); // this is an important line.
|
|
||||||
this.set('namedViews', Ember.Object.create());
|
|
||||||
this._super();
|
|
||||||
},
|
|
||||||
|
|
||||||
// Add an item to the container.
|
|
||||||
addItem: function(name, viewClass, index) {
|
|
||||||
// view = this.createChildView(view);
|
|
||||||
|
|
||||||
if (typeof index == 'undefined') {
|
|
||||||
index = this.get('length');
|
|
||||||
}
|
|
||||||
this.replace(index, 0, [viewClass]);
|
|
||||||
this.get('namedViews').set(name, viewClass);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Remove an item from the container.
|
|
||||||
removeItem: function(name) {
|
|
||||||
this.removeObject(this.get('namedViews').get(name));
|
|
||||||
this.get('namedViews').set(name, null);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Replace an item in the container with another one.
|
|
||||||
replaceItem: function(name, viewClass) {
|
|
||||||
// view = this.createChildView(view);
|
|
||||||
|
|
||||||
var oldView = this.get('namedViews').get(name);
|
|
||||||
var index = this.indexOf(oldView);
|
|
||||||
this.replace(index, 1, [viewClass])
|
|
||||||
this.get('namedViews').set(name, viewClass);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Move an item in the container to a new position.
|
|
||||||
moveItem: function(name, index) {
|
|
||||||
var view = this.get('namedViews').get(name);
|
|
||||||
this.removeItem(name);
|
|
||||||
this.addItem(name, view, index);
|
|
||||||
},
|
|
||||||
|
|
||||||
firstItem: function() {
|
|
||||||
return this.objectAt(0);
|
|
||||||
}.property('content.@each'),
|
|
||||||
|
|
||||||
getItem: function(name) {
|
|
||||||
return this.get('namedViews').get(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
57
framework/core/ember/app/utils/tagged-array.js
Normal file
57
framework/core/ember/app/utils/tagged-array.js
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import Ember from 'ember';
|
||||||
|
|
||||||
|
export default Ember.ArrayProxy.extend({
|
||||||
|
content: null,
|
||||||
|
taggedObjects: null,
|
||||||
|
|
||||||
|
init: function() {
|
||||||
|
this.set('content', []);
|
||||||
|
this.set('taggedObjects', {});
|
||||||
|
this._super();
|
||||||
|
},
|
||||||
|
|
||||||
|
pushObjectWithTag: function(obj, tag) {
|
||||||
|
this.insertAtWithTag(this.get('length'), obj, tag);
|
||||||
|
},
|
||||||
|
|
||||||
|
insertAtWithTag: function(idx, obj, tag) {
|
||||||
|
this.insertAt(idx, obj);
|
||||||
|
this.get('taggedObjects')[tag] = obj;
|
||||||
|
},
|
||||||
|
|
||||||
|
insertAfterTag: function(anchorTag, obj, tag) {
|
||||||
|
var idx = this.indexOfTag(anchorTag);
|
||||||
|
this.insertAtWithTag(idx + 1, obj, newTag);
|
||||||
|
},
|
||||||
|
|
||||||
|
insertBeforeTag: function(anchorTag, obj, tag) {
|
||||||
|
var idx = this.indexOfTag(anchorTag);
|
||||||
|
this.insertAtWithTag(idx - 1, obj, tag);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeByTag: function(tag) {
|
||||||
|
var idx = this.indexOfTag(tag);
|
||||||
|
this.removeAt(idx);
|
||||||
|
delete this.get('taggedObjects')[tag];
|
||||||
|
},
|
||||||
|
|
||||||
|
replaceByTag: function(tag, obj) {
|
||||||
|
var idx = this.indexOfTag(tag);
|
||||||
|
this.removeByTag(tag);
|
||||||
|
this.insertAtWithTag(idx, obj, tag);
|
||||||
|
},
|
||||||
|
|
||||||
|
moveByTag: function(tag, idx) {
|
||||||
|
var obj = this.objectByTag(tag);
|
||||||
|
this.removeByTag(tag);
|
||||||
|
this.insertAtWithTag(idx, obj, tag);
|
||||||
|
},
|
||||||
|
|
||||||
|
indexOfTag: function(tag) {
|
||||||
|
return this.indexOf(this.get('taggedObjects')[tag]);
|
||||||
|
},
|
||||||
|
|
||||||
|
objectByTag: function(tag) {
|
||||||
|
return this.get('taggedObjects')[tag];
|
||||||
|
}
|
||||||
|
});
|
@@ -1,16 +1,15 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
import NamedContainerView from '../utils/named-container-view';
|
import TaggedArray from '../utils/tagged-array';
|
||||||
import Menu from '../utils/menu';
|
import ActionButton from '../components/ui/controls/action-button';
|
||||||
import MenuItem from '../components/menu-item';
|
import DropdownSplit from '../components/ui/controls/dropdown-split';
|
||||||
import DropdownSplit from '../components/dropdown-split';
|
import DropdownButton from '../components/ui/controls/dropdown-button';
|
||||||
import DropdownButton from '../components/dropdown-button';
|
import DiscussionScrollbar from '../components/discussions/stream-scrollbar';
|
||||||
import DiscussionScrollbar from '../components/discussion-scrollbar';
|
|
||||||
import PostStreamMixin from '../mixins/post-stream';
|
import PostStreamMixin from '../mixins/post-stream';
|
||||||
|
|
||||||
export default Ember.View.extend(Ember.Evented, PostStreamMixin, {
|
export default Ember.View.extend(Ember.Evented, PostStreamMixin, {
|
||||||
|
|
||||||
sidebar: Ember.ContainerView,
|
sidebarItems: Ember.ContainerView,
|
||||||
|
|
||||||
// Set up a new menu view that will contain controls to be shown in the
|
// Set up a new menu view that will contain controls to be shown in the
|
||||||
// footer. The template will only render these controls if the last post is
|
// footer. The template will only render these controls if the last post is
|
||||||
@@ -30,7 +29,7 @@ export default Ember.View.extend(Ember.Evented, PostStreamMixin, {
|
|||||||
didInsertElement: function() {
|
didInsertElement: function() {
|
||||||
|
|
||||||
// We've just inserted the discussion view.
|
// We've just inserted the discussion view.
|
||||||
this.trigger('populateSidebar', this.get('sidebar'));
|
// this.trigger('populateSidebar', this.get('sidebar'));
|
||||||
|
|
||||||
// Whenever the window's scroll position changes, we want to check to
|
// Whenever the window's scroll position changes, we want to check to
|
||||||
// see if any terminal 'gaps' are in the viewport and trigger their
|
// see if any terminal 'gaps' are in the viewport and trigger their
|
||||||
@@ -60,14 +59,14 @@ export default Ember.View.extend(Ember.Evented, PostStreamMixin, {
|
|||||||
},
|
},
|
||||||
|
|
||||||
setupSidebar: function(sidebar) {
|
setupSidebar: function(sidebar) {
|
||||||
this.set('controls', Menu.create());
|
var items = TaggedArray.create();
|
||||||
this.trigger('populateControls', this.get('controls'));
|
this.trigger('populateControls', items);
|
||||||
sidebar.pushObject(DropdownSplit.create({
|
sidebarItems.pushObject(DropdownSplit.create({
|
||||||
items: this.get('controls'),
|
items: items,
|
||||||
icon: 'reply',
|
icon: 'reply',
|
||||||
buttonClass: 'btn-primary',
|
buttonClass: 'btn-primary',
|
||||||
menuClass: 'pull-right'
|
menuClass: 'pull-right'
|
||||||
}));
|
}), 'controls');
|
||||||
|
|
||||||
sidebar.pushObject(DropdownButton.create({items: this.get('controls')}));
|
sidebar.pushObject(DropdownButton.create({items: this.get('controls')}));
|
||||||
|
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
import Ember from 'ember';
|
import Ember from 'ember';
|
||||||
|
|
||||||
import DropdownSelect from '../components/dropdown-select';
|
import DropdownSelect from '../components/ui/controls/dropdown-select';
|
||||||
import ButtonItem from '../components/button-item';
|
import ActionButton from '../components/ui/controls/action-button';
|
||||||
import NavItem from '../components/nav-item';
|
import NavItem from '../components/ui/items/nav-item';
|
||||||
import Menu from '../utils/menu';
|
import TaggedArray from '../utils/tagged-array';
|
||||||
|
|
||||||
export default Ember.View.extend({
|
export default Ember.View.extend({
|
||||||
|
|
||||||
sidebarView: Ember.ContainerView.extend(),
|
sidebarItems: null,
|
||||||
|
|
||||||
classNameBindings: ['pinned'],
|
classNameBindings: ['pinned'],
|
||||||
|
|
||||||
@@ -17,7 +17,9 @@ export default Ember.View.extend({
|
|||||||
|
|
||||||
didInsertElement: function() {
|
didInsertElement: function() {
|
||||||
|
|
||||||
this.trigger('populateSidebar', this.get('sidebar'));
|
var sidebarItems = TaggedArray.create();
|
||||||
|
this.trigger('populateSidebar', sidebarItems);
|
||||||
|
this.set('sidebarItems', sidebarItems);
|
||||||
|
|
||||||
var view = this;
|
var view = this;
|
||||||
|
|
||||||
@@ -58,44 +60,37 @@ export default Ember.View.extend({
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
setupSidebar: function(sidebar) {
|
populateSidebarDefault: function(sidebar) {
|
||||||
sidebar.pushObject(ButtonItem.create({
|
var newDiscussion = ActionButton.create({
|
||||||
title: 'Start a Discussion',
|
title: 'Start a Discussion',
|
||||||
icon: 'edit',
|
icon: 'edit',
|
||||||
class: 'btn-primary'
|
class: 'btn-primary'
|
||||||
}));
|
})
|
||||||
|
sidebar.pushObjectWithTag(newDiscussion, 'newDiscussion');
|
||||||
|
|
||||||
var nav = Menu.create();
|
var nav = TaggedArray.create();
|
||||||
this.trigger('populateNav', nav);
|
this.trigger('populateNav', nav);
|
||||||
sidebar.pushObject(DropdownSelect.create({
|
sidebar.pushObjectWithTag(DropdownSelect.createWithItems(nav), 'nav');
|
||||||
items: nav
|
|
||||||
}));
|
|
||||||
}.on('populateSidebar'),
|
}.on('populateSidebar'),
|
||||||
|
|
||||||
setupNav: function(nav) {
|
populateNavDefault: function(nav) {
|
||||||
nav.addItem('all', NavItem.create({
|
nav.pushObjectWithTag(NavItem.create({
|
||||||
title: 'All Discussions',
|
title: 'All Discussions',
|
||||||
icon: 'comments-o',
|
icon: 'comments-o',
|
||||||
linkTo: '"discussions" (query-params filter="")'
|
linkTo: '"discussions" (query-params filter="")'
|
||||||
}));
|
}), 'all');
|
||||||
|
|
||||||
nav.addItem('private', NavItem.create({
|
nav.pushObjectWithTag(NavItem.create({
|
||||||
title: 'Private',
|
title: 'Private',
|
||||||
icon: 'envelope-o',
|
icon: 'envelope-o',
|
||||||
linkTo: '"discussions" (query-params filter="private")'
|
linkTo: '"discussions" (query-params filter="private")'
|
||||||
}));
|
}), 'private');
|
||||||
|
|
||||||
nav.addItem('following', NavItem.create({
|
nav.pushObjectWithTag(NavItem.create({
|
||||||
title: 'Following',
|
title: 'Following',
|
||||||
icon: 'star',
|
icon: 'star',
|
||||||
linkTo: '"discussions" (query-params filter="following")'
|
linkTo: '"discussions" (query-params filter="following")'
|
||||||
}));
|
}), 'following');
|
||||||
|
|
||||||
nav.addItem('categories', NavItem.create({
|
|
||||||
title: 'Categories',
|
|
||||||
icon: 'reorder',
|
|
||||||
linkTo: '"categories"'
|
|
||||||
}));
|
|
||||||
}.on('populateNav'),
|
}.on('populateNav'),
|
||||||
|
|
||||||
willDestroyElement: function() {
|
willDestroyElement: function() {
|
||||||
|
Reference in New Issue
Block a user