What's changed
Features (78)
-
asset: expose last_modified_by field for Asset (#5912)
Expose
last_modified_by
value in asset API endpoint responseExpose the
last_modified_by
field for Asset serializer.The field is
now available in the response for the following endpoints:-
/api/v2/assets/
-
/api/v2/organizations/<org_id>/assets/
-
/api/v2/project-views/<pv_uid>/assets/
-
-
attachment: create Celery tasks for attachment file deletion (#5662)
Introduced initial Celery task structure for handling attachment file
deletion.This PR adds tasks for asynchronous deletion of attachment files using
Celery -
attachments: create query file for removing attachments and a way to test it (#5577)
-
attachments: add a simple component for a deleted attachment (#5591)
Adds a text component to display when an attachment has been deleted
from a submission. -
attachments: add download and delete buttons (#5599)
-
attachments: handle deleted attachments in repeat groups (#5605)
In Data Table, for attachment related questions (e.g.
audio
) inside
repeat groups, it displays "Deleted" word instead of the response for
deleted attachments. -
attachments: add bulk deleting attachments using the row selector in table with mock api (#5626)
Adds a way to bulk delete attachments for submissions through the table
view bulk options. -
attachments: modal displays background audio in player and add remove attachment dropdown (#5673)
Now single submission modal will display background audio in audio
player. Background audio player also have dropdown menu to be downloaded
or deleted. -
attachments: make bulk delete attachments account for partial permissions (#5695)
Displays the correct number of attachments/submissions in the UI when
bulk deleting based on current user permissions. -
attachments: new endpoint to bulk delete specific attachments on an asset (#5666)
Add new endpoint which allows users to delete specific attachments on an
project.- Users can only make
DELETE
requests to this endpoint and must pass a
list of attachment uids as the payload - Users must have either partial or full
edit_submission
permissions
in order to delete attachments
- Users can only make
-
attachments: new endpoint to bulk delete all attachments from a submission (#5705)
Add new endpoint which allows users to delete all attachments from a
submission. -
attachments: update storage counters when attachments are moved to or from trash (#5686)
Ensure storage counters are updated when attachments are trashed or
restored in ongoing projects.This change improves storage accounting by updating
attachment_storage_bytes
on bothUserProfile
andXForm
when
attachments are soft-deleted or restored using
AttachmentTrash.toggle_statuses()
.- When an attachment is moved to the trash,
pre_delete_attachment(only_update_counters=True)
is invoked to
decrement storage usage. - When an attachment is restored,
post_save_attachment(created=True)
is used to restore the counters. - Logic is in place to prevent counters from being decremented twice if
the submission is deleted after the attachment has already been trashed.
- When an attachment is moved to the trash,
-
attachments: update admin model to support attachments in trash bin (#5738)
Improved the admin interface to support managing attachments in the
trash bin.Attachments that are moved to the trash can now be viewed and managed
directly from the admin panel. This includes the ability to permanently
delete attachments from the trash ("Empty trash") or restore them ("Put
back"). These actions update relevant storage counters and are logged in
the AuditLogs. This enhancement provides better visibility and control
over trashed attachments for admins. -
attachments: Add tests for
move_to_trash
andput_back
support forAttachmentTrash
(#5793)Added unit tests for attachment trash functionality, including
move_to_trash
,put_back
, and media file deletion behavior.Added unit tests to verify the behavior of
move_to_trash
and
put_back
for attachment objects. These tests confirm that:- Attachments are properly marked for deletion and storage counters
updated - Media files are deleted via the
empty_attachment
task while
retaining the DB record - Attachments can be restored and associated storage values are
recalculated - Task restart logic works correctly based on status and time thresholds
- Attachments are properly marked for deletion and storage counters
-
attachments: Update mongo documents to expose attachment deleted flag (#5788)
Added
is_deleted
flag to attachments in Mongo to reflect deletion
status after attachment trash or restore actions.This update ensures that the _attachments array stored in Mongo instance
documents accurately reflects the deletion status of each attachment.This change ensures that:
- Each attachment in the
_attachments
array now includes an
is_deleted
flag. - The flag is automatically updated when attachments are moved to trash
or restored. - This is implemented efficiently using Mongo
bulk_write()
operations.
- Each attachment in the
-
attachments: Update formpack export to handle deleted attachments (#5819)
Ensure KPI installs the latest formpack version to support new export
features for deleted media attachments.This PR updates the formpack dependency hash in
requirements.in
,
requirements.txt
, anddev_requirements.txt
to use the commit from
formpack#335. That
PR introduces support for displaying deleted attachments more clearly in
exports:- Replaces
{field}_URL
with the textDeleted
when the attachment is
marked as deleted andinclude_media_url=True
.
These changes ensure that exports generated by KPI reflect deleted
attachments more transparently for end users. - Replaces
-
attachments: Add Celery task to process users exceeding storage limit (#5909)
Adds a new celery task that identifies users who have exceeded their
storage limits for a configurable number of days and dispatches a
cleanup task for each. This prepares the foundation for automated
enforcement of storage quotas via attachment deletion.This PR introduces a Celery task
(schedule_auto_attachment_cleanup_for_users
) that:- Runs periodically via Celery Beat (every 30 mins, currently commented
out inCELERY_BEAT_SCHEDULE
) - Filters users from the
ExceededLimitCounter
model who have exceeded
their storage quota for more than
LIMIT_ATTACHMENT_REMOVAL_GRACE_PERIOD
days (default: 90) - For each qualifying user, dispatches a cleanup task
(auto_delete_excess_attachments(user_id)
), currently a placeholder.
Additional Constance settings added:
AUTO_DELETE_ATTACHMENTS
: Global toggle for enabling/disabling the
auto deletion (default: False)LIMIT_ATTACHMENT_REMOVAL_GRACE_PERIOD
: Grace period before
triggering cleanup for over-quota users
- Runs periodically via Celery Beat (every 30 mins, currently commented
-
attachments: Add celery task to auto delete excess attachments (#5938)
Adds auto_delete_excess_attachments task that soft-deletes a user’s
oldest attachments until their storage usage falls below the configured
limit. This completes the attachment cleanup workflow for users
exceeding their storage quotas.This PR adds the
auto_delete_excess_attachments(user_id)
Celery task,
which:- Checks if the user is exceeding their storage quota
- If so, iterates over the user's oldest attachments (
date_created
order) - Soft-deletes attachments using the existing
move_to_trash()
utility - Stops once the user is back within the allowed quota
-
billing: add xform pending_transfer flag () (#5685)
Adds a new
pending_transfer
field to the xform model and updates the
suspend_submissions()
method onOpenRosaDeploymentBackend
to update
this field instead of updating thesubmissions_suspended
flag on the
user model. -
billing: add exceeded limit counter (#5780)
Adds a new
ExceededLimitCounter
model for tracking how long a user has
been over their quota for a given usage type. -
billing: add usage balances to usage calculator (#5790)
Adds a
get_usage_balances()
method to the UsageCalculator that returns
a dict of the user's current usage balance relative to their usage
limits. -
billing: create useTrackingPeriod hook (#5817)
This PR:
- Adds the
useTrackingPeriod
hook - Replaces current uses of the
trackingPeriod
, previously from the
useUsage
hook the the new hook
- Adds the
-
billing: add balances to service usage api (#5808)
Adds a field 'balances' on the service usage endpoint that indicates
whether and by how much a user is over their usage limit for each usage
type. -
billing: ensure accurate usage limit reporting (#5860)
Adds a
check_limit_exceeded()
util to update ExceededLimitCounters
after submissions are submitted or nlp counters are updated. -
billing: Replace useUsage with useServiceUsageQuery (#5873)
This PR replaces the current
useUsage
by a react query implementation
inuseServiceUsage
hook.
All uses of the currentuseUsage
andusageContext
were removed and
replaced by the new hook. -
billing: block asr/mt actions when usage limit exceeded (#5872)
Blocks ASR/MT actions with a 402 payment required error if asset owner
has exceeded the relevant ASR/MT usage limit. -
billing: reset usage/limit data on subscription change (#5882)
Clears usage calculator cache and updates or remove counters as
necessary whenever a subscription is saved. -
billing: block submissions for users over usage limit (#5866)
Blocks submissions with a 402 payment required error if asset owner has
exceeded their submission or storage limit. -
billing: recurring task to update limit counters (#5933)
Adds a recurring task to check usage and update or remove exceeded limit
counters that are more than one day old and not modified in the past day
to ensure that counters remain up-to-date. -
billing: disable/enable usage limit enforcement on frontend (#6000)
Disable/enable NLP usage limit enforcement on the frontend depending on
backend USAGE_LIMIT_ENFORCEMENT configuration. -
billing: allow disabling limit enforcement (#5997)
Adds a constance config setting for toggling whether or not usage limits
should be enforced on stripe-enabled instances. Set to False by default. -
billing: disable/enable usage limit enforcement on frontend (#6039)
Disable/enable NLP usage limit enforcement on the frontend depending on
backend USAGE_LIMIT_ENFORCEMENT configuration. -
datatable: handle deleted audio attachment (#5619)
In forms data table, display deleted audiofiles as deleted. The button
for NLP is still there to access transcripts. -
datatable: handle deleted file attachment (#5620)
In forms data table, display deleted files as deleted. Hover on it to
see the original path. -
dataview: handle deleted attachments (#5622)
In forms data view, display deleted attachments as deleted. The button
for NLP is still there to access transcripts. -
disclaimers: disable override when disclaimers are hidden (#6092)
Disable the creation of an asset-specific disclaimer when the default
disclaimer is hidden.In Django admin, clarify that a user can either select 'Hide disclaimer
for all languages of the form' or create an overriding disclaimer (but
not both) by disabling the areas for creating an override when 'Hide
disclaimer for all languages' is checked. -
enketo: allow user media for preview iframe (#6093)
This PR adds the
allow
attribute to the form preview iframe to allow
the use of user media from thre preview.
Geolocation was also added, since there are geolocation widgets in
Enketo.- ℹ️ have an account and a project with an audio question
- Setup Enketo to work with KPI
(docs) - Pull the
feat-audio-recording
branch from Enketo - Open the form in the Preview (eye icon from the form view)
- Try to record audio
- 🟢 The microphone should be accessible by the form
-
exports: Add option to filter exports by date (#5934)
Adds the option to choose the export range in the UI. Helps with an
error that can occur on the backend because it was OOM.Users can select one or more dates, if only one date is selected it will
be treated as "greater than" or "less than" if it is the start or end
date respectfully. -
formLanding: General UI improvements of the deployed form history view (#5795)
Some UI improvements to help modernize the form version history view.
- Updating the "deployed" badge to match our other badges
- Left-align the date in the "Last modified" column instead of center
right aligned - Clone icons should sit under the clone header and not next to the date
when the form was last modified.
-
gallery: handle deleted attachments (#5611)
In gallery, display deleted attachments as deleted. Also, show the
filename on hover. -
longRunningMigrations: add system check to validate completion of critical long-running migrations (#5655)
Added a Django system check to ensure important long-running migrations
have completedThis PR introduces a Django system check that validates whether specific
long-running migrations—considered critical to data integrity or system
functionality—have been completed. If any of these migrations are still
running or incomplete, the system check will raise an error to prevent
the application from starting.This mechanism not only protects the system from running in an
inconsistent state, but also serves as a useful signal for sysadmins,
giving them immediate visibility into whether the database is fully
up-to-date. Instead of silently failing or relying on logs, this check
provides a clear and explicit message during startup, making it easier
to identify and act on pending background data migrations. -
massEmail: query for identifying inactive users based on login, form activity, and submissions (#5569)
Detect and return a list of users who have been inactive for a specified
period based on login activity, project updates, and submissions.This update introduces a method to identify inactive users who have not:
- Logged into their account.
- Modified their projects or had modifications made by others.
- Received submissions to their projects.
By default, the inactivity period is set to 365 days but can be
configured dynamically. -
massEmail: add celery task to mark old enqueued mass email record as failed (#5590)
Automatically marks old enqueued mass email records as failed if they
exceed a configurable expiry period.This PR introduces a Celery task that periodically scans
MassEmailRecord
entries with statusenqueued
and updates them to
failed
if they were created before the configured expiry threshold
(MASS_EMAIL_RECORD_EXPIRY_DAYS
). This ensures that stale email records
do not remain indefinitely enqueued. -
massEmail: add admin action to enqueue mass email records for scheduled sending (#5604)
Added an admin action to create mass email jobs and records, allowing
admins to enqueue emails for users based on predefined queries.Introduces an "Add to daily send queue" action in the Django admin for
MassEmailConfig
. When selected, it:- Checks if emails for the selected configuration are already enqueued
or being sent. If so, it notifies the user and exits. - If not, it creates a
MassEmailJob
and enqueues email records for
eligible users asynchronously via a Celery task. - Notifies the admin that emails have been successfully scheduled for
the next day.
This improves automation and ensures scheduled mass email dispatches run
efficiently. - Checks if emails for the selected configuration are already enqueued
-
massEmail: update mass email models (#5608)
Added support for scheduling mass emails with a configurable frequency
and introduced a constraint to prevent duplicate email records for the
same user in a given email job.- Added
frequency
(integer) andlive
(boolean) fields to
MassEmailConfig
to allow configuring email sending behavior. - Ensured
frequency
defaults to-1
andlive
defaults toFalse
. - These fields are not displayed in the admin panel.
- Enforced a uniqueness constraint on
(email_job, user)
in
MassEmailRecord
to prevent duplicate email records for the same user
in a given email job.
- Added
-
massEmail: create/register celery tasks mass emails (#5574)
Celery task and admin action to send emails for mass email
configurations asynchronously by user request on the admin screen.The mass email configs admin action "Send emails" triggers a celery task
for each email config that creates or uses an existing mass email job
that is associated to a set of mass email records. The records are
linked to a user, they start with enqueued status and when they are
processed by the celery task, their status is set to sent or failed.
This is work in progress, future PRs will enable more functionality. -
massEmails: query for users approaching submission limits (#5572)
Query for users who are approaching their maximum submission limit.
Create queries for users who are over 90% and 100%, respectively, of
their submission limit. These queries will be accessible by mass email
jobs. -
massEmails: Query for users reaching nlp usage limits (#5633)
Create the query for retrieving users who are >90% and >100% of their
nlp usage limits.The query returns a list of user uids. It will be used as part of a
MassEmailConfig. Emails that use that query will be sent to the list of
users generated by it. The usage calculated is the same as what is shown
on the Usage page. -
massEmails: create celery task for generating daily user lists (#5640)
Added a new task to generate and enqueue
MassEmailRecords
while
tracking processed configurations using caching.This update introduces a task that processes active MassEmailConfig
entries, gathering all configs withdate_created < today
and
live==True
, ensuring emails are only sent to eligible users based on
predefined rules. The task:- Caches processed email configs to avoid duplicate processing.
- If a cache object for today's emails doesn't already exist, it creates
a new cache object<todays_date>_emails
as an empty set, representing
emails for which today's user list has already been generated. - Skips configs with existing enqueued or sent records.
- Filters out users who have received the same email within the
configured frequency. - Handles duplicate entry errors to ensure robustness.
This prevents redundant emails and improves the reliability of the email
queuing system. -
massEmails: condense send interval on dev machines (#5657)
Adds a test setting that condenses the mass email send job to treat 15
minutes as a day and run every 5 minutes. Only for use on testing/dev
machines. -
massEmails: Celery task for sending emails (#5659)
Adds a new task to sync with the recurring emails feature. For now this
task is not enabled but it will replace the old task in the near future. -
massEmails: add 80% queries (#5743)
Adds new queries for mass emails for finding users who are between 80%
and 90% of their storage and submission limits. -
massEmails: add test query (#5779)
Add the ability to email a Constance-defined selection of users for
easier testing of mass emails. -
massEmails: prioritize recurring sends over one-time (#5760)
Allocates send capacity to recurring emails first, then allocates
whatever is left to the one-time emails.Previously, send capacity was allotted to each email E by calculating (#
of enqueued E records/total enqueued records)*total send capacity. In
order to ensure recurring emails go out regardless of any large one-time
sends that may be pending, we are dividing emails into "one-time" and
"recurring" categories. For a recurring email R, the send capacity is
now (# of enqueued R records/total enqueued recurring records)*total
send capacity. After the send capacity for each recurring email is
calculated, any remaining capacity is allocated among the one-time sends
using the same calculation. -
massEmails: enable recurring sends (#5796)
Turn on new process for recurring mass emails.
Allows the creation of regularly recurring emails for certain
conditions. Instead of just creating email configs and sending them the
next day with 'Add to daily send,' superusers specify a frequency for
how often a given individual should receive the email. One time sends
are still possible with a frequency of -1. Once a recurring email is
added to the daily send, beginning the next day, users matching the
query will be calculated every day and emails sent, filtering out those
who received the same email too recently. -
massEmails: adapt timeouts for condensed send mode (#5821)
Lower the timeouts for mass email sends when in test mode.
-
massEmails: allow multiple sends of one-time emails (#5831)
Allow one-off emails to be resent if they have completely finished
sending. -
massEmails: preview query results (#5841)
Allow users to download a list of expected recipients of a mass email
based on the query used.Creates ExportJobs for MassEmailConfigs that will have details about the
expected recipients for the emails. Once requested, the user will
receive an email when the job is done and be able to download the list
from Django admin. -
massEmails: download a CSV of recipients from the last 30 days (#5843)
Allow superusers to download a report of recipients of all emails for
the past 30 days. -
nlp: handle deleted audiofile (#5612)
In NLP, display deleted audiofiles as deleted.
-
nlp: disable ASR for deleted attachment (#5629)
Creating automated transcript or translation is no longer possible after
attachment is deleted. -
nlp: processing view button conditional rendering (#5631)
Hide "Open" button in Data Table for
audio
question responses that now
have deleted attachment and no NLP features in use. -
permissions: use
delete-all
permissions endpoint on frontend (#5543)The "Remove shared project" button and the "Delete" button in the
sharing modal were not fully removing users' access, so they have been
updated to completely remove all their permissions and ensure they are
fully removed from the project. -
projectHistoryLogs: add project owner to submission logs (#5645)
Add asset owner to project history logs for submission-related actions.
-
projectHistoryLogs: add owner to deployment logs (#5647)
Add the project owner to all project history logs dealing with
deployment/archiving. -
projectHistoryLogs: add owner to permission logs (#5699)
Add project owner to project history logs that record changes to project
permissions. -
projectHistoryLogs: add project owner to related viewsets (#5706)
Add project owner to project history logs for adding/removing media,
exporting data, importing fields from other projects, and modifying REST
services. -
projectHistoryLogs: add owner to import and export logs (#5710)
Add project owner to the project history logs for importing new forms
and using the old export endpoint. -
projectHistoryLogs: change code to codename for partial perms (#5715)
Change the key from 'code' to 'codename' for consistency when creating
PH logs for partial permission changes. -
projectHistoryLogs: add project owner to remaining logs (#5804)
Add project owner to transfer, QA data update, name change, and settings
update project history logs. -
projectViews: handle last edited column in UI (#6094)
New column "Last edited" that displays username of user that has last
edited given project. It will appear by default for My Projects, Custom
Project Views, and My Org Projects View, allowing filtering and ordering
by it. -
releases: auto-generate changelog with git-cliff (eee3b36)
-
removingAttachments: use API instead of mocks (#5765)
Remove mock code that was operating single attachment deletion button
and bulk attachment deletion modal. Use ready APIs instead. -
trashBin: add object owner filters to
ProjectTrash
andAttachmentTrash
admin views (#5884)Admins can now filter trashed projects and attachments by the object
owner, making it easier to locate and manage soft-deleted content.This update improves the admin interface for the trash bin by adding
filters for project and attachment owners. When viewing trashed projects
or attachments, admins can now narrow down the list based on the user
who originally owned them.
This enhancement improves usability, especially on instances with large
volumes of deleted items, by making it faster and easier to find
relevant records. -
usageLimits: Replace useExceedingLimits (#5921)
This PR
- Includes usage information in
useServiceUsage
hook - Removes the
useExceedingLimits
hook and replaces its current usage
byuseServiceUsage
's new information.
- Includes usage information in
-
usageLimits: handle project ownership transfer limits (#5931)
This PR blocks the transfer project ownership button if either
submission
orstorage
limits are exceeded. -
usageLimits: Add limit banners to new pages (#5937)
This PR adds the service limits banner to the following views:
- Project summary
- Project form
- Project data
- Project settings (’general’ sub-section)
-
user: include uid in /me endpoint (#5922)
Add user uid to the current user endpoint.
Bug Fixes (62)
-
accessLogs: button spacing (#5609)
-
accountSettings: ensure correct help article URL for non-KoboToolbox instances (#5969)
The "Learn more about these changes here" link in account settings is
broken on KoboToolbox instances using a custom support URL -
activityLogs: export button correctly passes no payload (#6045)
-
attachment: avoid blocking migration (#6133)
Use
SKIP_HEAVY_MIGRATIONS
flag to alterlogger_attachment
table to
dropNULL
on specific fields -
attachmentStorage: fix UserProfile storage counter to exclude soft-deleted XForms (#5687)
Updates the management command to ensure that deleted projects (forms in
the trash) are no longer counted toward the user profile's attachment
storage usage.Previously, when a user soft-deleted a project, the media files
associated with that form continued to be included in the UserProfile's
attachment_storage_bytes
counter, which is used to track total storage
usage per account. This led to inconsistencies between the backend
storage counter and what users saw in the/service_usage/
page, which
already excluded deleted forms.This fix updates the
update_attachment_storage_bytes
management
command to exclude soft-deleted forms (pending_delete=True
) from the
total storage calculation at the user profile level. Individual XForm
storage totals are still updated, even for trashed forms, so they remain
accurate if restored. -
attachments: display attachment dropdown additionally to media in single submission modal (#5672)
Fixes bug where attachment dropdown did not display beside their
respective attachments. -
attachments: fix import order (#5694)
-
attachments: fix user profile counter bug on attachment deletion after project transfer (#5756)
Fixes a bug where storage counter on
UserProfile
was not updated
correctly when deleting or restoring attachments after transferring a
project to a new owner.There was a bug affecting attachment storage usage tracking: when a
project was transferred to a new owner, the storage counter on the new
owner'sUserProfile
object was not updated correctly if attachments
were later trashed or restored.This PR updates the attachment trash logic to ensure that ownership is
correctly reassigned before applying any storage counter updates. It
also adds a unit test to verify the correctness of counter updates
during transfer, trash, and restore operations. -
attachments: hide the "Delete media files only" button from any permission except
change_submissions
or higher (#5838)Those with
delete_submissions
permission for submissions now cannot
see the "Delete media files only" button in the bulk options and those
withchange_submissions
permission are now able to see the button. -
attachments: fix attachment deletion for edited submissions (#5844)
Fixes an issue where attachments could not be deleted from edited
submissions due to incorrect handling of submission UUIDs.This fix updates the attachment deletion logic to correctly filter using
root_uuid
for edited submissions. Previously, the API returned a 400
error when edited submissions were included, treating their root UUIDs
as invalid. The updated query ensures attachments from both original and
edited submissions can be deleted successfully. -
attachments: clear usage cache and remove limit counter after attachment cleanup (#6139)
Ensure users are unblocked immediately after excess attachments are
auto-deleted by clearing cached usage and removing the storage limit
counter right away.Previously, when celery task automatically deleted older attachments for
users exceeding their storage quota, the system did not immediately
clear the usage cache or remove the storage limit counter. As a result,
users could remain blocked for up to 15 minutes (due to caching) or
appear over quota until the next daily counter update.With this fix, the
auto_delete_excess_attachments
task now clears the
user’s usage cache and updates or removes the storage limit counter
immediately after cleanup, ensuring quota status reflects the changes
right away. -
avatar: avoid initials shrinking (#5621)
In some cases avatar initials were shrinking, causing them to not be a
circle anymore. -
billing: fix missing interval dropdown for "File Storage" add-on in some languages (#5797)
Fixes the issue where if Kobo is in some non-english languages, the time
interval dropdown for choosing month/year doesn't appear. -
exports: display export language labels instead of code (#6116)
Fixes issue where the default "language" is being shown as
_default
rather than the dropdown label "Labels". Now we always display the label
and fall back to the language code if this somehow fails. -
formBuilder: Question Matrix settings crash (#5646)
Opening settings for Question Matrix is possible again.
-
formatting: biome formatting (#5968)
Fixing an error in formatting that somehow got through the process
-
formbuilder: Improve accuracy in language for validation & skip logic description (#5919)
Changed the wording of
- "Previous responses should match all of these conditions"
- "Previous responses should match any of these conditions"
in the validation criteria and skip logic dropdowns to:
- All of these conditions must be met
- At least one of these conditions must be met
For improved context and accuracy to the actual logic
-
formbuilder: remove double prompt when existing formbuilder with changes (#5800)
Formbuilder only uses one method of warning user when leaving with
changes made. -
frontend: unable to access "Data" and "Settings" pages (#5571)
-
frontend: use kobo default line-height again (#5602)
Revert broken default line-height for various elements.
-
frontend: don't install playwright in dockerfile (#5776)
Reverse an accidental increase in docker file by 1.5GB.
-
frontend: printing styles (#5879)
Fix issues with styles while printing.
Now all Project related routes should be printable without data being
cropped out. The only issue still prevaling is printing horizontally
huge tables from Project → Data. In such case it is advised to change
the amount of columns being displayed before printing and using
landscape orientation of paper. -
frontend: type error in useServiceUsageQuery.ts (#6081)
-
kpi: Support geo+json mime type for form media (#5601)
Support geojson mime type
-
languageSelector: force refresh languages list after clearing the searchbox (#5681)
-
longRunningMigration: do not block fresh installs with system checks (#5772)
Prevented system checks from raising errors on fresh installs when
long-running migrations haven't been executed.System checks for long-running migrations were incorrectly raising
errors even on fresh installs, where no data exists and migrations are
not required. This caused unnecessary blocking during setup or
deployment of a new environment. -
massEmails: Use default plan name in templates (#5628)
Use the default plan name provided by the stripe product model in the
mas emails templates. A new utility function was added to the stripe app
in order to provide this name easily. -
massEmails: only import product if stripe enabled (#5632)
Fix a build failure that occurs when Stripe isn't enabled.
-
massEmails: fix plan name (#5639)
Use the correct plan name in mass emails.
-
massEmails: throttle mass email send (#5641)
Limit the rate of emails sent per second to avoid hitting SES limits.
-
massEmails: handle organizations with no owners (#5656)
Fixes an error that was causing 500s when attempting to trigger mass
emails with usage queries.Removes organizations with no owner when determining which organizations
may be over their limits since there is no one to email. -
massEmails: read MASS_EMAIL_CONDENSE_SEND from env (#5691)
-
massEmails: handle orgs with no owner (#5725)
Fix a 500 error that occurs when attempting to add a usage-dependent
email to the daily send. -
massEmails: fix 500 from usage queries (#5740)
Fixes a 500 error when trying to add usage-query-dependent emails to the
daily send. -
massEmails: make get_plan_name ordering more deterministic (#5811)
Ensure
get_plan_name()
util function returns plans before addons. -
massEmails: no error on empty test user list (#5830)
Do not attempt to send emails when the test email configuration is
empty.Fixes an error wherein if the
MASS_EMAIL_TEST_EMAILS
configuration in
Constance was empty, any email using thetest_users
query would throw
errors, which could kill the whole process and prevent other emails from
sending. -
massEmails: make sure sends are not interrupted when configs change (#5810)
Ensure emails continue to be sent throughout the day even when
configurations are changed before the send is over.Fixes a bug wherein if sending all mass emails took more than an hour
(either because of volume or because the process was killed) and new
configurations were added before all emails had been sent, emails would
stop sending for the rest of the day. The same thing would happen if an
existing configuration was removed from the daily send list. -
massEmails: convert dates to strings for xslx (#5847)
Fix exporting mass email records to XSLX format.
-
massEmails: rename export action (#5849)
Rename the export action from 'Export with celery' to 'Export recipient
list' for clarity -
nlp: handle old qpaths that point at deleted questions (#5754)
Allow users to access their project data even when older analysis
features refer to questions that have since been removed from the
project. -
organizations: skip stripe-related tests in no-stripe testing (#5732)
Uses
pytest.mark.skipif
to skip stripe-related MMO tests when testing
without Stripe. -
permissions: hide
discover_asset
in the UI (#5737) -
permissions: sharing modal correctly reflects asset type in permissions labels (#5736)
Fixes a bug where the sharing modals will always display "form" or
"project" regardless of asset type. Now the modal correctly references
the asset being shared. -
permissions: make sharing form request permissions upon opening (#5785)
Fixes issue where wharing modal did not update permissions until a hard
refresh. -
permissions: uncheckable permission checkboxes (#5798)
After selecting "Manage collection" permission in Library's Sharing
Form, User can unselect all checkboxes (one at a time) beck into initial
empty state. -
permissions: update team members row with changes from sharing modal (#5791)
When making changes to a project's permissions, if a user is added or
removed it will reflect immidately in the "Team members" component in
the "Summary" page. -
permissions: improve UI in Sharing Form (#6056)
Fix minor issue of "Act on submissions only from specific users (…)" not
mentioning all the users from permissions. -
projectHistoryLogs: remove query count checks from tests (#5674)
-
projects: "fields" selector uses same default display list as my projects route (#5801)
Fixes issue where the "fields" selector would show "Countries" checked
but the columns don't display it. Now the "fields" selector leaves
"Countries" unchecked by default (to match the columns). -
removingAttachments: add missing trailing slash in attachment bulk url (#5842)
-
removingAttachments: don't disable automatic translation button (#5858)
Don't disable automatic translation for deleted attachments.
-
storybook: handle the new '#' path alias (#5583)
-
storybook: make dates consistent in UniversalTable tests (#5789)
-
stripe: only import Product when stripe is enabled (#5579)
Return all limits as infinite when Stripe is not enabled.
Fixes a bug that was preventing kpi from starting up when Stripe was not
enabled. -
stripe: annotate methods requiring stripe functionality (#5649)
Fixes a bug that was preventing startup when stripe was disabled.
-
submissions: prevent the management command to crash when fixing
rootUuid
conflicts (#5971)Fixes a crash in the
clean_duplicated_submissions_root_uuid
command
when processing submissions without ameta/rootUuid
.This PR resolves an issue where the
clean_duplicated_submissions_root_uuid
management command would crash
if it encountered a submission that had never been edited and whose XML
lacked ameta/rootUuid
node. -
tests: Use
reverse()
instead of hardcoded url in unit tests (#5822)Replaced hardcoded URL in unit test with
reverse()
to ensure better
maintainability and consistency with URL routing.This change updates a test case to use Django's
reverse()
function
instead of hardcoding the API URL. -
linter (3456eb7)
-
fix merge conflicts (4adfd1e)
-
(reports): Fix infinite reloading failed report (#5755)
This PR fixes a bug where under a certain condition loading a report
containing a Group By configured fails and the app tries to reload it
infinitely. -
fix previous bad merge (8423be8)
Performance (1)
- attachments: Improve bulk update attachments storage counters (#5835)
Improved performance of storage counter updates when bulk trashing or
restoring attachments and projects.- Refactors the logic for updating attachment storage counters on user
profiles and xforms during bulk trash or restore operations. - With this PR, when a XForm is trashed or restored, only the
UserProfile
storage counter will be updated. The XForm’s storage value
remains unchanged because trashed forms are excluded from queries and
considered deleted along with their attachments.
- Refactors the logic for updating attachment storage counters on user
Continous Integration (47)
-
backend: run biome for static files too (#6084)
-
biome: fix filter syntax (#6114)
-
chromatic: run tests daily (#5781)
Once a day run Chromatic visual tests to verify we don't have unwanted
changes. -
chromatic: fix failing nightly builds (#5846)
-
dependabot: run nighly with automerge (#5929)
Make dependabot create daily bulk PRs with npm and github-actions
dependencies updates. PRs for patch and minor versions will get
auto-merged after successful tests. -
dependabot: automerge using squash (#5947)
-
dependabot: fix permissions issues for major update review request (#5957)
-
dependabot: disable automerging PRs (#5960)
-
dependabot: drop major version handling and only log automerge (#6002)
-
dependabot: drop dependabot prs limit (#6007)
-
dependabot: dependabot workflow typo fix (#6009)
-
dependabot: auto merge successful minor and patch deps prs (#6010)
-
dependabot: change dependabot PR limit for github-actions (#6011)
-
dependabot: make it group all types of minor/patch updates (#6022)
-
dependabot: fix duplicated wrong file (#6125)
-
frontend: build storybook (#5584)
-
frontend: skip storybook until fixing flaky tests (#6113)
-
gitlab: fix storybook deployment (#5786)
-
gitlab: update node version for Storybook deployment (#5787)
-
pr: remove forgotten debug (#5900)
-
pr: remove forgotten debug (#5900)
-
pr: typo in filters (#6046)
-
releases: use ISO week number (#5898)
-
releases: typo at secrets prop (#5906)
-
releases: typo at secrets prop (#5906)
-
releases: fix bash syntax typo (#5910)
-
releases: fix deploy to beta (#5911)
-
releases: auto-merge release branches (#5908)
-
releases: fix script execution perms (#5923)
-
releases: fix github action typo (#5924)
-
releases: use Github App for cascading merges (#5973)
-
releases: use Github App (#5979)
-
releases: delete previous unreleased branch (#5974)
-
releases: fix debugging leftovers (#5989)
-
releases: fix missing env variables (#6005)
-
releases: simplify and improve !failure() ifs (#6054)
-
storybook: install playwright and run tests (#5723)
Run Storybook tests on CI
-
format github action alert title (#5594)
-
run ci steps locally (#5593)
-
pytest with stripe disabled (#5650)
-
upgrade to ubuntu-24.04 for all jobs (#5881)
-
extract a reusable zulip workflow (#5890)
-
semi-automatic continuous bi-weekly releases (#5877)
-
use ISO week number everywhere (#5899)
-
use ISO week number everywhere (#5899)
-
update job filters (#5894)
-
share playwright cache across branches (#5895)
Build & Dependencies (3)
Testing (8)
-
backend: Add
deployment__uuid
to asset API (246a8ab) -
projectHistory: FormActivity stories (#5720)
-
projectHistoryLogs: check for project owner on submission logs (#5698)
-
projectHistoryLogs: backfill some unit tests (#5803)
-
storybook: ActionIcon click (#5669)
-
storybook: languageSelector search (#5670)
Add Storybook test to verify that searching LanguageSelector works
correctly. -
storybook: enable a11y tests (#5734)
Run a11y tests on CI
-
add query-counting tests to critical endpoints (#5696)
Security (26)
- deps: bump mobx-react from 7.6.0 to 9.2.0 (#5949)
- deps: bump react-textarea-autosize from 8.5.6 to 8.5.9 (#5952)
- deps: bump @tanstack/react-query from 5.50.1 to 5.83.0 (#5953)
- deps: bump backbone from 1.6.0 to 1.6.1 (#6021)
- deps: bump react-select from 5.8.0 to 5.10.2 (#6078)
- deps-dev: bump webpack-dev-middleware from 6.1.3 to 7.4.2 (#5950)
- deps-dev: bump @storybook/addon-docs from 9.0.0-beta.11 to 9.0.17 (#5951)
- deps-dev: bump webpack-cli from 5.1.4 to 6.0.1 (#5942)
- deps-dev: bump jest-environment-jsdom from 29.7.0 to 30.0.5 (#5954)
- deps-dev: bump @storybook/react-webpack5 from 9.0.0-beta.11 to 9.0.18 (#5972)
- deps-dev: bump fork-ts-checker-webpack-plugin from 9.0.2 to 9.1.0 (#5956)
- deps-dev: bump eslint-plugin-storybook from 9.0.0-beta.11 to 9.0.18 (#6013)
- deps-dev: bump cheerio from 1.0.0 to 1.1.2 (#6012)
- deps-dev: bump concurrently from 9.1.2 to 9.2.0 (#6015)
- deps-dev: bump @types/jquery from 3.5.30 to 3.5.32 (#6019)
- deps-dev: bump eslint-plugin-import from 2.31.0 to 2.32.0 (#6020)
- deps-dev: bump @types/leaflet from 1.9.16 to 1.9.20 (#6025)
- deps-dev: bump brace-expansion from 1.1.11 to 1.1.12 (#6063)
- deps-dev: bump @storybook/test-runner from 0.23.0-next.2 to 0.24.0-next.1 (#6070)
- deps-dev: bump typescript-plugin-css-modules from 5.1.0 to 5.2.0 (#6071)
- deps-dev: bump @testing-library/react from 16.0.1 to 16.3.0 (#6072)
- deps-dev: bump @vusion/webfonts-generator from 0.7.3 to 0.8.0 (#6075)
- deps-dev: bump msw from 2.7.3 to 2.10.4 (#6076)
- deps-dev: bump @testing-library/jest-dom from 6.5.0 to 6.6.4 (#6074)
- deps-dev: bump @faker-js/faker from 9.8.0 to 9.9.0 (#6079)
- deps-dev: bump eslint-plugin-react from 7.37.3 to 7.37.5 (#6086)
Refactor (40)
-
UniversalTable: use hardcoded mock data in stories (#5782)
-
attachments: simplify using arrow functions (#5597)
-
attachments: make Attachment inherit from
AbstractTimeStampedModel
(#5614) -
attachments: enforce non-nullable uid on Attachment model (#5615)
-
attachments: eliminate null values in the Attachment model , 1681 (#5636)
Disallow null or blank values for new Attachment model fields.
-
attachments: expose uid instead of pk in the data API endpoint (#5642)
-
attachments: match FE to the updated response for submission attachments (#5671)
-
attachments: bulk and single attachment deletion endpoints (#5733)
-
attachments: use DRF-compliant error format for field-specific validation (#5829)
Standardizes error responses to return a list of field-specific
validation errors using DRF format.This PR refactors the bulk deletion attachment validation logic to
comply with Django REST Framework’s error response format.Instead of returning a generic error or a flat structure, the API now
returns a dictionary where each field maps to a list of corresponding
error messages. -
billing: remove unused UpdateBadge component (#5586)
Removes UpdateBadge component file, as it is unused and the necessary UI
is already implemented. -
billing: standardize usage naming (#5748)
Switches to standardized choices for referring to usage types in backend
code. -
billing: add organization service usage tests (#5806)
Adds backend unit tests for the organization service usage endpoint.
-
billing: split stripe utils into several files (#5848)
Refactors stripe utils to reduce file size and risk of circular
dependencies. -
coffeeScript: fix DS0002 in mv.skipLogicHelpers.coffee (#5982)
-
coffeeScript: fix DS0002 in view.row.coffee (#5983)
-
coffeeScript: fix DS0002 in view.widgets.coffee (#5984)
-
coffeeScript: fix DS0002 in view.surveyApp.coffee (#5985)
-
coffeeScript: fix DS0002 in model.surveyFragment.coffee (#5986)
-
coffeeScript: fix DS0002 in view.rowDetail.SkipLogic.coffee (#5987)
-
coffeeScript: fix DS0002 in model.rowDetails.skipLogic.coffee (#5988)
-
formbuilder: bulk-decaffeinate on single file (#5897)
Part of the decaffeination process of the formbuilder. This is the "base
case" of converting a single file from.coffee
to.js
. -
formbuilder: remove implicit returns for
model.row.coffee
(#6036)Fixes DS102 from decaffeinate process
-
formbuilder: remove implicit returns in some coffeescript files (#6103)
Part of the decaffeination process. Removes implicit returns in many
coffeescript files for easier conversion. -
frontend: rename FormActivity files (#5702)
-
frontend: query client mock decorator (#5713)
-
frontend: update endpoints list file (#5714)
-
frontend: move endpoints mocks to new directory (#5719)
-
frontend: consistent mock files naming (#5792)
-
map: TypeScriptize Project Data Map files (#5558)
-
massEmails: refactor usage queries to make nlp easier (#5610)
Developer-only changes.
-
removingAttachments: better success and error handling in bulkDeleteAttachments (#5825)
-
select: replace and remove KoboSelect3 (#5679)
-
storybook: migrate to v8 and update obsolete stories (#5567)
-
storybook: reorganize stories (#5661)
-
storybook: migrate button tests (#5676)
-
submissionUtils: migrate code to TypeScript (#5652)
-
submissionUtils: type improvements (#5654)
-
trashBin: standardize status toggling via abstract base method (#5635)
Refactored
toggle_<model>_statuses
into an abstract method on the base
trash bin class and prepares the codebase for managing attachments in
the trash bin in future work.As part of upcoming work to support attachments in the trash bin system,
thetoggle_<model>_statuses
method has been moved to the base class as
an abstract method. This change standardizes the implementation pattern
for all models handled by the trash bin system. -
trashBin: group tasks by object type for better organization (#5660)
Split trash bin tasks into separate files based on the object they
operate on.Previously, all trash bin–related tasks were located in a single
tasks.py file, regardless of the object type (e.g., projects, accounts).
This refactor organizes tasks by grouping them into separate files
according to the object they manage.This restructuring sets the stage for integrating attachment-related
tasks cleanly and consistently. -
trashBin: unify status toggling inside
move_to_trash()
andput_back()
for all trash models (#5747)Simplified the trash process for attachments, projects, and users by
consolidating the status toggle into a single step.Previously, moving items (attachments, projects, or user accounts) to
the trash required calling bothtoggle_statuses()
and
move_to_trash()
separately. This update refactorsmove_to_trash()
to
internally handle the status change, unifying the logic across all trash
models.
Styling (4)
Chores (27)
-
cypress: remove code (#5735)
Remove cypress related code, as we are replacing it with storybook
tests. -
deps: bump the minor-and-patch group with 4 updates (#5948)
-
deps: bump the actions-deps group across 1 directory with 4 updates (#6003)
-
deps: bump http-proxy-middleware from 2.0.6 to 2.0.9 (#5680)
-
deps: update @sentry/react and minimum node version (#6030)
-
deps: bum react-cookie from 4.0.1 to 8.0.1 (#6065)
-
deps: bump pretty-bytes from 6.1.1 to 7.0.0 (#6024)
-
deps: bump patch-package from 6.5.1 to 8.0.0 (#6066)
-
deps: update dependabot ignore list (#6068)
-
deps: update autogenerated mockServiceWorker file (#6117)
-
deps-dev: bump webpack-cli from 5.1.4 to 6.0.1 (#6014)
-
deps-dev: bump @jest/create-cache-key-function from 29.7.0 to 30.0.5 (#6018)
-
deps-dev: bump @tanstack/react-query-devtools from 5.50.1 to 5.84.1 (#6073)
-
envStore: remove unused TS interface props (#5682)
-
frontend: remove unused getSubmissionsQuery function (#5603)
-
frontend: put back removed storybook script (#5638)
-
frontend: .git-blame-ignore-revs for Biome (#5764)
-
frontend: change package.json versions to use carets for all deps (#6061)
-
frontend: bump webpack-dev-server to 5.2.2 (#6062)
-
frontend: delete unused source-map-loader (#6064)
-
release: manually trigger deployment to staging (b154791)
-
removingAttachments: remove feature flag (#5824)
-
updateHelmRepo: Updating helm repo to use ghcr (#5853)
-
vscode: exclude compiled js from search (#5648)
-
improve long running migrations system checks message (#5665)
Enhanced the clarity and usefulness of system check messages for
long-running migrations.This update improves the system check messages related to long-running
migrations, making them more descriptive and actionable. The goal is to
help developers and sysadmins quickly understand which migrations are
incomplete and what steps may be required to resolve them. -
install playwright deps within ci_locally.sh (#5799)
-
update PR template (#5834)
Revert (7)
- revert "chore(deps-dev): bump webpack-cli from 5.1.4 to 6.0.1" (#5961)
- revert "chore(deps): bump mobx-react from 7.6.0 to 9.2.0" (#5962)
- revert "chore(deps-dev): bump jest-environment-jsdom from 29.7.0 to 30.0.5" (#5963)
- revert "chore(deps-dev): bump webpack-dev-middleware from 6.1.3 to 7.4.2" (#5964)
- revert "chore(deps): bump @tanstack/react-query from 5.50.1 to 5.83.0" (#5966)
- revert "test(backend): Add
deployment__uuid
to asset API" (e78ce0b) - revert "feat(billing): disable/enable usage limit enforcement on frontend " (#6038)
Other (6)
Full Changelog: https://github.com/kobotoolbox/kpi/compare/2.025.29c..2.025.34