working on vcard display
Signed-off-by: Stephan Richter <s.richter@srsoftware.de>
This commit is contained in:
15
frontend/src/routes/contact/Card.svelte
Normal file
15
frontend/src/routes/contact/Card.svelte
Normal file
@@ -0,0 +1,15 @@
|
||||
<script>
|
||||
import FN from './FN.svelte';
|
||||
import Name from './Name.svelte';
|
||||
import Org from './Org.svelte';
|
||||
|
||||
let { contact } = $props();
|
||||
</script>
|
||||
|
||||
<div>
|
||||
<Org vcard={contact.vcard} /><br/>
|
||||
<FN vcard={contact.vcard} /><br/>
|
||||
<Name vcard={contact.vcard} />
|
||||
<hr/>
|
||||
<pre>{contact.vcard}</pre>
|
||||
</div>
|
||||
9
frontend/src/routes/contact/FN.svelte
Normal file
9
frontend/src/routes/contact/FN.svelte
Normal file
@@ -0,0 +1,9 @@
|
||||
<script>
|
||||
import { fn } from '../../vcard.js';
|
||||
|
||||
let { vcard } = $props();
|
||||
|
||||
let name = $derived(fn(vcard));
|
||||
</script>
|
||||
|
||||
<span class="formatted name">{name}</span>
|
||||
@@ -1,58 +1,15 @@
|
||||
<script>
|
||||
import Card from './Card.svelte';
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
import { api } from '../../urls.svelte';
|
||||
import { error, yikes } from '../../warn.svelte';
|
||||
import { t } from '../../translations.svelte';
|
||||
|
||||
import { byName } from '../../vcard.js';
|
||||
|
||||
let contacts = $state(null)
|
||||
|
||||
function parseAdr(key,val){
|
||||
var parts = val.split(';');
|
||||
var adr = {
|
||||
postbox : parts[0],
|
||||
ext : parts[1],
|
||||
street : parts[2],
|
||||
locality : parts[3],
|
||||
region : parts[4],
|
||||
code : parts[5],
|
||||
country : parts[6]
|
||||
}
|
||||
parts = key.split(';');
|
||||
for (let part of parts){
|
||||
let inner = part.split('=');
|
||||
if (inner.length<2) continue;
|
||||
const k = inner[0];
|
||||
const v = inner.slice(1).join('=');
|
||||
adr[k] = v;
|
||||
}
|
||||
return adr;
|
||||
}
|
||||
|
||||
function parse(data){
|
||||
var code = data.vcard;
|
||||
const lines = code.split("\n");
|
||||
let unprocessed = null;
|
||||
var o = {};
|
||||
for (var line of lines){
|
||||
if (unprocessed = null) unprocessed = line;
|
||||
if (line.startsWith(' ')) { // extend line
|
||||
unprocessed += line.substring(1);
|
||||
} else {
|
||||
// process complete line
|
||||
const parts = line.split(':');
|
||||
var prefix = parts[0];
|
||||
var val = parts.slice(1).join(':');
|
||||
var key = prefix.split(';')[0].toUpperCase();
|
||||
switch (key) {
|
||||
case "ADR": o[key] = parseAdr(prefix,val); break;
|
||||
default:
|
||||
if (key) o[prefix]=val;
|
||||
}
|
||||
unprocessed = line;
|
||||
}
|
||||
}
|
||||
console.log(o);
|
||||
}
|
||||
|
||||
async function load(){
|
||||
const url = api('contact/list');
|
||||
@@ -60,7 +17,7 @@
|
||||
if (res.ok){
|
||||
yikes();
|
||||
var data = await res.json();
|
||||
contacts = Object.values(data).map(parse).sort((a,b) => a.FN.localeCompare(b.FN));
|
||||
contacts = Object.values(data).sort(byName);
|
||||
console.log(contacts);
|
||||
} else {
|
||||
error(res);
|
||||
@@ -70,4 +27,7 @@
|
||||
onMount(load);
|
||||
</script>
|
||||
|
||||
<h1>{t('contacts')}</h1>
|
||||
<h1>{t('contacts')}</h1>
|
||||
{#each contacts as contact}
|
||||
<Card {contact} />
|
||||
{/each}
|
||||
23
frontend/src/routes/contact/Name.svelte
Normal file
23
frontend/src/routes/contact/Name.svelte
Normal file
@@ -0,0 +1,23 @@
|
||||
<script>
|
||||
import { name } from '../../vcard.js';
|
||||
|
||||
let { vcard } = $props();
|
||||
|
||||
let n = $derived(name(vcard));
|
||||
</script>
|
||||
|
||||
{#if n.prefix}
|
||||
<span class="name prefix">{n.prefix}</span>
|
||||
{/if}
|
||||
{#if n.given}
|
||||
<span class="given name">{n.given}</span>
|
||||
{/if}
|
||||
{#if n.family}
|
||||
<span class="family name">{n.family}</span>
|
||||
{/if}
|
||||
{#if n.additional}
|
||||
<span class="additional name">{n.additional}</span>
|
||||
{/if}
|
||||
{#if n.suffix}
|
||||
<span class="name suffix">{n.suffix}</span>
|
||||
{/if}
|
||||
9
frontend/src/routes/contact/Org.svelte
Normal file
9
frontend/src/routes/contact/Org.svelte
Normal file
@@ -0,0 +1,9 @@
|
||||
<script>
|
||||
import { org } from '../../vcard.js';
|
||||
|
||||
let { vcard } = $props();
|
||||
|
||||
let o = $derived(org(vcard));
|
||||
</script>
|
||||
|
||||
<span class="organization">{o}</span>
|
||||
82
frontend/src/vcard.js
Normal file
82
frontend/src/vcard.js
Normal file
@@ -0,0 +1,82 @@
|
||||
export function parse(data){
|
||||
var code = data.vcard;
|
||||
const lines = code.split("\n");
|
||||
let unprocessed = null;
|
||||
var o = {};
|
||||
for (var line of lines){
|
||||
if (unprocessed = null) unprocessed = line;
|
||||
if (line.startsWith(' ')) { // extend line
|
||||
unprocessed += line.substring(1);
|
||||
} else {
|
||||
// process complete line
|
||||
const parts = line.split(':');
|
||||
var prefix = parts[0];
|
||||
var val = parts.slice(1).join(':');
|
||||
var key = prefix.split(';')[0].toUpperCase();
|
||||
switch (key) {
|
||||
case "ADR": o[key] = parseAdr(prefix,val); break;
|
||||
default:
|
||||
if (key) o[prefix]=val;
|
||||
}
|
||||
unprocessed = line;
|
||||
}
|
||||
}
|
||||
console.log(o);
|
||||
}
|
||||
|
||||
function parseAdr(key,val){
|
||||
var parts = val.split(';');
|
||||
var adr = {
|
||||
postbox : parts[0],
|
||||
ext : parts[1],
|
||||
street : parts[2],
|
||||
locality : parts[3],
|
||||
region : parts[4],
|
||||
code : parts[5],
|
||||
country : parts[6]
|
||||
}
|
||||
parts = key.split(';');
|
||||
for (let part of parts){
|
||||
let inner = part.split('=');
|
||||
if (inner.length<2) continue;
|
||||
const k = inner[0];
|
||||
const v = inner.slice(1).join('=');
|
||||
adr[k] = v;
|
||||
}
|
||||
return adr;
|
||||
}
|
||||
|
||||
export function fn(vcard){
|
||||
const match = vcard.match(/^FN:(.+)$/m);
|
||||
return match ? match[1].trim() : '';
|
||||
}
|
||||
|
||||
export function org(vcard){
|
||||
const match = vcard.match(/^ORG:(.+)$/m);
|
||||
return match ? match[1].trim() : '';
|
||||
}
|
||||
|
||||
export function name(vcard){
|
||||
const match = vcard.match(/^N:(.+)$/m);
|
||||
let name = {
|
||||
family: null,
|
||||
given: null,
|
||||
additional: null,
|
||||
prefix: null,
|
||||
suffix: null
|
||||
}
|
||||
if (match){
|
||||
const parts = match[1].trim().split(';');
|
||||
name.family = parts[0];
|
||||
name.given = parts[1];
|
||||
name.additional = parts[2];
|
||||
name.prefix = parts[3];
|
||||
name.suffix = parts[4];
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
export function byName(a,b){
|
||||
return fn(a.vcard).localeCompare(fn(b.vcard));
|
||||
}
|
||||
Reference in New Issue
Block a user