feat: add 'caselaw' (פסיקה) kind alongside חוק/תקנות/חוזרים
Court rulings get their own kind so users can filter search results to "פסיקה" specifically and upload case-law PDFs from the ניהול tab. PHP validators in Controller + Service accept the new kind; the search dropdown and upload kind dropdown gain a "פסיקה" option; kindHe in index.js maps caselaw → "פסיקה" so jobs list, search results, and browse view all label it consistently. Backend: depends on shira-hermes commit 16eeeff (kind validators + chunker fallback) and migration 003_caselaw_kind.sql (already applied on dev — alters CHECK constraints on kb_source.kind and kb_ingest_job.kind to include 'caselaw'). Refs Task Master #18 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -36,6 +36,7 @@
|
||||
<option value="law">חוק</option>
|
||||
<option value="regulation">תקנות</option>
|
||||
<option value="circular">חוזרים</option>
|
||||
<option value="caselaw">פסיקה</option>
|
||||
</select>
|
||||
<button type="button" class="btn btn-primary" data-action="submit">חפש</button>
|
||||
<button type="button" class="btn btn-default" data-action="clearResults"
|
||||
@@ -88,6 +89,7 @@
|
||||
<option value="law">חוק</option>
|
||||
<option value="regulation">תקנות</option>
|
||||
<option value="circular">חוזר</option>
|
||||
<option value="caselaw">פסיקה</option>
|
||||
</select>
|
||||
</div>
|
||||
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;">
|
||||
|
||||
@@ -247,7 +247,7 @@ define('modules/knowledge-base/views/kb/index', ['view'], function (Dep) {
|
||||
done: '<span class="label label-success">הושלם</span>',
|
||||
failed: '<span class="label label-danger">נכשל</span>',
|
||||
};
|
||||
const kindHe = {law: 'חוק', regulation: 'תקנות', circular: 'חוזר'};
|
||||
const kindHe = {law: 'חוק', regulation: 'תקנות', circular: 'חוזר', caselaw: 'פסיקה'};
|
||||
const rows = items.map(j => {
|
||||
const when = j.completed_at || j.started_at || j.created_at || '';
|
||||
const whenShort = String(when).slice(0, 19).replace('T', ' ');
|
||||
@@ -813,7 +813,7 @@ define('modules/knowledge-base/views/kb/index', ['view'], function (Dep) {
|
||||
return;
|
||||
}
|
||||
const initialIdx = (typeof selectedIdx === 'number' && hits[selectedIdx]) ? selectedIdx : 0;
|
||||
const kindHe = {law: 'חוק', regulation: 'תקנה', circular: 'חוזר'};
|
||||
const kindHe = {law: 'חוק', regulation: 'תקנה', circular: 'חוזר', caselaw: 'פסיקה'};
|
||||
const self = this;
|
||||
|
||||
const isPdfBacked = h => h && (h.kind === 'regulation' || h.kind === 'circular');
|
||||
@@ -1112,7 +1112,7 @@ define('modules/knowledge-base/views/kb/index', ['view'], function (Dep) {
|
||||
answerHtml = '<div style="white-space:pre-wrap;">' + this.escape(text || '') + '</div>';
|
||||
}
|
||||
|
||||
const kindHe = {law: 'חוק', regulation: 'תקנה', circular: 'חוזר'};
|
||||
const kindHe = {law: 'חוק', regulation: 'תקנה', circular: 'חוזר', caselaw: 'פסיקה'};
|
||||
|
||||
// Dedup sources by source_id (first occurrence = most relevant),
|
||||
// but remember every page that came up per source so users can
|
||||
@@ -1252,8 +1252,8 @@ define('modules/knowledge-base/views/kb/index', ['view'], function (Dep) {
|
||||
$list.html('<div class="text-muted">אין מקורות.</div>');
|
||||
return;
|
||||
}
|
||||
const kindHe = {law: 'חוק', regulation: 'תקנות', circular: 'חוזרים'};
|
||||
const grouped = {law: [], regulation: [], circular: []};
|
||||
const kindHe = {law: 'חוק', regulation: 'תקנות', circular: 'חוזרים', caselaw: 'פסיקה'};
|
||||
const grouped = {law: [], regulation: [], circular: [], caselaw: []};
|
||||
this._sources.forEach(s => {
|
||||
if (grouped[s.kind]) grouped[s.kind].push(s);
|
||||
});
|
||||
|
||||
@@ -145,8 +145,8 @@ class KnowledgeBase
|
||||
// For multipart/form-data EspoCRM's getParsedBody() returns an empty
|
||||
// stdClass; the form fields land in $_POST as PHP parses them.
|
||||
$kind = $_POST['kind'] ?? null;
|
||||
if (!in_array($kind, ['law', 'regulation', 'circular'], true)) {
|
||||
throw new BadRequest('kind must be one of: law, regulation, circular.');
|
||||
if (!in_array($kind, ['law', 'regulation', 'circular', 'caselaw'], true)) {
|
||||
throw new BadRequest('kind must be one of: law, regulation, circular, caselaw.');
|
||||
}
|
||||
$topicId = $this->coerceTopicId($_POST['topicId'] ?? $_POST['topic_id'] ?? null);
|
||||
if ($topicId === null) {
|
||||
|
||||
@@ -37,7 +37,7 @@ class KnowledgeBaseService
|
||||
public function search(string $query, string $kind, int $topK, ?int $topicId = null): array
|
||||
{
|
||||
$topK = max(1, min(15, $topK));
|
||||
if (!in_array($kind, ['any', 'law', 'regulation', 'circular'], true)) {
|
||||
if (!in_array($kind, ['any', 'law', 'regulation', 'circular', 'caselaw'], true)) {
|
||||
$kind = 'any';
|
||||
}
|
||||
|
||||
@@ -88,8 +88,8 @@ class KnowledgeBaseService
|
||||
if (!is_readable($tmpPath)) {
|
||||
throw new Error('Uploaded file is not readable on disk.');
|
||||
}
|
||||
if (!in_array($kind, ['law', 'regulation', 'circular'], true)) {
|
||||
throw new BadRequest('kind must be one of: law, regulation, circular.');
|
||||
if (!in_array($kind, ['law', 'regulation', 'circular', 'caselaw'], true)) {
|
||||
throw new BadRequest('kind must be one of: law, regulation, circular, caselaw.');
|
||||
}
|
||||
|
||||
$url = $this->getBaseUrl() . '/admin/kb/upload';
|
||||
|
||||
Reference in New Issue
Block a user