367 lines
9.4 KiB
Svelte
367 lines
9.4 KiB
Svelte
<script>
|
||
import { onMount } from 'svelte';
|
||
import { useTinyRouter } from 'svelte-tiny-router';
|
||
import { api, get, post, search, target } from '../../urls.svelte.js';
|
||
import { error, warn, yikes } from '../../warn.svelte';
|
||
import { t } from '../../translations.svelte.js';
|
||
import { display } from '../../time.svelte';
|
||
|
||
import Bookmark from '../bookmark/Template.svelte';
|
||
|
||
const router = useTinyRouter();
|
||
let counter = 9;
|
||
let bookmarks = $state(null);
|
||
let companies = $state(null);
|
||
let documents = $state(null);
|
||
let fulltext = false;
|
||
let notes = $state(null);
|
||
let pages = $state(null);
|
||
let projects = $state(null);
|
||
let stock = $state(null);
|
||
let tasks = $state(null);
|
||
let times = $state(null);
|
||
|
||
|
||
|
||
function doSearch(key){
|
||
warn(t('searching…'));
|
||
|
||
const data = { key : key, fulltext : fulltext };
|
||
post(api('bookmark/search'),data).then(handleBookmarks);
|
||
post(api('company/search '),data).then(handleCompanies);
|
||
post(api('document/search'),data).then(handleDocuments);
|
||
post(api('notes/search' ),data).then(handleNotes);
|
||
post(api('project/search' ),data).then(handleProjects);
|
||
post(api('task/search' ),data).then(handleTasks);
|
||
post(api('stock/search' ),data).then(handleStock);
|
||
post(api('time/search' ),data).then(handleTimes);
|
||
post(api('wiki/search' ),data).then(handleWikiPages);
|
||
}
|
||
|
||
async function getTitle(key,module,entity_id){
|
||
get(api(module+'/'+entity_id)).then(res => setTitle(res,key,module))
|
||
}
|
||
|
||
async function handleBookmarks(resp){
|
||
quitOne();
|
||
if (resp.ok){
|
||
const res = await resp.json();
|
||
bookmarks = Object.keys(res).length ? res : null;
|
||
} else {
|
||
error(resp);
|
||
}
|
||
}
|
||
|
||
async function handleCompanies(resp){
|
||
quitOne();
|
||
if (resp.ok){
|
||
const json = await resp.json();
|
||
companies = Object.keys(json).length ? json : null;
|
||
} else {
|
||
error(resp);
|
||
}
|
||
}
|
||
|
||
async function handleDocuments(resp){
|
||
quitOne();
|
||
if (resp.ok){
|
||
const json = await resp.json();
|
||
documents = Object.keys(json).length ? json : null;
|
||
} else {
|
||
error(resp);
|
||
}
|
||
}
|
||
|
||
async function handleNotes(resp){
|
||
quitOne();
|
||
if (resp.ok){
|
||
const json = await resp.json();
|
||
if ( Object.keys(json).length ) {
|
||
for (let key of Object.keys(json)){
|
||
let module = json[key].module;
|
||
let entity_id = json[key].entity_id;
|
||
json[key].title = t(module)+' '+entity_id;
|
||
getTitle(key,module,entity_id);
|
||
}
|
||
notes = json;
|
||
} else notes = null;
|
||
} else {
|
||
error(resp);
|
||
}
|
||
}
|
||
|
||
async function handleProjects(resp){
|
||
quitOne();
|
||
if (resp.ok){
|
||
const res = await resp.json();
|
||
projects = Object.keys(res).length ? res : null;
|
||
} else {
|
||
error(resp);
|
||
}
|
||
}
|
||
|
||
async function handleStock(resp){
|
||
quitOne();
|
||
if (resp.ok){
|
||
const res = await resp.json();
|
||
stock = Object.keys(res).length ? res : null;
|
||
} else {
|
||
error(resp);
|
||
}
|
||
}
|
||
|
||
async function handleTasks(resp){
|
||
quitOne();
|
||
if (resp.ok){
|
||
const res = await resp.json();
|
||
tasks = Object.keys(res).length ? res : null;
|
||
} else {
|
||
error(resp);
|
||
}
|
||
}
|
||
|
||
async function handleTimes(resp){
|
||
quitOne();
|
||
if (resp.ok){
|
||
const res = await resp.json();
|
||
times = Object.keys(res).length ? res : null;
|
||
} else {
|
||
error(resp);
|
||
}
|
||
}
|
||
|
||
async function handleWikiPages(resp){
|
||
quitOne();
|
||
if (resp.ok){
|
||
const res = await resp.json();
|
||
pages = Object.keys(res).length ? res : null;
|
||
} else {
|
||
error(resp);
|
||
}
|
||
}
|
||
|
||
function onclick(e){
|
||
e.preventDefault();
|
||
var target = e.target;
|
||
while (target && !target.href) target=target.parentNode;
|
||
let href = target.getAttribute('href');
|
||
if (href) router.navigate(href);
|
||
return false;
|
||
}
|
||
|
||
async function setKey(ev){
|
||
if (ev) ev.preventDefault();
|
||
doSearch(search.key);
|
||
}
|
||
|
||
async function setTitle(resp,key,module){
|
||
if (resp.ok){
|
||
const json = await resp.json();
|
||
if (json.name) notes[key].title = t(module)+": "+json.name;
|
||
if (json.title) notes[key].title = t(module)+": "+json.title;
|
||
if (module == 'document'){
|
||
notes[key].title = t(json.type)+" "+json.number;
|
||
}
|
||
}
|
||
}
|
||
|
||
function quitOne(){
|
||
counter--;
|
||
if (counter > 0) {
|
||
warn(t('searching…')+" "+counter);
|
||
} else yikes();
|
||
}
|
||
|
||
function updateUrl(ev){
|
||
ev.preventDefault();
|
||
let url = window.location.origin + window.location.pathname;
|
||
if (search.key) {
|
||
url += '?key=' + encodeURI(search.key);
|
||
window.history.replaceState(history.state, '', url);
|
||
doSearch(search.key);
|
||
}
|
||
}
|
||
|
||
$effect(() => {
|
||
doSearch(router.getQueryParam('key'));
|
||
});
|
||
</script>
|
||
|
||
<svelte:head>
|
||
<title>Umbrella – {t('search')}{search.key?': '+search.key:''}</title>
|
||
</svelte:head>
|
||
|
||
<fieldset class="search">
|
||
<legend>{t('search')} - {search.key}</legend>
|
||
<form onsubmit={updateUrl}>
|
||
<label>
|
||
{t('key')}
|
||
<input type="text" bind:value={search.key} />
|
||
</label>
|
||
<label>
|
||
<input type="checkbox" bind:checked={fulltext} />
|
||
{t('fulltext')}
|
||
</label>
|
||
<button type="submit">{t('go')}</button>
|
||
</form>
|
||
</fieldset>
|
||
{#if projects}
|
||
<fieldset>
|
||
<legend>
|
||
{t('projects')}
|
||
</legend>
|
||
<ul>
|
||
{#each Object.values(projects) as project}
|
||
<li>
|
||
<a href="/project/{project.id}/view" {onclick} >{project.name}</a>
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
</fieldset>
|
||
{/if}
|
||
{#if tasks}
|
||
<fieldset>
|
||
<legend>
|
||
{t('tasks')}
|
||
</legend>
|
||
<ul>
|
||
{#each Object.values(tasks) as task}
|
||
<li>
|
||
<a href="/task/{task.id}/view" {onclick} class={task.status.name}>{task.name}</a>
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
</fieldset>
|
||
{/if}
|
||
{#if bookmarks}
|
||
<fieldset>
|
||
<legend>
|
||
{t('bookmarks')}
|
||
</legend>
|
||
<ul>
|
||
{#each Object.values(bookmarks) as bookmark}
|
||
<li>
|
||
<a href={bookmark.url} target="_blank">{@html target(bookmark.comment.rendered)}</a>
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
</fieldset>
|
||
{/if}
|
||
{#if companies}
|
||
<fieldset>
|
||
<legend>
|
||
{t('companies')}
|
||
</legend>
|
||
<ul>
|
||
{#each Object.values(companies) as company}
|
||
<li>
|
||
<a href="/company/{company.id}/view" {onclick} >{company.name}</a>
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
</fieldset>
|
||
{/if}
|
||
{#if stock}
|
||
<fieldset>
|
||
<legend>
|
||
{t('stock')}
|
||
</legend>
|
||
{#if Object.keys(stock.items).length }
|
||
{t('items')}
|
||
<ul>
|
||
{#each Object.values(stock.items) as item}
|
||
<li>
|
||
<a href="/stock/{item.owner.type}/{item.owner.id}/item/{item.owner_number}" {onclick} >
|
||
{item.name} [{t('code')}: <span class="code">{item.code}</span>]
|
||
</a>
|
||
{@html item.description.rendered}
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
{/if}
|
||
{#if Object.keys(stock.locations).length}
|
||
{t('locations')}
|
||
<ul>
|
||
{#each Object.values(stock.locations) as loc (loc.id)}
|
||
<li>
|
||
<a href="/stock/location/{loc.id}">{loc.name}</a>
|
||
<br/> {@html loc.description.rendered}
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
{/if}
|
||
</fieldset>
|
||
{/if}
|
||
{#if times}
|
||
<fieldset>
|
||
<legend>
|
||
{t('timetracking')}
|
||
</legend>
|
||
<ul>
|
||
{#each Object.values(times) as time}
|
||
<li>
|
||
<a href="/time/{time.id}/view" {onclick} >
|
||
{display(time.start_time)}{#if time.end_time}…{display(time.end_time)}{/if}
|
||
{time.subject}
|
||
</a>
|
||
<br/>
|
||
{@html target(time.description.rendered)}
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
</fieldset>
|
||
{/if}
|
||
{#if documents}
|
||
<fieldset>
|
||
<legend>
|
||
{t('documents')}
|
||
</legend>
|
||
<ul>
|
||
{#each Object.values(documents) as document}
|
||
<li>
|
||
<a href="/document/{document.id}/view" {onclick} >
|
||
{document.number}
|
||
({document.date})
|
||
{document.sender.name.split('\n')[0]}
|
||
→
|
||
{document.customer.name.split('\n')[0]}
|
||
</a>
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
</fieldset>
|
||
{/if}
|
||
{#if pages}
|
||
<fieldset>
|
||
<legend>
|
||
{t('wiki_pages')}
|
||
</legend>
|
||
<ul>
|
||
{#each Object.values(pages) as page}
|
||
<li>
|
||
<a href="/wiki/{page.id}/view" {onclick} >
|
||
{page.title}
|
||
</a>
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
</fieldset>
|
||
{/if}
|
||
{#if notes}
|
||
<fieldset>
|
||
<legend>
|
||
{t('notes')}
|
||
</legend>
|
||
<ul>
|
||
{#each Object.values(notes) as note}
|
||
<li>
|
||
<b>
|
||
<a href="/{note.module}/{note.entity_id}/view" {onclick} >{note.title}</a>
|
||
</b>
|
||
{@html target(note.text.rendered)}
|
||
</li>
|
||
{/each}
|
||
</ul>
|
||
</fieldset>
|
||
{/if}
|