Pārlūkot izejas kodu

Colors in Event Calendar using color picker (#3857)

* Add Color field to Event, show colored event in calendar

* [minor] handle edge cases

* Fix test boilerplate

* Add test for event

* fix codacy

* fix test
version-14
Faris Ansari pirms 8 gadiem
committed by Rushabh Mehta
vecāks
revīzija
44ee24aa75
11 mainītis faili ar 196 papildinājumiem un 29 dzēšanām
  1. +2
    -2
      frappe/core/doctype/doctype/boilerplate/test_controller.js
  2. +2
    -1
      frappe/core/doctype/version/test_version.py
  3. +5
    -5
      frappe/desk/doctype/event/event.json
  4. +36
    -0
      frappe/desk/doctype/event/test_event.js
  5. +1
    -0
      frappe/public/build.json
  6. +0
    -1
      frappe/public/css/calendar.css
  7. +5
    -0
      frappe/public/js/frappe/form/control.js
  8. +121
    -0
      frappe/public/js/frappe/ui/colors.js
  9. +21
    -17
      frappe/public/js/frappe/views/calendar/calendar.js
  10. +1
    -2
      frappe/public/less/calendar.less
  11. +2
    -1
      frappe/tests/ui/tests.txt

+ 2
- 2
frappe/core/doctype/doctype/boilerplate/test_controller.js Parādīt failu

@@ -8,9 +8,9 @@ QUnit.test("test: {doctype}", function (assert) {{
// number of asserts
assert.expect(1);

frappe.run_serially('{doctype}', [
frappe.run_serially([
// insert a new {doctype}
() => frappe.tests.make([
() => frappe.tests.make('{doctype}', [
// values to be set
{{key: 'value'}}
]),


+ 2
- 1
frappe/core/doctype/version/test_version.py Parādīt failu

@@ -14,12 +14,13 @@ class TestVersion(unittest.TestCase):
new_doc = copy.deepcopy(old_doc)

old_doc.color = None
new_doc.color = '#fafafa'

diff = get_diff(old_doc, new_doc)['changed']

self.assertEquals(get_fieldnames(diff)[0], 'color')
self.assertTrue(get_old_values(diff)[0] is None)
self.assertEquals(get_new_values(diff)[0], 'blue')
self.assertEquals(get_new_values(diff)[0], '#fafafa')

new_doc.starts_on = "2017-07-20"



+ 5
- 5
frappe/desk/doctype/event/event.json Parādīt failu

@@ -312,9 +312,9 @@
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "blue",
"default": "",
"fieldname": "color",
"fieldtype": "Select",
"fieldtype": "Color",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
@@ -325,7 +325,7 @@
"label": "Color",
"length": 0,
"no_copy": 0,
"options": "red\ngreen\nblue\nyellow\nskyblue\norange",
"options": "",
"permlevel": 0,
"precision": "",
"print_hide": 0,
@@ -895,8 +895,8 @@
"issingle": 0,
"istable": 0,
"max_attachments": 0,
"modified": "2017-07-06 12:37:44.036819",
"modified_by": "Administrator",
"modified": "2017-08-03 16:34:54.657796",
"modified_by": "faris@erpnext.com",
"module": "Desk",
"name": "Event",
"owner": "Administrator",


+ 36
- 0
frappe/desk/doctype/event/test_event.js Parādīt failu

@@ -0,0 +1,36 @@

QUnit.test("test: Event", function (assert) {
let done = assert.async();

// number of asserts
assert.expect(4);

const subject = '_Test Event 1';
const datetime = frappe.datetime.now_datetime();
const hex = '#6be273';
const rgb = 'rgb(107, 226, 115)';

frappe.run_serially([
// insert a new Event
() => frappe.tests.make('Event', [
// values to be set
{subject: subject},
{starts_on: datetime},
{color: hex}
]),
() => {
assert.equal(cur_frm.doc.subject, subject, 'Subject correctly set');
assert.equal(cur_frm.doc.starts_on, datetime, 'Date correctly set');
assert.equal(cur_frm.doc.color, hex, 'Color correctly set');
},
() => frappe.set_route('List', 'Event', 'Calendar'),
() => frappe.timeout(2),
() => {
const bg_color = $(`.result-list:visible .fc-day-grid-event:contains("${subject}")`)
.css('background-color');
assert.equal(bg_color, rgb, 'Event background color is set correctly');
},
() => done()
]);

});

+ 1
- 0
frappe/public/build.json Parādīt failu

@@ -87,6 +87,7 @@
"public/js/frappe/ui/messages.js",
"public/js/frappe/ui/keyboard.js",
"public/js/frappe/ui/emoji.js",
"public/js/frappe/ui/colors.js",

"public/js/frappe/request.js",
"public/js/frappe/socketio_client.js",


+ 0
- 1
frappe/public/css/calendar.css Parādīt failu

@@ -73,7 +73,6 @@ th.fc-day-header {
background: #cfdce5 !important;
}
.fc-day-grid-event {
background-color: rgba(94, 100, 255, 0.2) !important;
border: none !important;
margin: 5px 4px 0 !important;
padding: 1px 5px !important;


+ 5
- 0
frappe/public/js/frappe/form/control.js Parādīt failu

@@ -688,6 +688,8 @@ frappe.ui.form.ControlColor = frappe.ui.form.ControlData.extend({
},
set_formatted_input: function(value) {
this._super(value);

if(!value) value = '#ffffff';
this.$input.css({
"background-color": value
});
@@ -721,6 +723,9 @@ frappe.ui.form.ControlColor = frappe.ui.form.ControlData.extend({
});
},
validate: function (value) {
if(value === '') {
return '';
}
var is_valid = /^#[0-9A-F]{6}$/i.test(value);
if(is_valid) {
return value;


+ 121
- 0
frappe/public/js/frappe/ui/colors.js Parādīt failu

@@ -0,0 +1,121 @@
// Copyright (c) 2017, Frappe Technologies Pvt. Ltd. and Contributors
// MIT License. See license.txt

frappe.provide("frappe.ui");

frappe.ui.color_map = {
red: ["#ffc4c4", "#ff8989", "#ff4d4d", "#a83333"],
brown: ["#ffe8cd", "#ffd19c", "#ffb868", "#a87945"],
orange: ["#ffd2c2", "#ffa685", "#ff7846", "#a85b5b"],
peach: ["#ffd7d7", "#ffb1b1", "#ff8989", "#a84f2e"],
yellow: ["#fffacd", "#fff168", "#fff69c", "#a89f45"],
yellowgreen: ["#ebf8cc", "#d9f399", "#c5ec63", "#7b933d"],
green: ["#cef6d1", "#9deca2", "#6be273", "#428b46"],
cyan: ["#d2f8ed", "#a4f3dd", "#77ecca", "#49937e"],
skyblue: ["#d2f1ff", "#a6e4ff", "#78d6ff", "#4f8ea8"],
blue: ["#d2d2ff", "#a3a3ff", "#7575ff", "#4d4da8"],
purple: ["#dac7ff", "#b592ff", "#8e58ff", "#5e3aa8"],
pink: ["#f8d4f8", "#f3aaf0", "#ec7dea", "#934f92"]
};

frappe.ui.color = {
get: function(color_name, shade) {
if(color_name && shade) return this.get_color_shade(color_name, shade);
if(color_name) return this.get_color_shade(color_name, 'default');
return frappe.ui.color_map;
},
get_color: function(color_name) {
const color_names = Object.keys(frappe.ui.color_map);
if(color_names.includes(color_name)) {
return frappe.ui.color_map[color_name];
} else {
throw new RangeError(`${color_name} can be one of ${color_names}`);
}
},
get_color_shade: function(color_name, shade) {
const shades = {
'default': 2,
'light': 1,
'extra-light': 0,
'dark': 3
};

if(Object.keys(shades).includes(shade)) {
return frappe.ui.color_map[color_name][shades[shade]];
} else {
throw new RangeError(`${shade} can be one of ${Object.keys(shades)}`);
}
},
all: function() {
return Object.values(frappe.ui.color_map)
.reduce((acc, curr) => acc.concat(curr) , []);
},
names: function() {
return Object.keys(frappe.ui.color_map);
},
validate: function(color_name) {
if(!color_name) return false;
if(color_name.startsWith('#')) {
return this.all().includes(color_name);
}
return this.names().includes(color_name);
},
get_color_name: function(hex) {
for (const key in frappe.ui.color_map) {
const colors = frappe.ui.color_map[key];
if (colors.includes(hex)) return key;
}
},
get_contrast_color: function(hex) {
if(!this.validate(hex)) {
const brightness = this.brightness(hex);
if(brightness < 128) {
return this.lighten(hex, 0.5);
}
return this.lighten(hex, -0.5);
}

const color_name = this.get_color_name(hex);
const colors = this.get_color(color_name);
const shade_value = colors.indexOf(hex);
if(shade_value <= 1) {
return this.get(color_name, 'dark');
}
return this.get(color_name, 'extra-light');
},

lighten(color, percent) {
// https://stackoverflow.com/a/13542669/5353542
var f = parseInt(color.slice(1), 16),
t = percent < 0 ? 0 : 255,
p = percent < 0 ? percent * -1 : percent,
R = f >> 16,
G = f >> 8 & 0x00FF,
B = f & 0x0000FF;
return "#" +
(0x1000000 +
(Math.round((t - R) * p) + R) *
0x10000 +
(Math.round((t - G) * p) + G) *
0x100 + (Math.round((t - B) * p) + B)
).toString(16).slice(1);
},

hex_to_rgb(hex) {
if(hex.startsWith('#')) {
hex = hex.substring(1);
}
const r = parseInt(hex.substring(0, 2), 16);
const g = parseInt(hex.substring(2, 4), 16);
const b = parseInt(hex.substring(4, 6), 16);
return {r, g, b};
},

brightness(hex) {
const rgb = this.hex_to_rgb(hex);
// https://www.w3.org/TR/AERT#color-contrast
// 255 - brightest (#fff)
// 0 - darkest (#000)
return (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000;
}
};

+ 21
- 17
frappe/public/js/frappe/views/calendar/calendar.js Parādīt failu

@@ -100,7 +100,8 @@ frappe.views.Calendar = Class.extend({
color_map: {
"danger": "red",
"success": "green",
"warning": "orange"
"warning": "orange",
"default": "blue"
},
get_system_datetime: function(date) {
date._offset = moment.user_utc_offset;
@@ -232,25 +233,28 @@ frappe.views.Calendar = Class.extend({
d.end = frappe.datetime.convert_to_user_tz(d.end);

me.fix_end_date_for_event_render(d);

let color;
if(me.get_css_class) {
color = me.color_map[me.get_css_class(d)];
// if invalid, fallback to blue color
if(!Object.values(me.color_map).includes(color)) {
color = "blue";
}
} else {
// color field can be set in {doctype}_calendar.js
// see event_calendar.js
color = d.color;
}

if(!color) color = "blue";
d.className = "fc-bg-" + color;
me.prepare_colors(d);
return d;
});
},
prepare_colors: function(d) {
let color, color_name;
if(this.get_css_class) {
color_name = this.color_map[this.get_css_class(d)];
color_name =
frappe.ui.color.validate(color_name) ?
color_name :
'blue';
d.backgroundColor = frappe.ui.color.get(color_name, 'extra-light');
d.textColor = frappe.ui.color.get(color_name, 'dark');
} else {
color = d.color;
if(!color) color = frappe.ui.color.get('blue', 'extra-light');
d.backgroundColor = color;
d.textColor = frappe.ui.color.get_contrast_color(color);
}
return d;
},
update_event: function(event, revertFunc) {
var me = this;
frappe.model.remove_from_locals(me.doctype, event.name);


+ 1
- 2
frappe/public/less/calendar.less Parādīt failu

@@ -27,7 +27,7 @@ th.fc-widget-header {

.fc-unthemed .fc-today {
background-color: #FFF !important;
.fc-day-number {
background-color: @brand-primary;
min-width: 20px;
@@ -90,7 +90,6 @@ th.fc-day-header {
}

.fc-day-grid-event {
background-color: rgba(94, 100, 255, 0.2) !important;
border: none !important;
margin: 5px 4px 0 !important;
padding: 1px 5px !important;


+ 2
- 1
frappe/tests/ui/tests.txt Parādīt failu

@@ -9,4 +9,5 @@ frappe/tests/ui/test_kanban/test_kanban_filters.js
frappe/tests/ui/test_kanban/test_kanban_column.js
frappe/core/doctype/report/test_query_report.js
frappe/tests/ui/test_linked_with.js
frappe/custom/doctype/customize_form/test_customize_form.js
frappe/custom/doctype/customize_form/test_customize_form.js
frappe/desk/doctype/event/test_event.js

Notiek ielāde…
Atcelt
Saglabāt