Skip to content
Draft
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
4 changes: 4 additions & 0 deletions content/use/usegalaxy-org/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ platforms:
platform_url: "https://usegalaxy.org"
platform_text: "UseGalaxy.org Server (Main)"
platform_location: US
- platform_group: "academic-cloud"
platform_url: "https://test.galaxyproject.org"
platform_text: "UseGalaxy.org Test Server (Main)"
platform_location: US
summary: "The [Galaxy Project](/galaxy-project/) free public server; biomedical research "
comments:
- "Strong on genomics; good central repository for shared Galaxy objects. See [Main](/main/) for more."
Expand Down
50 changes: 50 additions & 0 deletions content/usegalaxy/apply/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
---
title: UseGalaxy Servers - Apply for UseGalaxy “dot-star” Membership
---

## Who this is for

Operators of public Galaxy instances who want to join the **usegalaxy.\*** federation (the “dot-star” network).

## How to apply

1. **Open a new issue** in `galaxyproject/galaxy-hub` using the template **“usegalaxy.* Dot-Star Application.”**
2. **Complete all required fields** and submit the issue for federation review.

## What you’ll provide (concise checklist)

- **Instance identity**
- Region/Country
- Public instance URL
- Link to your public org/repos (infra configs, playbooks, containers, Helm charts)
- **Infrastructure & reproducibility**
- Visibility of infra/playbooks: Public / Partially public / Private (with explanation)
- Notes on what’s public vs. private and any plans to open more
- **User access & policies**
- Access policy (registration open; anonymous jobs may be allowed but **not required**)
- Terms of Service / Usage Policy URL
- Data retention/deletion policy URL (incl. inactive accounts)
- **Storage & reference data**
- Default per-user storage quota (GB)
- Short-term/scratch storage availability
- CVMFS reference data availability/link
- **Operations & reliability**
- Approximate tool count
- Public uptime/status page URL
- Uptime over the last 90 days (%) + methodology/source
- Upgrade policy & cadence (commitment to timely upgrades)
- Cross-UseGalaxy testing participation (yes/planned/not yet)
- Optional: Link to metrics dashboards (e.g., KUI)
- **Community & stewardship**
- Confirm adherence to the Galaxy Code of Conduct
- Commit to participating in admin/community channels (SIGs, meetings, Matrix/mailing lists)
- Commit to contributing back issues/PRs/knowledge where feasible
- **People & proof**
- Operations team, on-call/incident process, and support channels
- Evidence & references (links to PRs, monitoring panels, docs, prior discussions)
- Any open questions for reviewers

## What happens next

- Federation maintainers review your application issue, may ask follow-ups, and confirm alignment with expectations (e.g., uptime, upgrade cadence, cross-testing).
- Upon acceptance, your site is listed with the UseGalaxy servers and aligned with federation practices (e.g., CVMFS reference data).
195 changes: 195 additions & 0 deletions content/usegalaxy/designations.csv

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions content/usegalaxy/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ We want to see servers meeting several loose requirements to be considered part
- *Functional*: The site provides >90% uptime as monitored by the [status page](https://status.galaxyproject.org/), and participates in automated cross-usegalaxy testing initiatives.
- *Conduct*: Adhere to the [Galaxy Project Code of Conduct](https://galaxyproject.org/community/coc/).

For more information, please read more about the [application process here](apply/).

We're excited to see new services join us!

## Incubating Members
Expand Down
116 changes: 114 additions & 2 deletions gridsome.server.js
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,27 @@ class nodeModifier {
}
return node;
},
Platform: function (node) {
// Process each platform URL to add designation data
if (node.platforms && Array.isArray(node.platforms)) {
for (const platform of node.platforms) {
platform.designation = null;

if (platform.platform_url) {
const url = normalizeUrl(platform.platform_url);
const designation = DESIGNATIONS_MAP.get(url);
if (designation) {
platform.designation = designation;
console.log(
`Found designation for ${platform.platform_url}: ${designation.designation} (Tier ${designation.tier})`,
);
}
}
}
}

return node;
},
};
}

Expand Down Expand Up @@ -383,6 +404,71 @@ function parseNavbarItem(rawItem, pathPrefix) {
return item;
}

// Helper function to normalize URLs for consistent matching
function normalizeUrl(url) {
if (!url) return null;
return url
.replace(/^https?:\/\//, "") // Remove protocol
.replace(/\/$/, "") // Remove trailing slash
.replace(/:\d+$/, "") // Remove port numbers
.toLowerCase(); // Normalize case
}

function loadDesignationsData() {
const designationsPath = path.join(__dirname, "content/usegalaxy/designations.csv");
if (!fs.existsSync(designationsPath)) {
console.warn("Designations CSV file not found:", designationsPath);
return new Map();
}

const csvContent = fs.readFileSync(designationsPath, "utf8");
const lines = csvContent.split("\n").filter((line) => line.trim());
const headers = lines[0].split(",").map((h) => h.trim());
const designationsMap = new Map();

for (let i = 1; i < lines.length; i++) {
const line = lines[i];
if (!line.trim()) continue;

// Parse CSV line, handling quoted values
const values = [];
let current = "";
let inQuotes = false;

for (let j = 0; j < line.length; j++) {
const char = line[j];
if (char === '"') {
inQuotes = !inQuotes;
} else if (char === "," && !inQuotes) {
values.push(current.trim());
current = "";
} else {
current += char;
}
}
values.push(current.trim());

if (values.length >= headers.length) {
const designation = {};
headers.forEach((header, index) => {
designation[header.toLowerCase()] = values[index] || "";
});

// Show all designations with URLs
if (designation.url) {
const normalizedUrl = normalizeUrl(designation.url);
if (normalizedUrl) {
designationsMap.set(normalizedUrl, designation);
}
}
}
}

return designationsMap;
}

const DESIGNATIONS_MAP = loadDesignationsData();

module.exports = function (api) {
api.loadSource((actions) => {
// Using the Data Store API: https://gridsome.org/docs/data-store-api/
Expand Down Expand Up @@ -426,7 +512,7 @@ module.exports = function (api) {
};
}
actions.addSchemaResolvers(schemas);
actions.addSchemaTypes(
actions.addSchemaTypes([
actions.schema.createObjectType({
name: "Dataset",
interfaces: ["Node"],
Expand All @@ -436,7 +522,30 @@ module.exports = function (api) {
main_subsite: "String",
},
}),
);
actions.schema.createObjectType({
name: "Platform",
interfaces: ["Node"],
extensions: { infer: true },
fields: {
designation: {
type: "PlatformDesignation",
resolve: (obj) => obj.designation,
},
},
}),
actions.schema.createObjectType({
name: "PlatformDesignation",
fields: {
operative: "String",
tier: "Int",
url: "String",
city: "String",
region: "String",
description: "String",
notes: "String",
},
}),
]);
});

// Populate the derived fields.
Expand Down Expand Up @@ -532,6 +641,9 @@ module.exports = function (api) {
platform_text
platform_location
platform_purview
designation {
tier
}
}
}
}
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
},
"dependencies": {
"@babel/core": "^7.16.5",
"@fortawesome/fontawesome-free": "^5.15.4",
"@fortawesome/fontawesome-free": "^6.7.2",
"@gridsome/plugin-sitemap": "^0.4.0",
"@gridsome/source-filesystem": "^0.6.2",
"@gridsome/transformer-remark": "^0.6.4",
Expand Down Expand Up @@ -74,6 +74,7 @@
"devDependencies": {
"@babel/preset-env": "^7.15.8",
"@testing-library/cypress": "^8.0.1",
"abort-controller": "^3.0.0",
"axe-core": "^4.3.3",
"cypress": "8.6.0",
"cypress-axe": "^0.13.0",
Expand All @@ -85,6 +86,7 @@
"http-server": "^13.0.2",
"jest": "^27.3.1",
"linkinator": "^6.1.2",
"node-fetch": "^3.3.2",
"sass-loader": "^10.1.1",
"start-server-and-test": "^1.14.0"
},
Expand Down
54 changes: 31 additions & 23 deletions src/composables/useTableSorting.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export function useTableSorting() {
platform: platformSortHandler,
title: titleSortHandler,
summary: textSortHandler,
// tier: tierSortHandler,
tier: tierSortHandler,
region: regionSortHandler,
};

Expand Down Expand Up @@ -81,17 +81,17 @@ export function useTableSorting() {
* @param {Object} bRow - Second row object
* @returns {number} - Sort result (-1, 0, 1)
*/
// const tierSortHandler = (aRow, bRow) => {
// // TODO refactor into another method
// const a = getTierValue(aRow);
// const b = getTierValue(bRow);
const tierSortHandler = (aRow, bRow) => {
// TODO refactor into another method
const a = getTierValue(aRow);
const b = getTierValue(bRow);

// if (a === null && b === null) return 0;
// if (a === null) return 1;
// if (b === null) return -1;
if (a === null && b === null) return 0;
if (a === null) return 1;
if (b === null) return -1;

// return a - b;
// };
return a - b;
};

/**
* Sort handler for region columns (handles string region values)
Expand Down Expand Up @@ -128,17 +128,25 @@ export function useTableSorting() {
* @param {Object} row - Row object
* @returns {number|null} - Tier value for sorting
*/
// const getTierValue = (row) => {
// if (row.designation && Array.isArray(row.designation) && row.designation.length > 0) {
// const tier = parseInt(row.designation[0].tier, 10);
// return isNaN(tier) ? null : tier;
// }
// if (row.designation && row.designation.tier) {
// const tier = parseInt(row.designation.tier, 10);
// return isNaN(tier) ? null : tier;
// }
// return null;
// };
const getTierValue = (row, platform_group = null) => {
if (!row.platforms || !Array.isArray(row.platforms)) {
return null;
}

// Find the platform with the matching group that has designation data
for (const platform of row.platforms) {
if (platform_group && platform.platform_group !== platform_group) {
continue;
}

if (platform.designation && platform.designation.tier) {
const tier = parseInt(platform.designation.tier, 10);
return isNaN(tier) ? null : tier;
}
}

return null;
};

/**
* Get the region value for sorting (returns string value or null)
Expand Down Expand Up @@ -253,14 +261,14 @@ export function useTableSorting() {
platformSortHandler,
titleSortHandler,
textSortHandler,
// tierSortHandler,
tierSortHandler,
regionSortHandler,

createSortableField,
createSortableFields,

getPlatformDisplayValue,
// getTierValue,
getTierValue,
getRegionValue,
compareStrings,
getSortState,
Expand Down
Loading
Loading