I'm using highcharts-react-official (v. ^3.1.0)
for drawing org-chart, but I have a problem with rounding the links between nodes (some specific nodes).
I want to change the linkRadius property for only the end corners[Please check the attached image].
const initialTree = [
{ from: 'block1', to: 'block2'},
{ from: 'block1', to: 'block3' },
{ from: 'block1', to: 'block4' },
],
const [treeOptions, updateTreeOptions] = useState({
chart: {
height: expandAllCards && treeType === 'BRAND_SUITABILITY' ? 545 : 325,
width: expandAllCards ? HTREE_WIDTH[treeType].expandAll : HTREE_WIDTH[treeType].collapsed,
inverted: true,
spacing: [0, 0, 0, 0],
marginTop: -82,
marginLeft: expandAllCards && treeType === 'BRAND_SUITABILITY' ? 25 : undefined,
marginRight: expandAllCards && treeType === 'BRAND_SUITABILITY' ? 25 : undefined,
animation: false,
},
exporting: {
enabled: false,
},
credits: {
enabled: false,
},
title: {
text: null,
},
series: [
{
type: 'organization',
name: 'Highsoft',
keys: ['from', 'to'],
borderRadius: 0,
nodePadding: 0,
borderWidth: 0,
linkRadius: 0,
minNodeLength: 106,
nodeWidth: 188,
linkColor: '#e8e9eb',
data: [...initialTree],
marker: {
radius: 10,
},
levels: [
{
level: 0,
color: 'none',
linkColor: '#b3b3b3',
},
{
level: 1,
linkColor: 'transparent',
color: 'none',
},
{
level: 2,
color: 'none',
},
],
colorByPoint: false,
color: '#007ad0',
events: {
click: (
e: ChartClickEventObject & {
point: {
id: string | number;
linksFrom: string[];
reportURL: string;
name: string;
incidents: number;
dashboardId: string;
treeType: TreeType;
schemaName: string;
slideOutAlias: string;
};
path: Array<{ id: string }>;
},
) => {
if (!e || !e.point) return;
const clickType = (() => {
const isCorrectClick = e.composedPath && typeof e.composedPath === 'function';
if (!isCorrectClick) return;
if (e.composedPath()?.some((el: Element) => el.id === `node-toggle-${e.point.id}`)) return 'toggle';
if (e.composedPath()?.some((el: Element) => el.id === `node-incidents-${e.point.id}`))
return 'incidents-slideout';
})();
if (!clickType) return;
const {
// eslint-disable-next-line #typescript-eslint/no-shadow
point: { id, linksFrom, reportURL, name, treeType: currentTreeType, schemaName, slideOutAlias = '' },
} = e;
if (!currentTreeType) return;
const currentFullTreeConnections = Connections[TreeTypeProps[currentTreeType].connectionsId];
const currentInitialTree = currentFullTreeConnections.filter(
object => object.from === TreeTypeProps[currentTreeType].rootId,
);
switch (clickType) {
case 'toggle': {
if (linksFrom.length === 0) {
const updatedConnections = [
...currentInitialTree,
...currentFullTreeConnections.filter(connection => connection.from === id),
];
const updatedTreeOptionsState = {
...treeOptions,
chart: {
...treeOptions.chart,
height: 544,
width: HTREE_WIDTH[currentTreeType].expanded,
},
series: [
{
...treeOptions.series[0],
data: updatedConnections,
levels: [
...treeOptions.series[0].levels,
{
level: 1,
linkColor: '#b3b3b3',
color: 'none',
},
],
},
],
};
updateTreeOptions(updatedTreeOptionsState);
} else {
const updatedTreeOptionsState = {
...treeOptions,
chart: {
...treeOptions.chart,
height: 325,
width: HTREE_WIDTH[currentTreeType].collapsed,
},
series: [
{
...treeOptions.series[0],
data: currentInitialTree,
levels: [
...treeOptions.series[0].levels,
{
level: 1,
linkColor: 'transparent',
color: 'none',
},
],
},
],
};
updateTreeOptions(updatedTreeOptionsState);
}
sendVisualizationManipulation({
alias: slideOutAlias,
params: {
height:
linksFrom.length === 0
? VisualizationManipulationChangeHeight.expand
: VisualizationManipulationChangeHeight.collapse,
},
});
break;
}
case 'incidents-slideout': {
if (reportURL === '' || !reportURL) break;
SlideOut.open({
targetId: reportURL,
title: [`${name} ${SCHEMA_TYPES.get(schemaName)}`],
});
break;
}
default:
break;
}
},
},
dataLabels: {
padding: 0,
borderWidth: 0,
color: '#fff',
nodeFormatter: function nodeFormatterFn() {
// eslint-disable-next-line react/no-this-in-sfc
if (!this.point) return null;
// eslint-disable-next-line react/no-this-in-sfc
const { options, level, id, linksFrom } = this.point;
const currentTreeType = options.treeType as TreeType;
if (!currentTreeType) return null;
const isRoot = level === 0;
const isOtherCard = id === 'OTHER';
const { connectionsId } = TreeTypeProps[currentTreeType];
const hasChildren = Connections[connectionsId].find(object => object.from === id);
const isCollapsible = !isRoot && hasChildren;
const reportURLExists = !!options.reportURL && options.reportURL !== '';
let arrowColor;
const isRateChangeValid = (options.rateChange && +options.rateChange !== 0) || undefined;
if (Number(options.rateChange || 0) === 0) {
arrowColor = ARROW_GRAY_COLOR;
} else {
arrowColor =
+options.rateChange * (options.positiveValues ? -1 : 1) > 0
? ARROW_NEGATIVE_COLOR
: ARROW_POSITIVE_COLOR;
}
const cardTree = (
<MainTreeCard
border={`1px solid ${isRoot ? options.rootBorderColor : options.generalBorderColor}`}
borderLeft={`4px solid ${options.borderLeftColor}`}
width={`${options.width}px`}
height={`${options.height}px`}
backgroundColor={options.bgColor}
padding={isRoot ? '7px 9px 14px 10px' : '11px 7px 8px 10px'}>
<TopLabel
fontSize={`${options.fontSize}px}`}
letterSpacing={!isRoot ? '0.25px' : 'normal'}
// eslint-disable-next-line no-nested-ternary
marginBottom={isRoot ? '19px' : isOtherCard ? '16px' : '17px'}
lineHeight={isRoot ? '22px' : '18px'}
height={`${options.labelHeight}px}`}>
{options.name}
</TopLabel>
<FlexContainer
flexDirection={isRoot ? 'row' : 'column'}
height={isRoot ? '45px' : ''}
justifyContent='space-between'>
<FlexContainer
flexDirection='column'
justifyContent='flex-start'
paddingLeft={isRoot ? '2px' : ''}
marginBottom={!isRoot ? '12px' : ''}>
<TopValueLabel
id={`node-incidents-${id}`}
fontSize={`${!isOtherCard ? options.fontSizeIncidents : 12}px`}
fontWeight={!isOtherCard ? '400' : '700'}
marginBottom={isRoot ? '0' : '5px'}
lineHeight={isRoot ? '31px' : '17px'}
letterSpacing={isOtherCard ? '0.2px' : 'normal'}
color={reportURLExists ? '#7740bf' : '#14113b'}
cursor={reportURLExists ? 'pointer' : 'auto'}
isLinked={reportURLExists ? 1 : 0}>
{!isOtherCard ? formatNumber(options.incidents, options.incidentsType) : 'View Report'}
</TopValueLabel>
{!isOtherCard && (
<TopMeasureLabel
marginTop={isRoot ? '0' : '-3px'}
lineHeight={isRoot ? '12px' : 'normal'}
letterSpacing={isRoot ? '0.2px' : 'normal'}>
{options.amountLabel}
</TopMeasureLabel>
)}
</FlexContainer>
{!isOtherCard && (
<FlexContainer flexDirection='row' width={isRoot ? '102px' : '82px'} justifyContent='space-between'>
<FlexContainer flexDirection='column'>
<TopSecondValueLabel
fontSize={!isRoot ? '20px' : '28px'}
lineHeight={isRoot ? '31px' : '17px'}
marginBottom={isRoot ? 0 : '2px'}>
{formatNumber(options.incidentRate, options.incidentRateType)}
</TopSecondValueLabel>
<TopMeasureLabel
marginTop='0'
letterSpacing={isRoot ? '0.2px' : 'normal'}
lineHeight={isRoot ? '12px' : 'normal'}>
{options.rateLabel}
</TopMeasureLabel>
</FlexContainer>
<FlexContainer justifyContent='center' alignSelf='end'>
<FlexContainer flexDirection='column' marginBottom='1px'>
{/* eslint-disable-next-line no-nested-ternary */}
{isRateChangeValid ? (
+options.rateChange > 0 ? (
<ICONS.ARROW_UP
width={11}
height={6}
marginTop='3px'
marginRight='2px'
fill={arrowColor}
/>
) : (
<ICONS.ARROW_DOWN
width={11}
height={6}
marginTop='3px'
marginRight='2px'
fill={arrowColor}
/>
)
) : null}
</FlexContainer>
<ChangeRateLabel color={arrowColor}>
{getFormattedChangeRateLabel(options.rateChange, false)}
</ChangeRateLabel>
</FlexContainer>
</FlexContainer>
)}
</FlexContainer>
{isCollapsible && hasChildren && !options.expandAllCards && (
<ToggleLabel id={`node-toggle-${id}`} marginLeft={isRoot ? '7px' : 0}>
{linksFrom.length === 0 ? (
<>
See More
<Arrow
rotate='rotate(45deg)'
position='relative'
borderWidth='0 2px 2px 0'
left='6px'
bottom='2px'
/>
</>
) : (
<>
See Less
<Arrow
position='relative'
borderWidth='0 2px 2px 0'
top='2px'
left='1px'
marginLeft='5px'
rotate='rotate(-135deg)'
/>
</>
)}
</ToggleLabel>
)}
</MainTreeCard>
);
return ReactDOMServer.renderToString(cardTree);
},
},
},
],
tooltip: {
enabled: false,
},
});
I've tried to change the linkRadius property, but it has changed all the links radius.
Any suggestions how I can do it ?
Thanks !
First of all, the linkRadius option is deprecated, you should use link.radius. However, Highcharts API only allows setting the same radius for all of the links. To set the radius individually, you need to modify Highcharts core, for example by the below plugin:
(function(H) {
H.wrap(H.seriesTypes.organization.prototype, 'translateLink', function(proceed, point) {
if (point.from === 'CSO') {
const linkOptions = this.options.link;
const originalRadius = linkOptions.radius;
// set custom radius for a specific point
linkOptions.radius = 0;
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
// restore the original option
linkOptions.radius = originalRadius;
} else {
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
}
});
}(Highcharts));
Live demo: https://jsfiddle.net/BlackLabel/zdxe7423/
API Reference: https://api.highcharts.com/highcharts/series.organization.link.radius
Docs: https://www.highcharts.com/docs/extending-highcharts/extending-highcharts
I am having problems using this plug with events that are triggered from the batch url. The plugin is as follows:
Cypress.Commands.add('eventCall' , function ({
alias = 'postEvent',
name,
event,
properties = {},
} = {})
const eventType = event ? 'track' : 'page';
const url =
eventType === 'track'
? 'https://api.segment.io/v1/t'
: 'https://api.segment.io/v1/batch';
const propertyNames = Object.keys(properties);
cy.wrap(alias).as('eventAlias');
if (propertyNames.length > 0) {
cy.wrap(propertyNames).as(`${alias}PropertyNames`);
cy.wrap(properties).as(`${alias}ExpectedProperties`);
cy.wrap({}).as(`${alias}ActualProperties`);
}
cy.intercept('POST', url, (req) => {
const requestBody = JSON.parse(req.body);
if (
(eventType === 'track' && requestBody.event === event) ||
(eventType === 'page' && requestBody.name === name) ||
(eventType === 'page' && !name)
) {
req.alias = alias;
if (propertyNames.length > 0) {
this[`${alias}ActualProperties`] = requestBody.properties;
}
}
});
});
the type of event I am trying to validate is the following:
analytics.track({
anonymousId: '123213123',
userId: '10000000000111111',
event: 'EVENT NUMBER1',
properties: {
cart_id: '4069313',
name: 'aaa',
price: 0,
product_id: '1234'
}
});
And in Cypress I am trying to access as follows:
cy.SegmentCall({
event: 'EVENT NUMBER1',
properties: {
cart_id: '4069313',
name: 'aaa',
price: 0,
product_id: '1234'
},
});
});
But I can't get it to work. Does anyone have any idea
This code is inside a .vue file. Receiving the "Error: Table has no columns." Inside the methods function, it won't receive the values from firebase to display a chart/graph to web app. What am I doing incorrectly? I think the values am I trying to receive inside "chartData:[ ]" or "mounted()" is incorrect and may be causing the issue. Any help is much appreciated.
export default {
name: "App",
components: {
GChart
},
methods: {
getHumidity(){
get(
query(ref(db, auth.currentUser.uid + "/Environment/humidity"),
orderByChild("humidity")
)
).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
for (const item in snapshot.val()) {
this.pgoods.push({
humidity: snapshot.val()[item].humidity,
expir: snapshot.val()[item].humidity,
});
}
} else {
this.pgoods = [];
}
return float(snapshot.val());
});
}
getPressure(){
get(
query(ref(db, auth.currentUser.uid + "/Environment/pressure"),
orderByChild("pressure")
)
).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
for (const item in snapshot.val()) {
this.pgoods.push({
pressure: snapshot.val()[item].pressure,
expir: snapshot.val()[item].pressure,
});
}
} else {
this.pgoods = [];
}
return float(snapshot.val());
});
}
getTime(){
get(
query(ref(db, auth.currentUser.uid + "/Environment/time"),
orderByChild("time")
)
).then((snapshot) => {
if (snapshot.exists()) {
console.log(snapshot.val());
for (const item in snapshot.val()) {
this.pgoods.push({
time: snapshot.val()[item].time,
expir: snapshot.val()[item].time,
});
}
} else {
this.pgoods = [];
}
return float(snapshot.val());
});
},
},
data(){
return{
chartData: [
["Time", "Pressure", "Humidity"],
[this.getTime(), this.getPressure(), this.getHumidity()],
[this.getTime(), this.getPressure(), this.getHumidity()],
],
},
mounted(){
this.getTemperature();
this.getHumidity();
},
}
Hello this is my first time. I have problem with like that I have 3000 items and I use framework like vue, element-ui and meteor. I pull all the items through a remote el-select that selects to add more remote select array object.I don't know why it slow performance and crush.
This is my picture
// Find item opts method
_getItemOpts(query, type) {
type = type || 'remote'
let exp = new RegExp(query)
let selector = {}
if (exp) {
selector = {
itemType: { $ne: 'Bundle' },
// , 'Sale'
activityType: { $in: ['Purchase'] },
status: 'Active',
$or: [
{ name: { $regex: exp, $options: 'i' } },
{ refNo: { $regex: exp, $options: 'i' } },
{ barcode: { $regex: exp, $options: 'i' } },
],
}
}
// Find item
findItems
.callPromise({ selector: selector })
.then(result => {
// console.log(result)
if (type == 'remote') {
this.itemOpts = result
}
this.loading = false
})
.catch(err => {
this.loading = false
Notify.error({ message: err })
})
},
Please help me.
Well no magick is here. U tryin to add to DOM 3000 of elements, so no wonder its crashes. Try to narrow results, for example show them only when user enters 3 letters
Hello I have problem compute vue filter by category it work not properly when I add item on Service tab and then click on Medicine tab remote search item by category it will stuck and filter not work and when I click in Service tab back it show only number 2.
this my template
<el-table
:data="itemFilters"
row-key="no"
style="width: 100%"
>
This my script
computed: {
itemFilters() {
const self = this
let item = self.form.items.filter(o => {
return o.categoryName === self.tabActive || o.itemId === ''
})
return item
},
},
this Method
methods: {
_getItemOpts(query, type) {
let exp = new RegExp(query)
let selector = {
$or: [
{ name: { $regex: exp, $options: 'i' } },
{ refNo: { $regex: exp, $options: 'i' } },
{ barcode: { $regex: exp, $options: 'i' } },
],
activityType: { $in: ['Sale'] },
status: 'Active',
'catDoc.name': this.tabActive,
}
// For form Sale Return and receipts refund
if (this.formName == 'Sale_Return' || this.formName == 'Receipt_Refund') {
selector.itemType = { $ne: 'Bundle' }
}
findItems
.callPromise({ selector: selector })
.then(result => {
// this.itemOpts = result
if (type == 'remote') {
// For remote
this.form.items[this.activeIndex].itemOpts = result
} else {
// For scan barcode
let item = result[0]
if (item) {
let row = {
itemId: item._id,
itemType: item.itemType,
memo: '',
qty: 1,
qtyRate: 1,
unitId: item.units[0].unitId,
units: item.units,
price: item.price,
amountBeforeDiscount: item.price,
discountRate: 0,
discountValue: 0,
amountAfterDiscount: item.price,
taxId: '',
taxAmount: 0,
// For expand bundle item
subItems: [],
expand: 'expand',
// For sales only(cash sales and invoice)
// refSaleOrderId: '',
// refSaleOrderDetailId: '',
// refNo: '',
itemOpts: result,
}
this.form.items.push(row)
} else {
Notify.warning({ message: 'This item do not set barcode!' })
}
}
this.loading = false
})
.catch(err => {
this.loading = false
this.$notify.error(err.reason)
})
},
}
Please help...