summaryrefslogtreecommitdiffstats
path: root/client/components/main
diff options
context:
space:
mode:
Diffstat (limited to 'client/components/main')
-rw-r--r--client/components/main/events.js8
-rw-r--r--client/components/main/header.jade40
-rw-r--r--client/components/main/header.js10
-rw-r--r--client/components/main/header.styl266
-rw-r--r--client/components/main/helpers.js63
-rw-r--r--client/components/main/layouts.jade17
-rw-r--r--client/components/main/popup.js16
-rw-r--r--client/components/main/popup.styl585
-rw-r--r--client/components/main/popup.tpl.jade13
-rw-r--r--client/components/main/rendered.js40
-rw-r--r--client/components/main/router.js5
-rw-r--r--client/components/main/spinner.styl45
-rw-r--r--client/components/main/spinner.tpl.jade6
-rw-r--r--client/components/main/templates.html18
14 files changed, 1132 insertions, 0 deletions
diff --git a/client/components/main/events.js b/client/components/main/events.js
new file mode 100644
index 00000000..beb90c5e
--- /dev/null
+++ b/client/components/main/events.js
@@ -0,0 +1,8 @@
+Template.editor.events({
+ // Pressing Ctrl+Enter should submit the form.
+ 'keydown textarea': function(event) {
+ if (event.keyCode === 13 && (event.metaKey || event.ctrlKey)) {
+ $(event.currentTarget).parents('form:first').submit();
+ }
+ }
+});
diff --git a/client/components/main/header.jade b/client/components/main/header.jade
new file mode 100644
index 00000000..588c9b6e
--- /dev/null
+++ b/client/components/main/header.jade
@@ -0,0 +1,40 @@
+template(name="header")
+ #header(class=currentBoard.colorClass)
+ //-
+ If the user is connected we display a small "quick-access" top bar that
+ list all starred boards with a link to go there. This is inspired by the
+ Reddit "subreddit" bar.
+ The first link goes to the boards page.
+ if currentUser
+ #header-quick-access
+ ul
+ li
+ +linkTo(route="Boards")
+ span.fa.fa-home
+ | All boards
+ each currentUser.starredBoards
+ li.separator -
+ li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}")
+ +linkTo(route="Board" data=this)
+ = title
+ else
+ li.current Star a board to add a shortcut in this bar.
+
+ li
+ a.js-create-board
+ i.fa.fa-plus(title="Create a new board")
+
+ +headerUserBar
+
+ //-
+ The main bar is a colorful bar that provide all the meta-data for the
+ current page. This bar is contextual based.
+ If the user is not connected we display "sign in" and "log in" buttons.
+ #header-main-bar
+ if $.Session.get 'currentBoard'
+ +headerBoard
+ else
+ +headerTitle
+
+template(name="headerTitle")
+ h1 LibreBoard
diff --git a/client/components/main/header.js b/client/components/main/header.js
new file mode 100644
index 00000000..2a545309
--- /dev/null
+++ b/client/components/main/header.js
@@ -0,0 +1,10 @@
+Template.header.helpers({
+ // Reactively set the color of the page from the color of the current board.
+ headerTemplate: function() {
+ return 'headerBoard';
+ }
+});
+
+Template.header.events({
+ 'click .js-create-board': Popup.open('createBoard')
+});
diff --git a/client/components/main/header.styl b/client/components/main/header.styl
new file mode 100644
index 00000000..1177d930
--- /dev/null
+++ b/client/components/main/header.styl
@@ -0,0 +1,266 @@
+@import 'nib'
+
+global-reset()
+
+#header
+ color: white
+ transition: background-color 0.4s
+ background: #27AE60
+
+ #header-quick-access
+ background-color: rgba(0, 0, 0, 0.2)
+ padding: 4px 10px
+ height: 16px
+ font-size: 12px
+ display: flex
+
+ ul li, #header-user-bar
+ color: darken(white, 17%)
+
+ a
+ color: inherit
+ text-decoration: none
+
+ &:hover
+ color: white
+
+ ul
+ flex: 1
+ transition: opacity 0.2s
+ margin-left: 5px
+
+ li
+ display: block
+ float: left
+ width: auto
+ color: darken(white, 15%)
+ padding: 0 4px 1px 4px
+
+ &.separator
+ padding: 0 2px 1px 2px
+
+ &.current
+ font-style: italic
+
+ &:first-child .fa-home
+ margin-right: 5px
+
+ #header-main-bar
+ height: 30px
+ padding: 8px
+
+ h1
+ font-size: 19px
+ line-height: 1.7em
+ margin: 0 20px 0 10px
+ float: left
+
+ &.header-board-menu
+ cursor: pointer
+
+ .fa-angle-down
+ font-size: 0.8em
+ // line-height: 1.1em
+ margin-left: 5px
+
+ .board-header-starred .fa
+ color: yellow
+
+ .board-header-members
+ float: right
+
+ .member
+ display: block
+ width: 32px
+ height: @width
+
+ .add-board-member
+ color: white
+ display: flex
+ align-items: center
+ justify-content: center
+ border: 1px solid white
+ height: 32px - 2px
+ width: @height
+
+ i.fa-plus
+ margin-top: 2px
+
+ .header-btn:last-child
+ margin-right: 0
+
+
+
+// #header {
+// background: #138871;
+// height: 30px;
+// overflow: hidden;
+// padding: 5px;
+// position: relative;
+// z-index: 10;
+// }
+
+// .header-logo {
+// bottom: 0;
+// display: block;
+// height: 25px;
+// left: 50%;
+// position: absolute;
+// top: 8px;
+// width: 80px;
+// margin-left: - @width/2;
+// text-align: center;
+// z-index: 2;
+// opacity: .5;
+// transition: opacity ease-in 85ms;
+// color: white;
+// font-size: 22px;
+// text-decoration: none;
+// background-image: url('/logos/white_logo.png');
+
+// &:hover {
+// opacity: .8;
+// color: white;
+// }
+// }
+
+// .header-btn.header-btn-feedback {
+// background: rgba(255, 255, 255, .1);
+// background: linear-gradient(to bottom, rgba(255, 255, 255, .1) 0, rgba(255, 255, 255, .05) 100%);
+// padding-left: 22px;
+// margin-right: 16px;
+
+// .header-btn-icon {
+// top: 1px;
+// }
+// }
+
+.header-btn {
+ border-radius: 3px;
+ user-select: none;
+ background: rgba(255, 255, 255, .3);
+ background: linear-gradient(to bottom, rgba(255, 255, 255, .3) 0, rgba(255, 255, 255, .2) 100%);
+ color: #f3f3f3;
+ display: block;
+ float: left;
+ font-weight: 700;
+ height: 30px;
+ line-height: 30px;
+ padding: 0 10px;
+ position: relative;
+ margin-right: 8px;
+ min-width: 30px;
+ text-decoration: none;
+ cursor: pointer;
+
+ .header-btn-icon {
+ font-size: 16px;
+ line-height: 28px;
+ position: absolute;
+ top: 0;
+ left: 0;
+ }
+
+ &.new-notifications {
+ background: #ba1212;
+
+ &:hover {
+ background: #d11515;
+ }
+ }
+
+ &.header-member .member {
+ margin: 0;
+ border-top-left-radius: 3px;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 3px;
+
+ &:hover .member-avatar {
+ opacity: 1;
+ }
+ }
+
+ &:hover {
+ background: rgba(255, 255, 255, .4);
+ background: linear-gradient(to bottom, rgba(255, 255, 255, .4) 0, rgba(255, 255, 255, .3) 100%);
+ color: #fff;
+
+ .header-btn-count {
+ background: #d11515;
+ }
+ }
+
+ &:active {
+ background: rgba(255, 255, 255, .4);
+ background: linear-gradient(to bottom, rgba(255, 255, 255, .4) 0, rgba(255, 255, 255, .3) 100%);
+ }
+
+ &.upgrade {
+ margin-right: 16px;
+
+ .icon-sm {
+ padding: 6px 2px 6px 4px;
+ }
+ }
+
+ &.upgrade,
+ &.header-boards {
+ padding-left: 4px;
+ }
+
+ &.header-boards {
+ padding-right: 4px;
+ }
+
+ &.header-login,
+ &.header-signup {
+ padding: 0 12px;
+ }
+
+ &.header-signup {
+ background: #48b512;
+ background: linear-gradient(to bottom, #48b512 0, #3d990f 100%);
+
+ &:hover {
+ background: #3d990f;
+ background: linear-gradient(to bottom, #3d990f 0, #327d0c 100%);
+ }
+
+ &:active {
+ background: #327d0c;
+ }
+ }
+
+ &.header-go-to-boards {
+ padding: 0 8px 0 38px;
+ }
+
+ &.header-go-to-boards .member {
+ border-top-left-radius: 3px;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 3px;
+ position: absolute;
+ left: 0;
+ }
+}
+
+// .header-btn-text {
+// padding: 0 8px;
+// }
+
+// .header-notification-list ul {
+// margin-top: 8px;
+// }
+
+// .header-notification-list .action-comment {
+// max-height: 250px;
+// overflow-y: auto;
+// }
+
+// .header-user {
+// position: absolute;
+// top: 5px;
+// right: 0;
+// }
diff --git a/client/components/main/helpers.js b/client/components/main/helpers.js
new file mode 100644
index 00000000..7ad602f1
--- /dev/null
+++ b/client/components/main/helpers.js
@@ -0,0 +1,63 @@
+var Helpers = {
+ error: function() {
+ return Session.get('error');
+ },
+
+ toLowerCase: function(text) {
+ return text && text.toLowerCase();
+ },
+
+ toUpperCase: function(text) {
+ return text && text.toUpperCase();
+ },
+
+ firstChar: function(text) {
+ return text && text[0].toUpperCase();
+ },
+
+ session: function(prop) {
+ return Session.get(prop);
+ },
+
+ getUser: function(userId) {
+ return Users.findOne(userId);
+ }
+};
+
+// Register all Helpers
+_.each(Helpers, function(fn, name) { Blaze.registerHelper(name, fn); });
+
+// XXX I believe we should compute a HTML rendered field on the server that
+// would handle markdown, emojies and user mentions. We can simply have two
+// fields, one source, and one compiled version (in HTML) and send only the
+// compiled version to most users -- who don't need to edit.
+// In the meantime, all the transformation are done on the client using the
+// Blaze API.
+var at = HTML.CharRef({html: '@', str: '@'});
+Blaze.Template.registerHelper('mentions', new Template('mentions', function() {
+ var view = this;
+ var content = Blaze.toHTML(view.templateContentBlock);
+ var currentBoard = Session.get('currentBoard');
+ var knowedUsers = _.map(currentBoard.members, function(member) {
+ member.username = Users.findOne(member.userId).username;
+ return member;
+ });
+
+ var mentionRegex = /\B@(\w*)/gi;
+ var currentMention, knowedUser, href, linkClass, linkValue, link;
+ while (currentMention = mentionRegex.exec(content)) {
+
+ knowedUser = _.findWhere(knowedUsers, { username: currentMention[1] });
+ if (! knowedUser)
+ continue;
+
+ linkValue = [' ', at, knowedUser.username];
+ href = Router.url('Profile', { username: knowedUser.username });
+ linkClass = 'atMention' + (knowedUser.userId === Meteor.userId() ? ' me' : '');
+ link = HTML.A({ href: href, 'class': linkClass }, linkValue);
+
+ content = content.replace(currentMention[0], Blaze.toHTML(link));
+ }
+
+ return HTML.Raw(content);
+}));
diff --git a/client/components/main/layouts.jade b/client/components/main/layouts.jade
new file mode 100644
index 00000000..18df4d9e
--- /dev/null
+++ b/client/components/main/layouts.jade
@@ -0,0 +1,17 @@
+head
+ title LibreBoard
+ meta(name="viewport"
+ content="maximum-scale=1.0,width=device-width,initial-scale=1.0,user-scalable=0")
+ link(rel="shortcut icon" href="/favicon.png")
+
+template(name="userFormsLayout")
+ h1.at-form-landing-logo
+ img(src="/logo.png" title="LibreBoard")
+ +yield
+
+template(name="defaultLayout")
+ #surface
+ +header
+ #content
+ +yield
+
diff --git a/client/components/main/popup.js b/client/components/main/popup.js
new file mode 100644
index 00000000..53695d10
--- /dev/null
+++ b/client/components/main/popup.js
@@ -0,0 +1,16 @@
+Popup.template.events({
+ click: function(evt) {
+ if (evt.originalEvent) {
+ evt.originalEvent.clickInPopup = true;
+ }
+ },
+ 'click .js-back-view': function() {
+ Popup.back();
+ },
+ 'click .js-close-popover': function() {
+ Popup.close();
+ },
+ 'click .js-confirm': function() {
+ this.__afterConfirmAction.call(this);
+ }
+});
diff --git a/client/components/main/popup.styl b/client/components/main/popup.styl
new file mode 100644
index 00000000..8c9993af
--- /dev/null
+++ b/client/components/main/popup.styl
@@ -0,0 +1,585 @@
+@import 'nib'
+
+.pop-over
+ background: #fff
+ border-radius: 3px
+ border: 1px solid #dbdbdb
+ border-bottom-color: #c2c2c2
+ box-shadow: 0 1px 6px rgba(0, 0, 0, .3)
+ display: none
+ overflow: hidden
+ position: absolute
+ width: 300px
+ z-index: 99999
+ margin-top: 5px
+
+ hr
+ margin: 4px -10px
+ width: 275px + 2*10px
+
+ input[type="text"],
+ input[type="email"],
+ input[type="password"]
+ margin: 4px 0 12px
+ width: 100%
+
+ input[type="file"]
+ width: 240px
+
+ select
+ width: 100%
+ margin-bottom: 14px
+
+ textarea
+ height: 72px
+ margin: 4px 0 12px
+ width: 100%
+
+ .empty
+ margin: 0
+
+ img
+ max-width: 270px
+
+ .custom-image img
+ height: 18px
+ left: 9px
+ top: 9px
+ width: 18px
+
+ .title
+ line-height: 32px
+
+ .header
+ height: 36px
+ position: relative
+ margin-bottom: 8px
+ background: #F7F7F7
+ border-bottom: 1px solid #dcdcdc
+ color: darken(white, 60%)
+
+ .header-title
+ display: block
+ line-height: 32px
+ padding-top: 4px
+ margin: 0 10px
+ font-weight: bold
+ overflow: hidden
+ text-overflow: ellipsis
+ white-space: nowrap
+
+ .back-btn, .close-btn
+ &:hover .icon-sm
+ color: darken(white, 80%)
+
+ .back-btn
+ padding: 10px
+ float: left
+
+ .close-btn
+ padding: 10px 10px 10px 4px
+ position: absolute
+ top: 0
+ right: 0
+
+ .content
+ overflow-x: hidden
+ overflow-y: auto
+ padding: 0 10px 10px
+ max-height: 550px
+
+ .quiet
+ padding: 6px 6px 4px
+
+ &.search-over
+ background: #f0f0f0
+ min-height: 114px
+
+ .header
+ display: none
+
+ .content
+ padding: 8px 4px 8px 10px
+ margin-right: 8px
+
+ &::-webkit-scrollbar-button
+ display: block
+ height: 4px
+ width: 4px
+
+.select-members-list
+ margin-bottom: 8px
+
+.pop-over-list
+
+ &.navigable li.not-selectable>a:hover,
+ li.not-selectable>a:hover
+ color: #8c8c8c
+ cursor: default
+
+ .icon-sm
+ color: #a6a6a6
+
+ li > a
+ cursor: pointer
+ display: block
+ font-weight: 700
+ padding: 6px 10px
+ position: relative
+ margin: 0 -10px
+ text-decoration: none
+
+ .item-name
+ display: block
+ width: auto
+ padding-right: 22px
+
+ &:hover
+ background-color: #005377
+ color: #fff
+
+ .sub-name,
+ .quiet
+ color: #eee
+
+ .unread-indicator
+ background: #fff
+
+ .icon-sm
+ color: #fff
+
+ .sub-name
+ clear: both
+ color: #8c8c8c
+ display: block
+ font-size: 12px
+ font-weight: 400
+ line-height: 15px
+ margin-top: 4px
+
+ &.current
+ background-color: #e2e6e9
+
+ .unread-indicator
+ background: #2e85b8
+ background: linear-gradient(to bottom, #2e85b8 0, #2b7cab 100%)
+ border-radius: 7px
+ display: block
+ height: 14px
+ opacity: 0
+ position: absolute
+ right: 16px
+ top: 8px
+ width: 14px
+
+ &.any
+ opacity: 1
+
+ &:active
+ background-color: #2e85b8
+
+ &.disabled
+ color: #8c8c8c
+ cursor: default
+
+ .vis-icon
+ opacity: .35
+
+ .icon-sm
+ color: #a6a6a6
+
+ &:hover
+ background: none
+
+ .sub-name,
+ .quiet
+ color: #8c8c8c
+
+ .icon-sm
+ color: #a6a6a6
+
+ &:active
+ background: none
+
+ &.inset li > a
+ border-radius: 3px
+ margin: 0
+
+ .pop-over-list.checkable
+
+ .icon-check
+ display: none
+ position: absolute
+ top: 6px
+ right: 12px
+
+ li.active a
+ padding-right: 28px
+
+ .icon-check
+ display: block
+
+ &.left-check
+
+ .icon-check
+ right: auto
+ left: 10px
+
+ li a
+ padding-right: 10px
+ padding-left: 30px
+
+ li.active a
+ padding-right: 10px
+
+ &.normal-weight li>a
+ font-weight: 400
+
+ &.navigable
+
+ li > a:hover
+ background-color: transparent
+ color: #4d4d4d
+
+ .sub-name,
+ .quiet
+ color: #8c8c8c
+
+ .icon-sm
+ color: #a6a6a6
+
+ li.selected > a
+ background-color: #005377
+ color: #fff
+
+ .sub-name,
+ .quiet
+ color: #eee
+
+ li.selected > a
+
+ &.current
+ background-color: #005377
+
+ .unread-indicator
+ background: #fff
+
+ .icon-sm
+ color: #fff
+
+ &:active
+ background-color: #005377
+
+.pop-over.miniprofile
+
+ .header
+ border-bottom-color: transparent
+ height: 30px
+ position: absolute
+ right: 0
+ top: 0
+ width: 60px
+ z-index: 1
+
+ .header-title
+ display: none
+
+ .pop-over-list
+ padding-top: 8px
+
+.mini-profile-info
+ margin-top: 8px
+ min-height: 56px
+ position: relative
+
+ .member-large
+ position: absolute
+ top: 2px
+ left: 2px
+
+ .info
+ margin: 0 0 0 64px
+ word-wrap: break-word
+
+ h3 a
+ text-decoration: none
+
+ &:hover
+ text-decoration: underline
+
+.pop-over.avdetail .header
+ border-bottom-color: transparent
+ height: 20px
+ position: absolute
+ top: 8px
+ left: 8px
+ right: 8px
+ z-index: 0
+
+.pop-over.avdetail .header-title
+ display: none
+
+.pop-over.avdetail .content
+ text-align: center
+
+.pop-over.avdetail .mem-info
+ margin: 2px 24px 8px
+ position: relative
+ z-index: 1
+ width: 222px
+
+.pop-over.avdetail .mem-info h3 a
+ text-decoration: none
+
+.pop-over.avdetail .mem-info h3 a:hover
+ text-decoration: underline
+
+.pop-over-label-list li,
+.pop-over-member-list li
+
+ &.disabled a
+ cursor:default
+
+ &:not(.disabled):hover a
+ background-color: #005377
+ color: #fff
+
+
+.pop-over-label-list,
+.pop-over-member-list,
+.pop-over-emoji-list,
+.pop-over-card-list
+ li
+ a
+ border-radius: 3px
+ display: block
+ height: 30px
+ line-height: 30px
+ overflow: hidden
+ position: relative
+ text-overflow: ellipsis
+ text-decoration: none
+ white-space: nowrap
+ padding: 4px
+ margin-bottom: 2px
+
+ &.multi-line
+ line-height: 16px
+
+ .member
+ margin-right: 8px
+
+ .card-label
+ float: left
+ height: 30px
+ margin: 0 8px 0 0
+ padding: 0
+ width: 30px
+
+ .option,
+ .icon-check
+ background-clip: content-box
+ background-origin: content-box
+ padding: 11px
+ position: absolute
+ top: 0
+ right: 0
+
+ .sub-name
+ font-size: 12px
+
+
+ &:last-child a
+ margin-bottom: 0
+
+ &.disabled
+ opacity: .5
+
+ &.active a,
+ &.selected a
+ background: none
+ color: #4d4d4d
+ cursor: default
+
+ .quiet
+ color: #8c8c8c
+
+ &.email-invite
+
+ .member
+ display: none
+
+ a
+ padding: 0 10px
+
+ &.selected a
+ background-color: #005377
+ color: #fff
+
+ .quiet
+ color: #eee
+
+ .card-label
+ border-radius: 3px
+
+ .icon-check
+ color: #fff
+
+ &.active a .icon-check
+ display: block
+
+ &.unconfirmed a.name
+ line-height: 16px
+
+ &.options li
+
+ &.selected a
+ padding-right: 28px
+
+ .option
+ display: block
+ opacity: .5
+
+ &:hover
+ opacity: 1
+
+ &.disabled.selected a
+ padding-right: 0
+
+ .option
+ display: none
+
+
+ &.no-option.selected a
+ padding-right: 6px
+
+ .option
+ display: none
+
+ &.collapsed
+
+ &.checkable li.active a
+ padding-right: 0
+
+ li
+ float: left
+ margin: 0 3px 3px 0
+
+ a
+ padding: 0
+ margin: 0
+ width: 30px
+
+ .member
+ opacity: .8
+
+ .full-name
+ display: none
+
+ &.selected a .member,
+ &.active.selected a .member
+ border-color: #005377
+ opacity: .9
+
+ &.active a
+
+ .member
+ border-color: #2e85b8
+ opacity: 1
+
+ .icon-check
+ border-radius: 3px
+ background-color: #2e85b8
+ bottom: 0
+ color: #fff
+ display: block
+ padding: 0
+ right: 0
+ top: auto
+
+ &.checkable li.active a
+ padding-right: 28px
+
+ &.filtered li
+ display: none
+
+ &.matches-filter
+ display: block
+
+ &.limited li.exceeds-limit
+ display: none
+
+.pop-over-emoji-list li > a
+ padding: 2px 4px
+
+ .emoji
+ margin: 0 6px
+
+.pop-over-card-list li > a
+ padding: 2px 4px
+
+.login-signup-popover
+ padding: 15px
+
+ .form-tabs
+ display: none
+
+ h1
+ margin-bottom: 15px
+
+ p
+ margin: 8px 0
+
+ .form-parts-container
+ position: relative
+
+ .active-box
+ position: absolute
+ top: 0
+ background: #e2e2e2
+ border: 1px solid #c9c9c9
+ border-radius: 3px
+ z-index: 1
+ height: 100%
+ width: 49%
+ transition-property: all
+ transition-duration: .4s
+ opacity: 1
+
+ &.start
+ opacity: 0
+ left: 25%
+
+ .signup-form,
+ .login-form
+ position: relative
+ box-sizing: border-box
+ padding: 20px
+ width: 50%
+ z-index: 2
+ opacity: .3
+ transition-property: opacity
+ transition-duration: .2s
+
+ .active
+ opacity: 1
+
+
+ .js-signup-form-pos
+ left: 0
+
+ .login-form
+ position: absolute
+ top: 0
+
+ .login-form .icon-google
+ position: absolute
+ left: 5px
+ top: 3px
+
+ .login-form .button.google
+ padding-left: 40px
+ margin: 0 0 15px 0
+
+ .js-login-form-pos
+ left: 50%
diff --git a/client/components/main/popup.tpl.jade b/client/components/main/popup.tpl.jade
new file mode 100644
index 00000000..ba24db0a
--- /dev/null
+++ b/client/components/main/popup.tpl.jade
@@ -0,0 +1,13 @@
+.pop-over.clearfix(
+ class="{{#unless title}}miniprofile{{/unless}}"
+ class=currentBoard.colorClass
+ style="display:block; left:{{offset.left}}px; top:{{offset.top}}px;")
+ .header.clearfix
+ if hasPopupParent
+ a.back-btn.js-back-view
+ i.fa.fa-chevron-left
+ span.header-title= title
+ a.close-btn.js-close-popover
+ i.fa.fa-times
+ .content.clearfix
+ +Template.dynamic(template=popupName data=dataContext)
diff --git a/client/components/main/rendered.js b/client/components/main/rendered.js
new file mode 100644
index 00000000..787e8225
--- /dev/null
+++ b/client/components/main/rendered.js
@@ -0,0 +1,40 @@
+Template.editor.rendered = function() {
+ this.$('textarea').textcomplete([
+ // Emojies
+ {
+ match: /\B:([\-+\w]*)$/,
+ search: function(term, callback) {
+ callback($.map(Emoji.values, function(emoji) {
+ return emoji.indexOf(term) === 0 ? emoji : null;
+ }));
+ },
+ template: function(value) {
+ var image = '<img src="' + Emoji.baseImagePath + value + '.png"></img>';
+ return image + value;
+ },
+ replace: function(value) {
+ return ':' + value + ':';
+ },
+ index: 1
+ },
+
+ // User mentions
+ {
+ match: /\B@(\w*)$/,
+ search: function(term, callback) {
+ var currentBoard = Boards.findOne(Session.get('currentBoard'));
+ callback($.map(currentBoard.members, function(member) {
+ var username = Users.findOne(member.userId).username;
+ return username.indexOf(term) === 0 ? username : null;
+ }));
+ },
+ template: function(value) {
+ return value;
+ },
+ replace: function(username) {
+ return '@' + username + ' ';
+ },
+ index: 1
+ }
+ ]);
+};
diff --git a/client/components/main/router.js b/client/components/main/router.js
new file mode 100644
index 00000000..bae832e8
--- /dev/null
+++ b/client/components/main/router.js
@@ -0,0 +1,5 @@
+Router.route('/', {
+ name: 'Home',
+ redirectLoggedInUsers: true,
+ authenticated: true
+});
diff --git a/client/components/main/spinner.styl b/client/components/main/spinner.styl
new file mode 100644
index 00000000..f4b8cc86
--- /dev/null
+++ b/client/components/main/spinner.styl
@@ -0,0 +1,45 @@
+/*
+ * From https://github.com/tobiasahlin/SpinKit
+ *
+ * Usage:
+ *
+ * <div class="sk-spinner sk-spinner-wave">
+ * <div class="sk-rect1"></div>
+ * <div class="sk-rect2"></div>
+ * <div class="sk-rect3"></div>
+ * <div class="sk-rect4"></div>
+ * <div class="sk-rect5"></div>
+ * </div>
+ *
+ */
+
+.sk-spinner-wave {
+
+ &.sk-spinner {
+ width: 50px;
+ height: 50px;
+ margin: auto;
+ margin-top: 30vh;
+ text-align: center;
+ font-size: 10px;
+ }
+
+ div {
+ background-color: #333;
+ height: 100%;
+ width: 6px;
+ display: inline-block;
+
+ animation: sk-waveStretchDelay 1.2s infinite ease-in-out;
+ }
+
+ .sk-rect2 { animation-delay: -1.1s }
+ .sk-rect3 { animation-delay: -1.0s }
+ .sk-rect4 { animation-delay: -0.9s }
+ .sk-rect5 { animation-delay: -0.8s }
+}
+
+@keyframes sk-waveStretchDelay {
+ 0%, 40%, 100% { transform: scaleY(0.4) }
+ 20% { transform: scaleY(1.0) }
+}
diff --git a/client/components/main/spinner.tpl.jade b/client/components/main/spinner.tpl.jade
new file mode 100644
index 00000000..9310a6e5
--- /dev/null
+++ b/client/components/main/spinner.tpl.jade
@@ -0,0 +1,6 @@
+.sk-spinner.sk-spinner-wave(class=currentBoard.colorClass)
+ .sk-rect1
+ .sk-rect2
+ .sk-rect3
+ .sk-rect4
+ .sk-rect5
diff --git a/client/components/main/templates.html b/client/components/main/templates.html
new file mode 100644
index 00000000..e9be0f93
--- /dev/null
+++ b/client/components/main/templates.html
@@ -0,0 +1,18 @@
+<template name="notfound">
+ {{ > message label='page-not-found'}}
+</template>
+
+<template name='message'>
+ <div class="big-message quiet {{ color }}">
+ <h1>{{_ label}}</h1>
+ {{#with pathFor route='Login'}}
+ <p>{{{_ 'page-maybe-private' this}}}</p>
+ {{/with}}
+ </div>
+</template>
+
+<template name="editor">
+ <textarea class="{{class}}" placeholder="{{_ 'comment-placeholder'}}" id="{{id}}" tabindex="1">{{> UI.contentBlock }}</textarea>
+</template>
+
+<template name="viewer">{{#markdown}}{{#emoji}}{{#mentions}}{{> UI.contentBlock }}{{/mentions}}{{/emoji}}{{/markdown}}</template>