Does Vue Cli 4.4.6 scaffold ES2020 into the project - vue.js

If I run vue create my-new-app using the latest Vue Cli (currently version 4.4.6) will all the new ES2020 features be implemented? (I've tested "optional chaining" and seem to be able to use that)
If so, how can I tell from the scaffolded code? I'm seeing #vue/cli-plugin-babel/preset in babel.config.js, does that do it?
I believe ES2020 has been officially completed. Let me know if that's incorrect.

The Babel plugins indeed allow compilation of ES2020 features. You can view which plugins are in use by enabling debug before running the build:
// babel.config.js
module.exports = {
presets: [
// BEFORE:
// '#vue/cli-plugin-babel/preset'
['#vue/cli-plugin-babel/preset', { debug: true }]
]
}
The debug output will look like this:
⠇ Building for production...#babel/preset-env: `DEBUG` option
Using targets:
{
"android": "81",
"chrome": "80",
"edge": "18",
"firefox": "76",
"ie": "11",
"ios": "12.2",
"opera": "67",
"safari": "13",
"samsung": "10.1"
}
Using modules transform: false
Using plugins:
proposal-nullish-coalescing-operator { "edge":"18", "ie":"11", "ios":"12.2", "safari":"13", "samsung":"10.1" }
proposal-optional-chaining { "edge":"18", "ie":"11", "ios":"12.2", "safari":"13", "samsung":"10.1" }
proposal-json-strings { "edge":"18", "ie":"11" }
proposal-optional-catch-binding { "edge":"18", "ie":"11" }
transform-parameters { "ie":"11" }
proposal-async-generator-functions { "edge":"18", "ie":"11" }
proposal-object-rest-spread { "edge":"18", "ie":"11" }
transform-dotall-regex { "edge":"18", "firefox":"76", "ie":"11" }
proposal-unicode-property-regex { "edge":"18", "firefox":"76", "ie":"11" }
transform-named-capturing-groups-regex { "edge":"18", "firefox":"76", "ie":"11" }
transform-async-to-generator { "ie":"11" }
transform-exponentiation-operator { "ie":"11" }
transform-template-literals { "ie":"11", "ios":"12.2" }
transform-literals { "ie":"11" }
transform-function-name { "edge":"18", "ie":"11" }
transform-arrow-functions { "ie":"11" }
transform-classes { "ie":"11" }
transform-object-super { "ie":"11" }
transform-shorthand-properties { "ie":"11" }
transform-duplicate-keys { "ie":"11" }
transform-computed-properties { "ie":"11" }
transform-for-of { "ie":"11" }
transform-sticky-regex { "ie":"11" }
transform-unicode-escapes { "ie":"11" }
transform-unicode-regex { "ie":"11" }
transform-spread { "ie":"11" }
transform-destructuring { "ie":"11" }
transform-block-scoping { "ie":"11" }
transform-typeof-symbol { "ie":"11" }
transform-new-target { "ie":"11" }
transform-regenerator { "ie":"11" }
syntax-dynamic-import { "android":"81", "chrome":"80", "edge":"18", "firefox":"76", "ie":"11", "ios":"12.2", "opera":"67", "safari":"13", "samsung":"10.1" }
syntax-top-level-await { "android":"81", "chrome":"80", "edge":"18", "firefox":"76", "ie":"11", "ios":"12.2", "opera":"67", "safari":"13", "samsung":"10.1" }
Using polyfills with `usage` option:
⠏ Building for production...
[/Users/tony/src/tmp/vue-tmp7/src/main.js] Based on your code and targets, core-js polyfills were not added.
⠴ Building for production...#babel/preset-env: `DEBUG` option
Using targets:
{
"android": "81",
"chrome": "80",
"edge": "18",
"firefox": "76",
"ie": "11",
"ios": "12.2",
"opera": "67",
"safari": "13",
"samsung": "10.1"
}
Using modules transform: false
Using plugins:
proposal-nullish-coalescing-operator { "edge":"18", "ie":"11", "ios":"12.2", "safari":"13", "samsung":"10.1" }
proposal-optional-chaining { "edge":"18", "ie":"11", "ios":"12.2", "safari":"13", "samsung":"10.1" }
proposal-json-strings { "edge":"18", "ie":"11" }
proposal-optional-catch-binding { "edge":"18", "ie":"11" }
transform-parameters { "ie":"11" }
proposal-async-generator-functions { "edge":"18", "ie":"11" }
proposal-object-rest-spread { "edge":"18", "ie":"11" }
transform-dotall-regex { "edge":"18", "firefox":"76", "ie":"11" }
proposal-unicode-property-regex { "edge":"18", "firefox":"76", "ie":"11" }
transform-named-capturing-groups-regex { "edge":"18", "firefox":"76", "ie":"11" }
transform-async-to-generator { "ie":"11" }
transform-exponentiation-operator { "ie":"11" }
transform-template-literals { "ie":"11", "ios":"12.2" }
transform-literals { "ie":"11" }
transform-function-name { "edge":"18", "ie":"11" }
transform-arrow-functions { "ie":"11" }
transform-classes { "ie":"11" }
transform-object-super { "ie":"11" }
transform-shorthand-properties { "ie":"11" }
transform-duplicate-keys { "ie":"11" }
transform-computed-properties { "ie":"11" }
transform-for-of { "ie":"11" }
transform-sticky-regex { "ie":"11" }
transform-unicode-escapes { "ie":"11" }
transform-unicode-regex { "ie":"11" }
transform-spread { "ie":"11" }
transform-destructuring { "ie":"11" }
transform-block-scoping { "ie":"11" }
transform-typeof-symbol { "ie":"11" }
transform-new-target { "ie":"11" }
transform-regenerator { "ie":"11" }
syntax-dynamic-import { "android":"81", "chrome":"80", "edge":"18", "firefox":"76", "ie":"11", "ios":"12.2", "opera":"67", "safari":"13", "samsung":"10.1" }
syntax-top-level-await { "android":"81", "chrome":"80", "edge":"18", "firefox":"76", "ie":"11", "ios":"12.2", "opera":"67", "safari":"13", "samsung":"10.1" }
Using polyfills with `usage` option:
[/Users/tony/src/tmp/vue-tmp7/src/App.vue] Based on your code and targets, core-js polyfills were not added.
⠧ Building for production...
[/Users/tony/src/tmp/vue-tmp7/src/components/HelloWorld.vue] Based on your code and targets, core-js polyfills were not added.
Tested with Node 14, Vue CLI 4.4.6, and #babel/preset-env 7.10.3 on macOS Catalina
ES2020 features supported as of Vue CLI 4.4.6
optional chaining
nullish coalescing
Promise.prototype.allSettled
String.prototype.matchAll
private class fields
dynamic imports enhancement
BigInt - might require an ESLint config to avoid a lint error when using the constructor

Related

mongodb aggregation - setting the contents of array as input, while storing sibling keys

I'm in the middle of an aggregation pipeline when I have the following data passed from the previous step as input to a "count all leaves in all branches/trees/forests" as indicated in this question: Need guidance on mongo aggregate lookup to count subnodes in all child nodes for each node
{
forest_ranger: "bob",
some_other_data: {},
forests: [
{
forest_id: 'forestA',
trees: [
{
tree_id: 'treeA',
branches: [
{
branch_id: 'branchA',
}
]
}
]
}
],
}
I have that all working properly, but only if I'm reading directly from a collection.
My question is - how can I
a) save forest_ranger and some_other_data "for later"
b) and start the next stage by mapping forests as the array of
documents that are input to the "count all leaves"?
Note - I tried to get just (b) working for starters, but I can't seem to treat "forests" as an array so that the solution in the link above can do its magic.
Then- when that phase is done, extract what was stored in (a) to get the original format back with all the counts.
That is the main disadvantage of using $group. You have to explicitly carry forward every non participating fields using either $first or $last like this:
Get the test data with those additional fields from this new MongoPlayground link.
Check the updated query taken from the link:
db.Forests.aggregate([
{ $unwind: "$forests" },
{ $unwind: "$forests.trees" },
{ $unwind: "$forests.trees.branches" },
{
$lookup: {
from: "Leaves",
localField: "forests.trees.branches.branch_id",
foreignField: "branch_id",
as: "forests.trees.branches.leaves"
}
},
{
$addFields: {
"forests.trees.branches.leaf_count": { $size: "$forests.trees.branches.leaves" }
}
},
{
$project: { "forests.trees.branches.leaves": 0 }
},
{
$group: {
_id: {
forest_id: "$forests.forest_id",
tree_id: "$forests.trees.tree_id"
},
forest_ranger: { $first: "$forest_ranger" },
some_other_data: { $first: "$some_other_data" },
leaf_count: { $sum: "$forests.trees.branches.leaf_count" },
branches: { $push: "$forests.trees.branches" }
}
},
{
$group: {
_id: "$_id.forest_id",
forest_ranger: { $first: "$forest_ranger" },
some_other_data: { $first: "$some_other_data" },
leaf_count: { $sum: "$leaf_count" },
trees: {
$push: {
leaf_count: { $sum: "$leaf_count" },
tree_id: "$_id.tree_id",
branches: "$branches"
}
}
}
},
{
$group: {
_id: null,
forest_ranger: { $first: "$forest_ranger" },
some_other_data: { $first: "$some_other_data" },
leaf_count: { $sum: "$leaf_count" },
forests: {
$push: {
leaf_count: { $sum: "$leaf_count" },
forest_id: "$_id",
trees: "$trees"
}
}
}
},
{
$project: { _id: 0 }
}
])
Output:
{
"forest_ranger" : "bob",
"some_other_data" : {
"data" : "Dummy data"
},
"leaf_count" : 4,
"forests" : [
{
"leaf_count" : 3,
"forest_id" : "forestA",
"trees" : [
{
"leaf_count" : 1,
"tree_id" : "treeB",
"branches" : [
{
"branch_id" : "branchB",
"leaf_count" : 1
}
]
},
{
"leaf_count" : 2,
"tree_id" : "treeA",
"branches" : [
{
"branch_id" : "branchA",
"leaf_count" : 1
},
{
"branch_id" : "branchA1",
"leaf_count" : 1
},
{
"branch_id" : "branchA2",
"leaf_count" : 0
}
]
}
]
},
{
"leaf_count" : 1,
"forest_id" : "forestB",
"trees" : [
{
"leaf_count" : 0,
"tree_id" : "treeD",
"branches" : [
{
"branch_id" : "branchD",
"leaf_count" : 0
}
]
},
{
"leaf_count" : 1,
"tree_id" : "treeC",
"branches" : [
{
"branch_id" : "branchC",
"leaf_count" : 1
}
]
}
]
},
{
"leaf_count" : 0,
"forest_id" : "forestC",
"trees" : [
{
"leaf_count" : 0,
"tree_id" : "treeE",
"branches" : [
{
"branch_id" : "branchE",
"leaf_count" : 0
}
]
}
]
}
]
}

How to load prefixed json files in i18next?

My project is working well with i18next library. This is my files working:
i18n/index.js
import i18n from 'i18next';
// import LanguageDetector from 'i18next-browser-languagedetector';
import pt from './locales/pt/common.json';
import en from './locales/en/common.json';
const options = {
interpolation: { escapeValue: false },
lng: 'en',
resources: {
pt: {
common: pt,
},
en: {
common: en,
},
},
fallbackLng: 'pt',
ns: ['common'],
defaultNS: 'common',
react: {
wait: true,
},
};
i18n.init(options);
export default i18n;
i18n/locales/en/common.json
"editor": {
"sidebar": {
"header": {
...
}
}
}
i18n/locales/pt/common.json
"editor": {
"sidebar": {
"header": {
...
}
}
}
However, I need to prefix my json files with en and pt-BR. This way, my project stop working. Does anyone have a simple solution?
i18n/locales/en/common.json
"en" {
"editor": {
"sidebar": {
"header": {
...
}
}
}
}
i18n/locales/pt/common.json
"pt-BR" {
"editor": {
"sidebar": {
"header": {
...
}
}
}
}
I posted this question on Gitbub and #jamuhl answered. His solution is:
resources: {
pt: {
common: pt[pt-BR],
},
en: {
common: en.en,
},
},

Creating a custom rally list from source using app-catalog on github

I am trying to use the Rally App Catalog and the custom list app
I would like to add an additional selector (item type) and rename some of the headers on the fly. First I just want the sample to run. As it currently stands, it looks broken to me.
When I use the rally-app-builder build function and then paste the result app.html into a custom app I get a blank page with working app settings.
Here the uncompressed version from my initial attempt.
<script src="https://rally1.rallydev.com/apps/2.1/sdk-debug.js"></script>
<!DOCTYPE html>
<html>
<head>
<title>Custom List</title>
<script type="text/javascript" src="/apps/2.1/sdk.js"></script>
<script type="text/javascript">
Rally.onReady(function() {
(function() {
var Ext = window.Ext4 || window.Ext;
var getHiddenFieldConfig = function(name) {
return {
name: name,
xtype: 'rallytextfield',
hidden: true,
handlesEvents: {
typeselected: function(type) {
this.setValue(null);
}
}
};
};
Ext.define('Rally.apps.customlist.Settings', {
singleton: true,
requires: [
'Rally.ui.combobox.FieldComboBox',
'Rally.ui.combobox.ComboBox',
'Rally.ui.CheckboxField'
],
getFields: function(app) {
this.app = app;
return [{
name: 'type',
xtype: 'rallycombobox',
allowBlank: false,
autoSelect: false,
shouldRespondToScopeChange: true,
context: this.app.getContext(),
initialValue: 'HierarchicalRequirement',
storeConfig: {
model: Ext.identityFn('TypeDefinition'),
sorters: [{
property: 'DisplayName'
}],
fetch: ['DisplayName', 'ElementName', 'TypePath', 'Parent', 'UserListable'],
filters: [{
property: 'UserListable',
value: true
}],
autoLoad: false,
remoteSort: false,
remoteFilter: true
},
displayField: 'DisplayName',
valueField: 'TypePath',
listeners: {
select: function(combo) {
this.app.clearFiltersAndSharedViews();
combo.fireEvent('typeselected', combo.getRecord().get('TypePath'), combo.context);
},
scope: this
},
bubbleEvents: ['typeselected'],
readyEvent: 'ready',
handlesEvents: {
projectscopechanged: function(context) {
this.refreshWithNewContext(context);
}
}
}, {
type: 'query'
}, {
name: 'showControls',
xtype: 'rallycheckboxfield',
fieldLabel: 'Show Control Bar'
},
getHiddenFieldConfig('columnNames'),
getHiddenFieldConfig('order')
];
}
});
})();
(function() {
var Ext = window.Ext4 || window.Ext;
Ext.define('Rally.apps.customlist.CustomListApp', {
extend: 'Rally.app.GridBoardApp',
requires: [
'Deft.Promise',
'Rally.apps.customlist.Settings',
'Rally.data.BulkRecordUpdater',
'Rally.data.ModelTypes',
'Rally.data.PreferenceManager',
'Rally.data.util.Sorter',
'Rally.data.wsapi.Filter',
'Rally.ui.gridboard.plugin.GridBoardInlineFilterControl',
'Rally.ui.gridboard.plugin.GridBoardSharedViewControl',
'Rally.ui.notify.Notifier',
'Rally.util.String'
],
disallowedAddNewTypes: ['user', 'userprofile', 'useriterationcapacity', 'testcaseresult', 'task', 'scmrepository', 'project', 'changeset', 'change', 'builddefinition', 'build', 'program'],
orderedAllowedPageSizes: [10, 25, 50, 100, 200],
readOnlyGridTypes: ['build', 'change', 'changeset'],
statePrefix: 'customlist',
allowExpansionStateToBeSaved: false,
isEditable: true,
config: {
defaultSettings: {
showControls: true
}
},
initComponent: function() {
this.appName = 'CustomList-' + this.getAppId();
this.callParent(arguments);
},
getSettingsFields: function() {
return Rally.apps.customlist.Settings.getFields(this);
},
loadModelNames: function() {
this.modelNames = _.compact([this._getTypeSetting()]);
this._setColumnNames(this._getColumnNamesSetting());
return Deft.Promise.when(this.modelNames);
},
addGridBoard: function() {
this.callParent(arguments);
if (!this.getSetting('showControls')) {
this.gridboard.getHeader().hide();
}
},
loadGridBoard: function() {
if (_.isEmpty(this.modelNames)) {
Ext.defer(function() {
this.fireEvent('settingsneeded', this);
this.publishComponentReady();
}, 1, this);
} else {
this.enableAddNew = this._shouldEnableAddNew();
this.enableRanking = this._shouldEnableRanking();
this.callParent(arguments);
}
},
getGridConfig: function() {
var config = _.merge(this.callParent(arguments), {
allColumnsStateful: true,
enableEditing: !_.contains(this.readOnlyGridTypes, this._getTypeSetting().toLowerCase()),
listeners: {
beforestaterestore: this._onBeforeGridStateRestore,
beforestatesave: this._onBeforeGridStateSave,
scope: this
},
pagingToolbarCfg: {
hidden: !this.getSetting('showControls'),
pageSizes: this.orderedAllowedPageSizes
}
});
var invalidQueryFilters = Rally.util.Filter.findInvalidSubFilters(this._getQueryFilter(), this.models);
if (invalidQueryFilters.length) {
config.store.on('beforeload', function(store) {
Ext.defer(function() {
store.fireEvent('load', store, store.getRootNode(), [], true);
}, 1);
return false;
});
this._showInvalidQueryMessage(config, _.map(invalidQueryFilters, function(filter) {
return 'Could not find the attribute "' + filter.property.split('.')[0] + '" on type "' + this.models[0].displayName + '" in the query segment "' + filter.toString() + '"';
}, this));
}
return config;
},
getColumnCfgs: function() {
return _.union(this.callParent(arguments), _.isEmpty(this.columnNames) && this.enableRanking ? ['DragAndDropRank'] : []);
},
getFilterControlConfig: function() {
return _.merge(this.callParent(arguments), {
listeners: {
beforestaterestore: {
fn: this._onBeforeFilterButtonStateRestore,
scope: this
}
}
});
},
getGridBoardCustomFilterControlConfig: function() {
var context = this.getContext();
var isArtifactModel = this.models[0].isArtifact();
var blackListFields = isArtifactModel ? ['ModelType', 'PortfolioItemType'] : ['ArtifactSearch', 'ModelType'];
var whiteListFields = isArtifactModel ? ['Milestones', 'Tags'] : [];
if (this.models[0].isProject()) {
blackListFields.push('SchemaVersion');
} else if (this.models[0].isRelease()) {
blackListFields.push('ChildrenPlannedVelocity', 'Version');
}
var config = {
ptype: 'rallygridboardinlinefiltercontrol',
inlineFilterButtonConfig: {
stateful: true,
stateId: context.getScopedStateId('custom-list-inline-filter'),
legacyStateIds: [
this.getScopedStateId('owner-filter'),
this.getScopedStateId('custom-filter-button')
],
filterChildren: true,
inlineFilterPanelConfig: {
quickFilterPanelConfig: {
defaultFields: isArtifactModel ? ['ArtifactSearch', 'Owner'] : [],
addQuickFilterConfig: {
blackListFields: blackListFields,
whiteListFields: whiteListFields
}
},
advancedFilterPanelConfig: {
advancedFilterRowsConfig: {
propertyFieldConfig: {
blackListFields: blackListFields,
whiteListFields: whiteListFields
}
}
}
}
}
};
if (isArtifactModel) {
config.inlineFilterButtonConfig.modelNames = this.modelNames;
} else {
config.inlineFilterButtonConfig.model = this.models[0];
}
return config;
},
getSharedViewConfig: function() {
var context = this.getContext();
return {
ptype: 'rallygridboardsharedviewcontrol',
sharedViewConfig: {
stateful: true,
stateId: context.getScopedStateId('custom-list-shared-view'),
enableUrlSharing: this.isFullPageApp !== false
}
};
},
getGridBoardConfig: function() {
var config = this.callParent(arguments);
return _.merge(config, {
listeners: {
viewchange: function() {
this.loadGridBoard();
},
filterchange: function() {
this.gridboard.getGridOrBoard().noDataPrimaryText = undefined;
this.gridboard.getGridOrBoard().noDataSecondaryText = undefined;
},
scope: this
}
});
},
onTreeGridReady: function(grid) {
if (grid.store.getTotalCount() > 10) {
this.gridboard.down('#pagingToolbar').show();
}
this.callParent(arguments);
},
getGridStoreConfig: function() {
var sorters = this._getValidSorters(Rally.data.util.Sorter.sorters(this.getSetting('order')));
if (_.isEmpty(sorters)) {
var rankField = this.getContext().getWorkspace().WorkspaceConfiguration.DragDropRankingEnabled ? 'DragAndDropRank' : 'Rank';
var defaultSort = Rally.data.ModelTypes.areArtifacts(this.modelNames) ? rankField : Rally.data.util.Sorter.getDefaultSort(this.modelNames[0]);
sorters = Rally.data.util.Sorter.sorters(defaultSort);
}
return {
listeners: {
warning: {
fn: this._onGridStoreWarning,
scope: this
}
},
pageSize: 10,
sorters: sorters
};
},
getAddNewConfig: function() {
var config = {
minWidth: 700,
openEditorAfterAddFailure: false,
margin: 0
};
if (!this.getContext().isFeatureEnabled('F6971_REACT_DASHBOARD_PANELS')) {
config.disableAddButton = this.appContainer.slug === 'incompletestories';
}
return _.merge(this.callParent(arguments), config);
},
getFieldPickerConfig: function() {
return _.merge(this.callParent(arguments), {
buttonConfig: {
disabled: !this._userHasPermissionsToEditPanelSettings()
},
gridAlwaysSelectedValues: function() {
return [];
},
gridFieldBlackList: this._getTypeSetting().toLowerCase() === 'task' ? ['Rank'] : []
});
},
getPermanentFilters: function() {
return this._getQueryFilter().concat(this._getTimeboxScopeFilter()).concat(this._getProjectFilter());
},
onTimeboxScopeChange: function() {
this.callParent(arguments);
this.loadGridBoard();
},
clearFiltersAndSharedViews: function() {
var context = this.getContext();
if (this.gridboard) {
this.gridboard.down('rallyinlinefilterpanel').clear();
this.gridboard.down('rallysharedviewcombobox').reset();
}
Ext.create('Rally.data.wsapi.Store', {
model: Ext.identityFn('preference'),
autoLoad: true,
filters: [{
property: 'AppId',
value: context.getAppId()
}, {
property: 'Type',
value: 'View'
}, {
property: 'Workspace',
value: context.getWorkspace()._ref
}],
context: context.getDataContext(),
listeners: {
load: function(store, records) {
if (!_.isEmpty(records)) {
var batchStore = Ext.create('Rally.data.wsapi.batch.Store', {
requester: this,
data: records
});
batchStore.removeAll();
batchStore.sync();
}
store.destroyStore();
},
scope: this
}
});
},
_getTypeSetting: function() {
return this.getSetting('type') || this.getSetting('url');
},
_getColumnNamesSetting: function() {
return this.getSetting('columnNames') ||
(this.getSetting('fetch') || '').split(',');
},
_getQueryFilter: function() {
var query = new Ext.Template(this.getSetting('query')).apply({
projectName: this.getContext().getProject().Name,
projectOid: this.getContext().getProject().ObjectID,
user: this.getContext().getUser()._ref
});
if (query) {
try {
return [Rally.data.wsapi.Filter.fromQueryString(query)];
} catch (e) {
Rally.ui.notify.Notifier.showError({
message: e.message
});
}
}
return [];
},
_getProjectFilter: function() {
return this.modelNames[0].toLowerCase() === 'milestone' ? [
Rally.data.wsapi.Filter.or([{
property: 'Projects',
operator: 'contains',
value: this.getContext().getProjectRef()
}, {
property: 'TargetProject',
operator: '=',
value: null
}])
] : [];
},
_getTimeboxScopeFilter: function() {
var timeboxScope = this.getContext().getTimeboxScope();
var hasTimeboxField = timeboxScope && _.any(this.models, timeboxScope.isApplicable, timeboxScope);
return hasTimeboxField ? [timeboxScope.getQueryFilter()] : [];
},
_shouldEnableAddNew: function() {
return !_.contains(this.disallowedAddNewTypes, this._getTypeSetting().toLowerCase());
},
_shouldEnableRanking: function() {
return this._getTypeSetting().toLowerCase() !== 'task';
},
_setColumnNames: function(columnNames) {
this.columnNames = _.compact(_.isString(columnNames) ? columnNames.split(',') : columnNames);
},
_onBeforeFilterButtonStateRestore: function(filterButton, state) {
if (state && state.filters && state.filters.length) {
var stateFilters = _.map(state.filters, function(filterStr) {
return Rally.data.wsapi.Filter.fromQueryString(filterStr);
});
var validFilters = Rally.util.Filter.removeNonapplicableTypeSpecificFilters(stateFilters, this.models);
state.filters = _.invoke(validFilters, 'toString');
}
},
_hasViewSelected: function() {
var sharedViewConfig = this.getSharedViewConfig().sharedViewConfig;
if (sharedViewConfig && sharedViewConfig.stateId) {
var value = (Ext.state.Manager.get(sharedViewConfig.stateId) || {}).value;
return !_.isEmpty(value);
}
return false;
},
_onBeforeGridStateRestore: function(grid, state) {
if (!state) {
return;
}
if (state.columns) {
var appScopedColumnNames = this._getValidUuids(grid, this.getColumnCfgs());
var userScopedColumnNames = this._getValidUuids(grid, state.columns);
if (this._hasViewSelected()) {
state.columns = userScopedColumnNames;
} else {
// Get the columns that are present in the app scope and not in the user scope
var differingColumns = _.difference(appScopedColumnNames, userScopedColumnNames);
// If there are columns in the app scope that are not in the
// user scope, append them to the user scope to preserve
// user scope column order
if (differingColumns.length > 0) {
state.columns = state.columns.concat(differingColumns);
}
// Filter out any columns that are in the user scope that are not in the
// app scope
state.columns = _.filter(state.columns, function(column) {
return _.contains(appScopedColumnNames, _.isObject(column) ? column.dataIndex : column);
}, this);
}
}
if (state.sorters) {
state.sorters = this._getValidSorters(state.sorters);
if (_.isEmpty(state.sorters)) {
delete state.sorters;
}
}
},
_getValidUuids: function(grid, columns) {
return _.reduce(columns, function(result, column) {
var dataIndex = this._getColumnDataIndex(column);
var field = this._getModelField(grid, dataIndex);
if (field) {
result.push(dataIndex);
}
return result;
}, [], this);
},
_getModelField: function(grid, dataIndex) {
return grid.getModels()[0].getField(dataIndex);
},
_getColumnDataIndex: function(column) {
return _.isObject(column) ? column.dataIndex : column;
},
_onBeforeGridStateSave: function(grid, state) {
var newColumnNames = this._getColumnNamesFromState(state);
if (!_.isEmpty(newColumnNames)) {
this._setColumnNames(newColumnNames);
if (this._userHasPermissionsToEditPanelSettings()) {
this.updateSettingsValues({
settings: {
columnNames: newColumnNames.join(',')
}
});
}
}
},
_onGridStoreWarning: function(store, warnings, operation) {
var couldNotParseWarnings = _.filter(warnings, function(warning) {
return Rally.util.String.startsWith(warning, 'Could not parse ');
});
if (couldNotParseWarnings.length) {
_.assign(operation.resultSet, {
count: 0,
records: [],
total: 0,
totalRecords: 0
});
this._showInvalidQueryMessage(this.gridboard.getGridOrBoard(), couldNotParseWarnings);
}
},
_showInvalidQueryMessage: function(gridOrGridConfig, secondaryTextStrings) {
gridOrGridConfig.noDataPrimaryText = 'Invalid Query';
gridOrGridConfig.noDataSecondaryText = _.map(secondaryTextStrings, function(str) {
return '<div>' + str + '</div>';
}).join('');
},
_getValidSorters: function(sorters) {
return _.filter(sorters, function(sorter) {
return _.any(this.models, function(model) {
var field = model.getField(sorter.property);
return field && field.sortable;
});
}, this);
},
_userHasPermissionsToEditPanelSettings: function() {
return this.isEditable;
},
_getColumnNamesFromState: function(state) {
return _(state && state.columns).map(function(newColumn) {
return _.isObject(newColumn) ? newColumn.dataIndex : newColumn;
}).compact().value();
}
});
})();
Rally.launchApp('Rally.apps.customlist.CustomListApp', {
name: "Custom List",
parentRepos: ""
});
});
</script>
</head>
<body>
</body>
</html>
Ok, I got results by commenting out the following lines in getAddNewConfig:
getAddNewConfig: function () {
var config = {
minWidth: 700,
openEditorAfterAddFailure: false,
margin: 0
};
//if(!this.getContext().isFeatureEnabled('F6971_REACT_DASHBOARD_PANELS')) {
// config.disableAddButton = this.appContainer.slug === 'incompletestories';
//}
return _.merge(this.callParent(arguments), config);
},
It seems that 'this.appContainer.slug' is undefined for me.
Here's the final working CustomListApp.js generated from the comment stream in the answer above. The main tweaks were deleting some old code checking a feature toggle and giving it a default type to display (defect in this case) in the defaultSettings block.
(function() {
var Ext = window.Ext4 || window.Ext;
Ext.define('Rally.apps.customlist.CustomListApp', {
extend: 'Rally.app.GridBoardApp',
requires: [
'Deft.Promise',
'Rally.apps.customlist.Settings',
'Rally.data.BulkRecordUpdater',
'Rally.data.ModelTypes',
'Rally.data.PreferenceManager',
'Rally.data.util.Sorter',
'Rally.data.wsapi.Filter',
'Rally.ui.gridboard.plugin.GridBoardInlineFilterControl',
'Rally.ui.gridboard.plugin.GridBoardSharedViewControl',
'Rally.ui.notify.Notifier',
'Rally.util.String'
],
disallowedAddNewTypes: ['user', 'userprofile', 'useriterationcapacity', 'testcaseresult', 'task', 'scmrepository', 'project', 'changeset', 'change', 'builddefinition', 'build', 'program'],
orderedAllowedPageSizes: [10, 25, 50, 100, 200],
readOnlyGridTypes: ['build', 'change', 'changeset'],
statePrefix: 'customlist',
allowExpansionStateToBeSaved: false,
isEditable: true,
config: {
defaultSettings: {
showControls: true,
type: 'defect' //important to include a default type to display
}
},
initComponent: function () {
this.appName = 'CustomList-' + this.getAppId();
if (this.defaultSettings.url) {
Ext.apply(this.defaultSettings, { type: this.defaultSettings.url });
}
this.callParent(arguments);
},
getSettingsFields: function() {
return Rally.apps.customlist.Settings.getFields(this);
},
loadModelNames: function () {
this.modelNames = _.compact(this.getTypeSetting());
this._setColumnNames(this._getColumnNamesSetting());
return Deft.Promise.when(this.modelNames);
},
addGridBoard: function () {
this.callParent(arguments);
if (!this.getSetting('showControls')) {
this.gridboard.getHeader().hide();
}
},
loadGridBoard: function () {
if (_.isEmpty(this.modelNames)) {
Ext.defer(function () {
this.fireEvent('settingsneeded', this);
this.publishComponentReady();
}, 1, this);
} else {
this.enableAddNew = this._shouldEnableAddNew();
this.enableRanking = this._shouldEnableRanking();
this.callParent(arguments);
}
},
getGridConfig: function () {
var config = _.merge(this.callParent(arguments), {
allColumnsStateful: true,
enableEditing: _.intersection(this.readOnlyGridTypes, this.getTypeSetting()).length === 0,
listeners: {
beforestaterestore: this._onBeforeGridStateRestore,
beforestatesave: this._onBeforeGridStateSave,
scope: this
},
pagingToolbarCfg: {
hidden: !this.getSetting('showControls'),
pageSizes: this.orderedAllowedPageSizes
}
});
var invalidQueryFilters = Rally.util.Filter.findInvalidSubFilters(this._getQueryFilter(), this.models);
if (invalidQueryFilters.length) {
config.store.on('beforeload', function (store) {
Ext.defer(function () {
store.fireEvent('load', store, store.getRootNode(), [], true);
}, 1);
return false;
});
this._showInvalidQueryMessage(config, _.map(invalidQueryFilters, function (filter) {
return 'Could not find the attribute "'+ filter.property.split('.')[0] +'" on type "'+ this.models[0].displayName +'" in the query segment "'+ filter.toString() + '"';
}, this));
}
return config;
},
getColumnCfgs: function() {
return _.union(this.callParent(arguments), _.isEmpty(this.columnNames) && this.enableRanking ? ['DragAndDropRank'] : []);
},
getFilterControlConfig: function () {
return _.merge(this.callParent(arguments), {
listeners: {
beforestaterestore: {
fn: this._onBeforeFilterButtonStateRestore,
scope: this
}
}
});
},
getGridBoardCustomFilterControlConfig: function() {
var context = this.getContext();
var isArtifactModel = this.models[0].isArtifact();
var blackListFields = isArtifactModel ? ['ModelType', 'PortfolioItemType', 'LastResult'] : ['ArtifactSearch', 'ModelType'];
var whiteListFields = isArtifactModel ? ['Milestones', 'Tags'] : [];
if (this.models[0].isProject()) {
blackListFields.push('SchemaVersion');
} else if (this.models[0].isRelease()) {
blackListFields.push('ChildrenPlannedVelocity', 'Version');
}
var config = {
ptype: 'rallygridboardinlinefiltercontrol',
inlineFilterButtonConfig: {
stateful: true,
stateId: context.getScopedStateId('custom-list-inline-filter'),
legacyStateIds: [
this.getScopedStateId('owner-filter'),
this.getScopedStateId('custom-filter-button')
],
filterChildren: true,
inlineFilterPanelConfig: {
quickFilterPanelConfig: {
defaultFields: isArtifactModel ? ['ArtifactSearch', 'Owner'] : [],
addQuickFilterConfig: {
blackListFields: blackListFields,
whiteListFields: whiteListFields
}
},
advancedFilterPanelConfig: {
advancedFilterRowsConfig: {
propertyFieldConfig: {
blackListFields: blackListFields,
whiteListFields: whiteListFields
}
}
}
}
}
};
if (isArtifactModel) {
config.inlineFilterButtonConfig.modelNames = this.modelNames;
} else {
config.inlineFilterButtonConfig.model = this.models[0];
}
return config;
},
getSharedViewConfig: function() {
var context = this.getContext();
return {
ptype: 'rallygridboardsharedviewcontrol',
sharedViewConfig: {
stateful: true,
stateId: context.getScopedStateId('custom-list-shared-view'),
enableUrlSharing: this.isFullPageApp !== false
}
};
},
getGridBoardConfig: function () {
var config = this.callParent(arguments);
return _.merge(config, {
listeners: {
viewchange: function() {
this.loadGridBoard();
},
filterchange: function() {
this.gridboard.getGridOrBoard().noDataPrimaryText = undefined;
this.gridboard.getGridOrBoard().noDataSecondaryText = undefined;
},
scope: this
}
});
},
onTreeGridReady: function (grid) {
if (grid.store.getTotalCount() > 10) {
this.gridboard.down('#pagingToolbar').show();
}
this.callParent(arguments);
},
getGridStoreConfig: function () {
var sorters = this._getValidSorters(Rally.data.util.Sorter.sorters(this.getSetting('order')));
if (_.isEmpty(sorters)) {
var rankField = this.getContext().getWorkspace().WorkspaceConfiguration.DragDropRankingEnabled ? 'DragAndDropRank' : 'Rank';
var defaultSort = Rally.data.ModelTypes.areArtifacts(this.modelNames) ? rankField : Rally.data.util.Sorter.getDefaultSort(this.modelNames[0]);
sorters = Rally.data.util.Sorter.sorters(defaultSort);
}
return {
listeners: {
warning: {
fn: this._onGridStoreWarning,
scope: this
}
},
pageSize: 10,
sorters: sorters
};
},
getAddNewConfig: function () {
var config = {
minWidth: 700,
openEditorAfterAddFailure: false,
margin: 0
};
return _.merge(this.callParent(arguments), config);
},
getFieldPickerConfig: function () {
return _.merge(this.callParent(arguments), {
buttonConfig: {
disabled: !this._userHasPermissionsToEditPanelSettings()
},
gridAlwaysSelectedValues: function () { return []; },
gridFieldBlackList: this._shouldEnableRanking() ? [] : ['Rank']
});
},
getPermanentFilters: function () {
return this._getQueryFilter().concat(this._getTimeboxScopeFilter()).concat(this._getProjectFilter());
},
onTimeboxScopeChange: function() {
this.callParent(arguments);
this.loadGridBoard();
},
clearFiltersAndSharedViews: function() {
var context = this.getContext();
if (this.gridboard) {
this.gridboard.down('rallyinlinefilterpanel').clear();
this.gridboard.down('rallysharedviewcombobox').reset();
}
Ext.create('Rally.data.wsapi.Store', {
model: Ext.identityFn('preference'),
autoLoad: true,
filters: [
{property: 'AppId', value: context.getAppId()},
{property: 'Type', value: 'View'},
{property: 'Workspace', value: context.getWorkspace()._ref}
],
context: context.getDataContext(),
listeners: {
load: function(store, records) {
if(!_.isEmpty(records)) {
var batchStore = Ext.create('Rally.data.wsapi.batch.Store', {
requester: this,
data: records
});
batchStore.removeAll();
batchStore.sync();
}
store.destroyStore();
},
scope: this
}
});
},
getTypeSetting: function() {
return (this.getSetting('type') || this.getSetting('url') || '').toLowerCase().split(',');
},
_getColumnNamesSetting: function() {
return this.getSetting('columnNames') ||
(this.getSetting('fetch') || '').split(',');
},
_getQueryFilter: function () {
var query = new Ext.Template(this.getSetting('query')).apply({
projectName: this.getContext().getProject().Name,
projectOid: this.getContext().getProject().ObjectID,
user: this.getContext().getUser()._ref
});
if (query) {
try {
return [ Rally.data.wsapi.Filter.fromQueryString(query) ];
} catch(e) {
Rally.ui.notify.Notifier.showError({ message: e.message });
}
}
return [];
},
_getProjectFilter: function () {
return this.modelNames[0].toLowerCase() === 'milestone' ? [
Rally.data.wsapi.Filter.or([
{ property: 'Projects', operator: 'contains', value: this.getContext().getProjectRef() },
{ property: 'TargetProject', operator: '=', value: null }
])
] : [];
},
_getTimeboxScopeFilter: function () {
var timeboxScope = this.getContext().getTimeboxScope();
var hasTimeboxField = timeboxScope && _.any(this.models, timeboxScope.isApplicable, timeboxScope);
return hasTimeboxField ? [ timeboxScope.getQueryFilter() ] : [];
},
_shouldEnableAddNew: function() {
return _.intersection(this.disallowedAddNewTypes, this.getTypeSetting()).length === 0;
},
_shouldEnableRanking: function() {
return !_.contains(this.getTypeSetting(), 'task');
},
_setColumnNames: function (columnNames) {
this.columnNames = _.compact(_.isString(columnNames) ? columnNames.split(',') : columnNames);
},
_onBeforeFilterButtonStateRestore: function (filterButton, state) {
if (state && state.filters && state.filters.length) {
var stateFilters = _.map(state.filters, function (filterStr) {
return Rally.data.wsapi.Filter.fromQueryString(filterStr);
});
var validFilters = Rally.util.Filter.removeNonapplicableTypeSpecificFilters(stateFilters, this.models);
state.filters = _.invoke(validFilters, 'toString');
}
},
_hasViewSelected: function() {
var sharedViewConfig = this.getSharedViewConfig().sharedViewConfig;
if (sharedViewConfig && sharedViewConfig.stateId) {
var value = (Ext.state.Manager.get(sharedViewConfig.stateId) || {}).value;
return !_.isEmpty(value);
}
return false;
},
_onBeforeGridStateRestore: function (grid, state) {
if (!state) {
return;
}
if (state.columns) {
var appScopedColumnNames = this._getValidUuids(grid, this.getColumnCfgs());
var userScopedColumnNames = this._getValidUuids(grid, state.columns);
if (this._hasViewSelected()) {
state.columns = userScopedColumnNames;
} else {
// Get the columns that are present in the app scope and not in the user scope
var differingColumns = _.difference(appScopedColumnNames, userScopedColumnNames);
// If there are columns in the app scope that are not in the
// user scope, append them to the user scope to preserve
// user scope column order
if (differingColumns.length > 0) {
state.columns = state.columns.concat(differingColumns);
}
// Filter out any columns that are in the user scope that are not in the
// app scope
state.columns = _.filter(state.columns, function (column) {
return _.contains(appScopedColumnNames, _.isObject(column) ? column.dataIndex : column);
}, this);
}
}
if (state.sorters) {
state.sorters = this._getValidSorters(state.sorters);
if (_.isEmpty(state.sorters)) {
delete state.sorters;
}
}
},
_getValidUuids: function(grid, columns) {
return _.reduce(columns, function(result, column) {
var dataIndex = this._getColumnDataIndex(column);
var field = this._getModelField(grid, dataIndex);
if (field) {
result.push(dataIndex);
}
return result;
}, [], this);
},
_getModelField: function(grid, dataIndex) {
return grid.getModels()[0].getField(dataIndex);
},
_getColumnDataIndex: function(column) {
return _.isObject(column) ? column.dataIndex : column;
},
_onBeforeGridStateSave: function (grid, state) {
var newColumnNames = this._getColumnNamesFromState(state);
if (!_.isEmpty(newColumnNames)) {
this._setColumnNames(newColumnNames);
if (this._userHasPermissionsToEditPanelSettings()) {
this.updateSettingsValues({
settings: {
columnNames: newColumnNames.join(',')
}
});
}
}
},
_onGridStoreWarning: function(store, warnings, operation) {
var couldNotParseWarnings = _.filter(warnings, function(warning){
return Rally.util.String.startsWith(warning, 'Could not parse ');
});
if(couldNotParseWarnings.length) {
_.assign(operation.resultSet, {
count: 0,
records: [],
total: 0,
totalRecords: 0
});
this._showInvalidQueryMessage(this.gridboard.getGridOrBoard(), couldNotParseWarnings);
}
},
_showInvalidQueryMessage: function(gridOrGridConfig, secondaryTextStrings) {
gridOrGridConfig.noDataPrimaryText = 'Invalid Query';
gridOrGridConfig.noDataSecondaryText = _.map(secondaryTextStrings, function(str){
return '<div>' + str + '</div>';
}).join('');
},
_getValidSorters: function (sorters) {
return _.filter(sorters, function (sorter) {
return _.any(this.models, function (model) {
var field = model.getField(sorter.property);
return field && field.sortable;
});
}, this);
},
_userHasPermissionsToEditPanelSettings: function () {
return this.isEditable;
},
_getColumnNamesFromState: function (state) {
return _(state && state.columns).map(function (newColumn) {
return _.isObject(newColumn) ? newColumn.dataIndex : newColumn;
}).compact().value();
}
});
})();

DOJO how to Add title to TableContainer

Programmatically developing a TableContainer. All the child information and properties of TableContainer are fetched from a JSON file. In the client javascript code, we process this inoformation to prepare the TableContainer.
Planned to use TableContainer label as the Header for that container, but failed , as the container label is placed in the center of the first column as shown in the screenshot-1
I am expecting the headers to appear as in the screenshot-2
FYI, I have many tablecontainers placed in Root Table container where each table container should have a header
Following is the json:
"element":[
{
"type":"container",
"propertylist":{
"property":[
{
"name":"label",
"value":"Common Parameters"
},
{
"name":"id",
"value":"commonParams"
}
]
},
"element":[
{
"type":"textfield",
"propertylist":{
"property":[
{
"name":"label",
"value":"Profile Name"
},
{
"name":"id",
"value":"profileName"
}
]
}
},
{
"type":"textfield",
"propertylist":{
"property":[
{
"name":"label",
"value":"Description"
},
{
"name":"id",
"value":"description"
}
]
}
},
{
"type":"checkbox",
"propertylist":{
"property":[
{
"name":"label",
"value":"Dual-ended"
},
{
"name":"checked",
"value":false
},
{
"name":"id",
"value":"dualEnded"
}
]
}
},
{
"type":"checkbox",
"propertylist":{
"property":[
{
"name":"label",
"value":"DST is OAM-aware"
},
{
"name":"checked",
"value":false
},
{
"name":"id",
"value":"dstIsOAMAware"
}
]
}
},
{
"type":"combobox",
"propertylist":{
"property":[
{
"name":"label",
"value":"Traffic Type"
},
{
"name":"store",
"value":"{{name='Y.1731 OAM', id:1},{name='Simulated Customer',id:2}}"
},
{
"name":"value",
"value":"1"
},
{
"name":"id",
"value":"trafficType"
}
]
}
},
{
"type":"combobox",
"propertylist":{
"property":[
{
"name":"label",
"value":"MEG Level"
},
{
"name":"store",
"value":"{{id:0},{id:1},{id:2},{id:3},{id:4},{id:5}{id:6},{id:7}}"
},
{
"name":"value",
"value":"8"
},
{
"name":"id",
"value":"megLevel"
}
]
}
},
{
"type":"combobox",
"actionlist":{
"action":[
{
"name":"onclick",
"value":"handleUserDefinedFramesize"
}
]
},
"propertylist":{
"property":[
{
"name":"label",
"value":"Frame Size"
},
{
"name":"values",
"value":"{{id:1,name:'64 bytes'},{id:1,name:'128 bytes'},{id:1,name:'256 bytes'},{id:1,name:'512 bytes'},{id:1,name:'1024 bytes'},{id:1,name:'1280 bytes'},{id:1,name:'1518 bytes'},{id:1,name:'MTU'},{id:1,name:'User-defined'}}"
},
{
"name":"value",
"value":"4"
},
{
"name":"id",
"value":"frameSize"
}
]
}
},
{
"type":"textfield",
"propertylist":{
"property":[
{
"name":"label",
"value":"User-defined Frame Size"
},
{
"name":"units",
"value":"bytes"
},
{
"name":"disabled",
"value":"true"
},
{
"name":"value",
"value":"2000"
},
{
"name":"id",
"value":"userDefinedFS"
}
]
}
},
{
"type":"textfield",
"propertylist":{
"property":[
{
"name":"label",
"value":"Dwell Time"
},
{
"name":"units",
"value":"msecs"
},
{
"name":"value",
"value":"500"
},
{
"name":"id",
"value":"dwellTime"
}
]
}
}
]
}
Code to process the json:
function process(metaData){
//alert(JSON.stringify(metaData));
switch(metaData.type){
case "container":
var tableContainer = new dojox.layout.TableContainer({
cols: 1,
"labelWidth": "150"
});
if(metaData.propertylist){
metaData.propertylist.property.forEach(function(prop) {
//var row = domConstruct.toDom('<div class="greyHeader" style="width:40% !important;">' + prop.value + '</div>');
//tabContainer.addChild(row);
tableContainer.set(prop.name, prop.value);
});
}
return tableContainer;
break;
case "textfield":
var textBox = new dijit.form.TextBox();
metaData.propertylist.property.forEach(function(prop) {
textBox.set(prop.name, prop.value);
});
return textBox;
break;
case "checkbox":
var checkBox = new dijit.form.CheckBox();
metaData.propertylist.property.forEach(function(prop) {
checkBox.set(prop.name, prop.value);
});
return checkBox;
break;
case "combobox":
// store is a mandatory param that is required otherwise this.domNode is null
var filteringSelect = new dijit.form.FilteringSelect({store:new Memory({data:[]})});
console.log(JSON.stringify(metaData.propertylist.property));
metaData.propertylist.property.forEach(function(prop) {
if(prop.name == 'store'){
filteringSelect.store = new Memory({data: prop.value});
}else{
filteringSelect.set(prop.name, prop.value);
}
});
return filteringSelect;
break;
case "button":
var button = new Button();
metaData.propertylist.property.forEach(function(prop) {
button.set(prop.name, prop.value);
});
return button;
break;
case "contentpane":
var contentPane = new ContentPane();
if(metaData.propertylist){
metaData.propertylist.property.forEach(function(prop) {
contentPane.set(prop.name, prop.value);
});
}
return contentPane;
break;
}
}
Please let me know, how i can use table container's label as a header
Curious to know how we can add html text to a table container.
I have found a solution for this problem
Written a custom widget which takes label as a constructor parameter, and overridden the buildRendering function to return the following
this.domNode = domConstruct.toDom('' + '' + '');
then it appears as a label

Curve Line Graphic and Jsonfile

I realized this curve line graph using d3 and nvd3:
d3.json('/Models/Scripts/test_data2.json', function(data) {
nv.addGraph(function() {
var chart = nv.models.lineWithFocusChart();
// chart.transitionDuration(500);
chart.xAxis
.tickFormat(d3.format(',f'));
chart.x2Axis
.tickFormat(d3.format(',f'));
chart.yAxis
.tickFormat(d3.format(',.2f'));
chart.y2Axis
.tickFormat(d3.format(',.2f'));
d3.select('#chart svg')
.datum(data)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
});
The question is, how should I write my json file to recognize different curves?
If I have the following json it doesn't work with two or more lines. I did several tries.
[{"CurveArray":[{
"Line1":[
{
"x":-52482.23046875,
"y":0.0
},
{
"x":-51380.384892578128,
"y":0.4
},
{
"x":-50278.539316406248,
"y":2
},
{
"x":-49176.693740234376,
"y":0.9
},
{
"x":-48074.848164062496,
"y":0.7
}
]},
"Line2":[
{
"x":-52482.23046875,
"y":0.0
},
{
"x":-51380.384892578128,
"y":0.4
},
{
"x":-50278.539316406248,
"y":2
},
{
"x":-49176.693740234376,
"y":0.9
},
{
"x":-48074.848164062496,
"y":0.7
}
]}
]}]
I tried to modify so:
It doesn't work again.
[
{
key: "Line1",
value: [
{
"x":-52482.23046875,
"y":0.0
},
{
"x":-51380.384892578128,
"y":0.4
},
{
"x":-50278.539316406248,
"y":2
},
{
"x":-49176.693740234376,
"y":0.9
},
{
"x":-48074.848164062496,
"y":0.7
}
]
},
{
key: "Line2",
value: [
{
"x":-50000,
"y":0.0
},
{
"x":-59000,
"y":0.4
},
{
"x":-48000,
"y":2
},
{
"x":-49100,
"y":0.9
},
{
"x":-49800,
"y":0.7
}
]
}
]