From 690174297d0b3976fd8c24b27c03e496db94a2f0 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Thu, 1 Jan 2015 20:08:38 +1030 Subject: [PATCH 1/7] Rejigging templates for redesign. - Componentize more stuff, heading in the direction of Ember 2.0 - Start CSS from scratch - Everything is broken atm! --- ...tification-message.js => alert-message.js} | 0 .../{views => components}/discussion-item.js | 0 .../{views => components}/discussion-post.js | 0 .../discussion-scrollbar.js | 0 .../discussions-list-item.js} | 0 ember/app/helpers/render-hook.js | 6 - ember/app/router.js | 1 - ember/app/routes/discussion.js | 8 - ember/app/routes/discussions/index.js | 8 - ember/app/styles/app.less | 6 +- .../{flarum => }/bootstrap/bootstrap.less | 0 ember/app/styles/bootstrap/variables.less | 1 + ember/app/styles/config.less | 55 +- .../styles/flarum/bootstrap/variables.less | 832 ----------------- ember/app/styles/flarum/discussion.less | 357 -------- ember/app/styles/flarum/discussions.less | 454 --------- ember/app/styles/flarum/global.less | 858 ------------------ ember/app/templates/application.hbs | 80 +- .../templates/components/alert-message.hbs | 9 + .../{ => components}/discussion-post.hbs | 0 .../{ => components}/discussion-scrollbar.hbs | 0 .../components/discussions-list-item.hbs | 50 + .../components/notification-message.hbs | 9 - .../app/templates/components/search-input.hbs | 4 +- ember/app/templates/discussion-header.hbs | 9 - ember/app/templates/discussion.hbs | 8 +- ember/app/templates/discussions-header.hbs | 7 - ember/app/templates/discussions-nav.hbs | 4 - ember/app/templates/discussions-result.hbs | 60 -- ember/app/templates/discussions.hbs | 73 +- .../templates/partials/discussion-header.hbs | 0 ember/app/transitions.js | 12 - ember/app/transitions/slide-left.js | 2 - ember/app/transitions/slide-right.js | 2 - ember/app/transitions/slide.js | 48 - ember/app/views/discussion-sidebar.js | 50 - ember/app/views/discussions-nav.js | 22 - ember/app/views/discussions-sidebar.js | 127 --- 38 files changed, 181 insertions(+), 2981 deletions(-) rename ember/app/components/{notification-message.js => alert-message.js} (100%) rename ember/app/{views => components}/discussion-item.js (100%) rename ember/app/{views => components}/discussion-post.js (100%) rename ember/app/{views => components}/discussion-scrollbar.js (100%) rename ember/app/{views/discussions-result.js => components/discussions-list-item.js} (100%) delete mode 100644 ember/app/helpers/render-hook.js rename ember/app/styles/{flarum => }/bootstrap/bootstrap.less (100%) create mode 100644 ember/app/styles/bootstrap/variables.less delete mode 100644 ember/app/styles/flarum/bootstrap/variables.less delete mode 100644 ember/app/styles/flarum/discussion.less delete mode 100644 ember/app/styles/flarum/discussions.less delete mode 100644 ember/app/styles/flarum/global.less create mode 100644 ember/app/templates/components/alert-message.hbs rename ember/app/templates/{ => components}/discussion-post.hbs (100%) rename ember/app/templates/{ => components}/discussion-scrollbar.hbs (100%) create mode 100644 ember/app/templates/components/discussions-list-item.hbs delete mode 100644 ember/app/templates/components/notification-message.hbs delete mode 100644 ember/app/templates/discussion-header.hbs delete mode 100644 ember/app/templates/discussions-header.hbs delete mode 100644 ember/app/templates/discussions-nav.hbs delete mode 100644 ember/app/templates/discussions-result.hbs create mode 100644 ember/app/templates/partials/discussion-header.hbs delete mode 100644 ember/app/transitions.js delete mode 100644 ember/app/transitions/slide-left.js delete mode 100644 ember/app/transitions/slide-right.js delete mode 100644 ember/app/transitions/slide.js delete mode 100644 ember/app/views/discussion-sidebar.js delete mode 100644 ember/app/views/discussions-nav.js delete mode 100644 ember/app/views/discussions-sidebar.js diff --git a/ember/app/components/notification-message.js b/ember/app/components/alert-message.js similarity index 100% rename from ember/app/components/notification-message.js rename to ember/app/components/alert-message.js diff --git a/ember/app/views/discussion-item.js b/ember/app/components/discussion-item.js similarity index 100% rename from ember/app/views/discussion-item.js rename to ember/app/components/discussion-item.js diff --git a/ember/app/views/discussion-post.js b/ember/app/components/discussion-post.js similarity index 100% rename from ember/app/views/discussion-post.js rename to ember/app/components/discussion-post.js diff --git a/ember/app/views/discussion-scrollbar.js b/ember/app/components/discussion-scrollbar.js similarity index 100% rename from ember/app/views/discussion-scrollbar.js rename to ember/app/components/discussion-scrollbar.js diff --git a/ember/app/views/discussions-result.js b/ember/app/components/discussions-list-item.js similarity index 100% rename from ember/app/views/discussions-result.js rename to ember/app/components/discussions-list-item.js diff --git a/ember/app/helpers/render-hook.js b/ember/app/helpers/render-hook.js deleted file mode 100644 index 3315962e7..000000000 --- a/ember/app/helpers/render-hook.js +++ /dev/null @@ -1,6 +0,0 @@ -import Ember from 'ember'; - -export default Ember.Handlebars.makeBoundHelper(function(name, options) { - return new Handlebars.SafeString(''); -}); - diff --git a/ember/app/router.js b/ember/app/router.js index db67dc38e..b6afe1a0d 100644 --- a/ember/app/router.js +++ b/ember/app/router.js @@ -16,7 +16,6 @@ Router.map(function() { this.resource('user', { path: '/user/:username' }, function() { this.route('activity'); this.route('posts'); - this.route('discussions'); this.route('preferences'); }); }); diff --git a/ember/app/routes/discussion.js b/ember/app/routes/discussion.js index d67ae363d..c0dee2df9 100644 --- a/ember/app/routes/discussion.js +++ b/ember/app/routes/discussion.js @@ -6,14 +6,6 @@ export default Ember.Route.extend({ start: {replace: true} }, - renderTemplate: function() { - this.render(); - this.render('discussion-sidebar', { - into: 'application', - outlet: 'sidebar' - }); - }, - model: function(params) { return this.store.find('discussion', params.id); }, diff --git a/ember/app/routes/discussions/index.js b/ember/app/routes/discussions/index.js index 1cf728ba1..41b5f5b11 100644 --- a/ember/app/routes/discussions/index.js +++ b/ember/app/routes/discussions/index.js @@ -2,14 +2,6 @@ import Ember from 'ember'; export default Ember.Route.extend({ - renderTemplate: function() { - this.render(); - this.render('discussions-sidebar', { - into: 'application', - outlet: 'sidebar' - }); - }, - setupController: function(controller, model) { this.controllerFor('discussions').set('paneShowing', false); this.controllerFor('discussions').set('paned', false); diff --git a/ember/app/styles/app.less b/ember/app/styles/app.less index 3e9bf677f..cd63f717d 100644 --- a/ember/app/styles/app.less +++ b/ember/app/styles/app.less @@ -1,14 +1,12 @@ +// @import "config-default.less"; @import "config.less"; @flarum-base: "flarum/"; @bootstrap-base: "../../bower_components/bootstrap/less/"; @font-awesome-base: "../../bower_components/font-awesome/less/"; -@import "@{flarum-base}bootstrap/bootstrap.less"; +@import "bootstrap/bootstrap.less"; @import "@{font-awesome-base}font-awesome.less"; @fa-font-path: "../font-awesome/fonts"; -@import "@{flarum-base}global.less"; -@import "@{flarum-base}discussions.less"; -@import "@{flarum-base}discussion.less"; diff --git a/ember/app/styles/flarum/bootstrap/bootstrap.less b/ember/app/styles/bootstrap/bootstrap.less similarity index 100% rename from ember/app/styles/flarum/bootstrap/bootstrap.less rename to ember/app/styles/bootstrap/bootstrap.less diff --git a/ember/app/styles/bootstrap/variables.less b/ember/app/styles/bootstrap/variables.less new file mode 100644 index 000000000..c25915906 --- /dev/null +++ b/ember/app/styles/bootstrap/variables.less @@ -0,0 +1 @@ +@btn-primary-bg: @fl-primary-color; \ No newline at end of file diff --git a/ember/app/styles/config.less b/ember/app/styles/config.less index 3831f28cd..83426b9c4 100644 --- a/ember/app/styles/config.less +++ b/ember/app/styles/config.less @@ -1,32 +1,33 @@ -// Default blue -@flarum-hue: 210; -@flarum-saturation: 30%; -@flarum-lightness: 90%; -@flarum-body-saturation: 30%; -@flarum-body-lightness: 99.99%; +@fl-primary-color: #4d698e; +@fl-secondary-color: #edf2f7; +@fl-dark-hdr: false; -@flarum-primary-color: hsl(@flarum-hue, @flarum-saturation, 35%); +// --------------------------------- +// BODY -@flarum-background-color: hsl(@flarum-hue, @flarum-saturation, @flarum-lightness); -@flarum-background-image: none; -@flarum-background-repeat: no-repeat; +@fl-body-bg: #fff; +@fl-body-color: #444; +@fl-body-muted-color: hsl(hue(@fl-secondary-color), 18%, 72%); // todo +@fl-body-muted-more-color: #bbb; +@fl-body-heading-color: @fl-body-color; -@flarum-bg-primary-color: contrast(@flarum-background-color, @flarum-primary-color, #fff); -@flarum-bg-secondary-color: contrast(@flarum-background-color, rgba(255, 255, 255, 0.1), darken(@flarum-background-color, 7%)); -@flarum-bg-text-color: @flarum-bg-primary-color; -@flarum-bg-link-color: @flarum-bg-primary-color; -@flarum-bg-muted-color: contrast(@flarum-background-color, rgba(255, 255, 255, 0.25), desaturate(darken(@flarum-bg-secondary-color, 25%), 10%)); +@fl-body-control-bg: @fl-secondary-color; +@fl-body-control-color: @fl-body-muted-color; -// styles for a background image -// @flarum-bg-primary-color: rgba(255, 255, 255, 0.8); -// @flarum-bg-secondary-color: rgba(255, 255, 255, 0.2); -// @flarum-bg-text-color: @flarum-bg-primary-color; -// @flarum-bg-link-color: @flarum-bg-primary-color; -// @flarum-bg-muted-color: contrast(@flarum-background-color, lighten(@flarum-bg-secondary-color, 20%), darken(@flarum-bg-secondary-color, 20%)); +@fl-body-control-primary-bg: @fl-primary-color; +@fl-body-control-primary-color: #fff; -@flarum-body-background-color: hsl(@flarum-hue, @flarum-body-saturation, @flarum-body-lightness); -@flarum-body-primary-color: contrast(@flarum-body-background-color, @flarum-primary-color, #fff); -@flarum-body-secondary-color: contrast(@flarum-body-background-color, lighten(@flarum-body-background-color, 13%), desaturate(darken(@flarum-body-background-color, 10%), 10%)); -@flarum-body-text-color: contrast(@flarum-body-background-color, #555, #fff); -@flarum-body-link-color: @flarum-body-primary-color; -@flarum-body-muted-color: contrast(@flarum-body-background-color, lighten(@flarum-body-secondary-color, 20%), darken(@flarum-body-secondary-color, 25%)); +// --------------------------------- +// HEADER + +@fl-hdr-light-bg: @fl-body-bg; +@fl-hdr-light-color: @fl-primary-color; +@fl-hdr-light-muted-color: @fl-body-muted-color; +@fl-hdr-light-control-bg: @fl-body-control-bg; +@fl-hdr-light-control-color: @fl-body-control-color; + +@fl-hdr-dark-bg: @fl-primary-color; +@fl-hdr-dark-color: #fff; +@fl-hdr-dark-muted-color: fade(#fff, 0.5); +@fl-hdr-dark-control-bg: fade(#000, 0.1); +@fl-hdr-dark-control-color: #fff; \ No newline at end of file diff --git a/ember/app/styles/flarum/bootstrap/variables.less b/ember/app/styles/flarum/bootstrap/variables.less deleted file mode 100644 index 10fcaca40..000000000 --- a/ember/app/styles/flarum/bootstrap/variables.less +++ /dev/null @@ -1,832 +0,0 @@ -// -// Variables -// -------------------------------------------------- - - -//== Colors -// -//## Gray and brand colors for use across Bootstrap. - -@gray-darker: lighten(#000, 13.5%); // #222 -@gray-dark: lighten(#000, 20%); // #333 -@gray: lighten(#000, 33.5%); // #555 -@gray-light: lighten(#000, 60%); // #999 -@gray-lighter: lighten(#000, 93.5%); // #eee - -@brand-primary: @flarum-body-primary-color; // CHANGED -@brand-success: #5cb85c; -@brand-info: #5bc0de; -@brand-warning: #f0ad4e; -@brand-danger: #d9534f; - - -//== Scaffolding -// -// ## Settings for some of the most global styles. - -//** Background color for ``. -@body-bg: @flarum-background-color; // CHANGED -//** Global text color on ``. -@text-color: @flarum-bg-text-color; // CHANGED - -//** Global textual link color. -@link-color: @brand-primary; -//** Link hover color set via `darken()` function. -@link-hover-color: darken(@link-color, 15%); - - -//== Typography -// -//## Font, line-height, and color for body text, headings, and more. - -@font-family-sans-serif: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif; // CHANGED -@font-family-serif: Georgia, "Times New Roman", Times, serif; -//** Default monospace fonts for ``, ``, and `
`.
-@font-family-monospace:   Menlo, Monaco, Consolas, "Courier New", monospace;
-@font-family-base:        @font-family-sans-serif;
-
-@font-size-base:          13px; // CHANGED
-@font-size-large:         ceil((@font-size-base * 1.25)); // ~18px
-@font-size-small:         ceil((@font-size-base * 0.85)); // ~12px
-
-@font-size-h1:            floor((@font-size-base * 2.6)); // ~36px
-@font-size-h2:            floor((@font-size-base * 2.15)); // ~30px
-@font-size-h3:            ceil((@font-size-base * 1.7)); // ~24px
-@font-size-h4:            ceil((@font-size-base * 1.25)); // ~18px
-@font-size-h5:            @font-size-base;
-@font-size-h6:            ceil((@font-size-base * 0.85)); // ~12px
-
-//** Unit-less `line-height` for use in components like buttons.
-@line-height-base:        1.538461538; // 20/13 CHANGED
-//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
-@line-height-computed:    floor((@font-size-base * @line-height-base)); // ~20px
-
-//** By default, this inherits from the ``.
-@headings-font-family:    inherit;
-@headings-font-weight:    500;
-@headings-line-height:    1.1;
-@headings-color:          inherit;
-
-
-//-- Iconography
-//
-//## Specify custom locations of the include Glyphicons icon font. Useful for those including Bootstrap via Bower.
-
-@icon-font-path:          "../fonts/";
-@icon-font-name:          "glyphicons-halflings-regular";
-@icon-font-svg-id:        "glyphicons_halflingsregular";
-
-//== Components
-//
-//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
-
-@padding-base-vertical:     9px; // CHANGED
-@padding-base-horizontal:   15px; // CHANGED
-
-@padding-large-vertical:    10px;
-@padding-large-horizontal:  16px;
-
-@padding-small-vertical:    5px;
-@padding-small-horizontal:  10px;
-
-@padding-xs-vertical:       1px;
-@padding-xs-horizontal:     5px;
-
-@line-height-large:         1.33;
-@line-height-small:         1.5;
-
-@border-radius-base:        4px;
-@border-radius-large:       6px;
-@border-radius-small:       3px;
-
-//** Global color for active items (e.g., navs or dropdowns).
-@component-active-color:    #fff;
-//** Global background color for active items (e.g., navs or dropdowns).
-@component-active-bg:       @brand-primary;
-
-//** Width of the `border` for generating carets that indicator dropdowns.
-@caret-width-base:          4px;
-//** Carets increase slightly in size for larger components.
-@caret-width-large:         5px;
-
-
-//== Tables
-//
-//## Customizes the `.table` component with basic values, each used across all table variations.
-
-//** Padding for ``s and ``s.
-@table-cell-padding:            8px;
-//** Padding for cells in `.table-condensed`.
-@table-condensed-cell-padding:  5px;
-
-//** Default background color used for all tables.
-@table-bg:                      transparent;
-//** Background color used for `.table-striped`.
-@table-bg-accent:               #f9f9f9;
-//** Background color used for `.table-hover`.
-@table-bg-hover:                #f5f5f5;
-@table-bg-active:               @table-bg-hover;
-
-//** Border color for table and cell borders.
-@table-border-color:            #ddd;
-
-
-//== Buttons
-//
-//## For each of Bootstrap's buttons, define text, background and border color.
-
-@btn-font-weight:                normal;
-
-@btn-default-color:              @flarum-body-primary-color; // CHANGED
-@btn-default-bg:                 darken(@flarum-body-secondary-color, 7%); // CHANGED
-@btn-default-border:             @btn-default-bg; // CHANGED
-
-@btn-primary-color:              contrast(@brand-primary, @flarum-body-secondary-color, #fff); // CHANGED
-@btn-primary-bg:                 @brand-primary;
-@btn-primary-border:             @btn-primary-bg; // CHANGED
-
-@btn-success-color:              #fff;
-@btn-success-bg:                 @brand-success;
-@btn-success-border:             @btn-success-bg; // CHANGED
-
-@btn-info-color:                 #fff;
-@btn-info-bg:                    @brand-info;
-@btn-info-border:                @btn-info-bg; // CHANGED
-
-@btn-warning-color:              #fff;
-@btn-warning-bg:                 @brand-warning;
-@btn-warning-border:             @btn-warning-bg; // CHANGED
-
-@btn-danger-color:               #fff;
-@btn-danger-bg:                  @brand-danger;
-@btn-danger-border:              @btn-danger-bg; // CHANGED
-
-@btn-link-disabled-color:        @gray-light;
-
-
-//== Forms
-//
-//##
-
-//** `` background color
-@input-bg:                       #fff;
-//** `` background color
-@input-bg-disabled:              @gray-lighter;
-
-//** Text color for ``s
-@input-color:                    @gray;
-//** `` border color
-@input-border:                   #ccc;
-//** `` border radius
-@input-border-radius:            @border-radius-base;
-//** Border color for inputs on focus
-@input-border-focus:             #66afe9;
-
-//** Placeholder text color
-@input-color-placeholder:        @gray-light;
-
-//** Default `.form-control` height
-@input-height-base:              (@line-height-computed + (@padding-base-vertical * 2) + 2);
-//** Large `.form-control` height
-@input-height-large:             (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
-//** Small `.form-control` height
-@input-height-small:             (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
-
-@legend-color:                   @gray-dark;
-@legend-border-color:            #e5e5e5;
-
-//** Background color for textual input addons
-@input-group-addon-bg:           @gray-lighter;
-//** Border color for textual input addons
-@input-group-addon-border-color: @input-border;
-
-
-//== Dropdowns
-//
-//## Dropdown menu container and contents.
-
-//** Background for the dropdown menu.
-@dropdown-bg:                    #fff;
-//** Dropdown menu `border-color`.
-@dropdown-border:                rgba(0,0,0,.15);
-//** Dropdown menu `border-color` **for IE8**.
-@dropdown-fallback-border:       #ccc;
-//** Divider color for between dropdown items.
-@dropdown-divider-bg:            #e5e5e5;
-
-//** Dropdown link text color.
-@dropdown-link-color:            @gray-dark;
-//** Hover color for dropdown links.
-@dropdown-link-hover-color:      darken(@gray-dark, 5%);
-//** Hover background for dropdown links.
-@dropdown-link-hover-bg:         #f5f5f5;
-
-//** Active dropdown menu item text color.
-@dropdown-link-active-color:     @component-active-color;
-//** Active dropdown menu item background color.
-@dropdown-link-active-bg:        @component-active-bg;
-
-//** Disabled dropdown menu item background color.
-@dropdown-link-disabled-color:   @gray-light;
-
-//** Text color for headers within dropdown menus.
-@dropdown-header-color:          @gray-light;
-
-// Note: Deprecated @dropdown-caret-color as of v3.1.0
-@dropdown-caret-color:           #000;
-
-
-//-- Z-index master list
-//
-// Warning: Avoid customizing these values. They're used for a bird's eye view
-// of components dependent on the z-axis and are designed to all work together.
-//
-// Note: These variables are not generated into the Customizer.
-
-@zindex-navbar:            1000;
-@zindex-dropdown:          1000;
-@zindex-popover:           1010;
-@zindex-tooltip:           1030;
-@zindex-navbar-fixed:      1030;
-@zindex-modal-background:  1040;
-@zindex-modal:             1050;
-
-
-//== Media queries breakpoints
-//
-//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
-
-// Extra small screen / phone
-// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1
-@screen-xs:                  480px;
-@screen-xs-min:              @screen-xs;
-@screen-phone:               @screen-xs-min;
-
-// Small screen / tablet
-// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1
-@screen-sm:                  768px;
-@screen-sm-min:              @screen-sm;
-@screen-tablet:              @screen-sm-min;
-
-// Medium screen / desktop
-// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1
-@screen-md:                  992px;
-@screen-md-min:              @screen-md;
-@screen-desktop:             @screen-md-min;
-
-// Large screen / wide desktop
-// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1
-@screen-lg:                  1200px;
-@screen-lg-min:              @screen-lg;
-@screen-lg-desktop:          @screen-lg-min;
-
-// So media queries don't overlap when required, provide a maximum
-@screen-xs-max:              (@screen-sm-min - 1);
-@screen-sm-max:              (@screen-md-min - 1);
-@screen-md-max:              (@screen-lg-min - 1);
-
-
-//== Grid system
-//
-//## Define your custom responsive grid.
-
-//** Number of columns in the grid.
-@grid-columns:              12;
-//** Padding between columns. Gets divided in half for the left and right.
-@grid-gutter-width:         15px;
-// Navbar collapse
-//** Point at which the navbar becomes uncollapsed.
-@grid-float-breakpoint:     @screen-sm-min;
-//** Point at which the navbar begins collapsing.
-@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
-
-
-//== Navbar
-//
-//##
-
-// Basics of a navbar
-@navbar-height:                    50px;
-@navbar-margin-bottom:             @line-height-computed;
-@navbar-border-radius:             @border-radius-base;
-@navbar-padding-horizontal:        floor((@grid-gutter-width / 2));
-@navbar-padding-vertical:          ((@navbar-height - @line-height-computed) / 2);
-@navbar-collapse-max-height:       340px;
-
-@navbar-default-color:             #777;
-@navbar-default-bg:                #f8f8f8;
-@navbar-default-border:            darken(@navbar-default-bg, 6.5%);
-
-// Navbar links
-@navbar-default-link-color:                #777;
-@navbar-default-link-hover-color:          #333;
-@navbar-default-link-hover-bg:             transparent;
-@navbar-default-link-active-color:         #555;
-@navbar-default-link-active-bg:            darken(@navbar-default-bg, 6.5%);
-@navbar-default-link-disabled-color:       #ccc;
-@navbar-default-link-disabled-bg:          transparent;
-
-// Navbar brand label
-@navbar-default-brand-color:               @navbar-default-link-color;
-@navbar-default-brand-hover-color:         darken(@navbar-default-brand-color, 10%);
-@navbar-default-brand-hover-bg:            transparent;
-
-// Navbar toggle
-@navbar-default-toggle-hover-bg:           #ddd;
-@navbar-default-toggle-icon-bar-bg:        #888;
-@navbar-default-toggle-border-color:       #ddd;
-
-
-// Inverted navbar
-// Reset inverted navbar basics
-@navbar-inverse-color:                      @gray-light;
-@navbar-inverse-bg:                         #222;
-@navbar-inverse-border:                     darken(@navbar-inverse-bg, 10%);
-
-// Inverted navbar links
-@navbar-inverse-link-color:                 @gray-light;
-@navbar-inverse-link-hover-color:           #fff;
-@navbar-inverse-link-hover-bg:              transparent;
-@navbar-inverse-link-active-color:          @navbar-inverse-link-hover-color;
-@navbar-inverse-link-active-bg:             darken(@navbar-inverse-bg, 10%);
-@navbar-inverse-link-disabled-color:        #444;
-@navbar-inverse-link-disabled-bg:           transparent;
-
-// Inverted navbar brand label
-@navbar-inverse-brand-color:                @navbar-inverse-link-color;
-@navbar-inverse-brand-hover-color:          #fff;
-@navbar-inverse-brand-hover-bg:             transparent;
-
-// Inverted navbar toggle
-@navbar-inverse-toggle-hover-bg:            #333;
-@navbar-inverse-toggle-icon-bar-bg:         #fff;
-@navbar-inverse-toggle-border-color:        #333;
-
-
-//== Navs
-//
-//##
-
-//=== Shared nav styles
-@nav-link-padding:                          10px 15px;
-@nav-link-hover-bg:                         @gray-lighter;
-
-@nav-disabled-link-color:                   @gray-light;
-@nav-disabled-link-hover-color:             @gray-light;
-
-@nav-open-link-hover-color:                 #fff;
-
-//== Tabs
-@nav-tabs-border-color:                     #ddd;
-
-@nav-tabs-link-hover-border-color:          @gray-lighter;
-
-@nav-tabs-active-link-hover-bg:             @body-bg;
-@nav-tabs-active-link-hover-color:          @gray;
-@nav-tabs-active-link-hover-border-color:   #ddd;
-
-@nav-tabs-justified-link-border-color:            #ddd;
-@nav-tabs-justified-active-link-border-color:     @body-bg;
-
-//== Pills
-@nav-pills-border-radius:                   @border-radius-base;
-@nav-pills-active-link-hover-bg:            @component-active-bg;
-@nav-pills-active-link-hover-color:         @component-active-color;
-
-
-//== Pagination
-//
-//##
-
-@pagination-color:                     @link-color;
-@pagination-bg:                        #fff;
-@pagination-border:                    #ddd;
-
-@pagination-hover-color:               @link-hover-color;
-@pagination-hover-bg:                  @gray-lighter;
-@pagination-hover-border:              #ddd;
-
-@pagination-active-color:              #fff;
-@pagination-active-bg:                 @brand-primary;
-@pagination-active-border:             @brand-primary;
-
-@pagination-disabled-color:            @gray-light;
-@pagination-disabled-bg:               #fff;
-@pagination-disabled-border:           #ddd;
-
-
-//== Pager
-//
-//##
-
-@pager-bg:                             @pagination-bg;
-@pager-border:                         @pagination-border;
-@pager-border-radius:                  15px;
-
-@pager-hover-bg:                       @pagination-hover-bg;
-
-@pager-active-bg:                      @pagination-active-bg;
-@pager-active-color:                   @pagination-active-color;
-
-@pager-disabled-color:                 @pagination-disabled-color;
-
-
-//== Jumbotron
-//
-//##
-
-@jumbotron-padding:              30px;
-@jumbotron-color:                inherit;
-@jumbotron-bg:                   @gray-lighter;
-@jumbotron-heading-color:        inherit;
-@jumbotron-font-size:            ceil((@font-size-base * 1.5));
-
-
-//== Form states and alerts
-//
-//## Define colors for form feedback states and, by default, alerts.
-
-@state-success-text:             #3c763d;
-@state-success-bg:               #dff0d8;
-@state-success-border:           darken(spin(@state-success-bg, -10), 5%);
-
-@state-info-text:                #31708f;
-@state-info-bg:                  #d9edf7;
-@state-info-border:              darken(spin(@state-info-bg, -10), 7%);
-
-@state-warning-text:             #8a6d3b;
-@state-warning-bg:               #fcf8e3;
-@state-warning-border:           darken(spin(@state-warning-bg, -10), 5%);
-
-@state-danger-text:              #a94442;
-@state-danger-bg:                #f2dede;
-@state-danger-border:            darken(spin(@state-danger-bg, -10), 5%);
-
-
-//== Tooltips
-//
-//##
-
-//** Tooltip max width
-@tooltip-max-width:           200px;
-//** Tooltip text color
-@tooltip-color:               #fff;
-//** Tooltip background color
-@tooltip-bg:                  #000;
-@tooltip-opacity:             .9;
-
-//** Tooltip arrow width
-@tooltip-arrow-width:         5px;
-//** Tooltip arrow color
-@tooltip-arrow-color:         @tooltip-bg;
-
-
-//== Popovers
-//
-//##
-
-//** Popover body background color
-@popover-bg:                          #fff;
-//** Popover maximum width
-@popover-max-width:                   276px;
-//** Popover border color
-@popover-border-color:                rgba(0,0,0,.2);
-//** Popover fallback border color
-@popover-fallback-border-color:       #ccc;
-
-//** Popover title background color
-@popover-title-bg:                    darken(@popover-bg, 3%);
-
-//** Popover arrow width
-@popover-arrow-width:                 10px;
-//** Popover arrow color
-@popover-arrow-color:                 #fff;
-
-//** Popover outer arrow width
-@popover-arrow-outer-width:           (@popover-arrow-width + 1);
-//** Popover outer arrow color
-@popover-arrow-outer-color:           rgba(0,0,0,.25);
-//** Popover outer arrow fallback color
-@popover-arrow-outer-fallback-color:  #999;
-
-
-//== Labels
-//
-//##
-
-//** Default label background color
-@label-default-bg:            @gray-light;
-//** Primary label background color
-@label-primary-bg:            @brand-primary;
-//** Success label background color
-@label-success-bg:            @brand-success;
-//** Info label background color
-@label-info-bg:               @brand-info;
-//** Warning label background color
-@label-warning-bg:            @brand-warning;
-//** Danger label background color
-@label-danger-bg:             @brand-danger;
-
-//** Default label text color
-@label-color:                 #fff;
-//** Default text color of a linked label
-@label-link-hover-color:      #fff;
-
-
-//== Modals
-//
-//##
-
-//** Padding applied to the modal body
-@modal-inner-padding:         20px;
-
-//** Padding applied to the modal title
-@modal-title-padding:         15px;
-//** Modal title line-height
-@modal-title-line-height:     @line-height-base;
-
-//** Background color of modal content area
-@modal-content-bg:                             #fff;
-//** Modal content border color
-@modal-content-border-color:                   rgba(0,0,0,.2);
-//** Modal content border color **for IE8**
-@modal-content-fallback-border-color:          #999;
-
-//** Modal backdrop background color
-@modal-backdrop-bg:           #000;
-//** Modal backdrop opacity
-@modal-backdrop-opacity:      .5;
-//** Modal header border color
-@modal-header-border-color:   #e5e5e5;
-//** Modal footer border color
-@modal-footer-border-color:   @modal-header-border-color;
-
-@modal-lg:                    900px;
-@modal-md:                    600px;
-@modal-sm:                    300px;
-
-
-//== Alerts
-//
-//## Define alert colors, border radius, and padding.
-
-@alert-padding:               15px;
-@alert-border-radius:         @border-radius-base;
-@alert-link-font-weight:      bold;
-
-@alert-success-bg:            @state-success-bg;
-@alert-success-text:          @state-success-text;
-@alert-success-border:        @state-success-border;
-
-@alert-info-bg:               @state-info-bg;
-@alert-info-text:             @state-info-text;
-@alert-info-border:           @state-info-border;
-
-@alert-warning-bg:            @state-warning-bg;
-@alert-warning-text:          @state-warning-text;
-@alert-warning-border:        @state-warning-border;
-
-@alert-danger-bg:             @state-danger-bg;
-@alert-danger-text:           @state-danger-text;
-@alert-danger-border:         @state-danger-border;
-
-
-//== Progress bars
-//
-//##
-
-//** Background color of the whole progress component
-@progress-bg:                 #f5f5f5;
-//** Progress bar text color
-@progress-bar-color:          #fff;
-
-//** Default progress bar color
-@progress-bar-bg:             @brand-primary;
-//** Success progress bar color
-@progress-bar-success-bg:     @brand-success;
-//** Warning progress bar color
-@progress-bar-warning-bg:     @brand-warning;
-//** Danger progress bar color
-@progress-bar-danger-bg:      @brand-danger;
-//** Info progress bar color
-@progress-bar-info-bg:        @brand-info;
-
-
-//== List group
-//
-//##
-
-//** Background color on `.list-group-item`
-@list-group-bg:                 #fff;
-//** `.list-group-item` border color
-@list-group-border:             #ddd;
-//** List group border radius
-@list-group-border-radius:      @border-radius-base;
-
-//** Background color of single list elements on hover
-@list-group-hover-bg:           #f5f5f5;
-//** Text color of active list elements
-@list-group-active-color:       @component-active-color;
-//** Background color of active list elements
-@list-group-active-bg:          @component-active-bg;
-//** Border color of active list elements
-@list-group-active-border:      @list-group-active-bg;
-@list-group-active-text-color:  lighten(@list-group-active-bg, 40%);
-
-@list-group-link-color:         #555;
-@list-group-link-heading-color: #333;
-
-
-//== Panels
-//
-//##
-
-@panel-bg:                    #fff;
-@panel-body-padding:          15px;
-@panel-border-radius:         @border-radius-base;
-
-//** Border color for elements within panels
-@panel-inner-border:          #ddd;
-@panel-footer-bg:             #f5f5f5;
-
-@panel-default-text:          @gray-dark;
-@panel-default-border:        #ddd;
-@panel-default-heading-bg:    #f5f5f5;
-
-@panel-primary-text:          #fff;
-@panel-primary-border:        @brand-primary;
-@panel-primary-heading-bg:    @brand-primary;
-
-@panel-success-text:          @state-success-text;
-@panel-success-border:        @state-success-border;
-@panel-success-heading-bg:    @state-success-bg;
-
-@panel-info-text:             @state-info-text;
-@panel-info-border:           @state-info-border;
-@panel-info-heading-bg:       @state-info-bg;
-
-@panel-warning-text:          @state-warning-text;
-@panel-warning-border:        @state-warning-border;
-@panel-warning-heading-bg:    @state-warning-bg;
-
-@panel-danger-text:           @state-danger-text;
-@panel-danger-border:         @state-danger-border;
-@panel-danger-heading-bg:     @state-danger-bg;
-
-
-//== Thumbnails
-//
-//##
-
-//** Padding around the thumbnail image
-@thumbnail-padding:           4px;
-//** Thumbnail background color
-@thumbnail-bg:                @body-bg;
-//** Thumbnail border color
-@thumbnail-border:            #ddd;
-//** Thumbnail border radius
-@thumbnail-border-radius:     @border-radius-base;
-
-//** Custom text color for thumbnail captions
-@thumbnail-caption-color:     @text-color;
-//** Padding around the thumbnail caption
-@thumbnail-caption-padding:   9px;
-
-
-//== Wells
-//
-//##
-
-@well-bg:                     #f5f5f5;
-@well-border:                 darken(@well-bg, 7%);
-
-
-//== Badges
-//
-//##
-
-@badge-color:                 #fff;
-//** Linked badge text color on hover
-@badge-link-hover-color:      #fff;
-@badge-bg:                    @gray-light;
-
-//** Badge text color in active nav link
-@badge-active-color:          @link-color;
-//** Badge background color in active nav link
-@badge-active-bg:             #fff;
-
-@badge-font-weight:           bold;
-@badge-line-height:           1;
-@badge-border-radius:         10px;
-
-
-//== Breadcrumbs
-//
-//##
-
-@breadcrumb-padding-vertical:   8px;
-@breadcrumb-padding-horizontal: 15px;
-//** Breadcrumb background color
-@breadcrumb-bg:                 #f5f5f5;
-//** Breadcrumb text color
-@breadcrumb-color:              #ccc;
-//** Text color of current page in the breadcrumb
-@breadcrumb-active-color:       @gray-light;
-//** Textual separator for between breadcrumb elements
-@breadcrumb-separator:          "/";
-
-
-//== Carousel
-//
-//##
-
-@carousel-text-shadow:                        0 1px 2px rgba(0,0,0,.6);
-
-@carousel-control-color:                      #fff;
-@carousel-control-width:                      15%;
-@carousel-control-opacity:                    .5;
-@carousel-control-font-size:                  20px;
-
-@carousel-indicator-active-bg:                #fff;
-@carousel-indicator-border-color:             #fff;
-
-@carousel-caption-color:                      #fff;
-
-
-//== Close
-//
-//##
-
-@close-font-weight:           bold;
-@close-color:                 #000;
-@close-text-shadow:           0 1px 0 #fff;
-
-
-//== Code
-//
-//##
-
-@code-color:                  #c7254e;
-@code-bg:                     #f9f2f4;
-
-@kbd-color:                   #fff;
-@kbd-bg:                      #333;
-
-@pre-bg:                      #f5f5f5;
-@pre-color:                   @gray-dark;
-@pre-border-color:            #ccc;
-@pre-scrollable-max-height:   340px;
-
-
-//== Type
-//
-//##
-
-//** Text muted color
-@text-muted:                  @gray-light;
-//** Abbreviations and acronyms border color
-@abbr-border-color:           @gray-light;
-//** Headings small color
-@headings-small-color:        @gray-light;
-//** Blockquote small color
-@blockquote-small-color:      @gray-light;
-//** Blockquote font size
-@blockquote-font-size:        (@font-size-base * 1.25);
-//** Blockquote border color
-@blockquote-border-color:     @gray-lighter;
-//** Page header border color
-@page-header-border-color:    @gray-lighter;
-//** Width of horizontal description list titles
-@dl-horizontal-offset:        @component-offset-horizontal;
-//** Horizontal line color.
-@hr-border:                   @gray-lighter;
-
-//== Miscellaneous
-//
-//##
-
-//** Horizontal line color.
-@hr-border:                   @gray-lighter;
-
-//** Horizontal offset for forms and lists.
-@component-offset-horizontal: 180px;
-
-
-//== Container sizes
-//
-//## Define the maximum width of `.container` for different screen sizes.
-
-// Small screen / tablet
-@container-tablet:             ((720px + @grid-gutter-width));
-//** For `@screen-sm-min` and up.
-@container-sm:                 @container-tablet;
-
-// Medium screen / desktop
-@container-desktop:            ((940px + @grid-gutter-width));
-//** For `@screen-md-min` and up.
-@container-md:                 @container-desktop;
-
-// Large screen / wide desktop
-@container-large-desktop:      ((1140px + @grid-gutter-width));
-//** For `@screen-lg-min` and up.
-@container-lg:                 @container-large-desktop;
diff --git a/ember/app/styles/flarum/discussion.less b/ember/app/styles/flarum/discussion.less
deleted file mode 100644
index d8f894746..000000000
--- a/ember/app/styles/flarum/discussion.less
+++ /dev/null
@@ -1,357 +0,0 @@
-.discussion-header, .post, .items div.gap:first-of-type:last-of-type {
-	max-width: 800px;
-}
-
-.posts {
-	// margin-bottom: 15px;
-}
-.posts .post {
-	padding-top: 25px;
-	padding-bottom: 25px;
-	border-bottom: 1px solid @flarum-body-secondary-color;
-}
-.item.highlight .post {
-	box-shadow: inset 0 -5px 0 rgba(255, 255, 0, 0.2), inset 0 5px 0 rgba(255, 255, 0, 0.2);
-}
-.items .item:first-of-type {
-	border-top: 0;
-}
-.items .item:last-of-type {
-	border-bottom: 0;
-}
-.post {
-	padding-left: 65px;
-	transition: 0.2s box-shadow;
-}
-.gap {
-	padding: 20px 0;
-	text-align: center;
-	color: @flarum-bg-muted-color;
-	margin: -1px -30px 0;
-	cursor: pointer;
-	border-top: 1px dashed @flarum-body-background-color !important;
-	border-bottom: 1px dashed @flarum-body-background-color !important;
-	transition: color 0.2s, padding 0.2s;
-	background: lighten(@flarum-background-color, 0%);
-	text-transform: uppercase;
-	font-size: 12px;
-	letter-spacing: 1px;
-	overflow: hidden;
-	position: relative;
-}
-.items div.gap:first-of-type {
-	margin-top: -30px;
-	position: relative;
-}
-.items div.gap:last-of-type {
-	margin-bottom: -30px;
-	border-bottom: 0;
-}
-.items div.gap:first-of-type:last-of-type {
-	margin: 0;
-	background: @flarum-body-background-color;
-	color: @flarum-body-muted-color;
-}
-.items div.gap:first-of-type:last-of-type:after {
-	display: none;
-}
-.gap.active, .gap:hover, .gap.loading {
-	padding: 50px 0;
-}
-.gap.loading {
-	color: @flarum-bg-muted-color;
-	transition: none;
-}
-.gap.down:after {
-	content: '\f078';
-	font-family: 'FontAwesome';
-	display: block;
-	opacity: 0;
-	transition: opacity 0.2s;
-	margin-bottom: -25px;
-	margin-top: 10px;
-	height: 15px;
-	color: @flarum-body-muted-color;
-}
-.gap.up:before {
-	content: '\f077';
-	font-family: 'FontAwesome';
-	display: block;
-	opacity: 0;
-	transition: opacity 0.4s;
-	margin-top: -25px;
-	margin-bottom: 10px;
-	height: 15px;
-}
-.gap:hover:before, .gap:hover:after, .gap.loading:before, .gap.loading:after, .gap.active:before, .gap.active:after {
-	opacity: 1;
-}
-
-
-
-.post {
-	line-height: 1.75em;
-	position: relative;
-}
-.item .controls {
-	// position: absolute;
-	// right: 10px;
-	// top: -2px;
-	// display: none;
-	float: right;
-	margin: 0 0 0 10px;
-}
-.item:hover .controls {
-	display: block;
-}
-.post .controls .btn {
-	margin-top: -2px;
-}
-.post header {
-	margin-bottom: 10px;
-}
-.post header, .post header a {
-	color: @flarum-body-muted-color;
-}
-.post .user {
-	margin: 0;
-	display: inline;
-}
-.post .user, .post .user a {
-	color: @flarum-body-primary-color;
-	font-weight: 600;
-	font-size: 16px;
-}
-.post .time {
-	font-size: 12px;
-	float: right;
-	&, & a {
-		color: @flarum-body-muted-color;
-	}
-}
-.post .reply-to {
-	margin-left: 5px;
-}
-
-.post {
-	// float: left;
-}
-.post-meta {
-	// float: left;
-	position: absolute;
-	left: 100%;
-	top: 25px;
-	margin-left: 30px;
-	width: 100px;
-	color: @flarum-body-muted-color;
-	// opacity: 0;
-	// transition: opacity 0s;
-}
-.post-icon {
-	float: left;
-
-}
-
-.post.deleted {
-
-	& .post-body,
-	& .post-meta,
-	& .avatar,
-	& .reply-to {
-		display: none;
-	}
-
-	& header {
-		margin-bottom: 0;
-	}
-
-	&, & header, & header a {
-		color: fadeout(@flarum-body-text-color, 50%);
-	}
-}
-
-@media screen and (max-width: 1300px) {
-	.post-meta {
-		position: static;
-		margin: 0;
-		width: auto;
-		margin-bottom: -15px;
-	}
-	.post-meta li {
-		display: inline;
-		margin-right: 15px;
-	}
-	.post-meta .reveal {
-		opacity: 1 !important;
-	}
-}
-.post-meta ul {
-	list-style-type: none;
-	margin: 0;
-	padding: 0;
-	line-height: 2em;
-}
-.post-meta a {
-	color: @flarum-body-muted-color;
-}
-.post-meta a:hover {
-	color: @flarum-body-primary-color;
-	text-decoration: none;
-}
-.post-meta .reveal {
-	opacity: 0;
-	transition: opacity 0.2s;
-}
-.item:hover .post-meta .reveal {
-	opacity: 1
-}
-
-.post header .avatar, .post .post-icon {
-	margin-left: -65px;
-	float: left;
-}
-.activity {
-	font-size: 16px;
-	// padding-top: 20px;
-	// padding-bottom: 20px;
-}
-.activity, .activity a {
-	color: @flarum-body-text-color;
-}
-.post .post-icon {
-	width: 48px;
-	text-align: right;
-	font-size: 22px;
-}
-.activity a {
-	font-weight: 600;
-}
-.discussion-header h4 {
-	font-size: 14px;
-	text-align: center;
-	margin: 0 0 15px 0;
-}
-.discussion-header h4, .discussion-header h4 a {
-	color: @flarum-body-muted-color;
-}
-.discussion-header .category {
-	padding: 3px 7px;
-	font-size: 13px;
-}
-.discussion-header h4 a {
-	font-weight: 600;
-}
-
-
-.discussion-footer {
-	margin-top: 15px;
-}
-.discussion-footer .list-inline {
-	margin-bottom: 0;
-}
-
-.discussion-controls {
-	margin: 0 auto;
-	margin-bottom: 30px;
-}
-.discussion-controls .btn {
-	// margin-top: 10px;
-}
-.discussion-controls .btn-group {
-	width: 100%;
-}
-
-.btn-group-suffix {
-	display: table;
-	border-spacing: 1px;
-}
-.btn-group-suffix .btn {
-	display: table-cell;
-	float: none;
-	width: 100%;
-}
-// .btn-group-suffix .dropdown-toggle {
-// 	float: right;
-// 	margin-right: -40px;
-// 	width: 39px;
-// }
-
-
-@media (min-width: @screen-md-min) {
-
-	.discussion-scrubber {
-		margin: 0 auto;
-		text-align: right;
-		margin-right: 3px;
-	}
-	.scrubber a {
-		color: @flarum-bg-muted-color;
-	}
-	.scrubber a i {
-		font-size: 14px;
-		margin-left: 5px;
-	}
-	.scrubber a:hover {
-		text-decoration: none;
-		color: @flarum-bg-link-color;
-	}
-	.scrubber .scrollbar {
-		margin: 10px 4px 10px 0;
-		position: relative;
-		cursor: pointer;
-	}
-	.scrubber .scrollbar-before, .scrubber .scrollbar-after {
-		border-right: 1px solid @flarum-bg-secondary-color;
-	}
-	.scrubber .scrollbar-slider {
-		position: relative;
-		width: 100%;
-		padding: 5px 0;
-	}
-	.scrubber .handle {
-		height: 100%;
-		width: 9px;
-		background: @flarum-bg-primary-color;
-		border-radius: 9px;
-		float: right;
-		margin-right: -4px;
-		transition: background 0.2s;
-	}
-	.scrubber .disabled .handle {
-		background: @flarum-bg-secondary-color;
-	}
-	.scrubber .info {
-		height: (2em * @line-height-base);
-		margin-top: (-1em * @line-height-base);
-		position: absolute;
-		top: 50%;
-		width: 100%;
-		right: 15px;
-	}
-	.scrubber .info strong {
-		display: block;
-	}
-	.scrubber .info .description {
-		color: @flarum-bg-muted-color;
-	}
-	.scrollbar-highlights {
-		position: absolute;
-		left: 0;
-		right: 0;
-		top: 0;
-		bottom: 0;
-		list-style-type: none;
-	}
-	.scrollbar-highlights li {
-		position: absolute;
-		right: -6px;
-		background: #fc0;
-		height: 8px;
-		width: 13px;
-		border-radius: 4px;
-		box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.15), inset 0 0 0 1px rgba(255, 255, 255, 0.5);
-		opacity: 0.99;
-	}
-}
-
-
diff --git a/ember/app/styles/flarum/discussions.less b/ember/app/styles/flarum/discussions.less
deleted file mode 100644
index f4b881d65..000000000
--- a/ember/app/styles/flarum/discussions.less
+++ /dev/null
@@ -1,454 +0,0 @@
-.discussions-header, .discussions {
-	max-width: 1200px;
-}
-
-.discussions {
-	list-style: none;
-	margin: 0;
-	padding: 0;
-}
-.discussions > li {
-	.clearfix();
-	border-bottom: 1px solid @flarum-body-secondary-color;
-	position: relative;
-	line-height: 20px;
-	padding-left: 45px;
-	padding-right: 30px;
-}
-.discussions > li.highlight, .discussions > li.active {
-	background: lighten(@flarum-body-secondary-color, 8%);
-}
-.discussions, .discussions a {
-	color: @flarum-body-muted-color;
-}
-.discussions .action {
-	float: left;
-	width: 45px;
-	padding-right: 12px;
-	margin-left: -45px;
-	text-align: right;
-	// visibility: hidden;
-	// opacity: 0.5;
-	min-height: 1px;
-	padding-top: 12px;
-	padding-bottom: 12px;
-	font-size: 12px;
-	color: @flarum-body-muted-color;
-}
-.discussions .action .unread {
-	color: #fff;
-	background: @flarum-body-primary-color;
-	padding: 0 4px;
-	border-radius: 4px;
-	font-weight: 600;
-}
-.discussions li:hover .action {
-	visibility: visible;
-}
-.discussions .action:hover {
-	text-decoration: none;
-	// opacity: 0.75;
-}
-.discussions .action:active {
-	opacity: 0.5;
-}
-.discussions .info {
-	float: left;
-	width: 74%;
-	margin-right: 2%;
-	padding-top: 12px;
-	padding-bottom: 12px;
-	display: block;
-}
-.discussions .info .title {
-	font-weight: 300;
-	font-size: 16px;
-	color: @flarum-body-link-color;
-	margin-right: 5px;
-}
-.discussions .icon {
-	margin-right: 5px;
-	font-size: 14px;
-	color: @flarum-body-link-color;
-	margin-left: 0;
-}
-.discussions .info:hover {
-	text-decoration: none;
-}
-.discussions .info:hover .title {
-	text-decoration: underline;
-}
-// .discussions .info > span {
-// 	font-size: 12px;
-// 	margin-left: 5px;
-// }
-.discussions .info .draft {
-	color:#4ea11b;
-}
-.discussions .info .excerpt {
-	display: block;
-	white-space: normal;
-	color: @flarum-body-muted-color;
-	line-height: 1.5em;
-	margin: 10px 0 5px;
-}
-.discussions .category {
-	float: right;
-	margin: -1px 0 -1px 10px;
-}
-.discussions .terminal-post {
-	float: left;
-	width: 15%;
-	white-space: nowrap;
-	overflow: hidden;
-	text-overflow: ellipsis;
-	padding-top: 12px;
-	padding-bottom: 12px;
-	font-size: 90%;
-}
-.discussions .terminal-post .avatar {
-	margin: -1px 5px -1px 0;
-}
-.discussions .replies {
-	float: left;
-	width: 8%;
-	font-size: 20px;
-	font-weight: 300;
-	text-align: center;
-	padding-top: 12px;
-	padding-bottom: 12px;
-}
-.discussions .unread .title {
-	font-weight: 600;
-}
-.discussions .locked .title, .discussions .icon-locked {
-	color: #777;
-}
-.discussions .locked .unread {
-	background-color: #777;
-}
-.discussions .sticky .title, .discussions .icon-sticky {
-	color: #D03202;
-}
-.discussions .sticky .unread {
-	background-color: #D03202;
-}
-.discussions .following .title {
-	color: #F5A623 !important;
-}
-.discussions .icon-following {
-	color: #F5A623;
-}
-.discussions .following .unread {
-	background-color: #F5A623 !important;
-}
-.discussions .controls {
-	position: absolute;
-	right: 0;
-	top: 11px;
-	display: none;
-}
-.discussions li:hover .controls {
-	display: block;
-}
-.discussions .relevant-posts {
-	clear: both;
-	// border: solid lighten(@flarum-body-text-color, 62%);
-	// border-width: 1px;
-	border-radius: 3px;
-	margin-bottom: 30px;
-	// padding: 0 10px;
-}
-.discussions .relevant-posts .post {
-	padding: 5px 0 5px 35px;
-	display: block;
-	// border-color: lighten(@flarum-body-text-color, 62%);
-	border: 0;
-	// margin-top: -1px;
-	color: @flarum-body-muted-color;
-}
-.discussions .relevant-posts .post:hover {
-	text-decoration: none;
-	// background: lighten(@flarum-body-secondary-color, 8%);
-	color: @flarum-body-text-color;
-	// padding-left: 45px;
-	// padding-right: 10px;
-	// margin-left: -10px;
-	// margin-right: -10px;
-}
-.discussions .relevant-posts .avatar {
-	margin-left: -35px;
-	opacity: 0.25;
-	float: left;
-}
-.discussions .relevant-posts .post:hover .avatar {
-	opacity: 1;
-}
-
-.load-more {
-	text-align: center;
-	margin-top: 20px;
-}
-.load-more .loading {
-	padding: 10px 0;
-}
-
-.discussions-pane {
-	left: 300px - 375px;
-	width: 100%;
-}
-.discussions-pane.paned {
-	position: fixed;
-	z-index: 10;
-	overflow: auto;
-	top: 0;
-	bottom: 0;
-	width: 375px;
-	padding: 2.5vh 0;
-	background: #fff;
-	border-right: 5px solid @flarum-background-color;
-	transition: left 0.2s;
-
-	&.showing {
-		left: 325px;
-	}
-
-	& .page-header .pull-right {
-		right: 20px;
-	}
-
-	& .discussions > li {
-		padding-right: 15px;
-		padding-left: 15px;
-
-		& .action {
-			padding-top: 15px;
-			padding-bottom: 15px;
-		}
-		& .info {
-			padding: 15px 0;
-			width: 85%;
-			min-height: 70px;
-			& .category {
-				padding: 1px 4px;
-				font-size: 11px;
-				margin-top: 0;
-			}
-			& .name {
-				display: block;
-			}
-			& .title {
-				font-size: 14px;
-			}
-			& .excerpt {
-				display: none;
-			}
-		}
-		& .controls {
-			display: none;
-		}
-		& .terminal-post {
-			width: 13%;
-			text-align: right;
-			float: right;
-			padding: 15px 0 5px;
-			& .avatar {
-				display: none;
-			}
-			& a {
-				margin: 0;
-			}
-		}
-		// & .replies {
-		// 	width: auto;
-		// 	float: right;
-		// 	clear: right;
-		// 	padding: 0 5px;
-		// 	border-radius: 4px;
-		// 	background: @flarum-body-secondary-color;
-		// 	color: #fff;
-		// 	font-size: 12px;
-		// 	font-weight: 600;
-		// 	margin-bottom: 15px;
-		// }
-		& .replies, & .action .unread {
-			width: auto;
-			float: none;
-			position: absolute;
-			top: 37px;
-			right: 15px;
-			padding: 0 5px;
-			border-radius: 4px;
-			color: #fff;
-			font-size: 12px;
-			font-weight: 600;
-			pointer-events: none;
-		}
-		& .replies {
-			background: @flarum-body-secondary-color;
-		}
-		&.unread .replies {
-			display: none;
-		}
-	}
-}
-
-.pinned {
-	& .discussions-pane {
-		left: 325px;
-		transition: left 0.2s, width 0.2s;
-	}
-	& .discussion-pane {
-		margin-left: 375px;
-	}
-}
-
-.discussions-header .select {
-	vertical-align: -1px;
-	margin-left: 10px;
-}
-
-
-
-@media (max-width: @screen-sm-max) {
-	.discussions-pane.paned {
-		display: none;
-	}
-	.discussions-header {
-		display: none;
-	}
-	.discussions {
-		& > li {
-			margin-left: 20px;
-			padding: 0;
-			line-height: inherit;
-		}
-		& .discussion {
-			position: relative;
-			background: #fff;
-		}
-		& .controls {
-			position: absolute;
-			left: 0;
-			right: 0;
-			bottom: 0;
-			top: 0;
-			display: block;
-
-			& .dropdown-toggle {
-				display: none;
-			}
-			& .dropdown-menu {
-				float: none;
-				position: static;
-				display: block;
-				text-align: center;
-				margin: 0;
-				padding: 0;
-				border: 0;
-				box-shadow: none;
-				width: auto;
-				min-width: 0;
-				background: none;
-				height: 100%;
-
-				& li {
-					float: left;
-					margin: 0;
-					height: 100%;
-
-					& a {
-						height: 100%;
-						padding: 25px 10px;
-						background: @flarum-body-primary-color;
-						color: #fff;
-						&.delete {
-							background: #e74135;
-						}
-					}
-					& .fa {
-						font-size: 22px;
-					}
-					& span {
-						display: none;
-					}
-				}
-			}
-		}
-		& .info {
-			display: block;
-			padding: 15px 75px 15px 20px;
-			width: auto;
-			float: none;
-			min-height: 70px;
-			margin: 0 0 0 -20px;
-			&.pressed {
-				background: @flarum-body-secondary-color;
-			}
-			& .category {
-				padding: 1px 4px;
-				font-size: 11px;
-				margin-top: 0;
-			}
-			& .name {
-				display: block;
-			}
-			& .excerpt {
-				display: none;
-			}
-		}
-		& .info:hover .title {
-			text-decoration: none;
-		}
-		& .info:after {
-			content: '\f054';
-			font-family: FontAwesome;
-			position: absolute;
-			right: 10px;
-			top: 15px;
-			color: @flarum-body-secondary-color;
-		}
-		& .info .title {
-			font-weight: 400;
-			font-size: 13px;
-		}
-		& .unread .title {
-			font-weight: 600;
-		}
-		& .terminal-post {
-			width: auto;
-			float: none;
-			position: absolute;
-			top: 15px;
-			right: 25px;
-			padding: 0;
-			pointer-events: none;
-			& .avatar {
-				display: none;
-			}
-			& a {
-				margin: 0;
-			}
-		}
-
-		& .replies, & .action .unread {
-			width: auto;
-			float: none;
-			position: absolute;
-			top: 37px;
-			right: 25px;
-			padding: 0 5px;
-			border-radius: 4px;
-			color: #fff;
-			font-size: 12px;
-			font-weight: 600;
-			pointer-events: none;
-		}
-		& .replies {
-			background: @flarum-body-secondary-color;
-		}
-		& .unread .replies {
-			display: none;
-		}
-	}
-}
diff --git a/ember/app/styles/flarum/global.less b/ember/app/styles/flarum/global.less
deleted file mode 100644
index fccf58d20..000000000
--- a/ember/app/styles/flarum/global.less
+++ /dev/null
@@ -1,858 +0,0 @@
-@import url(http://fonts.googleapis.com/css?family=Open+Sans:400,300,600);
-
-@import url(http://fonts.googleapis.com/css?family=Fugaz+One);
-
-// .pace .pace-progress {
-//   background: @flarum-bg-muted-color;
-//   position: fixed;
-//   z-index: 2000;
-//   top: 0;
-//   left: 0;
-//   height: 2px;
-
-//   -webkit-transition: width 1s;
-//   -moz-transition: width 1s;
-//   -o-transition: width 1s;
-//   transition: width 1s;
-// }
-
-// .pace-inactive {
-//   display: none;
-// }
-
-body {
-	background-color: @flarum-background-color;
-	background-image: @flarum-background-image;
-	color: @flarum-bg-text-color;
-	// -webkit-font-smoothing: antialiased;
-}
-body, input, button, select, textarea {
-	font-size: 13px;
-}
-body, h1, h2, h3, h4, h5, h6 {
-	font-family: 'Open Sans', sans-serif;
-}
-a {
-	color: @flarum-bg-link-color;
-}
-a:hover {
-	color: @flarum-bg-link-color;
-}
-#wrapper {
-	padding-top: 2.5vh;
-	padding-bottom: 2.5vh;
-}
-@media (min-width: @screen-md-min) {
-	#sidebar {
-		position: fixed;
-		top: 0;
-		bottom: 0;
-		height: 100%;
-		width: 295px;
-		padding: 2.5vh 25px 2.5vh 0;
-		display: table;
-		z-index: 20;
-	}
-	#sidebar-body {
-		display: table-row;
-		height: 100%;
-	}
-	#sidebar-content {
-		overflow: auto;
-		height: 100%;
-		box-sizing: content-box;
-		padding: 10px 25px;
-		margin: 0 -25px;
-	}
-	#sidebar-content .toolbar, #sidebar-content .body {
-		list-style-type: none;
-		margin: 0 0 10px;
-		padding: 0;
-	}
-	#sidebar-footer {
-		display: table-row;
-	}
-	#sidebar footer {
-		border-top: 1px solid @flarum-bg-secondary-color;
-		padding-top: 15px;
-	}
-	#sidebar-footer .statistics {
-		border-bottom: 1px solid @flarum-bg-secondary-color;
-		padding: 10px 0;
-	}
-	#sidebar-footer .statistics i {
-		margin-right: 10px;
-	}
-	#sidebar-footer .statistics a {
-		margin-right: 10px;
-	}
-	#sidebar-footer .meta {
-		padding-top: 10px;
-		.clearfix();
-	}
-	#sidebar-footer .meta > a, #sidebar-footer .meta > .dropdown > a {
-		color: @flarum-bg-muted-color;
-	}
-	#sidebar-footer .language {
-		float: left;
-	}
-	#sidebar-footer .powered-by {
-		float: right;
-	}
-	#sidebar-header {
-		display: table-row;
-	}
-	#sidebar header {
-	}
-	#sidebar header h1 {
-		font-weight: 600;
-		font-size: 18px;
-		margin: 0 0 15px;
-		line-height: 1.5em;
-		text-align: center;
-
-		// font-family: Fugaz One;
-		// font-weight: normal;
-		// font-size: 22px;
-	}
-	#sidebar header h1 .logo {
-		display: block;
-		margin: 0 auto;
-		padding-bottom: 10px;
-	}
-}
-#sidebar .search {
-	white-space: nowrap;
-	margin-bottom: 15px;
-}
-#sidebar .search input, #sidebar .search .search-nav {
-	border-radius: 20px;
-	background: transparent;
-	border: 1px solid @flarum-bg-secondary-color;
-	box-shadow: none;
-	padding: @padding-base-vertical @padding-base-horizontal;
-}
-#sidebar .search input {
-	padding-right: 30px;
-}
-#sidebar .search input::-webkit-input-placeholder {
-	color: @flarum-bg-muted-color;
-}
-#sidebar .search input::-moz-placeholder {
-	color: @flarum-bg-muted-color;
-}
-.search-input {
-	position: relative;
-}
-.search-input input[type=text] {
-	padding-right: 30px;
-	-webkit-appearance: none;
-}
-.search-input .clear {
-	position: absolute;
-	right: 13px;
-	top: @padding-base-vertical;
-	line-height: 18px;
-	color: @flarum-bg-muted-color;
-	font-size: 18px;
-	transition: transform 0.1s;
-	transform: scale(0.01);
-}
-.search-input.clearable .clear {
-	transform: scale(1);
-}
-#sidebar .search input:focus, #sidebar .search .search-nav, #sidebar .search-input.active input {
-	background: @flarum-body-background-color;
-	color: @flarum-body-text-color;
-	border-color: transparent;
-}
-#sidebar .search-nav {
-	text-align: center;
-}
-#sidebar .search-nav, #sidebar .search-nav a {
-	color: @flarum-body-muted-color;
-}
-#sidebar .search-nav a {
-	padding: 5px 10px;
-	margin: 0 -5px;
-}
-#sidebar .search-nav a:hover {
-	color: @flarum-body-primary-color;
-	text-decoration: none;
-}
-#sidebar .search-nav a.disabled {
-	color: @flarum-body-secondary-color;
-	cursor: default;
-}
-.nav-list {
-	list-style: none;
-	padding: 0;
-	margin: 0;
-	margin-top: 10px;
-}
-.nav-list li a {
-	display: block;
-	padding: (@padding-base-vertical + 1) @padding-base-horizontal;
-	color: @flarum-bg-link-color;
-	border-top: 1px solid @flarum-bg-secondary-color;
-}
-.nav-list li a i {
-	float: left;
-	margin-right: 10px;
-	margin-top: 3px;
-	text-decoration: none;
-	font-size: 14px;
-}
-
-.nav-list li.active + li a, .nav-list:not(.categories) li:first-of-type > a {
-	border-top: 0;
-}
-.nav-list li.active a {
-	color: contrast(@flarum-bg-primary-color, #000, #fff) !important;
-	background: @flarum-bg-primary-color;
-	border-radius: @border-radius-base;
-	font-weight: 600;
-	border-top: 0;
-}
-.nav-list li.active a:hover {
-	text-decoration: none;
-}
-.nav-list li a.count {
-	float: right;
-	border: 0;
-	background: none;
-}
-
-.nav-list .header {
-	display: block;
-	color: @flarum-bg-muted-color;
-	text-transform: uppercase;
-	font-weight: 600;
-	font-size: 12px;
-	border-top: 0;
-	padding: 8px 0;
-	margin-top: 15px;
-}
-.nav-list-small li a {
-	padding: 7px 12px;
-}
-
-.nav-list.categories {
-	margin-left: 35px;
-}
-.nav-list ul {
-	list-style: none;
-	margin: 0;
-	padding: 0;
-}
-.nav-list ul ul {
-	padding-left: 20px;
-	font-size: 12px;
-	display: none;
-}
-.nav-list.categories .color {
-	width: 16px;
-	height: 16px;
-	display: inline-block;
-	box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
-	border-radius: 4px;
-	margin-top: 2px;
-}
-
-.category {
-	padding: 2px 6px;
-	border-radius: 4px;
-	font-size: 12px;
-	display: inline-block;
-	line-height: @line-height-base;
-	color: @flarum-body-muted-color;
-	border: 1px solid @flarum-body-secondary-color;
-}
-// .category-announcements {
-// 	background-color: #2D4053;
-// 	color: #fff !important;
-// }
-// .category-general {
-// 	background-color: #D9D9D9;
-// 	color: #555 !important;
-// }
-// .category-support {
-// 	background-color: #5A69DB;
-// 	color: #fff !important;
-// }
-// .category-feedback {
-// 	background-color: #529E3C;
-// 	color: #fff !important;
-// }
-// .category-core {
-// 	background-color: #F7D64E;
-// 	color: #7E6500 !important;
-// }
-// .category-plugins {
-// 	background-color: #EC9A3D;
-// 	color: #fff !important;
-// }
-// .category-themes {
-// 	background-color: #DB5A5A;
-// 	color: #fff !important;
-// }
-
-#body {
-	background: @flarum-body-background-color;
-	margin-left: 295px;
-	padding: 2.5vh 30px;
-	border-radius: @border-radius-base;
-	// min-height: 94vh;
-	color: @flarum-body-text-color;
-}
-.page-header {
-	border-bottom: 1px solid @flarum-body-secondary-color;
-	position: relative;
-	padding-bottom: 40px;
-	margin: 0;
-}
-.page-header h2 {
-	text-align: center;
-	font-size: 22px;
-	font-weight: 300;
-	color: @flarum-body-primary-color;
-	margin: 0;
-}
-.page-header h2 i {
-	margin-right: 5px;
-}
-.page-header:before {
-	content: " ";
-	position: absolute;
-	display: block;
-	width: 0;
-	height: 0;
-	border: 15px solid transparent;
-	border-bottom-color: @flarum-body-secondary-color;
-	border-top-width: 0;
-	left: 50%;
-	bottom: -1px;
-	margin-left: -15px;
-}
-.page-header:after {
-	content: " ";
-	position: absolute;
-	display: block;
-	width: 0;
-	height: 0;
-	border: 14px solid transparent;
-	border-bottom-color: @flarum-body-background-color;
-	border-top-width: 0;
-	left: 50%;
-	bottom: -2px;
-	margin-left: -14px;
-}
-.page-header .pull-right {
-	position: absolute;
-	right: 0;
-}
-.page-header .pull-left {
-	position: absolute;
-	left: 0;
-}
-
-.btn {
-	padding: @padding-base-vertical @padding-base-horizontal;
-	font-weight: 600;
-}
-.btn-following {
-	.button-variant(#d80; #ffd; #ffd);
-}
-.btn i {
-	font-size: 14px;
-}
-.btn .icon-caret-down {
-	margin: 0 2px;
-}
-.btn:active,
-.btn.active,
-.btn-group.open .dropdown-toggle {
-	.box-shadow(inset 0 1px 4px rgba(0,0,0,.05));
-}
-
-.btn-default {
-	&,
-	&:hover,
-	&:focus,
-	&:active,
-	&.active,
-	.open .dropdown-toggle& {
-		background: transparent;
-		border-color: @flarum-body-secondary-color;
-		color: @flarum-body-muted-color;
-		font-weight: normal;
-	}
-}
-
-#sidebar .btn-default {
-	.button-variant(@flarum-bg-primary-color; @flarum-bg-secondary-color; @flarum-bg-secondary-color);
-	border: 0;
-	font-weight: 600;
-}
-
-.btn-sm {
-	padding: @padding-small-vertical @padding-small-horizontal;
-	border-radius: @border-radius-base;
-	font-size: 13px;
-}
-.btn-xs {
-	padding: @padding-xs-vertical @padding-xs-horizontal;
-	border-radius: @border-radius-base;
-}
-
-.select {
-	// margin-right: @padding-small-horizontal;
-}
-.select select {
-	-webkit-appearance: none;
-	background: transparent;
-	border-color: @flarum-body-secondary-color;
-	color: @flarum-body-muted-color;
-	padding: @padding-small-vertical @padding-small-horizontal;
-	padding-right: @padding-small-horizontal + 16;
-	outline: none;
-	border-radius: @border-radius-base;
-	cursor: pointer;
-	margin-right: -3px;
-	line-height: 1.5em;
-}
-.select i {
-	margin-left: -@padding-small-horizontal - 12;
-	pointer-events: none;
-	font-size: 12px;
-	color: @flarum-body-muted-color;
-}
-
-
-.controls.open {
-	display: block !important;
-}
-
-
-.tooltip-inner {
-	padding: 5px 8px;
-}
-
-#message-container {
-	position: fixed;
-	left: 0;
-	right: 0;
-	top: 2vh;
-	text-align: center;
-	z-index: 100;
-	pointer-events: none;
-}
-.message {
-	background: fade(#feb, 95%);
-	box-shadow: 0 0 0 1px fade(#c2991a, 40%), 0 3px 3px rgba(0, 0, 0, 0.1);
-	padding: @padding-base-vertical @padding-base-horizontal;
-	display: inline-block;
-	border-radius: @border-radius-base;
-	pointer-events: auto;
-	text-align: left;
-	&, & a {
-		color: #a61;
-	}
-}
-.message a {
-	font-weight: bold;
-	margin: 0 -10px 0 0;
-	padding: 10px;
-}
-.message-warning {
-	background: fade(#c21a1a, 95%);
-	box-shadow: 0 0 0 1px fade(#911, 80%), 0 3px 3px rgba(0, 0, 0, 0.1);
-	&, & a {
-		color: #fff;
-	}
-}
-.message-text {
-	display: inline-block;
-	max-width: 400px;
-	vertical-align: middle;
-}
-.message-actions {
-	display: inline-block;
-	vertical-align: middle;
-}
-
-.avatar, .avatar img {
-	display: inline-block;
-	width: 48px;
-	height: 48px;
-	border-radius: 24px;
-	color: #fff;
-	font-size: 26px;
-	font-weight: 300;
-	text-align: center;
-	line-height: 48px;
-	vertical-align: top;
-}
-.avatar-thumb, .avatar-thumb img {
-	width: 24px;
-	height: 24px;
-	font-size: 13px;
-	line-height: 24px;
-	vertical-align: middle;
-}
-
-#session {
-	// position: fixed;
-	// top: 10px;
-	// right: 10px;
-	// background: darken(@flarum-body-background-color, 3%);
-	// box-shadow: 0 1px 0 rgba(0, 0, 0, 0.1);
-	// border-radius: 24px;
-	// padding: 5px;
-	z-index: 100;
-	text-align: center;
-}
-#session > ul {
-	list-style-type: none;
-	padding: 0;
-	margin: 0;
-	.clearfix();
-}
-#session > ul > li {
-	display: inline-block;
-	// border-right: 1px solid @flarum-bg-secondary-color;
-	vertical-align: middle;
-}
-#session > ul > li:last-of-type {
-	border-right: 0;
-}
-#session > ul > li > a, #session > ul > li > .dropdown > a {
-	display: block;
-	height: 24px;
-	line-height: 24px;
-	padding: 0 10px;
-}
-#session .avatar-thumb {
-	margin-right: 10px;
-	margin-left: -10px;
-	vertical-align: 0;
-}
-#session .notifications-dropdown .dropdown-toggle i {
-	font-size: 14px;
-	// color: @flarum-bg-muted-color;
-}
-#session .badge {
-	background: #e00;
-	color: #fff;
-	font-size: 10px;
-	font-weight: bold;
-	border-radius: 3px;
-	padding: 2px 3px;
-	position: absolute;
-	top: -1px;
-	right: 8px;
-	line-height: 10px;
-}
-
-
-
-.btn-icon {
-	color: @flarum-body-muted-color;
-	font-size: 14px;
-	padding-left: 7px;
-	padding-right: 7px;
-	background: transparent;
-	border-color: transparent;
-}
-.btn-icon:hover {
-	// color: @flarum-body-muted-color;
-	text-decoration: none;
-}
-
-
-.dropdown-menu .fa {
-	font-size: 14px;
-}
-
-
-.loading {
-	color: @flarum-body-muted-color;
-	padding: 50px 0;
-}
-
-/* Full width styles */
-@media (min-width: @screen-md-min) {
-	.container {
-		max-width: none;
-		width: auto;
-		padding: 0;
-	}
-	#sidebar {
-		width: 325px;
-		padding-left: 25px;
-		background: @flarum-background-color;
-		background-image: @flarum-background-image;
-	}
-	#body {
-		margin-left: 325px;
-		border-radius: 0;
-		// max-width: 900px;
-	}
-	#wrapper {
-		padding: 0;
-	}
-}
-
-body {
-	background: @flarum-body-background-color;
-}
-
-
-
-/* New post */
-.composer {
-	position: fixed;
-	left: 330px;
-	right: 30px;
-	bottom: -100%;
-	// right: 0;
-	z-index: 9;
-	max-width: 800px;
-	// transition: bottom 0.5s;
-}
-#body {
-	// transition: padding-bottom 0.5s;
-}
-.composer-handle {
-	// background: @flarum-background-color;
-	cursor: row-resize;
-	// height: 5px;
-}
-.composer-body {
-	padding: 15px 15px 0;
-	border: 1px solid @flarum-body-primary-color;
-	border-radius: 4px;
-	background: @flarum-body-background-color;
-	// background: @flarum-body-background-color;
-	box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
-}
-.composer-controls {
-	position: absolute;
-	right: 15px;
-	top: 15px;
-}
-.composer-controls a {
-	color: @flarum-body-muted-color;
-	font-size: 14px;
-	margin-left: 5px;
-}
-.composer-controls a:hover {
-	color: @flarum-body-primary-color;
-	font-size: 14px;
-	margin-left: 5px;
-}
-.composer h3 {
-	font-size: 13px;
-	color: @flarum-body-muted-color;
-	font-weight: 400;
-	margin: 0 0 15px;
-	padding-bottom: 15px;
-	border-bottom: 1px solid @flarum-body-secondary-color;
-}
-
-.composer-editor {
-
-}
-.composer-editor textarea {
-	.box-shadow(none);
-	min-height: 200px;
-	background: @flarum-body-background-color;
-	border: 0;
-	resize: none;
-	padding: 0;
-	// padding-bottom: 0;
-	&:focus {
-		.box-shadow(none);
-	}
-}
-.composer-editor-controls {
-	padding: 15px 0;
-	.clearfix();
-}
-.composer-editor-controls .btn {
-}
-.composer-editor-controls .pull-left > .btn:first-child {
-	margin-right: 5px;
-}
-.composer-editor-controls .pull-right > .btn {
-	margin-left: 5px;
-}
-
-
-.composer.collapsed .composer-handle {
-	height: 5px;
-}
-.composer.collapsed .composer-body {
-	padding-bottom: 1px;
-}
-.composer.collapsed .composer-editor {
-	display: none;
-}
-
-
-.highlight-keyword {
-	background: #fff28e;
-	padding: 1px 4px;
-	border-radius: 3px;
-	color: @flarum-body-text-color;
-}
-
-
-
-
-/* Small devices (tablets, 768px and up) */
-@media (min-width: @screen-sm-min) {
-	#sidebar-header .mobile-header {
-		display: none;
-	}
-}
-
-/* Medium devices (desktops, 992px and up) */
-@media (min-width: @screen-md-min) {
-
-}
-
-/* Large devices (large desktops, 1200px and up) */
-@media (min-width: @screen-lg-min) {
-
-}
-
-
-@media (max-width: @screen-sm-max) {
-	body {
-		padding-top: 45px;
-	}
-	#sidebar-header header {
-		display: none;
-	}
-	#sidebar-header .mobile-header {
-		display: block;
-		position: fixed;
-		top: 0;
-		left: 0;
-		right: 0;
-		background: @flarum-background-color;
-		padding: 12px 10px;
-		color: @flarum-bg-primary-color;
-		text-align: center;
-		z-index: 20;
-		height: 45px;
-	}
-	#sidebar-header .mobile-header h1 {
-		font-size: 16px;
-		font-weight: 600;
-		display: inline-block;
-		width: 80%;
-		margin: 0;
-		white-space: nowrap;
-		text-overflow: ellipsis;
-		overflow: hidden;
-	}
-	#sidebar-header .mobile-header .back {
-		position: absolute;
-		left: 15px;
-		top: 10px;
-		font-size: 18px;
-	}
-	#sidebar-header .search {
-		padding: 10px 15px;
-		margin: 0;
-		background: lighten(@flarum-body-secondary-color, 5%);
-		& .search-input input {
-			border: 0;
-			background: #fff;
-		}
-	}
-
-	#sidebar-footer {
-		display: none;
-	}
-
-	#sidebar-content {
-		overflow: hidden;
-		height: auto;
-		-webkit-overflow-scrolling: touch;
-		padding: 0;
-		margin: 0;
-		display: block;
-		position: fixed;
-		bottom: 0;
-		left: 0;
-		right: 0;
-		top: auto;
-		background: #fff;
-		box-shadow: 0 -1px 0 rgba(0, 0, 0, 0.15);
-		height: 45px;
-		width: auto;
-		z-index: 20;
-	}
-	#sidebar-content .toolbar {
-		margin: 0;
-		padding: 0;
-		display: table;
-		list-style-type: none;
-		width: 100%;
-
-		& li {
-			display: table-cell;
-			text-align: center;
-		}
-		& li:first-of-type {
-			text-align: left;
-		}
-		& li:last-of-type {
-			text-align: right;
-		}
-
-		& .btn {
-			padding: 13px;
-			transition: opacity 0.3s;
-			&:active {
-				opacity: 0.25;
-			}
-		}
-		& .btn, & .btn-default, & .btn-group {
-			display: inline-block;
-			background: none !important;
-			border: 0 !important;
-			box-shadow: none !important;
-			width: auto;
-
-			& span {
-				display: none;
-			}
-		}
-	}
-	#sidebar-content .body {
-		display: none;
-	}
-
-	.discussion-scrubber {
-		& .scrubber-first, & .scrollbar-before, & .handle, & .description, & .scrollbar-after, & .scrubber-last {
-			display: none;
-		}
-		& .info {
-			padding: 15px;
-		}
-	}
-
-
-
-	#body {
-		margin-left: 0;
-		padding: 0;
-	}
-	#wrapper {
-		padding: 0;
-	}
-}
diff --git a/ember/app/templates/application.hbs b/ember/app/templates/application.hbs
index 053e7f0ce..2f5eae784 100644
--- a/ember/app/templates/application.hbs
+++ b/ember/app/templates/application.hbs
@@ -1,56 +1,62 @@
-{{outlet "modal"}}
+
-{{#if notificationMessage}} -
- {{notification-message message=notificationMessage closeAction="hideMessage"}} -
-{{/if}} + -
- -
+
{{outlet}} +
- {{render "composer"}} -
+
+ {{menu-list items=footerControls}} +
+ +{{outlet "modal"}} + +{{render "composer"}} + +
+ {{#each alert in alerts}} + {{alert-message message=alert}} + {{/each}} +
\ No newline at end of file diff --git a/ember/app/templates/components/alert-message.hbs b/ember/app/templates/components/alert-message.hbs new file mode 100644 index 000000000..6e0fdeb4b --- /dev/null +++ b/ember/app/templates/components/alert-message.hbs @@ -0,0 +1,9 @@ +
+ {{alert.text}} + + Undo + {{#if alert.dismissable}} + {{fa-icon "times"}} + {{/if}} + +
diff --git a/ember/app/templates/discussion-post.hbs b/ember/app/templates/components/discussion-post.hbs similarity index 100% rename from ember/app/templates/discussion-post.hbs rename to ember/app/templates/components/discussion-post.hbs diff --git a/ember/app/templates/discussion-scrollbar.hbs b/ember/app/templates/components/discussion-scrollbar.hbs similarity index 100% rename from ember/app/templates/discussion-scrollbar.hbs rename to ember/app/templates/components/discussion-scrollbar.hbs diff --git a/ember/app/templates/components/discussions-list-item.hbs b/ember/app/templates/components/discussions-list-item.hbs new file mode 100644 index 000000000..bf443df94 --- /dev/null +++ b/ember/app/templates/components/discussions-list-item.hbs @@ -0,0 +1,50 @@ +
+ + {{menu-list items=controls class="dropdown-menu pull-right"}} +
+ +
+ + {{#link-to "user" discussion.startUser}}{{user-avatar discussion.startUser}}{{/link-to}} + +
+ {{#each badge in badges}} + {{fl-badge badge}} + {{/each}} +
+ + {{#link-to "discussion" discussion.content (query-params searchQuery=searchQuery) class="info"}} + +

{{highlight-words discussion.title searchQuery}}

+
+ + {{#if displayStartPosts}} + {{#link-to "user" discussion.startUser}}{{discussion.startUser.username}}{{/link-to}} posted + {{#link-to "discussion" discussion.content}}{{abbreviate-time discussion.startTime}}{{/link-to}} + {{else}} + {{#link-to "user" discussion.lastUser}}{{discussion.lastUser.username}}{{/link-to}} posted + {{#link-to "discussion" discussion.content (query-params start="last")}}{{abbreviate-time discussion.lastTime}}{{/link-to}} + {{/if}} + + {{/link-to}} + +
+ {{#if discussion.unread}} + {{abbreviate-number discussion.unreadCount}} unread + {{else}} + {{abbreviate-number discussion.repliesCount}} replies + {{/if}} +
+ + {{#if relevantPosts}} +
+ {{#each post in relevantPosts}} + {{#link-to "discussion" discussion.content (query-params start=post.number) class="post item"}} + {{user-avatar post.user class="avatar-thumb"}} + {{highlight-words post.relevantContent searchQuery}} + {{/link-to}} + {{/each}} +
+ {{/if}} + +
diff --git a/ember/app/templates/components/notification-message.hbs b/ember/app/templates/components/notification-message.hbs deleted file mode 100644 index 43cee91e3..000000000 --- a/ember/app/templates/components/notification-message.hbs +++ /dev/null @@ -1,9 +0,0 @@ -
- {{message.text}} - - Undo - {{#if message.dismissable}} - - {{/if}} - -
diff --git a/ember/app/templates/components/search-input.hbs b/ember/app/templates/components/search-input.hbs index ce9b004ad..8dfa49f4a 100644 --- a/ember/app/templates/components/search-input.hbs +++ b/ember/app/templates/components/search-input.hbs @@ -1,2 +1,2 @@ -{{input type="text" placeholder="Search forum..." class="form-control" value=value action="search"}} -{{fa-icon "times-circle"}} +{{input type="text" placeholder=placeholder class="form-control" value=value action="search"}} + - {{menu-list items=view.controls class="dropdown-menu pull-right"}} - --}} - -
- - {{!-- {{#if view.action}} - - {{partial view.action}} - - {{/if}} --}} - - - {{#if discussion.unread}} - {{discussion.unread}} - {{/if}} - - - {{#link-to "discussion" discussion.content (query-params searchQuery=searchQuery) class="info"}} - {{#if discussion.category}} - {{discussion.category}} - {{/if}} - - {{!-- {{#if discussion.following}}{{fa-icon "star" class="icon icon-following"}}{{/if}} --}} - {{#if discussion.sticky}}{{fa-icon "thumb-tack" class="icon icon-sticky"}}{{/if}} - {{#if discussion.locked}}{{fa-icon "lock" class="icon icon-locked"}}{{/if}} - {{highlight-words discussion.title searchQuery}} - - {{#if discussion.sticky}} - {{discussion.excerpt}} - {{/if}} - {{/link-to}} - - - {{#if displayStartPosts}} - {{#link-to "user" discussion.startUser}}{{user-avatar discussion.startUser class="avatar-thumb"}}{{/link-to}} - {{#link-to "discussion" discussion.content}}{{abbreviate-time discussion.startTime}}{{/link-to}} - {{else}} - {{#link-to "user" discussion.lastUser}}{{user-avatar discussion.lastUser class="avatar-thumb"}}{{/link-to}} - {{#link-to "discussion" discussion.content (query-params start="last")}}{{abbreviate-time discussion.lastTime}}{{/link-to}} - {{/if}} - - - {{abbreviate-number discussion.repliesCount}} - - {{#if view.relevantPosts}} -
- {{#each post in view.relevantPosts}} - {{#link-to "discussion" discussion.content (query-params start=post.number) class="post item"}} - {{user-avatar post.user class="avatar-thumb"}} - {{highlight-words post.relevantContent searchQuery}} - {{/link-to}} - {{/each}} -
- {{/if}} - - {{render-hook "discussions-result"}} - -
diff --git a/ember/app/templates/discussions.hbs b/ember/app/templates/discussions.hbs index 2f6891cab..cc0ce8883 100644 --- a/ember/app/templates/discussions.hbs +++ b/ember/app/templates/discussions.hbs @@ -1,9 +1,17 @@ -
- - - {{#if resultsLoading}} - {{loading-indicator size="small"}} - {{else}} -
    - {{#each discussion in content}} - {{view "discussions-result" discussion=discussion}} - {{/each}} -
- - {{#if moreResults}} -
- {{#if loadingMore}} - {{loading-indicator size="small"}} - {{else}} - Load More - {{/if}}
+
+ +
+
+ + {{#if resultsLoading}} + {{loading-indicator size="small"}} + {{else}} +
    + {{#each discussion in content}} + {{discussions-list-item discussion=discussion}} + {{/each}} +
+ + {{#if moreResults}} +
+ {{#if loadingMore}} + {{loading-indicator size="small"}} + {{else}} + + {{/if}} +
+ {{/if}} {{/if}} - {{/if}} + + + -
- {{liquid-outlet}} +
+ {{outlet}}
diff --git a/ember/app/templates/partials/discussion-header.hbs b/ember/app/templates/partials/discussion-header.hbs new file mode 100644 index 000000000..e69de29bb diff --git a/ember/app/transitions.js b/ember/app/transitions.js deleted file mode 100644 index 52c15b3b9..000000000 --- a/ember/app/transitions.js +++ /dev/null @@ -1,12 +0,0 @@ -export default function() { - this.transition( - this.fromRoute('discussions-sidebar'), - this.toRoute('discussion-sidebar'), - this.use('slideLeft') - ); - this.transition( - this.fromRoute('discussions'), - this.toRoute('discussion'), - this.use('slideLeft') - ); -} diff --git a/ember/app/transitions/slide-left.js b/ember/app/transitions/slide-left.js deleted file mode 100644 index 4fca2cf96..000000000 --- a/ember/app/transitions/slide-left.js +++ /dev/null @@ -1,2 +0,0 @@ -import { curryTransition } from "vendor/liquid-fire"; -export default curryTransition('slide', 'x', -1, { duration: 300 }); diff --git a/ember/app/transitions/slide-right.js b/ember/app/transitions/slide-right.js deleted file mode 100644 index 5be9c7b5b..000000000 --- a/ember/app/transitions/slide-right.js +++ /dev/null @@ -1,2 +0,0 @@ -import { curryTransition } from "vendor/liquid-fire"; -export default curryTransition('slide', 'x', 1, { duration: 300 }); diff --git a/ember/app/transitions/slide.js b/ember/app/transitions/slide.js deleted file mode 100644 index 9026f0ba8..000000000 --- a/ember/app/transitions/slide.js +++ /dev/null @@ -1,48 +0,0 @@ -import { stop, animate, Promise, isAnimating, finish } from "vendor/liquid-fire"; - -export default function slide(oldView, insertNewView, dimension, direction, opts) { - var oldParams = {}, - newParams = {}, - firstStep, - property, - measure; - - if (dimension.toLowerCase() === 'x') { - property = 'translateX'; - measure = 'width'; - } else { - property = 'translateY'; - measure = 'height'; - } - - if (isAnimating(oldView, 'moving-in')) { - firstStep = finish(oldView, 'moving-in'); - } else { - stop(oldView); - firstStep = Promise.cast(); - } - - - return firstStep.then(insertNewView).then(function(newView){ - // if (newView && newView.$() && oldView && oldView.$()) { - // var sizes = [parseInt(newView.$().css(measure), 10), - // parseInt(oldView.$().css(measure), 10)]; - // var bigger = Math.max.apply(null, sizes); - var bigger = 20; - oldParams[property] = (bigger * direction) + 'px'; - newParams[property] = ["0px", (-1 * bigger * direction) + 'px']; - // } - // else { - // oldParams[property] = (100 * direction) + '%'; - // newParams[property] = ["0%", (-100 * direction) + '%']; - // } - - oldParams['opacity'] = [0, 1]; - newParams['opacity'] = [1, 0]; - - return Promise.all([ - animate(oldView, oldParams, opts), - animate(newView, newParams, opts, 'moving-in') - ]); - }); -} diff --git a/ember/app/views/discussion-sidebar.js b/ember/app/views/discussion-sidebar.js deleted file mode 100644 index c798e8545..000000000 --- a/ember/app/views/discussion-sidebar.js +++ /dev/null @@ -1,50 +0,0 @@ -import Ember from 'ember'; - -import NamedContainerView from '../utils/named-container-view'; -import Menu from '../utils/menu'; -import MenuSplit from '../components/menu-split'; -import MenuItem from '../components/menu-item'; -import DiscussionScrollbar from './discussion-scrollbar'; - -export default Ember.View.extend({ - - // NamedContainerView which will be rendered in the template. - content: null, - controls: null, - - template: Ember.Handlebars.compile('{{menu-list items=view.toolbar class="toolbar"}}{{menu-list items=view.content class="body"}}'), - - construct: function() { - this.set('toolbar', NamedContainerView.create()); - this.set('content', NamedContainerView.create()); - this.set('controls', Menu.create()); - }.on('init'), - - didInsertElement: function() { - var view = this; - var toolbar = this.get('toolbar'); - var content = this.get('content'); - - var ReplyItem = MenuItem.extend({ - title: 'Reply', - icon: 'reply', - classNameBindings: ['className', 'replying:disabled'], - replying: function() { - return this.get('parentController.controllers.composer.showing'); - }.property('parentController.controllers.composer.showing'), - action: function() { view.get('controller').send('reply'); }, - parentController: this.get('controller'), - }); - this.get('controls').addItem('reply', ReplyItem); - - toolbar.addItem('menu', MenuSplit.extend({ - items: this.get('controls'), - classNames: ['discussion-controls'] - })); - - toolbar.addItem('scrollbar', DiscussionScrollbar.extend({ - controller: this.get('controller') - })); - } - -}); diff --git a/ember/app/views/discussions-nav.js b/ember/app/views/discussions-nav.js deleted file mode 100644 index fdbe14951..000000000 --- a/ember/app/views/discussions-nav.js +++ /dev/null @@ -1,22 +0,0 @@ -import Ember from 'ember'; - -export default Ember.View.extend({ - - classNames: ['search-nav'], - templateName: 'discussions-nav', - - type: 'discussions', - - mouseEnter: function() { - clearTimeout(this.get('controller.paneTimeout')); - this.set('controller.paneShowing', true); - }, - - mouseLeave: function() { - var view = this; - this.set('controller.paneTimeout', setTimeout(function() { - view.set('controller.paneShowing', false); - }, 500)); - } - -}); diff --git a/ember/app/views/discussions-sidebar.js b/ember/app/views/discussions-sidebar.js deleted file mode 100644 index 438b6f2df..000000000 --- a/ember/app/views/discussions-sidebar.js +++ /dev/null @@ -1,127 +0,0 @@ -import Ember from 'ember'; - -import NamedContainerView from '../utils/named-container-view'; -import Menu from '../utils/menu'; -import NavItem from '../components/nav-item'; -import ButtonItem from '../components/button-item'; -import MenuList from '../components/menu-list'; -import ItemCollection from '../components/item-collection'; - -export default Ember.View.extend({ - - // NamedContainerView which will be rendered in the template. - content: null, - - template: Ember.Handlebars.compile('{{menu-list items=view.toolbar class="toolbar"}}{{menu-list items=view.content class="body"}}'), - - construct: function() { - this.set('toolbar', NamedContainerView.create()); - this.set('content', NamedContainerView.create()); - }.on('init'), - - didInsertElement: function() { - var self = this; - var content = this.get('content'); - var toolbar = this.get('toolbar'); - - // Add the 'New Discussion' button. When clicked, this will trigger the - // application's composer or something - toolbar.addItem('newDiscussion', ButtonItem.extend({ - title: 'New Discussion', - icon: 'plus', - class: 'btn-default btn-block', - action: function() { - self.set('controller.controllers.composer.showing', true); - }, - disabled: function() { - return this.get('parentController.controllers.composer.showing'); - }.property('parentController.controllers.composer.showing'), - parentController: this.get('controller') - })); - - // Add the discussions navigation list. - var nav = Menu.create(); - - nav.addItem('all', NavItem.extend({ - title: 'All Discussions', - icon: 'comments-o', - linkTo: '"discussions" (query-params filter="")' - })); - - nav.addItem('private', NavItem.extend({ - title: 'Private', - icon: 'envelope-o', - linkTo: '"discussions" (query-params filter="private")' - })); - - nav.addItem('following', NavItem.extend({ - title: 'Following', - icon: 'star', - linkTo: '"discussions" (query-params filter="following")' - })); - - nav.addItem('categories', NavItem.extend({ - title: 'Categories', - icon: 'reorder', - linkTo: '"categories"' - })); - - content.addItem('nav', ItemCollection.extend({classNames: ['nav-list'], items: nav})); - - // var tree = { - // 'Flarum': ['Announcements', 'General', 'Support', 'Feedback'], - // 'Extend': ['Core', 'Plugins', 'Themes'] - // }; - - var tree = { - 'Ninetech': ['Announcements', 'Sales', 'General', 'Off-Topic'], - 'Development': ['Getting Started', 'Databases', 'Targets', 'Add-Ons'] - }; - - // var tree = { - // 'TV Addicts': ['General'], - // 'Shows': ['Breaking Bad', 'Game of Thrones', 'Doctor Who', 'Sherlock', 'Arrested Development', '72 more...'] - // }; - - // var tree = { - // 'Categories': ['GameToAid', 'General', 'Journals', 'Gaming', 'Technology', 'Music', 'Movies, TV & Books'] - // }; - - // var tree = { - // 'Society': ['News', 'Committee', 'General'], - // 'Year Levels': ['First Year', 'Second Year', 'Third Year', 'Fourth Year', 'Fifth Year', 'Sixth Year', 'Honours'] - // }; - - var items = Menu.create(); - - var CategoryNavItem = NavItem.extend({ - iconTemplate: function() { - return ''; - // return ''; - }.property('title'), - linkTo: '"discussions" (query-params filter="category")' - }); - - for (var section in tree) { - var categories = tree[section]; - var categoryItems = Menu.create(); - - categories.forEach(function(category) { - categoryItems.addItem(category.replace(/\./g, ''), CategoryNavItem.extend({ - title: category - })); - }); - - items.addItem(section, Ember.View.extend({ - tagName: 'li', - template: Ember.Handlebars.compile('{{view.title}}{{item-collection items=view.items}}'), - title: section, - items: categoryItems - })); - } - - content.addItem('categories', ItemCollection.extend({classNames: ['nav-list', 'nav-list-small', 'categories'], items: items})); - - } - -}); From 89c8f80f3f8d374858824c672177180e0f9f7569 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Fri, 2 Jan 2015 11:46:40 +1030 Subject: [PATCH 2/7] Working on responsive dropdown menu components. --- ember/app/components/discussion-scrollbar.js | 4 +-- ember/app/components/dropdown-button.js | 21 ++++++++++++ ember/app/components/dropdown-split.js | 24 ++++++++++++++ ember/app/components/menu-split.js | 15 --------- .../templates/components/dropdown-button.hbs | 8 +++++ .../templates/components/dropdown-split.hbs | 8 +++++ ember/app/templates/components/menu-split.hbs | 13 -------- ember/app/templates/discussion.hbs | 12 +++---- ember/app/utils/named-container-view.js | 10 +----- ember/app/views/discussion.js | 32 ++++++++++++++----- 10 files changed, 93 insertions(+), 54 deletions(-) create mode 100644 ember/app/components/dropdown-button.js create mode 100644 ember/app/components/dropdown-split.js delete mode 100644 ember/app/components/menu-split.js create mode 100644 ember/app/templates/components/dropdown-button.hbs create mode 100644 ember/app/templates/components/dropdown-split.hbs delete mode 100644 ember/app/templates/components/menu-split.hbs diff --git a/ember/app/components/discussion-scrollbar.js b/ember/app/components/discussion-scrollbar.js index f5589189c..e4acd0d5f 100644 --- a/ember/app/components/discussion-scrollbar.js +++ b/ember/app/components/discussion-scrollbar.js @@ -10,7 +10,7 @@ export default Ember.View.extend(PostStreamMixin, { @property templateName @type String */ - templateName: 'discussion-scrollbar', + templateName: 'components/discussion-scrollbar', classNames: ['scrubber', 'discussion-scrubber'], // An object which represents/ecapsulates the scrollbar. @@ -28,7 +28,7 @@ export default Ember.View.extend(PostStreamMixin, { windowWasResized: function(event) { var view = event.data.view; - view.scrollbar.$.height($('#sidebar-content').height() + $('#sidebar-content').offset().top - view.scrollbar.$.offset().top - 80); + // view.scrollbar.$.height($('#sidebar-content').height() + $('#sidebar-content').offset().top - view.scrollbar.$.offset().top - 80); view.scrollbar.update(); }, diff --git a/ember/app/components/dropdown-button.js b/ember/app/components/dropdown-button.js new file mode 100644 index 000000000..9b6b1a3d1 --- /dev/null +++ b/ember/app/components/dropdown-button.js @@ -0,0 +1,21 @@ +import Ember from 'ember'; + +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') +}); diff --git a/ember/app/components/dropdown-split.js b/ember/app/components/dropdown-split.js new file mode 100644 index 000000000..13b9cf5cc --- /dev/null +++ b/ember/app/components/dropdown-split.js @@ -0,0 +1,24 @@ +import Ember from 'ember'; + +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') +}); diff --git a/ember/app/components/menu-split.js b/ember/app/components/menu-split.js deleted file mode 100644 index cddbcf4dc..000000000 --- a/ember/app/components/menu-split.js +++ /dev/null @@ -1,15 +0,0 @@ -import Ember from 'ember'; - -export default Ember.Component.extend({ - items: null, // NamedContainerView/Menu - layoutName: 'components/menu-split', - show: 1, - - visibleItems: function() { - return this.get('items').slice(0, this.get('show')); - }.property('items'), - - hiddenItems: function() { - return this.get('items').slice(this.get('show')); - }.property('items'), -}); diff --git a/ember/app/templates/components/dropdown-button.hbs b/ember/app/templates/components/dropdown-button.hbs new file mode 100644 index 000000000..de9494ba0 --- /dev/null +++ b/ember/app/templates/components/dropdown-button.hbs @@ -0,0 +1,8 @@ +{{#if items}} + + {{menu-list items=items class=dropdownMenuClass}} +{{/if}} \ No newline at end of file diff --git a/ember/app/templates/components/dropdown-split.hbs b/ember/app/templates/components/dropdown-split.hbs new file mode 100644 index 000000000..32931e96e --- /dev/null +++ b/ember/app/templates/components/dropdown-split.hbs @@ -0,0 +1,8 @@ +{{#if items}} + {{view items.firstItem class=mainButtonClass}} + + {{menu-list items=items class=dropdownMenuClass}} +{{/if}} \ No newline at end of file diff --git a/ember/app/templates/components/menu-split.hbs b/ember/app/templates/components/menu-split.hbs deleted file mode 100644 index 13978bdd6..000000000 --- a/ember/app/templates/components/menu-split.hbs +++ /dev/null @@ -1,13 +0,0 @@ -{{#if items}} - -{{/if}} diff --git a/ember/app/templates/discussion.hbs b/ember/app/templates/discussion.hbs index f7ff5348c..232547901 100644 --- a/ember/app/templates/discussion.hbs +++ b/ember/app/templates/discussion.hbs @@ -2,6 +2,10 @@ {{partial "partials/discussion-header"}} + +
{{#each item in postStream}} @@ -10,10 +14,4 @@ {{/discussion-item}} {{/each}} -
- -{{#if postStream.lastLoaded}} -
- {{menu-list items=view.footerControls class="list-inline"}} -
-{{/if}} + \ No newline at end of file diff --git a/ember/app/utils/named-container-view.js b/ember/app/utils/named-container-view.js index 539d4d5a2..219ffb922 100644 --- a/ember/app/utils/named-container-view.js +++ b/ember/app/utils/named-container-view.js @@ -48,15 +48,7 @@ export default Ember.ArrayProxy.extend({ firstItem: function() { return this.objectAt(0); - }.property(), - - secondItem: function() { - return this.objectAt(1); - }.property(), - - remainingItems: function() { - return this.slice(2); - }.property(), + }.property('content.@each'), getItem: function(name) { return this.get('namedViews').get(name); diff --git a/ember/app/views/discussion.js b/ember/app/views/discussion.js index 89d280172..2b5a92e30 100644 --- a/ember/app/views/discussion.js +++ b/ember/app/views/discussion.js @@ -1,11 +1,17 @@ import Ember from 'ember'; +import NamedContainerView from '../utils/named-container-view'; import Menu from '../utils/menu'; import MenuItem from '../components/menu-item'; +import DropdownSplit from '../components/dropdown-split'; +import DropdownButton from '../components/dropdown-button'; +import DiscussionScrollbar from '../components/discussion-scrollbar'; import PostStreamMixin from '../mixins/post-stream'; export default Ember.View.extend(Ember.Evented, PostStreamMixin, { + sidebar: Ember.ContainerView, + // 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 // showing. @@ -23,11 +29,8 @@ export default Ember.View.extend(Ember.Evented, PostStreamMixin, { didInsertElement: function() { - this.set('footerControls', Menu.create()); - - // We've just inserted the discussion view. Let's start off by - // populating the footer controls menu object. - this.trigger('populateControls', this.get('footerControls')); + // We've just inserted the discussion view. + this.trigger('populateSidebar', this.get('sidebar')); // Whenever the window's scroll position changes, we want to check to // see if any terminal 'gaps' are in the viewport and trigger their @@ -56,13 +59,26 @@ export default Ember.View.extend(Ember.Evented, PostStreamMixin, { controller.off('loadedIndex', this, this.loadedIndex); }, - // By default, we just populate the footer controls with a 'reply' button. - addDefaultControls: function(controls) { + setupSidebar: function(sidebar) { + this.set('controls', Menu.create()); + this.trigger('populateControls', this.get('controls')); + sidebar.pushObject(DropdownSplit.create({ + items: this.get('controls'), + icon: 'reply', + buttonClass: 'btn-primary', + menuClass: 'pull-right' + })); + + sidebar.pushObject(DropdownButton.create({items: this.get('controls')})); + + sidebar.pushObject(DiscussionScrollbar.create()); + }.on('populateSidebar'), + + setupControls: function(controls) { var view = this; var ReplyItem = MenuItem.extend({ title: 'Reply', icon: 'reply', - className: 'btn btn-primary', classNameBindings: ['className', 'replying:disabled'], replying: function() { return this.get('parentController.controllers.composer.showing'); From 686c54f837bf3fdb300b474542c25bce4131b44b Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Fri, 2 Jan 2015 17:17:19 +1030 Subject: [PATCH 3/7] Update ember.js (fix view helper regression) --- ember/bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ember/bower.json b/ember/bower.json index be21f6e52..e78561e86 100644 --- a/ember/bower.json +++ b/ember/bower.json @@ -3,7 +3,7 @@ "dependencies": { "handlebars": "2.0.0", "jquery": "^1.11.1", - "ember": "1.9.0", + "ember": "1.9.1", "ember-data": "1.0.0-beta.12", "ember-resolver": "~0.1.10", "loader.js": "stefanpenner/loader.js#1.0.1", From 23424a51c6de988c0eb9a0bf73cf6b96ebb4b9f1 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Sat, 3 Jan 2015 08:19:31 +1030 Subject: [PATCH 4/7] Update git URL --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bb42324d0..b23cd40ba 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ Currently Flarum is in its very early stages, and it isn’t pretty. **It is far 2. Clone the [Flarum skeleton app](https://github.com/flarum/flarum) and set up the Vagrant box: ``` - git clone git@github.com:flarum/flarum + git clone https://github.com/flarum/flarum.git cd flarum vagrant up ``` From 9375f605a813ad0b91c894163f93a0cce4d7d117 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Sat, 3 Jan 2015 12:26:14 +1030 Subject: [PATCH 5/7] Working on interface components. --- ember/app/components/button-item.js | 2 +- ember/app/components/discussions-list-item.js | 18 +++---- ember/app/components/dropdown-button.js | 18 ++++++- ember/app/components/dropdown-select.js | 30 ++++++++++++ ember/app/components/dropdown-split.js | 18 ++++++- ember/app/components/menu-item-container.js | 6 +++ ember/app/components/menu-item-separator.js | 3 +- ember/app/components/menu-item.js | 1 + ember/app/components/menu-list.js | 2 +- ember/app/components/nav-item.js | 19 ++++--- ember/app/components/select-input.js | 2 +- .../templates/components/dropdown-button.hbs | 4 +- .../templates/components/dropdown-select.hbs | 7 +++ .../templates/components/dropdown-split.hbs | 4 +- .../components/menu-item-container.hbs | 1 + ember/app/templates/components/menu-list.hbs | 2 +- ember/app/templates/discussions.hbs | 6 +-- ember/app/utils/menu.js | 21 +------- ember/app/utils/named-container-view.js | 3 +- ember/app/views/discussions.js | 49 +++++++++++++++++++ 20 files changed, 161 insertions(+), 55 deletions(-) create mode 100644 ember/app/components/dropdown-select.js create mode 100644 ember/app/components/menu-item-container.js create mode 100644 ember/app/templates/components/dropdown-select.hbs create mode 100644 ember/app/templates/components/menu-item-container.hbs diff --git a/ember/app/components/button-item.js b/ember/app/components/button-item.js index 687ac852f..ed81a892a 100644 --- a/ember/app/components/button-item.js +++ b/ember/app/components/button-item.js @@ -10,7 +10,7 @@ export default Ember.View.extend({ classNames: ['btn'], classNameBindings: ['class', 'disabled'], - layout: Ember.Handlebars.compile('{{#if view.icon}}{{fa-icon view.icon class="fa-fw"}} {{/if}}{{view.title}}'), + layout: Ember.Handlebars.compile('{{#if view.icon}}{{fa-icon view.icon class="fa-fw"}} {{/if}}{{view.title}}'), click: function() { this.action(); diff --git a/ember/app/components/discussions-list-item.js b/ember/app/components/discussions-list-item.js index 60c3241bc..f9be29fc2 100755 --- a/ember/app/components/discussions-list-item.js +++ b/ember/app/components/discussions-list-item.js @@ -131,18 +131,18 @@ export default Ember.View.extend({ var discussion = this.get('discussion'); - var controls = this.get('controls'); + // var controls = this.get('controls'); - controls.addItem('sticky', MenuItem.extend({title: 'Sticky', icon: 'thumb-tack', action: 'sticky'})); - controls.addItem('lock', MenuItem.extend({title: 'Lock', icon: 'lock', action: 'lock'})); + // controls.addItem('sticky', MenuItem.extend({title: 'Sticky', icon: 'thumb-tack', action: 'sticky'})); + // controls.addItem('lock', MenuItem.extend({title: 'Lock', icon: 'lock', action: 'lock'})); - controls.addSeparator(); + // controls.addSeparator(); - controls.addItem('delete', MenuItem.extend({title: 'Delete', icon: 'times', className: 'delete', action: function() { - // this.get('controller').send('delete', discussion); - var discussion = view.$().slideUp().find('.discussion'); - discussion.css('position', 'relative').animate({left: -discussion.width()}); - }})); + // controls.addItem('delete', MenuItem.extend({title: 'Delete', icon: 'times', className: 'delete', action: function() { + // // this.get('controller').send('delete', discussion); + // var discussion = view.$().slideUp().find('.discussion'); + // discussion.css('position', 'relative').animate({left: -discussion.width()}); + // }})); }, actions: { diff --git a/ember/app/components/dropdown-button.js b/ember/app/components/dropdown-button.js index 9b6b1a3d1..bbbf25034 100644 --- a/ember/app/components/dropdown-button.js +++ b/ember/app/components/dropdown-button.js @@ -1,5 +1,7 @@ import Ember from 'ember'; +import MenuItemContainer from '../components/menu-item-container'; + export default Ember.Component.extend({ items: null, // NamedContainerView/Menu layoutName: 'components/dropdown-button', @@ -17,5 +19,19 @@ export default Ember.Component.extend({ itemCountClass: function() { return 'item-count-'+this.get('items.length'); - }.property('items') + }.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.[]') }); diff --git a/ember/app/components/dropdown-select.js b/ember/app/components/dropdown-select.js new file mode 100644 index 000000000..779c54120 --- /dev/null +++ b/ember/app/components/dropdown-select.js @@ -0,0 +1,30 @@ +import Ember from 'ember'; + +import Menu from '../utils/menu'; + +export default Ember.Component.extend({ + items: [], + layoutName: 'components/dropdown-select', + classNames: ['dropdown', 'dropdown-select', '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.length'), + + currentItem: function() { + return this.get('menu.childViews').findBy('active'); + }.property('menu.childViews.@each.active') +}); diff --git a/ember/app/components/dropdown-split.js b/ember/app/components/dropdown-split.js index 13b9cf5cc..7465d159d 100644 --- a/ember/app/components/dropdown-split.js +++ b/ember/app/components/dropdown-split.js @@ -1,5 +1,7 @@ import Ember from 'ember'; +import MenuItemContainer from '../components/menu-item-container'; + export default Ember.Component.extend({ items: null, // NamedContainerView/Menu layoutName: 'components/dropdown-split', @@ -20,5 +22,19 @@ export default Ember.Component.extend({ itemCountClass: function() { return 'item-count-'+this.get('items.length'); - }.property('items') + }.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.[]') }); diff --git a/ember/app/components/menu-item-container.js b/ember/app/components/menu-item-container.js new file mode 100644 index 000000000..bb7e0d3bd --- /dev/null +++ b/ember/app/components/menu-item-container.js @@ -0,0 +1,6 @@ +import Ember from 'ember'; + +export default Ember.Component.extend({ + tagName: 'li', + layoutName: 'components/menu-item-container' +}); diff --git a/ember/app/components/menu-item-separator.js b/ember/app/components/menu-item-separator.js index ec7c4932c..4845311e3 100644 --- a/ember/app/components/menu-item-separator.js +++ b/ember/app/components/menu-item-separator.js @@ -1,5 +1,6 @@ import Ember from 'ember'; export default Ember.Component.extend({ - liClass: 'divider' + liClass: 'divider', + active: false }); diff --git a/ember/app/components/menu-item.js b/ember/app/components/menu-item.js index b80d608eb..f96caadae 100644 --- a/ember/app/components/menu-item.js +++ b/ember/app/components/menu-item.js @@ -6,6 +6,7 @@ var MenuItem = Ember.Component.extend({ className: '', action: null, divider: false, + active: false, tagName: 'a', attributeBindings: ['href'], diff --git a/ember/app/components/menu-list.js b/ember/app/components/menu-list.js index c059697a4..da93e4c22 100644 --- a/ember/app/components/menu-list.js +++ b/ember/app/components/menu-list.js @@ -2,5 +2,5 @@ import Ember from 'ember'; export default Ember.Component.extend({ tagName: 'ul', - layoutName: 'components/menu-list', + layoutName: 'components/menu-list' }); diff --git a/ember/app/components/nav-item.js b/ember/app/components/nav-item.js index 6528dffd8..76d585df9 100644 --- a/ember/app/components/nav-item.js +++ b/ember/app/components/nav-item.js @@ -5,18 +5,24 @@ export default Ember.Component.extend({ title: '', action: null, badge: '', - badgeAction: null, - // active: false, tagName: 'li', classNameBindings: ['active'], active: function() { - return this.get('childViews').anyBy('active'); + return !! this.get('childViews').anyBy('active'); }.property('childViews.@each.active'), + // init: function() { + // var params = this.params; + // if (params[params.length - 1].queryParams) { + // this.queryParamsObject = {values: params.pop().queryParams}; + // } + + // this._super(); + // }, + layout: function() { - return Ember.Handlebars.compile('{{badge}}\ - {{#link-to '+this.get('linkTo')+'}}'+this.get('iconTemplate')+'{{title}}{{/link-to}}'); + return Ember.Handlebars.compile('{{#link-to '+this.get('linkTo')+'}}'+this.get('iconTemplate')+' {{title}} {{badge}}{{/link-to}}'); }.property('linkTo', 'iconTemplate'), iconTemplate: function() { @@ -26,9 +32,6 @@ export default Ember.Component.extend({ actions: { main: function() { this.get('action')(); - }, - badge: function() { - this.get('badgeAction')(); } } }); diff --git a/ember/app/components/select-input.js b/ember/app/components/select-input.js index d01c5e7ff..2800009a2 100644 --- a/ember/app/components/select-input.js +++ b/ember/app/components/select-input.js @@ -4,6 +4,6 @@ export default Ember.View.extend({ tagName: 'span', classNames: ['select'], - layout: Ember.Handlebars.compile('{{view Ember.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"}}') }); diff --git a/ember/app/templates/components/dropdown-button.hbs b/ember/app/templates/components/dropdown-button.hbs index de9494ba0..166c04c1c 100644 --- a/ember/app/templates/components/dropdown-button.hbs +++ b/ember/app/templates/components/dropdown-button.hbs @@ -1,8 +1,8 @@ {{#if items}} - - {{menu-list items=items class=dropdownMenuClass}} + {{menu-list items=containedItems class=dropdownMenuClass}} {{/if}} \ No newline at end of file diff --git a/ember/app/templates/components/dropdown-select.hbs b/ember/app/templates/components/dropdown-select.hbs new file mode 100644 index 000000000..c9edd6eaa --- /dev/null +++ b/ember/app/templates/components/dropdown-select.hbs @@ -0,0 +1,7 @@ +{{#if items}} + + {{menu-list items=items class=dropdownMenuClass viewName="menu"}} +{{/if}} \ No newline at end of file diff --git a/ember/app/templates/components/dropdown-split.hbs b/ember/app/templates/components/dropdown-split.hbs index 32931e96e..3175accb3 100644 --- a/ember/app/templates/components/dropdown-split.hbs +++ b/ember/app/templates/components/dropdown-split.hbs @@ -1,8 +1,8 @@ {{#if items}} {{view items.firstItem class=mainButtonClass}} - - {{menu-list items=items class=dropdownMenuClass}} + {{menu-list items=containedItems class=dropdownMenuClass}} {{/if}} \ No newline at end of file diff --git a/ember/app/templates/components/menu-item-container.hbs b/ember/app/templates/components/menu-item-container.hbs new file mode 100644 index 000000000..6c76e440e --- /dev/null +++ b/ember/app/templates/components/menu-item-container.hbs @@ -0,0 +1 @@ +{{view item}} \ No newline at end of file diff --git a/ember/app/templates/components/menu-list.hbs b/ember/app/templates/components/menu-list.hbs index 40dd5f6ea..0eddfdb34 100644 --- a/ember/app/templates/components/menu-list.hbs +++ b/ember/app/templates/components/menu-list.hbs @@ -1,3 +1,3 @@ {{#each item in items}} -
  • {{view item}}
  • + {{view item}} {{/each}} diff --git a/ember/app/templates/discussions.hbs b/ember/app/templates/discussions.hbs index cc0ce8883..c18e15832 100644 --- a/ember/app/templates/discussions.hbs +++ b/ember/app/templates/discussions.hbs @@ -1,11 +1,7 @@
    diff --git a/ember/app/utils/menu.js b/ember/app/utils/menu.js index ec1b655fb..533eef4da 100644 --- a/ember/app/utils/menu.js +++ b/ember/app/utils/menu.js @@ -5,29 +5,10 @@ import MenuItemSeparator from '../components/menu-item-separator'; export default NamedContainerView.extend({ - tagName: 'ul', - - active: null, - i: 1, addSeparator: function(index) { var item = MenuItemSeparator; this.addItem('separator'+(this.i++), item, index); - }, - - activeChanged: function() { - var active = this.get('active'); - if (typeof active != 'array') { - active = [active]; - } - - var namedViews = this.get('namedViews'); - var view; - for (var name in namedViews) { - if (namedViews.hasOwnProperty(name) && (view = namedViews.get(name))) { - view.set('active', active.indexOf(name) !== -1); - } - } - }.observes('active') + } }); diff --git a/ember/app/utils/named-container-view.js b/ember/app/utils/named-container-view.js index 219ffb922..ca1f7b9b3 100644 --- a/ember/app/utils/named-container-view.js +++ b/ember/app/utils/named-container-view.js @@ -3,11 +3,10 @@ import Ember from 'ember'; export default Ember.ArrayProxy.extend({ content: null, - namedViews: null, init: function() { - this.set('content', Ember.A()); + this.set('content', Ember.A()); // this is an important line. this.set('namedViews', Ember.Object.create()); this._super(); }, diff --git a/ember/app/views/discussions.js b/ember/app/views/discussions.js index abe05c12d..b16e7ed47 100644 --- a/ember/app/views/discussions.js +++ b/ember/app/views/discussions.js @@ -1,7 +1,14 @@ import Ember from 'ember'; +import DropdownSelect from '../components/dropdown-select'; +import ButtonItem from '../components/button-item'; +import NavItem from '../components/nav-item'; +import Menu from '../utils/menu'; + export default Ember.View.extend({ + sidebarView: Ember.ContainerView.extend(), + classNameBindings: ['pinned'], pinned: function() { @@ -10,6 +17,8 @@ export default Ember.View.extend({ didInsertElement: function() { + this.trigger('populateSidebar', this.get('sidebar')); + var view = this; this.$().find('.discussions-pane').on('mouseenter', function() { @@ -49,6 +58,46 @@ export default Ember.View.extend({ }); }, + setupSidebar: function(sidebar) { + sidebar.pushObject(ButtonItem.create({ + title: 'Start a Discussion', + icon: 'edit', + class: 'btn-primary' + })); + + var nav = Menu.create(); + this.trigger('populateNav', nav); + sidebar.pushObject(DropdownSelect.create({ + items: nav + })); + }.on('populateSidebar'), + + setupNav: function(nav) { + nav.addItem('all', NavItem.create({ + title: 'All Discussions', + icon: 'comments-o', + linkTo: '"discussions" (query-params filter="")' + })); + + nav.addItem('private', NavItem.create({ + title: 'Private', + icon: 'envelope-o', + linkTo: '"discussions" (query-params filter="private")' + })); + + nav.addItem('following', NavItem.create({ + title: 'Following', + icon: 'star', + linkTo: '"discussions" (query-params filter="following")' + })); + + nav.addItem('categories', NavItem.create({ + title: 'Categories', + icon: 'reorder', + linkTo: '"categories"' + })); + }.on('populateNav'), + willDestroyElement: function() { this.set('controller.test', $(window).scrollTop()); $(window).off('scroll.loadMore'); From 0ed141d49eda6b65c6d2497cb742162fb6599780 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Sat, 3 Jan 2015 12:26:22 +1030 Subject: [PATCH 6/7] Clean up routes --- ember/app/router.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ember/app/router.js b/ember/app/router.js index b6afe1a0d..7e5ad6637 100644 --- a/ember/app/router.js +++ b/ember/app/router.js @@ -7,17 +7,19 @@ var Router = Ember.Router.extend({ }); Router.map(function() { - this.resource('categories', { path: '/categories' }); - this.resource('discussions', { path: '/' }, function() { - this.resource('discussion', { path: '/:id/:slug' }); + this.resource('discussions', {path: '/'}, function() { + this.resource('discussion', {path: '/:id/:slug'}, function() { + this.route('near', {path: '/:near'}); + }); }); - this.resource('user', { path: '/user/:username' }, function() { + this.resource('user', {path: '/u/:username'}, function() { this.route('activity'); this.route('posts'); - this.route('preferences'); + this.resource('preferences'); }); + }); export default Router; From f62e8e2541f10194ec81182bd94aaaf42fc15770 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Sat, 3 Jan 2015 21:51:47 +1030 Subject: [PATCH 7/7] Big component restructure/overhaul --- ember/app/components/button-item.js | 18 ------ ember/app/components/discussion-post.js | 55 ------------------ .../discussion-listing.js} | 12 ++-- ember/app/components/discussions/post.js | 55 ++++++++++++++++++ .../stream-item.js} | 2 +- .../stream-scrollbar.js} | 7 +-- ember/app/components/dropdown-button.js | 37 ------------ ember/app/components/dropdown-split.js | 40 ------------- ember/app/components/item-collection.js | 6 -- ember/app/components/menu-list.js | 6 -- .../controls/action-button.js} | 16 ++---- .../components/ui/controls/dropdown-button.js | 21 +++++++ .../{ => ui/controls}/dropdown-select.js | 11 ++-- .../components/ui/controls/dropdown-split.js | 16 ++++++ ember/app/components/ui/controls/item-list.js | 20 +++++++ .../{ => ui/controls}/loading-indicator.js | 2 - .../{ => ui/controls}/search-input.js | 0 .../{ => ui/controls}/select-input.js | 2 - .../items/component-item.js} | 2 +- .../app/components/{ => ui/items}/nav-item.js | 0 .../items/separator-item.js} | 6 +- ember/app/templates/application.hbs | 8 +-- .../templates/components/discussion-post.hbs | 13 ----- .../discussion-listing.hbs} | 5 +- .../post-comment.hbs} | 0 .../post-title.hbs} | 0 .../templates/components/discussions/post.hbs | 12 ++++ .../scrollbar.hbs} | 0 .../components/menu-item-container.hbs | 1 - ember/app/templates/components/menu-list.hbs | 3 - .../{ => ui/controls}/dropdown-button.hbs | 2 +- .../{ => ui/controls}/dropdown-select.hbs | 4 +- .../{ => ui/controls}/dropdown-split.hbs | 4 +- .../controls/item-list.hbs} | 2 +- .../{ => ui/controls}/search-input.hbs | 0 .../{ => ui/controls}/text-editor.hbs | 0 .../components/ui/items/component-item.hbs | 1 + ember/app/templates/composer.hbs | 2 +- ember/app/templates/discussions.hbs | 24 ++++---- ember/app/utils/menu.js | 14 ----- ember/app/utils/named-container-view.js | 56 ------------------ ember/app/utils/tagged-array.js | 57 +++++++++++++++++++ ember/app/views/discussion.js | 25 ++++---- ember/app/views/discussions.js | 47 +++++++-------- 44 files changed, 262 insertions(+), 352 deletions(-) delete mode 100644 ember/app/components/button-item.js delete mode 100644 ember/app/components/discussion-post.js rename ember/app/components/{discussions-list-item.js => discussions/discussion-listing.js} (94%) create mode 100644 ember/app/components/discussions/post.js rename ember/app/components/{discussion-item.js => discussions/stream-item.js} (98%) rename ember/app/components/{discussion-scrollbar.js => discussions/stream-scrollbar.js} (97%) delete mode 100644 ember/app/components/dropdown-button.js delete mode 100644 ember/app/components/dropdown-split.js delete mode 100644 ember/app/components/item-collection.js delete mode 100644 ember/app/components/menu-list.js rename ember/app/components/{menu-item.js => ui/controls/action-button.js} (70%) create mode 100644 ember/app/components/ui/controls/dropdown-button.js rename ember/app/components/{ => ui/controls}/dropdown-select.js (79%) create mode 100644 ember/app/components/ui/controls/dropdown-split.js create mode 100644 ember/app/components/ui/controls/item-list.js rename ember/app/components/{ => ui/controls}/loading-indicator.js (99%) rename ember/app/components/{ => ui/controls}/search-input.js (100%) rename ember/app/components/{ => ui/controls}/select-input.js (99%) rename ember/app/components/{menu-item-container.js => ui/items/component-item.js} (63%) rename ember/app/components/{ => ui/items}/nav-item.js (100%) rename ember/app/components/{menu-item-separator.js => ui/items/separator-item.js} (57%) delete mode 100644 ember/app/templates/components/discussion-post.hbs rename ember/app/templates/components/{discussions-list-item.hbs => discussions/discussion-listing.hbs} (87%) rename ember/app/templates/components/{post-type-comment.hbs => discussions/post-comment.hbs} (100%) rename ember/app/templates/components/{post-type-title.hbs => discussions/post-title.hbs} (100%) create mode 100644 ember/app/templates/components/discussions/post.hbs rename ember/app/templates/components/{discussion-scrollbar.hbs => discussions/scrollbar.hbs} (100%) delete mode 100644 ember/app/templates/components/menu-item-container.hbs delete mode 100644 ember/app/templates/components/menu-list.hbs rename ember/app/templates/components/{ => ui/controls}/dropdown-button.hbs (80%) rename ember/app/templates/components/{ => ui/controls}/dropdown-select.hbs (56%) rename ember/app/templates/components/{ => ui/controls}/dropdown-split.hbs (66%) rename ember/app/templates/components/{item-collection.hbs => ui/controls/item-list.hbs} (50%) rename ember/app/templates/components/{ => ui/controls}/search-input.hbs (100%) rename ember/app/templates/components/{ => ui/controls}/text-editor.hbs (100%) create mode 100644 ember/app/templates/components/ui/items/component-item.hbs delete mode 100644 ember/app/utils/menu.js delete mode 100644 ember/app/utils/named-container-view.js create mode 100644 ember/app/utils/tagged-array.js diff --git a/ember/app/components/button-item.js b/ember/app/components/button-item.js deleted file mode 100644 index ed81a892a..000000000 --- a/ember/app/components/button-item.js +++ /dev/null @@ -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}}{{view.title}}'), - - click: function() { - this.action(); - } -}); diff --git a/ember/app/components/discussion-post.js b/ember/app/components/discussion-post.js deleted file mode 100644 index 1eeaa9604..000000000 --- a/ember/app/components/discussion-post.js +++ /dev/null @@ -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); - } - -}); diff --git a/ember/app/components/discussions-list-item.js b/ember/app/components/discussions/discussion-listing.js similarity index 94% rename from ember/app/components/discussions-list-item.js rename to ember/app/components/discussions/discussion-listing.js index f9be29fc2..addf8019a 100755 --- a/ember/app/components/discussions-list-item.js +++ b/ember/app/components/discussions/discussion-listing.js @@ -1,12 +1,12 @@ - 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() { - this.set('controls', Menu.create()); + // this.set('controls', Menu.create()); }.on('init'), tagName: 'li', @@ -18,7 +18,7 @@ export default Ember.View.extend({ 'discussion.following:following', 'active' ], - templateName: 'discussions-result', + templateName: 'components/discussions/discussion-listing', active: function() { return this.get('childViews').anyBy('active'); diff --git a/ember/app/components/discussions/post.js b/ember/app/components/discussions/post.js new file mode 100644 index 000000000..5e1bf63ad --- /dev/null +++ b/ember/app/components/discussions/post.js @@ -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); + } + +}); diff --git a/ember/app/components/discussion-item.js b/ember/app/components/discussions/stream-item.js similarity index 98% rename from ember/app/components/discussion-item.js rename to ember/app/components/discussions/stream-item.js index 060a75d2c..919f3f872 100644 --- a/ember/app/components/discussion-item.js +++ b/ember/app/components/discussions/stream-item.js @@ -4,7 +4,7 @@ import Ember from 'ember'; // single item may represent a single post, or it may represent a gap of many // posts which have not been loaded. -export default Ember.View.extend({ +export default Ember.Component.extend({ classNames: ['item'], classNameBindings: ['item.gap:gap', 'loading', 'direction'], attributeBindings: [ diff --git a/ember/app/components/discussion-scrollbar.js b/ember/app/components/discussions/stream-scrollbar.js similarity index 97% rename from ember/app/components/discussion-scrollbar.js rename to ember/app/components/discussions/stream-scrollbar.js index e4acd0d5f..3f31dbd88 100644 --- a/ember/app/components/discussion-scrollbar.js +++ b/ember/app/components/discussions/stream-scrollbar.js @@ -1,8 +1,7 @@ import Ember from 'ember'; -import MenuItem from '../components/menu-item'; -import Scrollbar from '../utils/scrollbar'; -import PostStreamMixin from '../mixins/post-stream'; +import Scrollbar from '../../utils/scrollbar'; +import PostStreamMixin from '../../mixins/post-stream'; export default Ember.View.extend(PostStreamMixin, { @@ -10,7 +9,7 @@ export default Ember.View.extend(PostStreamMixin, { @property templateName @type String */ - templateName: 'components/discussion-scrollbar', + templateName: 'components/discussions/stream-scrollbar', classNames: ['scrubber', 'discussion-scrubber'], // An object which represents/ecapsulates the scrollbar. diff --git a/ember/app/components/dropdown-button.js b/ember/app/components/dropdown-button.js deleted file mode 100644 index bbbf25034..000000000 --- a/ember/app/components/dropdown-button.js +++ /dev/null @@ -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.[]') -}); diff --git a/ember/app/components/dropdown-split.js b/ember/app/components/dropdown-split.js deleted file mode 100644 index 7465d159d..000000000 --- a/ember/app/components/dropdown-split.js +++ /dev/null @@ -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.[]') -}); diff --git a/ember/app/components/item-collection.js b/ember/app/components/item-collection.js deleted file mode 100644 index a9a01a5cf..000000000 --- a/ember/app/components/item-collection.js +++ /dev/null @@ -1,6 +0,0 @@ -import Ember from 'ember'; - -export default Ember.Component.extend({ - tagName: 'ul', - layoutName: 'components/item-collection', -}); diff --git a/ember/app/components/menu-list.js b/ember/app/components/menu-list.js deleted file mode 100644 index da93e4c22..000000000 --- a/ember/app/components/menu-list.js +++ /dev/null @@ -1,6 +0,0 @@ -import Ember from 'ember'; - -export default Ember.Component.extend({ - tagName: 'ul', - layoutName: 'components/menu-list' -}); diff --git a/ember/app/components/menu-item.js b/ember/app/components/ui/controls/action-button.js similarity index 70% rename from ember/app/components/menu-item.js rename to ember/app/components/ui/controls/action-button.js index f96caadae..f24158268 100644 --- a/ember/app/components/menu-item.js +++ b/ember/app/components/ui/controls/action-button.js @@ -1,6 +1,6 @@ import Ember from 'ember'; -var MenuItem = Ember.Component.extend({ +export default Ember.Component.extend({ title: '', icon: '', className: '', @@ -8,6 +8,8 @@ var MenuItem = Ember.Component.extend({ divider: false, active: false, + classNames: ['btn', 'btn-default'], + tagName: 'a', attributeBindings: ['href'], classNameBindings: ['className'], @@ -19,14 +21,4 @@ var MenuItem = Ember.Component.extend({ // this.sendAction('action'); this.get('action')(); } -}); - -MenuItem.reopenClass({ - separator: function() { - return this.create({ - divider: true - }); - } -}) - -export default MenuItem; +}); \ No newline at end of file diff --git a/ember/app/components/ui/controls/dropdown-button.js b/ember/app/components/ui/controls/dropdown-button.js new file mode 100644 index 000000000..ff74c9287 --- /dev/null +++ b/ember/app/components/ui/controls/dropdown-button.js @@ -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') +}); diff --git a/ember/app/components/dropdown-select.js b/ember/app/components/ui/controls/dropdown-select.js similarity index 79% rename from ember/app/components/dropdown-select.js rename to ember/app/components/ui/controls/dropdown-select.js index 779c54120..367cdccbf 100644 --- a/ember/app/components/dropdown-select.js +++ b/ember/app/components/ui/controls/dropdown-select.js @@ -1,10 +1,8 @@ import Ember from 'ember'; -import Menu from '../utils/menu'; - export default Ember.Component.extend({ items: [], - layoutName: 'components/dropdown-select', + layoutName: 'components/ui/controls/dropdown-select', classNames: ['dropdown', 'dropdown-select', 'btn-group'], classNameBindings: ['itemCountClass'], @@ -24,7 +22,12 @@ export default Ember.Component.extend({ return 'item-count-'+this.get('items.length'); }.property('items.length'), - currentItem: function() { + activeItem: function() { return this.get('menu.childViews').findBy('active'); }.property('menu.childViews.@each.active') + +}).reopenClass({ + createWithItems: function(items) { + return this.create({items: items}); + } }); diff --git a/ember/app/components/ui/controls/dropdown-split.js b/ember/app/components/ui/controls/dropdown-split.js new file mode 100644 index 000000000..099479e69 --- /dev/null +++ b/ember/app/components/ui/controls/dropdown-split.js @@ -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.[]') +}); diff --git a/ember/app/components/ui/controls/item-list.js b/ember/app/components/ui/controls/item-list.js new file mode 100644 index 000000000..72899f14e --- /dev/null +++ b/ember/app/components/ui/controls/item-list.js @@ -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.[]') +}); diff --git a/ember/app/components/loading-indicator.js b/ember/app/components/ui/controls/loading-indicator.js similarity index 99% rename from ember/app/components/loading-indicator.js rename to ember/app/components/ui/controls/loading-indicator.js index 6da887851..fc3c97e22 100644 --- a/ember/app/components/loading-indicator.js +++ b/ember/app/components/ui/controls/loading-indicator.js @@ -1,7 +1,6 @@ import Ember from 'ember'; export default Ember.Component.extend({ - classNames: ['loading'], layout: Ember.Handlebars.compile(' '), @@ -9,5 +8,4 @@ export default Ember.Component.extend({ didInsertElement: function() { this.$().spin(this.get('size')); } - }); diff --git a/ember/app/components/search-input.js b/ember/app/components/ui/controls/search-input.js similarity index 100% rename from ember/app/components/search-input.js rename to ember/app/components/ui/controls/search-input.js diff --git a/ember/app/components/select-input.js b/ember/app/components/ui/controls/select-input.js similarity index 99% rename from ember/app/components/select-input.js rename to ember/app/components/ui/controls/select-input.js index 2800009a2..18c797501 100644 --- a/ember/app/components/select-input.js +++ b/ember/app/components/ui/controls/select-input.js @@ -1,9 +1,7 @@ import Ember from 'ember'; export default Ember.View.extend({ - tagName: 'span', classNames: ['select'], layout: Ember.Handlebars.compile('{{view "select" content=view.content optionValuePath=view.optionValuePath optionLabelPath=view.optionLabelPath value=view.value}} {{fa-icon "sort"}}') - }); diff --git a/ember/app/components/menu-item-container.js b/ember/app/components/ui/items/component-item.js similarity index 63% rename from ember/app/components/menu-item-container.js rename to ember/app/components/ui/items/component-item.js index bb7e0d3bd..5ab602774 100644 --- a/ember/app/components/menu-item-container.js +++ b/ember/app/components/ui/items/component-item.js @@ -2,5 +2,5 @@ import Ember from 'ember'; export default Ember.Component.extend({ tagName: 'li', - layoutName: 'components/menu-item-container' + layoutName: 'components/ui/items/component-item' }); diff --git a/ember/app/components/nav-item.js b/ember/app/components/ui/items/nav-item.js similarity index 100% rename from ember/app/components/nav-item.js rename to ember/app/components/ui/items/nav-item.js diff --git a/ember/app/components/menu-item-separator.js b/ember/app/components/ui/items/separator-item.js similarity index 57% rename from ember/app/components/menu-item-separator.js rename to ember/app/components/ui/items/separator-item.js index 4845311e3..3b1c679c8 100644 --- a/ember/app/components/menu-item-separator.js +++ b/ember/app/components/ui/items/separator-item.js @@ -1,6 +1,6 @@ import Ember from 'ember'; export default Ember.Component.extend({ - liClass: 'divider', - active: false -}); + tagName: 'li', + classNames: ['divider'] +}); \ No newline at end of file diff --git a/ember/app/templates/application.hbs b/ember/app/templates/application.hbs index 2f5eae784..483f43f9c 100644 --- a/ember/app/templates/application.hbs +++ b/ember/app/templates/application.hbs @@ -23,17 +23,17 @@ {{/link-to}} - {{menu-list items=headerPrimaryControls class="nav"}} + {{ui/controls/item-list items=headerPrimaryControls class="nav"}}
    - {{menu-list items=headerSecondaryControls}} + {{ui/controls/item-list items=headerSecondaryControls}}
    @@ -46,7 +46,7 @@
    - {{menu-list items=footerControls}} + {{ui/controls/item-list items=footerControls}}
    diff --git a/ember/app/templates/components/discussion-post.hbs b/ember/app/templates/components/discussion-post.hbs deleted file mode 100644 index 443143e5c..000000000 --- a/ember/app/templates/components/discussion-post.hbs +++ /dev/null @@ -1,13 +0,0 @@ -{{#if view.controls}} -
    - - {{menu-list items=view.controls class="dropdown-menu pull-right"}} -
    -{{/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}} diff --git a/ember/app/templates/components/discussions-list-item.hbs b/ember/app/templates/components/discussions/discussion-listing.hbs similarity index 87% rename from ember/app/templates/components/discussions-list-item.hbs rename to ember/app/templates/components/discussions/discussion-listing.hbs index bf443df94..096e67475 100644 --- a/ember/app/templates/components/discussions-list-item.hbs +++ b/ember/app/templates/components/discussions/discussion-listing.hbs @@ -1,7 +1,4 @@ -
    - - {{menu-list items=controls class="dropdown-menu pull-right"}} -
    +{{ui/controls/dropdown-button items=controls class="contextual-controls"}}
    diff --git a/ember/app/templates/components/post-type-comment.hbs b/ember/app/templates/components/discussions/post-comment.hbs similarity index 100% rename from ember/app/templates/components/post-type-comment.hbs rename to ember/app/templates/components/discussions/post-comment.hbs diff --git a/ember/app/templates/components/post-type-title.hbs b/ember/app/templates/components/discussions/post-title.hbs similarity index 100% rename from ember/app/templates/components/post-type-title.hbs rename to ember/app/templates/components/discussions/post-title.hbs diff --git a/ember/app/templates/components/discussions/post.hbs b/ember/app/templates/components/discussions/post.hbs new file mode 100644 index 000000000..33b8bb121 --- /dev/null +++ b/ember/app/templates/components/discussions/post.hbs @@ -0,0 +1,12 @@ +{{!-- {{#if view.controls}} +
    + + {{menu-list items=controls class="dropdown-menu pull-right"}} +
    +{{/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}} diff --git a/ember/app/templates/components/discussion-scrollbar.hbs b/ember/app/templates/components/discussions/scrollbar.hbs similarity index 100% rename from ember/app/templates/components/discussion-scrollbar.hbs rename to ember/app/templates/components/discussions/scrollbar.hbs diff --git a/ember/app/templates/components/menu-item-container.hbs b/ember/app/templates/components/menu-item-container.hbs deleted file mode 100644 index 6c76e440e..000000000 --- a/ember/app/templates/components/menu-item-container.hbs +++ /dev/null @@ -1 +0,0 @@ -{{view item}} \ No newline at end of file diff --git a/ember/app/templates/components/menu-list.hbs b/ember/app/templates/components/menu-list.hbs deleted file mode 100644 index 0eddfdb34..000000000 --- a/ember/app/templates/components/menu-list.hbs +++ /dev/null @@ -1,3 +0,0 @@ -{{#each item in items}} - {{view item}} -{{/each}} diff --git a/ember/app/templates/components/dropdown-button.hbs b/ember/app/templates/components/ui/controls/dropdown-button.hbs similarity index 80% rename from ember/app/templates/components/dropdown-button.hbs rename to ember/app/templates/components/ui/controls/dropdown-button.hbs index 166c04c1c..d48fb2bc2 100644 --- a/ember/app/templates/components/dropdown-button.hbs +++ b/ember/app/templates/components/ui/controls/dropdown-button.hbs @@ -4,5 +4,5 @@ {{title}} {{fa-icon "caret-down" class="icon-caret"}} - {{menu-list items=containedItems class=dropdownMenuClass}} + {{ui/controls/item-list items=items class=dropdownMenuClass}} {{/if}} \ No newline at end of file diff --git a/ember/app/templates/components/dropdown-select.hbs b/ember/app/templates/components/ui/controls/dropdown-select.hbs similarity index 56% rename from ember/app/templates/components/dropdown-select.hbs rename to ember/app/templates/components/ui/controls/dropdown-select.hbs index c9edd6eaa..9a57f27c9 100644 --- a/ember/app/templates/components/dropdown-select.hbs +++ b/ember/app/templates/components/ui/controls/dropdown-select.hbs @@ -1,7 +1,7 @@ {{#if items}} - {{menu-list items=items class=dropdownMenuClass viewName="menu"}} + {{ui/controls/item-list items=items class=dropdownMenuClass viewName="menu"}} {{/if}} \ No newline at end of file diff --git a/ember/app/templates/components/dropdown-split.hbs b/ember/app/templates/components/ui/controls/dropdown-split.hbs similarity index 66% rename from ember/app/templates/components/dropdown-split.hbs rename to ember/app/templates/components/ui/controls/dropdown-split.hbs index 3175accb3..ecbb4ed42 100644 --- a/ember/app/templates/components/dropdown-split.hbs +++ b/ember/app/templates/components/ui/controls/dropdown-split.hbs @@ -1,8 +1,8 @@ {{#if items}} - {{view items.firstItem class=mainButtonClass}} + {{view firstItem class=mainButtonClass}} - {{menu-list items=containedItems class=dropdownMenuClass}} + {{ui/controls/item-list items=items class=dropdownMenuClass}} {{/if}} \ No newline at end of file diff --git a/ember/app/templates/components/item-collection.hbs b/ember/app/templates/components/ui/controls/item-list.hbs similarity index 50% rename from ember/app/templates/components/item-collection.hbs rename to ember/app/templates/components/ui/controls/item-list.hbs index 0eddfdb34..1d60ed182 100644 --- a/ember/app/templates/components/item-collection.hbs +++ b/ember/app/templates/components/ui/controls/item-list.hbs @@ -1,3 +1,3 @@ -{{#each item in items}} +{{#each item in listItems}} {{view item}} {{/each}} diff --git a/ember/app/templates/components/search-input.hbs b/ember/app/templates/components/ui/controls/search-input.hbs similarity index 100% rename from ember/app/templates/components/search-input.hbs rename to ember/app/templates/components/ui/controls/search-input.hbs diff --git a/ember/app/templates/components/text-editor.hbs b/ember/app/templates/components/ui/controls/text-editor.hbs similarity index 100% rename from ember/app/templates/components/text-editor.hbs rename to ember/app/templates/components/ui/controls/text-editor.hbs diff --git a/ember/app/templates/components/ui/items/component-item.hbs b/ember/app/templates/components/ui/items/component-item.hbs new file mode 100644 index 000000000..d56136e7a --- /dev/null +++ b/ember/app/templates/components/ui/items/component-item.hbs @@ -0,0 +1 @@ +{{view component}} \ No newline at end of file diff --git a/ember/app/templates/composer.hbs b/ember/app/templates/composer.hbs index ec63b0940..0e6734076 100644 --- a/ember/app/templates/composer.hbs +++ b/ember/app/templates/composer.hbs @@ -11,7 +11,7 @@

    {{{title}}}

    - {{text-editor placeholder=""}} + {{ui/controls/text-editor placeholder=""}}
    diff --git a/ember/app/templates/discussions.hbs b/ember/app/templates/discussions.hbs index c18e15832..c940cd9f5 100644 --- a/ember/app/templates/discussions.hbs +++ b/ember/app/templates/discussions.hbs @@ -1,44 +1,40 @@
    - - {{#link-to (query-params show="discussions") class="btn btn-default btn-sm"}}{{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="discussions") class="btn btn-default"}}{{fa-icon "bars"}}{{/link-to}} + {{#link-to (query-params show="posts") class="btn btn-default"}}{{fa-icon "square-o"}}{{/link-to}} - {{select-input - content=sortOptions - optionValuePath="content.sort" - optionLabelPath="content.label" - value=sort}} + {{ui/controls/select-input class="control-sort" content=sortOptions optionValuePath="content.sort" optionLabelPath="content.label" value=sort}}
    - + {{#ui/controls/action-button class="control-markAsRead"}}{{fa-icon "check"}}{{/ui/controls/action-button}}
    {{#if resultsLoading}} - {{loading-indicator size="small"}} + {{ui/controls/loading-indicator size="small"}} {{else}}
      {{#each discussion in content}} - {{discussions-list-item discussion=discussion}} + {{discussions/discussion-listing discussion=discussion}} {{/each}}
    {{#if moreResults}}
    {{#if loadingMore}} - {{loading-indicator size="small"}} + {{ui/controls/loading-indicator size="small"}} {{else}} - + {{#ui/controls/action-button class="control-loadMore" action="loadMore"}}Load More{{/ui/controls/action-button}} {{/if}}
    {{/if}} diff --git a/ember/app/utils/menu.js b/ember/app/utils/menu.js deleted file mode 100644 index 533eef4da..000000000 --- a/ember/app/utils/menu.js +++ /dev/null @@ -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); - } - -}); diff --git a/ember/app/utils/named-container-view.js b/ember/app/utils/named-container-view.js deleted file mode 100644 index ca1f7b9b3..000000000 --- a/ember/app/utils/named-container-view.js +++ /dev/null @@ -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); - } - -}); diff --git a/ember/app/utils/tagged-array.js b/ember/app/utils/tagged-array.js new file mode 100644 index 000000000..76b253082 --- /dev/null +++ b/ember/app/utils/tagged-array.js @@ -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]; + } +}); diff --git a/ember/app/views/discussion.js b/ember/app/views/discussion.js index 2b5a92e30..dff73d884 100644 --- a/ember/app/views/discussion.js +++ b/ember/app/views/discussion.js @@ -1,16 +1,15 @@ import Ember from 'ember'; -import NamedContainerView from '../utils/named-container-view'; -import Menu from '../utils/menu'; -import MenuItem from '../components/menu-item'; -import DropdownSplit from '../components/dropdown-split'; -import DropdownButton from '../components/dropdown-button'; -import DiscussionScrollbar from '../components/discussion-scrollbar'; +import TaggedArray from '../utils/tagged-array'; +import ActionButton from '../components/ui/controls/action-button'; +import DropdownSplit from '../components/ui/controls/dropdown-split'; +import DropdownButton from '../components/ui/controls/dropdown-button'; +import DiscussionScrollbar from '../components/discussions/stream-scrollbar'; import PostStreamMixin from '../mixins/post-stream'; 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 // 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() { // 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 // 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) { - this.set('controls', Menu.create()); - this.trigger('populateControls', this.get('controls')); - sidebar.pushObject(DropdownSplit.create({ - items: this.get('controls'), + var items = TaggedArray.create(); + this.trigger('populateControls', items); + sidebarItems.pushObject(DropdownSplit.create({ + items: items, icon: 'reply', buttonClass: 'btn-primary', menuClass: 'pull-right' - })); + }), 'controls'); sidebar.pushObject(DropdownButton.create({items: this.get('controls')})); diff --git a/ember/app/views/discussions.js b/ember/app/views/discussions.js index b16e7ed47..30e1e4ec0 100644 --- a/ember/app/views/discussions.js +++ b/ember/app/views/discussions.js @@ -1,13 +1,13 @@ import Ember from 'ember'; -import DropdownSelect from '../components/dropdown-select'; -import ButtonItem from '../components/button-item'; -import NavItem from '../components/nav-item'; -import Menu from '../utils/menu'; +import DropdownSelect from '../components/ui/controls/dropdown-select'; +import ActionButton from '../components/ui/controls/action-button'; +import NavItem from '../components/ui/items/nav-item'; +import TaggedArray from '../utils/tagged-array'; export default Ember.View.extend({ - sidebarView: Ember.ContainerView.extend(), + sidebarItems: null, classNameBindings: ['pinned'], @@ -17,7 +17,9 @@ export default Ember.View.extend({ didInsertElement: function() { - this.trigger('populateSidebar', this.get('sidebar')); + var sidebarItems = TaggedArray.create(); + this.trigger('populateSidebar', sidebarItems); + this.set('sidebarItems', sidebarItems); var view = this; @@ -58,44 +60,37 @@ export default Ember.View.extend({ }); }, - setupSidebar: function(sidebar) { - sidebar.pushObject(ButtonItem.create({ + populateSidebarDefault: function(sidebar) { + var newDiscussion = ActionButton.create({ title: 'Start a Discussion', icon: 'edit', class: 'btn-primary' - })); + }) + sidebar.pushObjectWithTag(newDiscussion, 'newDiscussion'); - var nav = Menu.create(); + var nav = TaggedArray.create(); this.trigger('populateNav', nav); - sidebar.pushObject(DropdownSelect.create({ - items: nav - })); + sidebar.pushObjectWithTag(DropdownSelect.createWithItems(nav), 'nav'); }.on('populateSidebar'), - setupNav: function(nav) { - nav.addItem('all', NavItem.create({ + populateNavDefault: function(nav) { + nav.pushObjectWithTag(NavItem.create({ title: 'All Discussions', icon: 'comments-o', linkTo: '"discussions" (query-params filter="")' - })); + }), 'all'); - nav.addItem('private', NavItem.create({ + nav.pushObjectWithTag(NavItem.create({ title: 'Private', icon: 'envelope-o', linkTo: '"discussions" (query-params filter="private")' - })); + }), 'private'); - nav.addItem('following', NavItem.create({ + nav.pushObjectWithTag(NavItem.create({ title: 'Following', icon: 'star', linkTo: '"discussions" (query-params filter="following")' - })); - - nav.addItem('categories', NavItem.create({ - title: 'Categories', - icon: 'reorder', - linkTo: '"categories"' - })); + }), 'following'); }.on('populateNav'), willDestroyElement: function() {