mirror of
https://github.com/maputnik/editor.git
synced 2026-08-25 14:37:27 +00:00
Fix missing font auto complete menu (#1491)
## Launch Checklist This fixes the position of the autocomplete list - CSS fix mostly. It also changes the loading of the metadata to be using promises instead of callbacks. I couldn't reproduce the following issue, so I'll be closing it for now. - Fixes #945 Before: <img width="563" height="577" alt="image" src="https://github.com/user-attachments/assets/6ea264e1-cb85-4a8a-8df5-ab50e7815333" /> After: <img width="563" height="577" alt="image" src="https://github.com/user-attachments/assets/27fa2901-dd96-44fd-9774-363fd4c5ed98" /> - [x] Briefly describe the changes in this PR. - [x] Link to related issues. - [x] Include before/after visuals or gifs if this PR includes visual changes. --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
@@ -207,6 +207,20 @@ describe("layer editor", () => {
|
|||||||
it("compound filter");
|
it("compound filter");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("layout", () => {
|
||||||
|
it("text-font", () => {
|
||||||
|
when.setStyle("font");
|
||||||
|
when.collapseGroupInLayerEditor();
|
||||||
|
when.collapseGroupInLayerEditor(1);
|
||||||
|
when.collapseGroupInLayerEditor(2);
|
||||||
|
when.doWithin("spec-field:text-font", () => {
|
||||||
|
get.element(".maputnik-autocomplete input").first().click();
|
||||||
|
});
|
||||||
|
then(get.element(".maputnik-autocomplete-menu-item")).shouldBeVisible();
|
||||||
|
then(get.element(".maputnik-autocomplete-menu-item")).shouldHaveLength(3);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("paint", () => {
|
describe("paint", () => {
|
||||||
it("expand/collapse");
|
it("expand/collapse");
|
||||||
it("color");
|
it("color");
|
||||||
|
|||||||
@@ -85,6 +85,13 @@ export class MaputnikDriver {
|
|||||||
fixture: "rectangles-style.json",
|
fixture: "rectangles-style.json",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
this.helper.given.interceptAndMockResponse({
|
||||||
|
method: "GET",
|
||||||
|
url: baseUrl + "example-style-with-fonts.json",
|
||||||
|
response: {
|
||||||
|
fixture: "example-style-with-fonts.json",
|
||||||
|
},
|
||||||
|
});
|
||||||
this.helper.given.interceptAndMockResponse({
|
this.helper.given.interceptAndMockResponse({
|
||||||
method: "GET",
|
method: "GET",
|
||||||
url: "*example.local/*",
|
url: "*example.local/*",
|
||||||
@@ -95,6 +102,11 @@ export class MaputnikDriver {
|
|||||||
url: "*example.com/*",
|
url: "*example.com/*",
|
||||||
response: [],
|
response: [],
|
||||||
});
|
});
|
||||||
|
this.helper.given.interceptAndMockResponse({
|
||||||
|
method: "GET",
|
||||||
|
url: "https://www.glyph-server.com/*",
|
||||||
|
response: ["Font 1", "Font 2", "Font 3"],
|
||||||
|
});
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,7 +126,7 @@ export class MaputnikDriver {
|
|||||||
this.helper.when.wait(200);
|
this.helper.when.wait(200);
|
||||||
},
|
},
|
||||||
setStyle: (
|
setStyle: (
|
||||||
styleProperties: "geojson" | "raster" | "both" | "layer" | "rectangles" | "",
|
styleProperties: "geojson" | "raster" | "both" | "layer" | "rectangles" | "font" | "",
|
||||||
zoom?: number
|
zoom?: number
|
||||||
) => {
|
) => {
|
||||||
const url = new URL(baseUrl);
|
const url = new URL(baseUrl);
|
||||||
@@ -134,6 +146,9 @@ export class MaputnikDriver {
|
|||||||
case "rectangles":
|
case "rectangles":
|
||||||
url.searchParams.set("style", baseUrl + "rectangles-style.json");
|
url.searchParams.set("style", baseUrl + "rectangles-style.json");
|
||||||
break;
|
break;
|
||||||
|
case "font":
|
||||||
|
url.searchParams.set("style", baseUrl + "example-style-with-fonts.json");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (zoom) {
|
if (zoom) {
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"id": "test-style",
|
||||||
|
"version": 8,
|
||||||
|
"name": "Test Style",
|
||||||
|
"metadata": {
|
||||||
|
"maputnik:renderer": "mlgljs"
|
||||||
|
},
|
||||||
|
"sources": {
|
||||||
|
"example": {
|
||||||
|
"type": "geojson",
|
||||||
|
"data": {
|
||||||
|
"type": "FeatureCollection",
|
||||||
|
"features":[{
|
||||||
|
"type": "Feature",
|
||||||
|
"properties": {
|
||||||
|
"name": "Dinagat Islands"
|
||||||
|
},
|
||||||
|
"geometry":{
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [125.6, 10.1]
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"glyphs": "https://www.glyph-server.com/fonts/{fontstack}/{range}.pbf",
|
||||||
|
"sprites": "https://example.local/fonts/{fontstack}/{range}.pbf",
|
||||||
|
"layers": [
|
||||||
|
{
|
||||||
|
"id": "label",
|
||||||
|
"type": "symbol",
|
||||||
|
"source": "example",
|
||||||
|
"layout": {
|
||||||
|
"text-font": ["Font"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -294,13 +294,13 @@ export default class App extends React.Component<any, AppState> {
|
|||||||
const accessToken = metadata["maputnik:openmaptiles_access_token"] || tokens.openmaptiles;
|
const accessToken = metadata["maputnik:openmaptiles_access_token"] || tokens.openmaptiles;
|
||||||
|
|
||||||
const glyphUrl = (typeof urlTemplate === "string")? urlTemplate.replace("{key}", accessToken): urlTemplate;
|
const glyphUrl = (typeof urlTemplate === "string")? urlTemplate.replace("{key}", accessToken): urlTemplate;
|
||||||
downloadGlyphsMetadata(glyphUrl, fonts => {
|
downloadGlyphsMetadata(glyphUrl).then(fonts => {
|
||||||
this.setState({ spec: updateRootSpec(this.state.spec, "glyphs", fonts)});
|
this.setState({ spec: updateRootSpec(this.state.spec, "glyphs", fonts)});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
updateIcons(baseUrl: string) {
|
updateIcons(baseUrl: string) {
|
||||||
downloadSpriteMetadata(baseUrl, icons => {
|
downloadSpriteMetadata(baseUrl).then(icons => {
|
||||||
this.setState({ spec: updateRootSpec(this.state.spec, "sprite", icons)});
|
this.setState({ spec: updateRootSpec(this.state.spec, "sprite", icons)});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-29
@@ -1,44 +1,39 @@
|
|||||||
import npmurl from "url";
|
async function loadJSON<T>(url: string, defaultValue: T): Promise<T> {
|
||||||
|
try {
|
||||||
function loadJSON(url: string, defaultValue: any, cb: (...args: any[]) => void) {
|
const response = await fetch(url, {
|
||||||
fetch(url, {
|
mode: "cors",
|
||||||
mode: "cors",
|
credentials: "same-origin"
|
||||||
credentials: "same-origin"
|
|
||||||
})
|
|
||||||
.then((response) => {
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error("Failed to load metadata for " + url);
|
|
||||||
}
|
|
||||||
return response.json();
|
|
||||||
})
|
|
||||||
.then((body) => {
|
|
||||||
cb(body);
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
console.warn("Can not load metadata for " + url + ", using default value " + defaultValue);
|
|
||||||
cb(defaultValue);
|
|
||||||
});
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to load metadata for " + url);
|
||||||
|
}
|
||||||
|
return await response.json();
|
||||||
|
} catch {
|
||||||
|
console.warn("Can not load metadata for " + url + ", using default value " + defaultValue);
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function downloadGlyphsMetadata(urlTemplate: string, cb: (...args: any[]) => void) {
|
export async function downloadGlyphsMetadata(urlTemplate: string): Promise<string[]> {
|
||||||
if(!urlTemplate) return cb([]);
|
if(!urlTemplate) return [];
|
||||||
|
|
||||||
// Special handling because Tileserver GL serves the fontstacks metadata differently
|
// Special handling because Tileserver GL serves the fontstacks metadata differently
|
||||||
// https://github.com/klokantech/tileserver-gl/pull/104#issuecomment-274444087
|
// https://github.com/klokantech/tileserver-gl/pull/104#issuecomment-274444087
|
||||||
const urlObj = npmurl.parse(urlTemplate);
|
const urlObj = new URL(urlTemplate);
|
||||||
const normPathPart = "/%7Bfontstack%7D/%7Brange%7D.pbf";
|
const normPathPart = "/" + encodeURIComponent("{fontstack}") + "/" + encodeURIComponent("{range}") + ".pbf";
|
||||||
if(urlObj.pathname === normPathPart) {
|
if(urlObj.pathname === normPathPart) {
|
||||||
urlObj.pathname = "/fontstacks.json";
|
urlObj.pathname = "/fontstacks.json";
|
||||||
} else {
|
} else {
|
||||||
urlObj.pathname = urlObj.pathname!.replace(normPathPart, ".json");
|
urlObj.pathname = urlObj.pathname!.replace(normPathPart, ".json");
|
||||||
}
|
}
|
||||||
const url = npmurl.format(urlObj);
|
const url = urlObj.toString();
|
||||||
|
const fonts = await loadJSON(url, [] as string[]);
|
||||||
loadJSON(url, [], cb);
|
return [...new Set(fonts)];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function downloadSpriteMetadata(baseUrl: string, cb: (...args: any[]) => void) {
|
export async function downloadSpriteMetadata(baseUrl: string): Promise<string[]> {
|
||||||
if(!baseUrl) return cb([]);
|
if(!baseUrl) return [];
|
||||||
const url = baseUrl + ".json";
|
const url = baseUrl + ".json";
|
||||||
loadJSON(url, {}, glyphs => cb(Object.keys(glyphs)));
|
const glyphs = await loadJSON(url, {} as Record<string, string>);
|
||||||
|
return Object.keys(glyphs);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -198,7 +198,7 @@
|
|||||||
border: none;
|
border: none;
|
||||||
padding: 2px 0;
|
padding: 2px 0;
|
||||||
margin-right: 10px;
|
margin-right: 10px;
|
||||||
position: absolute;
|
position: absolute !important;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
max-height: 50%;
|
max-height: 50%;
|
||||||
background: vars.$color-gray;
|
background: vars.$color-gray;
|
||||||
|
|||||||
Reference in New Issue
Block a user