Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Code Block
    LAYER
        NAME "ward_lookup"
        STATUS OFF
        TYPE POLYGON
        DATA "Overlays/ward_lookup.shp"
        TOLERANCE 0
        METADATA
            qstring_validation_pattern "."
            qstr_validation_pattern "."
        END
        LABELITEM "name"
        CLASS
            NAME ""
            STYLE
                OUTLINECOLOR 81 167 174
                WIDTH 3
            END
            LABEL
                FONT "verdana"
                TYPE truetype
                SIZE 8
                COLOR 255 0 0
                OUTLINECOLOR 255 255 255
                OUTLINEWIDTH 3
            END
        END
    END

 


Of particular interest is:

...

Code Block
        LAYER
            NAME "ward_summary"
            STATUS OFF
            TYPE POINT
            INCLUDE "_datashare.map"
            DATA "wkb_geometry from (select ogc_fid, code, name, ST_PointOnSurface(wkb_geometry) as wkb_geometry from boundaryline.wards_surrey) as foo using unique ogc_fid using srid=27700"
            TOLERANCE 0
            METADATA
                qstring_validation_pattern "."
                qstr_validation_pattern "."
            END
            CLASS
                NAME ""
                STYLE
                    SYMBOL "circle"
                    COLOR 0 128 0
                    SIZE 8
                END
            END
        END

...


Of note is the SQL used in the DATA statement which creates a row per ward with a point within each ward polygon which will be used for the lookup. The PostGIS function ST_PointOnSurface returns a POINT guaranteed to lie on the surface of a polygon.

...

The My Ward page now simply displays the name of the ward that the current address falls within, not very excited but a start. 


Adding a list of planning applications

...

Studio - Workflow

  • Create a new Stored Procedure Task called Create ward_planning_summary, choose:
    • Database: DataShare
    • Function: at_sys_create_table from the Astun category (from v6.0.0 this is called wkf_create_table under the -Workflow- Function filter)
    • Set the tablename parameter to: ward_planning_summary and the selectstatement to:
Code Block
languagesql
        WITH counts AS (
            SELECT wards.code,
                count(*) AS count
            FROM planning.surrey_planning planning,
                boundaryline.wards_surrey wards
            WHERE st_intersects(wards.wkb_geometry, planning.wkb_geometry)
            GROUP BY wards.code
        )
        SELECT wards.ogc_fid,
            wards.code,
            st_pointonsurface(wards.wkb_geometry) AS wkb_geometry,
            'There ' ||
            CASE WHEN counts.count = 1 THEN 'is ' ELSE 'are ' END ||
            coalesce(counts.count::text, 'no') ||
            ' planning application' ||
            CASE WHEN counts.count = 1 THEN '' ELSE 's' END AS summary
        FROM boundaryline.wards_surrey wards
        LEFT JOIN counts ON (wards.code = counts.code)

...

  • Create a ward_planning_summary layer in overlays.map

...


Code Block
        LAYER
            NAME "ward_planning_summary"
            STATUS OFF
            TYPE POINT
            INCLUDE "_datashare.map"
            DATA "wkb_geometry from (select * from ward_planning_summary) as foo using unique ogc_fid using srid=27700"
            TOLERANCE 0
            METADATA
                qstring_validation_pattern "."
                qstr_validation_pattern "."
            END
            CLASS
                NAME ""
                STYLE
                    SYMBOL "circle"
                    COLOR 0 128 0
                    SIZE 8
                END
            END
        END

Studio - MapSource

  • Create a Planning summary layer below the Summary group
    • Select the ward_planning_summary Layer Name
    • Ensure the Show MySearch and Show My option is checked
    • Choose the summary field

Create a ward map

Currently all data is shown in My Nearest panels but lets add a map showing the current ward then update the page style via CSS to display the map and summary panels side by side at the top of the page followed by all other panels as My Nearest panels below.

Studio - Workflow

First we're going to create a table which has a row per ward with a POINT within the ward and a html field containing an img element with the appropriate src URL to generate a map zoomed to the extent of the ward.

  • Create a new Stored Procedure Task called Create ward_map, choose:
    • Database: DataShare
    • Function: at_sys_create_table from the Astun categorycategory (from v6.0.0 this is called wkf_create_table under the -Workflow- Function filter)
    • Set the tablename parameter to: ward_map and the selectstatement to:
Code Block
languagesql
    WITH envelope AS (
        SELECT
            ogc_fid,
            wkb_geometry,
            code,
            name,
            st_expand(st_envelope(wkb_geometry), 300) AS envelope
        FROM boundaryline.wards_surrey wards
    ),
    coords AS (
        SELECT *,
            st_x(st_centroid(envelope.envelope))::int AS x,
            st_y(st_centroid(envelope.envelope))::int AS y,
            greatest((st_xmax(envelope) - st_xmin(envelope)), (st_ymax(envelope) - st_ymin(envelope)))::int AS z
        FROM envelope
    )
    SELECT
        ogc_fid,
        code,
        name,
        st_pointonsurface(wkb_geometry) AS wkb_geometry,
        '<img class="map" src="MapGetImage.aspx?RequestType=Map&MapWidth=450&MapHeight=450&MapSource=Astun/Default&Easting=' || x || '&Northing=' || y || '&Zoom=' || z || '&mapid=-1&ServiceAction=ZoomToLocation&Layers=ward_lookup,ward_summary" alt="' || name || '" />' AS html
    FROM coords
 


The SQL first creates an envelope result set which includes a geometry for the bounds of each ward, the coords result set then extracts the centre (x/y) and width (z) and finally a result set uses these values to construct a POINT within the ward and a html field containing anan img element with the appropriate src URL to generate a map zoomed to the extent of the ward. The URL specifies that the ward_lookuplayer is displayed on the map so that the boundaries are visible together with labels.

Mapfile

Code Block
LAYER
    NAME "ward_map"
    STATUS OFF
    TYPE POINT
    INCLUDE "_datashare.map" 
    DATA "wkb_geometry from (select *, html as html_raw from ward_map) as foo using unique ogc_fid using srid=27700"
    TOLERANCE 0
    METADATA
        qstring_validation_pattern "."
        qstr_validation_pattern "."
    END
    CLASS
        NAME ""
        STYLE
            SYMBOL "circle"
            COLOR 0 128 0
            SIZE 8
        END  
    END
END
 


Of note is the SQL used in the DATA statement which creates html_raw column by aliasing the existing html column. This allows us to use the html_raw column for the MapSource layer causing the raw HTML text to be output which will cause the img to be displayed.

Studio - MapSource

  • Create a Ward map Layer Group
    • Ensure Visible on Startup is checked
    • Move it up so it's the first Layer Group with the Summary Layer Group second
  • Create a Ward map Layer
    • Select the ward_map Layer Name
    • Ensure the Show MySearch and Show My option is checked
    • Choose the html_raw field and ensure Display field name is unchecked

Styling

To display the map and summary panels side by side at the top of the page we need a little JavaScript and CSS.

JavaScript

In order to allow us identify the first and second panels on the My Ward page we will use a little JavaScript to:

  • Add a class to the page body element to allow us to identify which page is currently being displayed
  • Add a class to each panel with it's position in the page
  • Disable ability to collapse the first two panels

Code Block
languagejs
    window.astun.customJS = function() {

        // Determine which page we are on from the selected tab
        var pageName = jQuery('.atTabSelected').val().replace(/\s/, '_').toLowerCase();

        // Add a class to the body to allow us to create specific rules for individual pages
        jQuery('body').addClass(pageName);

        // Add a class to each panel with it's position in the page,
        // atPanel0, atPanel1 etc.
        jQuery('.atPanelContainer .atPanel').each(function(idx) {
            jQuery(this).addClass('atPanel' + idx);
        });

        if (pageName === 'my_ward') {
            // Make the first two panels on the My Ward page non-collapsable
            jQuery('.atPanel.atPanel0, .atPanel.atPanel1').find("*").unbind();
            // Remove the "Click to toggle" tooltip
            jQuery('.atPanel.atPanel0, .atPanel.atPanel1').find(".atPanelHeader").attr("title", "");
        }

    };

CSS

The following CSS when added to one of the site specific CSS files found under the Web\custom directory applies the following styles:

  • Display the first two panel side by side and always expanded
  • Hide the headings for the summary panel
  • Hide the "Details" and "Distance" table headings
  • Make the ward map responsive
 


Code Block
languagecss
    /* Position the first two My Ward panels */
    .my_ward .atPanel.atPanel0, .my_ward  .atPanel.atPanel1 {
        width: 48%;
        float:left;
        margin-left: 10px;
    }

    /* Always display the content of the first two panels */
    .my_ward .atPanel.atPanel0 .atPanelParentContent, .my_ward  .atPanel.atPanel1 .atPanelParentContent {
        display: block !important;
    }

    /* Ensure the third panel displays below the first two */
    .my_ward .atPanel.atPanel0, .my_ward  .atPanel.atPanel2 {
        clear: both;
    }

    /* Style headers for the first two panels */

    .my_ward .atPanel.atPanel0 .atPanelHeader, .my_ward .atPanel.atPanel1 .atPanelHeader {
        cursor: default !important;    
    }
    .my_ward .atPanel.atPanel0 .atPanelStatusSign, .my_ward  .atPanel.atPanel1 .atPanelStatusSign {
        visibility: hidden;
    }

    /* Style panel content */

    /* Hide layer titles for first two panels */
    .my_ward .atPanel.atPanel0 h4, .my_ward  .atPanel.atPanel1 h4 {
        display: none;
    }

    .my_ward table thead {
        display: none;
    }
    .my_ward table tr th:nth-child(1),
    .my_ward table tr td:nth-child(1) {
        width: 100%;
    }

    /* Make the ward map responsive */
    .my_ward  img.map {
        width: 100%;
    }

Responsive design

As a bonus lets make some small changes to make the My Ward responsive and display appropriately on a range of device sizes. In this case we can simply add a single media query to our CSS to apply a different style to the first two panels when the screen width is smaller than a given size.

Code Block
languagecss
@media (max-width: 640px) {
    
	.my_ward .atPanel.atPanel0, .my_ward  .atPanel.atPanel1 {
		width: 100%;
		margin-left: 0;
	}

}