diff --git a/frappe/public/js/frappe/list/list_view.js b/frappe/public/js/frappe/list/list_view.js index 55abb4d65b..396cd983fb 100644 --- a/frappe/public/js/frappe/list/list_view.js +++ b/frappe/public/js/frappe/list/list_view.js @@ -957,6 +957,15 @@ frappe.views.ListView = class ListView extends frappe.views.BaseList { )}'>`; } + get_image_url(doc) { + let url = doc.image ? doc.image : doc[this.meta.image_field]; + // absolute url for mobile + if (window.cordova && !frappe.utils.is_url(url)) { + url = frappe.base_url + url; + } + return url || null; + } + setup_events() { this.setup_filterable(); this.setup_list_click(); diff --git a/frappe/public/js/frappe/views/image/image_view.js b/frappe/public/js/frappe/views/image/image_view.js index 742bcd969f..aec392e15a 100644 --- a/frappe/public/js/frappe/views/image/image_view.js +++ b/frappe/public/js/frappe/views/image/image_view.js @@ -142,20 +142,6 @@ frappe.views.ImageView = class ImageView extends frappe.views.ListView { `; } - get_image_url(data) { - var url; - url = data.image ? data.image : data[this.meta.image_field]; - - // absolute url for mobile - if (window.cordova && !frappe.utils.is_url(url)) { - url = frappe.base_url + url; - } - if (url) { - return url; - } - return null; - } - get_attached_images() { return frappe .call({ diff --git a/frappe/public/js/frappe/views/kanban/kanban_board.js b/frappe/public/js/frappe/views/kanban/kanban_board.js index 8711deb4b4..87ce2d098e 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_board.js +++ b/frappe/public/js/frappe/views/kanban/kanban_board.js @@ -608,6 +608,7 @@ frappe.provide("frappe.views"); title: remove_img_tags(card.title), disable_click: card._disable_click ? 'disable-click' : '', creation: card.creation, + image_url: cur_list.get_image_url(card), }; self.$card = $(frappe.render_template('kanban_card', opts)) .appendTo(wrapper); @@ -705,6 +706,7 @@ frappe.provide("frappe.views"); title: card[state.card_meta.title_field.fieldname], creation: moment(card.creation).format('MMM DD, YYYY'), _liked_by: card._liked_by, + image: card[cur_list.meta.image_field], tags: card._user_tags, column: card[state.board.field_name], assigned_list: card.assigned_list || assigned_list, diff --git a/frappe/public/js/frappe/views/kanban/kanban_card.html b/frappe/public/js/frappe/views/kanban/kanban_card.html index b67488f46f..b854b88d18 100644 --- a/frappe/public/js/frappe/views/kanban/kanban_card.html +++ b/frappe/public/js/frappe/views/kanban/kanban_card.html @@ -1,15 +1,22 @@
-
-
- {{ title }} -
-
- {{ creation }} -
+ {% if(image_url) { %} +
+ {{title}}
-
+ {% } %} +
+
+
+ {{ title }} +
+
+ {{ creation }} +
+
+
+
diff --git a/frappe/public/scss/common/mixins.scss b/frappe/public/scss/common/mixins.scss index afcb6164fd..6d71ea9d6f 100644 --- a/frappe/public/scss/common/mixins.scss +++ b/frappe/public/scss/common/mixins.scss @@ -37,6 +37,38 @@ background-color: var(--bg-light-gray); } +@mixin broken-img( + $content: null, + $height: 100%, + $top: 0, + $left: 0, + $background-color: var(--bg-color), + $border-radius: var(--border-radius), +) { + + @if $content { + img:after { + content: url($content); + } + } @else { + img:after { + content: url("data:image/svg+xml;utf8,"); + } + } + + img[alt]:after { + height: $height; + top: $top; + left: $left; + background-color: $background-color; + border-radius: $border-radius; + width: 100%; + position: absolute; + @include flex(); + z-index: 1; + } +} + // @mixin img-foreground() { // content: "\f1c5"; // display: block; diff --git a/frappe/public/scss/desk/file_view.scss b/frappe/public/scss/desk/file_view.scss index 141976e9a3..5c55a9f1ef 100644 --- a/frappe/public/scss/desk/file_view.scss +++ b/frappe/public/scss/desk/file_view.scss @@ -98,21 +98,10 @@ position: relative; } - img:after { - content: url("data:image/svg+xml;utf8,"); - } - - img[alt]:after { - height: 70px; - @include flex(); - position: absolute; - z-index: 1; - top: -15px; - left: 0px; - width: 100%; - background-color: var(--bg-color); - border-radius: var(--border-radius); - } + @include broken-img( + $height: 70px, + $top: -15px, + ); } } diff --git a/frappe/public/scss/desk/image_view.scss b/frappe/public/scss/desk/image_view.scss index e249361592..3b9d033406 100644 --- a/frappe/public/scss/desk/image_view.scss +++ b/frappe/public/scss/desk/image_view.scss @@ -154,20 +154,10 @@ width: 100%; } - img:after { - content: url("data:image/svg+xml;utf8,"); - } - - img[alt]:after { - height: 175px; - @include flex(); - position: absolute; - z-index: 1; - top: 0; - left: 0; - width: 100%; - background-color: var(--bg-color); - } + @include broken-img( + $height: 175px, + $border-radius: 0 + ); } .image-title { diff --git a/frappe/public/scss/desk/kanban.scss b/frappe/public/scss/desk/kanban.scss index 08f281a323..41bd0b2859 100644 --- a/frappe/public/scss/desk/kanban.scss +++ b/frappe/public/scss/desk/kanban.scss @@ -153,13 +153,15 @@ .kanban-card { @include flex(flex, space-between, null, column); - - @include card( - $padding: var(--padding-sm) var(--padding-md), - $background-color: var(--kanban-card-bg) - ); margin-top: var(--margin-sm); min-height: 100px; + @include card( + $padding: 0, + $background-color: var(--kanban-card-bg) + ); + .kanban-card-body { + padding: var(--padding-sm); + } } } @@ -211,6 +213,27 @@ } } + .kanban-image { + height: 125px; + + img { + border-radius: var(--border-radius) var(--border-radius) 0 0; + object-position: top; + object-fit: cover; + margin: 0 auto; + height: 100%; + width: 100%; + min-width: 100%; + color: transparent; + position: relative; + } + + @include broken-img( + $height: 125px, + $top: -4px, + ) + } + .kanban-card-edit { position: absolute; right: 10px; @@ -289,6 +312,7 @@ height: 22px; width: auto; padding: 2px 8px; + margin-bottom: var(--margin-xs); margin-right: var(--margin-xs); } } diff --git a/frappe/public/scss/website/website_image.scss b/frappe/public/scss/website/website_image.scss index a08f3a4ba7..c7a6992140 100644 --- a/frappe/public/scss/website/website_image.scss +++ b/frappe/public/scss/website/website_image.scss @@ -4,36 +4,10 @@ img { position: relative; } -// fallback for broken images -// img:after { -// content: url("data:image/svg+xml;utf8,"); -// display: flex; -// justify-content: center; -// align-items: center; -// position: absolute; -// z-index: 1; -// top: 0; -// left: 0; -// width: 100%; -// height: 100%; -// background-color: $light; -// padding: 50% 0; -// } - -img:after { - content: url("data:image/svg+xml;utf8,"); -} - -img[alt]:after { - height: 175px; - @include flex(); - position: absolute; - z-index: 1; - top: 0; - left: 0; - width: 100%; - background-color: var(--bg-color); -} +@include broken-img( + $height: 175px, + $border-radius: 0, +); .website-image-placeholder { display: flex;