Implement Creative guidelines
119
app.css
|
@ -1,9 +1,46 @@
|
||||||
.current-timer {
|
&.box.apps_ticket_sidebar.app_view {
|
||||||
font-weight: bold;
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section[data-main] {
|
||||||
|
font-family: Lucida Grande;
|
||||||
}
|
}
|
||||||
|
|
||||||
.live-timer {
|
.live-timer {
|
||||||
font-size: 15px;
|
font-size: 26px;
|
||||||
|
font-weight: regular;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.total-time {
|
||||||
|
padding-top: 15px;
|
||||||
|
paddint-bottom: 0px;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
[class^="icon-time-"] {
|
||||||
|
background-position: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-time-play {
|
||||||
|
background-image: app-asset-url("_play_inactive@1x.png");
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-image: app-asset-url("_play_active@1x.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-time-pause {
|
||||||
|
background-image: app-asset-url("_pause_inactive@1x.png");
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background-image: app-asset-url("_pause_active@1x.png");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-time-reset {
|
||||||
|
background-image: app-asset-url("_refresh_inactive@1x.png");
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-center {
|
.text-center {
|
||||||
|
@ -19,13 +56,79 @@ input {
|
||||||
|
|
||||||
.timelogs-container {
|
.timelogs-container {
|
||||||
display: none;
|
display: none;
|
||||||
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
table {
|
.timelogs-container .heading {
|
||||||
margin-bottom: none;
|
border-top: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
padding: 10px 0px 10px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-group {
|
.csv-export {
|
||||||
display: inline-block;
|
font-size: 11px;
|
||||||
padding-top: 7px;
|
}
|
||||||
|
|
||||||
|
.table {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
|
||||||
|
tr:hover td {
|
||||||
|
background-color:white;
|
||||||
|
}
|
||||||
|
|
||||||
|
th {
|
||||||
|
font-size: 11px;
|
||||||
|
font-weight: normal;
|
||||||
|
color: #333;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
border-top: 0px;
|
||||||
|
padding-top: 10px;
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 11px;
|
||||||
|
color: #8c8c8c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.expand-bar {
|
||||||
|
background-color: #F8F8F8;
|
||||||
|
border-top: 1px solid #f0f0f0;
|
||||||
|
padding-top: 0px;
|
||||||
|
padding-bottom: 15px;
|
||||||
|
display: block;
|
||||||
|
margin-left: -15px;
|
||||||
|
margin-right: -15px;
|
||||||
|
-webkit-border-bottom-right-radius: 5px;
|
||||||
|
-webkit-border-bottom-left-radius: 5px;
|
||||||
|
-moz-border-radius-bottomright: 5px;
|
||||||
|
-moz-border-radius-bottomleft: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
|
||||||
|
.arrow {
|
||||||
|
margin-top: 12px;
|
||||||
|
height: 6px;
|
||||||
|
min-width: 11px;
|
||||||
|
display: block;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center;
|
||||||
|
background-image: app-asset-url("ico-arrow-up-normal.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-image: app-asset-url("hover-bg.png");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: center top;
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
display: block;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
opacity: 0.4;
|
||||||
|
}
|
||||||
}
|
}
|
77
app.js
|
@ -22,12 +22,13 @@
|
||||||
'ticket.form.id.changed' : 'onTicketFormChanged',
|
'ticket.form.id.changed' : 'onTicketFormChanged',
|
||||||
'fetchAudits.done' : 'onFetchAuditsDone',
|
'fetchAudits.done' : 'onFetchAuditsDone',
|
||||||
'click .pause' : 'onPauseClicked',
|
'click .pause' : 'onPauseClicked',
|
||||||
'click .resume' : 'onResumeClicked',
|
'click .play' : 'onPlayClicked',
|
||||||
'click .reset' : 'onResetClicked',
|
'click .reset' : 'onResetClicked',
|
||||||
'click .modal-save' : 'onModalSaveClicked',
|
'click .modal-save' : 'onModalSaveClicked',
|
||||||
'click a.timelogs-opener:not([disabled])' : 'onTimeLogsContainerClicked',
|
'click a.timelogs-opener:not([disabled])' : 'onTimeLogsContainerClicked',
|
||||||
'shown .modal' : 'onModalShown',
|
'shown .modal' : 'onModalShown',
|
||||||
'hidden .modal' : 'onModalHidden'
|
'hidden .modal' : 'onModalHidden',
|
||||||
|
'click .expand-bar' : 'onTimelogsClicked'
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -84,35 +85,33 @@
|
||||||
},
|
},
|
||||||
|
|
||||||
onFetchAuditsDone: function(data) {
|
onFetchAuditsDone: function(data) {
|
||||||
var timelogs = _.reduce(data.audits, function(memo, audit) {
|
var status = "",
|
||||||
var newStatus = _.find(audit.events, function(event) {
|
timelogs = _.reduce(data.audits, function(memo, audit) {
|
||||||
return event.field_name == 'status';
|
var newStatus = _.find(audit.events, function(event) {
|
||||||
}, this),
|
return event.field_name == 'status';
|
||||||
event = _.find(audit.events, function(event) {
|
}, this),
|
||||||
return event.field_name == this.setting('time_field_id');
|
event = _.find(audit.events, function(event) {
|
||||||
}, this),
|
return event.field_name == this.setting('time_field_id');
|
||||||
status;
|
}, this);
|
||||||
|
|
||||||
if (event) {
|
if (newStatus){
|
||||||
if (newStatus){
|
status = newStatus.value;
|
||||||
status = newStatus.value;
|
}
|
||||||
} else {
|
|
||||||
status = _.last(memo).status;
|
|
||||||
}
|
|
||||||
|
|
||||||
memo.push({
|
if (event) {
|
||||||
time: this.TimeHelper.secondsToTimeString(parseInt(event.value, 0)),
|
memo.push({
|
||||||
date: new Date(audit.created_at).toLocaleString(),
|
time: this.TimeHelper.secondsToTimeString(parseInt(event.value, 0)),
|
||||||
status: status,
|
date: new Date(audit.created_at).toLocaleString(),
|
||||||
localized_status: this.I18n.t(helpers.fmt('statuses.%@', status)),
|
status: status,
|
||||||
user: _.find(data.users, function(user) {
|
localized_status: this.I18n.t(helpers.fmt('statuses.%@', status)),
|
||||||
return user.id === audit.author_id;
|
user: _.find(data.users, function(user) {
|
||||||
})
|
return user.id === audit.author_id;
|
||||||
});
|
})
|
||||||
}
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return memo;
|
return memo;
|
||||||
}, [], this);
|
}, [], this);
|
||||||
|
|
||||||
this.renderTimelogs(timelogs.reverse());
|
this.renderTimelogs(timelogs.reverse());
|
||||||
},
|
},
|
||||||
|
@ -120,17 +119,17 @@
|
||||||
onPauseClicked: function(e) {
|
onPauseClicked: function(e) {
|
||||||
var $el = this.$(e.currentTarget);
|
var $el = this.$(e.currentTarget);
|
||||||
|
|
||||||
$el.removeClass('pause').addClass('resume');
|
$el.find('i').addClass('active');
|
||||||
$el.find('i').prop('class', 'icon-play');
|
this.$('.play i').removeClass('active');
|
||||||
|
|
||||||
this.manuallyPaused = this.paused = true;
|
this.manuallyPaused = this.paused = true;
|
||||||
},
|
},
|
||||||
|
|
||||||
onResumeClicked: function(e) {
|
onPlayClicked: function(e) {
|
||||||
var $el = this.$(e.currentTarget);
|
var $el = this.$(e.currentTarget);
|
||||||
|
|
||||||
$el.removeClass('resume').addClass('pause');
|
$el.find('i').addClass('active');
|
||||||
$el.find('i').prop('class', 'icon-pause');
|
this.$('.pause i').removeClass('active');
|
||||||
|
|
||||||
this.manuallyPaused = this.paused = false;
|
this.manuallyPaused = this.paused = false;
|
||||||
},
|
},
|
||||||
|
@ -139,16 +138,8 @@
|
||||||
this.elapsedTime = 0;
|
this.elapsedTime = 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
onTimeLogsContainerClicked: function(e) {
|
onTimelogsClicked: function() {
|
||||||
var $el = this.$(e.currentTarget);
|
this.$('.timelogs-container').slideToggle();
|
||||||
|
|
||||||
if (!this.$('.timelogs-container').is(':visible')) {
|
|
||||||
$el.addClass('active');
|
|
||||||
this.$('.timelogs-container').show();
|
|
||||||
} else {
|
|
||||||
$el.removeClass('active');
|
|
||||||
this.$('.timelogs-container').hide();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onModalSaveClicked: function() {
|
onModalSaveClicked: function() {
|
||||||
|
|
После Ширина: | Высота: | Размер: 17 KiB |
После Ширина: | Высота: | Размер: 17 KiB |
После Ширина: | Высота: | Размер: 17 KiB |
После Ширина: | Высота: | Размер: 17 KiB |
После Ширина: | Высота: | Размер: 18 KiB |
После Ширина: | Высота: | Размер: 1.5 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -1,5 +1,8 @@
|
||||||
<header>
|
<div class="app-container">
|
||||||
<span class="logo"/>
|
<header>
|
||||||
<h3>{{setting "name"}}</h3>
|
<span class="logo"/>
|
||||||
</header>
|
<h3>{{setting "name"}}</h3>
|
||||||
<section data-main/>
|
</header>
|
||||||
|
<section data-main/>
|
||||||
|
</div>
|
||||||
|
<a class="expand-bar"><i class="arrow"/></a>
|
||||||
|
|
|
@ -1,32 +1,21 @@
|
||||||
<div class="timers {{#unless display_timer }}hidden{{/unless}}">
|
<div class="timers {{#unless display_timer }}hidden{{/unless}}">
|
||||||
<div class="row-fluid current-timer">
|
<div class="row-fluid current-timer">
|
||||||
<div class="span8">
|
<div class="span6">
|
||||||
{{t "views.main.current_time_spent"}}:
|
<div class="live-timer ">00:00:00</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="span4">
|
<div class="span6">
|
||||||
<div class="live-timer pull-right">00:00:00</div>
|
<div class="text-center pull-right">
|
||||||
|
<button class="btn play" title="{{t "views.main.play"}}" {{#unless manual_pause_resume}}disabled{{/unless}}><i class="icon-time-play active"></i></button>
|
||||||
|
<button class="btn pause" title="{{t "views.main.pause"}}" {{#unless manual_pause_resume}}disabled{{/unless}}><i class="icon-time-pause"></i></button>
|
||||||
|
<button class="btn reset" title="{{t "views.main.reset"}}" {{#unless display_reset}}disabled{{/unless}}><i class="icon-time-reset"></i></button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row-fluid">
|
<div class="row-fluid total-time">
|
||||||
<div class="span8">
|
<div class="span12">
|
||||||
{{t "views.main.total_time_spent"}}:
|
<strong>{{t "views.main.total_time_spent"}}</strong>: <span class="live-totaltimer">00:00:00</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="span4">
|
|
||||||
<div class="live-totaltimer pull-right">00:00:00</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="text-center">
|
|
||||||
<div class="btn-group">
|
|
||||||
{{#if manual_pause_resume}}
|
|
||||||
<a class="btn pause" title="{{t "views.main.pause_resume"}}"><i class="icon-pause"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
{{#if display_reset}}
|
|
||||||
<a class="btn reset" title="{{t "views.main.reset"}}"><i class="icon-repeat"></i></a>
|
|
||||||
{{/if}}
|
|
||||||
<a class="btn timelogs-opener disabled" disabled="disabled"><strong>{{t "views.main.timelogs"}}</strong></a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
{{#if timelogs}}
|
{{#if timelogs}}
|
||||||
<table class="table">
|
<div class="heading">
|
||||||
|
<strong>{{t "views.timelogs.title"}}</strong>
|
||||||
|
<a download="{{csv_filename}}" href="data:text/csv;charset=utf-8,{{csv_string}}" class="csv-export pull-right">{{t "views.timelogs.csv_export"}}</a>
|
||||||
|
</div>
|
||||||
|
<table class="table table-condensed">
|
||||||
<thead>
|
<thead>
|
||||||
<th>{{t "views.main.timelogs_table.status"}}</th>
|
<th>{{t "views.main.timelogs_table.status"}}</th>
|
||||||
<th>{{t "views.main.timelogs_table.agent"}}</th>
|
<th>{{t "views.main.timelogs_table.agent"}}</th>
|
||||||
|
@ -19,7 +23,4 @@
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div class="text-center">
|
|
||||||
<a download="{{csv_filename}}" href="data:text/csv;charset=utf-8,{{csv_string}}" class="btn"><i class="icon-file"></i> CSV Timelogs</a>
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
@ -47,9 +47,9 @@
|
||||||
"views": {
|
"views": {
|
||||||
"main": {
|
"main": {
|
||||||
"pause": "Pause",
|
"pause": "Pause",
|
||||||
"current_time_spent": "Current Time Spent",
|
"total_time_spent": "Total time",
|
||||||
"total_time_spent": "Total Time Spent",
|
"play": "Play",
|
||||||
"pause_resume": "Pause/Resume",
|
"pause": "Pause",
|
||||||
"reset": "Reset",
|
"reset": "Reset",
|
||||||
"timelogs": "Timelogs",
|
"timelogs": "Timelogs",
|
||||||
"timelogs_table": {
|
"timelogs_table": {
|
||||||
|
@ -58,6 +58,10 @@
|
||||||
"status": "Status"
|
"status": "Status"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"timelogs": {
|
||||||
|
"title": "Timelogs",
|
||||||
|
"csv_export": "Export CSV"
|
||||||
|
},
|
||||||
"modal": {
|
"modal": {
|
||||||
"body": "The system shows that you spent the following time on this ticket, you can either edit it or leave it as is and click \"Save Ticket\".",
|
"body": "The system shows that you spent the following time on this ticket, you can either edit it or leave it as is and click \"Save Ticket\".",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
|
|