Merge pull request #4790 from achillesrasquinha/fixes-chat

[frappe-chat] Scroll Fixes
This commit is contained in:
Achilles Rasquinha 2018-01-08 23:57:02 +05:30 committed by GitHub
commit 853569d2d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 219 additions and 481 deletions

36
.github/CONTRIBUTING.md vendored Normal file
View file

@ -0,0 +1,36 @@
### Introduction (first timers)
Thank you for your interest in raising an Issue with ERPNext. An Issue could mean a bug report or a request for a missing feature. By raising a bug report, you are contributing to the development of ERPNext and this is the first step of participating in the community. Bug reports are very helpful for developers as they quickly fix the issue before other users start facing it.
Feature requests are also a great way to take the product forward. New ideas can come in any user scenario and the issue list also acts a roadmap of future features.
When you are raising an Issue, you should keep a few things in mind. Remember that the developer does not have access to your machine so you must give all the information you can while raising an Issue. If you are suggesting a feature, you should be very clear about what you want.
The Issue list is not the right place to ask a question or start a general discussion. If you want to do that , then the right place is the forum [https://discuss.erpnext.com](https://discuss.erpnext.com).
### Reply and Closing Policy
If your issue is not clear or does not meet the guidelines, then it will be closed. If it is closed, please supply the information asked and re-open it.
### General Issue Guidelines
1. **Search existing Issues:** Before raising a Issue, search if it has been raised before. Maybe add a 👍 or give additional help by creating a mockup if it is not already created.
1. **Report each issue separately:** Don't club multiple, unreleated issues in one note.
1. **Brief:** Please don't include long explanations. Use screenshots and bullet points instead of descriptive paragraphs.
### Bug Report Guidelines
1. **Steps to Reproduce:** The bug report must have a list of steps needed to reproduce a bug. If we cannot reproduce it, then we cannot solve it.
1. **Version Number:** Please add the version number in your report. Often a bug is fixed in the latest version
1. **Clear Title:** Add a clear subject to your bug report like "Unable to submit Purchase Order without Basic Rate" instead of just "Cannot Submit"
1. **Screenshots:** Screenshots are a great way of communicating the issues. Try adding annotations or using LiceCAP to take a screencast in `gif`.
### Feature Request Guidelines
1. **Clarity:** Clearly specify how do you want the feature to behave. Don't just say "I would like multiple PDF formats", say that "Ability to add multiple print formats for customers with different languages".
1. **Solution:** Try and identify how the feature should look like.
1. **Mockups:** Mockups are a great way to explain your requirement.
### What if my Issue is closed
Don't worry, take the feedback, supply the correct information and re-open it!

9
.github/ISSUE_TEMPLATE.md vendored Normal file
View file

@ -0,0 +1,9 @@
#### Expected Behaviour
#### Actual Behaviour
#### Steps to reproduce:
1.
Frappé version:

View file

@ -1,19 +1,3 @@
.frappe-chat-toggle {
height: 40px;
text-align: center;
}
.frappe-chat-toggle .octicon {
margin-top: 5px;
}
.frappe-chat .frappe-chat-popper > .frappe-chat-popper-collapse > .panel {
box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.25);
}
.frappe-chat .panel.panel-span {
border-radius: 0px;
}
.frappe-chat .panel.panel-span .panel-heading {
border-radius: 0px;
}
.font-bold {
font-weight: 700;
}
@ -26,32 +10,58 @@
.avatar {
padding: 1px;
}
.frappe-fab {
width: 48px;
height: 48px;
border-radius: 50%;
box-shadow: 0px 3px 6px 0px rgba(0, 0, 0, 0.25);
}
.frappe-fab:hover {
box-shadow: 0px 5px 9px 0px rgba(0, 0, 0, 0.25);
}
.frappe-fab.frappe-fab-sm {
width: 40px;
.navbar .frappe-chat-toggle {
height: 40px;
text-align: center;
}
.frappe-fab.frappe-fab-lg {
width: 56px;
height: 56px;
.navbar .octicon {
margin-top: 5px;
}
.frappe-chat > .frappe-chat-popper {
position: fixed;
bottom: 0px;
right: 0px;
margin: 20px;
z-index: 1035;
}
.frappe-chat > .frappe-chat-popper > .frappe-chat-popper-collapse > .panel {
width: 350px;
height: 500px;
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
}
.frappe-chat > .frappe-chat-popper > .frappe-chat-popper-collapse > .panel .panel-body .frappe-chat-room-list {
height: 400px;
overflow-y: auto;
}
.frappe-chat > .frappe-chat-popper > .frappe-chat-popper-collapse > .panel .chat-list.list-group {
height: 390px;
overflow-y: scroll;
}
.frappe-chat > .frappe-chat-popper > .frappe-chat-popper-collapse > .panel .frappe-chat-room-footer {
position: absolute;
left: 0px;
right: 0px;
bottom: 0px;
}
.frappe-chat > .frappe-chat-popper > .frappe-chat-popper-collapse > .panel.panel-span {
position: fixed;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
overflow: auto;
border-radius: 0px;
}
.frappe-chat > .frappe-chat-popper > .frappe-chat-popper-collapse > .panel.panel-span .panel-heading {
border-radius: 0px;
}
.frappe-chat .panel {
margin-bottom: 0px !important;
}
.frappe-chat .panel .panel-body {
padding: 10px;
}
.frappe-chat .panel .frappe-chat-room-footer {
position: absolute;
bottom: 0px;
.frappe-chat .frappe-chat-form {
margin: 1px;
}
.frappe-chat .frappe-chat-form .form-control {
font-size: 12px;
@ -62,69 +72,12 @@
.frappe-chat .frappe-chat-form .btn {
border-radius: 0px !important;
}
.frappe-chat .frappe-chat-form .list-group {
.frappe-chat .frappe-chat-form .hint-list.list-group {
margin-bottom: 0px !important;
max-height: 150px;
overflow-y: auto;
}
.frappe-chat .frappe-chat-form .list-group .list-group-item:first-child,
.frappe-chat .frappe-chat-form .list-group .list-group-item:last-child {
.frappe-chat .frappe-chat-form .hint-list.list-group .hint-list.list-group-item:first-child,
.frappe-chat .frappe-chat-form .hint-list.list-group .hint-list.list-group-item:last-child {
border-radius: 0px !important;
}
.frappe-chat-popper {
position: fixed;
bottom: 0px;
right: 0px;
margin: 20px;
z-index: 1035;
}
.frappe-chat-popper .frappe-chat-popper-collapse {
position: fixed;
bottom: 0px;
right: 0px;
margin: 20px;
}
.frappe-chat-popper .frappe-chat-popper-collapse > .panel {
position: relative;
width: 350px;
height: 500px;
overflow-y: auto;
}
.frappe-chat-popper .frappe-chat-popper-collapse > .panel .panel-body {
width: 350px;
height: 500px;
overflow-y: auto;
}
.frappe-chat-popper .frappe-chat-popper-collapse > .panel > .panel-heading .action {
padding: 5px;
}
.frappe-chat-popper .frappe-chat-popper-collapse > .panel.panel-primary a {
color: #FFF;
}
.frappe-chat-popper .frappe-chat-popper-collapse > .panel.panel-primary .text-muted {
color: #FFF !important;
}
.frappe-chat-popper .frappe-chat-popper-collapse .panel-span {
position: fixed;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
z-index: 1037;
overflow: auto;
border-radius: none;
}
.frappe-chat-emoji .dropdown-menu {
min-width: 250px;
background: none !important;
border: none !important;
}
.frappe-chat-emoji .panel {
margin-bottom: 0 !important;
height: 300px;
}
.frappe-chat-emoji .panel .form-group {
margin-bottom: 0 !important;
}

View file

@ -1638,7 +1638,14 @@ class extends Component
const rooms = state.query ? frappe.chat.room.search(state.query, state.rooms) : frappe.chat.room.sort(state.rooms)
const RoomList = h(frappe.Chat.Widget.RoomList, { rooms: rooms, click: this.room.select })
const RoomList = frappe._.is_empty(rooms) && !state.query ?
h("div", { style: "margin-top: 165px" },
h("div", { class: "text-center text-extra-muted" },
h("p","",__("You don't have any messages yet."))
)
)
:
h(frappe.Chat.Widget.RoomList, { rooms: rooms, click: this.room.select })
const Room = h(frappe.Chat.Widget.Room, { ...state.room, layout: props.layout, destroy: () => {
this.set_state({
room: { name: null, messages: [ ] }
@ -1660,10 +1667,10 @@ class extends Component
h("div", { class: "col-md-10 col-sm-9 layout-main-section-wrapper" },
state.room.name ?
Room : (
h("div", { style: "margin-top: 240px" },
h("div", "",
h("div", { class: "text-center text-extra-muted" },
h(frappe.components.Octicon, { type: "comment-discussion", style: "font-size: 48px" }),
h("p", null, __("Select a chat to start messaging."))
h("p","",__("Select a chat to start messaging."))
)
)
)
@ -1816,7 +1823,7 @@ class extends Component
const popper = props.layout === frappe.Chat.Layout.POPPER
return (
h("form", { oninput: this.change, onsubmit: this.submit, style: popper ? { "padding-left": "15px", "padding-right": "15px" } : null },
h("form", { oninput: this.change, onsubmit: this.submit },
h("div", { class: "form-group" },
h("div", { class: "input-group input-group-sm" },
props.span || props.layout !== frappe.Chat.Layout.PAGE ?
@ -1888,7 +1895,7 @@ class extends Component
const rooms = props.rooms
return rooms.length ? (
h("ul", { class: "nav nav-pills nav-stacked" },
h("ul", { class: "frappe-chat-room-list nav nav-pills nav-stacked" },
rooms.map(room => h(frappe.Chat.Widget.RoomList.Item, { ...room, click: props.click }))
)
) : null
@ -1981,8 +1988,8 @@ class extends Component
position.class === "media-left" ? avatar : null,
h("div", { class: "media-body" },
h("div", { class: "media-heading h6 ellipsis", style: `max-width: ${props.width_title || "100%"} display: inline-block` }, props.title),
props.content ? h("div", null, h("small", '', props.content)) : null,
props.subtitle ? h("div", null, h("small", { class: "text-muted" }, props.subtitle)) : null
props.content ? h("div","",h("small","",props.content)) : null,
props.subtitle ? h("div","",h("small", { class: "h6 text-muted" }, props.subtitle)) : null
),
position.class === "media-right" ? avatar : null
)
@ -2106,10 +2113,10 @@ class extends Component
})
:
h("div", { class: "panel-body" },
h("div", { style: "margin-top: 145px" },
h("div", { style: "margin-top: 135px" },
h("div", { class: "text-center text-extra-muted" },
h(frappe.components.Octicon, { type: "comment-discussion", style: "font-size: 48px" }),
h("p", null, __("Start a conversation."))
h("p","",__("Start a conversation."))
)
)
),
@ -2172,7 +2179,7 @@ class extends Component
h("div", { class: "panel-heading" },
h("div", { class: "row" },
popper ?
h("div", { class: "col-xs-1" },
h("div", { class: "col-xs-1 vcenter" },
h("a", { onclick: props.back }, h(frappe.components.Octicon, { type: "chevron-left" }))
) : null,
h("div", { class: popper ? "col-xs-10" : "col-xs-9" },
@ -2282,11 +2289,11 @@ class extends Component {
return (
h("div", { class: "frappe-chat-form" },
state.hints.length ?
h("li", { class: "list-group" },
h("li", { class: "hint-list list-group" },
state.hints.map((item) =>
{
return (
h("a", { class: "list-group-item", href: "javascript:void(0)", onclick: () =>
h("a", { class: "hint-list-item list-group-item", href: "javascript:void(0)", onclick: () =>
{
this.set_state({ content: item.content, hints: [ ] })
}},
@ -2376,102 +2383,14 @@ class extends Component
return (
h("div", { class: "list-group" },
frappe.ui.Emoji.map((category) =>
{
return (
h("div", { class: "list-group-item" },
h("div", { class: "h6" }, frappe._.capitalize(category.name)),
h("div", null,
)
)
)
})
)
)
}
}
// return (
// h("a", { class: "list-group-item", href: "#", onclick: () => {
// this.set_state({
// content: `${this.state.content}${item.value}`
// })
// }},
// props.hint.component(item)
// )
// )
frappe.Chat.Widget.Account
=
class extends Component {
render ( ) {
const { props } = this
const statuses = frappe.chat.profile.STATUSES.map(s => {
return {
value: s.name,
label: s.name,
color: s.color
}
})
return (
h(frappe.components.Select, { value: props.status, options: statuses, click: (value) => {
if ( props.status != value )
props.on_change_status(value)
}})
)
}
}
/**
* @description Chat List HOC
*
*
*/
frappe.Chat.Widget.ChatList
=
@ -2480,7 +2399,7 @@ class extends Component {
const { props } = this
return !frappe._.is_empty(props.messages) ? (
h("ul", { class: "list-group" },
h("ul", { class: "chat-list list-group" },
props.messages.map(m => h(frappe.Chat.Widget.ChatList.Item, {
...m
}))
@ -2524,66 +2443,4 @@ class extends Component {
frappe.Chat.Widget.ChatList.Bubble.defaultState =
{
creation: ""
}
// frappe.components.Select
// options - (Required) array of options of the format
// {
// label: "foo",
// value: "bar"
// }
// value - (Required) default value.
// click - (Optional) click handler on click event.
frappe.components.Select
=
class extends Component {
render ( ) {
const { props } = this
const selected = props.options.find(o => o.value === props.value)
return (
h("div", { class: "dropdown" },
h("button", { class: "btn btn-sm btn-default btn-block dropdown-toggle", "data-toggle": "dropdown" },
selected.color ?
h(frappe.components.Indicator, { color: selected.color }) : null,
selected.label ?
selected.label : selected.value,
),
h("ul", { class: "dropdown-menu" },
props.options.map(o => h(frappe.components.Select.Option, { ...o, click: props.click }))
)
)
)
}
}
frappe.components.Select.Option
=
class extends Component {
render ( ) {
const { props } = this
return (
h("li", null,
h("a", { onclick: () => props.click(props.value) },
props.color ?
h(frappe.components.Indicator, { color: props.color }) : null,
props.label ?
props.label : props.value
)
)
)
}
}
// frappe.components.Select.Option props
// same as frappe.components.Select.
}

View file

@ -1,153 +1,128 @@
// Author - Achilles Rasquinha <achilles@frappe.io>
// For most part, we haven't used the LESS framework and its language features.
// We could have written everything in CSS than introducing a compiler.
// A good start to learn the same - http://lesscss.org
// - Achilles Rasquinha <achilles@frappe.io>
// http://codeguide.co - @mdo (Author of Bootstrap)
// Typography
@font-weight-bold: 700;
@font-weight-heavy: 900;
@frappe-chat-toggle-height: 40px;
@frappe-chat-popper-panel-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); // BS modal's box shadow.
.frappe-chat-toggle
@frappe-chat-popper-margin: 20px;
@frappe-chat-popper-panel-width: 350px;
@frappe-chat-popper-panel-height: 500px;
// z-index greater than FAB, lesser than modal.
@frappe-chat-popper-z-index: 1035;
// BS modal's box-shadow
@frappe-chat-popper-panel-box-shadow: 0 5px 15px rgba(0, 0, 0, .5);
// https://github.com/twbs/bootstrap/blob/v3.3.7/less/variables.less#L278
// Keep z-index of the ChatPopper higher than others, lower than modal background.
@frappe-chat-form-font-size: 12px;
@frappe-chat-form-menu-border-radius: 4px;
@frappe-chat-form-list-group-height: 150px; // Hints
// Typography
.font-bold { font-weight: @font-weight-bold; }
.font-heavy { font-weight: @font-weight-heavy; }
// utilities
.cursor-pointer { cursor: pointer; }
// Hacks and Fixes
// suggested by rushabh@frappe.io
.avatar { padding: 1px; }
.navbar
{
height: @frappe-chat-toggle-height;
text-align: center;
.octicon
.frappe-chat-toggle
{
// Hack, somewhat.
margin-top: 5px;
height: @frappe-chat-toggle-height;
text-align: center;
}
.octicon { margin-top: 5px; } // Hack, somewhat.
}
.frappe-chat
{
.frappe-chat-popper
& > .frappe-chat-popper
{
position: fixed;
bottom: 0px;
right: 0px;
margin: @frappe-chat-popper-margin;
z-index: @frappe-chat-popper-z-index;
& > .frappe-chat-popper-collapse
{
& > .panel
{
width: @frappe-chat-popper-panel-width;
height: @frappe-chat-popper-panel-height;
box-shadow: @frappe-chat-popper-panel-box-shadow;
.panel-body
{
.frappe-chat-room-list
{
height: 400px; // Hack, sorry. :(
overflow-y: auto;
}
}
.chat-list.list-group
{
height: 390px;
overflow-y: scroll;
}
.frappe-chat-room-footer
{
position: absolute;
left: 0px;
right: 0px;
bottom: 0px;
}
}
& > .panel.panel-span
{
position: fixed;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
overflow: auto;
border-radius: 0px;
.panel-heading
{
border-radius: 0px;
}
}
}
}
.panel.panel-span
{
border-radius: 0px;
.panel-heading
{
border-radius: 0px;
}
}
}
// variables
@color-white: #FFF; //
@font-weight-bold: 700; //
@font-weight-heavy: 900; //
@frappe-chat-popper-panel-width: 350px; //
@frappe-chat-popper-panel-height: 500px; //
@frappe-chat-form-font-size: 12px;
@frappe-fab-width: 48px;
@frappe-fab-height: 48px;
@frappe-fab-lg: 56px;
@frappe-fab-sm: 40px;
// https://github.com/twbs/bootstrap/blob/v3.3.7/less/variables.less#L278
// Keep z-index of the FAB button higher than others, lower than modal background.
@frappe-fab-box-shadow: 0px 3px 6px 0px rgba(0,0,0,.25);
@frappe-fab-box-shadow-hover: 0px 5px 9px 0px rgba(0,0,0,.25);
@frappe-chat-panel-heading-box-shadow: 0px 2px 2px 0px rgba(0,0,0,.14); //
@frappe-chat-panel-body-padding: 10px;
@frappe-chat-panel-heading-action-padding: 5px;
@frappe-chat-popper-z-index: 1035;
@frappe-chat-popper-margin: 20px;
@frappe-chat-popper-panel-box-shadow: @frappe-fab-box-shadow;
// z-index greater than FAB, lesser than modal.
@frappe-chat-popper-panel-span-z-index: 1037;
@frappe-chat-form-list-group-height: 150px;
@frappe-chat-form-menu-border-radius: 4px;
@frappe-chat-emoji-width: 250px;
@frappe-chat-emoji-height: 300px;
.font-bold
{
font-weight: @font-weight-bold;
}
.font-heavy
{
font-weight: @font-weight-heavy;
}
.cursor-pointer
{
cursor: pointer;
}
.avatar
{
padding: 1px;
}
.frappe-fab
{
width: @frappe-fab-width;
height: @frappe-fab-height;
border-radius: 50%;
box-shadow: @frappe-fab-box-shadow;
&:hover
{
box-shadow: @frappe-fab-box-shadow-hover;
};
&.frappe-fab-sm
{
width: @frappe-fab-sm;
height: @frappe-fab-sm;
};
&.frappe-fab-lg
{
width: @frappe-fab-lg;
height: @frappe-fab-lg;
};
};
.frappe-chat
{
.panel
{
margin-bottom: 0px !important;
// .panel-heading
// {
// box-shadow: @frappe-chat-panel-heading-box-shadow;
// }
.panel-body
{
padding: @frappe-chat-panel-body-padding;
}
.frappe-chat-room-footer
{
position: absolute;
bottom: 0px;
}
}
.frappe-chat-form
{
margin: 1px; // Hack.
.form-control
{
font-size: @frappe-chat-form-font-size;
@ -163,109 +138,17 @@
border-radius: 0px !important;
}
.list-group
// Hints
.hint-list.list-group
{
margin-bottom: 0px !important;
max-height: @frappe-chat-form-list-group-height;
overflow-y: auto;
.list-group-item:first-child, .list-group-item:last-child
.hint-list.list-group-item:first-child, .hint-list.list-group-item:last-child
{
border-radius: 0px !important;
}
}
}
}
.frappe-chat-popper
{
position: fixed;
bottom: 0px;
right: 0px;
margin: @frappe-chat-popper-margin;
z-index: @frappe-chat-popper-z-index;
.frappe-chat-popper-collapse
{
position: fixed;
bottom: 0px;
right: 0px;
margin: @frappe-chat-popper-margin;
// margin-bottom: calc(@frappe-chat-popper-margin + 50px);
& > .panel
{
position: relative;
// box-shadow: @frappe-chat-popper-panel-box-shadow;
width: @frappe-chat-popper-panel-width;
height: @frappe-chat-popper-panel-height;
overflow-y: auto;
.panel-body
{
width: @frappe-chat-popper-panel-width;
height: @frappe-chat-popper-panel-height;
overflow-y: auto;
}
& > .panel-heading
{
// box-shadow: @frappe-chat-panel-heading-box-shadow;
.action
{
padding: @frappe-chat-panel-heading-action-padding;
}
}
&.panel-primary
{
a
{
color: @color-white;
}
.text-muted
{
color: @color-white !important;
}
}
};
.panel-span
{
position: fixed;
width: 100%;
height: 100%;
top: 0px;
left: 0px;
bottom: 0px;
right: 0px;
z-index: @frappe-chat-popper-panel-span-z-index;
overflow: auto;
border-radius: none;
};
};
};
.frappe-chat-emoji
{
.dropdown-menu
{
min-width: @frappe-chat-emoji-width;
background: none !important;
border: none !important;
}
.panel
{
margin-bottom: 0 !important;
height: @frappe-chat-emoji-height;
.form-group
{
margin-bottom: 0 !important;
}
}
};
}