Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
6 changes: 6 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,9 @@
NETLIFY_USE_YARN = "true"
NETLIFY_RESTORE_PYTHON = "false" # Prevent automatic Python setup
PIP_DISABLE_PIP_VERSION_CHECK = "1"

# TODO: Revert once the GitHub attestations API outage is resolved - this
# skips mise's supply-chain verification of the Python interpreter binary,
# which was failing builds with "No GitHub artifact attestations found"
# (GitHub's attestation endpoint was returning 503s)
MISE_PYTHON_GITHUB_ATTESTATIONS = "false"
24 changes: 24 additions & 0 deletions src/common-functions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,30 @@ export interface PropertyTypeStats {
gradeDistribution?: Record<string, number>;
}

/**
* Total emissions across every property type we have stats for, used as the
* denominator for a property type's share of citywide emissions. This covers
* a few types that don't have their own page, so shares across all types add
* up to slightly under 100%.
*/
export function getCitywideTotalEmissions(
statsByPropertyType: Record<string, PropertyTypeStats>,
): number {
return Object.values(statsByPropertyType).reduce(
(sum, stats) => sum + (stats.TotalGHGEmissions?.total ?? 0),
0,
);
}

/** Show a floor of "<0.1%" so tiny categories don't all read as 0% */
export function formatEmissionsPercent(percent: number): string {
if (percent > 0 && percent < 0.1) {
return '<0.1%';
}

return `${percent.toFixed(1)}%`;
}

export interface YearData {
GHGIntensity?: MetricStats;
TotalGHGEmissions?: MetricStats;
Expand Down
2 changes: 2 additions & 0 deletions src/components/layout/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ export default class AppHeader extends Vue {

<g-link class="nav-link" to="/large-owners"> Large Owners </g-link>

<g-link class="nav-link" to="/property-types"> Property Types </g-link>

<g-link class="nav-link" to="/cleanest-buildings">
Cleanest Buildings
</g-link>
Expand Down
70 changes: 70 additions & 0 deletions src/constants/property-type-helpers.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,74 @@ const helpers = require('./property-type-helpers.js') as {
slugifyPropertyType: (propertyType: string) => string;
};
export const slugifyPropertyType = helpers.slugifyPropertyType;

/**
* An emoji for each property type, used to make lists of property types easier
* to scan. Types not listed here fall back to PropertyTypeEmojiFallback.
*/
export const PropertyTypeEmoji: Record<string, string> = {
'Adult Education': '📚',
'Ambulatory Surgical Center': '🏥',
'Automobile Dealership': '🚗',
'Bank Branch': '🏦',
'College/University': '🎓',
'Convention Center': '🎪',
Courthouse: '⚖️',
'Data Center': '💾',
'Distribution Center': '📦',
'Enclosed Mall': '🛍️',
'Financial Office': '🏦',
'Fitness Center/Health Club/Gym': '🏋️',
'Hospital (General Medical & Surgical)': '🏥',
Hotel: '🏨',
'Ice/Curling Rink': '⛸️',
'Indoor Arena': '🏟️',
'K-12 School': '🏫',
Laboratory: '🔬',
Library: '📖',
'Medical Office': '🩺',
'Mixed Use Property': '🏙️',
'Movie Theater': '🎬',
'Multifamily Housing': '🏢',
Museum: '🏛️',
Office: '🏢',
Other: '🏗️',
'Other - Education': '📚',
'Other - Entertainment/Public Assembly': '🎭',
'Other - Lodging/Residential': '🏘️',
'Other - Mall': '🛍️',
'Other - Public Services': '🏛️',
'Other - Recreation': '🎡',
'Other - Services': '🔧',
'Other - Specialty Hospital': '🏥',
'Outpatient Rehabilitation/Physical Therapy': '🩼',
'Performing Arts': '🎭',
'Pre-school/Daycare': '🧸',
'Prison/Incarceration': '🔒',
'Repair Services (Vehicle, Shoe, Locksmith, etc.)': '🔧',
'Residence Hall/Dormitory': '🛏️',
'Residential Care Facility': '🧑‍⚕️',
'Retail Store': '🛒',
'Senior Care Community': '👵',
'Senior Living Community': '👵',
'Social/Meeting Hall': '🤝',
'Stadium (Open)': '🏟️',
'Strip Mall': '🏬',
'Supermarket/Grocery Store': '🥫',
'Urgent Care/Clinic/Other Outpatient': '🚑',
'Vehicle Dealership': '🚗',
'Wholesale Club/Supercenter': '🏬',
'Worship Facility': '🛐',
};

/** Emoji shown for any property type missing from PropertyTypeEmoji */
export const PropertyTypeEmojiFallback = '🏢';

/**
* Get the emoji for a property type, falling back to a generic building emoji
* for any type we haven't explicitly mapped
*/
export function getPropertyTypeEmoji(propertyType: string): string {
return PropertyTypeEmoji[propertyType] ?? PropertyTypeEmojiFallback;
}
</script>
Loading
Loading