How to remove all map layers from kepler.gl dynamically? - reactjs

I have added a div and dropdwn, on each option I have uploaded geojson data using addDatatoMap in reactjs .
On each time I selected the option , this uploaded the respective layer ,
But I am not able to remove the previous layers,
So any code or example to reset / clear map layers

After so many research I found the solution , so posted it to save other's time
import KeplerGlSchema from 'kepler.gl/schemas';
import { visStateUpdaters } from 'kepler.gl/reducers';
// // Clear Uploaded Data
RemoveUploadedData() {
// // returns uploaded Data on map
const dataToSave =
KeplerGlSchema.getDatasetToSave(this.props.demo.keplerGl.map);
console.log('dataToSave', dataToSave);
// // returns uploaded layer config on map
const configToSave =
KeplerGlSchema.getConfigToSave(this.props.demo.keplerGl.map);
console.log('configToSave', configToSave);
var layerConfigs = configToSave.config.visState.layers;
// // Removed each uploaded layers
if (configToSave && layerConfigs.length > 0) {
for (var i = 0; i < layerConfigs.length; i++) {
this.props.demo.keplerGl.map.visState =
visStateUpdaters.removeDatasetUpdater(
this.props.demo.keplerGl.map.visState,
{ key: dataToSave[i].data.id }
)
}
}
}

Related

React - useState appending to the array changes previously appended objects

Hi all,
I have a small react app that is creating (mapping from an array) new tabs (and panels) when there is a new message over the websocket.
There is an initial setup, that is hardcoded for the test purposes which sets up 2 tabs on load, any new ones should be appended to these two.
const INITIAL_ARRAY= [
{
id: 1,
child_component_config: {...}
},
{
id: 2,
child_component_config: {...}
}
];
const template = {
child_component_config: {...}
}
The code, simplifed:
const [current_array, setNewArray] = useState( INITIAL_ARRAY);
export default function ParentComponent() {
useEffect(() => {
const client = new ws...
client.onConnect = function (frame) {
var message = clientDesk.subscribe( '/topic/desks/4', function (message) {
// on message
var new_tab = TEMPLATE;
new_tab.id = Math.max( ...current_array.map( elem => elem.id ) ) + 1;
setActiveTab(new_tab.id);
setNewArray([...current_array, new_tab]);
}
}
}, [ current_array ]);
const tabs = map tabs
cosnt panels = map panels
return(
{tabs}
{panels}
)
The problem:
On first message from the WS the third element is added to the array properly (example-1)
, fourth one is added properly but it also overwrites the third element (example-2)
making them exactly the same. After fourth it gets strange, where some are overwritten and some are not.
I've tried:
Moving the state updating out of useEffect or removing useEffect completly
Storing current_array in a temp var before any logic
Adding a counter to track which tab's id is the latest -> tracking state of just one number works
const [tab_count, setTabCount] = useState( INITIAL_ARRAY.lenght );
Using counter to try to force rendering
Setting up a fixed number of objects in the initial array and just update which ever is needed (with and without counter)
Updating based on the previous value
setNewArray( prevArray => {
logic
return [...prevArray, new_tab];
}
After the first WS message, if the code is changed/saved and webpack compiled, the next message will add a new element to the array properly.
EDIT - Solved:
Managed to solve this by building a new object (instead of using the template) before adding it to the array.

Quill Editor inserts erroneous tab character when loading saved data with inline indent style

I'm wondering if the behavior I'm seeing is a bug and figured I'd ask here before submitting to github.
I need to be able to create, save, and edit saved email templates in the Quill editor. I also need to be able to use the output from Quill in an email, formatted how it was entered in the WYSIWYG editor, so I'm saving the HTML output with inline styles.
I have an issue with the indentation not rendering as it was entered when I load in a saved email template. I'm implementing the IndentAttributor like the following comment:
https://github.com/quilljs/quill/issues/1274#issuecomment-303619625
I dug into what Quill is doing and found in matchStyles() a tab character is getting inserted if textIndent is found.
Offending code in quill.js:
function matchStyles(node, delta) {
var formats = {};
var style = node.style || {};
if (style.fontStyle && computeStyle(node).fontStyle === 'italic') {
formats.italic = true;
}
if (style.fontWeight && (computeStyle(node).fontWeight.startsWith('bold') || parseInt(computeStyle(node).fontWeight) >= 700)) {
formats.bold = true;
}
if (Object.keys(formats).length > 0) {
delta = applyFormat(delta, formats);
}
if (parseFloat(style.textIndent || 0) > 0) {
// Could be 0.5in
delta = new _quillDelta2.default().insert('\t').concat(delta);
}
return delta;
}
I tested a change to the quill.js node_module to check for text-indent style. However, I'm not trying to hack the editor for a specific need and I'm not familiar enough with the editor to know whether or not this will have a negative impact on anything else.
function matchStyles(node, delta) {
console.log('in matchStyles()');
var formats = {};
var style = node.style || {};
if (style.fontStyle && computeStyle(node).fontStyle === 'italic') {
formats.italic = true;
}
if (style.fontWeight && (computeStyle(node).fontWeight.startsWith('bold') || parseInt(computeStyle(node).fontWeight) >= 700)) {
formats.bold = true;
}
if (Object.keys(formats).length > 0) {
delta = applyFormat(delta, formats);
}
if ((parseFloat(style.textIndent || 0) > 0) && !style.cssText.includes('text-indent')) { //fix to check for inline style
// Could be 0.5in
delta = new _quillDelta2.default().insert('\t').concat(delta); //problem here...
}
return delta;
}
Example project showing the issue:
https://stackblitz.com/edit/github-acpnmm
Highlight or inspect the initial text (coming from app.reducer.ts initial state) and you will see the tab character that was inserted.
Should Quill be recognizing the IndentAttributor and not insert the tab character?
I see you are using Quill in Angular project. I would suggest you to check this package: https://www.npmjs.com/package/ngx-quill. With this package you can choose the type of data (Text, HTML or Delta) that the Quill will process, and you can bind the Quill content to some variable. That way you can just store that value of that variable in the database. When you need to load the content again, fetch that value from the database, and again bind the Quill content to that value.

Showing/Hiding groups of markers using layers or some other grouping method

I have a set of markers which I want to have visible or not on a React Google map.
In ESRI/ArcGIS maps you can create layers which can be turned on or off, but it does not seem any equivalent features exist in Google maps.
I suppose can give the markers a specific class and turn their visibility on or off, but I am concerned this may impact performance.
Any suggestions on a way forward?
Google Maps API does not support this kind of custom layers (refer official docs for a supported list of layers).
The following custom component demonstrates how to group markers and toggle its visibility
function MarkersGroup(props, context) {
const layersRef = useRef(null);
useEffect(() => {
const map = context[MAP];
let layers = null;
if (!layersRef.current) {
layers = new window.google.maps.MVCObject();
for (let name in props.groupData) {
for (let item of props.groupData[name].items) {
const markerProps = { position: { lat: item.lat, lng: item.lng } };
const marker = new window.google.maps.Marker(markerProps);
marker.bindTo("map", layers, name);
}
}
layersRef.current = layers;
} else layers = layersRef.current;
for (let name in props.groupData) {
if (props.groupData[name].visible) {
layers.set(name, map);
} else {
layers.set(name, null);
}
}
});
return null;
}
Notes:
google.maps.MVCObject class - is used to store layer(markers) group
layer visibility is toggled via MVCObject.set method
Here is a demo

How to use ranges saved to React state - Microsoft Word javascript API?

I am using the Microsoft Word Javascript API. I have used the .search() function to retrieve an array of ranges and then have saved them to state.definitions in my App.js React component state. This part works. When I try to print out the state using console.log(JSON.stringify(this.state.definitions)), I see the ranges that I just saved.
In a separate function, I want to retrieve those ranges and highlight them in a new color. This part does not work. I don't get any errors, but I don't see any highlight changes in the document.
Interestingly, if I try to highlight the ranges BEFORE saving them to state, it works. This makes me think that the ranges that I am retrieving from state are not actually the ranges understood by Word.
Any help would be much appreciated.
var flattenedTerms contains an array of range items that were retrieved from Word a few lines above. This code successfully changes the font
for (var i = 0; i < flattenedTerms.length; i++) {
console.log('flattenedTerms: ', flattenedTerms[i]);
flattenedTerms[i].font.color = 'purple';
flattenedTerms[i].font.highlightColor = 'pink';
flattenedTerms[i].font.bold = true;
}
return context.sync().then(function () {
return resolve(flattenedTerms);
})
})
Now the flattenedTerms array, which contains the range items, has been saved to state.definitions using this.setState. This fails to change the font. All of the console.logs do print.
highlightDefinedTerms = () => {
var self = this;
return Word.run(
function (context) {
var definitions = self.state.definitions;
console.log('Highlighting ', definitions.length, ' terms.');
for (var i = 0; i < definitions.length; i++) {
console.log('Highlighting definition: ', JSON.stringify(definitions[i]));
definitions[i].font.color = 'blue';
definitions[i].font.highlightColor = 'red';
definitions[i].font.bold = true;
}
return context.sync();
}
)
}
You need to pass a first parameter to “Word.run” to specify the object whose context you want to resume.
Word.run(self.state.definitions, function(context) ...)

passing an array in a message from content script to background page in google chrome extension

I am writing a Google Chrome extension.
I want to pass a small array from a content script to background page in a message. Can I simply reference the array name or need I construct a JSON object from it first?
Here is the code:
IN THE CONTENT SCRIPT
var req;
var detailWin;
//drag off the f_foto class
var searchResult = document.getElementsByClassName("f_foto");
alert("Found Class f_foto "+searchResult.length+" times.");
//collect profile links
for (var i = 0; i<searchResult.length; ++i)
{
var profileLink=searchResult[i].getElementsByTagName("a");
profileLinks[i]=profileLink[0].href;
// alert(i+1+" of "+searchResult.length+" "+profileLinks[i]+" length of "+profileLinks[i].length);
}
for (var i = 0; i<searchResult.length; ++i)
{
//tell bkgd page to open link
chrome.extension.sendRequest({cmd: "openProfile", url: profileLinks[i]});
//BETTER TO SEND WHOLE ARRAY.
//LIKE THIS? chrome.extension.sendRequest({cmd: "openProfile", urlList: profileLinks});
//OR SHOULD I MAKE A JSON OBJECT OUT OF IT?
}
//IN THE BACKGROUND PAGE
var detailTabId = null;
var profileLinks = new Array();
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if(request.cmd == "openProfile") {
//IF RECEIVING AN ARRAY, PROCESS IT LIKE THIS?
// profileLinks= request.urlList;
// console.log=("Received "+ urlList.length + " links.");
chrome.tabs.create({url: request.url}, function(tab){
//save tab id so we can close this tab later
detailTabId = tab.id;
//profile tab is created, inject profile script
chrome.tabs.executeScript(tab.id, {file: "profile.js"});
});
}
});
An Array is a construct of a JSON object so there is no need to do anything other than what you are doing now.

Resources