Skip to content
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

Customizable URLs for studio #1316

Merged
merged 28 commits into from
May 18, 2022
Merged

Customizable URLs for studio #1316

merged 28 commits into from
May 18, 2022

Conversation

mbertrand
Copy link
Member

@mbertrand mbertrand commented May 11, 2022

Pre-Flight checklist

  • Screenshots and design review for any changes that affect layout or styling
  • Migrations
    • Migration is backwards-compatible with current production code
  • Testing
    • Code is tested
    • Changes have been manually tested
  • Settings
    • New settings are documented and present in app.json
    • New settings have reasonable development defaults, if applicable

What are the relevant tickets?

Closes #1336

What's this PR do?

  • Adds a url_path field to Website. The migration should prepopulate it with the same value as Website.name for all sites that have already been published to production.
  • When publishing to draft/live, url_path can be sent in the request body to set the field's value. The serializer should allow the field value to change as long as the site hasn't been published to production yet and the value is valid. If the value is changed, all WebsiteContent objects with populated file values for the site will have their synced_checksums reset so they will be resynced to github with the updated path.
  • Updates the HugoMarkdownSerializer to save the correct file values (based on url_path) to the backend (git) and vice versa.
  • Uses a new site-url-format field in site config to suggest a pattern for this field to the user on the front end.
  • Changes the publish drawer form, to include a url field if the site has not been published to production yet.
  • Updates both individual and mass pipeline definitions so that S3 files are copied to the right places. Creates/updates the site pipeline before each publish event to ensure that it has the correct url path baked in.

How should this be manually tested?

  • Update the ocw-course starter config with the new line here.
  • Start studio with concourse docker-compose --profile concourse up
  • Run manage.py upsert_mass_build_pipeline and backpopulate_pipelines, they should both succeed.
  • Try to publish an existing site with a publish_date, the drawer should look about the same and work the same.
  • Try to publish a new or existing site without a publish_date, you should see a URL field with a suggested path, any existing metadata values matching the pattern should be present. Enter a valid value and click 'Publish' to draft, check to see that the url_path is updated and the pipeline is triggered (it will fail, that's ok).
  • Go to the github repo and check that any resources for images, pdfs, etc have a file value that contains the site's url path.
  • Reload the page and try to publish again, the URL field should be set to whatever you entered last time instead of the suggested path. Modify it and click the "Publish" button, the pipeline should trigger again. Also check on the git repo and make sure the resource file paths have been updated again to the latest value.
  • The changes here affect most parts of the site, so try just about everything and make sure it still works.
  • The changes to the pipelines are best tested when this hits RC.

Where should the reviewer start?

https://github.com/mitodl/hq/discussions/1

Screenshots (if appropriate)

An unpublished site without any user-supplied url path so far:

Screen Shot 2022-05-17 at 3 45 16 PM

An unpublished site with a previously chosen url (still editable):

Screen Shot 2022-05-17 at 3 53 26 PM

A published site (no longer editable):

Screen Shot 2022-05-17 at 3 54 10 PM

@codecov-commenter
Copy link

codecov-commenter commented May 16, 2022

Codecov Report

Merging #1316 (415089c) into master (dfbfdfa) will increase coverage by 0.04%.
The diff coverage is 95.36%.

@@            Coverage Diff             @@
##           master    #1316      +/-   ##
==========================================
+ Coverage   89.06%   89.10%   +0.04%     
==========================================
  Files         231      232       +1     
  Lines        9557     9687     +130     
  Branches     1778     1827      +49     
==========================================
+ Hits         8512     8632     +120     
- Misses        928      930       +2     
- Partials      117      125       +8     
Impacted Files Coverage Δ
main/settings.py 94.49% <ø> (ø)
static/js/types/websites.ts 100.00% <ø> (ø)
static/js/util/factories/websites.ts 98.70% <ø> (ø)
websites/api.py 97.40% <ø> (ø)
content_sync/serializers.py 89.37% <75.00%> (-0.37%) ⬇️
websites/views.py 96.76% <86.95%> (-1.03%) ⬇️
websites/models.py 93.56% <92.30%> (-1.61%) ⬇️
content_sync/api.py 100.00% <100.00%> (ø)
content_sync/pipelines/concourse.py 89.68% <100.00%> (-0.14%) ⬇️
static/js/components/PublishDrawer.tsx 95.18% <100.00%> (ø)
... and 10 more

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update dfbfdfa...415089c. Read the comment docs.

@mbertrand mbertrand force-pushed the mb/siteurls branch 2 times, most recently from f21f4e5 to 058f706 Compare May 17, 2022 17:49
@mbertrand mbertrand changed the title Site URL based on starter config and metadata fields Customizable URLs for studio May 17, 2022
Copy link
Contributor

@ChristopherChudzicki ChristopherChudzicki left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will be great :) I'm still doing the manual testing but have looked through most of the code except the pipeline stuff. I left a few specific comments largey around ts stuff on the frontend. Small, but probably worth addressing since they're low effort.

Frontend bug I noticed...:

  1. Edit and save metadata form
  2. click publish ... publishing form is using old metadata values.

@@ -519,7 +567,7 @@ class Meta:
class WebsiteContentCreateSerializer(
serializers.ModelSerializer, RequestUserSerializerMixin
):
"""Serializer which creates a new WebsiteContent"""
"""Serializer mixin which validates that urls are unique"""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this docstring correct?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, pasted in the wrong place

Comment on lines 15 to 18
onSubmit: (
values: any,
formikHelpers: FormikHelpers<any>
) => void | Promise<any>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
onSubmit: (
values: any,
formikHelpers: FormikHelpers<any>
) => void | Promise<any>
onSubmit: (
values: SiteFormValues,
formikHelpers: FormikHelpers< SiteFormValues >
) => void

void is good enough for the return value; nothing should be using that value.

.trim()
.required()
.matches(
/^[a-zA-Z0-9\-._]*$/,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably a question for Ferdi, but we may want to pick either dash or underscore and not allow both.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally don't like underscores in the url but I dont think we should disallow them .

option
}: Props): JSX.Element | null => {
const initialValues: SiteFormValues = {
// @ts-ignore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here and elsewhere, we should use @ts-expect-error for suppressing errors. That directive will throw an error if used unnecessarily. (I've encountered a fair number of unnecessary @ts-ignore in our code; @ts-expect-error is somewhat newer, so may not have existed when studio started.).

website,
disabled,
option
}: Props): JSX.Element | null => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This component never returns null.

My personal preference is to use the React.FC helper to declare functional component types...export const PublishForm: React.FC<Props> = ({...whateverProps}) => {}, then React takes care of the return type.

Comment on lines 122 to 123
expect(error).toBeInstanceOf(ValidationError)
// @ts-ignore
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's an assertIsInstanceOf helper in test_util if you want to do this without the @ts-ignore. assertIsInstanceOf will narrow the type (expect...toBeInstanceOf... does not narrow the type).

Comment on lines 56 to 59
;[null, "courses/5.2-my-course"].forEach(urlPath => {
it(`initialValue for url_path should be based on website ${
urlPath ? "url_path" : "url_suggestion"
}`, () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use it.each([...])("Description...", option => {}) here to reduce nesting / use jest conventions. https://jestjs.io/docs/api#describeeachtablename-fn-timeout

If the array is an array of objects, you can access them by $name in the description string... My personal preference is to hardcode the title formatting like

it.each([
{ urlPath: null, basedOn: "url_suggestion" },
{ urlPath: "courses/5.2-my-course", basedOn: "url_path" }
]).only("initialValue ... based on website $basedOn", ({ urlPath }) => {...})

@@ -0,0 +1,130 @@
import React from "react"
import sinon, { SinonStub } from "sinon"
import { shallow } from "enzyme"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a general comment, not worth addressing right now.

Opinion: For new tests, we should avoid enzyme and shallow rendering. Enzyme does only supports React 16 and below, which is two major versions behind current. See #1275 and or https://github.com/mitodl/hq/discussions/17

Comment on lines +238 to +239
for section in re.findall(r"(\[.+?\])+", site_config.site_url_format) or []:
section_type, section_field = re.sub(r"[\[\]]+", "", section).split(":")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we changed the config format to

{sitemetadata.primary_course_number}-{sitemetadata.course_title}-{sitemetadata.term}-{sitemetadata.year}

We might be able to do site_config.site_url_format.format(sitemetadata=metadata).

Do you think this would be worth doing? We'd need a version of the metadata dict that supports attribute access, but we would get formatting and some validation builtin (e.g., .format raises KeyError if keys are missing).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea! But it doesn't quite work as intended if any of the metadata fields haven't been filled out yet. For example, when I try it on a site with fields for primary_course_number and title but no term and year, I get:

slugify(site_config.site_url_format.format(**metadata).replace(".", "-"))

>2.18-time-travel-101-abc-

But what I want is placeholders for the missing values like 2.18-time-travel-101-abc-{term}-{year}

@ChristopherChudzicki
Copy link
Contributor

ChristopherChudzicki commented May 18, 2022

@mbertrand I tried the pipelines / renaming etc and everything worked as expected: URLs got updated in github when I changed the course url 👍

Do you think the frontend form using outdated metadata is a blocking issue? Probably not?

@mbertrand
Copy link
Member Author

Do you think the frontend form using outdated metadata is a blocking issue? Probably not?

I think I know how to fix that, will give it a shot.

@gumaerc
Copy link
Contributor

gumaerc commented May 18, 2022

I'm not sure I could point out anything from a technical standpoint that @ChristopherChudzicki hasn't already mentioned, but for what it's worth I experienced the same behavior where updating my metadata wasn't reflected on the URL in the publish drawer until I refreshed the page. One UI thing that I noticed that I didn't see pointed out is that with the new text field in the publish drawer, it seems to open super wide:

image

Do we maybe want to restrict the width on this? I tried publishing my test course, which already existed, and I noticed that the file attributes have a seemingly random amount of /media prefixed at the beginning. Is this maybe something to do with my local env, or the test course itself? You can take a look at the resources in my published test course here: https://github.com/gumaerc-testorg/cpg-test-course-3/tree/main/content/resources

@mbertrand
Copy link
Member Author

I made the publish drawer deliberately wide if the site hasn't been published to production yet, because the site-url-format string that is the default value in the URL field is so long. I mentioned to Ferdi that maybe we should come up with some shorter value to display, maybe without the sitemetadata: in each section, so [primary_course_number]-[title]-[term]-[year] (though that's still a bit long).

If you're seeing /media for files. you probably don't have OCW_STUDIO_USE_S3 set to True in your .env file.

@mbertrand
Copy link
Member Author

The suggested url format in the publish drawer should now be updated after a metadata change.

Copy link
Contributor

@gumaerc gumaerc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@mbertrand mbertrand merged commit 3c0e45a into master May 18, 2022
@odlbot odlbot mentioned this pull request May 18, 2022
2 tasks
@odlbot odlbot mentioned this pull request May 24, 2022
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Customizable URLs
5 participants