Skip to content

Commit

Permalink
Merge branch 'mm204-filter-config' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
Nick Stokoe committed Mar 29, 2024
2 parents 5a35916 + d9d9bdf commit 30f15e5
Show file tree
Hide file tree
Showing 16 changed files with 304 additions and 134 deletions.
34 changes: 23 additions & 11 deletions CONFIG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ is essentially an empty object, but that would result in a totally empty map.

For the sake of illustration, here is an example of what you might put
in this parameter for a map with pins which have a `size`,
`description` and `address` field, in addition of the hard-wired
bare minimum fields of `uri`, `name`, `lat` and `lng`. The
`description` and `address` properties, in addition of the hard-wired
bare minimum properties of `uri`, `name`, `lat` and `lng`. The
`size` field can be one of several pre-defined values - a taxonomy,
also known as a vocabulary. Because of the `filterableFields`
attribute, there will be a single drop-down on the search panel for this
narrowing the displayed pins by values of this field.
also known as a vocabulary. Because of the presence of a `filter`
attribute of `size`, there will be a single drop-down on the search
panel for this narrowing the displayed pins by values of this field.

```
import { ConfigData } from "mykomap/app/model/config-schema";
Expand All @@ -36,14 +36,14 @@ import { InitiativeObj } from "mykomap/src/map-app/app/model/initiative";
const config: ConfigData = {
htmlTitle: "Outlets",
fields: {
propDefs: { // the old name for this is 'fields', but deprecated
address: 'value',
size: {
type: 'vocab',
uri: 'sz:',
filter: undefined,
},
},
filterableFields: ["size"],
vocabularies: [
{
type: 'json',
Expand Down Expand Up @@ -76,7 +76,7 @@ This config would need to be accompanied with a `example.json` file
defining the vocabs, and a data file `example.csv`. Both of these
can be supplied in map project source code in the `www/` directory,
or an URL to elsewhere can be supplied. The `transform` attribute defines
the mapping from CSV fields to map pin fields.
the mapping from CSV fields to map pin properties.

The vocabs file might look like this, which defines one vocabulary: size,
represented in the config by the abbreviated base URI `sz:`. The language
Expand Down Expand Up @@ -248,10 +248,10 @@ True if the directory should feature coloured entries

- *type:* `{PropDefs}` A dictionary of initiative property definitions, or just a property type string, keyed by property id
- *in string context:* parsed as-is
- *default:* `[object Object]`
- *default:* `undefined`
- *settable?:* no

Defines extended definitions of new or existing initiative fields
If present, defines extended definitions of extended or existing initiative fields (deprecated - use propDefs going forward)



Expand Down Expand Up @@ -426,6 +426,18 @@ Responses to SPARQL queries will normally be cached in /services/locCache.txt if



### `propDefs`

- *type:* `{PropDefs}` A dictionary of initiative property definitions, or just a property type string, keyed by property id
- *in string context:* parsed as-is
- *default:* `[object Object]`
- *settable?:* no

Defines extended definitions of extended or existing initiative properties




### `searchedFields`

- *type:* `{string[]}` An array of strings.
Expand Down Expand Up @@ -563,7 +575,7 @@ The name of the variant used to generate this map application.
- *default:* No vocabs are queried if nothing is provided
- *settable?:* no

Specifies the vocabularies to obtain via SPARQL query for use in `fields`
Specifies the vocabularies to obtain via SPARQL query for use in `propDefs`



Expand Down
39 changes: 37 additions & 2 deletions src/map-app/app/map-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import { Map } from "./map";
import { MapPresenter } from "./presenter/map";
import { MarkerManager } from "./marker-manager";
import { Config } from "./model/config";
import { DataServices } from "./model/data-services";
import { DataServices, isVocabPropDef } from "./model/data-services";
import { EventBus } from "../eventbus";
import "./map"; // Seems to be needed to prod the leaflet CSS into loading.
import { SidebarPresenter } from "./presenter/sidebar";
import { PhraseBook } from "../localisations";
import { toString as _toString } from '../utils';
import { Action, AppState, PropEquality, StateManager, TextSearch } from "./state-manager";
import { StateChange } from "../undo-stack";
import { Dictionary } from "../common-types";

export class MapUI {
public map?: Map;
Expand All @@ -28,7 +29,12 @@ export class MapUI {
this.labels = this.dataServices.getFunctionalLabels();

const allInitiatives = new Set(dataServices.getAggregatedData().loadedInitiatives);
const initialState = new AppState(allInitiatives, allInitiatives);
const initialFilters = this.mkInitialFilters();

const initialState = AppState.startState(allInitiatives, undefined, initialFilters);

// Set the intial state when constructing the StateManager. This will be the state
// to which a reset returns to.
this.stateManager = new StateManager(initialState, change => this.onStateChange(change));

// This is here to resolve a circular dependency loop - MapUI needs the SidebarView
Expand All @@ -45,6 +51,35 @@ export class MapUI {
EventBus.Directory.initiativeClicked.sub(initiative => this.onInitiativeClickedInSidebar(initiative));
}

// This inspects the config and constructs an appropriate set of
// filters to construct the initial AppState with.
static mkInitialFilters(config: Config): Dictionary<PropEquality> {
const filters: Dictionary<PropEquality> = {};
const filteredFields = config.getFilteredPropDefs();
for(const name in filteredFields) {
const propDef = filteredFields[name];
const filter = propDef.filter;
if (filter != undefined) {
// If we get here, this property should have a default filter
// value set.

// We can only filter Vocab properties (single or multi), so check that.
if (isVocabPropDef(propDef)) {
filters[name] = new PropEquality(
name, filter, propDef.type === 'multi'
);
}
}
}
return filters;
}

// This inspects the MapUI's config and constructs an appropriate
// set of filters to construct the initial AppState with.
private mkInitialFilters() {
return MapUI.mkInitialFilters(this.config);
}

createMap() {
if (this.mapPresenter) return;

Expand Down
Loading

0 comments on commit 30f15e5

Please sign in to comment.