UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

111 lines (110 loc) • 4.57 kB
// SPDX-License-Identifier: Apache-2.0 import { isStreetViewProviderConfigured } from '../configuration/streetviewconfig.js'; /** * The available Layouts of the Map Grid, defined by the Cells of each of their rows: * each number is the number of columns the Cell spans. * The name of a Layout is <number of columns>x<number of rows> when all its Cells have the same size, * or <cells of the first row>+<cells of the second row> when a Cell spans the whole width. */ const LAYOUTS = { '1x1': [[1]], '2x1': [[1, 1]], '1x2': [[1], [1]], '2x2': [ [1, 1], [1, 1] ], '2+1': [[1, 1], [2]], '1+2': [[2], [1, 1]] }; export const LAYOUT_TYPES = Object.keys(LAYOUTS); /** Minimal size of a Column or of a Row of the Grid, in percent of the Grid. */ export const MIN_CELL_SIZE = 15; /** Maximal size of a Column or of a Row of the Grid, in percent of the Grid. */ export const MAX_CELL_SIZE = 85; /** * The Components that can be displayed in a Cell of the Grid. * To make a new Component available to the user, it is enough to add it to this list * (and to add its Element to the Grid in the HTML of the application). * A StreetView is only available when its provider is configured. */ export const AVAILABLE_CELL_COMPONENTS = [ { id: 'map-2d', tagName: 'girafe-map-2d', label: '2D Map' }, { id: 'map-3d', tagName: 'girafe-map-3d', label: '3D Map' }, { id: 'streetview-google', tagName: 'girafe-streetview-google', label: 'Google Street View', provider: 'google' } ]; export function isLayoutType(value) { return LAYOUT_TYPES.includes(value); } export function isCellComponent(value) { return AVAILABLE_CELL_COMPONENTS.some((component) => component.id === value); } function getProvider(component) { return 'provider' in component ? component.provider : undefined; } /** Whether a Component can be offered to the user: a StreetView needs the configuration of its provider. */ export function isCellComponentAvailable(id, streetviewConfig) { const component = AVAILABLE_CELL_COMPONENTS.find((candidate) => candidate.id === id); const provider = component ? getProvider(component) : undefined; return provider === undefined || isStreetViewProviderConfigured(streetviewConfig, provider); } function getLayoutRows(type) { return LAYOUTS[type]; } function sumOf(values) { return values.reduce((total, value) => total + value, 0); } /** The number of columns and of rows of a Layout. */ export function getGridSize(type) { const rows = getLayoutRows(type); const columns = Math.max(...rows.map((spans) => sumOf(spans))); return { columns: columns, rows: rows.length }; } /** The Cells of a Layout, in the order they are indexed: row by row, from left to right. */ export function getLayoutCells(type) { const cells = []; for (const [row, spans] of getLayoutRows(type).entries()) { let column = 0; for (const columnSpan of spans) { cells.push({ row: row, column: column, columnSpan: columnSpan }); column += columnSpan; } } return cells; } /** The sizes, in percent, of the equally distributed columns and rows of a Layout. */ export function getDefaultSizes(type) { const { columns, rows } = getGridSize(type); return { columns: new Array(columns).fill(100 / columns), rows: new Array(rows).fill(100 / rows) }; } /** * Distributes the Components on the Cells of a Layout. * The Components that are already placed keep their Cell as long as it still exists, * and the Cells that are added by the new Layout are left empty: a Component is only * displayed when the user explicitly chooses it, so that the libraries it needs * (Cesium, Google Maps, ...) are not loaded unnecessarily. */ export function distributeCells(type, currentCells) { const cellCount = getLayoutCells(type).length; const cells = currentCells.slice(0, cellCount); while (cells.length < cellCount) { cells.push(null); } return cells; } /** * The Layout of the Map Grid: which Layout is displayed, which Component is displayed * in each of its Cells, and the sizes of its columns and rows (in percent), * which the user can change by dragging the splitters. * * The Cells are indexed row by row: in a 2x2 Layout, the Cell 0 is the top-left one, * the Cell 1 the top-right one, the Cell 2 the bottom-left one and the Cell 3 the bottom-right one. */ export default class LayoutState { type = '1x1'; cells = ['map-2d']; sizes = { columns: [100], rows: [100] }; }