diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml index 452ebb34..d39d746a 100644 --- a/.github/dependabot.yaml +++ b/.github/dependabot.yaml @@ -3,5 +3,5 @@ updates: - package-ecosystem: bundler directory: "/" schedule: - interval: daily - open-pull-requests-limit: 10 + interval: weekly + open-pull-requests-limit: 5 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml new file mode 100644 index 00000000..c5901037 --- /dev/null +++ b/.github/workflows/docs.yml @@ -0,0 +1,66 @@ +name: Docs Build + +on: + push: + paths: + - 'docs/**' + pull_request: + paths: + - 'docs/**' + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + defaults: + run: + working-directory: docs + steps: + - uses: actions/checkout@v4 + + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3' + bundler-cache: true + working-directory: docs + + - name: Build Jekyll site + run: bundle exec jekyll build --baseurl /flextensions + env: + JEKYLL_ENV: production + PAGES_REPO_NWO: berkeley-cds/flextensions + + - name: Check for broken internal links + run: | + # Verify all internal .html files were generated + echo "Generated site files:" + find _site -name '*.html' | sort + echo "" + echo "Checking for broken internal links..." + # Extract internal href links and verify they resolve + broken=0 + for file in $(find _site -name '*.html'); do + # Extract href values pointing to /flextensions/ paths + grep -oP 'href="(/flextensions/[^"]*)"' "$file" 2>/dev/null | while read -r match; do + path=$(echo "$match" | grep -oP '"/flextensions/[^"]*"' | tr -d '"') + # Convert URL path to file path + local_path="_site${path#/flextensions}" + # Check if it's a directory (index.html) or file + if [ -d "$local_path" ] && [ -f "$local_path/index.html" ]; then + continue + elif [ -f "$local_path" ]; then + continue + elif [ -f "${local_path}.html" ]; then + continue + elif [ -f "${local_path%/}/index.html" ]; then + continue + else + echo "::warning file=$file::Broken link: $path (resolved to $local_path)" + broken=1 + fi + done + done + if [ "$broken" -eq 1 ]; then + echo "::warning::Some internal links may be broken. Check warnings above." + fi diff --git a/.gitignore b/.gitignore index 8faebd3e..b8b4a5cd 100644 --- a/.gitignore +++ b/.gitignore @@ -81,3 +81,9 @@ yarn-debug.log* /config/credentials/production.key .DS_Store + +# Jekyll docs +docs/_site/ +docs/.jekyll-cache/ +docs/.jekyll-metadata +docs/Gemfile.lock diff --git a/README.md b/README.md index 784f6758..dd6b54ab 100644 --- a/README.md +++ b/README.md @@ -81,8 +81,6 @@ Cite the software itself using the following DOI: https://doi.org/10.5281/zenodo.17246291 -References: - ``` # IEEE [1]M. Ball, “Flextensions”. Zenodo, Aug. 20, 2025. doi: 10.5281/zenodo.17246291. diff --git a/app/controllers/session_controller.rb b/app/controllers/session_controller.rb index 230bbd63..81fd512c 100644 --- a/app/controllers/session_controller.rb +++ b/app/controllers/session_controller.rb @@ -35,6 +35,7 @@ def logout def omniauth_callback if params[:error].present? + Rails.logger.error("OmniAuth callback error: #{params[:error_description] || params[:error]}") redirect_to root_path, alert: 'Authentication failed. Please try again.' return end diff --git a/app/controllers/user_to_courses_controller.rb b/app/controllers/user_to_courses_controller.rb index 353e63eb..b07d7336 100644 --- a/app/controllers/user_to_courses_controller.rb +++ b/app/controllers/user_to_courses_controller.rb @@ -10,7 +10,7 @@ def toggle_allow_extended_requests render json: { success: true }, status: :ok else flash[:alert] = "Failed to update enrollment: #{@enrollment.errors.full_messages.to_sentence}" - render json: { redirect_to: course_path(@course) }, status: :unprocessable_entity + render json: { redirect_to: course_path(@course) }, status: :unprocessable_content end end diff --git a/docs/Gemfile b/docs/Gemfile new file mode 100644 index 00000000..b03e0293 --- /dev/null +++ b/docs/Gemfile @@ -0,0 +1,15 @@ +source "https://rubygems.org" + +gem "jekyll", "~> 4.3" +gem "jekyll-theme-primer", "~> 0.6" + +group :jekyll_plugins do + gem "jekyll-feed", "~> 0.12" + gem "jekyll-seo-tag", "~> 2.8" +end + +# Windows and JRuby does not include zoneinfo files +platforms :mingw, :x64_mingw, :mswin, :jruby do + gem "tzinfo", ">= 1", "< 3" + gem "tzinfo-data" +end diff --git a/docs/README.md b/docs/README.md index 63cdf092..4908afa4 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,65 +1,42 @@ ---- -title: Flextensions - Assignment Extension Management for Canvas -permalink: / ---- - - +# Flextensions Documentation -# Welcome to Flextensions 👋 [→][flextensions] +This directory contains the source files for the Flextensions documentation site, served at [berkeley-cdss.github.io/flextensions](https://berkeley-cdss.github.io/flextensions). -[**Flextensions**][flextensions] is your one-stop solution to manage and access assignment extensions across all your UC Berkeley courses*. Whether you're course staff or a student, Flextensions streamlines extension workflows and makes extension data easy to access and manage. +The site is built with [Jekyll](https://jekyllrb.com/) and deployed automatically via GitHub Pages from the `docs/` directory on `main`. -_* Well, all of your courses which use bCourses or Gradescope and enable assignment extensions. :)_ - -[flextensions]: https://flextensions.berkeley.edu - ---- +## Local Development -## 🚀 What Does Flextensions Do? +```bash +cd docs +bundle install +bundle exec jekyll serve +``` -### [🧑‍🏫 For Course Staff](/flextensions/instructors/): -- View and manage extensions requests for all assignments in your course. -- Grant extensions to students with a few clicks. -- Monitor extension usage across your course. -- Automate approving extension requests and email sending +Then visit http://localhost:4000/flextensions/. -### [🎓 For Students](/flextensions/students/): -- View all your granted extensions in one place. -- See how long your extension lasts and when the new due date is. -- Stay informed and organized without checking multiple systems. +## Directory Structure ---- +- `*.md` — Documentation pages (each has YAML front matter with `title` and `permalink`) +- `_config.yml` — Jekyll configuration +- `api/` — Swagger/OpenAPI reference (static HTML, not processed by Jekyll) +- `img/` — Images used in documentation +- `_site/` — Generated output (gitignored) -## 🔧 How It Works +## Adding a Page -Flextensions connects directly with bCourses (Canvas) and imports your assignments. The interface is intuitive and role-based—course staff can grant and manage, while students can view. +Create a new `.md` file with front matter: +```markdown --- - -Are you a developer? Check out the [Developer Documentation](/flextensions/developers/) documention to contribute to Flextensions and the [API Reference](/flextensions/api/) to learn how to integrate Flextensions with your own applications. - -Want to know what's new? See the [Updates page](/flextensions/updates/) for recent changes or visit the [GitHub Releases](https://github.com/berkeley-cdss/flextensions/releases) for a full changelog. - +title: Your Page Title +permalink: /your-page/ --- -## Credits - -Flextensions was originally developed by students in [CS169L](https://saasbook.info), during the Spring 2024 and Spring 2025 semesters, as part of the [Software as a Service](https://saasbook.info) course at UC Berkeley. - -Student developers (in alphabetical order): +Content here... +``` -* Connor Bernard, Spring 2024 -* Cynthia Lixinyi, Spring 2024 -* [Diandian Liu](https://www.linkedin.com/in/diandian-liu/), Spring 2025 -* [Eric Huang](https://huanger2.github.io), Spring 2025 -* Evan Kandell, Spring 2024 -* Sepehr Behmanesh Fard, Spring 2024 -* [Tashrique Ahmed](https://tashrique.com), Spring 2025 -* [Tianye Meng](https://www.linkedin.com/in/tianye-meng-611b22253/), Spring 2025 -* [Yaman Tarakji](https://www.linkedin.com/in/yaman-tarakji-602530196), Spring 2025 -* Zee Babar, Spring 2024 +Internal links should use absolute paths starting with `/flextensions/`, e.g. `[Developers](/flextensions/developers/)`. -[Michael Ball][mball], Armando Fox, and Lisa Yan are the faculty members who have overseen the development of Flextensions. +## CI -[mball]: https://mball.co/ +The `Docs Build` workflow (`.github/workflows/docs.yml`) validates the Jekyll build and checks for broken internal links on PRs that touch `docs/`. diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 00000000..72f64c12 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1,27 @@ +title: Flextensions +description: Assignment Extension Management for Canvas +baseurl: /flextensions +url: https://berkeley-cdss.github.io + +# Build settings +markdown: kramdown +theme: jekyll-theme-primer + +# Exclude from processing +exclude: + - Gemfile + - Gemfile.lock + - README.md + - .jekyll-cache + - _site + +# Include the API docs (static HTML) +include: + - api + +# Default front matter +defaults: + - scope: + path: "" + values: + layout: default diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..853cf4ac --- /dev/null +++ b/docs/index.md @@ -0,0 +1,71 @@ +--- +title: Flextensions - Assignment Extension Management for Canvas +permalink: / +--- + + + +# Welcome to Flextensions 👋 [→][flextensions] + +[**Flextensions**][flextensions] is your one-stop solution to manage and access assignment extensions across all your UC Berkeley courses*. Whether you're course staff or a student, Flextensions streamlines extension workflows and makes extension data easy to access and manage. + +_* Well, all of your courses which use bCourses or Gradescope and enable assignment extensions. :)_ + +[flextensions]: https://flextensions.berkeley.edu + +--- + +## 🚀 What Does Flextensions Do? + +### [🧑‍🏫 For Course Staff](/flextensions/instructors/): +- View and manage extensions requests for all assignments in your course. +- Grant extensions to students with a few clicks. +- Monitor extension usage across your course. +- Automate approving extension requests and email sending +- Use as an [API](/docs/api/index.html) to integrate with your own tools and systems. + +### [🎓 For Students](/flextensions/students/): +- View all your granted extensions in one place. +- See how long your extension lasts and when the new due date is. +- Stay informed and organized without checking multiple systems. + +--- + +## 🔧 How It Works + +Flextensions connects directly with bCourses (Canvas) and imports your assignments. The interface is intuitive and role-based—course staff can grant and manage, while students can view. + +--- + +Are you a developer? Check out the [Developer Documentation](/flextensions/developers/) documention to contribute to Flextensions and the [API Reference](/flextensions/api/) to learn how to integrate Flextensions with your own applications. + +Want to know what's new? See the [Updates page](/flextensions/updates/) for recent changes or visit the [GitHub Releases](https://github.com/berkeley-cdss/flextensions/releases) for a full changelog. + +Interested in the research behind Flextensions? Check out the [Research page](/flextensions/research/). + +--- + +## Credits + +Flextensions is currently maintained by [Michael Ball][mball], [Continuing Lecturer in EECS][mb_eecs]. It has been developed by students in [CS169L](https://saasbook.info), during the Spring 2024, 2025 and 2026 semesters, as part of the [Software as a Service](https://saasbook.info) course at UC Berkeley. + +The Flextensions project has been generously supported by the [Research, Teaching, and Learning](https://teaching.berkeley.edu) and the [Office of the Vice Provost for Undergraduate Education](https://ue.berkeley.edu) at UC Berkeley through the [Seamless Learning Project](https://berkeley-cdss.github.io/seamless-learning/). + +Student developers (in alphabetical order): + +* Connor Bernard, Spring 2024 +* Cynthia Lixinyi, Spring 2024 +* [Diandian Liu](https://www.linkedin.com/in/diandian-liu/), Spring 2025 +* [Eric Huang](https://huanger2.github.io), Spring 2025 +* Evan Kandell, Spring 2024 +* Sepehr Behmanesh Fard, Spring 2024 +* [Tashrique Ahmed](https://tashrique.com), Spring 2025 +* [Tianye Meng](https://www.linkedin.com/in/tianye-meng-611b22253/), Spring 2025 +* [Yaman Tarakji](https://www.linkedin.com/in/yaman-tarakji-602530196), Spring 2025 +* Zee Babar, Spring 2024 + +Armando Fox, and Lisa Yan are faculty members who have also overseen the development of Flextensions and make significant contributions to the project. + +[mball]: https://mball.co/ +[mb_eecs]: https://www.eecs.berkeley.edu/Faculty/Homepages/mball.html diff --git a/docs/instructors.md b/docs/instructors.md index baf20db5..d5fb9e1d 100644 --- a/docs/instructors.md +++ b/docs/instructors.md @@ -28,7 +28,7 @@ On the **Courses** page, click a blue course name (e.g., **CS 161**, **CS 168**) ### Syncing Assignments -If you have added new assignments in Canvas, you can click **Sync Assignments** to import the latest assignments from Canvas into Flextensions. +If you have added new assignments in Canvas (or Gradescope, if configured), you can click **Sync Assignments** to import the latest assignments into Flextensions. ### Enabling Assignments @@ -83,7 +83,7 @@ The **Enrollments** tab shows all instructors and students currently associated The list will refresh with updated data, including new students and instructors, and will remove users no longer in the course. > [!NOTE] -> ⚠️ If if a student is added to the course after you have already imported a course, you will need to sync the course enrollments to ensure they are able to access the Flextensions course. +> ⚠️ If a student is added to the course after you have already imported a course, you will need to sync the course enrollments to ensure they are able to access the Flextensions course. ## Filtering Student Requests By clicking the name of a student in the **Enrollments** tab, you can filter the requests to only show those made by that student. This is useful for quickly reviewing all requests from a specific student. @@ -99,21 +99,21 @@ Control when and how requests are automatically approved: - **Auto-approve within days** Automatically approves requests made within the specified number of days before the assignment due date. Leave blank to disable. - +- **Auto-approve within days (Ex)** + Applies a similar rule specifically to students with a DSP accommodation flag. - **Maximum requests to auto-approve** Sets a per-student limit on auto-approved requests. Use `0` for no limit. After setting these options, click **Save Settings** to save. -### Extendate Late Due Date Automatically +### Extend Late Due Date Automatically _This setting is enabled by default._ When enabled, the late due date will be automatically extended by the same amount of time as the original extension when an extension is granted. This setting can be toggled on or off by instructors. -If you use "Slip Days" or otherwise accept late submissions you can enable this, so students who go beyond their extnded due date will have the option to submit late work until the late due date. +If you use "Slip Days" or otherwise accept late submissions you can enable this, so students who go beyond their extended due date will have the option to submit late work until the late due date. You may wish to disable this if you do not want students to have the option to submit late work, or if you set the late due date to a very distant date (e.g., end of semester) and do not want it to be extended further. @@ -198,13 +198,13 @@ Once configured, click **Update** at the bottom of the page to save your setting --- -## [Integration Guide](/integrations) +## [Integration Guide](/flextensions/integrations/) Flextensions supports integrations with: * Slack Webhooks * Google Sheets -* Gradescope (coming soon!) +* Gradescope --- diff --git a/docs/research.md b/docs/research.md new file mode 100644 index 00000000..527e5e1d --- /dev/null +++ b/docs/research.md @@ -0,0 +1,32 @@ +--- +title: Research +permalink: /research/ +--- + +# Research + +We publish research and experience reports on the use of Flextensions in the classroom. + +## Citation +If you use Flextensions in your research, please cite the tool itself using the following DOI: + +https://doi.org/10.5281/zenodo.17246291 + +``` +# IEEE +[1]M. Ball, “Flextensions”. Zenodo, Aug. 20, 2025. doi: 10.5281/zenodo.17246291. + +# APA +Ball, M., Fox, A., Yan, L., huanger2, Yaman Tarakji, Tashrique Ahmed, Connor, Jerry, Cynthia Xinyi Li, Tianye Meng, Peter Tran, Dana Kim, andypumpkineater, Evan Kandell, dg-ucb, Sepehr Behmanesh, felder, & Zee Babar. (2025). Flextensions. Zenodo. +https://doi.org/10.5281/zenodo.17246291 +``` + +## Publications + +**Automated Support for Flexible Extensions** + +Poster. Jordan Schwartz, Madison Bohannan, Jacob Yim, Yuerou Tang, Dana Benedicto, Charisse Liu, Armando Fox, Lisa Yan, and Narges Norouzi. 2024. Automated Support for Flexible Extensions. In Proceedings of the 55th ACM Technical Symposium on Computer Science Education V. 2 (SIGCSE 2024), March 20–23, 2024, Portland, OR, USA. ACM, New York, NY, USA, 2 pages. https://doi.org/10.1145/3626253.3635628 + +**Supporting Mastery Learning with Flexible Extensions** + +Poster. Yuerou Tang, Jacob Yim, Jordan Schwartz, Madison Bohannan, Dana Benedicto, Charisse Liu, Armando Fox, Lisa Yan, and Narges Norouzi. 2024. Supporting Mastery Learning with Flexible Extensions. In Proceedings of the 55th ACM Technical Symposium on Computer Science Education V. 2 (SIGCSE 2024), March 20–23, 2024, Portland, OR, USA. ACM, New York, NY, USA, 2 pages. https://doi.org/10.1145/3626253.3635615