Fix moving cards in carts, json importer, and further rerender fixes and optimizations
Signed-off-by: Egor Savkin <es@m-labs.hk>
This commit is contained in:
parent
2bfc16e3c0
commit
c09d583fa6
File diff suppressed because one or more lines are too long
@ -1,9 +1,14 @@
|
||||
import {OverlayTrigger} from "react-bootstrap";
|
||||
import React from "react";
|
||||
import {MaxLevel} from "./warnings";
|
||||
import {useShopStore} from "./shop_store";
|
||||
import {compareArraysLevelOne} from "./utils";
|
||||
|
||||
|
||||
export function CardWarnings({warnings, prefix}) {
|
||||
export function CardWarnings({crate_index, card_index}) {
|
||||
|
||||
const warnings = useShopStore(state => state.crates[crate_index].items[card_index].show_warnings, compareArraysLevelOne);
|
||||
|
||||
const max_level = MaxLevel(warnings);
|
||||
return (
|
||||
<OverlayTrigger
|
||||
@ -14,7 +19,7 @@ export function CardWarnings({warnings, prefix}) {
|
||||
<div className="k-popup-warning" {...props}>
|
||||
{warnings.map((warning, _i) => {
|
||||
return (
|
||||
<p className="rule warning" key={`warnmsg_${prefix}_${warning.name}`}>
|
||||
<p className="rule warning" key={`warnmsg_${card_index}_${warning.name}`}>
|
||||
<i>{warning.message}</i>
|
||||
</p>
|
||||
)
|
||||
@ -28,7 +33,9 @@ export function CardWarnings({warnings, prefix}) {
|
||||
)
|
||||
}
|
||||
|
||||
export function WarningIndicator({warnings}) {
|
||||
export function WarningIndicator({crate_index, card_index}) {
|
||||
const warnings = useShopStore(state => state.crates[crate_index].items[card_index].show_warnings, compareArraysLevelOne);
|
||||
|
||||
const max_level = MaxLevel(warnings);
|
||||
return (
|
||||
<img
|
||||
|
@ -1,14 +1,14 @@
|
||||
import React from 'react'
|
||||
import {Droppable} from "@hello-pangea/dnd";
|
||||
import {cartStyle} from "./utils";
|
||||
import {cartStyle, compareArraysWithIds} from "./utils";
|
||||
import {ProductCartItem} from "./ProductCartItem";
|
||||
import {FakePlaceholder} from "./FakePlaceholder";
|
||||
import {FillExtData} from "./options/utils";
|
||||
import {hp_to_slots} from "./count_resources";
|
||||
import {useShopStore} from "./shop_store";
|
||||
|
||||
// #!render_count
|
||||
import {useRenderCount} from "@uidotdev/usehooks";
|
||||
import {useShallow} from "zustand/react/shallow";
|
||||
|
||||
/**
|
||||
* Component that displays a list of <ProductCartItem>
|
||||
@ -18,9 +18,7 @@ export function Cart({crate_index}) {
|
||||
const renderCount = useRenderCount();
|
||||
|
||||
const crate = useShopStore((state) => state.crates[crate_index], (a, b) => {
|
||||
//console.log(a, b)
|
||||
return a.items.length === b.items.length && a.occupiedHP === b.occupiedHP && a.crate_mode === b.crate_mode
|
||||
//return a === b
|
||||
return compareArraysWithIds(a.items, b.items) && a.occupiedHP === b.occupiedHP && a.crate_mode === b.crate_mode
|
||||
});
|
||||
const crateParams = useShopStore((state) => state.crateParams);
|
||||
|
||||
|
@ -1,18 +1,17 @@
|
||||
import React from "react";
|
||||
import {LevelUI} from "./warnings";
|
||||
import {useShopStore} from "./shop_store";
|
||||
import {compareArraysWithIds} from "./utils";
|
||||
|
||||
// #!render_count
|
||||
import {useRenderCount} from "@uidotdev/usehooks";
|
||||
|
||||
const compareArrays = (a, b) =>
|
||||
a.length === b.length &&
|
||||
a.every((element, index) => element.id === b[index].id);
|
||||
|
||||
export function CrateWarnings({crate_index}) {
|
||||
// #!render_count
|
||||
const renderCount = useRenderCount();
|
||||
|
||||
const crate_warnings = useShopStore(state => (state.crates[crate_index].warnings), compareArrays)
|
||||
const crate_warnings = useShopStore(state => (state.crates[crate_index].warnings), compareArraysWithIds)
|
||||
|
||||
// #!render_count
|
||||
console.log("CrateWarnings renders: ", renderCount)
|
||||
|
@ -6,10 +6,29 @@ import {Validation} from "./validate";
|
||||
// #!render_count
|
||||
import {useRenderCount} from "@uidotdev/usehooks";
|
||||
|
||||
const JSONExample = JSON.stringify({
|
||||
"items": [{"pn": "1124"}, {"pn": "2118"}, {"pn": "2118"}, {"pn": "2128"}],
|
||||
"type": "desktop"
|
||||
});
|
||||
const JSONExample = JSON.stringify([
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"pn": "1124",
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"pn": "2118",
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"pn": "2118",
|
||||
"options": null
|
||||
},
|
||||
{
|
||||
"pn": "2128",
|
||||
"options": null
|
||||
}
|
||||
],
|
||||
"type": "rack"
|
||||
}
|
||||
]);
|
||||
|
||||
export function ImportJSON() {
|
||||
// #!render_count
|
||||
|
49
static/js/shop/OptionsWrapper.jsx
Normal file
49
static/js/shop/OptionsWrapper.jsx
Normal file
@ -0,0 +1,49 @@
|
||||
import {DialogPopup} from "./options/DialogPopup";
|
||||
import React from "react";
|
||||
import {useShopStore} from "./shop_store";
|
||||
import {SummaryPopup} from "./options/SummaryPopup";
|
||||
|
||||
export function OptionsDialogWrapper({crate_index, card_index, first, last}) {
|
||||
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
||||
const options = useShopStore((state) => state.crates[crate_index].items[card_index].options);
|
||||
const options_data = useShopStore((state) => state.crates[crate_index].items[card_index].options_data);
|
||||
const card_size = useShopStore((state) => state.crates[crate_index].items[card_index].size);
|
||||
const options_class = useShopStore((state) => state.crates[crate_index].items[card_index].options_class);
|
||||
|
||||
const onOptionsUpdate = useShopStore((state) => state.updateOptions);
|
||||
|
||||
return (
|
||||
<DialogPopup
|
||||
options={options}
|
||||
data={options_data}
|
||||
options_class={options_class}
|
||||
key={"popover" + card_index}
|
||||
id={"popover" + card_index}
|
||||
big={card_size === "big"}
|
||||
first={first}
|
||||
last={last}
|
||||
target={{
|
||||
construct: ((outvar, value) => {
|
||||
// console.log("construct", outvar, value, options_data);
|
||||
options_data[outvar] = value;
|
||||
}),
|
||||
update: ((outvar, value) => {
|
||||
// console.log("update", outvar, value, options_data);
|
||||
if (outvar in options_data) options_data[outvar] = value;
|
||||
onOptionsUpdate(crate_id, card_index, {[outvar]: value});
|
||||
})
|
||||
}}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function OptionsSummaryWrapper({crate_index, card_index}) {
|
||||
const card_id = useShopStore((state) => state.crates[crate_index].items[card_index].id);
|
||||
const options = useShopStore((state) => state.crates[crate_index].items[card_index].options);
|
||||
const options_data = useShopStore((state) => state.crates[crate_index].items[card_index].options_data);
|
||||
|
||||
return (
|
||||
<SummaryPopup id={card_id + "options"} options={options}
|
||||
data={options_data}/>
|
||||
)
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
import React from 'react'
|
||||
import {Draggable} from "@hello-pangea/dnd";
|
||||
import {DialogPopup} from "./options/DialogPopup";
|
||||
import {productStyle} from "./utils";
|
||||
import {compareObjectsEmptiness, productStyle} from "./utils";
|
||||
import {Resources} from "./Resources";
|
||||
import {CardWarnings} from "./CardWarnings";
|
||||
import {useShopStore} from "./shop_store";
|
||||
import {OptionsDialogWrapper} from "./OptionsWrapper";
|
||||
|
||||
// #!render_count
|
||||
import {useRenderCount} from "@uidotdev/usehooks";
|
||||
@ -13,36 +13,30 @@ import {useRenderCount} from "@uidotdev/usehooks";
|
||||
* Component that renders a product.
|
||||
* Used in the crate
|
||||
*/
|
||||
export function ProductCartItem({card_index, crate_index, ext_data, first, last}) {
|
||||
export function ProductCartItem({card_index, crate_index, first, last}) {
|
||||
// #!render_count
|
||||
const renderCount = useRenderCount();
|
||||
|
||||
|
||||
const card = useShopStore((state) => state.crates[crate_index].items[card_index],
|
||||
(a, b) => {
|
||||
//console.log(a.options_data, b.options_data, a.options_data === b.options_data)
|
||||
return a.id === b.id && a.show_warnings === b.show_warnings && a.counted_resources === b.counted_resources && a.options_data === b.options_data
|
||||
} );
|
||||
(a, b) => a.id === b.id);
|
||||
|
||||
const card_show_warnings = useShopStore(state => state.crates[crate_index].items[card_index].show_warnings, compareObjectsEmptiness);
|
||||
const card_counted_resources = useShopStore(state => state.crates[crate_index].items[card_index].counted_resources, compareObjectsEmptiness);
|
||||
|
||||
const highlighted = useShopStore((state) => state.crates[crate_index].id === state.highlighted.crate && card_index === state.highlighted.card);
|
||||
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
||||
const setHighlight = useShopStore((state) => state.highlightCard);
|
||||
const removeHighlight = useShopStore((state) => state.highlightReset);
|
||||
const onCardUpdate = useShopStore((state) => state.updateOptions);
|
||||
const onCardRemove = useShopStore((state) => state.deleteCard);
|
||||
|
||||
// #!render_count
|
||||
console.log("ProductCartItem renders: ", renderCount)
|
||||
|
||||
let options, options_data;
|
||||
const warnings = card && card.show_warnings;
|
||||
const resources = card && card.counted_resources;
|
||||
|
||||
if (card && card.options) {
|
||||
options = card.options;
|
||||
if (!card.options_data) card.options_data = {};
|
||||
options_data = card.options_data;
|
||||
options_data.ext_data = ext_data;
|
||||
}
|
||||
const options = card && card.options && card.options.length > 0;
|
||||
const warnings = card_show_warnings && card_show_warnings.length > 0;
|
||||
const resources = card_counted_resources && card_counted_resources.length > 0;
|
||||
|
||||
return (
|
||||
<Draggable draggableId={card.id} index={card_index}>
|
||||
@ -69,31 +63,16 @@ export function ProductCartItem({card_index, crate_index, ext_data, first, last}
|
||||
{/* warning container */}
|
||||
|
||||
<div className="progress-container warning d-flex justify-content-evenly">
|
||||
{warnings && warnings.length > 0 &&
|
||||
(<CardWarnings warnings={warnings} prefix={card_index}/>)
|
||||
{warnings &&
|
||||
(<CardWarnings crate_index={crate_index} card_index={card_index} />)
|
||||
}
|
||||
|
||||
{options && (
|
||||
<DialogPopup
|
||||
options={options}
|
||||
data={options_data}
|
||||
options_class={card.options_class}
|
||||
key={"popover" + card_index}
|
||||
id={"popover" + card_index}
|
||||
big={card.size === "big"}
|
||||
<OptionsDialogWrapper
|
||||
crate_index={crate_index}
|
||||
card_index={card_index}
|
||||
first={first}
|
||||
last={last}
|
||||
target={{
|
||||
construct: ((outvar, value) => {
|
||||
// console.log("construct", outvar, value, options_data);
|
||||
options_data[outvar] = value;
|
||||
}),
|
||||
update: ((outvar, value) => {
|
||||
// console.log("update", outvar, value, options_data);
|
||||
if (outvar in options_data) options_data[outvar] = value;
|
||||
onCardUpdate(crate_id, card_index, {[outvar]: value});
|
||||
})
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
@ -123,7 +102,7 @@ export function ProductCartItem({card_index, crate_index, ext_data, first, last}
|
||||
|
||||
{/* progression container */}
|
||||
{resources && (
|
||||
<Resources resources={resources}/>
|
||||
<Resources crate_index={crate_index} card_index={card_index} />
|
||||
)}
|
||||
|
||||
|
||||
|
@ -4,6 +4,8 @@ import {v4 as uuidv4} from "uuid";
|
||||
|
||||
// #!render_count
|
||||
import {useRenderCount} from "@uidotdev/usehooks";
|
||||
import {useShopStore} from "./shop_store";
|
||||
import {compareArraysLevelOne} from "./utils";
|
||||
|
||||
|
||||
const resourcesWidthStyle = (occupied, max) => {
|
||||
@ -64,9 +66,12 @@ function RenderResources({resources, library}) {
|
||||
return result;
|
||||
}
|
||||
|
||||
export function Resources({resources}) {
|
||||
export function Resources({crate_index, card_index}) {
|
||||
// #!render_count
|
||||
const renderCount = useRenderCount();
|
||||
|
||||
const resources = useShopStore(state => state.crates[crate_index].items[card_index].counted_resources, compareArraysLevelOne);
|
||||
|
||||
// #!render_count
|
||||
console.log("Resources renders: ", renderCount)
|
||||
return (
|
||||
|
@ -1,12 +1,13 @@
|
||||
import {formatMoney} from "./utils";
|
||||
import {compareObjectsEmptiness, formatMoney} from "./utils";
|
||||
import {WarningIndicator} from "./CardWarnings";
|
||||
import {SummaryPopup} from "./options/SummaryPopup";
|
||||
import React from "react";
|
||||
import {useShopStore} from "./shop_store";
|
||||
import {OptionsSummaryWrapper} from "./OptionsWrapper";
|
||||
|
||||
// #!render_count
|
||||
import {useRenderCount} from "@uidotdev/usehooks";
|
||||
|
||||
|
||||
export function SummaryCrateCard({crate_index, card_index}) {
|
||||
// #!render_count
|
||||
const renderCount = useRenderCount();
|
||||
@ -19,15 +20,17 @@ export function SummaryCrateCard({crate_index, card_index}) {
|
||||
const highlighted = useShopStore((state) => state.crates[crate_index].id === state.highlighted.crate && card_index === state.highlighted.card);
|
||||
const crate_id = useShopStore((state) => state.crates[crate_index].id);
|
||||
const card = useShopStore((state) => state.crates[crate_index].items[card_index],
|
||||
(a, b) => a.id === b.id && a.options_data === b.options_data && a.show_warnings === b.show_warnings);
|
||||
(a, b) => a.id === b.id);
|
||||
const card_show_warnings = useShopStore(state => state.crates[crate_index].items[card_index].show_warnings, compareObjectsEmptiness);
|
||||
const card_options_data = useShopStore(state => state.crates[crate_index].items[card_index].options_data, compareObjectsEmptiness);
|
||||
|
||||
// #!render_count
|
||||
console.log("SummaryCrateCard renders: ", renderCount)
|
||||
|
||||
|
||||
const options = card && card.options;
|
||||
const options_data = card && card.options_data;
|
||||
const warnings = card && card.show_warnings;
|
||||
const options = card && card.options && card.options.length > 0;
|
||||
const options_data = card_options_data && Object.keys(card_options_data).length > 0;
|
||||
const warnings = card_show_warnings && card_show_warnings.length > 0;
|
||||
|
||||
return (
|
||||
<tr
|
||||
@ -54,8 +57,8 @@ export function SummaryCrateCard({crate_index, card_index}) {
|
||||
|
||||
<div style={{'width': '45px', 'height': '20px'}}
|
||||
className="d-inline-flex align-content-center align-self-center justify-content-evenly">
|
||||
{(warnings && warnings.length > 0 ? (
|
||||
<WarningIndicator warnings={warnings}/>
|
||||
{(warnings ? (
|
||||
<WarningIndicator crate_index={crate_index} card_index={card_index}/>
|
||||
) : (
|
||||
<span style={{
|
||||
'display': 'inline-block',
|
||||
@ -63,8 +66,7 @@ export function SummaryCrateCard({crate_index, card_index}) {
|
||||
}}> </span>
|
||||
))}
|
||||
{((options && options_data) ? (
|
||||
<SummaryPopup id={card.id + "options"} options={options}
|
||||
data={options_data}/>
|
||||
<OptionsSummaryWrapper crate_index={crate_index} card_index={card_index}/>
|
||||
) : (
|
||||
<span style={{
|
||||
'display': 'inline-block',
|
||||
|
@ -17,7 +17,7 @@ export function validateJSON(description) {
|
||||
for (const crate of crates_raw) {
|
||||
if (!crate.type || !crate.items || !(crate.type in crate_modes)) return false;
|
||||
for (const card of crate.items) {
|
||||
if (!(card.pn in pn_to_card)) return false;
|
||||
if (!(card.pn in pn_to_card) || card.options === undefined) return false;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@ -36,7 +36,7 @@ export function JSONToCrates(description) {
|
||||
items: Array.from(crate.items.map((card, _i) => ({
|
||||
...pn_to_card(card.pn),
|
||||
id: uuidv4(),
|
||||
options_data: card.options
|
||||
options_data: card.options || {}
|
||||
}))),
|
||||
warnings: [],
|
||||
occupiedHP: 0,
|
||||
|
@ -5,6 +5,7 @@ import {data as shared_data, itemsUnfoldedList} from "./utils";
|
||||
import {true_type_of} from "./options/utils";
|
||||
import {v4 as uuidv4} from "uuid";
|
||||
import {FillResources} from "./count_resources";
|
||||
import {FillExtData} from "./options/utils";
|
||||
import {TriggerCrateWarnings, TriggerWarnings} from "./warnings";
|
||||
import {Validation, validateEmail, validateNote, validateJSONInput} from "./validate";
|
||||
import {CratesToJSON, JSONToCrates} from "./json_porter";
|
||||
@ -67,10 +68,17 @@ const useImportJSON = ((set, get) => ({
|
||||
closeImport: () => set(state => ({
|
||||
importShouldOpen: false
|
||||
})),
|
||||
loadDescription: () => set(state => ({
|
||||
_loadDescription: () => set(state => ({
|
||||
importShouldOpen: false,
|
||||
crates: JSONToCrates(state.importValue.value)
|
||||
})),
|
||||
loadDescription: () => {
|
||||
get()._loadDescription()
|
||||
get().crates.forEach((crate, _i) => {
|
||||
get().fillExtData(crate.id)
|
||||
get().fillWarnings(crate.id)
|
||||
})
|
||||
},
|
||||
updateImportDescription: (new_description) => set(state => ({
|
||||
importValue: {
|
||||
value: new_description,
|
||||
@ -254,14 +262,12 @@ const useCart = ((set, get) => ({
|
||||
return {
|
||||
crates: state.crates.map((crate, _i) => {
|
||||
if (crate_to === crate_from && crate_to === crate.id) {
|
||||
// TODO fix
|
||||
//const the_card = {...crate[index_from]};
|
||||
let items_copy = Array.from(crate.items);
|
||||
delete items_copy[index_from];
|
||||
console.log(crate_from, index_from, crate_to, index_to, items_copy.toSpliced(index_to+1, 0, the_card).filter((item, _) => !!item))
|
||||
let item = items_copy.splice(index_from, 1)[0]
|
||||
items_copy.splice(index_to, 0, item).filter((item, _) => !!item)
|
||||
return {
|
||||
...crate,
|
||||
items: items_copy.toSpliced(index_to+1, 0, {...the_card}).filter((item, _) => !!item)
|
||||
items: items_copy
|
||||
}
|
||||
} else if (crate_to === crate.id) {
|
||||
return {
|
||||
@ -341,6 +347,26 @@ const useCart = ((set, get) => ({
|
||||
})
|
||||
})),
|
||||
|
||||
fillExtData: (crate_id) => set(state => ({
|
||||
crates: state.crates.map((crate, _i) => {
|
||||
if (crate_id === crate.id) {
|
||||
let itemsCopy = Array.from(crate.items);
|
||||
|
||||
itemsCopy = itemsCopy.map((item, index) => {
|
||||
if (!item.options) return item;
|
||||
if (!item.options_data) item.options_data = {};
|
||||
item.options_data.ext_data = FillExtData(itemsCopy, index);
|
||||
return item;
|
||||
});
|
||||
return {
|
||||
...crate,
|
||||
items: Array.from(itemsCopy)
|
||||
}
|
||||
}
|
||||
else return crate;
|
||||
})
|
||||
})),
|
||||
|
||||
totalOrderPrice: () => {
|
||||
let sum = 0;
|
||||
get().crates.forEach( (crate, _i) => {
|
||||
@ -357,11 +383,13 @@ const useCart = ((set, get) => ({
|
||||
newCrate: () => {
|
||||
const crate_id = "crate" + get().crates.length;
|
||||
get()._newCrate(crate_id)
|
||||
get().fillExtData(crate_id);
|
||||
get().fillWarnings(crate_id);
|
||||
},
|
||||
|
||||
setCrateMode: (id, mode) => {
|
||||
get()._setCrateMode(id, mode)
|
||||
get().fillExtData(crate_id);
|
||||
get().fillWarnings(id);
|
||||
get().setActiveCrate(id);
|
||||
},
|
||||
@ -370,6 +398,7 @@ const useCart = ((set, get) => ({
|
||||
const dest = crate_to || get().active_crate;
|
||||
if (!dest) return {};
|
||||
get()._addCardFromBacklog(dest, index_from, index_to)
|
||||
get().fillExtData(dest);
|
||||
get().fillWarnings(dest);
|
||||
get().setActiveCrate(dest);
|
||||
if (!just_mounted) {
|
||||
@ -379,12 +408,17 @@ const useCart = ((set, get) => ({
|
||||
|
||||
moveCard: (crate_from, index_from, crate_to, index_to) => {
|
||||
get()._moveCard(crate_from, index_from, crate_to, index_to);
|
||||
get().fillExtData(crate_to);
|
||||
get().fillWarnings(crate_to);
|
||||
get().setActiveCrate(crate_to);
|
||||
if (crate_from !== crate_to) get().fillWarnings(crate_from);
|
||||
if (crate_from !== crate_to) {
|
||||
get().fillExtData(crate_from);
|
||||
get().fillWarnings(crate_from);
|
||||
}
|
||||
},
|
||||
deleteCard: (crate_id, index) => {
|
||||
get()._deleteCard(crate_id, index);
|
||||
get().fillExtData(crate_id);
|
||||
get().fillWarnings(crate_id);
|
||||
if (crate_id === get().highlighted.crate && index === get().highlighted.card) get().highlightReset()
|
||||
},
|
||||
@ -395,6 +429,7 @@ const useCart = ((set, get) => ({
|
||||
|
||||
updateOptions: (crate_id, index, new_options) => {
|
||||
get()._updateOptions(crate_id, index, new_options);
|
||||
get().fillExtData(crate_id);
|
||||
get().fillWarnings(crate_id);
|
||||
}
|
||||
}))
|
||||
|
@ -63,3 +63,32 @@ export const range = (start, end) => {
|
||||
const length = end - start;
|
||||
return Array.from({ length }, (_, i) => start + i);
|
||||
}
|
||||
|
||||
|
||||
export const move = (source, destination, droppableSource, droppableDestination) => {
|
||||
console.log('==> move', source, destination);
|
||||
const sourceClone = Array.from(source);
|
||||
const destClone = Array.from(destination);
|
||||
const [removed] = sourceClone.splice(droppableSource.index, 1);
|
||||
|
||||
destClone.splice(droppableDestination.index, 0, removed);
|
||||
|
||||
const result = {columns: {}};
|
||||
result.columns[droppableSource.droppableId] = sourceClone;
|
||||
result.columns[droppableDestination.droppableId] = destClone;
|
||||
|
||||
return result;
|
||||
};
|
||||
|
||||
export const compareArraysWithIds = (a, b) =>
|
||||
a.length === b.length &&
|
||||
a.every((element, index) => element.id === b[index].id);
|
||||
|
||||
export const compareArraysLevelOne = (a, b) =>
|
||||
a.length === b.length &&
|
||||
a.every((element, index) => element === b[index]);
|
||||
|
||||
export function compareObjectsEmptiness(a, b) {
|
||||
return (!a && !b) || (!(!a !== !b) && Object.getPrototypeOf(a) === Object.getPrototypeOf(b) &&
|
||||
(Object.getPrototypeOf(a) !== Object.getPrototypeOf([]) || !!Object.keys(a).length === !!Object.keys(b).length))
|
||||
}
|
@ -20,7 +20,7 @@ module.exports = {
|
||||
options: {
|
||||
debug: false,
|
||||
directives: {
|
||||
render_count: true,
|
||||
render_count: false,
|
||||
},
|
||||
params: {
|
||||
ENV: process.env.NODE_ENV,
|
||||
|
Loading…
Reference in New Issue
Block a user