diff --git a/docs/how-tos/create-a-new-filter.rst b/docs/how-tos/create-a-new-filter.rst index 2fcbdc0e..b5d3ea3c 100644 --- a/docs/how-tos/create-a-new-filter.rst +++ b/docs/how-tos/create-a-new-filter.rst @@ -5,20 +5,20 @@ Create a New Open edX Filter with Long-Term Support Open edX Filters are supported and maintained by the Open edX community. This mechanism is designed to be extensible and flexible to allow developers to create new filters to implement custom behavior in the application. This guide describes how to create a new Open edX filter with long-term support by following the practices outlined in the :doc:`../decisions/0007-filter-design-practices` ADR. -Filters design with long-support follow closely the practices described in the ADR to minimize breaking changes, maximize compatibility and support for future versions of Open edX. +Filters designed with long-support follow closely the practices described in the ADR to minimize breaking changes and maximize compatibility and support for future Open edX versions. .. note:: Before starting, ensure you've reviewed the documentation on :doc:`docs.openedx.org:developers/concepts/hooks_extension_framework`, this documentation helps you decide if creating a new filter is necessary. You should also review the documentation on :doc:`../decisions/0007-filter-design-practices` to understand the practices that should be followed when creating a new filter. Throughout this guide, we will use an example of creating a new filter that will be triggered when a user enrolls in a course from the course about page to better illustrate the steps involved in creating a new filter. Key Outlines from Filter Design Practices ------------------------------------------ +******************************************** - Clearly describe the behavior the filter modifies. - Use concise names that reflect the filter's purpose. - Ensure consistent and narrow triggering logic. - Provide sufficient context in arguments to modify intended behavior. -- Avoid runtime dependencies by including relevant context in arguments. +- Avoid runtime dependencies by including the relevant context in arguments. - Keep arguments closely tied to the filter's responsibility. - Allow flexibility for developers to customize behavior. - Handle exceptions properly to halt the application behavior when needed without breaking the application. @@ -26,61 +26,61 @@ Key Outlines from Filter Design Practices - Annotate the argument types for clarity and safety. Assumptions ------------ +************ - You have a development environment set up using `Tutor`_. - You have a basic understanding of Python and Django. - You understand the concept of filters or have reviewed the relevant :doc:`/concepts/index` docs. -- You are familiar with the terminology used in the project, such as the terms :term:`Filter Type`. If not, you can review the :doc:`../reference/glossary` docs. +- You are familiar with the terminology used in the project, such as the term :term:`Filter Type`. If not, you can review the :doc:`../reference/glossary` docs. - You have reviewed the :doc:`../decisions/0007-filter-design-practices` ADR. - You have identified that you need to create a new filter and have a use case for the filter. .. warning:: You only need to create a new filter if you have a use case that cannot be implemented using the existing filters. Before creating a new filter, review the :doc:`existing filters <../reference/filters>` to see if any of them can be used to implement your use case. Steps ------ +******* To create a new Open edX Filter with long-term support, follow these steps: Step 1: Propose the Use Case to the Community -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +=============================================== -Before contributing a new filter, it is important to propose the filter to the community to get feedback on the filter's design and use case. For instance, you could create a post in Open edX Discuss Forum or create a new issue in the repository's issue tracker describing your use case for the new filter. Here is an example of community members that have taken this step: +Before contributing a new filter, it is important to propose the filter to the community to get feedback on the filter's design and use case. For instance, you could create a post in the Open edX Discuss Forum or create a new issue in the repository's issue tracker describing your use case for the new filter. Here is an example of community members who have taken this step: - `Add Extensibility Mechanism to IDV to Enable Integration of New IDV Vendor Persona`_ -.. note:: If your use case is too specific to your organization, you can implement them in your own library and use it within your services by adopting an organization-scoped approach. However, if you think that your use case could be beneficial to the community, you should propose it to the community for feedback and collaboration. +.. note:: If your use case is too specific to your organization, you can implement it in your own library and use it within your services by adopting an organization-scoped approach. However, if you think that your use case could be beneficial to the community, you should propose it to the community for feedback and collaboration. -In our example our use case proposal could be: +In our example, our use case proposal could be: I want to add a filter that will be triggered when a user enrolls in a course from the course about page. This filter will be used to prevent users from enrolling in a course if they do not meet the eligibility criteria. The filter will be triggered when the user clicks the enroll button on the course about page and will check if the user meets the eligibility criteria. If the user does not meet the criteria, the filter will raise an exception to prevent the user from enrolling in the course. If you are confident that the filter is beneficial to the community, you can proceed to the next steps and implement the filter. Step 2: Place Your Filter in an Architecture Subdomain -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +========================================================== -To implement the new filter in the library, you should understand the purpose of the filter and where it fits in the Open edX main architecture subdomains. This will help you place the filter in the right architecture subdomain and ensure that the filter is consistent with the framework's definitions. Fore more details on the Open edX Architectural Subdomains, refer to the :doc:`../reference/architecture-subdomains`. +To implement the new filter in the library, you should understand the purpose of the filter and where it fits in the Open edX main architecture subdomains. This will help you place the filter in the right architecture subdomain and ensure that the filter is consistent with the framework's definitions. For more details on the Open edX Architectural Subdomains, refer to the :doc:`../reference/architecture-subdomains`. In our example, the filter is related to the enrollment process, which is part of the ``learning`` subdomain. Therefore, the filter should be placed in the ``/learning`` module in the library. The subdomain is also used as part of the :term:`filter type `, which is used to identify the filter. The filter type should be unique and follow the naming convention for filter types specified in the :doc:`../decisions/0004-filters-naming-and-versioning` ADR. For the enrollment filter, the filter type could be ``org.openedx.learning.course.enrollment.v1``, where ``learning`` is the subdomain. -.. note:: If you don't find a suitable subdomain for your filter, you can propose a new subdomain to the community. However, new subdomains may require some discussion with the community. So we encourage you to start the conversation as soon as possible through any of the communication channels available. +.. note:: If you don't find a suitable subdomain for your filter, you can propose a new subdomain to the community. However, new subdomains may require some discussion with the community. So, we encourage you to start the conversation as soon as possible through any of the communication channels available. Step 3: Identify the Triggering Logic -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +======================================= The triggering logic for the filter should be identified to ensure that the filter is triggered consistently in the right places. We should ensure that maximum coverage is achieved with minimal modifications when placing the :term:`filter definition` in the service we are modifying. The goal is to focus on core, critical areas where the logic we want to modify executes. For this, choose a specific point in the service where the filter should be triggered. This could be a method in a service, a view, or a model where the logic that you want to modify is executed. The triggering logic should be consistent and narrow to ensure that the filter is triggered only when the conditions are met. For instance, the triggering logic should be a place where all enrollment logic goes through, ensuring that the filter is triggered consistently when a user enrolls in a course. This could be the ``enroll`` method in the enrollment model in the LMS, which is called when a user enrolls in a course in all cases. -.. note:: When designing an filter take into account the support over time of the service and triggering logic. If the service is likely to change or be deprecated, consider the implications of implementing the filter in that service. +.. note:: When designing a filter, consider the support over time of the service and triggering logic. If the service is likely to change or be deprecated, consider the implications of implementing the filter in that service. -.. note:: It is helpful to inspect the triggering logic to review the data that is available at the time the filter is triggered. This will help you determine the arguments of the filter and how the filter can modify the behavior. +.. note:: It is helpful to inspect the triggering logic to review the available data when the filter is triggered. This will help you determine the arguments of the filter and how the filter can modify the behavior. Step 4: Determine the Arguments of the Filter -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +================================================ Filter arguments are in-memory objects that can be manipulated and returned to the calling process to change a component's behavior. This is why they depend heavily on the specific behavior you want to modify and the information available at that point in the application flow. It's helpful to ask yourself: @@ -92,15 +92,16 @@ Our goal is to provide developers with enough control to implement new features As a rule of thumb, start by passing the most relevant context data from the application flow, and then gradually add more details as you analyze the behavior of the triggering logic. -.. note:: Consider the criticality of the arguments, could they be removed in the near future? This would mean introducing breaking changes to the filter. +.. note:: Consider the criticality of the arguments. For example, could they be removed in the near future? This would mean introducing breaking changes to the filter.. -In our example, the filter arguments could include the user, course key, and enrollment mode. These arguments are essential for the filter to determine if the user meets the eligibility criteria for enrollment and it is the minimum information required to make the decision (user to check the eligibility, course key to identify the course, and mode to determine the type of enrollment). +In our example, the filter arguments could include the user, course key, and enrollment mode. These arguments are essential for the filter to determine if the user meets the eligibility criteria for enrollment, and it is the minimum information required to make the decision (user to check the eligibility, course key to identify the course, and mode to determine the type of enrollment). Step 5: Implement the Filter Definition -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +========================================= Implement the :term:`filter definition` by creating a new class that inherits from the |OpenEdxPublicFilter| class. The filter definition should implement the ``run_filter`` method, which defines the input and output behavior of the filter. The ``run_filter`` method should call the method |OpenEdxPublicFilter.run_pipeline|, passing down the input arguments and returning the final output of the filter. This class should be placed in the appropriate subdomain module in the library, in the ``filters.py`` file. + .. note:: The input arguments of the ``run_filter`` method should match the arguments that the triggering logic provides. The output of the filter should be consistent with the behavior that the filter intends to modify. Usually, the output is the modified data or the original data if no modifications are needed. .. note:: Try using type hints to annotate the arguments and return types of the ``run_filter`` method to provide clarity and safety. @@ -144,39 +145,39 @@ In our example, the filter definition could be implemented as follows: - The ``run_filter`` method is the main method of the filter that is called when the filter is triggered. The method should call the |OpenEdxPublicFilter.run_pipeline| method, passing down the input arguments and returning the final output of the filter. - Use arguments names that are consistent with the triggering logic to avoid confusion and improve readability. -.. note:: Implement exceptions that are related to the filter behavior and specify how the filter should modify the application behavior with each exception. The caller should handle each exception differently based the exceptions purpose. For example, the caller should halt the application behavior when the ``PreventEnrollment`` exception is raised. +.. note:: Implement exceptions that are related to the filter behavior and specify how the filter should modify the application behavior with each exception. The caller should handle each exception differently based on the exception's purpose. For example, the caller should halt the application behavior when the ``PreventEnrollment`` exception is raised. Step 6: Trigger the Filter in the Application -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +============================================== After implementing the filter definition, you should trigger the filter in the application where the triggering logic is executed. This will ensure that the filter is triggered when the conditions are met and that the filter is modifying the behavior as intended. -In our example, we identified that the triggering logic is the ``enroll`` method in the enrollment model in the LMS. Therefore, we should trigger the filter in the ``enroll`` method, passing down the user, course key, and mode arguments to the filter. The filter should be placed so that it is triggered before the enrollment process is completed, so can alter the enrollment process if the user does not meet the eligibility criteria. +In our example, we identified that the triggering logic is the ``enroll`` method in the enrollment model in the LMS. Therefore, we should trigger the filter in the ``enroll`` method, passing down the user, course key, and mode arguments to the filter. The filter should be placed so that it is triggered before the enrollment process is completed, which can alter the enrollment process if the user does not meet the eligibility criteria. -.. note:: Try placing the filter so it can be triggered before the process is completed, so it can alter the process if needed. In some cases, this would be at the beginning of the process, while in others it would be elsewhere. +.. note:: Try placing the filter so it can be triggered before the process is completed, so it can alter the process if needed. In some cases, this would be at the beginning of the process, while in others, it would be elsewhere. Step 7: Implement Your Pipeline Steps -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +======================================== -Implementing pipeline steps allows you to modify the behavior of the application when the filter is triggered. Pipeline steps are a sequence of steps that are executed in a specific order to modify the behavior of the application. You can configure them with the :term:`filter configuration` to define the sequence of steps that are executed when the filter is triggered. Follow the steps in the :doc:`../how-tos/create-a-pipeline-step` guide to implement the pipeline steps for the filter. +Implementing pipeline steps allows you to modify the application's behavior when the filter is triggered. Pipeline steps are a sequence of steps that are executed in a specific order to modify the behavior of the application. You can configure them with the :term:`filter configuration` to define the sequence of steps that are executed when the filter is triggered. Follow the steps in the :doc:`../how-tos/create-a-pipeline-step` guide to implement the pipeline steps for the filter. Step 8: Test the Filter -~~~~~~~~~~~~~~~~~~~~~~~ +======================== -After triggering the filter in the application, you should test the filter to ensure that it is triggered when the conditions are met and that the filter is modifying the behavior as intended. You should test the filter with different scenarios to ensure that the filter is working as expected and that the filter is not breaking the application by adding tests in the service where the filter is being implemented. Also, test the filter signature by adding unit tests to the library to ensure that the arguments are being passed correctly and that the output is consistent with the behavior that the filter intends to modify. +After triggering the filter in the application, you should test the filter to ensure that it is triggered when the conditions are met and that the filter is modifying the behavior as intended. You should test the filter with different scenarios to ensure that it is working as expected and that it is not breaking the application by adding tests in the service where the filter is being implemented. Also, test the filter signature by adding unit tests to the library to ensure that the arguments are being passed correctly and that the output is consistent with the behavior that the filter intends to modify. -In the service tests you should include at least the following scenarios: +In the service tests, you should include at least the following scenarios: - The filter is triggered when the triggering logic is executed. - The filter when executed with the correct arguments returns the expected output. -- When there are pipeline steps configured, the filter executes the pipeline steps. +- When pipeline steps are configured, the filter executes them. - When no pipeline steps are configured, the filter acts as a no-op. - The filter does not break the application when raising exceptions. -You can test the filter by configuring a dummy :term:`Pipeline Step` only for testing purposes. This will allow you to test the filter in isolation and ensure that the filter is working as expected. You can also test the filter in the application by triggering the filter with different scenarios to ensure that the filter is working as expected. In the `test_filters.py`_ you can review how this is done for the enrollment filter. +You can test the filter by configuring a dummy :term:`Pipeline Step` only for testing purposes. This will allow you to test the filter in isolation and ensure that the filter is working as expected. You can also test the filter in the application by triggering it with different scenarios to ensure that the filter works as expected. In the `test_filters.py`_, you can review how this is done for the enrollment filter. Step 9: Continue the Contribution Process -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +=========================================== After implementing the filter, you should continue the contribution process by creating a pull request in the repository. The pull requests should contain the changes you made to implement the filter, including the filter definition, data attrs, and the places where the filter is triggered. @@ -184,3 +185,11 @@ For more details on how the contribution flow works, refer to the :doc:`docs.ope .. _Add Extensibility Mechanism to IDV to Enable Integration of New IDV Vendor Persona: https://openedx.atlassian.net/wiki/spaces/OEPM/pages/4307386369/Proposal+Add+Extensibility+Mechanisms+to+IDV+to+Enable+Integration+of+New+IDV+Vendor+Persona .. _test_filters.py: https://github.com/openedx/edx-platform/blob/master/common/djangoapps/student/tests/test_filters.py#L114-L190 + +**Maintenance chart** + ++--------------+-------------------------------+----------------+--------------------------------+ +| Review Date | Reviewer | Release | Test situation | ++--------------+-------------------------------+----------------+--------------------------------+ +|2025-02-13 | Maria Grimaldi | Sumac | Pass. | ++--------------+-------------------------------+----------------+--------------------------------+ diff --git a/docs/how-tos/create-a-pipeline-step.rst b/docs/how-tos/create-a-pipeline-step.rst index 4a073ff8..43edb7ac 100644 --- a/docs/how-tos/create-a-pipeline-step.rst +++ b/docs/how-tos/create-a-pipeline-step.rst @@ -3,34 +3,34 @@ Create a Pipeline Step ###################### -When a filter is triggered in the Open edX platform, the pipeline tooling executes a series of pipeline steps in a specific order. Each pipeline step processes data and returns the output to the next step in the pipeline which can be used to modify the application's behavior. This guide explains how to create a pipeline step for a filter in the Open edX platform. +When a filter is triggered in the Open edX platform, the pipeline tooling executes a series of pipeline steps in a specific order. Each pipeline step processes data and returns the output to the next step in the pipeline, which can be used to modify the application's behavior. This guide explains how to create a pipeline step for a filter in the Open edX platform. -Throughout this guide, we will implement the use case of allowing users to enroll in a course only if they have a valid email address. We will create a pipeline step that checks if the user's email address is valid and raise an exception if it is not. +Throughout this guide, we will implement the use case of allowing users to enroll in a course only if they have a valid email address. We will create a pipeline step that checks if the user's email address is valid and raises an exception if it is not. Assumptions ------------ +************ - You have a development environment set up using `Tutor`_. - You have a basic understanding of Python and Django. - You understand the concept of filters or have reviewed the relevant :doc:`/concepts/index` docs. -- You are familiar with the terminology used in the project, such as the terms :term:`Filter Type`. If not, you can review the :doc:`../reference/glossary` docs. +- You are familiar with the terminology used in the project, such as the term :term:`Filter Type`. If not, you can review the :doc:`../reference/glossary` docs. - You have reviewed the :doc:`../decisions/0007-filter-design-practices` ADR. - You understand the use case for the filter and the specific logic you want to implement in the pipeline step. Steps ------ +****** To create a pipeline step for a filter in the Open edX platform, follow these steps: Step 1: Understand your Use Case and Identify the Filter to Use -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +================================================================= -Before creating a pipeline step, you should understand your use case for the filter and the specific logic you want to implement in the pipeline step. In our example, we want to prevent users from enrolling in a course if they do not have a valid email address. We will create a pipeline step that checks if the user's email address is valid and raise an exception if it is not. +Before creating a pipeline step, you should understand your use case for the filter and the specific logic you want to implement in the pipeline step. In our example, we want to prevent users from enrolling in a course if they do not have a valid email address. We will create a pipeline step that checks if the user's email address is valid and raises an exception if it is not. You should review the :doc:`list of filters <../reference/filters>` available in the Open edX platform and identify the filter that best fits your use case. In our example, we will use the |CourseEnrollmentStarted| filter to implement the logic for our use case. You should review the filter's arguments to understand the data that will be passed to the pipeline step and the expected output. This will help you define the pipeline step's logic and signature. Step 2: Install Open edX Filters -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +================================= First, add the ``openedx-filters`` library into your dependencies so the environment recognizes the filter you want to use. You can install ``openedx-filters`` by running: @@ -38,14 +38,14 @@ First, add the ``openedx-filters`` library into your dependencies so the environ pip install openedx-filters -This will mainly make the filters available for your CI/CD pipeline and local development environment. If you are using the Open edX platform, the library should be already be installed in the environment so no need to install it. +This will mainly make the filters available for your CI/CD pipeline and local development environment. If you are using the Open edX platform, the library should already be installed in the environment, so there is no need to install it. Step 3: Create a Pipeline Step -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +================================== A :term:`pipeline step` is a class that inherits from the base class |PipelineStep| and defines specific logic within its |PipelineStep.run_filter| method. The ``run_filter`` method is executed by the pipeline tooling when the filter is triggered. To create a pipeline step, you should: -1. Create a new Python module for the pipeline step called ``pipeline.py``. Pipeline steps are usually implemented in a `Open edX Django plugins`_, so you should create the module in the plugin's directory. +1. Create a new Python module for the pipeline step called ``pipeline.py``. Pipeline steps are usually implemented in a `Open edX Django plugin`_, so you should create the module in the plugin's directory. 2. Create a new class for the pipeline step that inherits from the base class |PipelineStep|. 3. Implement the logic for the pipeline step within the |PipelineStep.run_filter| method. The method signature should match the filter's signature to ensure compatibility with the pipeline tooling. In our example, the method should accept the user, course key, and enrollment mode as arguments and return the same arguments if the email address is valid. If the email address is not valid, the method should raise an exception. 4. You can take an iterative approach to developing the pipeline step by testing it locally and making changes as needed. @@ -78,10 +78,10 @@ Consider the following when creating a pipeline step: - Limit each step to a single responsibility to make the code easier to maintain and test. - Keep the pipeline step logic simple and focused on the specific task it needs to perform. - Consider the performance implications of the pipeline step and avoid adding unnecessary complexity or overhead, considering the pipeline will be executed each time the filter is triggered. -- Implement error handling and logging in the pipeline step to handle exceptions and provide useful information for debugging, considering both development and production environments. E.g., when the email is not valid, we raise an exception to prevent the user from enrolling in the course. Logging relevant information when an exception is raised can help identify the root cause of a problem. +- Implement error handling and logging in the pipeline step to handle exceptions and provide useful information for debugging, considering both development and production environments. For example, when the email is not valid, we raise an exception to prevent the user from enrolling in the course. Logging relevant information when an exception is raised can help identify the root cause of a problem. Step 4: Configure the Pipeline for the Filter -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +=============================================== After creating the pipeline step, you need to configure the pipeline for the filter in the :term:`filter configuration`. The configuration settings are specific for each :term:`filter type` and define the pipeline steps to be executed when the filter is triggered. You should add the path to the pipeline step class in the filter's pipeline configuration. @@ -99,7 +99,7 @@ In our example, we will configure the pipeline for the |CourseEnrollmentStarted| } Step 5: Test the Pipeline Step -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +=============================== After creating the pipeline step and configuring the pipeline for the filter, you should test the pipeline step to ensure it works as expected. You can trigger the filter in your development environment and verify that the pipeline step is executed correctly. You should test different scenarios, including valid and invalid email addresses, to ensure the pipeline step behaves as expected. @@ -128,7 +128,7 @@ In our example, you could write a unit test for the pipeline step like this: ) Step 6: Debug and Iterate -~~~~~~~~~~~~~~~~~~~~~~~~~ +========================== After testing the pipeline step, you should debug and iterate on the implementation as needed. Consider the following when debugging and iterating on the pipeline step: @@ -139,6 +139,19 @@ After testing the pipeline step, you should debug and iterate on the implementat - In unit tests, mock external dependencies as closely as possible to the real environment to ensure the pipeline step behaves as expected in different scenarios, since sometimes using real data can lead to unexpected results. - In production environments, monitor the pipeline step's performance and behavior to identify any issues and optimize the implementation as needed. -.. note:: The default behavior of the pipeline tooling is to fail silently if a runtime exception is raised in a pipeline step. You can configure the filter to raise an exception when the pipeline step fails by setting ``fail_silently: False`` in the filter configuration. This will help you identify issues early and take appropriate action to resolve them. :term:`Filter Exceptions` will always be raised in the pipeline and will halt the execution of the pipeline. You can use exceptions to control the flow of the pipeline and handle specific scenarios in the pipeline step. In our example, we raise an exception when the user's email address is not valid to prevent them from enrolling in the course. The exceptions considered by the ``fail_silently`` flag are runtime exceptions that are not intentionally raised by the developer during the filter's execution, use the configuration as you see fit. +.. note:: The default behavior of the pipeline tooling is to fail silently if a runtime exception is raised in a pipeline step. You can configure the filter to raise an exception when the pipeline step fails by setting ``fail_silently: False`` in the filter configuration. This will help you identify issues early and take appropriate action to resolve them. :term:`Filter exceptions` will always be raised in the pipeline and will halt its execution. You can use exceptions to control the flow of the pipeline and handle specific scenarios in the pipeline step. In our example, we raise an exception when the user's email address is not valid to prevent them from enrolling in the course. The exceptions considered by the ``fail_silently`` flag are runtime exceptions that the developer does not intentionally raise during the filter's execution, use the configuration as you see fit. + +.. _Tutor: https://docs.tutor.edly.io/ +.. _CourseEnrollmentStarted filter: https://github.com/openedx/openedx-filters/blob/main/openedx_filters/learning/filters.py#L145-L170 +.. _PipelineStep: https://github.com/openedx/openedx-filters/blob/main/openedx_filters/filters.py#L10-L77 +.. _Open edX Django plugin: https://docs.openedx.org/en/latest/developers/concepts/platform_overview.html#new-plugin +.. _run_filter: https://github.com/openedx/openedx-filters/blob/main/openedx_filters/filters.py#L60-L77 + +**Maintenance chart** + ++--------------+-------------------------------+----------------+--------------------------------+ +| Review Date | Reviewer | Release | Test situation | ++--------------+-------------------------------+----------------+--------------------------------+ +|2025-02-13 | Maria Grimaldi | Sumac | Pass. | ++--------------+-------------------------------+----------------+--------------------------------+ -.. _Open edX Django plugins: https://docs.openedx.org/en/latest/developers/concepts/platform_overview.html#new-plugin diff --git a/docs/quickstarts/use-filters-to-change-enrollment.rst b/docs/quickstarts/use-filters-to-change-enrollment.rst index 694ddc2a..927fa5e1 100644 --- a/docs/quickstarts/use-filters-to-change-enrollment.rst +++ b/docs/quickstarts/use-filters-to-change-enrollment.rst @@ -1,7 +1,7 @@ Using Open edX Filters in the LMS service ------------------------------------------ +########################################### -Live example +Live Example ************ For filter steps samples you can visit the `openedx-filters-samples`_ plugin, where @@ -9,3 +9,11 @@ you can find minimal steps exemplifying the different ways on how to use ``openedx-filters``. .. _openedx-filters-samples: https://github.com/eduNEXT/openedx-filters-samples + +**Maintenance chart** + ++--------------+-------------------------------+----------------+--------------------------------+ +| Review Date | Reviewer | Release | Test situation | ++--------------+-------------------------------+----------------+--------------------------------+ +|2025-02-13 | Maria Grimaldi | Sumac | Pass. | ++--------------+-------------------------------+----------------+--------------------------------+