forked from mirrors/homebox
feat: link implementation (#100)
* link implementation * add docs for links * use btn instead of badge
This commit is contained in:
parent
97a34475c8
commit
2d34557f69
9 changed files with 120 additions and 6 deletions
|
@ -9,6 +9,14 @@
|
|||
<slot :name="detail.slot || detail.name" v-bind="{ detail }">
|
||||
<DateTime v-if="detail.type == 'date'" :date="detail.text" />
|
||||
<Currency v-else-if="detail.type == 'currency'" :amount="detail.text" />
|
||||
<template v-else-if="detail.type === 'link'">
|
||||
<div class="tooltip tooltip-primary tooltip-right" :data-tip="detail.href">
|
||||
<a class="btn btn-primary btn-xs" :href="detail.href" target="_blank">
|
||||
<Icon name="mdi-open-in-new" class="mr-2 swap-on"></Icon>
|
||||
{{ detail.text }}
|
||||
</a>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ detail.text }}
|
||||
</template>
|
||||
|
|
|
@ -15,7 +15,13 @@ type CurrencyDetail = BaseDetail & {
|
|||
text: string;
|
||||
};
|
||||
|
||||
export type CustomDetail = DateDetail | CurrencyDetail;
|
||||
type LinkDetail = BaseDetail & {
|
||||
type: "link";
|
||||
text: string;
|
||||
href: string;
|
||||
};
|
||||
|
||||
export type CustomDetail = DateDetail | CurrencyDetail | LinkDetail;
|
||||
|
||||
export type Detail = BaseDetail & {
|
||||
text: StringLike;
|
||||
|
|
32
frontend/composables/utils.test.ts
Normal file
32
frontend/composables/utils.test.ts
Normal file
|
@ -0,0 +1,32 @@
|
|||
import { describe, expect, test } from "vitest";
|
||||
import { maybeUrl } from "./utils";
|
||||
|
||||
describe("maybeURL works as expected", () => {
|
||||
test("basic valid URL case", () => {
|
||||
const result = maybeUrl("https://example.com");
|
||||
expect(result.isUrl).toBe(true);
|
||||
expect(result.url).toBe("https://example.com");
|
||||
expect(result.text).toBe("Link");
|
||||
});
|
||||
|
||||
test("special URL syntax", () => {
|
||||
const result = maybeUrl("[My Text](http://example.com)");
|
||||
expect(result.isUrl).toBe(true);
|
||||
expect(result.url).toBe("http://example.com");
|
||||
expect(result.text).toBe("My Text");
|
||||
});
|
||||
|
||||
test("not a url", () => {
|
||||
const result = maybeUrl("not a url");
|
||||
expect(result.isUrl).toBe(false);
|
||||
expect(result.url).toBe("");
|
||||
expect(result.text).toBe("");
|
||||
});
|
||||
|
||||
test("malformed special syntax", () => {
|
||||
const result = maybeUrl("[My Text(http://example.com)");
|
||||
expect(result.isUrl).toBe(false);
|
||||
expect(result.url).toBe("");
|
||||
expect(result.text).toBe("");
|
||||
});
|
||||
});
|
|
@ -33,3 +33,35 @@ export function fmtCurrency(value: number | string, currency = "USD", locale = "
|
|||
});
|
||||
return formatter.format(value);
|
||||
}
|
||||
|
||||
export type MaybeUrlResult = {
|
||||
isUrl: boolean;
|
||||
url: string;
|
||||
text: string;
|
||||
};
|
||||
|
||||
export function maybeUrl(str: string): MaybeUrlResult {
|
||||
const result: MaybeUrlResult = {
|
||||
isUrl: str.startsWith("http://") || str.startsWith("https://"),
|
||||
url: "",
|
||||
text: "",
|
||||
};
|
||||
|
||||
if (!result.isUrl && !str.startsWith("[")) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (str.startsWith("[")) {
|
||||
const match = str.match(/\[(.*)\]\((.*)\)/);
|
||||
if (match && match.length === 3) {
|
||||
result.isUrl = true;
|
||||
result.text = match[1];
|
||||
result.url = match[2];
|
||||
}
|
||||
} else {
|
||||
result.url = str;
|
||||
result.text = "Link";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -96,10 +96,25 @@
|
|||
name: "Notes",
|
||||
text: item.value?.notes,
|
||||
},
|
||||
...item.value.fields.map(field => ({
|
||||
name: field.name,
|
||||
text: field.textValue,
|
||||
})),
|
||||
...item.value.fields.map(field => {
|
||||
/**
|
||||
* Support Special URL Syntax
|
||||
*/
|
||||
const url = maybeUrl(field.textValue);
|
||||
if (url.isUrl) {
|
||||
return {
|
||||
name: field.name,
|
||||
text: url.text,
|
||||
type: "link",
|
||||
href: url.url,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: field.name,
|
||||
text: field.textValue,
|
||||
};
|
||||
}),
|
||||
];
|
||||
});
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue