diff --git a/frappe/public/js/frappe/form/footer/new_timeline.js b/frappe/public/js/frappe/form/footer/new_timeline.js
new file mode 100644
index 0000000000..992357f60f
--- /dev/null
+++ b/frappe/public/js/frappe/form/footer/new_timeline.js
@@ -0,0 +1,108 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+// MIT License. See license.txt
+
+frappe.ui.form.NewTimeline = class {
+ constructor(opts) {
+ Object.assign(this, opts);
+ this.make();
+ }
+
+ make() {
+ this.timeline_wrapper = $(`
`);
+ this.parent.replaceWith(this.timeline_wrapper);
+ this.timeline_items = [];
+ this.render_timeline_items();
+ }
+
+ refresh() {
+
+ }
+
+ add_action_button() {
+
+ }
+
+ render_timeline_items() {
+ this.prepare_timeline_contents();
+
+ this.timeline_items.sort((item1, item2) => item1.creation - item2.creation);
+ this.timeline_items.forEach(item => {
+ this.timeline_wrapper.append(this.get_timeline_item(item));
+ });
+ }
+
+ prepare_timeline_contents() {
+ const doc_info = this.frm.get_docinfo();
+ doc_info.views.forEach(view => {
+ this.timeline_items.push({
+ icon: 'view',
+ creation: view.creation,
+ content: this.get_view_content(view),
+ });
+ });
+
+ Array.from(Array(5)).forEach(() => {
+ this.timeline_items.push({
+ icon: ['mail', 'view', 'call', 'edit'][Math.floor(Math.random() * 4)],
+ creation: Date(),
+ content: `Lorem Ipsum is simply dummy text of the printing and
+ typesetting industry. Lorem Ipsum has been the industry's
+ standard dummy text ever since the 1500s,`,
+ card: true
+ });
+ });
+
+ doc_info.communications.forEach(communication => {
+ this.timeline_items.push({
+ icon: 'mail',
+ creation: communication.creation,
+ card: true,
+ content: this.get_communication_content(communication),
+ });
+ });
+ }
+
+ get_timeline_item(item) {
+ const timeline_item = $(`
+
+
+ ${frappe.utils.icon(item.icon, 'md')}
+
+
+
+
+ `);
+ timeline_item.find('.timeline-content').append(item.content);
+ return timeline_item;
+ }
+
+ get_view_content(doc) {
+ return `
+
+ `;
+ }
+
+ get_communication_content(doc) {
+ let item = $(frappe.render_template('timeline_email', { doc }));
+ this.setup_reply(item);
+ item.find(".timeline-email-content").append(doc.content);
+ return item;
+ }
+
+ setup_reply(communication_box) {
+ let actions = communication_box.find('.actions');
+ let reply = $(`
${frappe.utils.icon('reply', 'md')}`).click(e => {
+ console.log(e);
+ });
+ let reply_all = $(`
${frappe.utils.icon('reply-all', 'md')}`).click(e => {
+ console.log(e);
+ });
+ actions.append(reply);
+ actions.append(reply_all);
+ }
+};
\ No newline at end of file
diff --git a/frappe/public/js/frappe/form/templates/timeline_email.html b/frappe/public/js/frappe/form/templates/timeline_email.html
new file mode 100644
index 0000000000..6adff6ddf8
--- /dev/null
+++ b/frappe/public/js/frappe/form/templates/timeline_email.html
@@ -0,0 +1,11 @@
+
+
+
+ {{ frappe.avatar(doc.owner) }}
+ {{ frappe.user.full_name(doc.owner) }}
+ {{ comment_when(doc.creation) }}
+
+
+
+
+
\ No newline at end of file
diff --git a/frappe/public/scss/global.scss b/frappe/public/scss/global.scss
index 3473459bb0..9c2452c78e 100644
--- a/frappe/public/scss/global.scss
+++ b/frappe/public/scss/global.scss
@@ -215,6 +215,9 @@ select.input-xs {
font-weight: 600;
}
+.text-color {
+ color: var(--text-color);
+}
/* dropdowns */
@@ -291,3 +294,7 @@ input[type="checkbox"] {
line-height: 10px;
}
}
+
+.frappe-card {
+ @include card();
+}
\ No newline at end of file
diff --git a/frappe/public/scss/main.scss b/frappe/public/scss/main.scss
index 6b057a5d7c..31ff7bb5a7 100644
--- a/frappe/public/scss/main.scss
+++ b/frappe/public/scss/main.scss
@@ -4,6 +4,7 @@
@import "~bootstrap/scss/bootstrap";
@import "global";
@import "form";
+@import "timeline";
@import "list";
@import "navbar";
@import "modal";
diff --git a/frappe/public/scss/timeline.scss b/frappe/public/scss/timeline.scss
new file mode 100644
index 0000000000..34ba6157fe
--- /dev/null
+++ b/frappe/public/scss/timeline.scss
@@ -0,0 +1,48 @@
+$timeline-item-icon-size: 34px;
+$timeline-item-left-margin: var(--margin-xl);
+$threshold: 50px;
+.new-timeline {
+ position: relative;
+ padding-left: var(--padding-xl);
+ padding-top: var(--padding-xl);
+ &:before {
+ content: ' ';
+ top: 0;
+ height: 100%;
+ position: absolute;
+ border-left: 1px solid var(--gray-300);
+ }
+
+ .timeline-item {
+ position: relative;
+ margin-bottom: var(--margin-lg);
+ .timeline-content {
+ max-width: 700px;
+ padding: var(--padding-sm);
+ margin-left: $timeline-item-left-margin;
+ &.frappe-card {
+ @include card($padding: var(--padding-lg));
+ }
+ }
+ .timeline-indicator {
+ width: $timeline-item-icon-size;
+ height: $timeline-item-icon-size;
+ border-radius: 50%;
+ position: absolute;
+ top: unquote("clamp(0px, 50% - #{$timeline-item-icon-size}/2, 50px)");
+ left: calc(-1 * (#{$timeline-item-icon-size}/2));
+ background-color: var(--gray-600);
+ display: inline-flex;
+ align-items: center;
+ .icon {
+ stroke: $white;
+ }
+ }
+
+ .timeline-email {
+ .timeline-email-content {
+ margin-top: var(--margin-sm);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/frappe/public/scss/website.scss b/frappe/public/scss/website.scss
index 2ce81de60c..edcd25ae9c 100644
--- a/frappe/public/scss/website.scss
+++ b/frappe/public/scss/website.scss
@@ -1,4 +1,5 @@
@import "variables";
+@import "mixins";
@import 'frappe/public/css/font-awesome';
@import "~bootstrap/scss/bootstrap";
@import 'multilevel-dropdown';