Implement Creative guidelines
119
app.css
|
@ -1,9 +1,46 @@
|
|||
.current-timer {
|
||||
font-weight: bold;
|
||||
&.box.apps_ticket_sidebar.app_view {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
section[data-main] {
|
||||
font-family: Lucida Grande;
|
||||
}
|
||||
|
||||
.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 {
|
||||
|
@ -19,13 +56,79 @@ input {
|
|||
|
||||
.timelogs-container {
|
||||
display: none;
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
table {
|
||||
margin-bottom: none;
|
||||
.timelogs-container .heading {
|
||||
border-top: 1px solid #ddd;
|
||||
border-bottom: 1px solid #ddd;
|
||||
padding: 10px 0px 10px 0px;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
display: inline-block;
|
||||
padding-top: 7px;
|
||||
.csv-export {
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.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',
|
||||
'fetchAudits.done' : 'onFetchAuditsDone',
|
||||
'click .pause' : 'onPauseClicked',
|
||||
'click .resume' : 'onResumeClicked',
|
||||
'click .play' : 'onPlayClicked',
|
||||
'click .reset' : 'onResetClicked',
|
||||
'click .modal-save' : 'onModalSaveClicked',
|
||||
'click a.timelogs-opener:not([disabled])' : 'onTimeLogsContainerClicked',
|
||||
'shown .modal' : 'onModalShown',
|
||||
'hidden .modal' : 'onModalHidden'
|
||||
'hidden .modal' : 'onModalHidden',
|
||||
'click .expand-bar' : 'onTimelogsClicked'
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -84,35 +85,33 @@
|
|||
},
|
||||
|
||||
onFetchAuditsDone: function(data) {
|
||||
var timelogs = _.reduce(data.audits, function(memo, audit) {
|
||||
var newStatus = _.find(audit.events, function(event) {
|
||||
return event.field_name == 'status';
|
||||
}, this),
|
||||
event = _.find(audit.events, function(event) {
|
||||
return event.field_name == this.setting('time_field_id');
|
||||
}, this),
|
||||
status;
|
||||
var status = "",
|
||||
timelogs = _.reduce(data.audits, function(memo, audit) {
|
||||
var newStatus = _.find(audit.events, function(event) {
|
||||
return event.field_name == 'status';
|
||||
}, this),
|
||||
event = _.find(audit.events, function(event) {
|
||||
return event.field_name == this.setting('time_field_id');
|
||||
}, this);
|
||||
|
||||
if (event) {
|
||||
if (newStatus){
|
||||
status = newStatus.value;
|
||||
} else {
|
||||
status = _.last(memo).status;
|
||||
}
|
||||
if (newStatus){
|
||||
status = newStatus.value;
|
||||
}
|
||||
|
||||
memo.push({
|
||||
time: this.TimeHelper.secondsToTimeString(parseInt(event.value, 0)),
|
||||
date: new Date(audit.created_at).toLocaleString(),
|
||||
status: status,
|
||||
localized_status: this.I18n.t(helpers.fmt('statuses.%@', status)),
|
||||
user: _.find(data.users, function(user) {
|
||||
return user.id === audit.author_id;
|
||||
})
|
||||
});
|
||||
}
|
||||
if (event) {
|
||||
memo.push({
|
||||
time: this.TimeHelper.secondsToTimeString(parseInt(event.value, 0)),
|
||||
date: new Date(audit.created_at).toLocaleString(),
|
||||
status: status,
|
||||
localized_status: this.I18n.t(helpers.fmt('statuses.%@', status)),
|
||||
user: _.find(data.users, function(user) {
|
||||
return user.id === audit.author_id;
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
return memo;
|
||||
}, [], this);
|
||||
return memo;
|
||||
}, [], this);
|
||||
|
||||
this.renderTimelogs(timelogs.reverse());
|
||||
},
|
||||
|
@ -120,17 +119,17 @@
|
|||
onPauseClicked: function(e) {
|
||||
var $el = this.$(e.currentTarget);
|
||||
|
||||
$el.removeClass('pause').addClass('resume');
|
||||
$el.find('i').prop('class', 'icon-play');
|
||||
$el.find('i').addClass('active');
|
||||
this.$('.play i').removeClass('active');
|
||||
|
||||
this.manuallyPaused = this.paused = true;
|
||||
},
|
||||
|
||||
onResumeClicked: function(e) {
|
||||
onPlayClicked: function(e) {
|
||||
var $el = this.$(e.currentTarget);
|
||||
|
||||
$el.removeClass('resume').addClass('pause');
|
||||
$el.find('i').prop('class', 'icon-pause');
|
||||
$el.find('i').addClass('active');
|
||||
this.$('.pause i').removeClass('active');
|
||||
|
||||
this.manuallyPaused = this.paused = false;
|
||||
},
|
||||
|
@ -139,16 +138,8 @@
|
|||
this.elapsedTime = 0;
|
||||
},
|
||||
|
||||
onTimeLogsContainerClicked: function(e) {
|
||||
var $el = this.$(e.currentTarget);
|
||||
|
||||
if (!this.$('.timelogs-container').is(':visible')) {
|
||||
$el.addClass('active');
|
||||
this.$('.timelogs-container').show();
|
||||
} else {
|
||||
$el.removeClass('active');
|
||||
this.$('.timelogs-container').hide();
|
||||
}
|
||||
onTimelogsClicked: function() {
|
||||
this.$('.timelogs-container').slideToggle();
|
||||
},
|
||||
|
||||
onModalSaveClicked: function() {
|
||||
|
|
После Ширина: | Высота: | Размер: 17 KiB |
После Ширина: | Высота: | Размер: 17 KiB |
После Ширина: | Высота: | Размер: 17 KiB |
После Ширина: | Высота: | Размер: 17 KiB |
После Ширина: | Высота: | Размер: 18 KiB |
После Ширина: | Высота: | Размер: 1.5 KiB |
После Ширина: | Высота: | Размер: 1.1 KiB |
|
@ -1,5 +1,8 @@
|
|||
<header>
|
||||
<span class="logo"/>
|
||||
<h3>{{setting "name"}}</h3>
|
||||
</header>
|
||||
<section data-main/>
|
||||
<div class="app-container">
|
||||
<header>
|
||||
<span class="logo"/>
|
||||
<h3>{{setting "name"}}</h3>
|
||||
</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="row-fluid current-timer">
|
||||
<div class="span8">
|
||||
{{t "views.main.current_time_spent"}}:
|
||||
<div class="span6">
|
||||
<div class="live-timer ">00:00:00</div>
|
||||
</div>
|
||||
<div class="span4">
|
||||
<div class="live-timer pull-right">00:00:00</div>
|
||||
<div class="span6">
|
||||
<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 class="row-fluid">
|
||||
<div class="span8">
|
||||
{{t "views.main.total_time_spent"}}:
|
||||
<div class="row-fluid total-time">
|
||||
<div class="span12">
|
||||
<strong>{{t "views.main.total_time_spent"}}</strong>: <span class="live-totaltimer">00:00:00</span>
|
||||
</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>
|
||||
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
{{#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>
|
||||
<th>{{t "views.main.timelogs_table.status"}}</th>
|
||||
<th>{{t "views.main.timelogs_table.agent"}}</th>
|
||||
|
@ -19,7 +23,4 @@
|
|||
{{/each}}
|
||||
</tbody>
|
||||
</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}}
|
||||
|
|
|
@ -47,9 +47,9 @@
|
|||
"views": {
|
||||
"main": {
|
||||
"pause": "Pause",
|
||||
"current_time_spent": "Current Time Spent",
|
||||
"total_time_spent": "Total Time Spent",
|
||||
"pause_resume": "Pause/Resume",
|
||||
"total_time_spent": "Total time",
|
||||
"play": "Play",
|
||||
"pause": "Pause",
|
||||
"reset": "Reset",
|
||||
"timelogs": "Timelogs",
|
||||
"timelogs_table": {
|
||||
|
@ -58,6 +58,10 @@
|
|||
"status": "Status"
|
||||
}
|
||||
},
|
||||
"timelogs": {
|
||||
"title": "Timelogs",
|
||||
"csv_export": "Export CSV"
|
||||
},
|
||||
"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\".",
|
||||
"close": "Close",
|
||||
|
|