Skip to content

Commit

Permalink
Merge pull request #251 from DigitalCommons/230-initiative-filtering-ui
Browse files Browse the repository at this point in the history
MM-230 Use common panel to display search results and include # of co-ops filtered
  • Loading branch information
rogup authored Jun 3, 2024
2 parents e333c07 + 5747de6 commit cd4db51
Show file tree
Hide file tree
Showing 20 changed files with 537 additions and 629 deletions.
2 changes: 1 addition & 1 deletion DEVELOPMENT.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ mykomap's repository:
Install the prerequisites

apt install php php-curl rsync # On Debian
npm run install
npm install

Run the development web server in the background (do this in a separate console):

Expand Down
88 changes: 53 additions & 35 deletions src/map-app/app/map-ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ 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 { toString as _toString, canDisplayExpandedSidebar } from '../utils';
import { Action, AppState, PropEquality, StateManager, TextSearch } from "./state-manager";
import { StateChange } from "../undo-stack";
import { Dictionary } from "../common-types";
Expand Down Expand Up @@ -48,7 +48,8 @@ export class MapUI {
});
};

EventBus.Directory.initiativeClicked.sub(initiative => this.onInitiativeClickedInSidebar(initiative));
EventBus.Map.initiativeClicked.sub(initiative => this.onInitiativeClicked(initiative));
EventBus.Map.clearFiltersAndSearch.sub(() => this.clearFiltersAndSearch());
}

// This inspects the config and constructs an appropriate set of
Expand Down Expand Up @@ -99,6 +100,7 @@ export class MapUI {
onNewInitiatives() {
const loadedInitiatives = this.dataServices.getAggregatedData().loadedInitiatives;
this.stateManager.reset(loadedInitiatives);
this.refreshSidebar();
}

createPresenter(): MapPresenter {
Expand All @@ -113,8 +115,8 @@ export class MapUI {
this.stateManager.clearPropFilter(filterName);
}

resetSearch(): void {
this.stateManager.reset();
clearFiltersAndSearch(): void {
this.stateManager.clearFiltersAndSearch();
}

/// Returns a list of property values matching the given filter
Expand All @@ -131,36 +133,38 @@ export class MapUI {
throw new Error(`an attempt to add a filter on an unknown propery name '${propName}'`);

const isMulti = propDef.type === 'multi';
if (value === undefined)
if (value === undefined) {
this.stateManager.clearPropFilter(propName);
else
} else {
this.stateManager.propFilter(new PropEquality(propName, value, isMulti));
}

if (canDisplayExpandedSidebar()) // on smaller screens, wait until user clicks Show Results
EventBus.Sidebar.showInitiativeList.pub();
}

isSelected(initiative: Initiative): boolean {
// Currently unimplemented - I can see an sea-initiative-active class
// being applied if a test was true, but it makes no sense in the current
// context AFAICT. The test was:
// initiative === this.contextStack.current()?.initiatives[0]

// The main thing is seemed to do is highlight an initiative (or
// initiatives) in the directory pop-out list of initiatives in a
// category.

// For now, just return false always. We may re-implement this later.
return false;
const selectedInitiatives = this.mapPresenter?.getSelectedInitiatives() ?? [];
return selectedInitiatives.includes(initiative);
}

toggleSelectInitiative(initiative: Initiative) {
// Currently unimplemented.
const selectedInitiatives = this.mapPresenter?.getSelectedInitiatives() ?? [];

// EventBus.Markers.needToShowLatestSelection.pub(lastContent.initiatives);
if (selectedInitiatives.includes(initiative)) {
EventBus.Markers.needToShowLatestSelection.pub(selectedInitiatives.filter(i => i !== initiative));
} else {
EventBus.Markers.needToShowLatestSelection.pub([...selectedInitiatives, initiative]);
}
}


performSearch(text: string) {
console.log("Search submitted: [" + text + "]");
this.stateManager.textSearch(new TextSearch(text));

if (canDisplayExpandedSidebar()) {// on smaller screens, wait until user clicks Show Results
EventBus.Sidebar.showInitiativeList.pub();
}
}

// Text to show in the search box
Expand All @@ -182,26 +186,40 @@ export class MapUI {
}

private refreshSidebar() {
this.getSidebarPresenter(this).then((presenter) => presenter.changeSidebar());
this.getSidebarPresenter(this).then((presenter) => {
presenter.refreshSidebar();
});
}



private notifyMapNeedsToNeedsToBeZoomedAndPannedOneInitiative(initiative: Initiative) {
const data = EventBus.Map.mkSelectAndZoomData([initiative]);
EventBus.Map.needsToBeZoomedAndPanned.pub(data);
private notifyMapNeedsToNeedsToSelectAndZoomOnInitiative(initiative: Initiative) {
const maxZoom = this.config.getMaxZoomOnOne();
const defaultPos = this.config.getDefaultLatLng();

const data = EventBus.Map.mkSelectAndZoomData([initiative], { maxZoom, defaultPos });
EventBus.Map.selectAndZoomOnInitiative.pub(data);
}

private onInitiativeClickedInSidebar(initiative?: Initiative) {
if (!initiative)
return;
private onInitiativeClicked(initiative?: Initiative) {
console.log('Clicked', initiative);

//this.parent.mapui.stateManager.append(new SearchResults([initiative]));
//console.log(this.parent.mapui.stateManager.current());

this.notifyMapNeedsToNeedsToBeZoomedAndPannedOneInitiative(initiative);
this.refreshSidebar();
EventBus.Initiative.searchedInitiativeClicked.pub(initiative);
if (initiative) {
// Move the window to the right position first
this.notifyMapNeedsToNeedsToSelectAndZoomOnInitiative(initiative);
// Populate the sidebar and highlight the intiative in the directory
this.getSidebarPresenter(this).then((presenter) => {
presenter.populateInitiativeSidebar(
initiative,
this.markers.getInitiativeContent(initiative) ?? ''
);
});
}
else {
// User has deselected
EventBus.Markers.needToShowLatestSelection.pub([]);
this.getSidebarPresenter(this).then((presenter) => {
presenter.hideInitiativeSidebar();
});
}
}

currentItem() {
Expand Down
15 changes: 9 additions & 6 deletions src/map-app/app/presenter/map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { MapUI } from '../map-ui';

export class MapPresenter extends BasePresenter {
readonly view: MapView;
private previouslySelected: Initiative[] = [];
private currentlySelected: Initiative[] = [];

constructor(readonly mapUI: MapUI) {
super();
Expand All @@ -35,7 +35,7 @@ export class MapPresenter extends BasePresenter {
EventBus.Initiatives.loadStarted.sub(() => this.onInitiativeLoadMessage());
EventBus.Initiatives.loadFailed.sub(error => this.onInitiativeLoadMessage(error));

EventBus.Markers.needToShowLatestSelection.sub(initiative => this.onMarkersNeedToShowLatestSelection(initiative));
EventBus.Markers.needToShowLatestSelection.sub(initiatives => this.onMarkersNeedToShowLatestSelection(initiatives));
EventBus.Map.needsToBeZoomedAndPanned.sub(data => this.onMapNeedsToBeZoomedAndPanned(data));
EventBus.Map.needToShowInitiativeTooltip.sub(initiative => this.onNeedToShowInitiativeTooltip(initiative));
EventBus.Map.needToHideInitiativeTooltip.sub(initiative => this.onNeedToHideInitiativeTooltip(initiative));
Expand All @@ -49,7 +49,7 @@ export class MapPresenter extends BasePresenter {
}

onInitiativeClicked() {
EventBus.Directory.initiativeClicked.pub(undefined);
EventBus.Map.initiativeClicked.pub(undefined);
}

onLoad() {
Expand Down Expand Up @@ -88,19 +88,19 @@ export class MapPresenter extends BasePresenter {
console.log("onInitiativeComplete");

// Call this last so map will have bounds set (else error!)
this.mapUI.onNewInitiatives();
this.mapUI.onNewInitiatives();
}

private onInitiativeLoadMessage(error?: EventBus.Initiatives.DatasetError) {
this.view.startLoading(error);
}

onMarkersNeedToShowLatestSelection(selected: Initiative[]) {
this.previouslySelected.forEach((initiative) => {
this.currentlySelected.forEach((initiative) => {
this.mapUI.markers.setUnselected(initiative);
});

this.previouslySelected = selected;
this.currentlySelected = selected;

//zoom in and then select
selected.forEach((initiative) => {
Expand Down Expand Up @@ -144,4 +144,7 @@ export class MapPresenter extends BasePresenter {
this.view.selectAndZoomOnInitiative(data);
}

getSelectedInitiatives(): Initiative[] {
return this.currentlySelected;
}
}
65 changes: 53 additions & 12 deletions src/map-app/app/presenter/sidebar.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { EventBus } from '../../eventbus';
import { MapUI } from '../map-ui';
import { Initiative } from '../model/initiative';
import { SidebarView } from '../view/sidebar';
import { BasePresenter } from './base';
import { AboutSidebarPresenter } from './sidebar/about';
Expand Down Expand Up @@ -58,28 +59,30 @@ export class SidebarPresenter extends BasePresenter {

this.changeSidebar(defaultPanel);
}

// Changes or refreshes the sidebar
//
// @param name - the sidebar to change

/**
* Changes the sidebar
* @param name the sidebar to change (needs to be one of the keys of this.sidebar)
*/
changeSidebar(name?: SidebarId): void {
if (!name) {
if (this.sidebarName) {
// Just refresh the currently showing sidebar.
this.children[this.sidebarName]?.refreshView();
this.children[this.sidebarName]?.refreshView(false);
}
else {
// If nothing is showing, refresh the first in the list. Or nothing, if none.
// If no sidebar is set, pick the first one
let key: SidebarId;
for(key in this.children) {
const child = this.children[key];
if (!child)
continue;

this.sidebarName = key;
child.refreshView();
child.refreshView(true);
break;
}
console.warn('No sidebars to show');
}
return;
}
Expand All @@ -89,7 +92,7 @@ export class SidebarPresenter extends BasePresenter {
const child = this.children[name];
if (child !== undefined) {
this.sidebarName = name;
child.refreshView();
child.refreshView(true);
}
return;
}
Expand All @@ -101,6 +104,34 @@ export class SidebarPresenter extends BasePresenter {
);
}

/**
* Fully refresh the sidebar
*/
refreshSidebar() {
if (this.sidebarName) {
this.children[this.sidebarName]?.refreshView(true);
} else {
// If no sidebar is set, pick the first one
let key: SidebarId;
for(key in this.children) {
const child = this.children[key];
if (!child)
continue;

this.sidebarName = key;
child.refreshView(true);
break;
}
console.warn('No sidebars to show');
}

// If we get here it's not a valid sidebar (possibly it wasn't configured)
console.warn(
"Attempting to call SidebarPresenter.changeSidebar() with a "+
`non-existant sidebar '${name}' - ignoring.`
);
}

showSidebar() {
this.view.showSidebar();
}
Expand All @@ -118,6 +149,14 @@ export class SidebarPresenter extends BasePresenter {
this.view.hideInitiativeSidebar();
}

populateInitiativeSidebar(initiative: Initiative, initiativeContent: string) {
this.view.populateInitiativeSidebar(initiative, initiativeContent);
}

showInitiativeList() {
this.view.showInitiativeList();
}

hideInitiativeList() {
this.view.hideInitiativeList();
}
Expand All @@ -133,18 +172,20 @@ export class SidebarPresenter extends BasePresenter {
});
EventBus.Sidebar.showDirectory.sub(() => {
this.changeSidebar("directory");
this.view.showInitiativeList();
this.showSidebar();
});
EventBus.Sidebar.showDatasets.sub(() => {
this.changeSidebar("datasets");
this.showSidebar();
});
EventBus.Sidebar.showSidebar.sub(() => this.showSidebar());
EventBus.Sidebar.hideSidebar.sub(() => this.hideSidebar());
EventBus.Sidebar.hideInitiativeSidebar.sub(() => this.hideInitiativeSidebar());
EventBus.Sidebar.showInitiativeList.sub(() => this.showInitiativeList());
EventBus.Sidebar.hideInitiativeList.sub(() => this.hideInitiativeList());
EventBus.Initiatives.reset.sub(() => this.changeSidebar());
EventBus.Initiatives.loadComplete.sub(() => this.changeSidebar());
EventBus.Initiatives.reset.sub(() => {
this.changeSidebar();
this.hideInitiativeList();
});
}

}
Expand Down
Loading

0 comments on commit cd4db51

Please sign in to comment.