A Flask-based web application for viewing, searching, and managing customer service line information with interactive maps and detailed asset data.
- Data Table with Search: Browse customer accounts with real-time search by Account Number or Service Address
- Detailed Asset View: Double-click any row to see comprehensive asset information and service line material
- Interactive Map: View asset locations on an interactive Leaflet map with color-coded markers
- Service Line Status Indicators:
- 🟢 Green - Safe materials (Copper, Plastic, Non-Lead)
- 🟡 Yellow - Materials requiring replacement (Lead, Galvanized)
- ⚪ Gray - Unknown or unverified materials
- Update Service Line Data: Submit corrections for unknown or unsafe service line materials
- Profanity Filtering: Comprehensive content validation on Location Description submissions
- User-Friendly UI: Responsive design with pagination, real-time validation, and loading states
- Backend: Python 3.x with Flask
- Frontend: HTML5, CSS3, JavaScript (ES6+)
- Mapping: Leaflet.js with OpenStreetMap tiles
- API Integration: ArcGIS REST API for feature services
- Styling: Custom CSS with responsive design
example_table_application/
├── app.py # Main Flask application
├── api_handlers.py # Request handlers and utilities
├── profanity_filter.py # Content validation and filtering
├── requirements.txt # Python dependencies
├── .env.example # Environment variables template
├── templates/
│ └── index.html # Main HTML template
├── static/
│ ├── css/
│ │ └── styles.css # Application styling
│ └── js/
│ └── main.js # Client-side interactivity
└── README.md # This file
- Python 3.8+
- pip (Python package manager)
- Modern web browser (Chrome, Firefox, Safari, Edge)
-
Clone or download the repository:
git clone <repository-url> cd example_table_application
-
Create a virtual environment (recommended):
python -m venv venv
-
Activate the virtual environment:
- On Windows:
venv\Scripts\activate
- On macOS/Linux:
source venv/bin/activate
- On Windows:
-
Install dependencies:
pip install -r requirements.txt
-
Set up environment variables:
- Copy
.env.exampleto.env:cp .env.example .env
- Edit
.envwith your ArcGIS credentials:CLIENT_ID=your_arcgis_client_id CLIENT_SECRET=your_arcgis_client_secret DATA_QUERY_URL1=https://your-arcgis-service.com/0/query DATA_QUERY_URL2=https://your-arcgis-service.com/1/query DATA_ADD_URL1=https://your-arcgis-service.com/1/addFeatures FLASK_ENV=development
- Important: Never commit
.envto version control. It's already in.gitignore.
- Copy
-
Run the application:
python app.py
-
Open in browser:
- Navigate to
http://localhost:5000
- Navigate to
This section explains how to set up the ArcGIS Online (AGOL) Feature Services required by this application.
The application expects two Feature Services with the following schema:
Used to display the main data table with all customer service line records.
Required Fields:
| Field Name | Type | Description |
|---|---|---|
PTR |
String | Account/Service Number (displayed in table) |
ServiceAddress |
String | Customer service address (displayed in table) |
GlobalID |
String/GUID | Unique identifier for each record |
coory |
Double | Latitude coordinate for map display |
coorx |
Double | Longitude coordinate for map display |
Sample Query Response:
{
"features": [
{
"attributes": {
"PTR": "ACC123456",
"ServiceAddress": "123 Main Street, City, State 12345",
"GlobalID": "{12345678-1234-1234-1234-123456789012}",
"coory": 40.7128,
"coorx": -74.0060
}
}
]
}Used to fetch detailed asset information and submit updates.
Required Fields:
| Field Name | Type | Description |
|---|---|---|
meterGlobal |
String/GUID | Reference to PTR record GlobalID |
LOCDESC |
String | Location description (max 100 chars) |
AssetID |
Integer | Asset identifier number |
MXUNumber |
Integer | Antenna/MXU number |
customerSL |
String | Service line material (Plastic, Copper, Non-Lead, etc.) |
Sample Query Response:
{
"features": [
{
"attributes": {
"LOCDESC": "Under driveway on east side",
"AssetID": 1001,
"MXUNumber": 5,
"customerSL": "Plastic",
"meterGlobal": "{12345678-1234-1234-1234-123456789012}"
}
}
]
}-
Create Feature Services in AGOL:
- Log into your ArcGIS Online organization
- Create a new Feature Service with two layers (Service 0 and Service 1)
- Add the required fields above to each layer
-
Configure Permissions:
- Enable "Query" capability for reading data
- Enable "Create, Update, Delete" capabilities for Service 1 to allow submissions
- Set up appropriate sharing settings
-
Obtain Service URLs:
- For DATA_QUERY_URL1:
https://services{X}.arcgis.com/{organization_id}/arcgis/rest/services/{service_name}/FeatureServer/0/query - For DATA_QUERY_URL2:
https://services{X}.arcgis.com/{organization_id}/arcgis/rest/services/{service_name}/FeatureServer/1/query - For DATA_ADD_URL1:
https://services{X}.arcgis.com/{organization_id}/arcgis/rest/services/{service_name}/FeatureServer/1/addFeatures
- For DATA_QUERY_URL1:
-
Set up OAuth2 Authentication:
- Register a new application in your AGOL organization
- Create OAuth2 credentials (Client ID and Client Secret)
- Ensure the application has appropriate permissions to query and edit features
-
Add credentials to
.envfile:CLIENT_ID=your_oauth_client_id CLIENT_SECRET=your_oauth_client_secret DATA_QUERY_URL1=https://services7.arcgis.com/your_org_id/arcgis/rest/services/YourService/FeatureServer/0/query DATA_QUERY_URL2=https://services7.arcgis.com/your_org_id/arcgis/rest/services/YourService/FeatureServer/1/query DATA_ADD_URL1=https://services7.arcgis.com/your_org_id/arcgis/rest/services/YourService/FeatureServer/1/addFeatures
-
Use the dropdown to select your search field:
- Account Number: Search by customer account/PTR
- Service Address: Search by service location address
-
Type your search query in the search box
- Searches are case-insensitive
- Partial matches are supported (e.g., "123" finds "12345" and "91234")
- Results update automatically as you type
-
Browse paginated results (15 records per page)
-
Double-click any row in the table to open the detail modal
-
The modal displays:
- Customer Service Line Material (with color-coded indicator)
- Asset Number
- Antenna Number
- Location Description
- Interactive map showing the asset location
-
Legend (bottom-right of map):
- Shows what each marker color represents
- Displays loading and unknown states
If the service line material is Unknown or marked for Replacement:
-
Click the "Update Info" button (top-right of the detail modal)
-
A form will appear with fields for:
- Asset Number (read-only if existing)
- Antenna Number (read-only if existing)
- Service Line Material (dropdown: Plastic, Copper, Non-Lead)
- Location Description (max 100 characters)
-
Fill in the form:
- Select the correct service line material
- Add any relevant location notes
- Character counter shows usage (turns red near limit)
-
Submit:
- A loading spinner appears during submission
- On success, a confirmation message displays with a checkmark
- Click "Done" to close the form
- The modal updates with the new information
- The map marker color updates to reflect the new material
- Character limit exceeded: Location Description is limited to 100 characters
- Inappropriate language detected: Submission rejected if profanity is detected
- Invalid character patterns: Rejects suspicious patterns (e.g., excessive repetition)
- Missing required fields: Asset Number and Service Line Material are required
- Invalid number format: Asset Number and Antenna Number must be valid integers
Fetches all customer records for the data table.
Response:
[
{
"id": "PTR_123",
"address": "123 Main St",
"globalid": "{12345-67890}",
"latitude": 40.7128,
"longitude": -74.0060
}
]Fetches detailed asset information for a specific record.
Response:
{
"attributes": {
"customerSL": "Copper",
"AssetID": 1001,
"MXUNumber": 5,
"LOCDESC": "Under sidewalk, north side"
}
}Submits updated service line information.
Request Body:
{
"AssetID": 1001,
"MXUNumber": 5,
"customerSL": "Plastic",
"LOCDESC": "Updated location info",
"meterGlobal": "{12345-67890}"
}Response (Success):
{
"success": true,
"attributes": {
"customerSL": "Plastic",
"AssetID": 1001,
"MXUNumber": 5,
"LOCDESC": "Updated location info",
"meterGlobal": "{12345-67890}"
},
"objectId": 12345,
"globalId": "{12345-67890}"
}Configuration is managed through environment variables. Create a .env file in the project root (copy from .env.example):
# ArcGIS OAuth2 Credentials
CLIENT_ID=your_client_id_here
CLIENT_SECRET=your_client_secret_here
# ArcGIS Feature Service URLs
DATA_QUERY_URL1=https://services7.arcgis.com/your_service_id/...
DATA_QUERY_URL2=https://services7.arcgis.com/your_service_id/...
DATA_ADD_URL1=https://services7.arcgis.com/your_service_id/...
# Flask Environment
FLASK_ENV=developmentRequired Variables:
CLIENT_ID: ArcGIS OAuth2 Client IDCLIENT_SECRET: ArcGIS OAuth2 Client SecretDATA_QUERY_URL1: Feature service URL for initial data queryDATA_QUERY_URL2: Feature service URL for single record queriesDATA_ADD_URL1: Feature service URL for adding/updating featuresFLASK_ENV: Set todevelopmentfor debug mode orproductionfor production
Security Note: The .env file is excluded from version control via .gitignore. Never commit credentials.
Defines profanity patterns and filtering logic. To add more filtered terms:
- Add regex patterns to
PROFANITY_PATTERNS - Update character substitutions in
CHAR_SUBSTITUTIONSif needed
Contains all business logic:
- Token generation using OAuth2
- Data fetching and transformation
- Input validation
- Feature submission
- Chrome 90+
- Firefox 88+
- Safari 14+
- Edge 90+
- Searches are performed client-side for instant results
- Pagination limits data table to 15 records per page
- API calls are optimized with specific field queries
- Map tiles are cached by browser
- Verify Python 3.8+ is installed:
python --version - Check all dependencies are installed:
pip install -r requirements.txt - Ensure no other application is using port 5000
- Verify all required environment variables are set in
.envfile
- Verify environment variables in
.envare correct - Check internet connection
- Ensure feature service URLs are valid and accessible
- Verify
CLIENT_IDandCLIENT_SECRETare valid ArcGIS OAuth2 credentials - Verify ArcGIS account has proper permissions
- Clear browser cache and reload
- Check browser console for errors (F12)
- Verify data was loaded successfully
- Check browser console for errors
- Verify latitude/longitude values are valid
- Ensure Leaflet.js CDN is accessible
- Check Location Description doesn't contain profanity
- Verify Asset Number and Antenna Number are valid integers
- Ensure GlobalID is properly set (check browser console)
- Verify ArcGIS service has add permissions
- Credentials Management: All sensitive credentials are stored in
.envfile, which is excluded from version control - Never commit
.env: The file is listed in.gitignoreto prevent accidental credential exposure - Environment Variables: Use environment variable configuration for both development and production
- Input Validation: All user input is validated and sanitized on the server
- Profanity Filter: Comprehensive filtering prevents inappropriate content submission
- HTTPS in Production: Always use HTTPS when deploying to production
The application runs in debug mode by default. For production:
- Use a production WSGI server (Gunicorn, uWSGI)
- Set environment variables for configuration
- Set
FLASK_ENV=production
To add new fields to submissions:
- Update the form in
templates/index.html - Add validation logic to
api_handlers.py - Update the submission dictionary structure
To search additional fields:
- Add field to dropdown in
templates/index.html - Update switch case in
main.jsfilterData function - Update API query fields in
api_handlers.py
This project is licensed under the MIT License - see the LICENSE file for details.
MIT License grants permission to use, modify, and distribute this software freely, provided the license and copyright notice are included.
For issues, questions, or suggestions, please contact:
- Project Owner: AustinA-py
- Repository: example_table_application
- Initial release
- Core features: search, view details, update service line information
- Interactive map with status indicators
- Comprehensive input validation and profanity filtering
- Responsive design for desktop and tablet