Bugfix, started working on mobile UI.

* Strted making the page responsive (size-based media queries, mobile meta
  tags, and reworked the UI for small sizes).
* Fixed bugs in the periodicRefresh function.
* Changed the yaw.prod.conf file to match the actual PROD coniguration.
This commit is contained in:
Jonathan Bernard 2014-03-30 03:37:59 +00:00
parent 54eb4fdafa
commit dc70b00403
6 changed files with 271 additions and 377 deletions

View File

@ -5,7 +5,7 @@ start() ->
ok = application:load(mnesia),
ok = application:set_env(mnesia, dir, "/home/jdbernard/projects/jdb-labs/timestamper/web-app/db/test"),
ok = mnesia:start(),
error_logger:info_report("TimeStampter app started."),
error_logger:info_report("TimeStamper app started."),
ok.
create_tables(Nodes) ->

28
www/css/forSize.scss Normal file
View File

@ -0,0 +1,28 @@
@import url(//fonts.googleapis.com/css?family=Maven+Pro:400,700|Exo:400,600|PT+Mono);
/** ### forSize
* This mixin allows us to apply some rules selectively based on the screen
* size. There are three primary sizes: `small`, `medium`, and `large`, which
* are mutually exclusive. Additionally there are two additional sizes:
* `notSmall` and `ultraLarge`. `notSmall`, as the name implies matches any
* value which is not the small screen size, so it overlaps with medium,
* large, and ultraLarge. `ultraLarge` defines a wider minimum screen size
* than large, but neither large nor ultraLarge specify maximum widths,
* so ultraLarge is a strict subset of large. A screen large enough to match
* ultraLarge will also match large (compare with medium and large: matching
* medium means it will not match large, and vice versa). */
@mixin forSize($size) {
@if $size == small {
@media screen and (max-width: $smallScreen) { @content; } }
@else if $size == notSmall {
@media screen and (min-width: $smallScreen + 1) { @content; } }
@else if $size == medium {
@media screen and (min-width: $smallScreen + 1) and (max-width: $wideScreen - 1) { @content; } }
@else if $size == large {
@media screen and (min-width: $wideScreen) { @content; } }
@else if $size == ultraLarge {
@media screen and (min-width: $ultraWideScreen) { @content; } }
}

View File

@ -3,7 +3,12 @@
* TimeStamper main CSS for screen media types
*/
$smallScreen: 640px;
$wideScreen: 1000px;
$ultraWideScreen: 1400px;
@import "rounded";
@import "forSize";
$darkTxt: #222;
$lightTxt: #eee;
@ -13,122 +18,134 @@ $medBg: #CCC;
* {
color: inherit;
}
margin: 0;
padding: 0;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box; }
/* HTML5 elements */
article,aside,details,figcaption,figure,
footer,header,hgroup,menu,nav,section {
display:block; }
body {
color: $darkTxt;
width: 75%;
margin: auto;
padding: 0;
}
line-height: 1.4; }
.hidden { display: none; }
input {
border: solid thin lighten($darkTxt, 20%);
-webkit-box-shadow: inset 0px 2px 4px #CCC;
box-shadow: inset 0px 2px 4px #CCC;
margin: 0;
margin-bottom: 0.5em; // IE fix
padding: 0;
font-family: Cantarell;
}
font-family: Cantarell; }
#top {
background: $darkBg;
color: $lightTxt;
margin: 0;
opacity: 1;
padding: 0.5em 0; // IE Fix
padding: 0.5rem 0;
position: fixed;
top: 0px;
width: 75%;
z-index: 1;
* {
margin: 0;
padding: 0;
}
#fade-bar {
background: url('img/fade.png') repeat-x;
height: 32px;
width: 100%;
}
}
padding-top: 0.5rem; }
#timeline {
border-bottom: thin solid $lightBg;
font-family: Arvo;
font-size: 1.5em;
padding: 0 2em;
padding: 0 2rem;
.timeline-desc {
display: inline-block;
width: 70%;
}
.timeline-desc-input { width: 70% }
.timeline-id { display: inline-block; }
.timeline-desc-input, .timeline-id-input {
font-family: inherit;
font-size: inherit;
color: $darkBg;
display: none;
}
display: none; }
&.edit-id {
.timeline-id-input { display: inline-block; }
.timeline-id { display: none; }
}
.timeline-id { display: none; } }
&.edit-desc {
.timeline-desc-input { display: inline-block; }
.timeline-desc { display: none; }
}
.timeline-desc { display: none; } }
.drop-menu {
text-align: right;
display: inline-block;
width: 29%;
.drop-menu-items {
text-align: right;
right: 0;
width: 172.41%;
.new-timeline-link {
padding-right: 0.5em;
font-size: medium;
a { text-decoration: underline; }
img {
position: relative;
top: 4px;
left: -4px;
}
}
.timeline-link {
padding: 0 0.5em;
font-size: medium;
border-left: thin solid white
}
}
}
}
#entry-list {
padding-bottom: 1rem;
.day-seperator {
background: $medBg;
color: $darkBg;
font-family: Cantarell;
font-weight: bold;
margin: 1rem 0 0 0;
padding: 0 2rem;
h5 { color: #667; } }
#new-entry {
margin: 0.5rem 0 0 0;
padding: 0 2rem; }
.timestamp, .timestamp-input, .duration { text-align: right; }
.entry {
font-family: Cantarell;
padding: 0 2rem;
.mark {
position: relative;
img.expand-entry, img.collapse-entry {
display: none;
left: -20px;
position: absolute;
top: 6px; } }
&:hover .mark img.expand-entry, &.show-notes img.collapse-entry { display: inline; }
.mark-input, .timestamp-input,
&.show-notes:hover img.expand-entry { display: none; }
.notes {
display: none;
font-family: Cantarell;
font-size: small;
padding: 0 0 0 1em;
:first-child { margin-top: 0; }
.notes-input, pre, code { font-family: 'Anonymous Pro'; } }
.notes * { width: 100%; }
&.edit-mark {
.mark-input { display: inline-block; }
.mark { display: none; } }
&.edit-timestamp {
.timestamp-input { display: inline-block; }
.timestamp { display: none; } }
.notes-input { display: none; }
&.edit-notes .notes-input { display: block; }
&.edit-notes .notes-text { display: none; }
&.current .duration {
-webkit-animation: pulse 1s infinite alternate;
-moz-animation: pulse 1s infinite alternate;
-o-animation: pulse 1s infinite alternate;
animation: pulse 1s infinite alternate; } } }
.dialog {
background: white;
background: rgba(255, 255, 255, 0.5);
color: $lightTxt;
margin: 0;
padding: 0;
position: fixed;
top: 0px;
@ -139,11 +156,6 @@ input {
z-index: 10;
* {
margin: 0;
padding: 0;
}
div.container {
background: $darkBg;
@ -159,17 +171,13 @@ input {
border-bottom: thin solid $lightBg;
font-family: Arvo;
padding-bottom: 0.5em;
margin-bottom: 0.5em;
}
margin-bottom: 0.5em; }
label {
display: inline-block;
width: 6em;
}
width: 6em; }
input {
color: $darkTxt;
}
input { color: $darkTxt; }
.button-panel {
margin-top: 0.5em;
@ -185,254 +193,15 @@ input {
font-family: Arvo;
font-size: 1.2em;
a { color: $lightBg; }
}
}
}
}
a { color: $lightBg; } } } } }
#login.dialog {
background: white;
opacity: 1;
}
/*#login {
background: white;
color: $lightTxt;
margin: 0;
padding: 0;
opacity: 1;
position: fixed;
top: 0px;
left: 0px;
width: 100%;
height: 100em;
z-index: 10;
* {
margin: 0;
padding: 0;
}
div.container {
background: $darkBg;
border-radius: 10px;
font-family: Cantarell;
margin-left: auto;
margin-right: auto;
margin-top: 4em;
padding: 1em;
width: 20em;
h2 {
border-bottom: thin solid $lightBg;
font-family: Arvo;
padding-bottom: 0.5em;
margin-bottom: 0.5em;
}
label {
display: inline-block;
width: 6em;
}
input {
color: $darkTxt;
}
#login-button {
text-align: right;
margin-top: 0.5em;
font-family: Arvo;
font-size: 1.2em;
.validate-tips { font-size: 1em; }
a { color: $lightBg; }
}
}
}*/
#user {
font-family: "Josefin Sans";
margin-top: -0.3em; // IE fix
padding: 0 2em;
margin-top: -0.3rem;
padding: 0 2rem;
width: 100%;
.fullname, .username {
display: inline-block;
font-size: larger;
}
.fullname-input {
font-family: inherit;
font-size: inherit;
color: $darkBg;
display: none;
}
&.edit-fullname{
.fullname-input { display: inline-block; }
.fullname { display: none; }
}
.user-menu { display: inline-block; }
.user-menu .user-menu-items {
list-style: none;
display: none;
li {
display: inline-block;
padding-left: 0.5em;
}
a { text-decoration: none; }
a:hover { text-decoration: underline; }
}
.user-menu:hover .user-menu-items, .user-menu-items:hover { display: inline-block; }
}
#entry-list {
margin: 6em 0 0 0;
margin: 6rem 0 0 0;
padding-bottom: 1em 0 0 0;
padding-bottom: 1rem 0 0 0;
.day-seperator {
background: $medBg;
color: $darkBg;
font-family: Cantarell;
font-weight: bold;
margin: 1em 0 0 0;
margin: 1rem 0 0 0;
padding: 0 2em;
padding: 0 2rem;
* {
margin: 0;
padding: 0;
}
h4, h5 { display: inline-block; }
h5 { color: #667; }
}
#new-entry {
margin: 0.5em 0 0 0;
padding: 0 2em;
margin: 0.5rem 0 0 0;
padding: 0 2rem;
* {
margin: 0;
padding: 0;
}
}
.timestamp, .timestamp-input, .duration {
text-align: right;
width: 14%;
}
.mark, .mark-input { width: 70%; }
.entry {
font-family: Cantarell;
padding: 0 2em;
padding: 0 2rem;
div { display: inline-block; }
.mark {
margin: 0;
padding: 0;
position: relative;
* {
margin: 0;
padding: 0;
}
img.expand-entry, img.collapse-entry {
display: none;
left: -20px;
position: absolute;
top: 6px;
}
}
&:hover .mark img.expand-entry, &.show-notes img.collapse-entry { display: inline; }
.mark-input, .timestamp-input,
&.show-notes:hover img.expand-entry { display: none; }
.notes {
display: none;
font-family: Cantarell;
font-size: small;
margin: 0;
padding: 0 0 0 1em;
width: 70%;
:first-child { margin-top: 0; }
.notes-input, pre, code { font-family: 'Anonymous Pro'; }
}
.notes * { width: 100%; }
&.edit-mark {
.mark-input { display: inline-block; }
.mark { display: none; }
}
&.edit-timestamp {
.timestamp-input { display: inline-block; }
.timestamp { display: none; }
}
.notes-input { display: none; }
&.edit-notes .notes-input { display: block; }
&.edit-notes .notes-text { display: none; }
&.current .duration {
-webkit-animation: pulse 1s infinite alternate;
-moz-animation: pulse 1s infinite alternate;
-o-animation: pulse 1s infinite alternate;
animation: pulse 1s infinite alternate; }
}
}
opacity: 1; }
.drop-menu {
margin: 0;
padding: 0;
position: relative;
* {
margin: 0;
padding: 0;
}
.drop-menu-items {
display: none;
list-style: none;
@ -440,9 +209,7 @@ input {
li {
display: inline-block;
padding-left: 0.5em;
}
}
padding-left: 0.5em; } }
&:hover .drop-menu-items, .drop-menu-items:hover { display: block; }
@ -450,44 +217,150 @@ input {
display: inline-block;
text-decoration: none;
&:hover {
text-decoration: underline;
}
}
}
&:hover { text-decoration: underline; } } }
.footer {
background: $darkBg;
color: $lightTxt;
font-family: Bentham;
margin: 0;
padding: 1em 0;
padding: 1rem 0;
text-align: center;
width: 100%;
* {
margin: 0;
padding: 0;
}
a {
color: lighten($lightTxt, 20%);
text-decoration: none;
&:hover { text-decoration: underline; }
}
}
&:hover { text-decoration: underline; } } }
.logo {
font-family: Bentham;
text-decoration: overline underline;
color: inherit;
text-decoration: overline underline; }
@include forSize(notSmall) {
body { width: 75%; }
#top {
position: fixed;
top: 0px;
width: 75%;
z-index: 1; }
#timeline {
font-size: 1.5em;
padding: 0 2rem;
.timeline-desc {
display: inline-block;
width: 70%; }
.timeline-desc-input { width: 70% }
.timeline-id { display: inline-block; }
.drop-menu {
text-align: right;
display: inline-block;
width: 29%;
.drop-menu-items {
text-align: right;
right: 0;
width: 172.41%;
.new-timeline-link {
padding-right: 0.5em;
font-size: medium;
a { text-decoration: underline; }
img {
position: relative;
top: 4px;
left: -4px; } }
.timeline-link {
padding: 0 0.5em;
font-size: medium;
border-left: thin solid white } } } }
#user {
font-family: "Josefin Sans";
margin-top: 0.3rem;
padding: 0 0 0.3rem 2rem;
width: 100%;
.fullname, .username {
display: inline-block;
font-size: larger; }
.fullname-input {
font-family: inherit;
font-size: inherit;
color: $darkBg;
display: none; }
&.edit-fullname{
.fullname-input { display: inline-block; }
.fullname { display: none; } }
.user-menu { display: inline-block; }
.user-menu .user-menu-items {
list-style: none;
display: none;
li {
display: inline-block;
padding-left: 0.5em; }
a { text-decoration: none; }
a:hover { text-decoration: underline; }
}
.user-menu:hover .user-menu-items, .user-menu-items:hover { display: inline-block; } }
#entry-list {
margin: 6rem 0 0 0;
.timestamp, .timestamp-input, .duration { width: 14%; }
.mark, .mark-input, .notes { width: 70%; }
h4, h5, .entry div { display: inline-block; }
}
}
.hidden { display: none; }
@include forSize(small) {
body { width: 100%; }
#timeline {
font-size: 1.3em;
padding-bottom: 0.5rem;
.timeline-desc { display: block; }
.timeline-desc, .timeline-desc-input {
text-align: center;
width: 100%; }
.timeline-id, .timeline-id-input { display: none; } }
#user { display: none; }
#entry-list {
.timestamp, .timestamp-input { width: 18%; }
.mark, .notes { width: 80%; }
.mark-input { width: 98% }
.duration { display: none; }
h4.mark, h5.mark, h4.timestamp, h5.timestamp,
div.mark, div.timestamp{ display: inline-block; }
}
}
@-webkit-keyframes pulse {
from { opacity: 1; }

View File

@ -1,6 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8>
<meta name="viewport" content="width=device-width, user-scalable=no">
<title>TimeStamper - Simple Time Tracking</title>
<link href='//fonts.googleapis.com/css?family=Anonymous+Pro|Arvo|Bentham|Cantarell|Josefin+Sans' rel='stylesheet' type='text/css'>
<link rel="stylesheet" media="screen" href="css/ts-screen.css" type="text/css"/>

View File

@ -608,25 +608,29 @@ $(document).ready(function(){
var now = new Date();
var models = this.entries.collection.models;
// First we check if it is a new day. If it is, we need to
// re-render the chole list.
if (this.currentDay.getDate() != now.getDate()) {
// If the user is editing any one of the models, don't rerender
if (_.any(models, function(model) {
return ($(model.view.el).hasClass('edit-mark'); ||
$(model.view.el).hasClass('edit-timestamp'); ||
$(model.view.el).hasClass('edit-notes');) })) {
return ($(model.view.el).hasClass('edit-mark') ||
$(model.view.el).hasClass('edit-timestamp') ||
$(model.view.el).hasClass('edit-notes')) })) {
return }
// It's a new day! Rerender our whole list.
else { this.entries.render(); } }
// Otherwise we only need to re-render the most recent item.
else {
var currentModel = models[models.length - 1]
if ($(model.view.el).hasClass('edit-mark'); ||
$(model.view.el).hasClass('edit-timestamp'); ||
$(model.view.el).hasClass('edit-notes');) { return }
if ($(currentModel.view.el).hasClass('edit-mark') ||
$(currentModel.view.el).hasClass('edit-timestamp') ||
$(currentModel.view.el).hasClass('edit-notes')) { return }
// Refresh our latest entry view so the duration is up to date.
else { currentModelview.render(); } } },
else { currentModel.view.render(); } } },
selectTimeline: function(e) {
if (e) {

View File

@ -1,25 +1,12 @@
ebin_dir = /usr/local/var/yaws/jdb-labs.com/timestamper/ebin
include_dir = /usr/local/var/yaws/jdb-labs.com/timestamper/include
ebin_dir = /usr/local/var/yaws/timestamper.jdb-labs.com/ebin
include_dir = /usr/local/var/yaws/timestamper.jdb-labs.com/include
#runmod = timestamper
<server timestamper.jdb-labs.com>
port = 80
listen = 0.0.0.0
docroot = /usr/local/var/yaws/jdb-labs.com/timestamper/www
docroot = /usr/local/var/yaws/timestamper.jdb-labs.com/www
appmods = ts_api
</server>
<server timestamper.jdb-labs.com>
port = 443
listen = 0.0.0.0
docroot = /usr/local/var/yaws/jdb-labs.com/timestamper/www
appmods = ts_api
dir_listings = false
<ssl>
keyfile = /usr/local/var/yaws/keys/jdb-labs.com.key.pem
certfile = /usr/local/var/yaws/keys/jdb-labs.com.cert.pem
depth = 0
</ssl>
</server>