@christianriedl/media 1.0.182 → 1.0.184
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/booksService.d.ts +2 -0
- package/dist/booksService.js +5 -1
- package/dist/booksService.js.map +1 -1
- package/dist/iBooks.d.ts +2 -0
- package/package.json +1 -1
- package/src/components/BookLine.vue +15 -5
- package/src/components/BookSearchLine.vue +18 -7
- package/src/views/BooksPage.vue +97 -78
- package/src/views/BooksSearchPage.vue +57 -47
package/dist/booksService.d.ts
CHANGED
|
@@ -10,6 +10,8 @@ export declare class BooksService implements IBooksService {
|
|
|
10
10
|
cachedAuthors?: IAuthorShort[];
|
|
11
11
|
categories: string[];
|
|
12
12
|
flags: string[];
|
|
13
|
+
selectedAuthorId: number;
|
|
14
|
+
selectedBookId: number;
|
|
13
15
|
constructor(rest: IRest, user: string, statistics: IStatistics, log: ILogger);
|
|
14
16
|
getAuthors(surName?: string, givenName?: string, withBooks?: boolean, id?: number): Promise<IAuthor[]>;
|
|
15
17
|
getAuthorsShort(): Promise<IAuthorShort[]>;
|
package/dist/booksService.js
CHANGED
|
@@ -7,13 +7,17 @@ export class BooksService {
|
|
|
7
7
|
cachedAuthors;
|
|
8
8
|
categories;
|
|
9
9
|
flags;
|
|
10
|
+
selectedAuthorId;
|
|
11
|
+
selectedBookId;
|
|
10
12
|
constructor(rest, user, statistics, log) {
|
|
11
13
|
this.log = log;
|
|
12
14
|
this.rest = rest;
|
|
13
15
|
this.user = user;
|
|
14
16
|
this.mediaUrl = rest.serviceUrl;
|
|
15
17
|
this.categories = ["Literatur", "Geschichte", "Philosophie", "Naturwissenschaft"];
|
|
16
|
-
this.flags = ["
|
|
18
|
+
this.flags = ["liesC", "liesH", "ausgeborgt"];
|
|
19
|
+
this.selectedAuthorId = 0;
|
|
20
|
+
this.selectedBookId = 0;
|
|
17
21
|
}
|
|
18
22
|
async getAuthors(surName, givenName, withBooks, id) {
|
|
19
23
|
const info = await this.rest.getData('apibooks/authors', { surName, givenName, withBooks, id });
|
package/dist/booksService.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"booksService.js","sourceRoot":"","sources":["../src/booksService.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,cAAc,GAAqC,MAAM,CAAC,WAAW,CAAC,CAAC;AACpF,MAAM,OAAO,YAAY;IACrB,IAAI,CAAQ;IACZ,QAAQ,CAAS;IACjB,IAAI,CAAS;IACb,GAAG,CAAU;IACb,aAAa,CAAkB;IAC/B,UAAU,CAAW;IACrB,KAAK,CAAW;IAChB,YAAY,IAAW,EAAE,IAAY,EAAE,UAAuB,EAAE,GAAY;QACxE,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,UAAU,CAAC;QAChC,IAAI,CAAC,UAAU,GAAG,CAAC,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,mBAAmB,CAAC,CAAC;QAClF,IAAI,CAAC,KAAK,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"booksService.js","sourceRoot":"","sources":["../src/booksService.ts"],"names":[],"mappings":"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"}
|
package/dist/iBooks.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export interface IFullBook {
|
|
|
35
35
|
export interface IBooksService {
|
|
36
36
|
categories: string[];
|
|
37
37
|
flags: string[];
|
|
38
|
+
selectedAuthorId: number;
|
|
39
|
+
selectedBookId: number;
|
|
38
40
|
getAuthors(surName?: string, givenName?: string, withBooks?: boolean, id?: number): Promise<IAuthor[]>;
|
|
39
41
|
getAuthorsShort(): Promise<IAuthorShort[]>;
|
|
40
42
|
addAuthor(author: IAuthor): Promise<number>;
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { ref } from 'vue';
|
|
2
|
+
import { ref, computed } from 'vue';
|
|
3
3
|
import { IBook } from '@christianriedl/media';
|
|
4
4
|
|
|
5
|
-
const props = defineProps<{ book: IBook, flags: string[], add?: boolean, readonly?: boolean, ismobile?: boolean, allbooks?: IBook[] }>();
|
|
5
|
+
const props = defineProps<{ book: IBook, flags: string[], add?: boolean, readonly?: boolean, selected?: boolean, ismobile?: boolean, allbooks?: IBook[] }>();
|
|
6
6
|
const book = props.book;
|
|
7
7
|
const emits = defineEmits<{
|
|
8
8
|
(e: 'selectbook', id: number, func: () => void): void,
|
|
@@ -11,10 +11,15 @@
|
|
|
11
11
|
}>();
|
|
12
12
|
|
|
13
13
|
const cls = props.add ? ["bg-climate"] : ["bg-office"];
|
|
14
|
+
const classObject = computed(() => ({
|
|
15
|
+
'bg-secondary': props.selected,
|
|
16
|
+
'bg-climate': props.add
|
|
17
|
+
}));
|
|
14
18
|
const showDelete = ref(!props.add);
|
|
15
19
|
const showSelect = ref(!props.add);
|
|
16
20
|
const showSave = ref(false);
|
|
17
21
|
const selected = ref<IBook | string | undefined>();
|
|
22
|
+
const flags = ref<string[]>(book.flags ? book.flags.split(',') : []);
|
|
18
23
|
|
|
19
24
|
async function titleChanged(arg: IBook | string) {
|
|
20
25
|
if (typeof arg == 'string') {
|
|
@@ -45,10 +50,14 @@
|
|
|
45
50
|
function fieldChanged () {
|
|
46
51
|
showSave.value = true;
|
|
47
52
|
}
|
|
53
|
+
function flagsChanged () {
|
|
54
|
+
showSave.value = true;
|
|
55
|
+
book.flags = flags.value.join(',');
|
|
56
|
+
}
|
|
48
57
|
</script>
|
|
49
58
|
|
|
50
59
|
<template>
|
|
51
|
-
<v-row v-if="props.ismobile" dense align="center" :class="
|
|
60
|
+
<v-row v-if="props.ismobile" dense align="center" :class="classObject" @click="onSelect" >
|
|
52
61
|
<v-col cols="9" >
|
|
53
62
|
<v-text-field v-model="book.title" disabled hide-details density="compact" ></v-text-field>
|
|
54
63
|
</v-col>
|
|
@@ -56,7 +65,7 @@
|
|
|
56
65
|
<v-text-field v-model="book.year" disabled hide-details density="compact" ></v-text-field>
|
|
57
66
|
</v-col>
|
|
58
67
|
</v-row>
|
|
59
|
-
<v-row v-else dense align="center" :class="
|
|
68
|
+
<v-row v-else dense align="center" :class="classObject" @click="onSelect" >
|
|
60
69
|
<v-col v-if="props.add" cols="6" >
|
|
61
70
|
<v-combobox v-model="selected" :items="props.allbooks" item-value="id" item-title="title" hide-details density="compact" single-line @update:modelValue="titleChanged"></v-combobox>
|
|
62
71
|
</v-col>
|
|
@@ -70,11 +79,12 @@
|
|
|
70
79
|
<v-rating hover clearable :length="5" :size="32" v-model="book.rating" active-color="primary" @update:modelValue="fieldChanged" />
|
|
71
80
|
</v-col>
|
|
72
81
|
<v-col cols="2">
|
|
73
|
-
|
|
82
|
+
<v-select v-model="flags" :items="props.flags" multiple hide-details density="compact" single-line @update:modelValue="flagsChanged"></v-select>
|
|
74
83
|
</v-col>
|
|
75
84
|
<v-col cols="2">
|
|
76
85
|
<v-btn v-if="showSave" icon="$save" :disabled="props.readonly" @click="onSave"></v-btn>
|
|
77
86
|
<v-btn v-if="showDelete" icon="$delete" :disabled="props.readonly" @click="onDelete"></v-btn>
|
|
78
87
|
</v-col>
|
|
79
88
|
</v-row>
|
|
89
|
+
<v-divider></v-divider>
|
|
80
90
|
</template>
|
|
@@ -1,24 +1,35 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { ref, computed } from 'vue';
|
|
2
3
|
import { IFullBook } from '@christianriedl/media';
|
|
3
|
-
const props = defineProps<{ book: IFullBook, ismobile?: boolean }>();
|
|
4
|
+
const props = defineProps<{ book: IFullBook, selected?: boolean, ismobile?: boolean }>();
|
|
5
|
+
const emits = defineEmits<{
|
|
6
|
+
(e: 'selectbook'): void
|
|
7
|
+
}>();
|
|
4
8
|
const book = props.book;
|
|
9
|
+
const classObject = computed(() => ({
|
|
10
|
+
'bg-secondary': props.selected
|
|
11
|
+
}));
|
|
12
|
+
function onSelect () {
|
|
13
|
+
emits ("selectbook");
|
|
14
|
+
}
|
|
5
15
|
</script>
|
|
6
16
|
|
|
7
17
|
<template>
|
|
8
|
-
<v-row v-if="props.ismobile" dense align="center" class="
|
|
18
|
+
<v-row v-if="props.ismobile" dense align="center" :class="classObject" @click="onSelect">
|
|
9
19
|
<v-col cols="12" >
|
|
10
20
|
<p class="font-weight-bold">{{book.givenName + ' ' + book.surName}}</p>
|
|
11
21
|
</v-col>
|
|
12
22
|
<v-col cols="12" >
|
|
13
|
-
<p
|
|
23
|
+
<p>{{book.title}}</p>
|
|
14
24
|
</v-col>
|
|
15
25
|
</v-row>
|
|
16
|
-
<v-row v-else dense align="center" :class="
|
|
17
|
-
<v-col cols="
|
|
26
|
+
<v-row v-else dense align="center" :class="classObject" @click="onSelect" >
|
|
27
|
+
<v-col cols="4" >
|
|
18
28
|
<p class="font-weight-bold">{{book.givenName + ' ' + book.surName}}</p>
|
|
19
29
|
</v-col>
|
|
20
|
-
<v-col cols="
|
|
21
|
-
<p
|
|
30
|
+
<v-col cols="8" >
|
|
31
|
+
<p>{{book.title}}</p>
|
|
22
32
|
</v-col>
|
|
23
33
|
</v-row>
|
|
34
|
+
<v-divider></v-divider>
|
|
24
35
|
</template>
|
package/src/views/BooksPage.vue
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { inject, ref, reactive, onMounted, onUnmounted, computed, StyleValue } from 'vue';
|
|
3
|
+
import { useRouter } from 'vue-router';
|
|
3
4
|
import { IAppState, appStateSymbol, getOpenAISymbol, IOpenAIService, ICompleteData, EScope, EDevice } from '@christianriedl/utils';
|
|
4
5
|
import { BooksService, getBooksSymbol, IAuthorShort, IAuthor, IBook } from '@christianriedl/media';
|
|
5
6
|
import BookLine from '../components/BookLine.vue';
|
|
6
7
|
|
|
8
|
+
const router = useRouter();
|
|
7
9
|
const appState = inject(appStateSymbol)!;
|
|
8
10
|
const getBooksService = inject(getBooksSymbol)!;
|
|
9
11
|
const booksService = getBooksService() as BooksService;
|
|
10
12
|
const getOpenAI = inject(getOpenAISymbol)!;
|
|
11
13
|
const openAI = getOpenAI();
|
|
12
14
|
const authors = reactive<IAuthorShort[]>([]);
|
|
13
|
-
const
|
|
14
|
-
const
|
|
15
|
-
const
|
|
15
|
+
const selectedAuthor = ref<IAuthorShort | string | undefined>();
|
|
16
|
+
const currentAuthor = reactive<IAuthor>({ id: 0, surName: "", givenName: "", yearOfBirth: 0, books: [] });
|
|
17
|
+
const selectedBook = ref<IBook>({ id: 0, authorId: 0, title: ""});
|
|
16
18
|
let newBook: IBook;
|
|
17
19
|
const allBooks = ref<IBook[]>([]);
|
|
18
20
|
const lastAllBooksId = ref(0);
|
|
19
21
|
const mustAddAuthor = ref(false);
|
|
20
22
|
const mustUpdateAuthor = ref(false);
|
|
21
23
|
const showAddBookLine = ref(false);
|
|
22
|
-
const
|
|
24
|
+
const showSelectedBook = ref(false);
|
|
23
25
|
let setBookChanged: () => void;
|
|
24
26
|
let readonly = !(appState.scopes & EScope.Admin);
|
|
25
27
|
let isMobile = appState.isMobile && (appState.device != EDevice.iPad);
|
|
@@ -32,60 +34,66 @@
|
|
|
32
34
|
if (authorsShort) {
|
|
33
35
|
authors.splice(0, authors.length, ...authorsShort);
|
|
34
36
|
}
|
|
37
|
+
if (booksService.selectedAuthorId) {
|
|
38
|
+
selectedAuthor.value = authors.find ((x) => x.id == booksService.selectedAuthorId);
|
|
39
|
+
getCurrentAuthor (booksService.selectedAuthorId, true)
|
|
40
|
+
booksService.selectedAuthorId = 0;
|
|
41
|
+
booksService.selectedBookId = 0;
|
|
42
|
+
}
|
|
35
43
|
}
|
|
36
44
|
async function addAuthor() {
|
|
37
|
-
if (!checkAuthor(
|
|
45
|
+
if (!checkAuthor(currentAuthor))
|
|
38
46
|
return;
|
|
39
|
-
const id = await booksService.addAuthor(
|
|
47
|
+
const id = await booksService.addAuthor(currentAuthor);
|
|
40
48
|
if (id > 0) {
|
|
41
|
-
|
|
49
|
+
currentAuthor.id = id;
|
|
42
50
|
mustAddAuthor.value = false;
|
|
43
51
|
}
|
|
44
52
|
else
|
|
45
53
|
alert (`AddAuthor - error ${id}`);
|
|
46
54
|
}
|
|
47
55
|
async function updateAuthor() {
|
|
48
|
-
if (!checkAuthor(
|
|
56
|
+
if (!checkAuthor(currentAuthor))
|
|
49
57
|
return;
|
|
50
|
-
const rc = await booksService.updateAuthor(
|
|
58
|
+
const rc = await booksService.updateAuthor(currentAuthor);
|
|
51
59
|
if (rc)
|
|
52
60
|
mustUpdateAuthor.value = false;
|
|
53
61
|
else
|
|
54
62
|
alert ('UpdateAuthor - error');
|
|
55
63
|
}
|
|
56
64
|
async function deleteAuthor() {
|
|
57
|
-
if (!window.confirm(`Willst du ${
|
|
65
|
+
if (!window.confirm(`Willst du ${currentAuthor.surName} wirklich l�schen ?`))
|
|
58
66
|
return;
|
|
59
|
-
const rc = await booksService.deleteAuthor(
|
|
67
|
+
const rc = await booksService.deleteAuthor(currentAuthor.id);
|
|
60
68
|
if (rc) {
|
|
61
69
|
mustUpdateAuthor.value = false;
|
|
62
70
|
initAuthor ("");
|
|
63
71
|
}
|
|
64
72
|
else
|
|
65
|
-
alert (`DeleteAuthor ${
|
|
73
|
+
alert (`DeleteAuthor ${currentAuthor.id} - error`);
|
|
66
74
|
}
|
|
67
75
|
function initAuthor(surName: string) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
+
currentAuthor.id = 0;
|
|
77
|
+
currentAuthor.surName = surName;
|
|
78
|
+
currentAuthor.givenName = "";
|
|
79
|
+
currentAuthor.yearOfBirth = 0;
|
|
80
|
+
currentAuthor.yearOfDeath = undefined;
|
|
81
|
+
currentAuthor.category = undefined;
|
|
82
|
+
currentAuthor.country = undefined;
|
|
83
|
+
currentAuthor.books = [];
|
|
76
84
|
}
|
|
77
85
|
async function getCurrentAuthor (id: number, withBooks: boolean) : Promise<boolean> {
|
|
78
86
|
const authors = await booksService.getAuthors(undefined, undefined, withBooks, id);
|
|
79
87
|
if (authors && authors.length > 0) {
|
|
80
88
|
const a = authors[0];
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
currentAuthor.id = a.id;
|
|
90
|
+
currentAuthor.surName = a.surName;
|
|
91
|
+
currentAuthor.givenName = a.givenName;
|
|
92
|
+
currentAuthor.yearOfBirth = a.yearOfBirth;
|
|
93
|
+
currentAuthor.yearOfDeath = a.yearOfDeath;
|
|
94
|
+
currentAuthor.category = a.category;
|
|
95
|
+
currentAuthor.country = a.country;
|
|
96
|
+
currentAuthor.books = a.books ? a.books : [];
|
|
89
97
|
return true;
|
|
90
98
|
}
|
|
91
99
|
else {
|
|
@@ -94,14 +102,14 @@
|
|
|
94
102
|
}
|
|
95
103
|
}
|
|
96
104
|
async function authorNameChanged(arg: IAuthorShort | string) {
|
|
97
|
-
|
|
98
|
-
|
|
105
|
+
showSelectedBook.value = false;
|
|
106
|
+
selectedBook.value = { id: 0, authorId: 0, title: ""};
|
|
99
107
|
mustAddAuthor.value = typeof arg == 'string';
|
|
100
108
|
if (!mustAddAuthor.value) {
|
|
101
109
|
const authorShort = arg as IAuthorShort;
|
|
102
110
|
const rc = await getCurrentAuthor (authorShort.id, true);
|
|
103
|
-
if (rc && !
|
|
104
|
-
const rc = await getAuthorDataFromAI (
|
|
111
|
+
if (rc && !currentAuthor.country) {
|
|
112
|
+
const rc = await getAuthorDataFromAI (currentAuthor.surName, currentAuthor.givenName);
|
|
105
113
|
if (rc)
|
|
106
114
|
mustUpdateAuthor.value = true;
|
|
107
115
|
}
|
|
@@ -118,39 +126,44 @@
|
|
|
118
126
|
}
|
|
119
127
|
async function givenNameFocused(focus: boolean) {
|
|
120
128
|
if (!focus && mustAddAuthor.value) {
|
|
121
|
-
await getAuthorDataFromAI(
|
|
129
|
+
await getAuthorDataFromAI(currentAuthor.surName, currentAuthor.givenName);
|
|
122
130
|
}
|
|
123
131
|
}
|
|
132
|
+
function search () {
|
|
133
|
+
booksService.selectedAuthorId = 0;
|
|
134
|
+
booksService.selectedBookId = 0;
|
|
135
|
+
router.push({ path: 'booksearch' });
|
|
136
|
+
}
|
|
124
137
|
async function addNewBook() {
|
|
125
|
-
if (lastAllBooksId.value !=
|
|
126
|
-
allBooks.value = await getAuthorBooksFromAI (
|
|
127
|
-
lastAllBooksId.value =
|
|
138
|
+
if (lastAllBooksId.value != currentAuthor.id) {
|
|
139
|
+
allBooks.value = await getAuthorBooksFromAI (currentAuthor.surName, currentAuthor.givenName, currentAuthor.id);
|
|
140
|
+
lastAllBooksId.value = currentAuthor.id;
|
|
128
141
|
}
|
|
129
|
-
|
|
130
|
-
newBook = reactive<IBook>({ id: 0, authorId:
|
|
142
|
+
selectedBook.value = { id: 0, authorId: 0, title: ""};
|
|
143
|
+
newBook = reactive<IBook>({ id: 0, authorId: currentAuthor.id, title: "", rating: 0 });
|
|
131
144
|
showAddBookLine.value = true;
|
|
132
145
|
}
|
|
133
146
|
function cancelAddNewBook() {
|
|
134
147
|
showAddBookLine.value = false;
|
|
135
148
|
}
|
|
136
149
|
async function selectBook(id: number, func: () => void) {
|
|
137
|
-
if (
|
|
150
|
+
if (selectedBook.value.id == id) {
|
|
138
151
|
return;
|
|
139
152
|
}
|
|
140
153
|
setBookChanged = func;
|
|
141
|
-
if (
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
const books = await booksService.getBooks (
|
|
154
|
+
if (currentAuthor.books) {
|
|
155
|
+
selectedBook.value = currentAuthor.books.find (x => x.id == id) as IBook;
|
|
156
|
+
if (selectedBook.value && !selectedBook.value.description && !selectedBook.value.comment) {
|
|
157
|
+
const books = await booksService.getBooks (currentAuthor.id, selectedBook.value.id);
|
|
145
158
|
if (books && books.length > 0) {
|
|
146
|
-
|
|
147
|
-
|
|
159
|
+
selectedBook.value.description = books[0].description;
|
|
160
|
+
selectedBook.value.comment = books[0].comment;
|
|
148
161
|
}
|
|
149
|
-
|
|
150
|
-
if (!
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (
|
|
162
|
+
showSelectedBook.value = true;
|
|
163
|
+
if (!selectedBook.value.description) {
|
|
164
|
+
selectedBook.value.description ="WAITING..."
|
|
165
|
+
selectedBook.value.description = await getBookDescriptionFromAI (currentAuthor.surName, currentAuthor.givenName, selectedBook.value.title);
|
|
166
|
+
if (selectedBook.value.description && setBookChanged)
|
|
154
167
|
setBookChanged();
|
|
155
168
|
}
|
|
156
169
|
}
|
|
@@ -168,10 +181,10 @@
|
|
|
168
181
|
const rc = await booksService.deleteBook (id);
|
|
169
182
|
if (!rc)
|
|
170
183
|
alert (`DeleteBook ${id}- error`);
|
|
171
|
-
if (rc &&
|
|
172
|
-
const idx =
|
|
184
|
+
if (rc && currentAuthor.books) {
|
|
185
|
+
const idx = currentAuthor.books.findIndex ((x) => x.id == id);
|
|
173
186
|
if (idx >= 0)
|
|
174
|
-
|
|
187
|
+
currentAuthor.books.splice (idx, 1);
|
|
175
188
|
}
|
|
176
189
|
}
|
|
177
190
|
async function saveBook(book: IBook) {
|
|
@@ -181,9 +194,9 @@
|
|
|
181
194
|
const id = await booksService.addBook (book);
|
|
182
195
|
if (id < 0)
|
|
183
196
|
alert (`AddBook - error ${id}`);
|
|
184
|
-
if (id > 0 &&
|
|
197
|
+
if (id > 0 && currentAuthor.books) {
|
|
185
198
|
book.id = id;
|
|
186
|
-
|
|
199
|
+
currentAuthor.books.splice (0, 0, book);
|
|
187
200
|
showAddBookLine.value = false;
|
|
188
201
|
}
|
|
189
202
|
}
|
|
@@ -257,14 +270,14 @@
|
|
|
257
270
|
const prompt = `Geburtstag, Sterbetag, Geburtsland von ${givenName} ${surName} ?`;
|
|
258
271
|
const result = await openAI.completeJson(prompt, schema) as any;
|
|
259
272
|
if (result) {
|
|
260
|
-
if (!
|
|
261
|
-
|
|
262
|
-
if (!
|
|
263
|
-
|
|
264
|
-
if (!
|
|
265
|
-
|
|
266
|
-
if (!
|
|
267
|
-
|
|
273
|
+
if (!currentAuthor.yearOfBirth)
|
|
274
|
+
currentAuthor.yearOfBirth = getYear(result.geburtstag);
|
|
275
|
+
if (!currentAuthor.yearOfDeath)
|
|
276
|
+
currentAuthor.yearOfDeath = result.sterbetag ? getYear(result.sterbetag) : undefined;
|
|
277
|
+
if (!currentAuthor.category)
|
|
278
|
+
currentAuthor.category = booksService.categories[0];
|
|
279
|
+
if (!currentAuthor.country)
|
|
280
|
+
currentAuthor.country = result.geburtsland;
|
|
268
281
|
return true;
|
|
269
282
|
}
|
|
270
283
|
else {
|
|
@@ -342,7 +355,10 @@
|
|
|
342
355
|
<v-defaults-provider :defaults="{'VBtn':{'size':'large','variant':'flat','class':'bg-office'}}">
|
|
343
356
|
<v-row v-if="isMobile" dense align="center">
|
|
344
357
|
<v-col cols="6">Name</v-col>
|
|
345
|
-
<v-col cols="
|
|
358
|
+
<v-col cols="5">Vorname</v-col>
|
|
359
|
+
<v-col cols="1">
|
|
360
|
+
<v-btn icon="$search" @click="search"></v-btn>
|
|
361
|
+
</v-col>
|
|
346
362
|
</v-row>
|
|
347
363
|
<v-row v-else dense align="center">
|
|
348
364
|
<v-col cols="2">Name</v-col>
|
|
@@ -351,38 +367,41 @@
|
|
|
351
367
|
<v-col cols="1">Bis</v-col>
|
|
352
368
|
<v-col cols="2">Kategorie</v-col>
|
|
353
369
|
<v-col cols="2">Land</v-col>
|
|
370
|
+
<v-col cols="2">
|
|
371
|
+
<v-btn prepend-icon="$search" @click="search">Search</v-btn>
|
|
372
|
+
</v-col>
|
|
354
373
|
</v-row>
|
|
355
374
|
<v-row v-if="isMobile" dense align="center">
|
|
356
375
|
<v-col cols="6">
|
|
357
|
-
<v-combobox v-model="
|
|
376
|
+
<v-combobox v-model="selectedAuthor" :items="authors" item-value="id" item-title="sN" hide-details density="compact" single-line @update:modelValue="authorNameChanged"></v-combobox>
|
|
358
377
|
</v-col>
|
|
359
378
|
<v-col cols="6">
|
|
360
|
-
<v-text-field v-model="
|
|
379
|
+
<v-text-field v-model="currentAuthor.givenName" hide-details density="compact" @update:modelValue="fieldChanged" @update:focused="givenNameFocused"></v-text-field>
|
|
361
380
|
</v-col>
|
|
362
381
|
</v-row>
|
|
363
382
|
<v-row v-else dense align="center">
|
|
364
383
|
<v-col cols="2">
|
|
365
|
-
<v-combobox v-model="
|
|
384
|
+
<v-combobox v-model="selectedAuthor" :items="authors" item-value="id" item-title="sN" hide-details density="compact" single-line @update:modelValue="authorNameChanged"></v-combobox>
|
|
366
385
|
</v-col>
|
|
367
386
|
<v-col cols="2">
|
|
368
|
-
<v-text-field v-model="
|
|
387
|
+
<v-text-field v-model="currentAuthor.givenName" hide-details density="compact" @update:modelValue="fieldChanged" @update:focused="givenNameFocused"></v-text-field>
|
|
369
388
|
</v-col>
|
|
370
389
|
<v-col cols="1">
|
|
371
|
-
<v-text-field v-model="
|
|
390
|
+
<v-text-field v-model="currentAuthor.yearOfBirth" hide-details density="compact" type="number" @update:modelValue="fieldChanged"></v-text-field>
|
|
372
391
|
</v-col>
|
|
373
392
|
<v-col cols="1">
|
|
374
|
-
<v-text-field v-model="
|
|
393
|
+
<v-text-field v-model="currentAuthor.yearOfDeath" hide-details density="compact" type="number" @update:modelValue="fieldChanged"></v-text-field>
|
|
375
394
|
</v-col>
|
|
376
395
|
<v-col cols="2">
|
|
377
|
-
<v-select v-model="
|
|
396
|
+
<v-select v-model="currentAuthor.category" :items="booksService.categories" hide-details density="compact" single-line @update:modelValue="fieldChanged"></v-select>
|
|
378
397
|
</v-col>
|
|
379
398
|
<v-col cols="2">
|
|
380
|
-
<v-text-field v-model="
|
|
399
|
+
<v-text-field v-model="currentAuthor.country" hide-details density="compact" @update:modelValue="fieldChanged"></v-text-field>
|
|
381
400
|
</v-col>
|
|
382
401
|
<v-col cols="2">
|
|
383
402
|
<v-btn v-if="mustAddAuthor" @click="addAuthor" :disabled="readonly" prepend-icon="$plus">AUTHOR</v-btn>
|
|
384
403
|
<v-btn v-if="mustUpdateAuthor" @click="updateAuthor" :disabled="readonly" icon="$save"></v-btn>
|
|
385
|
-
<v-btn v-if="
|
|
404
|
+
<v-btn v-if="currentAuthor.id > 0" @click="deleteAuthor" :disabled="readonly" icon="$delete"></v-btn>
|
|
386
405
|
</v-col>
|
|
387
406
|
</v-row>
|
|
388
407
|
<v-divider></v-divider>
|
|
@@ -395,16 +414,16 @@
|
|
|
395
414
|
<v-col cols="1">JAHR</v-col>
|
|
396
415
|
<v-col cols="1">RATING</v-col>
|
|
397
416
|
<v-col cols="2">STATUS</v-col>
|
|
398
|
-
<v-col v-if="
|
|
417
|
+
<v-col v-if="currentAuthor.id" cols="2">
|
|
399
418
|
<v-btn v-if="!showAddBookLine" @click="addNewBook" :disabled="readonly" prepend-icon="$plus">BOOK</v-btn>
|
|
400
419
|
<v-btn v-if="showAddBookLine" @click="cancelAddNewBook" :disabled="readonly" icon="$cancel"></v-btn>
|
|
401
420
|
</v-col>
|
|
402
421
|
</v-row>
|
|
403
|
-
<book-line v-if="showAddBookLine" :book="newBook" :flags="
|
|
404
|
-
<book-line v-for="book in
|
|
405
|
-
<v-textarea v-if="
|
|
422
|
+
<book-line v-if="showAddBookLine" :book="newBook" :flags="booksService.flags" :add="true" :allbooks="allBooks" :readonly="readonly" :ismobile="isMobile" @selectbook="selectBook" @deletebook="deleteBook" @savebook="saveBook"></book-line>
|
|
423
|
+
<book-line v-for="book in currentAuthor.books" :key="book.id" :book="book" :flags="booksService.flags" :readonly="readonly" :selected="selectedBook == book" :ismobile="isMobile" @selectbook="selectBook" @deletebook="deleteBook" @savebook="saveBook"></book-line>
|
|
424
|
+
<v-textarea v-if="showSelectedBook" clearable auto-grow variant="outlined" label="Beschreibung" :disabled="isMobile" class="pt-2" v-model="selectedBook.description" @update:modelValue="descriptionChanged">
|
|
406
425
|
</v-textarea>
|
|
407
|
-
<v-textarea v-if="
|
|
426
|
+
<v-textarea v-if="showSelectedBook" clearable auto-grow variant="outlined" label="Kommentar" :disabled="isMobile" v-model="selectedBook.comment" @update:modelValue="descriptionChanged">
|
|
408
427
|
</v-textarea>
|
|
409
428
|
</v-defaults-provider>
|
|
410
429
|
</v-container>
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { inject, ref, reactive, onMounted, onUnmounted, computed, StyleValue } from 'vue';
|
|
3
3
|
import { IAppState, appStateSymbol, getOpenAISymbol, IOpenAIService, ICompleteData, EScope, EDevice } from '@christianriedl/utils';
|
|
4
|
-
import { BooksService, getBooksSymbol, IAuthorShort, IAuthor,
|
|
4
|
+
import { BooksService, getBooksSymbol, IAuthorShort, IAuthor, IFullBook } from '@christianriedl/media';
|
|
5
5
|
import BookSearchLine from '../components/BookSearchLine.vue';
|
|
6
6
|
|
|
7
7
|
const appState = inject(appStateSymbol)!;
|
|
8
8
|
const getBooksService = inject(getBooksSymbol)!;
|
|
9
9
|
const booksService = getBooksService() as BooksService;
|
|
10
10
|
const authors = reactive<IAuthorShort[]>([]);
|
|
11
|
-
const books = ref<
|
|
12
|
-
const
|
|
11
|
+
const books = ref<IFullBook[]>([]);
|
|
12
|
+
const selectedBook = ref<IFullBook|null>(null);
|
|
13
|
+
const selected = ref<IAuthorShort>({ id:0, gN: "", sN: "" });
|
|
13
14
|
const title = ref("");
|
|
14
15
|
const rating = ref(0);
|
|
15
16
|
const flags = ref("");
|
|
@@ -25,54 +26,63 @@
|
|
|
25
26
|
}
|
|
26
27
|
}
|
|
27
28
|
async function search() {
|
|
28
|
-
|
|
29
|
+
const sel = selected.value;
|
|
30
|
+
if (sel) {
|
|
31
|
+
books.value = await booksService.getFullBooks(sel.sN, sel.gN, title.value, flags.value, rating.value);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function select (book: IFullBook) {
|
|
35
|
+
selectedBook.value = book;
|
|
36
|
+
booksService.selectedAuthorId = book.authorId;
|
|
37
|
+
booksService.selectedBookId = book.bookId;
|
|
29
38
|
}
|
|
30
39
|
</script>
|
|
31
40
|
|
|
32
41
|
<template>
|
|
33
42
|
<v-container fluid class="bg-office" :style="heightStyle">
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
43
|
+
<v-defaults-provider :defaults="{'VBtn':{'size':'large','variant':'flat','class':'bg-office'}}">
|
|
44
|
+
<v-row v-if="isMobile" dense align="center">
|
|
45
|
+
<v-col cols="6">
|
|
46
|
+
<v-select v-model="selected" :items="authors" label="Author" return-object item-value="id" item-title="sN" hide-details density="compact" single-line ></v-select>
|
|
47
|
+
</v-col>
|
|
48
|
+
<v-col cols="6">
|
|
49
|
+
<p>{{selected.gN}}</p>
|
|
50
|
+
</v-col>
|
|
51
|
+
<v-col cols="6">
|
|
52
|
+
<v-text-field label="Titel" v-model="title" hide-details density="compact"></v-text-field>
|
|
53
|
+
</v-col>
|
|
54
|
+
<v-col cols="2">
|
|
55
|
+
<v-select label="Status" v-model="flags" :items="booksService.flags" hide-details density="compact" single-line ></v-select>
|
|
56
|
+
</v-col>
|
|
57
|
+
<v-col cols="2">
|
|
58
|
+
<v-rating label="Rating" hover clearable :length="5" :size="16" v-model="rating" active-color="primary" />
|
|
59
|
+
</v-col>
|
|
60
|
+
<v-col cols="2">
|
|
61
|
+
<v-btn @click="search" icon="$search"></v-btn>
|
|
62
|
+
</v-col>
|
|
63
|
+
</v-row>
|
|
64
|
+
<v-row v-else dense align="center">
|
|
65
|
+
<v-col cols="2">
|
|
66
|
+
<v-select v-model="selected" :items="authors" label="Author" return-object item-value="id" item-title="sN" hide-details density="compact" single-line ></v-select>
|
|
67
|
+
</v-col>
|
|
68
|
+
<v-col cols="2">
|
|
69
|
+
<p>{{selected.gN}}</p>
|
|
70
|
+
</v-col>
|
|
71
|
+
<v-col cols="3">
|
|
72
|
+
<v-text-field label="Titel" v-model="title" hide-details density="compact"></v-text-field>
|
|
73
|
+
</v-col>
|
|
74
|
+
<v-col cols="2">
|
|
75
|
+
<v-select label="Status" v-model="flags" :items="booksService.flags" hide-details density="compact" single-line ></v-select>
|
|
76
|
+
</v-col>
|
|
77
|
+
<v-col cols="1">
|
|
78
|
+
<v-rating label="Rating" hover clearable :length="5" :size="32" v-model="rating" active-color="primary" />
|
|
79
|
+
</v-col>
|
|
80
|
+
<v-col cols="2">
|
|
81
|
+
<v-btn @click="search" prepend-icon="$search">Search</v-btn>
|
|
82
|
+
</v-col>
|
|
83
|
+
</v-row>
|
|
84
|
+
<v-divider></v-divider>
|
|
85
|
+
<book-search-line v-for="book in books" :key="book.bookId" :book="book" :selected="selectedBook == book" :ismobile="isMobile" @selectbook="select(book)"></book-search-line>
|
|
86
|
+
</v-defaults-provider>
|
|
77
87
|
</v-container>
|
|
78
88
|
</template>
|