-
Notifications
You must be signed in to change notification settings - Fork 1
SS-1176 Users are able to set a custom default start URL for their apps #249
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
SS-1176 Users are able to set a custom default start URL for their apps #249
Conversation
… change to input form, and added validation for the url
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'm not sure, that this class belongs here, tbh
Like, it's a module for custom types, but this a validator, not a new type if it makes sence
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.
And you could use this docs to make it a part of initialization of a CharField on a apps/forms/custom.py:22
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 also agree that this is a validator rather than a new type and therefore does not belong in _types. Perhaps there was inspiration from the SubdomainCandidateName class but in that case it is logically a complete class with its own behavior and properties that we may continue to extend in the future.
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.
Rewrote it in the apps/forms/custom.py
| __name = None | ||
|
|
||
| def __init__(self, name: str): | ||
| self.__name = name |
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 see a reason to not do it like this:)
| __name = None | |
| def __init__(self, name: str): | |
| self.__name = name | |
| def __init__(self, name: str): | |
| self._name = name |
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.
Removed it.
| error_message = ( | ||
| "Your custom default URL is not valid, please correct it. " | ||
| "It must be 1-53 characters long." | ||
| " It can contain only Unicode letters, digits, hyphens" |
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.
So we are allowing unicode characters in the subpath?
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.
Yes. We had a discussion and agreed on keeping unicode characters.
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 have a few question about this file:
- Why didn't you include the
templates/apps/partials/srv_prepend_append_input_group.html? - I don't really like the
<script>to be placed here. On the other hand, it sort of logical for it to be here, considering all the design choices that we've made. I just don't like two things: that it potentially won't work if it'll be used anywhere else, other than an app with an input for subdomain and second thing is that scripts should be grouped together in the header and not scattered.
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 think because of the script I created a new file. I placed the script in the header section. Should I try to use the templates/apps/partials/srv_prepend_append_input_group.html for this?
| app_orms = (app_model for app_model in APP_REGISTRY.iter_orm_models() if issubclass(app_model, SocialMixin)) | ||
|
|
||
| for app_orm in app_orms: | ||
| logger.info("Processing: %s", app_orm) |
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.
Is there a reason to remove this?
apps/tests/test_forms.py
Outdated
| "port": 8000, | ||
| "image": "ghcr.io/scilifelabdatacentre/image:tag", | ||
| "tags": ["tag1", "tag2", "tag3"], | ||
| "custom_default_url": "valid-custom_default_url/", |
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'd call it a default_url_subpath, but I'm not insisting. Just that it's not a full URL, that's bothering me a little.
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.
Rename this field to default_url_subpath all together.
alfredeen
left a comment
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 do not see any unit tests of the URL sub path validation.
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.
Copilot reviewed 5 out of 8 changed files in this pull request and generated 1 suggestion.
Files not reviewed (3)
- templates/apps/partials/srv_prepend_input_group_custom_app.html: Language not supported
- portal/views.py: Evaluated as low risk
- apps/tests/test_forms.py: Evaluated as low risk
apps/helpers.py
Outdated
| URI = URI.strip("/") | ||
| if hasattr(instance, "custom_default_url") and instance.custom_default_url != "": | ||
| URI = URI + "/" + instance.custom_default_url | ||
| logger.info("Modified URI by adding custom default url for the custom app: " + URI) |
Copilot
AI
Nov 18, 2024
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.
String concatenation using the '+' operator is not recommended. Use formatted strings or the logger's formatting capabilities instead.
| logger.info("Modified URI by adding custom default url for the custom app: " + URI) | |
| logger.info("Modified URI by adding custom default url for the custom app: %s", URI) |
Wrote two (pass/fail) unit tests for this. |
churnikov
left a comment
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.
We are close:)
I think after this I'd approve
| import regex as re | ||
| from django.core.exceptions import ValidationError |
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.
| import regex as re | |
| from django.core.exceptions import ValidationError | |
| import regex as re | |
| from django.core.exceptions import ValidationError |
This should be caught by isort I think
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.
Thank you. Addressed it.
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.
Following this conversation https://github.com/ScilifelabDataCentre/serve/pull/249/files/3527fd079d58deac18bd5cd9461d242c37dbd8c7..83f995417664557d998e06b577565d4e008756c1#r1837858395
So I'd say, it would be best to also {%include %} the already existing markup for the prepend append group and not copy it.
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.
Thank you. Worked on it.
hamzaimran08
left a comment
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 would also suggest changing the file templates/apps/partials/srv_prepend_append_input_group.html with the following. The prepend text should be bold in my opinion
- <span class="input-group-text">{{ crispy_prepended_text }}</span>
+ <span class="input-group-text fw-bold">{{ crispy_prepended_text }}</span>| from django import forms | ||
| from django.core.exceptions import ValidationError | ||
| from django.utils.safestring import mark_safe | ||
|
|
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.
| from django.urls import reverse | |
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.
Thank you. Addressed it.
apps/forms/custom.py
Outdated
| image = forms.CharField(max_length=255, required=True) | ||
| path = forms.CharField(max_length=255, required=False) | ||
|
|
||
| default_url_subpath = forms.CharField(max_length=255, required=False, label="Custom default url subpath") |
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.
| default_url_subpath = forms.CharField(max_length=255, required=False, label="Custom default url subpath") | |
| default_url_subpath = forms.CharField(max_length=255, required=False, label="Custom URL subpath") |
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.
Thanks. Changed it.
| self.fields["volume"].initial = None | ||
|
|
||
| self.fields["default_url_subpath"].widget.attrs.update({"class": "textinput form-control"}) | ||
| self.fields["default_url_subpath"].help_text = "Specify a non-default start URL if your app requires that." |
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.
| self.fields["default_url_subpath"].help_text = "Specify a non-default start URL if your app requires that." | |
| self.fields["default_url_subpath"].help_text = "Specify a non-default start URL if your app requires that." | |
| apps_url = reverse('portal:apps') |
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.
Thanks. Modified it.
apps/forms/custom.py
Outdated
| "We will display this URL for your app in our app catalogue." | ||
| " Keep in mind that when your app does not have anything on the root URL" | ||
| " (<span id='id_custom_default_url_subpath_form_help_text'></span>), if a user manually" | ||
| " navigates to the root URL, they will see an empty page there." |
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.
| "We will display this URL for your app in our app catalogue." | |
| " Keep in mind that when your app does not have anything on the root URL" | |
| " (<span id='id_custom_default_url_subpath_form_help_text'></span>), if a user manually" | |
| " navigates to the root URL, they will see an empty page there." | |
| f"<span class='fw-bold'>Note:</span> This changes the URL connected to the Open button for an app" | |
| f" on the Serve <a href='{apps_url}'>Apps & Models</a> page." |
I think this text needs to be shorter. We can add a link to documentation and have longer text and examples of how to use this in a separate part of the docs in my opinion. This could be a separate task.
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.
Thanks. Edited it.
apps/forms/custom.py
Outdated
| "Subdomain/", | ||
| template="apps/partials/srv_prepend_input_group_custom_app.html", |
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.
| "Subdomain/", | |
| template="apps/partials/srv_prepend_input_group_custom_app.html", | |
| mark_safe("<span id='id_custom_default_url_prepend'>Subdomain/</span>"), | |
| template="apps/partials/srv_prepend_append_input_group.html", |
I think one way to this this is to not use a separate template but use apps/partials/srv_prepend_input_group_custom_app.html, add an id to the Prepend input group element using span so that it is accessible through the javascript id match that you use. I have also tried to shorten the id, you can ofcourse choose another name.
Then I suggest moving parts of your javascript to the templates/apps/create_base.html file. The changes can be the following:
Load get_setting
{% load get_setting %}In the script section make the following changes
+ const subdomainInput = document.getElementById("id_subdomain");
+ const customDefaultUrlFormModifiedUrlText = document.getElementById("id_custom_default_url_prepend");
+ function updateUrlWithSubdomain() {
+ const subdomainValue = subdomainInput.value.trim();
+ const displayValue = subdomainValue || "subdomain_name";
+ customDefaultUrlFormModifiedUrlText.innerHTML = `${displayValue}.{% get_setting 'DOMAIN' %}/</b>`;
+ }
// User is "finished typing," do something
function doneTyping () {
let subdomain_input = $("#id_subdomain").val();
if (subdomain_input.length == 0) {
//console.log("Empty subdomain input");
clearSubdomainValidation();
// Empty text field. Enable the submit button and clear any validation styles.
$("#submit-id-submit").prop('disabled', false);
}
else {
//console.log(`Checking subdomain validity for: ${subdomain_input}`);
// Run check if there is text in the input field
// Convert the input subdomain to lowercase for the validation.
// OK because the input form and the server does the same.
checkSubdomainValidity(subdomain_input.toLowerCase());
}
+ updateUrlWithSubdomain();
}
........
........
........
htmx.onLoad(function(content) {
runScript();
+ updateUrlWithSubdomain();
})We already have an eventlistener listening to keystrokes on the subdomain input box. So we can use that one to update the URL for your input prepend text.
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.
Thanks a lot for this suggestion. It helped me a lot to understand the existing scripts.
alfredeen
left a comment
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.
LGTM. Thanks for adding the unit tests. I will let others review the recent changes as well before approving.
Thank you so much. |
hamzaimran08
left a comment
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.
So, I think just this small change left. We need to catch the console error in case the element does not exist. Otherwise LGTM. Good work.
templates/apps/create_base.html
Outdated
| const subdomainValue = subdomainInput.value.trim(); | ||
| const displayValue = subdomainValue || "subdomain_name"; | ||
| customDefaultUrlFormModifiedUrlText.innerHTML = `${displayValue}.{% get_setting 'DOMAIN' %}/</b>`; |
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.
| const subdomainValue = subdomainInput.value.trim(); | |
| const displayValue = subdomainValue || "subdomain_name"; | |
| customDefaultUrlFormModifiedUrlText.innerHTML = `${displayValue}.{% get_setting 'DOMAIN' %}/</b>`; | |
| try { | |
| const subdomainValue = subdomainInput.value.trim(); | |
| const displayValue = subdomainValue || "subdomain_name"; | |
| customDefaultUrlFormModifiedUrlText.innerHTML = `${displayValue}.{% get_setting 'DOMAIN' %}/</b>`; | |
| } catch (error) { | |
| console.log("No custom url subpath option in this app type."); | |
| } |
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.
Thanks a lot. With it, it passed all the e2e test cases.
hamzaimran08
left a comment
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.
LGTM. Good work.
Thanks a lot. |
Description
Source: https://scilifelab.atlassian.net/browse/SS-1176
when we deploy an app it show app-subdomain.serve.scilifelab.se but if user wants the base page to be app-subdomain.serve.scilifelab.se/docs then that should be configurable. There is a field in the database for each app, called url. That’s the field we need to be able to modify with the extra setting.
This should be an advanced setting field for Custom app (similar to how site_dir is an advanced field for specifically Shiny apps now).
Checklist
If you're unsure about any of the items below, don't hesitate to ask. We're here to help!
This is simply a reminder of what we are going to look for before merging your code.
Further comments
Anything else you think we should know before merging your code!