Benjamin Harris 2 달 전
부모
커밋
f999e2d2f4
4개의 변경된 파일160개의 추가작업 그리고 1개의 파일을 삭제
  1. 118 0
      config/councils.json
  2. 1 0
      docker-compose.yml
  3. 22 1
      web/councils.php
  4. 19 0
      web/index.php

+ 118 - 0
config/councils.json

@@ -0,0 +1,118 @@
+{
+  "da_break_oday": {
+    "name": "Break O'Day Council",
+    "source_url": "https://www.bodc.tas.gov.au/council/advertised-development-applications/"
+  },
+  "da_brighton": {
+    "name": "Brighton Council",
+    "source_url": "https://www.brighton.tas.gov.au/planning/advertised-development-applications/"
+  },
+  "da_burnie": {
+    "name": "Burnie City Council",
+    "source_url": "https://www.burnie.tas.gov.au/Development/Planning/Permit-applications-on-exhibition"
+  },
+  "da_centralcoast": {
+    "name": "Central Coast Council",
+    "source_url": "https://www.centralcoast.tas.gov.au/current-planning-applications/"
+  },
+  "da_centralhighlands": {
+    "name": "Central Highlands Council",
+    "source_url": "https://centralhighlands.tas.gov.au/development-applications/"
+  },
+  "da_circularhead": {
+    "name": "Circular Head Council",
+    "source_url": "https://www.circularhead.tas.gov.au/council-services/development/planning"
+  },
+  "da_clarence": {
+    "name": "Clarence City Council",
+    "source_url": "https://www.ccc.tas.gov.au/development/advertised-plans/"
+  },
+  "da_derwentvalley": {
+    "name": "Derwent Valley Council",
+    "source_url": "https://www.derwentvalley.tas.gov.au/home/latest-news?f.News+category%7CnewsCategory=Public+Notice"
+  },
+  "da_devonportcity": {
+    "name": "Devonport City Council",
+    "source_url": "https://www.devonport.tas.gov.au/building-development/planning/advertised-planning-permit-applications/"
+  },
+  "da_dorset": {
+    "name": "Dorset Council",
+    "source_url": "https://www.dorset.tas.gov.au/online-development-application-enquiry"
+  },
+  "da_flinders_council": {
+    "name": "Flinders Council",
+    "source_url": "https://www.flinders.tas.gov.au/current-advertising"
+  },
+  "da_georgetown": {
+    "name": "George Town Council",
+    "source_url": "https://georgetown.tas.gov.au/development-applications/"
+  },
+  "da_glamorgan": {
+    "name": "Glamorgan Spring Bay Council",
+    "source_url": "https://gsbc.tas.gov.au/services-facilities/public-notices/"
+  },
+  "da_glenorchy": {
+    "name": "Glenorchy City Council",
+    "source_url": "https://www.gcc.tas.gov.au/services/planning-and-building/planning-and-development/planning-applications/"
+  },
+  "da_hobartcity": {
+    "name": "Hobart City Council",
+    "source_url": "https://portal.planbuild.tas.gov.au/external/advertisement/search"
+  },
+  "da_huonvalley": {
+    "name": "Huon Valley Council",
+    "source_url": "https://www.huonvalley.tas.gov.au/development/planning/advertised-applications/"
+  },
+  "da_kentish": {
+    "name": "Kentish Council",
+    "source_url": "https://www.kentish.tas.gov.au/services/building-and-planning-services/planningapp"
+  },
+  "da_kingborough": {
+    "name": "Kingborough Council",
+    "source_url": "https://www.kingborough.tas.gov.au/development/planning-notices/"
+  },
+  "da_kingisland": {
+    "name": "King Island Council",
+    "source_url": "https://kingisland.tas.gov.au/develop/planning/"
+  },
+  "da_latrobe": {
+    "name": "Latrobe Council",
+    "source_url": "https://www.latrobe.tas.gov.au/services/building-and-planning-services/planningapp"
+  },
+  "da_launcestoncity": {
+    "name": "Launceston City Council",
+    "source_url": "https://onlineservice.launceston.tas.gov.au/eProperty/P1/PublicNotices/AllPublicNotices.aspx?r=P1.LCC.WEBGUEST&f=%24P1.ESB.PUBNOTAL.ENQ"
+  },
+  "da_meandervalley": {
+    "name": "Meander Valley Council",
+    "source_url": "https://www.meander.tas.gov.au/advertised-approved-planning-applications"
+  },
+  "da_northernmidlands": {
+    "name": "Northern Midlands Council",
+    "source_url": "https://northernmidlands.tas.gov.au/planning/development-in-the-northern-midlands/development-applications-2"
+  },
+  "da_sorell": {
+    "name": "Sorell Council",
+    "source_url": "https://portal.planbuild.tas.gov.au/external/advertisement/search"
+  },
+  "da_southernmidlands": {
+    "name": "Southern Midlands Council",
+    "source_url": "https://www.southernmidlands.tas.gov.au/advertised-development-applications/"
+  },
+  "da_tasman": {
+    "name": "Tasman Council",
+    "source_url": "https://tasman.tas.gov.au/advertised-applications/"
+  },
+  "da_waratah_wynyard": {
+    "name": "Waratah-Wynyard Council",
+    "source_url": "https://www.warwyn.tas.gov.au/planning-and-development/advertised-permits/"
+  },
+  "da_westcoast": {
+    "name": "West Coast Council",
+    "source_url": "https://www.westcoast.tas.gov.au/planning-and-development/planning/advertised-development-applications/"
+  },
+  "da_westtamar": {
+    "name": "West Tamar Council",
+    "source_url": "https://www.wtc.tas.gov.au/advertised-planning-applications/"
+  }
+}

+ 1 - 0
docker-compose.yml

@@ -67,6 +67,7 @@ services:
     image: councils-web:latest
     volumes:
       - ./web:/var/www/html:ro
+      - ./config:/var/www/html/config:ro
       - ./downloads:/srv/files:ro
       - ./web/000-files.conf:/etc/apache2/conf-enabled/000-files.conf:ro
     ports:

+ 22 - 1
web/councils.php

@@ -18,7 +18,17 @@ $pdo = new PDO($dsn, $DB_USER, $DB_PASS, [
 
 function h($s): string { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
 
+// ---- Council config (name + source URL) ----
+$councilConfig = [];
+$cfgFile = __DIR__ . '/config/councils.json';
+if (is_readable($cfgFile)) {
+    $decoded = json_decode(file_get_contents($cfgFile), true);
+    if (is_array($decoded)) $councilConfig = $decoded;
+}
+
 function council_name_from_key(string $k): string {
+    global $councilConfig;
+    if (!empty($councilConfig[$k]['name'])) return $councilConfig[$k]['name'];
     $base = preg_replace('/^da_/', '', $k);
     $base = str_replace('_', ' ', $base);
     $map = [
@@ -28,6 +38,10 @@ function council_name_from_key(string $k): string {
     if (isset($map[$base])) return $map[$base];
     return ucwords($base);
 }
+function council_source_url(string $k): string {
+    global $councilConfig;
+    return $councilConfig[$k]['source_url'] ?? '';
+}
 
 function tableExists(PDO $pdo, string $table): bool {
     $st = $pdo->prepare("SHOW TABLES LIKE ?");
@@ -310,7 +324,14 @@ usort($summary, $cmp);
         <tbody>
         <?php foreach ($summary as $r): ?>
           <tr>
-            <td><?= h($r['council']) ?></td>
+            <td>
+              <?php $srcUrl = council_source_url($r['council_key']); ?>
+              <?php if ($srcUrl !== ''): ?>
+                <a href="<?= h($srcUrl) ?>" target="_blank" rel="noopener" class="text-decoration-none"><?= h($r['council']) ?> <span class="muted">↗</span></a>
+              <?php else: ?>
+                <?= h($r['council']) ?>
+              <?php endif; ?>
+            </td>
             <td class="nowrap"><code><?= h($r['council_key']) ?></code></td>
             <td class="text-end"><?= number_format((int)$r['total']) ?></td>
             <td class="text-end"><?= is_null($r['open']) ? '<span class="muted">n/a</span>' : number_format((int)$r['open']) ?></td>

+ 19 - 0
web/index.php

@@ -16,6 +16,14 @@ $pdo = new PDO($dsn, $DB_USER, $DB_PASS, [
     PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
 ]);
 
+// ---- Council config (name + source URL) ----
+$councilConfig = [];
+$cfgFile = __DIR__ . '/config/councils.json';
+if (is_readable($cfgFile)) {
+    $decoded = json_decode(file_get_contents($cfgFile), true);
+    if (is_array($decoded)) $councilConfig = $decoded;
+}
+
 // ---- Inputs ----
 $q             = trim((string)($_GET['q'] ?? ''));
 $councilKeySel = trim((string)($_GET['council_key'] ?? '')); // table name like da_meandervalley
@@ -70,6 +78,8 @@ function validate_table_name(string $table): void {
 }
 function h($s) { return htmlspecialchars((string)$s, ENT_QUOTES, 'UTF-8'); }
 function council_name_from_key(string $k): string {
+    global $councilConfig;
+    if (!empty($councilConfig[$k]['name'])) return $councilConfig[$k]['name'];
     $base = preg_replace('/^da_/', '', $k);
     $base = str_replace('_', ' ', $base);
     $map = [
@@ -79,6 +89,10 @@ function council_name_from_key(string $k): string {
     if (isset($map[$base])) return $map[$base];
     return ucwords($base);
 }
+function council_source_url(string $k): string {
+    global $councilConfig;
+    return $councilConfig[$k]['source_url'] ?? '';
+}
 function days_left(?string $ymd): ?int {
     if (!$ymd) return null;
     $d = DateTime::createFromFormat('Y-m-d', $ymd);
@@ -441,7 +455,12 @@ $classifiedCount = array_sum($typeCount);
                                 </div>
                                 <div class="col-md-3">
                                     <label class="form-label">Council</label>
+                                    <?php $srcUrl = council_source_url($r['council_key']); ?>
+                                    <?php if ($srcUrl !== ''): ?>
+                                    <a class="form-control form-control-sm text-decoration-none" href="<?= h($srcUrl) ?>" target="_blank" rel="noopener"><?= h($cname) ?> ↗</a>
+                                    <?php else: ?>
                                     <input type="text" class="form-control form-control-sm" value="<?= h($cname) ?>" disabled readonly>
+                                    <?php endif; ?>
                                 </div>
                                 <div class="col-6">
                                     <label class="form-label">Owner</label>