Skip to content

Commit

Permalink
Merge branch 'develop' into feature/search-listing-hide-form-option
Browse files Browse the repository at this point in the history
# Conflicts:
#	packages/ripple-tide-search/types.ts
  • Loading branch information
David Featherston committed Jan 11, 2024
2 parents a133185 + 502b674 commit 7b3699a
Show file tree
Hide file tree
Showing 174 changed files with 135,645 additions and 608 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
"@dpc-sdp/nuxt-ripple-cli",
"@dpc-sdp/ripple-test-utils",
"@dpc-sdp/nuxt-ripple-analytics",
"eslint-config-ripple"
"eslint-config-ripple",
"@dpc-sdp/ripple-ui-maps"
],
"cSpell.words": [
"colour",
Expand Down
75 changes: 75 additions & 0 deletions examples/nuxt-app/app.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,81 @@ export default defineAppConfig({
providedValues: values
}
}
},
locationDSLTransformFunctions: {
// DSL transform example for VSBA map tests
schoolBuildings: async (location) => {
return {
map: {
filter: null,
sort: null
},
listing: {
filter: location.name
? {
terms: {
[`field_suburb.keyword`]: [location.name]
}
}
: null,
sort: null
}
}
},
csl: async (location) => {
const serviceUrl = `https://services6.arcgis.com/GB33F62SbDxJjwEL/arcgis/rest/services/Vicmap_Admin/FeatureServer`
const layer = '9'
const format = 'pgeojson'
const query = encodeURIComponent(`LGA_NAME='${location.lga_key}'`)
const url = `${serviceUrl}/${layer}/query/?where=${query}&f=${format}&returnGeometry=true&spatialRel=esriSpatialRelIntersects&geometryType=esriGeometryEnvelope`

const response = await $fetch(url)

const listingFilter = response?.features[0]?.geometry
? {
geo_shape: {
location: {
shape: response?.features[0]?.geometry,
relation: 'within'
}
}
}
: null
return {
map: {
filter: null,
sort: null
},
listing: {
filter: listingFilter,
sort: null
}
}
}
},
mapPinStyleFn: {
vsbaPinIcons: (feature) => {
const projectType =
feature && feature['field_mappintype_name']
? feature['field_mappintype_name'][0]
: ''
switch (projectType) {
case 'New school':
return '#8A2A2B'
case 'School upgrade':
return '#df4809'
case 'Planning project':
return '#FF9E1B'
case 'Early childhood':
return '#87189D'
case 'Tech school':
return '#00B2A9'
case 'Non-government grant':
return '#71C5E8'
default:
return '#333333'
}
}
}
}
}
Expand Down
171 changes: 171 additions & 0 deletions examples/nuxt-app/components/global/VSBAProjectAreaLayer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
<template>
<ol-vector-layer
v-if="results.length > 0"
:title="layerIdentifier"
:zIndex="1"
>
<ol-source-vector :zIndex="0" :url="areaUrl" :format="shapeFormat">
</ol-source-vector>
<ol-style>
<ol-style-stroke :color="lineColor" width="2"></ol-style-stroke>
<ol-style-fill :color="fillColor"></ol-style-fill>
</ol-style>
</ol-vector-layer>
</template>

<script setup lang="ts">
import { GeoJSON } from 'ol/format'
import { Style, Fill, Stroke } from 'ol/style'
import { computed, inject, onMounted, nextTick } from 'vue'
interface Props {
results: any[]
lineColor?: string | Number[]
fillColor?: string | Number[]
areaDataKey?: string
}
const props = withDefaults(defineProps<Props>(), {
results: () => [],
lineColor: () => [102, 102, 102, 1],
fillColor: () => [26, 26, 26, 0.1],
areaDataKey: 'field_postcode'
})
const areas = computed(() => {
const matches = props.results.filter((itm) => {
return !itm.lat && itm[props.areaDataKey]
})
return matches
})
const mappedAreas = computed(() => {
return areas.value.map((area) => `'${area[props.areaDataKey]}'`)
})
const shapeFormat = new GeoJSON()
const areaUrl = computed(() => {
const baseArcGISURL =
'https://services6.arcgis.com/GB33F62SbDxJjwEL/ArcGIS/rest/services/Vicmap_Admin/FeatureServer/14/query'
const query = `postcode IN (${mappedAreas.value.join(',')})`
const inSR = '4326'
return `${baseArcGISURL}?where=${query}&geometryType=esriGeometryEnvelope&inSR=${inSR}&spatialRel=esriSpatialRelIntersects&units=esriSRUnit_Meter&returnGeodetic=false&outFields=postcode&returnGeometry=true&returnCentroid=false&f=pgeojson&token=`
})
const { rplMapRef, popup } = inject('rplMapInstance')
const defaultStyleFn = new Style({
fill: new Fill({
color: props.fillColor
}),
stroke: new Stroke({
color: props.lineColor,
width: 2
})
})
const mouseOverStyleFn = new Style({
fill: new Fill({
color: [26, 26, 26, 0.15]
}),
stroke: new Stroke({
color: props.lineColor,
width: 2
})
})
const layerIdentifier = 'shapeLayer'
const centerOnPopup = (map, popup, offset = { y: -100, x: 0 }) => {
const view = map.getView()
const resolution = view.getResolution()
const offsetCoord = [
popup.value.position[0] + offset.x * resolution,
popup.value.position[1] + offset.y * resolution
]
view.animate({
center: offsetCoord,
duration: 600
})
}
onMounted(async () => {
await nextTick()
if (rplMapRef.value) {
const map = rplMapRef.value
// Get reference to shapeLayer by title identifier
const allLayers = map.getLayers().getArray()
const shapeLayer = Array.from(allLayers).find(
(layer) => layer.get('title') === layerIdentifier
)
// shapeLayer.dispatchChangeEvent()
// define filter for getting only shapeLayer
const layerFilter = (feature, layer) => {
if (layer.get('title') === layerIdentifier) {
return feature
}
}
map.on('singleclick', function (evt) {
const clickedFeatures = []
// We need to keep track of features that are clicked outside of the shape layer, so that pins can take priority over the shape
const outOfLayerClickedFeatures = []
// Get the features at the click position
map.forEachFeatureAtPixel(
evt.pixel,
(f, layer) => {
if (layer.get('title') === layerIdentifier) {
clickedFeatures.push(f)
} else {
outOfLayerClickedFeatures.push(f)
}
},
{
hitTolerance: 5
}
)
if (outOfLayerClickedFeatures.length || !clickedFeatures.length) {
return
}
const feature = clickedFeatures[0]
const matchingResult = areas.value.filter((itm) => {
return itm.field_postcode[0] === feature?.get('postcode')
})
popup.value.isArea = true
popup.value.feature = Array.isArray(matchingResult)
? matchingResult
: [matchingResult]
popup.value.isOpen = true
popup.value.position = evt.coordinate
centerOnPopup(map, popup)
})
// Add a pointermove event listener to the map to detect shape hover
map.on('pointermove', function (evt) {
// Get the features at the mouse position
const feature = map.forEachFeatureAtPixel(evt.pixel, layerFilter, {
hitTolerance: 5
})
// reset all shapes not hovered
if (shapeLayer) {
const shapeSource = shapeLayer.getSource()
if (shapeSource) {
const shapeFeatures = shapeSource.getFeatures()
if (shapeFeatures) {
shapeFeatures.forEach(function (feature) {
feature.setStyle(defaultStyleFn)
})
}
}
}
// Change the style for the hovered shape on mouseover
if (feature) {
document.querySelector('canvas').style.cursor = 'pointer'
feature.setStyle(mouseOverStyleFn)
}
})
}
})
</script>
52 changes: 52 additions & 0 deletions examples/nuxt-app/components/global/VsbaMapPopupContent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<template>
<div class="vsba-map-popup-content">
<h4 class="rpl-type-p-small">What's happening?</h4>

<p
v-if="feature.field_project_title?.length === 1"
class="rpl-type-p-small"
>
{{ feature.title[0] }}
</p>
<RplContent v-else class="vsba-map-popup-list">
<ul>
<li v-for="project in feature.field_project_title" :key="project">
{{ project }}
</li>
</ul>
</RplContent>
<p class="rpl-type-p-small rpl-u-margin-t-3">
<RplTextLink :url="formatUrl(feature.url[0])">
View {{ feature.title[0] }}
</RplTextLink>
</p>
</div>
</template>
<script setup lang="ts">
interface Props {
feature: any
}
const props = withDefaults(defineProps<Props>(), {})
const formatUrl = (str) => str.replace(/\/site-(\d+)/, '')
</script>
<style>
.vsba-map-popup-content {
display: flex;
flex-direction: column;
}
.vsba-map-popup-list ul {
margin: 0;
font-size: var(--rpl-type-size-1);
line-height: var(--rpl-type-lh-3);
letter-spacing: var(--rpl-type-ls-1);
}
.vsba-map-popup-list ul li:before {
top: 0.6rem;
}
</style>
2 changes: 1 addition & 1 deletion examples/nuxt-app/cypress.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export default defineConfig({
projectId: 'mie4kg',
env: {
searchIndex: process.env.NUXT_PUBLIC_TIDE_APP_SEARCH_ENGINE_NAME,
NUXT_PUBLIC_TIDE_SITE: process.env.NUXT_PUBLIC_TIDE_SITE,
NUXT_PUBLIC_TIDE_SITE: process.env.NUXT_PUBLIC_TIDE_SITE
},
e2e: {
baseUrl: 'http://localhost:3000',
Expand Down
6 changes: 4 additions & 2 deletions examples/nuxt-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
"dev": "nuxt dev",
"dev:mock": "NUXT_PUBLIC_API_URL=http://localhost:3001 API_PORT=3001 concurrently 'pnpm mockserver' 'pnpm dev'",
"build": "nuxi build",
"preview": "nuxi preview",
"compile": "tsc --build",
"start": "node .output/server/index.mjs",
"start:mock": "NUXT_PUBLIC_API_URL=http://localhost:3001 API_PORT=3001 concurrently 'pnpm mockserver' 'pnpm start'",
"mockserver": "nuxt-ripple mock ./test/fixtures -S ./test/fixtures/site/reference.json -R mock-routes.json",
"cy:open": "cypress open --e2e --browser electron",
"cy:run": "cypress run --record",
"cy:run": "cypress run",
"test:ci": "NUXT_PUBLIC_API_URL=http://localhost:3001 API_PORT=3001 start-test start tcp:3000 'cy:run'",
"test:integration": "NUXT_PUBLIC_TIDE_SITE=TEST_SITE NUXT_PUBLIC_TIDE_BASE_URL=https://test.base.url/ start-test dev:mock tcp:3000 'cy:open'"
},
Expand All @@ -31,7 +32,8 @@
"@dpc-sdp/ripple-tide-media": "workspace:*",
"@dpc-sdp/ripple-tide-news": "workspace:*",
"@dpc-sdp/ripple-tide-publication": "workspace:*",
"@dpc-sdp/ripple-tide-search": "workspace:*"
"@dpc-sdp/ripple-tide-search": "workspace:*",
"@dpc-sdp/ripple-ui-maps": "workspace:*"
},
"devDependencies": {
"@dpc-sdp/ripple-test-utils": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Feature: Custom Collection
Given the "/api/tide/elasticsearch/sdp_data_pipelines_scl/_search" network request is stubbed with fixture "/landingpage/custom-collection/response-no-items" and status 200 as alias "cslReq"
Given I visit the page "/custom-collection"
Then the landing page component "TideCustomCollection" should exist
And the custom collection component should display the error "Sorry! We couldn't find any matches for ''."
And the custom collection component should display the error "Sorry, no results match your search. Try again with different search options or check back later."



21 changes: 21 additions & 0 deletions examples/nuxt-app/test/features/data-table/table-filters.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Feature: Custom Collection

As an editor I want to be able to add a view of results in a search index to a landing page with filters

Background:
Given the page endpoint for path "/" returns fixture "/map-table/ise/page" with status 200
Given the site endpoint returns fixture "/site/reference" with status 200
And the search autocomplete request is stubbed with "/search-listing/suggestions/none" fixture
Given I am using a "macbook-16" device

@mockserver
Scenario: On load
Given the "/api/tide/elasticsearch/sdp_data_pipelines_ise/_search" network request is stubbed with fixture "/map-table/ise/response" and status 200 as alias "cslReq"
Given the "/api/tide/elasticsearch/sdp_data_pipelines_ise/_search" aggregation request is stubbed with fixture "/map-table/ise/aggregations" and status 200 as alias "aggReq"
Given I visit the page "/"
Then the landing page component "TideCustomCollection" should exist
And the custom collection component should have a search input bar
And the custom collection component results count should read "Displaying 1-10 of 8269 results"
And the "cslReq" network request should be made to the elasticsearch endpoint
And the "aggReq" network request should be made to the elasticsearch endpoint
And the search listing layout should be "table"
1 change: 1 addition & 0 deletions examples/nuxt-app/test/features/landingpage/forms.feature
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ Feature: Forms
Then a "number" input with the label "Quantity" should exist
Then a "url" input with the label "Website" should exist
Then a "tel" input with the label "Mobile phone" should exist
Then a "date" input with the label "Date of birth" should exist
Then a select field with the label "Favourite colour" should exist
| required |
| true |
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 7b3699a

Please sign in to comment.