feat: Grid Searchversion-14
@@ -0,0 +1,59 @@ | |||
export default { | |||
name: "Child Table Doctype 1", | |||
actions: [], | |||
custom: 1, | |||
autoname: "format: Test-{####}", | |||
creation: "2022-02-09 20:15:21.242213", | |||
doctype: "DocType", | |||
editable_grid: 1, | |||
engine: "InnoDB", | |||
fields: [ | |||
{ | |||
fieldname: "data", | |||
fieldtype: "Data", | |||
in_list_view: 1, | |||
label: "Data" | |||
}, | |||
{ | |||
fieldname: "barcode", | |||
fieldtype: "Barcode", | |||
in_list_view: 1, | |||
label: "Barcode" | |||
}, | |||
{ | |||
fieldname: "check", | |||
fieldtype: "Check", | |||
in_list_view: 1, | |||
label: "Check" | |||
}, | |||
{ | |||
fieldname: "rating", | |||
fieldtype: "Rating", | |||
in_list_view: 1, | |||
label: "Rating" | |||
}, | |||
{ | |||
fieldname: "duration", | |||
fieldtype: "Duration", | |||
in_list_view: 1, | |||
label: "Duration" | |||
}, | |||
{ | |||
fieldname: "date", | |||
fieldtype: "Date", | |||
in_list_view: 1, | |||
label: "Date" | |||
} | |||
], | |||
links: [], | |||
istable: 1, | |||
modified: "2022-02-10 12:03:12.603763", | |||
modified_by: "Administrator", | |||
module: "Custom", | |||
naming_rule: "By fieldname", | |||
owner: "Administrator", | |||
permissions: [], | |||
sort_field: 'modified', | |||
sort_order: 'ASC', | |||
track_changes: 1 | |||
}; |
@@ -20,6 +20,12 @@ export default { | |||
label: "Child Table", | |||
options: "Child Table Doctype", | |||
reqd: 1 | |||
}, | |||
{ | |||
fieldname: "child_table_1", | |||
fieldtype: "Table", | |||
label: "Child Table 1", | |||
options: "Child Table Doctype 1" | |||
} | |||
], | |||
links: [], | |||
@@ -1,5 +1,6 @@ | |||
import doctype_with_child_table from '../fixtures/doctype_with_child_table'; | |||
import child_table_doctype from '../fixtures/child_table_doctype'; | |||
import child_table_doctype_1 from '../fixtures/child_table_doctype_1'; | |||
import doctype_to_link from '../fixtures/doctype_to_link'; | |||
const doctype_to_link_name = doctype_to_link.name; | |||
const child_table_doctype_name = child_table_doctype.name; | |||
@@ -9,6 +10,7 @@ context('Dashboard links', () => { | |||
cy.visit('/login'); | |||
cy.login(); | |||
cy.insert_doc('DocType', child_table_doctype, true); | |||
cy.insert_doc('DocType', child_table_doctype_1, true); | |||
cy.insert_doc('DocType', doctype_with_child_table, true); | |||
cy.insert_doc('DocType', doctype_to_link, true); | |||
return cy.window().its('frappe').then(frappe => { | |||
@@ -0,0 +1,107 @@ | |||
import doctype_with_child_table from '../fixtures/doctype_with_child_table'; | |||
import child_table_doctype from '../fixtures/child_table_doctype'; | |||
import child_table_doctype_1 from '../fixtures/child_table_doctype_1'; | |||
const doctype_with_child_table_name = doctype_with_child_table.name; | |||
context('Grid Search', () => { | |||
before(() => { | |||
cy.visit('/login'); | |||
cy.login(); | |||
cy.visit('/app/website'); | |||
cy.insert_doc('DocType', child_table_doctype, true); | |||
cy.insert_doc('DocType', child_table_doctype_1, true); | |||
cy.insert_doc('DocType', doctype_with_child_table, true); | |||
return cy.window().its('frappe').then(frappe => { | |||
return frappe.xcall("frappe.tests.ui_test_helpers.insert_doctype_with_child_table_record", { | |||
name: doctype_with_child_table_name | |||
}); | |||
}); | |||
}); | |||
it('Test search row visibility', () => { | |||
cy.window().its('frappe').then(frappe => { | |||
frappe.model.user_settings.save('Doctype With Child Table', 'GridView', { | |||
'Child Table Doctype 1': [ | |||
{'fieldname': 'data', 'columns': 2}, | |||
{'fieldname': 'barcode', 'columns': 1}, | |||
{'fieldname': 'check', 'columns': 1}, | |||
{'fieldname': 'rating', 'columns': 2}, | |||
{'fieldname': 'duration', 'columns': 2}, | |||
{'fieldname': 'date', 'columns': 2} | |||
] | |||
}); | |||
}); | |||
cy.visit(`/app/doctype-with-child-table/Test Grid Search`); | |||
cy.get('.frappe-control[data-fieldname="child_table_1"]').as('table'); | |||
cy.get('@table').find('.grid-row-check:last').click(); | |||
cy.get('@table').find('.grid-footer').contains('Delete').click(); | |||
cy.get('.grid-heading-row .grid-row .search').should('not.exist'); | |||
}); | |||
it('test search field for different fieldtypes', () => { | |||
cy.visit(`/app/doctype-with-child-table/Test Grid Search`); | |||
cy.get('.frappe-control[data-fieldname="child_table_1"]').as('table'); | |||
// Index Column | |||
cy.get('@table').find('.grid-heading-row .row-index.search input').type('3'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 2); | |||
cy.get('@table').find('.grid-heading-row .row-index.search input').clear(); | |||
// Data Column | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Data"]').type('Data'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 1); | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Data"]').clear(); | |||
// Barcode Column | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Barcode"]').type('092'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 4); | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Barcode"]').clear(); | |||
// Check Column | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Check"]').type('1'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 9); | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Check"]').clear(); | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Check"]').type('0'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 11); | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Check"]').clear(); | |||
// Rating Column | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Rating"]').type('3'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 3); | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Rating"]').clear(); | |||
// Duration Column | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Duration"]').type('3d'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 3); | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Duration"]').clear(); | |||
// Date Column | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Date"]').type('2022'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 4); | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Date"]').clear(); | |||
}); | |||
it('test with multiple filter', () => { | |||
cy.get('.frappe-control[data-fieldname="child_table_1"]').as('table'); | |||
// Data Column | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Data"]').type('a'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 10); | |||
// Barcode Column | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Barcode"]').type('0'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 8); | |||
// Duration Column | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Duration"]').type('d'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 5); | |||
// Date Column | |||
cy.get('@table').find('.grid-heading-row .search input[data-fieldtype="Date"]').type('02-'); | |||
cy.get('@table').find('.grid-body .rows .grid-row').should('have.length', 2); | |||
}); | |||
}); |
@@ -35,7 +35,7 @@ export default class Grid { | |||
&& this.frm.meta.__form_grid_templates[this.df.fieldname]) { | |||
this.template = this.frm.meta.__form_grid_templates[this.df.fieldname]; | |||
} | |||
this.filter = {}; | |||
this.is_grid = true; | |||
this.debounced_refresh = this.refresh.bind(this); | |||
this.debounced_refresh = frappe.utils.debounce(this.debounced_refresh, 100); | |||
@@ -274,6 +274,8 @@ export default class Grid { | |||
} | |||
make_head() { | |||
if (this.prevent_build) return; | |||
// labels | |||
if (this.header_row) { | |||
$(this.parent).find(".grid-heading-row .grid-row").remove(); | |||
@@ -286,12 +288,42 @@ export default class Grid { | |||
grid: this, | |||
configure_columns: true | |||
}); | |||
this.header_search = new GridRow({ | |||
parent: $(this.parent).find(".grid-heading-row"), | |||
parent_df: this.df, | |||
docfields: this.docfields, | |||
frm: this.frm, | |||
grid: this, | |||
show_search: true | |||
}); | |||
Object.keys(this.filter).length !== 0 && | |||
this.update_search_columns(); | |||
} | |||
update_search_columns() { | |||
for (const field in this.filter) { | |||
if (this.filter[field] && !this.header_search.search_columns[field]) { | |||
delete this.filter[field]; | |||
this.data = this.get_data(Object.keys(this.filter).length !== 0); | |||
break; | |||
} | |||
if (this.filter[field] && this.filter[field].value) { | |||
let $input = this.header_search.row_index.find('input'); | |||
if (field && field !== 'row-index') { | |||
$input = this.header_search.search_columns[field].find('input'); | |||
} | |||
$input.val(this.filter[field].value); | |||
} | |||
} | |||
} | |||
refresh(force) { | |||
refresh() { | |||
if (this.frm && this.frm.setting_dependency) return; | |||
this.data = this.get_data(); | |||
this.data = this.get_data(Object.keys(this.filter).length !== 0); | |||
!this.wrapper && this.make(); | |||
let $rows = $(this.parent).find('.rows'); | |||
@@ -453,7 +485,7 @@ export default class Grid { | |||
} | |||
make_sortable($rows) { | |||
new Sortable($rows.get(0), { | |||
this.grid_sortable = new Sortable($rows.get(0), { | |||
group: { name: this.df.fieldname }, | |||
handle: '.sortable-handle', | |||
draggable: '.grid-row', | |||
@@ -484,14 +516,78 @@ export default class Grid { | |||
$(this.frm.wrapper).trigger("grid-make-sortable", [this.frm]); | |||
} | |||
get_data() { | |||
var data = this.frm ? | |||
this.frm.doc[this.df.fieldname] || [] | |||
: this.df.data || this.get_modal_data(); | |||
// data.sort(function(a, b) { return a.idx - b.idx}); | |||
get_data(filter_field) { | |||
let data = []; | |||
if (filter_field) { | |||
data = this.get_filtered_data(); | |||
} else { | |||
data = this.frm ? | |||
this.frm.doc[this.df.fieldname] || [] | |||
: this.df.data || this.get_modal_data(); | |||
} | |||
return data; | |||
} | |||
get_filtered_data() { | |||
if (!this.frm) return; | |||
let all_data = this.frm.doc[this.df.fieldname]; | |||
for (const field in this.filter) { | |||
all_data = all_data.filter(data => { | |||
let {df, value} = this.filter[field]; | |||
return this.get_data_based_on_fieldtype(df, data, value.toLowerCase()); | |||
}); | |||
} | |||
return all_data; | |||
} | |||
get_data_based_on_fieldtype(df, data, value) { | |||
let fieldname = df.fieldname; | |||
let fieldtype = df.fieldtype; | |||
let fieldvalue = data[fieldname]; | |||
if (fieldtype === "Check") { | |||
value = frappe.utils.string_to_boolean(value); | |||
return (Boolean(fieldvalue) === value) && data; | |||
} else if (fieldtype === "Sr No" && data.idx.toString().includes(value)) { | |||
return data; | |||
} else if (fieldtype === "Duration" && fieldvalue) { | |||
let formatted_duration = frappe.utils.get_formatted_duration(fieldvalue); | |||
if (formatted_duration.includes(value)) { | |||
return data; | |||
} | |||
} else if (fieldtype === "Barcode" && fieldvalue) { | |||
let barcode = fieldvalue.startsWith('<svg') ? | |||
$(fieldvalue).attr('data-barcode-value') : fieldvalue; | |||
if (barcode.toLowerCase().includes(value)) { | |||
return data; | |||
} | |||
} else if (["Datetime", "Date"].includes(fieldtype) && fieldvalue) { | |||
let user_formatted_date = frappe.datetime.str_to_user(fieldvalue); | |||
if (user_formatted_date.includes(value)) { | |||
return data; | |||
} | |||
} else if (["Currency", "Float", "Int", "Percent", "Rating"].includes(fieldtype)) { | |||
let num = fieldvalue || 0; | |||
if (fieldtype === "Rating") { | |||
let out_of_rating = parseInt(df.options) || 5; | |||
num = num * out_of_rating; | |||
} | |||
if (num.toString().indexOf(value) > -1) { | |||
return data; | |||
} | |||
} else if (fieldvalue && fieldvalue.toLowerCase().includes(value)) { | |||
return data; | |||
} | |||
} | |||
get_modal_data() { | |||
return this.df.get_data ? this.df.get_data().filter(data => { | |||
if (!this.deleted_docs || !in_list(this.deleted_docs, data.name)) { | |||
@@ -775,18 +871,19 @@ export default class Grid { | |||
} | |||
setup_user_defined_columns() { | |||
if (this.frm) { | |||
let user_settings = frappe.get_user_settings(this.frm.doctype, 'GridView'); | |||
if (user_settings && user_settings[this.doctype] && user_settings[this.doctype].length) { | |||
this.user_defined_columns = user_settings[this.doctype].map(row => { | |||
let column = frappe.meta.get_docfield(this.doctype, row.fieldname); | |||
if (column) { | |||
column.in_list_view = 1; | |||
column.columns = row.columns; | |||
return column; | |||
} | |||
}); | |||
} | |||
if (!this.frm) return; | |||
let user_settings = frappe.get_user_settings(this.frm.doctype, 'GridView'); | |||
if (user_settings && user_settings[this.doctype] && user_settings[this.doctype].length) { | |||
this.user_defined_columns = user_settings[this.doctype].map(row => { | |||
let column = frappe.meta.get_docfield(this.doctype, row.fieldname); | |||
if (column) { | |||
column.in_list_view = 1; | |||
column.columns = row.columns; | |||
return column; | |||
} | |||
}); | |||
} | |||
} | |||
@@ -8,7 +8,7 @@ export default class GridRow { | |||
this.set_docfields(); | |||
this.columns = {}; | |||
this.columns_list = []; | |||
this.row_check_html = '<input type="checkbox" class="grid-row-check pull-left">'; | |||
this.row_check_html = '<input type="checkbox" class="grid-row-check">'; | |||
this.make(); | |||
} | |||
make() { | |||
@@ -204,23 +204,65 @@ export default class GridRow { | |||
})); | |||
} | |||
render_row(refresh) { | |||
var me = this; | |||
if (this.show_search && !this.show_search_row()) return; | |||
let me = this; | |||
this.set_row_index(); | |||
// index (1, 2, 3 etc) | |||
if(!this.row_index) { | |||
if (!this.row_index && !this.show_search) { | |||
// REDESIGN-TODO: Make translation contextual, this No is Number | |||
var txt = (this.doc ? this.doc.idx : __("No.")); | |||
this.row_index = $( | |||
`<div class="row-index sortable-handle col"> | |||
this.row_check = $( | |||
`<div class="row-check sortable-handle col"> | |||
${this.row_check_html} | |||
<span class="hidden-xs">${txt}</span></div>`) | |||
</div>`) | |||
.appendTo(this.row); | |||
this.row_index = $( | |||
`<div class="row-index sortable-handle col hidden-xs"> | |||
<span>${txt}</span> | |||
</div>`) | |||
.appendTo(this.row) | |||
.on('click', function(e) { | |||
if(!$(e.target).hasClass('grid-row-check')) { | |||
me.toggle_view(); | |||
} | |||
}); | |||
} else if (this.show_search) { | |||
this.row_check = $( | |||
`<div class="row-check col search"></div>` | |||
).appendTo(this.row); | |||
this.row_index = $( | |||
`<div class="row-index col search hidden-xs"> | |||
<input type="text" class="form-control input-xs text-center" > | |||
</div>` | |||
).appendTo(this.row); | |||
this.row_index.find('input').on('keyup', frappe.utils.debounce((e) => { | |||
let df = { | |||
fieldtype: "Sr No" | |||
}; | |||
this.grid.filter['row-index'] = { | |||
df: df, | |||
value: e.target.value | |||
}; | |||
if (e.target.value == "") { | |||
delete this.grid.filter['row-index']; | |||
} | |||
this.grid.grid_sortable | |||
.option('disabled', Object.keys(this.grid.filter).length !== 0); | |||
this.grid.prevent_build = true; | |||
me.grid.refresh(); | |||
this.grid.prevent_build = false; | |||
}, 500)); | |||
frappe.utils.only_allow_num_decimal(this.row_index.find('input')); | |||
} else { | |||
this.row_index.find('span').html(txt); | |||
} | |||
@@ -546,6 +588,7 @@ export default class GridRow { | |||
setup_columns() { | |||
this.focus_set = false; | |||
this.search_columns = {}; | |||
this.grid.setup_visible_columns(); | |||
this.grid.visible_columns.forEach((col, ci) => { | |||
@@ -561,8 +604,10 @@ export default class GridRow { | |||
txt = __(txt); | |||
} | |||
let column; | |||
if (!this.columns[df.fieldname]) { | |||
if (!this.columns[df.fieldname] && !this.show_search) { | |||
column = this.make_column(df, colsize, txt, ci); | |||
} else if (!this.columns[df.fieldname] && this.show_search) { | |||
column = this.make_search_column(df, colsize); | |||
} else { | |||
column = this.columns[df.fieldname]; | |||
this.refresh_field(df.fieldname, txt); | |||
@@ -580,6 +625,77 @@ export default class GridRow { | |||
} | |||
} | |||
}); | |||
if (this.show_search) { | |||
// last empty column | |||
$(`<div class="col grid-static-col col-xs-1"></div>`) | |||
.appendTo(this.row); | |||
} | |||
} | |||
show_search_row() { | |||
// show or remove search columns based on grid rows | |||
this.show_search = this.frm && this.frm.doc && | |||
this.frm.doc[this.grid.df.fieldname] && | |||
this.frm.doc[this.grid.df.fieldname].length >= 20; | |||
!this.show_search && this.wrapper.remove(); | |||
return this.show_search; | |||
} | |||
make_search_column(df, colsize) { | |||
let title = ""; | |||
let input_class = ""; | |||
let is_disabled = ""; | |||
if (["Text", "Small Text"].includes(df.fieldtype)) { | |||
input_class = "grid-overflow-no-ellipsis"; | |||
} else if (["Int", "Currency", "Float", "Percent"].includes(df.fieldtype)) { | |||
input_class = "text-right"; | |||
} else if (df.fieldtype === "Check") { | |||
title = __("1 = True & 0 = False"); | |||
input_class = "text-center"; | |||
} else if (df.fieldtype === 'Password') { | |||
is_disabled = 'disabled'; | |||
title = __('Password cannot be filtered'); | |||
} | |||
let $col = $('<div class="col grid-static-col col-xs-'+colsize+' search"></div>') | |||
.appendTo(this.row); | |||
let $search_input = $(` | |||
<input | |||
type="text" | |||
class="form-control input-xs ${input_class}" | |||
title="${title}" | |||
data-fieldtype="${df.fieldtype}" | |||
${is_disabled} | |||
> | |||
`).appendTo($col); | |||
this.search_columns[df.fieldname] = $col; | |||
$search_input.on('keyup', frappe.utils.debounce((e) => { | |||
this.grid.filter[df.fieldname] = { | |||
df: df, | |||
value: e.target.value | |||
}; | |||
if (e.target.value == '') { | |||
delete this.grid.filter[df.fieldname]; | |||
} | |||
this.grid.grid_sortable | |||
.option('disabled', Object.keys(this.grid.filter).length !== 0); | |||
this.grid.prevent_build = true; | |||
this.grid.refresh(); | |||
this.grid.prevent_build = false; | |||
}, 500)); | |||
["Currency", "Float", "Int", "Percent", "Rating"].includes(df.fieldtype) && | |||
frappe.utils.only_allow_num_decimal($search_input); | |||
return $col; | |||
} | |||
make_column(df, colsize, txt, ci) { | |||
@@ -1102,7 +1102,7 @@ Object.assign(frappe.utils, { | |||
seconds: round(seconds % 60) | |||
}; | |||
if (duration_options.hide_days) { | |||
if (duration_options && duration_options.hide_days) { | |||
total_duration.hours = round(seconds / 3600); | |||
total_duration.days = 0; | |||
} | |||
@@ -1462,5 +1462,23 @@ Object.assign(frappe.utils, { | |||
console.log(error); // eslint-disable-line | |||
return Promise.resolve(name); | |||
} | |||
}, | |||
only_allow_num_decimal(input) { | |||
input.on('input', (e) => { | |||
let self = $(e.target); | |||
self.val(self.val().replace(/[^0-9.]/g, '')); | |||
if ((e.which != 46 || self.val().indexOf('.') != -1) && (e.which < 48 || e.which > 57)) { | |||
e.preventDefault(); | |||
} | |||
}); | |||
}, | |||
string_to_boolean(string) { | |||
switch (string.toLowerCase().trim()) { | |||
case "t": case "true": case "y": case "yes": case "1": return true; | |||
case "f": case "false": case "n": case "no": case "0": case null: return false; | |||
default: return string; | |||
} | |||
} | |||
}); |
@@ -89,6 +89,29 @@ | |||
height: 34px; | |||
padding: 8px; | |||
max-height: 200px; | |||
&.search { | |||
padding: 7px !important; | |||
input { | |||
height: -webkit-fill-available; | |||
padding: 3px 7px; | |||
} | |||
} | |||
} | |||
.row-check { | |||
height: 34px; | |||
padding: 8px 3px !important; | |||
text-align: center; | |||
input { | |||
margin-right: 0 !important; | |||
} | |||
&.search { | |||
padding: 0 !important; | |||
} | |||
} | |||
.grid-row-check { | |||
@@ -124,7 +147,6 @@ | |||
.grid-row > .row { | |||
.col:last-child { | |||
margin-right: calc(-1 * var(--margin-sm)); | |||
border-right: none; | |||
} | |||
@@ -427,6 +449,7 @@ | |||
} | |||
.page-number { | |||
background-color: var(--fg-color); | |||
padding: 0 3px; | |||
} | |||
@@ -272,4 +272,47 @@ def update_child_table(name): | |||
'options': 'Doctype to Link' | |||
}) | |||
doc.save() | |||
doc.save() | |||
@frappe.whitelist() | |||
def insert_doctype_with_child_table_record(name): | |||
if frappe.db.get_all(name, {'title': 'Test Grid Search'}): | |||
return | |||
def insert_child(doc, data, barcode, check, rating, duration, date): | |||
doc.append('child_table_1', { | |||
'data': data, | |||
'barcode': barcode, | |||
'check': check, | |||
'rating': rating, | |||
'duration': duration, | |||
'date': date, | |||
}) | |||
doc = frappe.new_doc(name) | |||
doc.title = 'Test Grid Search' | |||
doc.append('child_table', {'title': 'Test Grid Search'}) | |||
insert_child(doc, 'Data', '09709KJKKH2432', 1, 0.5, 266851, "2022-02-21") | |||
insert_child(doc, 'Test', '09209KJHKH2432', 1, 0.8, 547877, "2021-05-27") | |||
insert_child(doc, 'New', '09709KJHYH1132', 0, 0.1, 3, "2019-03-02") | |||
insert_child(doc, 'Old', '09701KJHKH8750', 0, 0, 127455, "2022-01-11") | |||
insert_child(doc, 'Alpha', '09204KJHKH2432', 0, 0.6, 364, "2019-12-31") | |||
insert_child(doc, 'Delta', '09709KSPIO2432', 1, 0.9, 1242000, "2020-04-21") | |||
insert_child(doc, 'Update', '76989KJLVA2432', 0, 1, 183845, "2022-02-10") | |||
insert_child(doc, 'Delete', '29189KLHVA1432', 0, 0, 365647, "2021-05-07") | |||
insert_child(doc, 'Make', '09689KJHAA2431', 0, 0.3, 24, "2020-11-11") | |||
insert_child(doc, 'Create', '09709KLKKH2432', 1, 0.3, 264851, "2021-02-21") | |||
insert_child(doc, 'Group', '09209KJLKH2432', 1, 0.8, 537877, "2020-03-15") | |||
insert_child(doc, 'Slide', '01909KJHYH1132', 0, 0.5, 9, "2018-03-02") | |||
insert_child(doc, 'Drop', '09701KJHKH8750', 1, 0, 127255, "2018-01-01") | |||
insert_child(doc, 'Beta', '09204QJHKN2432', 0, 0.6, 354, "2017-12-30") | |||
insert_child(doc, 'Flag', '09709KXPIP2432', 1, 0, 1241000, "2021-04-21") | |||
insert_child(doc, 'Upgrade', '75989ZJLVA2432', 0.8, 1, 183645, "2020-08-13") | |||
insert_child(doc, 'Down', '28189KLHRA1432', 1, 0, 362647, "2020-06-17") | |||
insert_child(doc, 'Note', '09689DJHAA2431', 0, 0.1, 29, "2021-09-11") | |||
insert_child(doc, 'Click', '08189DJHAA2431', 1, 0.3, 209, "2020-07-04") | |||
insert_child(doc, 'Drag', '08189DIHAA2981', 0, 0.7, 342628, "2022-05-04") | |||
doc.insert() |