This may sound a bit stupid, but I am trying to use ModifyMode under the mode property of EditableGeoJsonLayer, but the adjustable handles do not appear, as it is supposed to in the "Geojson Editor" example posted on nebula.gl website. It would have been convenient if there were more examples regarding the editableGeojsonLayer API reference. This what I am trying to do:
new (EditableGeoJsonLayer as any)({
id: 'geojson',
data: featureState.data,
mode: ModifyMode,
selectedFeatureIndexes,
onEdit: ({updatedData}):any => {
setFeatureState({
data: updatedData
});
},
pickable: true,
pickingRadius: 15,
//onClick: data => InfoWindow(data.object.properties, data.coordinate, "New Shape", "PointView"),
}
Also after further tests, none of alter modes are working, but all draw modes and view modes are working fine
You should make sure the feature is selected ,as a matter of fact, make it can be seleted at first.
Make sure to have a selectionLayer when using ModifyMode. You must select the polygon before you can modify it. When the polygon/line is selected you should see the corner, and new point addition, blocks to drag-and-drop.
selectedFeatureIndexes should be an array of selected polygons ids. You can set this array in your selectionLayer onSelect by taking advantage of the pickingInfos parameter.
Here is a sample selectionLayer
const selectionLayer = new SelectionLayer({
id: "selection",
selectionType: "rectangle",
onSelect: ({ pickingInfos }) => {
// use pickingInfos to set the SelectedFeatureIndexes
setSelectedFeatureIndexes(pickingInfos.map((pi) => pi.index));
// any other functionality for selecting, like adding id's to state
},
layerIds: ["geojson"],
getTentativeFillColor: () => [255, 0, 255, 100],
getTentativeLineColor: () => [0, 0, 255, 255],
lineWidthMinPixels: 3,
});
Related
My situation is the following:
I have an array of game objects stored as an atom, each game in the array is of the same type and structure.
I have another atom which allows me to store the id of a game in the array that has been "targeted".
I have a selector which I can use to get the targeted game object by searching the array for a match between the game ids and the targeted game id I have stored.
Elsewhere in the application the game is rendered as a DOM element and calculations are made which I want to use to update the data in the game object in the global state.
It's this last step that's throwing me off. Should my selector be writable so I can update the game object? How do I do this?
This is a rough outline of the code I have:
export const gamesAtom = atom<GameData[]>({
key: 'games',
default: [
{
id: 1,
name: 'Bingo',
difficulty: 'easy',
},
{
id: 21,
name: 'Yahtzee',
difficulty: 'moderate',
},
{
id: 3,
name: 'Twister',
difficulty: 'hard',
},
],
});
export const targetGameIdAtom = atom<number | null>({
key: 'targetGameId',
default: null,
});
export const targetGameSelector = selector<GameData | undefined>({
key: 'targetGame',
get: ({ get }) => {
return get(gamesAtom).find(
(game: GameData) => game.id === get(selectedGameIdAtom)
);
},
// This is where I'm getting tripped up. Is this the place to do this? What would I write in here?
set: ({ set, get }, newValue) => {},
});
// Elsewhere in the application the data for the targetGame is pulled down and new values are provided for it. For example, perhaps I want to change the difficulty of Twister to "extreme" by sending up the newValue of {...targetGame, difficulty: 'extreme'}
Any help or being pointed in the right direction will be appreciated. Thanks!
I'm fetching a query, and modifying the order of the list in it, using cache.modify on the drag end.
This does modify cache, as it should but, it takes milliseconds to do that.
How to reproduce the issue:
I'm using react beautiful dnd, to make drag-n-drop card.
It provides onDragEnd handler, where we can specify what happens when the user stops dragging.
In this case, I want to reorder the list on the drag end.
Cache modify:
cache.modify({
id: cache.identify(data.pod),
fields: {
stories(existingStoriesRefs, { readField }) {
return reorder(existingStoriesRefs, sourceIndex, destinationIndex);
},
},
});
Reorder logic:
const reorder = (list: any[], startIndex: number, endIndex: number) => {
const result = Array.from(list);
const [removed] = result.splice(startIndex, 1);
result.splice(endIndex, 0, removed);
return result;
};
This is correctly working and rendering using stories in setState.
But, instead of copying Apollo data, to a new state, I think it's better to directly modify the cache.
But, using cache.modify, it works but, rendering is kind of glitchy. It seems, it first renders the existing list and then, modify cache in the next render. The glitch is around less than a second, but visible to the user.
I fixed it using cache.modify inside, mutation, and using optimistic update.
moveStoryMutation({
variables: {
id: stories[sourceIndex].id,
sourceIndex,
destinationIndex,
},
optimisticResponse: {
__typename: "Mutation",
moveStory: true,
},
update: (proxy) => {
proxy.modify({
id: proxy.identify(pod),
fields: {
stories(existingStoryRefs) {
return reorder(
existingStoryRefs,
sourceIndex,
destinationIndex
);
},
},
});
I am using Fluent UI DetailsList. My table looks like below:
I need filters below every column (text or drop-down) as shown below:
Please let me know if this is possible? Or maybe a way to display custom header (using html) ?
This actually turned out to be easier than I thought it'd be...
If you're ok with clicking the column header to reveal the choices (vs having the dropdown directly under the title) then this can be achieved using the ContextualMenu component in conjunction with DetailsList. I got it working by tweaking from the variable row height example in the official docs: https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist/variablerowheights.
Add a ContextualMenu underneath your DetailsList:
<DetailsList
items={items}
columns={columns}
/>
{this.state.contextualMenuProps && <ContextualMenu {...this.state.contextualMenuProps} />}
Inside your column definition, set the hasDropdown action so the user gets a UI indicator that they can/should click the header, and call a contextMenu method (note I'm using onColumnContextMenu as well as onColumnClick so it doesn't matter if they left or right click the header:
{
key: 'dept',
name: 'Department',
fieldName: 'dept',
minWidth: 125,
maxWidth: 200,
onColumnContextMenu: (column, ev) => {
this.onColumnContextMenu(column, ev);
},
onColumnClick: (ev, column) => {
this.onColumnContextMenu(column, ev);
},
columnActionsMode: ColumnActionsMode.hasDropdown,
}
When the onColumnContextMenu method gets invoked, we need to build the context menu properties that will get consumed by the ContextualMenu component. Note the dismissal method as well, which clears out the state so the menu is hidden.
private onContextualMenuDismissed = (): void => {
this.setState({
contextualMenuProps: undefined,
});
}
private onColumnContextMenu = (column: IColumn, ev: React.MouseEvent<HTMLElement>): void => {
if (column.columnActionsMode !== ColumnActionsMode.disabled) {
this.setState({
contextualMenuProps: this.getContextualMenuProps(ev, column),
});
}
};
Finally, inside of getContextualMenuProps you need to determine what the options should be for the user to click. In this example, I'm simply giving sort options (you'll need to add an onClick handler to actually do something when the user clicks the item), but I'll use the column to determine what those items should actually be and paint the filters into the items collection so the user can select one to filter.
private getContextualMenuProps = (ev: React.MouseEvent<HTMLElement>, column: IColumn): IContextualMenuProps => {
const items: IContextualMenuItem[] = [
{
key: 'aToZ',
name: 'A to Z',
iconProps: { iconName: 'SortUp' },
canCheck: true,
checked: column.isSorted && !column.isSortedDescending,
},
{
key: 'zToA',
name: 'Z to A',
iconProps: { iconName: 'SortDown' },
canCheck: true,
checked: column.isSorted && column.isSortedDescending,
}
];
return {
items: items,
target: ev.currentTarget as HTMLElement,
directionalHint: DirectionalHint.bottomLeftEdge,
gapSpace: 10,
isBeakVisible: true,
onDismiss: this.onContextualMenuDismissed,
}
}
Note the target on the ContextualMenuProps object, which is what tells the ContextualMenu where to lock itself onto (in this case, the column header that you clicked to instantiate the menu.
Detail list filter for each column without context menu -
https://codesandbox.io/s/rajesh-patil74-jzuiy?file=/src/DetailsList.CustomColumns.Example.tsx
For instance - Providing filter in text field associated with each column will apply filter on color column.
I am doing this in a mutation in Vuex:
console.time('ADD products')
state.products = products
console.timeEnd('ADD products')
The 'products' is an array of 350 objects. The state.product is declared in the store like:
const state = {
products: [],
...
}
The console.time/timeEnd is telling me this takes around 70ms to do. This cannot be as fast as it is supposed to be.
I have tried turning the strict mode on and off, as mentioned as a solution in similar posts, but with no effect at all.
Info:
Vue: 2.5.13
Vuex: 3.0.1
Debugging on latest version of Chrome on MacBook Pro
A product in the array looks like this:
{
id: 9633,
title: 'Dark Grey Canvas Satchel',
brand: 'Delton Bags',
price: '£49',
beforePrice: false,
isNew: false,
discount: 0,
link: 'http://localhost:3000/dark-grey-canvas-satchel-p.html',
images: [
'https://res.cloudinary.com/image/upload/f_auto,c_pad,q_80,w_X-WIDTH,h_X-HEIGHT/media/catalog/product/9/0/9027A-2.jpg',
'https://res.cloudinary.com/image/upload/f_auto,c_pad,q_80,w_X-WIDTH,h_X-HEIGHT/media/catalog/product/h/d/hd-trendhim-12-2016-12.jpg',
],
basePrice: 449,
localPrice: 49,
filters: {
th_filter_farve: ['228'],
th_filter_materiale: ['351'],
th_filter_computersize: ['573'],
th_brand: ['277'],
th_price: 49,
},
filterAttributes: { canBeShortened: 0 },
sorting: {
qty_ordered: 47,
qty_ordered_store: 0,
newest: '9633',
defaultSorting: 0,
},
}
What I am asking:
What can I expect the speed to be
Would any computed properties relying on this state.products be slowing this performance down?
What is the fastest way to add an array like this to the store?
Regards
Kasper
first paremeter is the filename and second is docDefinition(which value i will pass in second parameter) still confuse?
please help me out
The second parameter is an object that have all the options of "pdfmake".
The most fundamental concept to be mastered is the
document-definition-object which can be as simple as:
var docDefinition = { content: 'This is an sample PDF printed withpdfMake' };
or become pretty complex (having multi-level tables,
images, lists, paragraphs, margins, styles etc...).
You can check the documentation on Github https://github.com/bpampuch/pdfmake and do it more complex.
But if you use the function pdfExport, this one create the object with the data grid and it is more easy, Try this:
$scope.gridApi.exporter.pdfExport( uiGridExporterConstants.ALL, uiGridExporterConstants.ALL );
And they have more options that you can change in gridOptions:
exporterPdfDefaultStyle:{ fontSize: 11 },
exporterPdfFilename: 'filename.pdf',
exporterPdfTableHeaderStyle: { bold: true, fontSize: 12, color: 'black' },
exporterPdfTableStyle : { margin: [0, 5, 0, 15] },
exporterPdfHeader : null,
exporterPdfFooter : null,
gridOptions.exporterPdfOrientation : 'landscape',
etc...