-
-
Notifications
You must be signed in to change notification settings - Fork 215
feat: Link to project using name and version #1425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -213,6 +213,42 @@ function configRoutes() { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| permission: 'VIEW_PORTFOLIO', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path: 'projects/:name/:version/*', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: 'Project By Name and Version', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| beforeEnter: (to, from, next) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const searchParams = new URLSearchParams({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: to.params.name, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| version: to.params.version, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| router.app.axios | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .get( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| `${router.app.$api.BASE_URL}/${router.app.$api.URL_PROJECT_LOOKUP}?${searchParams}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .then((result) => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const trailingPathSegments = to.params.pathMatch | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ? `/${to.params.pathMatch}` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| : ''; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| next({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path: `projects/${result.data.uuid}${trailingPathSegments}`, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
WIStudent marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| replace: true, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| .catch(() => { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| next({ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| name: '404', | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| path: `projects/${result.data.uuid}${trailingPathSegments}`, | |
| replace: true, | |
| }); | |
| }) | |
| .catch(() => { | |
| next({ | |
| name: '404', | |
| path: `projects/${result.data.uuid}${trailingPathSegments}`, | |
| query: to.query, | |
| replace: true, | |
| }); | |
| }) | |
| .catch(() => { | |
| next({ | |
| name: '404', | |
| query: to.query, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary, neither the 404 page nor the project page seem to use query parameters.
Outdated
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
URL hash fragments are not preserved during the redirect. If the original URL contains a hash (e.g., for in-page navigation or state), it will be lost. Consider preserving the hash by including hash: to.hash in the next() object alongside the path.
| path: `projects/${result.data.uuid}${trailingPathSegments}`, | |
| replace: true, | |
| }); | |
| }) | |
| .catch(() => { | |
| next({ | |
| name: '404', | |
| path: `projects/${result.data.uuid}${trailingPathSegments}`, | |
| hash: to.hash, | |
| replace: true, | |
| }); | |
| }) | |
| .catch(() => { | |
| next({ | |
| name: '404', | |
| hash: to.hash, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary, neither the 404 page nor the project page seem to use hash fragments.
Copilot
AI
Jan 19, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error handling catches all errors uniformly, but different error types should potentially be handled differently. For example, a 404 (not found) is different from a 401 (unauthorized) or 500 (server error). Consider checking the error response status to provide more appropriate error handling, especially for authorization errors which might need different treatment than simple "not found" scenarios.
| .catch(() => { | |
| next({ | |
| name: '404', | |
| replace: true, | |
| }); | |
| .catch((error) => { | |
| const status = error && error.response && error.response.status; | |
| if (status === 404) { | |
| next({ | |
| name: '404', | |
| replace: true, | |
| }); | |
| } else if (status === 401 || status === 403) { | |
| next({ | |
| name: 'Login', | |
| replace: true, | |
| }); | |
| } else { | |
| // Cancel navigation on unexpected errors to avoid misreporting them as "not found" | |
| next(false); | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is necessary, both the project page and the lookup require the VIEW_PORTFOLIO permission. If the user doesn't have it, the global forEach navigation guard will redirect to the login page and the beforeEnter navigation guard in the Project By Name and Version route will not be called.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Project names and versions may contain special characters that need URL encoding. The current implementation doesn't decode these parameters before sending them to the API. If a project name contains special characters (e.g., spaces, slashes), the URL parameters extracted from to.params will already be decoded by Vue Router, but this should be verified. Additionally, consider validating that the name and version parameters don't contain path separators or other invalid characters that could cause routing issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Spaces and slashes are not a problem if encoded properly, vue-router will decode this
/projects/Test%20%2FABC/0.0.1/to nameTest /ABCandURLSearchParamswill encode it correctly.