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
2 changes: 1 addition & 1 deletion Middleware/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ Include your username and password in the request body as JSON, for example:

## Available Data Sources

- [Dataset Catalog](DATA_SOURCES.md) - Complete list of all available datasets
- [Dataset Catalog](src/main/resources/DATA_SOURCES.md) - Complete list of all available datasets

## Demo & Presentations

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;

import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
Expand Down Expand Up @@ -40,20 +38,12 @@ public DatasetController(DatasetAccessService datasetAccessService) {
@GetMapping("/list")
public ResponseEntity<String> listDatasets() {
try {
Path filePath = Paths.get("DATA_SOURCES.md");
String content = Files.readString(filePath, StandardCharsets.UTF_8);
var resource = new ClassPathResource("DATA_SOURCES.md");
String content = new String(resource.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(content);
} catch (IOException e) {
// Fallback: try relative to project root
try {
Path filePath = Paths.get("Middleware/DATA_SOURCES.md");
String content = Files.readString(filePath, StandardCharsets.UTF_8);
return ResponseEntity.ok().contentType(MediaType.TEXT_PLAIN).body(content);
} catch (IOException e2) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Could not load dataset list. Tried ./DATA_SOURCES.md and Middleware/DATA_SOURCES.md. "
+ "Working directory: " + Paths.get("").toAbsolutePath());
}
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body("Could not load DATA_SOURCES.md from classpath.");
}
}

Expand Down
84 changes: 43 additions & 41 deletions Middleware/src/main/resources/static/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@
<section class="hero">

<div class="logo-wrap">
<img src="/assets/logo.png" alt="CITYdata" style="width:300px;height:56px;object-fit:contain;">
<img id="logo-img" src="" style="width:300px;height:56px;object-fit:contain;">
</div>

<p>
Expand Down Expand Up @@ -411,46 +411,48 @@ <h3 id="modalTitle">API Response</h3>
<script>

// ── API call ──────────────────────────────────────────
async function callApi(route) {
const modal = document.getElementById('apiModal');
const box = document.getElementById('responseBox');
const badge = document.getElementById('statusBadge');
const title = document.getElementById('modalTitle');

title.textContent = route;
box.innerHTML = '<pre>Fetching…</pre>';
badge.textContent = '…';
badge.className = '';
modal.classList.add('open');

try {
const res = await fetch(route);
const text = await res.text();
badge.textContent = res.status + ' ' + res.statusText;
badge.className = res.ok ? 'ok' : 'err';

try {
const json = JSON.parse(text);
if ((route === '/operations/list' || route === '/producers/list') && Array.isArray(json)) {
box.innerHTML = renderNameParamsTable(json);
} else {
box.innerHTML = '<pre>' + JSON.stringify(json, null, 2) + '</pre>';
}
} catch {
if (route === '/api/datasets/list') {
box.innerHTML = renderMarkdownTable(text);
} else {
box.innerHTML = '<pre>' + text + '</pre>';
}
}

} catch (e) {
badge.textContent = 'ERROR';
badge.className = 'err';
box.innerHTML = '<pre>Request failed.\n\n' + e.message + '</pre>';
}
}

const BASE = window.location.pathname.split('/').slice(0, -1).join('/');
document.getElementById('logo-img').src = BASE + '/assets/logo.png';

async function callApi(route) {
const modal = document.getElementById('apiModal');
const box = document.getElementById('responseBox');
const badge = document.getElementById('statusBadge');
const title = document.getElementById('modalTitle');

title.textContent = route;
box.innerHTML = '<pre>Fetching…</pre>';
badge.textContent = '…';
badge.className = '';
modal.classList.add('open');

try {
const res = await fetch(BASE + route);
const text = await res.text();
badge.textContent = res.status + ' ' + res.statusText;
badge.className = res.ok ? 'ok' : 'err';

try {
const json = JSON.parse(text);
if ((route === '/operations/list' || route === '/producers/list') && Array.isArray(json)) {
box.innerHTML = renderNameParamsTable(json);
} else {
box.innerHTML = '<pre>' + JSON.stringify(json, null, 2) + '</pre>';
}
} catch {
if (route === '/api/datasets/list') {
box.innerHTML = renderMarkdownTable(text);
} else {
box.innerHTML = '<pre>' + text + '</pre>';
}
}

} catch (e) {
badge.textContent = 'ERROR';
badge.className = 'err';
box.innerHTML = '<pre>Request failed.\n\n' + e.message + '</pre>';
}
}
function renderNameParamsTable(data) {
const rows = data.map(d => {
const shortName = d.name.split('.').pop();
Expand Down
Loading