|  | 
|  | 1 | +2. Footer Links | 
|  | 2 | +######################## | 
|  | 3 | +.. The title should be a short noun phrase. For example, "1. Django IDA" or "9. LDAP for Multitenant Integration"; filename should be lowercase with punctuation removed and spaces replaced by dash | 
|  | 4 | +
 | 
|  | 5 | +Status | 
|  | 6 | +****** | 
|  | 7 | + | 
|  | 8 | +**Draft (=> Accepted)** | 
|  | 9 | + | 
|  | 10 | +.. **Accepted** *2023-05-11* | 
|  | 11 | +
 | 
|  | 12 | +.. Standard statuses | 
|  | 13 | +    - **Draft** if the decision is newly proposed and in active discussion | 
|  | 14 | +    - **Provisional** if the decision is still preliminary and in experimental phase | 
|  | 15 | +    - **Accepted** *(date)* once it is agreed upon | 
|  | 16 | +    - **Superseded** *(date)* with a reference to its replacement if a later ADR changes or reverses the decision | 
|  | 17 | +
 | 
|  | 18 | +    If an ADR has Draft status and the PR is under review, you can either use the intended final status (e.g. Provisional, Accepted, etc.), or you can clarify both the current and intended status using something like the following: "Draft (=> Provisional)". Either of these options is especially useful if the merged status is not intended to be Accepted. | 
|  | 19 | +
 | 
|  | 20 | +Context | 
|  | 21 | +******* | 
|  | 22 | + | 
|  | 23 | +.. This section describes the forces at play, including technological, political, social, and project local. These forces are probably in tension, and should be called out as such. The language in this section is value-neutral. It is simply describing facts. | 
|  | 24 | +
 | 
|  | 25 | +The footer component is basic - it only has a trademark logo and a language | 
|  | 26 | +selector. It doesn't look similar to the legacy UI footer. | 
|  | 27 | + | 
|  | 28 | +It also doesn't have many customization options. You can customize | 
|  | 29 | +LMS base URL and trade mark logo. | 
|  | 30 | + | 
|  | 31 | +If you want to have more advanced customizations, it's necessary to fork the | 
|  | 32 | +component, modify it, and then install the fork as a package instead of the | 
|  | 33 | +default footer at build time of MFEs. | 
|  | 34 | + | 
|  | 35 | +We want to make the MFE footer to closer resemble the legacy UI footer by | 
|  | 36 | +adding the same footer links as in the legacy UI, and to make it easier to | 
|  | 37 | +style the footer component. | 
|  | 38 | + | 
|  | 39 | +Decision | 
|  | 40 | +******** | 
|  | 41 | + | 
|  | 42 | +.. This section describes our response to these forces. It is stated in full sentences, with active voice. "We will …" | 
|  | 43 | +
 | 
|  | 44 | +Links | 
|  | 45 | +===== | 
|  | 46 | + | 
|  | 47 | +For specifying the footer links, we are going to use `MFE's config mechanism`_. | 
|  | 48 | +That would allow to specify a list of links in various ways: | 
|  | 49 | + | 
|  | 50 | +* At build time: | 
|  | 51 | +  * Via environmental variables | 
|  | 52 | +  * By providing them in ``env.config.js``, like so: | 
|  | 53 | + | 
|  | 54 | +    .. code-block:: javascript | 
|  | 55 | +
 | 
|  | 56 | +        const config = { | 
|  | 57 | +            FOOTER_LINKS: [ | 
|  | 58 | +                {"url": "https://google.com", "text": "Terms of service"}, | 
|  | 59 | +                {"url": "https://duckduckgo.com", "text": "Acceptable Use Policy"}, | 
|  | 60 | +                {"url": "https://openedx.org", "text": "Privacy Policy"}, | 
|  | 61 | +            ], | 
|  | 62 | +        }; | 
|  | 63 | +
 | 
|  | 64 | +        export default config; | 
|  | 65 | +
 | 
|  | 66 | +* At runtime, via ``MFE_CONFIG`` in LMS's Django settings: | 
|  | 67 | + | 
|  | 68 | +    .. code-block:: python | 
|  | 69 | +
 | 
|  | 70 | +        MFE_CONFIG = { | 
|  | 71 | +            "FOOTER_LINKS": [ | 
|  | 72 | +                {"url": "https://google.com", "text": "Terms of service"}, | 
|  | 73 | +                {"url": "https://duckduckgo.com", "text": "Acceptable Use Policy"}, | 
|  | 74 | +                {"url": "https://openedx.org", "text": "Privacy Policy"}, | 
|  | 75 | +            ], | 
|  | 76 | +        } | 
|  | 77 | +
 | 
|  | 78 | +In case the array is undefined or empty, we won't render any links (or it's | 
|  | 79 | +container). | 
|  | 80 | + | 
|  | 81 | +.. _MFE's config mechanism: https://github.com/openedx/frontend-platform/blob/master/src/config.js | 
|  | 82 | + | 
|  | 83 | +Styles | 
|  | 84 | +====== | 
|  | 85 | + | 
|  | 86 | +Since the root of the footer component is rendered as a footer HTML element, it | 
|  | 87 | +is unique enough to use ``footer`` as selector. To make it more convenient to | 
|  | 88 | +style footer's children, we will add unique class names, which will simplify | 
|  | 89 | +the SCSS selectors. | 
|  | 90 | + | 
|  | 91 | +These SCSS styles can be put in a custom `branding package`_ into | 
|  | 92 | +``paragon/_overrides.scss``. | 
|  | 93 | + | 
|  | 94 | +.. _branding package: https://github.com/openedx/brand-openedx | 
|  | 95 | + | 
|  | 96 | +Consequences | 
|  | 97 | +************ | 
|  | 98 | + | 
|  | 99 | +.. This section describes the resulting context, after applying the decision. All consequences should be listed here, not just the "positive" ones. A particular decision may have positive, negative, and neutral consequences, but all of them affect the team and project in the future. | 
|  | 100 | +
 | 
|  | 101 | +Positive | 
|  | 102 | +======== | 
|  | 103 | + | 
|  | 104 | +* There will be an option to make the MFE footer look similar to the legacy UI | 
|  | 105 | +  footer, without having to create and maintain a fork. | 
|  | 106 | +* Can add custom text/urls for links, unlike what branding v1 API allows. | 
|  | 107 | + | 
|  | 108 | +Negative | 
|  | 109 | +======== | 
|  | 110 | + | 
|  | 111 | +* There are already parameters that allow configuring the footer links for the | 
|  | 112 | +  legacy UI, which means that configuration will be duplicated (potentially in | 
|  | 113 | +  multiple places), in cases when the aim is to make the links in the legacy UI | 
|  | 114 | +  and MFE footers that same. | 
|  | 115 | + | 
|  | 116 | +Rejected Alternatives | 
|  | 117 | +********************* | 
|  | 118 | + | 
|  | 119 | +.. This section lists alternate options considered, described briefly, with pros and cons. | 
|  | 120 | +
 | 
|  | 121 | +React component props API | 
|  | 122 | +========================= | 
|  | 123 | + | 
|  | 124 | +Instead of reading the configuration values in the component, we could be | 
|  | 125 | +reading it somewhere else, and passing the values as props to the react | 
|  | 126 | +component. We couldn't identify any pros to this approach, and the cons are the | 
|  | 127 | +same as the cons from decoupling. | 
|  | 128 | + | 
|  | 129 | +Styling using CSS variables | 
|  | 130 | +=========================== | 
|  | 131 | + | 
|  | 132 | +Exposing styling customizations through the CSS variables would be similar to | 
|  | 133 | +styling via CSS classes, and it would be better aligned with the current | 
|  | 134 | +philosophy of Paragon, since it prefers CSS variables over custom CSS classes. | 
|  | 135 | + | 
|  | 136 | +The cons however, is that you can only expose one CSS attribute per variable. | 
|  | 137 | +This means that we would either heavily limit the styling options, or would | 
|  | 138 | +have to create many variables for each element and CSS attribute. | 
|  | 139 | + | 
|  | 140 | +Brading API V1 | 
|  | 141 | +============== | 
|  | 142 | + | 
|  | 143 | +LMS already has an API endpoint which could be used to retrieve the links that | 
|  | 144 | +are used in the footer (legacy UI footer uses the same API) in JSON format - | 
|  | 145 | +``api/branding/v1/footer``. | 
|  | 146 | + | 
|  | 147 | +The pros of using this approach would be that legacy and MFE footer would use | 
|  | 148 | +the same API and would have the same links, without having to duplicate the | 
|  | 149 | +configuration. | 
|  | 150 | + | 
|  | 151 | +The cons of using this approach are: | 
|  | 152 | + | 
|  | 153 | +* It would be necessary to make an additional API call from an MFE to get the | 
|  | 154 | +  links. | 
|  | 155 | +* No custom links, only what is allowed by the branding API. | 
|  | 156 | + | 
|  | 157 | +Third party footer | 
|  | 158 | +================== | 
|  | 159 | + | 
|  | 160 | +The proposed changes won't affect anyone who won't use this feature. And these | 
|  | 161 | +changes eliminate some frequent reasons for forking the footer component. Thus | 
|  | 162 | +creating a third party footer for these features, instead of upstreaming them | 
|  | 163 | +seems unjustified. | 
|  | 164 | + | 
|  | 165 | +.. References | 
|  | 166 | +.. ********** | 
|  | 167 | +
 | 
|  | 168 | +.. (Optional) List any additional references here that would be useful to the future reader. See `Documenting Architecture Decisions`_ for further input. | 
0 commit comments