Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/dependabot.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ updates:
- package-ecosystem: bundler
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
interval: weekly
open-pull-requests-limit: 5
66 changes: 66 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions app/controllers/session_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion app/controllers/user_to_courses_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
15 changes: 15 additions & 0 deletions docs/Gemfile
Original file line number Diff line number Diff line change
@@ -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
75 changes: 26 additions & 49 deletions docs/README.md
Original file line number Diff line number Diff line change
@@ -1,65 +1,42 @@
---
title: Flextensions - Assignment Extension Management for Canvas
permalink: /
---

<!-- NOTE to Authors: all absolute URLs should start with /flextensions/
-->
# 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/`.
27 changes: 27 additions & 0 deletions docs/_config.yml
Original file line number Diff line number Diff line change
@@ -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
71 changes: 71 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
title: Flextensions - Assignment Extension Management for Canvas
permalink: /
---

<!-- NOTE to Authors: all absolute URLs should start with /flextensions/
-->

# 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
16 changes: 8 additions & 8 deletions docs/instructors.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
Expand All @@ -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 (DSP)**
Applies a similar rule specifically to students with a DSP accommodation flag. -->
- **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.

Expand Down Expand Up @@ -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

---

Expand Down
Loading
Loading