UI Changes
diff --git a/erpnext/templates/includes/project_row.html b/erpnext/templates/includes/project_row.html
index 3c7331b..fc264c1 100644
--- a/erpnext/templates/includes/project_row.html
+++ b/erpnext/templates/includes/project_row.html
@@ -8,11 +8,10 @@
</div>
<div class="col-xs-4">
{% if doc.percent_complete %}
- <div class="progress" style="margin-bottom: 0!important;">
+ <div class="progress" style="margin-bottom: 0!important; margin-top: 10px!important; height:5px;">
<div class="progress-bar progress-bar-warning" role="progressbar"
aria-valuenow="{{ doc.percent_complete|round|int }}"
aria-valuemin="0" aria-valuemax="100" style="width:{{ doc.percent_complete|round|int }}%;">
- {{ doc.percent_complete|round|int }}% Complete
</div>
</div>
{% else %}
diff --git a/erpnext/templates/includes/projects.css b/erpnext/templates/includes/projects.css
index 99ec4c8..8c83e17 100644
--- a/erpnext/templates/includes/projects.css
+++ b/erpnext/templates/includes/projects.css
@@ -4,24 +4,46 @@
text-decoration: underline;
}
-.page-container .indicator {
+.page-container {
font-weight: normal;
+ margin: 50px auto;
+ max-width: 700px;
}
+.project-item:hover {
+ background-color: #f7f7f7;
+}
+
+.project-item {
+ color: #6c7680;
+ font-size: 14px;
+}
+
+.task-subject
+{
+ margin: 0px;
+}
+
+.item-timestamp
+{
+ font-size: 10px;
+}
.page-container .project-item {
padding-top: 5px;
padding-bottom: 5px;
}
#project-search {
- border: none;
+ position: relative;
+ outline:none;
+ border:none;
}
-.task-link {
+.task-link, .timelog-link {
font-weight: bold;
}
-.task-link.seen {
+.task-link.seen, .timelog-link.seen {
font-weight: normal;
}
@@ -62,116 +84,12 @@
padding: 8px;
}
-.timeline-centered {
- position: relative;
- margin-bottom: 10px;
+.gravatar-top{
+ margin-top:8px;
}
-.timeline-centered:before {
- content: '';
- position: absolute;
- display: block;
- width: 3px;
- background: #f5f5f6;
- /*left: 50%;*/
- top: 0px;
- bottom: 0px;
- margin-left: 10px;
-}
-
-.timeline-centered .timeline-entry {
- position: relative;
- /*width: 50%;
-float: right;*/
- margin-top: 5px;
- margin-left: 10px;
- margin-bottom: 5px;
- clear: both;
-}
-
-
-.timeline-centered .timeline-entry .timeline-entry-inner {
- position: relative;
- margin-left: -3px;
-}
-
-
-.timeline-centered .timeline-entry .timeline-entry-inner .timeline-icon {
- margin-top:14px;
- background: #fff;
- color: #737881;
- display: block;
- width: 10px;
- height: 10px;
- -webkit-background-clip: padding-box;
- -moz-background-clip: padding;
- background-clip: padding-box;
- -webkit-border-radius: 20px;
- -moz-border-radius: 20px;
- border-radius: 20px;
- text-align: center;
- -moz-box-shadow: 0 0 0 2px #f5f5f6;
- -webkit-box-shadow: 0 0 0 2px #f5f5f6;
- box-shadow: 0 0 0 2px #f5f5f6;
- line-height: 30px;
- float: left;
-}
-
-
-.timeline-centered .timeline-entry .timeline-entry-inner .timeline-icon.bg-primary {
- background-color: #303641;
- color: #fff;
-}
-
-.timeline-centered .timeline-entry .timeline-entry-inner .timeline-icon.bg-secondary {
- background-color: #ee4749;
- color: #fff;
-}
-
-.timeline-centered .timeline-entry .timeline-entry-inner .timeline-icon.bg-success {
- background-color: #98d85b;
- color: #fff;
-}
-
-.timeline-centered .timeline-entry .timeline-entry-inner .timeline-icon.bg-info {
- background-color: #21a9e1;
- color: #fff;
-}
-
-.timeline-centered .timeline-entry .timeline-entry-inner .timeline-icon.bg-warning {
- background-color: #ffa00a;
- color: #fff;
-}
-
-.timeline-centered .timeline-entry .timeline-entry-inner .timeline-icon.bg-danger {
- background-color: #ff5858;
- color: #fff;
-}
-
-
-.timeline-centered .timeline-entry .timeline-entry-inner .timeline-label {
- position: relative;
- background: #f5f5f6;
- padding: 1em;
- margin-left: 40px;
- -webkit-background-clip: padding-box;
- -moz-background-clip: padding;
- background-clip: padding-box;
- -webkit-border-radius: 3px;
- -moz-border-radius: 3px;
- border-radius: 3px;
-}
-
-.timeline-centered .timeline-entry .timeline-entry-inner .timeline-label:after {
- content: '';
- display: block;
- position: absolute;
- width: 0;
- height: 0;
- border-style: solid;
- border-width: 9px 9px 9px 0;
- border-color: transparent #f5f5f6 transparent transparent;
- left: 0;
- top: 10px;
- margin-left: -9px;
-}
+.progress-hg{
+ margin-bottom: 0!important;
+ margin-top: 30px!important;
+ height:5px;
+}
\ No newline at end of file
diff --git a/erpnext/templates/includes/projects/project_issues.html b/erpnext/templates/includes/projects/project_issues.html
deleted file mode 100644
index f8924f5..0000000
--- a/erpnext/templates/includes/projects/project_issues.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{%- from "templates/includes/projects/macros.html" import back_link -%}
-
-{% for issue in doc.issues %}
- <div class='issue'>
- <div class='row project-item'>
- <div class='col-xs-9'>
- <a class="no-decoration" href="/issues?name={{ issue.name}}{{ back_link(doc) }}">
- <span class="indicator {{ "red" if issue.status=="Open" else "green" }}">
- {% if issue.status == "Closed" %}
- {{ issue.subject }} resolved {{ frappe.utils.pretty_date(issue.resolution_date) }}
- {% else %}
- {{ issue.subject }} raised on {{ issue.opening_date }}
- {% endif %}
- </span>
- </a>
- </div>
- <div class='col-xs-3'>
- <div class='pull-right'>
- {% if issue.todo %}
- <span class="avatar avatar-small" title="{{ issue.todo.owner }}"> <img src="{{ issue.todo.user_image }}"></span>
- {% else %}
- <span class="avatar avatar-small avatar-empty"></span>
- {% endif %}
- </div>
- </div>
- </div>
- </div>
-{% endfor %}
\ No newline at end of file
diff --git a/erpnext/templates/includes/projects/project_search_box.html b/erpnext/templates/includes/projects/project_search_box.html
index 59ebaa4..ab02f0c 100644
--- a/erpnext/templates/includes/projects/project_search_box.html
+++ b/erpnext/templates/includes/projects/project_search_box.html
@@ -1,12 +1,21 @@
-<div class="project-search">
- <input type="text" id="project-search"
- placeholder="Search...">
- <span style="position:relative;
- left:-19px;"> <a href="/projects?project={{doc.name}}" class="octicon octicon-x text-extra-muted" title="Clear" ></a> </span>
+<div class="project-search text-muted pull-right">
+ <input type="text" id="project-search" placeholder="Quick Search">
+ <i class="octicon octicon-search"></i>
+</div>
+<div class="clearfix pull-right" style="width:300px;">
+ <h4 class="project-search-results pull-left"></h4>
+ <p class="pull-right">
+ <a style="display: none; padding-left:5px;" href="/projects?project={{doc.name}}" class="octicon octicon-x text-extra-muted clear" title="Clear Search" ></a>
+ </p>
</div>
<script>
frappe.ready(function() {
+ if(get_url_arg("q")){
+ var txt = get_url_arg("q");
+ $(".project-search-results").html("Search results for : " + txt);
+ $(".clear").toggle(true);
+ }
var thread = null;
function findResult(t) {
window.location.href="/projects?project={{doc.name}}&q=" + t;
diff --git a/erpnext/templates/includes/projects/project_tasks.html b/erpnext/templates/includes/projects/project_tasks.html
index 3db5a68..b4e5cec 100644
--- a/erpnext/templates/includes/projects/project_tasks.html
+++ b/erpnext/templates/includes/projects/project_tasks.html
@@ -3,22 +3,25 @@
{% for task in doc.tasks %}
<div class='task'>
<div class='row project-item'>
- <div class='col-xs-9'>
+ <div class='col-xs-1 gravatar-top'>
{% if task.todo %}
<span class="avatar avatar-small" title="{{ task.todo.owner }}">
<img src="{{ task.todo.user_image }}">
</span>
{% else %}
<span class="avatar avatar-small avatar-empty"></span>
- {% endif %}
+ {% endif %}
+ </div>
+ <div class='col-xs-11'>
<a class="no-decoration task-link {{ task.css_seen }}" href="/tasks?name={{ task.name }}{{ back_link(doc) }}">
- {% if task.status == "Closed" %}
- {{ task.subject }} completed on {{ task.closing_date }}
- {% else %}
- {{ task.subject }}
- {% endif %}
+ <div class="task-subject">{{ task.subject }}</div>
+ <span class="item-timestamp">modified {{ frappe.utils.pretty_date(task.modified) }}</span>
</a>
+ <span class="pull-right list-comment-count small {{ "text-extra-muted" if task.comment_count==0 else "text-muted" }}">
+ <i class="octicon octicon-comment-discussion"></i>
+ {{ task.comment_count }}
+ </span>
</div>
</div>
</div>
-{% endfor %}
\ No newline at end of file
+{% endfor %}
diff --git a/erpnext/templates/includes/projects/project_timelogs.html b/erpnext/templates/includes/projects/project_timelogs.html
index 7b5913b..c9a40b3 100644
--- a/erpnext/templates/includes/projects/project_timelogs.html
+++ b/erpnext/templates/includes/projects/project_timelogs.html
@@ -3,20 +3,19 @@
{% for timelog in doc.timelogs %}
<div class='timelog'>
<div class='row project-item'>
- <div class='col-xs-9'>
- <a class="no-decoration" href="/timelog_info?timelog={{ timelog.name}}">
- <span class="indicator {{ "green" if timelog.status=="Draft" else "blue" if timelog.status=="Submitted" else "darkgrey"}}">
-
- {{ timelog.title }}: From {{ frappe.format_date(timelog.from_time) }} to {{ frappe.format_date(timelog.to_time) }}
-
-</span>
- </a>
- </div>
- <div class='col-xs-3'>
- <div class='pull-right'>
- <span class="avatar avatar-small" title="{{ timelog.modified_by }}"> <img src="{{ timelog.user_image }}"></span>
- </div>
- </div>
+ <div class='col-xs-1 gravatar-top'>
+ <span class="avatar avatar-small" title="{{ timelog.modified_by }}"> <img src="{{ timelog.user_image }}"></span>
+ </div>
+ <div class='col-xs-11'>
+ <a class="no-decoration timelog-link {{ timelog.css_seen }}" href="/time-log?name={{ timelog.name}}{{ back_link(doc) }}">
+ <div class="timelog-subject">{{ timelog.title }}</div>
+ <span class="item-timestamp">From {{ frappe.format_date(timelog.from_time) }} to {{ frappe.format_date(timelog.to_time) }}</span>
+ </a>
+ <span class="pull-right list-comment-count small {{ "text-extra-muted" if timelog.comment_count==0 else "text-muted" }}">
+ <i class="octicon octicon-comment-discussion"></i>
+ {{ timelog.comment_count }}
+ </span>
+ </div>
</div>
</div>
{% endfor %}
\ No newline at end of file
diff --git a/erpnext/templates/pages/projects.html b/erpnext/templates/pages/projects.html
index fef79ce..199d63c 100644
--- a/erpnext/templates/pages/projects.html
+++ b/erpnext/templates/pages/projects.html
@@ -4,6 +4,10 @@
{%- from "templates/includes/projects/macros.html" import back_link -%}
+{% block header_actions %}
+{% include 'templates/includes/projects/project_search_box.html' %}
+{% endblock %}
+
{% block breadcrumbs %}
<div class="page-breadcrumbs" data-html-block="breadcrumbs">
<ul class="breadcrumb">
@@ -15,11 +19,6 @@
</div>
{% endblock %}
-{% block header %}
-<h1 class= "title">
-{{ doc.project_name }}
-</h1>
-{% endblock %}
{% block style %}
<style>
@@ -30,28 +29,31 @@
{% block page_content %}
-{% include 'templates/includes/projects/project_search_box.html' %}
-
-<!-- {% if frappe.form_dict.q %}
- <p class="text-muted"> <a href="/projects?project={{doc.name}}" class="text-muted">
- Filtered by "{{ frappe.form_dict.q }}" Clear</a></p>
-{% else %}
- <h3>{{ _("Activity Feed") }}</h3>
- <div class='project-timelines timeline-centered'>
- {% include "erpnext/templates/includes/projects/timeline.html" %}
- </div>
- {% if doc.timelines|length > 9 %}
- <p><a class='more-timelines small underline'>{{ _("More") }}</a><p>
- {% endif %}
-
-{% endif %} -->
-
-<div class='padding'></div>
-
-<h3>{{ _("Tasks") }}</h3>
+<div class="row">
+<div class="col-xs-6">
+<h2 class= "title">
+ {{ doc.project_name }}
+</h2>
+</div>
+<div class="col-xs-6">
+ {% if doc.percent_complete %}
+ <div class="progress progress-hg">
+ <div class="progress-bar progress-bar-warning active" role="progressbar"
+ aria-valuenow="{{ doc.percent_complete|round|int }}"
+ aria-valuemin="0" aria-valuemax="100" style="width:{{ doc.percent_complete|round|int }}%;">
+ </div>
+ </div>
+ {% endif %}
+</div>
+</div>
+<hr class="small">
+
+<div class="clearfix">
+ <h4 style="float: left;">{{ _("Tasks") }}</h4>
+ <a class="btn btn-secondary btn-default" style="float: right; position: relative; top: 20px;" href='/tasks?new=1&project={{ doc.project_name }}{{ back_link(doc) }}'>New task</a>
+</div>
<p>
-<a class='small underline' href='/tasks?new=1&project={{ doc.project_name }}{{ back_link(doc) }}'>New task</a>
<a class='small underline task-status-switch' data-status='Open'>{{ _("Show closed") }}</a>
</p>
@@ -67,28 +69,9 @@
{% endif %}
-<!-- <div class='padding'></div>
-<h3>{{ _("Issues") }}</h3>
-
-<p>
- <a class='small underline' href='/issues?new=1&project={{ doc.project_name }}{{ back_link(doc) }}'>New issue</a>
- <a class='small underline issue-status-switch' data-status='Open'>{{ _("Show closed") }}</a>
-</p>
-
-{% if doc.issues %}
- <div class='project-issue-section'>
- <div class='project-issue'>
- {% include "erpnext/templates/includes/projects/project_issues.html" %}
- </div>
- <p><a id='more-issue' style='display: none;' class='more-issues small underline'>{{ _("More") }}</a><p>
- </div>
-{% else %}
- <p class="text-muted">No Issues</p>
-{% endif %} -->
-
<div class='padding'></div>
-<h3>{{ _("Time Logs") }}</h3>
+<h4>{{ _("Time Logs") }}</h4>
{% if doc.timelogs %}
<div class='project-timelogs'>
diff --git a/erpnext/templates/pages/projects.js b/erpnext/templates/pages/projects.js
index a0e0ee0..de9cb76 100644
--- a/erpnext/templates/pages/projects.js
+++ b/erpnext/templates/pages/projects.js
@@ -66,6 +66,7 @@
},
dataType: "json",
success: function(data) {
+ console.log(data.message);
if(typeof data.message == 'undefined') {
$('.project-'+ item).html("No "+ item_status +" "+ item);
$(".more-"+ item).toggle(false);
diff --git a/erpnext/templates/pages/projects.py b/erpnext/templates/pages/projects.py
index c2cb6c7..86f064c 100644
--- a/erpnext/templates/pages/projects.py
+++ b/erpnext/templates/pages/projects.py
@@ -11,67 +11,17 @@
project = frappe.get_doc('Project', frappe.form_dict.project)
project.has_permission('read')
-
- context.issues = frappe.get_all('Issue', filters={'project': project.project_name},
- fields=['subject', 'opening_date', 'resolution_date', 'status', 'name', 'resolution_details','modified','modified_by'])
-
+
project.tasks = get_tasks(project.name, start=0, item_status='open',
search=frappe.form_dict.get("q"))
- project.issues = get_issues(project.name, start=0, item_status='open',
- search=frappe.form_dict.get("q"))
-
project.timelogs = get_timelogs(project.name, start=0,
search=frappe.form_dict.get("q"))
- project.timelines = get_timeline(project.project_name, start=0)
-
-
context.doc = project
-def get_timeline(project, start=10):
- '''Get timeline from project, tasks, issues'''
- issues_condition = ''
- project_issues = get_issues(project)
-
- if project_issues:
- issue_names = '({0})'.format(", ".join(["'{0}'".format(i.name) for i in project_issues]))
- issues_condition = """or (reference_doctype='Issue' and reference_name IN {issue_names})""".format(issue_names=issue_names)
-
-
- timelines = frappe.db.sql("""
- select
- sender_full_name,
- subject, communication_date, comment_type, name, creation, modified_by, reference_doctype, reference_name,
- _liked_by, comment_type, _comments
- from
- tabCommunication
- where
- (reference_doctype='Project' and reference_name=%s)
- or (timeline_doctype='Project' and timeline_name=%s)
- {issues_condition}
- order by
- modified DESC limit {start}, {limit}""".format(
- issues_condition=issues_condition, start=start, limit=10),
- (project, project), as_dict=True);
- for timeline in timelines:
- timeline.user_image = frappe.db.get_value('User', timeline.modified_by, 'user_image')
- return timelines
-
-@frappe.whitelist()
-def get_timelines_html(project, start=0):
- return frappe.render_template("erpnext/templates/includes/projects/timeline.html",
- {"doc": {
- "timelines": get_timeline(project, start)}
- }, is_path=True)
-
-def get_issue_list(project):
- return [issue.name for issue in get_issues(project)]
-
-
-
def get_tasks(project, start=0, search=None, item_status=None):
filters = {"project": project}
if search:
@@ -79,7 +29,7 @@
if item_status:
filters["status"] = item_status
tasks = frappe.get_all("Task", filters=filters,
- fields=["name", "subject", "status", "exp_start_date", "exp_end_date", "priority", "_seen"],
+ fields=["name", "subject", "status", "_seen", "_comments", "modified", "description"],
limit_start=start, limit_page_length=10)
for task in tasks:
@@ -90,8 +40,8 @@
task.todo=task.todo[0]
task.todo.user_image = frappe.db.get_value('User', task.todo.owner, 'user_image')
- if task._comments:
- task.comment_count = len(json.loads(task._comments or "[]"))
+
+ task.comment_count = len(json.loads(task._comments or "[]"))
task.css_seen = ''
if task._seen:
@@ -109,52 +59,23 @@
"tasks": get_tasks(project, start, item_status=item_status)}
}, is_path=True)
-
-
-
-def get_issues(project, start=0, search=None, item_status=None):
- filters = {"project": project}
- if search:
- filters["subject"] = ("like", "%{0}%".format(search))
- if item_status:
- filters["status"] = item_status
- issues = frappe.get_all("Issue", filters=filters,
- fields=["name", "subject", "status", "opening_date", "resolution_date", "resolution_details"],
- order_by='modified desc',
- limit_start=start, limit_page_length=10)
-
- for issue in issues:
- issue.todo = frappe.get_all('ToDo',filters={'reference_name':issue.name, 'reference_type':'Issue'},
- fields=["assigned_by", "owner", "modified", "modified_by"])
- if issue.todo:
- issue.todo=issue.todo[0]
- issue.todo.user_image = frappe.db.get_value('User', issue.todo.owner, 'user_image')
-
- return issues
-
-@frappe.whitelist()
-def get_issue_html(project, start=0, item_status=None):
- return frappe.render_template("erpnext/templates/includes/projects/project_issues.html",
- {"doc": {
- "name": project,
- "project_name": project,
- "issues": get_issues(project, start, item_status=item_status)}
- }, is_path=True)
-
-
-
-
-
def get_timelogs(project, start=0, search=None):
filters = {"project": project}
if search:
filters["title"] = ("like", "%{0}%".format(search))
timelogs = frappe.get_all('Time Log', filters=filters,
- fields=['name','title','task','activity_type','from_time','to_time','hours','status','modified','modified_by'],
+ fields=['name','title','task','activity_type','from_time','to_time','_comments','_seen','status','modified','modified_by'],
limit_start=start, limit_page_length=10)
for timelog in timelogs:
timelog.user_image = frappe.db.get_value('User', timelog.modified_by, 'user_image')
+
+ timelog.comment_count = len(json.loads(timelog._comments or "[]"))
+
+ timelog.css_seen = ''
+ if timelog._seen:
+ if frappe.session.user in json.loads(timelog._seen):
+ timelog.css_seen = 'seen'
return timelogs
@frappe.whitelist()