summaryrefslogtreecommitdiffstats
path: root/client/components/main
diff options
context:
space:
mode:
Diffstat (limited to 'client/components/main')
-rw-r--r--client/components/main/editor.jade3
-rwxr-xr-xclient/components/main/editor.js9
-rw-r--r--client/components/main/header.jade73
-rw-r--r--client/components/main/header.js5
-rw-r--r--client/components/main/header.styl4
-rw-r--r--client/components/main/layouts.jade59
-rw-r--r--client/components/main/layouts.js115
-rw-r--r--client/components/main/layouts.styl123
-rw-r--r--client/components/main/popup.styl3
9 files changed, 330 insertions, 64 deletions
diff --git a/client/components/main/editor.jade b/client/components/main/editor.jade
index 31f533e6..dbd61715 100644
--- a/client/components/main/editor.jade
+++ b/client/components/main/editor.jade
@@ -1,5 +1,6 @@
template(name="editor")
textarea.editor(
+ dir="auto"
class="{{class}}"
id=id
autofocus=autofocus
@@ -7,7 +8,7 @@ template(name="editor")
+Template.contentBlock
template(name="viewer")
- .viewer
+ .viewer(dir="auto")
+mentions
+markdown
{{> UI.contentBlock }}
diff --git a/client/components/main/editor.js b/client/components/main/editor.js
index 888fbe00..88d8abf0 100755
--- a/client/components/main/editor.js
+++ b/client/components/main/editor.js
@@ -36,13 +36,18 @@ import sanitizeXss from 'xss';
const at = HTML.CharRef({html: '@', str: '@'});
Blaze.Template.registerHelper('mentions', new Template('mentions', function() {
const view = this;
+ let content = Blaze.toHTML(view.templateContentBlock);
const currentBoard = Boards.findOne(Session.get('currentBoard'));
+ if (!currentBoard)
+ return HTML.Raw(sanitizeXss(content));
const knowedUsers = currentBoard.members.map((member) => {
- member.username = Users.findOne(member.userId).username;
+ const u = Users.findOne(member.userId);
+ if(u){
+ member.username = u.username;
+ }
return member;
});
const mentionRegex = /\B@([\w.]*)/gi;
- let content = Blaze.toHTML(view.templateContentBlock);
let currentMention;
while ((currentMention = mentionRegex.exec(content)) !== null) {
diff --git a/client/components/main/header.jade b/client/components/main/header.jade
index dd071b3e..75e84c0c 100644
--- a/client/components/main/header.jade
+++ b/client/components/main/header.jade
@@ -4,39 +4,38 @@ template(name="header")
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.
- unless isSandstorm
- if currentUser
- #header-quick-access(class=currentBoard.colorClass)
- if isMiniScreen
- ul
- li
- a(href="{{pathFor 'home'}}")
- span.fa.fa-home
+ if currentUser
+ #header-quick-access(class=currentBoard.colorClass)
+ if isMiniScreen
+ ul
+ li
+ a(href="{{pathFor 'home'}}")
+ span.fa.fa-home
- if currentList
- each currentBoard.lists
- li(class="{{#if $.Session.equals 'currentList' _id}}current{{/if}}")
- a.js-select-list
- = title
- #header-new-board-icon
- else
- ul
- li
- a(href="{{pathFor 'home'}}")
- span.fa.fa-home
- | {{_ 'all-boards'}}
- each currentUser.starredBoards
- li.separator -
- li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}")
- a(href="{{pathFor 'board' id=_id slug=slug}}")
+ if currentList
+ each currentBoard.lists
+ li(class="{{#if $.Session.equals 'currentList' _id}}current{{/if}}")
+ a.js-select-list
= title
- else
- li.current {{_ 'quick-access-description'}}
+ #header-new-board-icon
+ else
+ ul
+ li
+ a(href="{{pathFor 'home'}}")
+ span.fa.fa-home
+ | {{_ 'all-boards'}}
+ each currentUser.starredBoards
+ li.separator -
+ li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}")
+ a(href="{{pathFor 'board' id=_id slug=slug}}")
+ = title
+ else
+ li.current {{_ 'quick-access-description'}}
- a#header-new-board-icon.js-create-board
- i.fa.fa-plus(title="Create a new board")
+ a#header-new-board-icon.js-create-board
+ i.fa.fa-plus(title="Create a new board")
- +headerUserBar
+ +headerUserBar
#header(class=currentBoard.colorClass)
//-
@@ -46,17 +45,16 @@ template(name="header")
#header-main-bar(class="{{#if wrappedHeader}}wrapper{{/if}}")
+Template.dynamic(template=headerBar)
- unless hideLogo
+ //unless hideLogo
+
//-
On sandstorm, the logo shouldn't be clickable, because we only have one
page/document on it, and we don't want to see the home page containing
the list of all boards.
- if isSandstorm
- .wekan-logo
- img(src="{{pathFor '/wekan-logo-header.png'}}" alt="Wekan")
- else
- a.wekan-logo(href="{{pathFor 'home'}}" title="{{_ 'header-logo-title'}}")
- img(src="{{pathFor '/wekan-logo-header.png'}}" alt="Wekan")
+
+ // unless currentSetting.hideLogo
+ // a.wekan-logo(href="{{pathFor 'home'}}" title="{{_ 'header-logo-title'}}")
+ // img(src="{{pathFor '/logo-header.png'}}" alt="")
if appIsOffline
+offlineWarning
@@ -66,7 +64,8 @@ template(name="header")
.announcement
p
i.fa.fa-bullhorn
- | #{announcement}
+ +viewer
+ | #{announcement}
i.fa.fa-times-circle.js-close-announcement
template(name="offlineWarning")
diff --git a/client/components/main/header.js b/client/components/main/header.js
index 7fbc5716..c05b1c3c 100644
--- a/client/components/main/header.js
+++ b/client/components/main/header.js
@@ -1,11 +1,16 @@
Meteor.subscribe('user-admin');
Meteor.subscribe('boards');
+Meteor.subscribe('setting');
Template.header.helpers({
wrappedHeader() {
return !Session.get('currentBoard');
},
+ currentSetting() {
+ return Settings.findOne();
+ },
+
hideLogo() {
return Utils.isMiniScreen() && Session.get('currentBoard');
},
diff --git a/client/components/main/header.styl b/client/components/main/header.styl
index f9455f8e..e3c7618d 100644
--- a/client/components/main/header.styl
+++ b/client/components/main/header.styl
@@ -188,8 +188,6 @@
width: 100%
padding: 10px 0px
z-index: 30
- position: absolute
- bottom: 0px
ul
width: calc(100% - 60px)
@@ -218,7 +216,7 @@
position: absolute
right: 0px
padding: 10px
- margin: -10px
+ margin: -10px 0 -10px -10px
.announcement,
.offline-warning
diff --git a/client/components/main/layouts.jade b/client/components/main/layouts.jade
index 4d76aabb..9543c5c5 100644
--- a/client/components/main/layouts.jade
+++ b/client/components/main/layouts.jade
@@ -1,7 +1,6 @@
head
- title Wekan
- meta(name="viewport"
- content="maximum-scale=1.0,width=device-width,initial-scale=1.0,user-scalable=0")
+ title
+ meta(name="viewport" content="maximum-scale=1.0,width=device-width,initial-scale=1.0,user-scalable=0")
meta(http-equiv="X-UA-Compatible" content="IE=edge")
//- XXX We should use pathFor in the following `href` to support the case
where the application is deployed with a path prefix, but it seems to be
@@ -9,34 +8,47 @@ head
packages.
link(rel="shortcut icon" href="/wekan-favicon.png")
link(rel="apple-touch-icon" href="/wekan-favicon.png")
+ link(rel="mask-icon" href="/wekan-logo-150.svg")
link(rel="manifest" href="/wekan-manifest.json")
template(name="userFormsLayout")
section.auth-layout
- h1.at-form-landing-logo
- img(src="{{pathFor '/wekan-logo.png'}}" alt="Wekan")
section.auth-dialog
- +Template.dynamic(template=content)
- div.at-form-lang
- select.select-lang.js-userform-set-language
- each languages
- if isCurrentLanguage
- option(value="{{tag}}" selected="selected") {{name}}
- else
- option(value="{{tag}}") {{name}}
+ if isLoading
+ +loader
+ else
+ +Template.dynamic(template=content)
+ if currentSetting.displayAuthenticationMethod
+ +connectionMethod(authenticationMethod=currentSetting.defaultAuthenticationMethod)
+ div.at-form-lang
+ select.select-lang.js-userform-set-language
+ each languages
+ if isCurrentLanguage
+ option(value="{{tag}}" selected="selected") {{name}}
+ else
+ option(value="{{tag}}") {{name}}
template(name="defaultLayout")
+header
#content
+ | {{{afterBodyStart}}}
+Template.dynamic(template=content)
+ | {{{beforeBodyEnd}}}
if (Modal.isOpen)
#modal
.overlay
- .modal-content
- a.modal-close-btn.js-close-modal
- i.fa.fa-times-thin
- +Template.dynamic(template=Modal.getHeaderName)
- +Template.dynamic(template=Modal.getTemplateName)
+ if (Modal.isWide)
+ .modal-content-wide.modal-container
+ a.modal-close-btn.js-close-modal
+ i.fa.fa-times-thin
+ +Template.dynamic(template=Modal.getHeaderName)
+ +Template.dynamic(template=Modal.getTemplateName)
+ else
+ .modal-content.modal-container
+ a.modal-close-btn.js-close-modal
+ i.fa.fa-times-thin
+ +Template.dynamic(template=Modal.getHeaderName)
+ +Template.dynamic(template=Modal.getTemplateName)
template(name="notFound")
+message(label='page-not-found')
@@ -47,3 +59,14 @@ template(name="message")
unless currentUser
with(pathFor route='atSignIn')
p {{{_ 'page-maybe-private' this}}}
+
+template(name="loader")
+ h1.loadingText {{_ 'loading'}}
+ .lds-roller
+ div
+ div
+ div
+ div
+ div
+ div
+ div
diff --git a/client/components/main/layouts.js b/client/components/main/layouts.js
index f12718a7..d5113a25 100644
--- a/client/components/main/layouts.js
+++ b/client/components/main/layouts.js
@@ -6,7 +6,36 @@ const i18nTagToT9n = (i18nTag) => {
return i18nTag;
};
+const validator = {
+ set(obj, prop, value) {
+ if (prop === 'state' && value !== 'signIn') {
+ $('.at-form-authentication').hide();
+ } else if (prop === 'state' && value === 'signIn') {
+ $('.at-form-authentication').show();
+ }
+ // The default behavior to store the value
+ obj[prop] = value;
+ // Indicate success
+ return true;
+ },
+};
+
+Template.userFormsLayout.onCreated(function() {
+ const instance = this;
+ instance.currentSetting = new ReactiveVar();
+ instance.isLoading = new ReactiveVar(false);
+
+ Meteor.subscribe('setting', {
+ onReady() {
+ instance.currentSetting.set(Settings.findOne());
+ return this.stop();
+ },
+ });
+});
+
Template.userFormsLayout.onRendered(() => {
+ AccountsTemplates.state.form.keys = new Proxy(AccountsTemplates.state.form.keys, validator);
+
const i18nTag = navigator.language;
if (i18nTag) {
T9n.setLanguage(i18nTagToT9n(i18nTag));
@@ -15,6 +44,22 @@ Template.userFormsLayout.onRendered(() => {
});
Template.userFormsLayout.helpers({
+ currentSetting() {
+ return Template.instance().currentSetting.get();
+ },
+
+ isLoading() {
+ return Template.instance().isLoading.get();
+ },
+
+ afterBodyStart() {
+ return currentSetting.customHTMLafterBodyStart;
+ },
+
+ beforeBodyEnd() {
+ return currentSetting.customHTMLbeforeBodyEnd;
+ },
+
languages() {
return _.map(TAPi18n.getLanguages(), (lang, code) => {
const tag = code;
@@ -47,6 +92,15 @@ Template.userFormsLayout.events({
T9n.setLanguage(i18nTagToT9n(i18nTag));
evt.preventDefault();
},
+ 'click #at-btn'(event, instance) {
+ if (FlowRouter.getRouteName() === 'atSignIn') {
+ instance.isLoading.set(true);
+ authentication(event, instance)
+ .then(() => {
+ instance.isLoading.set(false);
+ });
+ }
+ },
});
Template.defaultLayout.events({
@@ -54,3 +108,64 @@ Template.defaultLayout.events({
Modal.close();
},
});
+
+async function authentication(event, instance) {
+ const match = $('#at-field-username_and_email').val();
+ const password = $('#at-field-password').val();
+
+ if (!match || !password) return undefined;
+
+ const result = await getAuthenticationMethod(instance.currentSetting.get(), match);
+
+ if (result === 'password') return undefined;
+
+ // Stop submit #at-pwd-form
+ event.preventDefault();
+ event.stopImmediatePropagation();
+
+ switch (result) {
+ case 'ldap':
+ return new Promise((resolve) => {
+ Meteor.loginWithLDAP(match, password, function() {
+ resolve(FlowRouter.go('/'));
+ });
+ });
+
+ case 'cas':
+ return new Promise((resolve) => {
+ Meteor.loginWithCas(match, password, function() {
+ resolve(FlowRouter.go('/'));
+ });
+ });
+
+ default:
+ return undefined;
+ }
+}
+
+function getAuthenticationMethod({displayAuthenticationMethod, defaultAuthenticationMethod}, match) {
+ if (displayAuthenticationMethod) {
+ return $('.select-authentication').val();
+ }
+ return getUserAuthenticationMethod(defaultAuthenticationMethod, match);
+}
+
+function getUserAuthenticationMethod(defaultAuthenticationMethod, match) {
+ return new Promise((resolve) => {
+ try {
+ Meteor.subscribe('user-authenticationMethod', match, {
+ onReady() {
+ const user = Users.findOne();
+
+ const authenticationMethod = user
+ ? user.authenticationMethod
+ : defaultAuthenticationMethod;
+
+ resolve(authenticationMethod);
+ },
+ });
+ } catch(error) {
+ resolve(defaultAuthenticationMethod);
+ }
+ });
+}
diff --git a/client/components/main/layouts.styl b/client/components/main/layouts.styl
index a79ff337..46ee720c 100644
--- a/client/components/main/layouts.styl
+++ b/client/components/main/layouts.styl
@@ -62,6 +62,23 @@ body
float: right
font-size: 24px
+ .modal-content-wide
+ width: 800px
+ min-height: 0px
+ margin: 42px auto
+ padding: 12px
+ border-radius: 4px
+ background: darken(white, 13%)
+ z-index: 110
+
+ h2
+ margin-bottom: 25px
+
+ .modal-close-btn
+ display: block
+ float: right
+ font-size: 24px
+
h1
font-size: 22px
line-height: 1.2em
@@ -273,7 +290,7 @@ kbd
// Implement a thiner close icon as suggested in
// https://github.com/FortAwesome/Font-Awesome/issues/1540#issuecomment-68689950
.fa.fa-times-thin:before
- content: '\00d7';
+ content: '\00d7'
.fa.fa-globe.colorful, .fa.fa-bell.colorful
color: #4caf50
@@ -368,8 +385,8 @@ a
@media screen and (max-width: 800px)
#content
- margin: 1px 0px 49px 0px
- height: calc(100% - 96px)
+ margin: 1px 0px 0px 0px
+ height: calc(100% - 0px)
> .wrapper
margin-top: 0px
@@ -382,3 +399,103 @@ a
height: 37px
margin: 8px 10px 0 0
width: 50px
+
+.select-authentication
+ width: 100%
+
+.auth-layout
+ display: flex
+ flex-direction: column
+ align-items: center
+ justify-content: center
+ height: 100%
+
+ .auth-dialog
+ margin: 0 !important
+
+.loadingText
+ text-align: center
+
+.lds-roller
+ display: block
+ margin: auto
+ position: relative
+ width: 64px
+ height: 64px
+
+ div
+ animation: lds-roller 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite
+ transform-origin: 32px 32px
+
+ div:after
+ content: " "
+ display: block
+ position: absolute
+ width: 6px
+ height: 6px
+ border-radius: 50%
+ background: #dedede
+ margin: -3px 0 0 -3px
+
+ div:nth-child(1)
+ animation-delay: -0.036s
+
+ div:nth-child(1):after
+ top: 50px
+ left: 50px
+
+ div:nth-child(2)
+ animation-delay: -0.072s
+
+ div:nth-child(2):after
+ top: 54px
+ left: 45px
+
+ div:nth-child(3)
+ animation-delay: -0.108s
+
+ div:nth-child(3):after
+ top: 57px
+ left: 39px
+
+ div:nth-child(4)
+ animation-delay: -0.144s
+
+ div:nth-child(4):after
+ top: 58px
+ left: 32px
+
+ div:nth-child(5)
+ animation-delay: -0.18s
+
+ div:nth-child(5):after
+ top: 57px
+ left: 25px
+
+ div:nth-child(6)
+ animation-delay: -0.216s
+
+ div:nth-child(6):after
+ top: 54px
+ left: 19px
+
+ div:nth-child(7)
+ animation-delay: -0.252s
+
+ div:nth-child(7):after
+ top: 50px
+ left: 14px
+
+ div:nth-child(8)
+ animation-delay: -0.288s
+
+ div:nth-child(8):after
+ top: 45px
+ left: 10px
+
+@keyframes lds-roller
+ 0%
+ transform: rotate(0deg)
+
+ 100%
+ transform: rotate(360deg)
diff --git a/client/components/main/popup.styl b/client/components/main/popup.styl
index b7c9e264..ff00eef3 100644
--- a/client/components/main/popup.styl
+++ b/client/components/main/popup.styl
@@ -33,6 +33,9 @@ $popupWidth = 300px
textarea
height: 72px
+ form a span
+ padding: 0 0.5rem
+
.header
height: 36px
position: relative