[enhancement] Show who is currently viewing a document
This commit is contained in:
parent
0cba385f24
commit
40f679322b
31 changed files with 403 additions and 164 deletions
|
|
@ -65,7 +65,7 @@
|
|||
"public/js/frappe/ui/messages.js",
|
||||
|
||||
"public/js/frappe/request.js",
|
||||
"public/js/frappe/socket.js",
|
||||
"public/js/frappe/socketio_client.js",
|
||||
"public/js/frappe/router.js",
|
||||
"public/js/frappe/defaults.js",
|
||||
"public/js/lib/microtemplate.js",
|
||||
|
|
@ -149,8 +149,10 @@
|
|||
"public/js/frappe/form/print_layout.html",
|
||||
"public/js/frappe/form/print.js",
|
||||
"public/js/frappe/form/sidebar.js",
|
||||
"public/js/frappe/form/users_in_sidebar.html",
|
||||
"public/js/frappe/form/share.js",
|
||||
"public/js/frappe/form/set_sharing.html",
|
||||
"public/js/frappe/form/form_viewers.js",
|
||||
"public/js/frappe/form/form_sidebar.html",
|
||||
|
||||
"public/js/frappe/form/footer/form_footer.html",
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
margin-left: -1px;
|
||||
}
|
||||
th.fc-widget-header {
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
color: #8C99A5;
|
||||
}
|
||||
.fc-unthemed th,
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ p {
|
|||
margin: 10px 0px;
|
||||
}
|
||||
.text-color {
|
||||
color: #36414c !important;
|
||||
color: #36414C !important;
|
||||
}
|
||||
.text-muted {
|
||||
color: #8d99a6 !important;
|
||||
color: #8D99A6 !important;
|
||||
}
|
||||
.text-extra-muted {
|
||||
color: #d1d8dd !important;
|
||||
|
|
@ -82,7 +82,7 @@ a.text-extra-muted {
|
|||
}
|
||||
kbd {
|
||||
color: inherit;
|
||||
background-color: #f0f4f7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
.btn [class^="icon-"],
|
||||
.nav [class^="icon-"],
|
||||
|
|
@ -186,7 +186,7 @@ a.badge-hover:active .badge {
|
|||
transform: translate(-50%, -50%);
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
text-align: center;
|
||||
color: #36414c !important;
|
||||
color: #36414C !important;
|
||||
}
|
||||
#freeze.dark {
|
||||
background-color: #334143;
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ p {
|
|||
margin: 10px 0px;
|
||||
}
|
||||
.text-color {
|
||||
color: #36414c !important;
|
||||
color: #36414C !important;
|
||||
}
|
||||
.text-muted {
|
||||
color: #8d99a6 !important;
|
||||
color: #8D99A6 !important;
|
||||
}
|
||||
.text-extra-muted {
|
||||
color: #d1d8dd !important;
|
||||
|
|
@ -82,7 +82,7 @@ a.text-extra-muted {
|
|||
}
|
||||
kbd {
|
||||
color: inherit;
|
||||
background-color: #f0f4f7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
.btn [class^="icon-"],
|
||||
.nav [class^="icon-"],
|
||||
|
|
@ -186,7 +186,7 @@ a.badge-hover:active .badge {
|
|||
transform: translate(-50%, -50%);
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
text-align: center;
|
||||
color: #36414c !important;
|
||||
color: #36414C !important;
|
||||
}
|
||||
#freeze.dark {
|
||||
background-color: #334143;
|
||||
|
|
@ -237,11 +237,11 @@ a.form-link {
|
|||
display: none;
|
||||
}
|
||||
.link-primary {
|
||||
color: #5e64ff;
|
||||
color: #5E64FF;
|
||||
}
|
||||
.link-primary:hover,
|
||||
.link-primary:focus {
|
||||
color: #5e64ff;
|
||||
color: #5E64FF;
|
||||
}
|
||||
.ui-autocomplete .link-option {
|
||||
font-weight: normal;
|
||||
|
|
@ -358,13 +358,13 @@ ul.linked-with-list li {
|
|||
.ui-autocomplete .ui-state-focus,
|
||||
.ui-datepicker .ui-state-hover,
|
||||
.ui-autocomplete .ui-state-hover {
|
||||
background-color: #f0f4f7 !important;
|
||||
color: #36414c !important;
|
||||
background-color: #F0F4F7 !important;
|
||||
color: #36414C !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
.ui-datepicker .ui-state-active,
|
||||
.ui-autocomplete .ui-state-active {
|
||||
background-color: #5e64ff !important;
|
||||
background-color: #5E64FF !important;
|
||||
color: #fff !important;
|
||||
text-shadow: none !important;
|
||||
}
|
||||
|
|
@ -390,7 +390,7 @@ ul.linked-with-list li {
|
|||
}
|
||||
}
|
||||
.panel-bg {
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
}
|
||||
.light-bg {
|
||||
background-color: #fafbfc;
|
||||
|
|
@ -452,7 +452,7 @@ ul.linked-with-list li {
|
|||
.msg-box {
|
||||
padding: 30px 15px;
|
||||
text-align: center;
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
}
|
||||
.no-border {
|
||||
border: none !important;
|
||||
|
|
@ -483,7 +483,7 @@ ul.linked-with-list li {
|
|||
border-top: 1px solid #d1d8dd;
|
||||
}
|
||||
.file-upload .input-group-addon {
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
font-size: 12px;
|
||||
}
|
||||
.file-upload .file-upload-or {
|
||||
|
|
|
|||
|
|
@ -75,11 +75,11 @@ body[data-route="desktop"] .navbar-default {
|
|||
letter-spacing: normal;
|
||||
}
|
||||
.app-icon:hover path {
|
||||
fill: #ffffff;
|
||||
fill: #fff;
|
||||
}
|
||||
.app-icon:hover i,
|
||||
.app-icon:hover {
|
||||
color: #ffffff;
|
||||
color: #fff;
|
||||
}
|
||||
.app-icon-small {
|
||||
padding: 12px;
|
||||
|
|
@ -168,7 +168,7 @@ body[data-route="desktop"] .navbar-default {
|
|||
}
|
||||
.desktop-list-item:hover,
|
||||
.desktop-list-item:focus {
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
}
|
||||
.desktop-list-item h4 {
|
||||
display: inline-block;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ body {
|
|||
.offcanvas .sidebar .divider {
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
background-color: #ebeff2;
|
||||
background-color: #EBEFF2;
|
||||
width: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ body {
|
|||
.offcanvas .sidebar .dropdown-menu > li > a:focus,
|
||||
.offcanvas .sidebar .sidebar-menu > li > a:active,
|
||||
.offcanvas .sidebar .dropdown-menu > li > a:active {
|
||||
background-color: #f0f4f7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.page-content {
|
||||
|
|
@ -124,7 +124,7 @@ body {
|
|||
}
|
||||
.offcanvas .sidebar-label {
|
||||
text-transform: uppercase;
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
font-size: 85%;
|
||||
margin: 0px;
|
||||
font-weight: bold;
|
||||
|
|
@ -175,7 +175,7 @@ body {
|
|||
background-color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
.navbar .navbar-search-icon {
|
||||
color: #6c7680;
|
||||
color: #6C7680;
|
||||
font-size: inherit;
|
||||
position: relative;
|
||||
right: 24px;
|
||||
|
|
@ -194,7 +194,7 @@ body {
|
|||
}
|
||||
.navbar-center {
|
||||
float: left;
|
||||
color: #6c7680;
|
||||
color: #6C7680;
|
||||
}
|
||||
#navbar-breadcrumbs > li > a:before {
|
||||
font-family: FontAwesome;
|
||||
|
|
@ -211,12 +211,12 @@ body {
|
|||
top: 3px;
|
||||
content: "\f105";
|
||||
margin-right: 10px;
|
||||
color: #c0c9d2;
|
||||
color: #C0C9D2;
|
||||
}
|
||||
#navbar-breadcrumbs > li > a:hover:before,
|
||||
#navbar-breadcrumbs > li > a:focus:before,
|
||||
#navbar-breadcrumbs > li > a:active:before {
|
||||
color: #36414c;
|
||||
color: #36414C;
|
||||
}
|
||||
#navbar-breadcrumbs > li > a {
|
||||
padding: 6px 15px 10px 0px;
|
||||
|
|
@ -245,7 +245,7 @@ body {
|
|||
}
|
||||
.breadcrumb {
|
||||
line-height: 1.5em;
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
background-color: transparent;
|
||||
margin-bottom: 10px;
|
||||
padding: 0px;
|
||||
|
|
@ -261,7 +261,7 @@ a,
|
|||
a:hover,
|
||||
a:focus,
|
||||
a:visited {
|
||||
color: #5e64ff;
|
||||
color: #5E64FF;
|
||||
}
|
||||
a.btn-primary {
|
||||
color: #fff;
|
||||
|
|
@ -296,7 +296,7 @@ h2 {
|
|||
border-top: 1px solid #d1d8dd;
|
||||
}
|
||||
.docs-footer a {
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
}
|
||||
.docs-footer li {
|
||||
display: inline-block;
|
||||
|
|
@ -312,7 +312,7 @@ h2 {
|
|||
font-weight: 400;
|
||||
}
|
||||
.jumbotron p {
|
||||
font-color: #8d99a6 !important;
|
||||
font-color: #8D99A6 !important;
|
||||
}
|
||||
.browser-image {
|
||||
min-height: 300px;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
.form-clickable-section {
|
||||
border-top: 1px solid #d1d8dd;
|
||||
padding: 10px 15px;
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
}
|
||||
.form-page.second-page {
|
||||
border-top: 1px solid #d1d8dd;
|
||||
|
|
@ -56,7 +56,7 @@
|
|||
}
|
||||
.form-section:not(:last-child),
|
||||
.form-inner-toolbar {
|
||||
border-bottom: 1px solid #ebeff2;
|
||||
border-bottom: 1px solid #EBEFF2;
|
||||
}
|
||||
.empty-section {
|
||||
display: none !important;
|
||||
|
|
@ -125,7 +125,7 @@
|
|||
}
|
||||
.control-label,
|
||||
.grid-heading-row {
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
font-size: 12px;
|
||||
}
|
||||
.control-label {
|
||||
|
|
@ -186,7 +186,7 @@ select.form-control {
|
|||
margin-top: -3px;
|
||||
margin-left: 1px;
|
||||
font-weight: 500;
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.layout-main .form-column.col-sm-12 > form > .input-max-width {
|
||||
|
|
@ -208,7 +208,7 @@ select.form-control {
|
|||
padding: 15px 15px 15px 0px;
|
||||
}
|
||||
.form-column {
|
||||
border-bottom: 1px solid #ebeff2;
|
||||
border-bottom: 1px solid #EBEFF2;
|
||||
}
|
||||
.form-column:last-child {
|
||||
border-bottom: 0px;
|
||||
|
|
@ -229,7 +229,7 @@ select.form-control {
|
|||
}
|
||||
.form-page .frappe-control {
|
||||
padding: 7px 15px;
|
||||
border-bottom: 1px solid #ebeff2;
|
||||
border-bottom: 1px solid #EBEFF2;
|
||||
margin: 0px -15px;
|
||||
}
|
||||
.form-page .frappe-control .link-btn {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
}
|
||||
.grid-heading-row {
|
||||
border-bottom: 1px solid #d1d8dd;
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
font-weight: bold;
|
||||
}
|
||||
.grid-row {
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@
|
|||
.fn-gantt .rightPanel .month,
|
||||
.fn-gantt .rightPanel .year,
|
||||
.fn-gantt .bottom {
|
||||
background-color: #f7fafc !important;
|
||||
background-color: #F7FAFC !important;
|
||||
}
|
||||
.fn-gantt .today {
|
||||
background-color: #D9F6FF !important;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
}
|
||||
.indicator.grey::before,
|
||||
.indicator-right.grey::after {
|
||||
background: #f0f4f7;
|
||||
background: #F0F4F7;
|
||||
}
|
||||
.indicator.blue::before,
|
||||
.indicator-right.blue::after {
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
.set-filters .btn-group .btn-default {
|
||||
background-color: transparent;
|
||||
border: 1px solid #d1d8dd;
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
}
|
||||
.filter-box {
|
||||
border-top: 1px solid #d1d8dd;
|
||||
|
|
@ -61,18 +61,18 @@
|
|||
margin-bottom: 0px;
|
||||
}
|
||||
.list-row-head {
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
border-bottom: 1px solid #d1d8dd !important;
|
||||
}
|
||||
.list-row:hover,
|
||||
.grid-row:hover {
|
||||
background: #f7fafc;
|
||||
background: #F7FAFC;
|
||||
}
|
||||
.list-row:last-child {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
.list-row-head {
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
border-bottom: 1px solid #d1d8dd !important;
|
||||
}
|
||||
.list-row .h6 {
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ body {
|
|||
.offcanvas .sidebar .divider {
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
background-color: #ebeff2;
|
||||
background-color: #EBEFF2;
|
||||
width: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ body {
|
|||
.offcanvas .sidebar .dropdown-menu > li > a:focus,
|
||||
.offcanvas .sidebar .sidebar-menu > li > a:active,
|
||||
.offcanvas .sidebar .dropdown-menu > li > a:active {
|
||||
background-color: #f0f4f7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
@media (max-width: 991px) {
|
||||
input[type='checkbox'] {
|
||||
|
|
@ -133,7 +133,7 @@ body {
|
|||
#navbar-breadcrumbs > li > a:before {
|
||||
content: "\f104";
|
||||
margin-right: 10px;
|
||||
color: #6c7680;
|
||||
color: #6C7680;
|
||||
}
|
||||
#navbar-breadcrumbs li:not(:nth-last-child(-n+1)) {
|
||||
display: none;
|
||||
|
|
@ -204,7 +204,7 @@ body {
|
|||
}
|
||||
.sidebar .navbar-search-icon {
|
||||
float: right;
|
||||
color: #6c7680;
|
||||
color: #6C7680;
|
||||
font-size: inherit;
|
||||
position: relative;
|
||||
right: 7px;
|
||||
|
|
@ -232,7 +232,7 @@ body {
|
|||
}
|
||||
.sidebar .user-menu,
|
||||
.sidebar .user-menu .octicon {
|
||||
color: #6c7680;
|
||||
color: #6C7680;
|
||||
}
|
||||
.sidebar .user-menu img {
|
||||
margin-top: -1px;
|
||||
|
|
@ -266,12 +266,12 @@ body {
|
|||
top: 3px;
|
||||
content: "\f104";
|
||||
margin-right: 10px;
|
||||
color: #6c7680;
|
||||
color: #6C7680;
|
||||
}
|
||||
body.no-breadcrumbs .navbar .navbar-home:hover:before,
|
||||
body.no-breadcrumbs .navbar .navbar-home:focus:before,
|
||||
body.no-breadcrumbs .navbar .navbar-home:active:before {
|
||||
color: #36414c !important;
|
||||
color: #36414C !important;
|
||||
}
|
||||
body[data-route=""] .navbar .navbar-home,
|
||||
body[data-route="desktop"] .navbar .navbar-home {
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@
|
|||
}
|
||||
.module-item:hover,
|
||||
.module-item:focus {
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
}
|
||||
.module-item:last-child {
|
||||
border: none;
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
background-color: rgba(255, 255, 255, 0.9);
|
||||
}
|
||||
.navbar .navbar-search-icon {
|
||||
color: #6c7680;
|
||||
color: #6C7680;
|
||||
font-size: inherit;
|
||||
position: relative;
|
||||
right: 24px;
|
||||
|
|
@ -61,7 +61,7 @@
|
|||
}
|
||||
.navbar-center {
|
||||
float: left;
|
||||
color: #6c7680;
|
||||
color: #6C7680;
|
||||
}
|
||||
#navbar-breadcrumbs > li > a:before {
|
||||
font-family: FontAwesome;
|
||||
|
|
@ -78,12 +78,12 @@
|
|||
top: 3px;
|
||||
content: "\f105";
|
||||
margin-right: 10px;
|
||||
color: #c0c9d2;
|
||||
color: #C0C9D2;
|
||||
}
|
||||
#navbar-breadcrumbs > li > a:hover:before,
|
||||
#navbar-breadcrumbs > li > a:focus:before,
|
||||
#navbar-breadcrumbs > li > a:active:before {
|
||||
color: #36414c;
|
||||
color: #36414C;
|
||||
}
|
||||
#navbar-breadcrumbs > li > a {
|
||||
padding: 6px 15px 10px 0px;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ body {
|
|||
.offcanvas .sidebar .divider {
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
background-color: #ebeff2;
|
||||
background-color: #EBEFF2;
|
||||
width: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ body {
|
|||
.offcanvas .sidebar .dropdown-menu > li > a:focus,
|
||||
.offcanvas .sidebar .sidebar-menu > li > a:active,
|
||||
.offcanvas .sidebar .dropdown-menu > li > a:active {
|
||||
background-color: #f0f4f7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.page-content {
|
||||
|
|
@ -124,7 +124,7 @@ body {
|
|||
}
|
||||
.offcanvas .sidebar-label {
|
||||
text-transform: uppercase;
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
font-size: 85%;
|
||||
margin: 0px;
|
||||
font-weight: bold;
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ body {
|
|||
.offcanvas .sidebar .divider {
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
background-color: #ebeff2;
|
||||
background-color: #EBEFF2;
|
||||
width: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
|
|
@ -52,5 +52,5 @@ body {
|
|||
.offcanvas .sidebar .dropdown-menu > li > a:focus,
|
||||
.offcanvas .sidebar .sidebar-menu > li > a:active,
|
||||
.offcanvas .sidebar .dropdown-menu > li > a:active {
|
||||
background-color: #f0f4f7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ body {
|
|||
.offcanvas .sidebar .divider {
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
background-color: #ebeff2;
|
||||
background-color: #EBEFF2;
|
||||
width: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ body {
|
|||
.offcanvas .sidebar .dropdown-menu > li > a:focus,
|
||||
.offcanvas .sidebar .sidebar-menu > li > a:active,
|
||||
.offcanvas .sidebar .dropdown-menu > li > a:active {
|
||||
background-color: #f0f4f7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
.hide-form-sidebar .form-sidebar {
|
||||
display: none !important;
|
||||
|
|
@ -108,7 +108,7 @@ body[data-route^="Module"] .main-menu .form-sidebar {
|
|||
.sidebar-menu h6,
|
||||
.sidebar-menu .h6 {
|
||||
text-transform: uppercase;
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
font-size: 10px;
|
||||
margin-top: 0px;
|
||||
}
|
||||
|
|
@ -122,7 +122,7 @@ body[data-route^="Module"] .main-menu .form-sidebar {
|
|||
}
|
||||
.form-sidebar .form-tags input {
|
||||
font-size: 12px !important;
|
||||
color: #36414c !important;
|
||||
color: #36414C !important;
|
||||
font-style: italic;
|
||||
}
|
||||
.form-sidebar .form-tags .tagit-new {
|
||||
|
|
@ -137,34 +137,39 @@ body[data-route^="Module"] .main-menu .form-sidebar {
|
|||
.form-sidebar .attachment-row a.close {
|
||||
margin-top: -5px;
|
||||
}
|
||||
.form-sidebar .form-shared .share-doc-btn {
|
||||
.form-sidebar .form-shared .share-doc-btn,
|
||||
.form-sidebar .form-viewers .share-doc-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
.form-sidebar .form-shared .octicon {
|
||||
.form-sidebar .form-shared .octicon,
|
||||
.form-sidebar .form-viewers .octicon {
|
||||
position: relative;
|
||||
top: 2px;
|
||||
left: 7px;
|
||||
}
|
||||
.form-sidebar .form-shared .avatar {
|
||||
.form-sidebar .form-shared .avatar,
|
||||
.form-sidebar .form-viewers .avatar {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.form-sidebar .form-shared .shared-with-everyone {
|
||||
.form-sidebar .form-shared .shared-with-everyone,
|
||||
.form-sidebar .form-viewers .shared-with-everyone {
|
||||
border-style: solid;
|
||||
border-color: #f0f4f7;
|
||||
background-color: #f0f4f7;
|
||||
border-color: #F0F4F7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
.form-sidebar .form-shared .shared-with-everyone .octicon {
|
||||
color: #36414c !important;
|
||||
.form-sidebar .form-shared .shared-with-everyone .octicon,
|
||||
.form-sidebar .form-viewers .shared-with-everyone .octicon {
|
||||
color: #36414C !important;
|
||||
}
|
||||
.form-sidebar .form-shared .share-doc-btn:hover,
|
||||
.form-sidebar .form-shared .share-doc-btn:focus,
|
||||
.form-sidebar .form-shared .share-doc-btn:active {
|
||||
background-color: #f0f4f7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
.form-sidebar .form-shared .share-doc-btn:hover .octicon-plus,
|
||||
.form-sidebar .form-shared .share-doc-btn:focus .octicon-plus,
|
||||
.form-sidebar .form-shared .share-doc-btn:active .octicon-plus {
|
||||
color: #36414c !important;
|
||||
color: #36414C !important;
|
||||
}
|
||||
.sidebar-left .form-sidebar .form-tags,
|
||||
.sidebar-left .form-sidebar .assignment-row,
|
||||
|
|
@ -172,20 +177,24 @@ body[data-route^="Module"] .main-menu .form-sidebar {
|
|||
.sidebar-left .form-sidebar .modified-by,
|
||||
.sidebar-left .form-sidebar .created-by,
|
||||
.sidebar-left .form-sidebar .tags-label,
|
||||
.sidebar-left .form-sidebar .shared-with-label {
|
||||
.sidebar-left .form-sidebar .shared-with-label,
|
||||
.sidebar-left .form-sidebar .form-viewers,
|
||||
.sidebar-left .form-sidebar .viewers-label {
|
||||
padding: 12px 14px;
|
||||
}
|
||||
.sidebar-left .form-sidebar .assigned-to-label,
|
||||
.sidebar-left .form-sidebar .attachments-label,
|
||||
.sidebar-left .form-sidebar .tags-label,
|
||||
.sidebar-left .form-sidebar .shared-with-label {
|
||||
.sidebar-left .form-sidebar .shared-with-label,
|
||||
.sidebar-left .form-sidebar .viewers-label {
|
||||
padding: 12px 14px;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.sidebar-left .form-sidebar .assigned-to-label,
|
||||
.sidebar-left .form-sidebar .tags-label,
|
||||
.sidebar-left .form-sidebar .attachments-label.has-attachments,
|
||||
.sidebar-left .form-sidebar .shared-with-label {
|
||||
.sidebar-left .form-sidebar .shared-with-label,
|
||||
.sidebar-left .form-sidebar .viewers-label {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
.sidebar-left .form-sidebar a.close {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
border-bottom: 1px solid #d1d8dd;
|
||||
}
|
||||
.slick-headerrow-column {
|
||||
background-color: #f7fafc !important;
|
||||
background-color: #F7FAFC !important;
|
||||
text-overflow: clip;
|
||||
}
|
||||
.slick-headerrow-column input {
|
||||
|
|
@ -37,9 +37,9 @@
|
|||
.slick-header-columns {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
border-color: #d1d8dd !important;
|
||||
color: #8d99a6 !important;
|
||||
color: #8D99A6 !important;
|
||||
}
|
||||
.slick-header-column:hover,
|
||||
.slick-header-column-active {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ ul.tree-children {
|
|||
color: #5e64ff !important;
|
||||
}
|
||||
.tree-hover {
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
min-height: 20px;
|
||||
border: 1px solid #d1d8dd;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,10 +18,10 @@ p {
|
|||
margin: 10px 0px;
|
||||
}
|
||||
.text-color {
|
||||
color: #36414c !important;
|
||||
color: #36414C !important;
|
||||
}
|
||||
.text-muted {
|
||||
color: #8d99a6 !important;
|
||||
color: #8D99A6 !important;
|
||||
}
|
||||
.text-extra-muted {
|
||||
color: #d1d8dd !important;
|
||||
|
|
@ -82,7 +82,7 @@ a.text-extra-muted {
|
|||
}
|
||||
kbd {
|
||||
color: inherit;
|
||||
background-color: #f0f4f7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
.btn [class^="icon-"],
|
||||
.nav [class^="icon-"],
|
||||
|
|
@ -186,7 +186,7 @@ a.badge-hover:active .badge {
|
|||
transform: translate(-50%, -50%);
|
||||
-webkit-transform: translate(-50%, -50%);
|
||||
text-align: center;
|
||||
color: #36414c !important;
|
||||
color: #36414C !important;
|
||||
}
|
||||
#freeze.dark {
|
||||
background-color: #334143;
|
||||
|
|
@ -288,7 +288,7 @@ a.no-decoration:active {
|
|||
}
|
||||
.indicator.grey::before,
|
||||
.indicator-right.grey::after {
|
||||
background: #f0f4f7;
|
||||
background: #F0F4F7;
|
||||
}
|
||||
.indicator.blue::before,
|
||||
.indicator-right.blue::after {
|
||||
|
|
@ -339,7 +339,7 @@ a.no-decoration:active {
|
|||
background-color: #fafbfc;
|
||||
}
|
||||
.panel-bg {
|
||||
background-color: #f7fafc;
|
||||
background-color: #F7FAFC;
|
||||
}
|
||||
.navbar-bg {
|
||||
background-color: #f5f7fa;
|
||||
|
|
@ -463,7 +463,7 @@ fieldset {
|
|||
margin: 0px;
|
||||
padding: 5px 0px;
|
||||
border: none;
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
font-size: 12px;
|
||||
}
|
||||
.page-sidebar .sidebar-item:first-child {
|
||||
|
|
@ -473,7 +473,7 @@ fieldset {
|
|||
padding-bottom: 10px;
|
||||
}
|
||||
.page-sidebar .sidebar-item a {
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
}
|
||||
.page-sidebar .sidebar-item a:hover {
|
||||
border-color: inherit;
|
||||
|
|
@ -499,7 +499,7 @@ fieldset {
|
|||
}
|
||||
.web-list-item {
|
||||
padding: 15px 0px;
|
||||
border-bottom: 1px solid #ebeff2;
|
||||
border-bottom: 1px solid #EBEFF2;
|
||||
}
|
||||
.web-list-item h1,
|
||||
.web-list-item h2,
|
||||
|
|
@ -609,7 +609,7 @@ a.active {
|
|||
color: inherit;
|
||||
}
|
||||
.breadcrumb > .active {
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
}
|
||||
.post:last-child {
|
||||
border-bottom: none;
|
||||
|
|
@ -662,7 +662,7 @@ body {
|
|||
.offcanvas .sidebar .divider {
|
||||
height: 1px;
|
||||
overflow: hidden;
|
||||
background-color: #ebeff2;
|
||||
background-color: #EBEFF2;
|
||||
width: 100%;
|
||||
margin: 0px;
|
||||
}
|
||||
|
|
@ -676,7 +676,7 @@ body {
|
|||
.offcanvas .sidebar .dropdown-menu > li > a:focus,
|
||||
.offcanvas .sidebar .sidebar-menu > li > a:active,
|
||||
.offcanvas .sidebar .dropdown-menu > li > a:active {
|
||||
background-color: #f0f4f7;
|
||||
background-color: #F0F4F7;
|
||||
}
|
||||
@media (max-width: 767px) {
|
||||
.page-content {
|
||||
|
|
@ -748,7 +748,7 @@ body {
|
|||
}
|
||||
.offcanvas .sidebar-label {
|
||||
text-transform: uppercase;
|
||||
color: #8d99a6;
|
||||
color: #8D99A6;
|
||||
font-size: 85%;
|
||||
margin: 0px;
|
||||
font-weight: bold;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@
|
|||
<li class="h6 shared-with-label">{%= __("Shared With") %}</li>
|
||||
<li class="form-shared"></li>
|
||||
</ul>
|
||||
<ul class="list-unstyled sidebar-menu">
|
||||
<li class="divider"></li>
|
||||
<li class="h6 viewers-label">{%= __("Currently Viewing") %}</li>
|
||||
<li class="form-viewers"></li>
|
||||
</ul>
|
||||
<ul class="list-unstyled sidebar-menu text-muted">
|
||||
<li class="modified-by"></li>
|
||||
<li class="created-by"></li>
|
||||
|
|
|
|||
76
frappe/public/js/frappe/form/form_viewers.js
Normal file
76
frappe/public/js/frappe/form/form_viewers.js
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
frappe.provide("frappe.ui.form");
|
||||
|
||||
frappe.ui.form.Viewers = Class.extend({
|
||||
init: function(opts) {
|
||||
$.extend(this, opts);
|
||||
},
|
||||
refresh: function(data_updated) {
|
||||
var me = this;
|
||||
this.parent.empty();
|
||||
|
||||
var viewers = this.frm.get_docinfo().viewers || {};
|
||||
|
||||
var users = [];
|
||||
var new_users = [];
|
||||
for (var i=0, l=(viewers.current || []).length; i < l; i++) {
|
||||
var username = viewers.current[i];
|
||||
if (username===user) {
|
||||
// current user
|
||||
continue;
|
||||
}
|
||||
|
||||
var user_info = frappe.user_info(username);
|
||||
users.push({
|
||||
image: user_info.image,
|
||||
fullname: user_info.fullname,
|
||||
title: __("{0} is currently viewing this document", [user_info.fullname])
|
||||
});
|
||||
|
||||
if (viewers.new.indexOf(username)!==-1) {
|
||||
new_users.push(user_info.fullname);
|
||||
}
|
||||
}
|
||||
|
||||
if (users.length) {
|
||||
this.parent.parent().removeClass("hidden");
|
||||
this.parent.append(frappe.render_template("users_in_sidebar", {"users": users}));
|
||||
} else {
|
||||
this.parent.parent().addClass("hidden");
|
||||
}
|
||||
|
||||
if (data_updated && new_users.length) {
|
||||
// new user viewing this document, who wasn't viewing in the past
|
||||
if (new_users.length===1) {
|
||||
show_alert(__("{0} is currently viewing this document", [new_users[0]]));
|
||||
} else {
|
||||
show_alert(__("{0} are currently viewing this document", [frappe.utils.comma_and(new_users)]));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
frappe.ui.form.set_viewers = function(data) {
|
||||
var doctype = data.doctype;
|
||||
var docname = data.docname;
|
||||
var past_viewers = (frappe.model.get_docinfo(doctype, docname).viewers || {}).past || [];
|
||||
var new_viewers = [];
|
||||
var viewers = data.viewers || [];
|
||||
|
||||
for (i=0, l=viewers.length; i < l; i++) {
|
||||
var username = viewers[i];
|
||||
if (past_viewers.indexOf(username)===-1) {
|
||||
new_viewers.push(username);
|
||||
}
|
||||
}
|
||||
|
||||
frappe.model.set_docinfo(doctype, docname, "viewers", {
|
||||
past: past_viewers.concat(new_viewers),
|
||||
new: new_viewers,
|
||||
current: viewers
|
||||
});
|
||||
|
||||
if (cur_frm.doc && cur_frm.doc.doctype===doctype && cur_frm.doc.name==docname) {
|
||||
cur_frm.viewers.refresh(true);
|
||||
}
|
||||
}
|
||||
|
|
@ -8,44 +8,45 @@ frappe.ui.form.Share = Class.extend({
|
|||
$.extend(this, opts);
|
||||
},
|
||||
refresh: function() {
|
||||
this.render_sidebar();
|
||||
},
|
||||
render_sidebar: function() {
|
||||
var me = this;
|
||||
this.parent.empty();
|
||||
|
||||
var everyone = null;
|
||||
var shared = $.map(this.shared || this.frm.get_docinfo().shared, function(s) {
|
||||
var shared = this.shared || this.frm.get_docinfo().shared;
|
||||
var users = [];
|
||||
for (var i=0, l=shared.length; i < l; i++) {
|
||||
var s = shared[i];
|
||||
|
||||
if (s.everyone) {
|
||||
everyone = s;
|
||||
users.push({
|
||||
icon: "octicon octicon-megaphone text-muted",
|
||||
avatar_class: "avatar-empty share-doc-btn shared-with-everyone",
|
||||
title: __("Shared with everyone")
|
||||
});
|
||||
} else {
|
||||
var user_info = frappe.user_info(s.user);
|
||||
users.push({
|
||||
image: user_info.image,
|
||||
fullname: user_info.fullname,
|
||||
title: __("Shared with {0}", [user_info.fullname])
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return s ? s.user : null;
|
||||
if (!me.frm.doc.__islocal) {
|
||||
users.push({
|
||||
icon: "octicon octicon-plus text-muted",
|
||||
avatar_class: "avatar-empty share-doc-btn",
|
||||
title: __("Share")
|
||||
});
|
||||
}
|
||||
|
||||
this.parent.append(frappe.render_template("users_in_sidebar", {"users": users}));
|
||||
this.parent.find(".avatar").on("click", function() {
|
||||
me.frm.share_doc();
|
||||
});
|
||||
|
||||
if (everyone) {
|
||||
$(repl('<span><a class="avatar avatar-small avatar-empty share-doc-btn shared-with-everyone" title="%(title)s">\
|
||||
<i class="octicon octicon-megaphone text-muted"></i></a></span>', {title: __("Shared with everyone")}))
|
||||
.appendTo(this.parent)
|
||||
.on("click", function() { me.frm.share_doc(); });
|
||||
}
|
||||
|
||||
for(var i=0; i<shared.length; i++) {
|
||||
var user_info = frappe.user_info(shared[i]);
|
||||
$(repl('<span class="avatar avatar-small" title="'
|
||||
+__("Shared with {0}", [user_info.fullname])+'">\
|
||||
<img class="media-object" src="%(image)s" alt="%(fullname)s"></span>',
|
||||
{image: user_info.image, fullname: user_info.fullname}))
|
||||
.appendTo(this.parent)
|
||||
.on("click", function() { me.frm.share_doc(); });
|
||||
}
|
||||
|
||||
// share
|
||||
if(!me.frm.doc.__islocal) {
|
||||
$(repl('<span><a class="avatar avatar-small avatar-empty share-doc-btn" title="%(title)s">\
|
||||
<i class="octicon octicon-plus text-muted"></i></a></span>', {title: __("Share")}))
|
||||
.appendTo(this.parent)
|
||||
.on("click", function() { me.frm.share_doc(); });
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
show: function() {
|
||||
var me = this;
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ frappe.ui.form.Sidebar = Class.extend({
|
|||
this.make_assignments();
|
||||
this.make_attachments();
|
||||
this.make_shared();
|
||||
this.make_viewers();
|
||||
this.make_tags();
|
||||
|
||||
this.bind_events();
|
||||
|
|
@ -46,6 +47,7 @@ frappe.ui.form.Sidebar = Class.extend({
|
|||
this.frm.assign_to.refresh();
|
||||
this.frm.attachments.refresh();
|
||||
this.frm.shared.refresh();
|
||||
this.frm.viewers.refresh();
|
||||
this.frm.tags && this.frm.tags.refresh(this.frm.doc._user_tags);
|
||||
this.sidebar.find(".modified-by").html(__("{0} edited this {1}",
|
||||
["<strong>" + frappe.user.full_name(this.frm.doc.modified_by) + "</strong>",
|
||||
|
|
@ -97,6 +99,12 @@ frappe.ui.form.Sidebar = Class.extend({
|
|||
parent: this.sidebar.find(".form-shared")
|
||||
});
|
||||
},
|
||||
make_viewers: function() {
|
||||
this.frm.viewers = new frappe.ui.form.Viewers({
|
||||
frm: this.frm,
|
||||
parent: this.sidebar.find(".form-viewers")
|
||||
});
|
||||
},
|
||||
add_user_action: function(label, click) {
|
||||
return $('<a>').html(label).appendTo($('<li class="user-action-row">')
|
||||
.appendTo(this.user_actions.removeClass("hide"))).on("click", click);
|
||||
|
|
|
|||
11
frappe/public/js/frappe/form/users_in_sidebar.html
Normal file
11
frappe/public/js/frappe/form/users_in_sidebar.html
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{% for (var i=0, l=users.length; i < l; i++) {
|
||||
var u = users[i];
|
||||
%}
|
||||
<span class="avatar avatar-small {{ u.avatar_class || "" }}" title="{{ u.title }}">
|
||||
{% if (u.icon) { %}
|
||||
<i class="{{ u.icon }}"></i>
|
||||
{% } else { %}
|
||||
<img class="media-object" src="{{ u.image }}" alt="{{ u.fullname }}">
|
||||
{% } %}
|
||||
</span>
|
||||
{% } %}
|
||||
|
|
@ -153,6 +153,12 @@ $.extend(frappe.model, {
|
|||
return frappe.model.docinfo[doctype] && frappe.model.docinfo[doctype][name] || null;
|
||||
},
|
||||
|
||||
set_docinfo: function(doctype, name, key, value) {
|
||||
if (frappe.model.docinfo[doctype] && frappe.model.docinfo[doctype][name]) {
|
||||
frappe.model.docinfo[doctype][name][key] = value;
|
||||
}
|
||||
},
|
||||
|
||||
new_comment: function(comment) {
|
||||
var reference_doctype = comment.comment_doctype || comment.reference_doctype;
|
||||
var reference_name = comment.comment_docname || comment.reference_name;
|
||||
|
|
|
|||
|
|
@ -42,9 +42,21 @@ frappe.socket = {
|
|||
frappe.socket.doc_subscribe(frm.doctype, frm.docname);
|
||||
});
|
||||
|
||||
// $(document).on('form-unload', function(e, frm) {
|
||||
// frappe.socket.doc_unsubscribe(frm.doctype, frm.docname);
|
||||
// });
|
||||
$(document).on("form_refresh", function(e, frm) {
|
||||
frappe.socket.doc_open(frm.doctype, frm.docname);
|
||||
});
|
||||
|
||||
$(document).on('form-unload', function(e, frm) {
|
||||
// frappe.socket.doc_unsubscribe(frm.doctype, frm.docname);
|
||||
frappe.socket.doc_close(frm.doctype, frm.docname);
|
||||
});
|
||||
|
||||
window.onbeforeunload = function() {
|
||||
// if tab/window is closed, notify other users
|
||||
if (cur_frm && cur_frm.doc) {
|
||||
frappe.socket.doc_close(cur_frm.doctype, cur_frm.docname);
|
||||
}
|
||||
}
|
||||
},
|
||||
get_host: function() {
|
||||
var host = frappe.urllib.get_base_url();
|
||||
|
|
@ -77,6 +89,14 @@ frappe.socket = {
|
|||
}
|
||||
})
|
||||
},
|
||||
doc_open: function(doctype, docname) {
|
||||
// notify that the user has opened this doc
|
||||
frappe.socket.socket.emit('doc_open', doctype, docname);
|
||||
},
|
||||
doc_close: function(doctype, docname) {
|
||||
// notify that the user has closed this doc
|
||||
frappe.socket.socket.emit('doc_close', doctype, docname);
|
||||
},
|
||||
setup_listeners: function() {
|
||||
frappe.socket.socket.on('task_status_change', function(data) {
|
||||
frappe.socket.process_response(data, data.status.toLowerCase());
|
||||
|
|
@ -88,16 +108,25 @@ frappe.socket = {
|
|||
setup_reconnect: function() {
|
||||
// subscribe again to open_tasks
|
||||
frappe.socket.socket.on("connect", function() {
|
||||
$.each(frappe.socket.open_tasks, function(task_id, opts) {
|
||||
frappe.socket.subscribe(task_id, opts);
|
||||
});
|
||||
// wait for 5 seconds before subscribing again
|
||||
// because it takes more time to start python server than nodejs server
|
||||
// and we use validation requests to python server for subscribing
|
||||
setTimeout(function() {
|
||||
$.each(frappe.socket.open_tasks, function(task_id, opts) {
|
||||
frappe.socket.subscribe(task_id, opts);
|
||||
});
|
||||
|
||||
// re-connect open docs
|
||||
$.each(frappe.socket.open_docs, function(d) {
|
||||
if(locals[d.doctype] && locals[d.doctype][d.name]) {
|
||||
frappe.socket.doc_subscribe(d.doctype, d.name);
|
||||
// re-connect open docs
|
||||
$.each(frappe.socket.open_docs, function(d) {
|
||||
if(locals[d.doctype] && locals[d.doctype][d.name]) {
|
||||
frappe.socket.doc_subscribe(d.doctype, d.name);
|
||||
}
|
||||
});
|
||||
|
||||
if (cur_frm && cur_frm.doc) {
|
||||
frappe.socket.doc_open(cur_frm.doc.doctype, cur_frm.doc.name);
|
||||
}
|
||||
})
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
},
|
||||
|
|
@ -136,3 +165,9 @@ frappe.realtime.on = function(event, callback) {
|
|||
frappe.socket.socket.on(event, callback);
|
||||
}
|
||||
}
|
||||
|
||||
frappe.realtime.publish = function(event, message) {
|
||||
if(frappe.socket.socket) {
|
||||
frappe.socket.socket.emit(event, message);
|
||||
}
|
||||
}
|
||||
|
|
@ -29,6 +29,9 @@ frappe.views.FormFactory = frappe.views.Factory.extend({
|
|||
frappe.model.new_comment(data);
|
||||
});
|
||||
|
||||
frappe.realtime.on("doc_viewers", function(data) {
|
||||
frappe.ui.form.set_viewers(data);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -445,7 +445,7 @@ _f.Frm.prototype.render_form = function(is_a_different_doc) {
|
|||
|
||||
// trigger global trigger
|
||||
// to use this
|
||||
$(document).trigger('form_refresh');
|
||||
$(document).trigger('form_refresh', [this]);
|
||||
|
||||
// fields
|
||||
this.refresh_fields();
|
||||
|
|
|
|||
|
|
@ -115,7 +115,7 @@ body[data-route^="Module"] .main-menu {
|
|||
margin-top: -5px;
|
||||
}
|
||||
|
||||
.form-shared {
|
||||
.form-shared, .form-viewers {
|
||||
.share-doc-btn {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
@ -161,14 +161,17 @@ body[data-route^="Module"] .main-menu {
|
|||
.modified-by,
|
||||
.created-by,
|
||||
.tags-label,
|
||||
.shared-with-label {
|
||||
.shared-with-label,
|
||||
.form-viewers,
|
||||
.viewers-label {
|
||||
.sidebar-padding;
|
||||
}
|
||||
|
||||
.assigned-to-label,
|
||||
.attachments-label,
|
||||
.tags-label,
|
||||
.shared-with-label {
|
||||
.shared-with-label,
|
||||
.viewers-label {
|
||||
.sidebar-padding;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
|
@ -176,7 +179,8 @@ body[data-route^="Module"] .main-menu {
|
|||
.assigned-to-label,
|
||||
.tags-label,
|
||||
.attachments-label.has-attachments,
|
||||
.shared-with-label {
|
||||
.shared-with-label,
|
||||
.viewers-label {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
|
|
|
|||
121
socketio.js
121
socketio.js
|
|
@ -6,7 +6,6 @@ var fs = require('fs');
|
|||
|
||||
var redis = require("redis")
|
||||
var subscriber = redis.createClient(12311);
|
||||
var r = redis.createClient(12311);
|
||||
|
||||
var request = require('superagent')
|
||||
var default_site;
|
||||
|
|
@ -31,6 +30,9 @@ io.on('connection', function(socket){
|
|||
if(!sid) {
|
||||
return;
|
||||
}
|
||||
|
||||
socket.user = cookie.parse(socket.request.headers.cookie).user_id;
|
||||
|
||||
// console.log("firing get_user_info");
|
||||
request.get(get_url(socket, '/api/method/frappe.async.get_user_info'))
|
||||
.type('form')
|
||||
|
|
@ -63,25 +65,17 @@ io.on('connection', function(socket){
|
|||
|
||||
socket.on('doc_subscribe', function(doctype, docname) {
|
||||
// console.log('trying to subscribe', doctype, docname)
|
||||
request.get(get_url(socket, '/api/method/frappe.async.can_subscribe_doc'))
|
||||
.type('form')
|
||||
.send({
|
||||
sid: sid,
|
||||
doctype: doctype,
|
||||
docname: docname
|
||||
})
|
||||
.end(function(err, res) {
|
||||
if(err) console.log(err);
|
||||
if(!res) {
|
||||
console.log("No response for doc_subscribe");
|
||||
return;
|
||||
}
|
||||
if(res.status == 200) {
|
||||
var room = get_doc_room(socket, doctype, docname);
|
||||
// console.log('joining', room)
|
||||
socket.join(room);
|
||||
}
|
||||
})
|
||||
can_subscribe_doc({
|
||||
socket: socket,
|
||||
sid: sid,
|
||||
doctype: doctype,
|
||||
docname: docname,
|
||||
callback: function(err, res) {
|
||||
var room = get_doc_room(socket, doctype, docname);
|
||||
// console.log('joining', room)
|
||||
socket.join(room);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('doc_unsubscribe', function(doctype, docname) {
|
||||
|
|
@ -89,13 +83,45 @@ io.on('connection', function(socket){
|
|||
socket.leave(room);
|
||||
});
|
||||
|
||||
socket.on('doc_open', function(doctype, docname) {
|
||||
// show who is currently viewing the form
|
||||
can_subscribe_doc({
|
||||
socket: socket,
|
||||
sid: sid,
|
||||
doctype: doctype,
|
||||
docname: docname,
|
||||
callback: function(err, res) {
|
||||
var room = get_open_doc_room(socket, doctype, docname);
|
||||
// console.log('joining', room)
|
||||
socket.join(room);
|
||||
|
||||
send_viewers({
|
||||
socket: socket,
|
||||
doctype: doctype,
|
||||
docname: docname,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('doc_close', function(doctype, docname) {
|
||||
// remove this user from the list of 'who is currently viewing the form'
|
||||
var room = get_open_doc_room(socket, doctype, docname);
|
||||
socket.leave(room);
|
||||
send_viewers({
|
||||
socket: socket,
|
||||
doctype: doctype,
|
||||
docname: docname,
|
||||
});
|
||||
});
|
||||
|
||||
// socket.on('disconnect', function (arguments) {
|
||||
// console.log("user disconnected", arguments);
|
||||
// });
|
||||
});
|
||||
|
||||
function send_existing_lines(task_id, socket) {
|
||||
r.hgetall('task_log:' + task_id, function(err, lines) {
|
||||
subscriber.hgetall('task_log:' + task_id, function(err, lines) {
|
||||
socket.emit('task_progress', {
|
||||
"task_id": task_id,
|
||||
"message": {
|
||||
|
|
@ -122,6 +148,10 @@ function get_doc_room(socket, doctype, docname) {
|
|||
return get_site_name(socket) + ':doc:'+ doctype + '/' + docname;
|
||||
}
|
||||
|
||||
function get_open_doc_room(socket, doctype, docname) {
|
||||
return get_site_name(socket) + ':open_doc:'+ doctype + '/' + docname;
|
||||
}
|
||||
|
||||
function get_user_room(socket, user) {
|
||||
return get_site_name(socket) + ':user:' + user;
|
||||
}
|
||||
|
|
@ -159,3 +189,52 @@ function get_url(socket, path) {
|
|||
}
|
||||
return socket.request.headers.origin + path;
|
||||
}
|
||||
|
||||
function can_subscribe_doc(args) {
|
||||
request.get(get_url(args.socket, '/api/method/frappe.async.can_subscribe_doc'))
|
||||
.type('form')
|
||||
.send({
|
||||
sid: args.sid,
|
||||
doctype: args.doctype,
|
||||
docname: args.docname
|
||||
})
|
||||
.end(function(err, res) {
|
||||
if(err) console.log(err);
|
||||
if(!res) {
|
||||
console.log("No response for doc_subscribe");
|
||||
return;
|
||||
}
|
||||
if(res.status == 200) {
|
||||
args.callback(err, res);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function send_viewers(args) {
|
||||
// send to doc room, 'users currently viewing this document'
|
||||
if (!(args && args.doctype && args.docname)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// open doc room
|
||||
var room = get_open_doc_room(args.socket, args.doctype, args.docname);
|
||||
|
||||
// socket ids connected to this room
|
||||
var clients = Object.keys(io.sockets.adapter.rooms[room] || {});
|
||||
|
||||
var viewers = [];
|
||||
for (var i in io.sockets.sockets) {
|
||||
var s = io.sockets.sockets[i];
|
||||
if (clients.indexOf(s.id)!==-1) {
|
||||
// this socket is connected to the room
|
||||
viewers.push(s.user);
|
||||
}
|
||||
}
|
||||
|
||||
// notify
|
||||
io.to(room).emit("doc_viewers", {
|
||||
doctype: args.doctype,
|
||||
docname: args.docname,
|
||||
viewers: viewers
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue