Full job board for your community: categorized listings, salary ranges, remote/employment filters, an application pipeline with statuses and internal notes, saved jobs, admin approval workflow and expiry handling.
Release v2.0.0
joblistings_job, joblistings_application, joblistings_category (new schema)
plus new joblistings_application_status_log and joblistings_saved_job tables —
the old generic job / application table names collided with the rest of the
HumHub ecosystem and are gone.humhub\widgets\bootstrap\Button/Badge/Alert, humhub\widgets\form\ActiveForm,
humhub\widgets\modal\Modal) instead of raw HTML/Bootstrap 3 classes.data-bs-toggle="modal" attribute with no ajax loader wired up, so
nothing happened; others navigated to a full page instead of opening a modal
at all). Every modal view now uses Modal::beginFormDialog() /
Modal::beginDialog() with ModalButton, matching the rest of HumHub.humhub\widgets\GridView
class; both admin grids now use the standard yii\grid\GridView.registerCss() /
registerJs() calls) into assets/JoblistingsAsset.php, and the JS is now a
proper humhub.module('joblistings.main', ...) module instead of inline
jQuery snippets, registered automatically by the module's controllers/widgets.Job::submit() was previously only ever called automatically
during initial creation, and neither the job detail page nor the admin
listings grid exposed a way to publish, close or reopen a job based on its
actual current status. Added JobController::actionSubmit/actionClose/
actionReopen (available to the owner or any ManageJobs admin), contextual
Publish/Close/Reopen buttons on the job detail page and in "My job listings",
and the admin listings grid now shows the correct action for each job's
status (Publish for drafts, Approve/Reject for pending, Close for published,
Reopen for closed) instead of an unconditional "Close" button.joblistings.js crashed on load ("$ is not a function") because it
called require('jquery') — jQuery is loaded globally by HumHub on every
page and isn't a registered module id, so require() returned undefined.
The module now uses the global jQuery directly, which broke the save/
bookmark toggle and the applicant status dropdown entirely until fixed.joblistings.js was updated again to receive jQuery as the fourth
humhub.module() factory argument (the convention the loader actually uses)
instead of a global lookup, and now guards the save-toggle and status-select
handlers against duplicate in-flight requests while a POST is pending.views/job/_job_item.php) switched from raw Bootstrap .card
markup to HumHub's own .panel/.panel-heading/.panel-body structure, to
match how the rest of HumHub (and the rest of this module) is themed..filter-toggle-link + Bootstrap 5's native collapse, no custom JS),
auto-expanded if a filter is already active from the URL. Note: this mirrors
the People page's collapse behavior, not its DirectoryFilters widget
itself — that class's internals weren't available to build against safely.New: views/admin/_nav.php — a quick-link bar (Dashboard/Listings/
Categories/Settings) now shown at the top of every admin page, highlighting
the current section. Wraps on mobile instead of relying solely on the admin
sidebar. The dashboard's stat tiles are now a 2-up grid on phones (4-up from
md), and the pending-approval row's Approve/Reject buttons stack full-width
on narrow screens instead of overflowing.
Cleanup: removed nine unreferenced leftover view files from earlier drafts (views/admin/create.php, update.php, view.php, _form.php, _job_item.php, create-category.php, update-category.php; views/application/_form.php; widgets/views/_job_item.php) — none were wired to any controller action.
New: the admin quick-nav bar (Dashboard/Listings/Categories/Settings) now opens each section in a modal too, and switching sections from inside an open modal reloads the modal in place rather than leaving it. Note: pagination and status-filter links inside the listings/categories grids are still plain links and will navigate to the full page if clicked from within the modal — only the top-level section switch is modal-aware so far.
Fix: "Saved jobs" and "My applications" were dead ends — the only way back to the job board was the main site menu or the browser's back button. Added a shared quick-nav bar (views/job/_nav.php: Browse Jobs / My Job Listings / Saved Jobs / My Applications / Manage, each conditional on permission) to the job board, "My job listings", "Saved jobs", and "My applications" pages, so all four are reachable from one another directly.
Fix: opening an admin section (Dashboard/Listings/Categories/Settings) as a modal from the quick-nav bar also rendered that same quick-nav bar again inside the modal, which was redundant clutter since the modal title already identifies the section. AdminController::renderAdminView() now passes an $isModal flag into the view, and all four admin views skip the nav bar when it's set.
Fix: the job board search/filter form never actually filtered anything.
JobSearch::search() called $this->load($params, ''), which looks for
flat query keys like ?keyword=foo — but the ActiveForm fields in
job/index.php render with the model's real (unoverridden) form name, i.e.
?JobSearch[keyword]=foo. The two never matched, so every filter was
silently dropped and the page just showed all published jobs regardless of
what was typed or selected. Changed to $this->load($params) so it reads
the actual submitted shape.
Fix: the "new application" notification (sent to a job owner) threw
"Missing required parameters: id" whenever it tried to render its link.
JobNotification::getUrl() built the application/view URL with a job_id
param, but that action expects the application's own id — job_id was
never a recognized route parameter, so the required id was always missing.
Checked notifications/views/mails/applicationStatusChanged.php against
newApplication.php (it was created as a copy early on and never diverged).
The shared template body is fine as-is — it's a generic wrapper around
MailContentEntry, with the actual per-notification wording coming from each
notification class's own html()/getMailSubject(), not the view itself —
but its docblock still said $viewable was a JobNotification. Corrected to
ApplicationStatusNotification.
Fix: sending a notification email threw "Undefined variable $params" and
crashed the queue job (confirmed in production, not just local testing).
Both notifications/views/mails/*.php reference the Yii2 convention $_params_
(the raw params array a view received, normally auto-available for
forwarding into a nested layout) to open the shared mail layout, but
HumHub's notification mail renderer (ViewPathRenderer) extracts the
individual variables ($viewable, $url, $date, etc.) into scope without also
defining $params itself. This is inherited unchanged from the original
v1 module (confirmed byte-identical), not something introduced in the
rewrite. Replaced with get_defined_vars(), which captures the same
extracted variables generically without depending on that renderer-specific
variable existing. Also defensively null-coalesced $space in the same
call (undocumented in the file's own @var docblock, unlike every other
variable used, and Job/Application content isn't space-scoped) to head off
the same class of crash one line later.
Release v1.0.7 (8/3/2026)
Release v1.0.6 (7/31/2026)
Release v1.0.5 (2/27/2026)
actionWithdraw querying by job_id instead of application id, preventing withdrawals from ever succeedingactionView in ApplicationController using application_id as parameter instead of job_id, breaking the applications modal for job creatorshumhub\widgets\ModalDialog replaced with humhub\widgets\modal\Modal across all modal viewsyii\widgets\ActiveForm replaced with humhub\widgets\form\ActiveFormhumhub\libs\Html & yii\helpers\Html replaced with humhub\helpers\Htmldata-toggle and data-target attributes replaced with data-bs-toggle and data-bs-targetbtn-default replaced with btn-light, form-group replaced with mb-3, pull-right replaced with float-endRelease v1.0.4 (7/15/2025)
Release v1.0.3 (6/16/2025)
Release v1.0.2 (1/28/2025)
category not set to required causes null error.Release v1.0.1 (12/13/2024)
date() for widget returning errorRelease v1.0.0 (12/1/2024)