UI Changes
diff --git a/erpnext/projects/doctype/project/project.py b/erpnext/projects/doctype/project/project.py
index fa2f6b4..edfd964 100644
--- a/erpnext/projects/doctype/project/project.py
+++ b/erpnext/projects/doctype/project/project.py
@@ -4,7 +4,7 @@
from __future__ import unicode_literals
import frappe
-from frappe.utils import flt, getdate
+from frappe.utils import flt, getdate, get_url
from frappe import _
from frappe.model.document import Document
@@ -36,7 +36,8 @@
self.validate_dates()
self.sync_tasks()
self.tasks = []
-
+ self.send_welcome_email()
+
def validate_dates(self):
if self.expected_start_date and self.expected_end_date:
if getdate(self.expected_end_date) < getdate(self.expected_start_date):
@@ -123,8 +124,26 @@
from `tabPurchase Invoice Item` where project = %s and docstatus=1""", self.name)
self.total_purchase_cost = total_purchase_cost and total_purchase_cost[0][0] or 0
+
+ def send_welcome_email(self):
+ url = get_url("/project/{0}".format(self.name))
+ messages = (
+ _("You have been invited to collaborate on the project: {0}".format(self.name)),
+ url,
+ _("Join")
+ )
+ content = """
+ <p>{0}.</p>
+ <p><a href="{1}">{2}</a></p>
+ """
+ for user in self.users:
+ if user.welcome_email_sent==0:
+ print user.welcome_email_sent
+ frappe.sendmail(user.user, subject=_("Project Collaboration Invitation"), content=content.format(*messages), bulk=True)
+ user.welcome_email_sent=1
+
def get_project_list(doctype, txt, filters, limit_start, limit_page_length=20):
return frappe.db.sql('''select distinct project.*
diff --git a/erpnext/projects/doctype/project_user/project_user.json b/erpnext/projects/doctype/project_user/project_user.json
index f808701..39863fd 100644
--- a/erpnext/projects/doctype/project_user/project_user.json
+++ b/erpnext/projects/doctype/project_user/project_user.json
@@ -33,6 +33,31 @@
"search_index": 1,
"set_only_once": 0,
"unique": 0
+ },
+ {
+ "allow_on_submit": 0,
+ "bold": 0,
+ "collapsible": 0,
+ "fieldname": "welcome_email_sent",
+ "fieldtype": "Check",
+ "hidden": 0,
+ "ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
+ "in_filter": 0,
+ "in_list_view": 0,
+ "label": "Welcome email sent",
+ "length": 0,
+ "no_copy": 0,
+ "permlevel": 0,
+ "precision": "",
+ "print_hide": 0,
+ "print_hide_if_no_value": 0,
+ "read_only": 0,
+ "report_hide": 0,
+ "reqd": 0,
+ "search_index": 0,
+ "set_only_once": 0,
+ "unique": 0
}
],
"hide_heading": 0,
@@ -44,7 +69,7 @@
"issingle": 0,
"istable": 1,
"max_attachments": 0,
- "modified": "2016-03-25 03:01:08.629640",
+ "modified": "2016-03-28 17:33:08.621181",
"modified_by": "Administrator",
"module": "Projects",
"name": "Project User",
@@ -54,5 +79,6 @@
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
- "sort_order": "DESC"
+ "sort_order": "DESC",
+ "track_seen": 0
}
\ No newline at end of file
diff --git a/erpnext/projects/doctype/time_log/time_log.json b/erpnext/projects/doctype/time_log/time_log.json
index fb1a710..21e68cc 100644
--- a/erpnext/projects/doctype/time_log/time_log.json
+++ b/erpnext/projects/doctype/time_log/time_log.json
@@ -19,6 +19,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Activity Type",
@@ -43,6 +44,7 @@
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Series",
@@ -68,6 +70,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Project",
@@ -93,6 +96,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Task",
@@ -117,6 +121,7 @@
"fieldtype": "Select",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Status",
@@ -141,6 +146,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -164,6 +170,7 @@
"fieldtype": "Datetime",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "From Time",
@@ -188,6 +195,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 1,
"label": "Hours",
@@ -211,6 +219,7 @@
"fieldtype": "Datetime",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "To Time",
@@ -234,6 +243,7 @@
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Billable",
@@ -257,6 +267,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -279,6 +290,7 @@
"fieldtype": "Text Editor",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Note",
@@ -302,6 +314,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -325,6 +338,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "User",
@@ -350,6 +364,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Employee",
@@ -375,6 +390,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -397,6 +413,7 @@
"fieldtype": "Check",
"hidden": 1,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "For Manufacturing",
@@ -422,6 +439,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -446,6 +464,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Production Order",
@@ -472,6 +491,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Operation",
@@ -498,6 +518,7 @@
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Operation ID",
@@ -523,6 +544,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -547,6 +569,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Workstation",
@@ -574,6 +597,7 @@
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Completed Qty",
@@ -599,6 +623,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -624,6 +649,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Costing Rate based on Activity Type (per hour)",
@@ -649,6 +675,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Costing Amount",
@@ -673,6 +700,7 @@
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -698,6 +726,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Billing Rate based on Activity Type (per hour)",
@@ -723,6 +752,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Additional Cost",
@@ -749,6 +779,7 @@
"fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Billing Amount",
@@ -773,6 +804,7 @@
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"length": 0,
@@ -797,6 +829,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Time Log Batch",
@@ -822,6 +855,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Sales Invoice",
@@ -846,6 +880,7 @@
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 1,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Amended From",
@@ -870,6 +905,7 @@
"fieldtype": "Data",
"hidden": 1,
"ignore_user_permissions": 0,
+ "ignore_xss_filter": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Title",
@@ -897,7 +933,7 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
- "modified": "2016-01-29 04:05:43.489154",
+ "modified": "2016-03-29 15:55:12.780956",
"modified_by": "Administrator",
"module": "Projects",
"name": "Time Log",
@@ -905,7 +941,7 @@
"permissions": [
{
"amend": 1,
- "apply_user_permissions": 0,
+ "apply_user_permissions": 1,
"cancel": 1,
"create": 1,
"delete": 1,
@@ -917,6 +953,8 @@
"print": 1,
"read": 1,
"report": 1,
+ "restrict": 0,
+ "restricted": 1,
"role": "Projects User",
"set_user_permissions": 0,
"share": 1,
@@ -937,6 +975,8 @@
"print": 1,
"read": 1,
"report": 1,
+ "restrict": 0,
+ "restricted": 0,
"role": "Projects Manager",
"set_user_permissions": 0,
"share": 1,
@@ -947,5 +987,6 @@
"read_only": 0,
"read_only_onload": 0,
"sort_order": "ASC",
- "title_field": "title"
+ "title_field": "title",
+ "track_seen": 1
}
\ No newline at end of file
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()