@christianriedl/media 1.0.183 → 1.0.185

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@christianriedl/media",
3
- "version": "1.0.183",
3
+ "version": "1.0.185",
4
4
  "description": "RIC media interfaces",
5
5
 
6
6
  "main": "dist/index.js",
@@ -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,6 +11,10 @@
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);
@@ -53,7 +57,7 @@
53
57
  </script>
54
58
 
55
59
  <template>
56
- <v-row v-if="props.ismobile" dense align="center" :class="cls" @click="onSelect" >
60
+ <v-row v-if="props.ismobile" dense align="center" :class="classObject" @click="onSelect" >
57
61
  <v-col cols="9" >
58
62
  <v-text-field v-model="book.title" disabled hide-details density="compact" ></v-text-field>
59
63
  </v-col>
@@ -61,7 +65,7 @@
61
65
  <v-text-field v-model="book.year" disabled hide-details density="compact" ></v-text-field>
62
66
  </v-col>
63
67
  </v-row>
64
- <v-row v-else dense align="center" :class="cls" @click="onSelect" >
68
+ <v-row v-else dense align="center" :class="classObject" @click="onSelect" >
65
69
  <v-col v-if="props.add" cols="6" >
66
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>
67
71
  </v-col>
@@ -78,8 +82,9 @@
78
82
  <v-select v-model="flags" :items="props.flags" multiple hide-details density="compact" single-line @update:modelValue="flagsChanged"></v-select>
79
83
  </v-col>
80
84
  <v-col cols="2">
81
- <v-btn v-if="showSave" icon="$save" :disabled="props.readonly" @click="onSave"></v-btn>
82
- <v-btn v-if="showDelete" icon="$delete" :disabled="props.readonly" @click="onDelete"></v-btn>
85
+ <v-btn v-if="showSave" icon="$save" :class="classObject" :disabled="props.readonly" @click="onSave"></v-btn>
86
+ <v-btn v-if="showDelete" icon="$delete" :class="classObject" :disabled="props.readonly" @click="onDelete"></v-btn>
83
87
  </v-col>
84
88
  </v-row>
89
+ <v-divider></v-divider>
85
90
  </template>
@@ -1,31 +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 }>();
4
5
  const emits = defineEmits<{
5
6
  (e: 'selectbook'): void
6
7
  }>();
7
8
  const book = props.book;
8
-
9
+ const classObject = computed(() => ({
10
+ 'bg-secondary': props.selected
11
+ }));
9
12
  function onSelect () {
10
13
  emits ("selectbook");
11
14
  }
12
15
  </script>
13
16
 
14
17
  <template>
15
- <v-row v-if="props.ismobile" dense align="center" class="bg-office" @click="onSelect">
18
+ <v-row v-if="props.ismobile" dense align="center" :class="classObject" @click="onSelect">
16
19
  <v-col cols="12" >
17
20
  <p class="font-weight-bold">{{book.givenName + ' ' + book.surName}}</p>
18
21
  </v-col>
19
22
  <v-col cols="12" >
20
- <p class="font-weight-medium">{{book.title}}</p>
23
+ <p>{{book.title}}</p>
21
24
  </v-col>
22
25
  </v-row>
23
- <v-row v-else dense align="center" class="bg-office" @click="onSelect >
24
- <v-col cols="6" >
26
+ <v-row v-else dense align="center" :class="classObject" @click="onSelect" >
27
+ <v-col cols="4" >
25
28
  <p class="font-weight-bold">{{book.givenName + ' ' + book.surName}}</p>
26
29
  </v-col>
27
- <v-col cols="6" >
28
- <p class="font-weight-medium">{{book.title}}</p>
30
+ <v-col cols="8" >
31
+ <p>{{book.title}}</p>
29
32
  </v-col>
30
33
  </v-row>
34
+ <v-divider></v-divider>
31
35
  </template>
@@ -12,16 +12,16 @@
12
12
  const getOpenAI = inject(getOpenAISymbol)!;
13
13
  const openAI = getOpenAI();
14
14
  const authors = reactive<IAuthorShort[]>([]);
15
- const selected = ref<IAuthorShort | string | undefined>();
16
- const author = reactive<IAuthor>({ id: 0, surName: "", givenName: "", yearOfBirth: 0, books: [] });
17
- const currentBook = ref<IBook>({ id: 0, authorId: 0, title: ""});
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: ""});
18
18
  let newBook: IBook;
19
19
  const allBooks = ref<IBook[]>([]);
20
20
  const lastAllBooksId = ref(0);
21
21
  const mustAddAuthor = ref(false);
22
22
  const mustUpdateAuthor = ref(false);
23
23
  const showAddBookLine = ref(false);
24
- const showCurrentBook = ref(false);
24
+ const showSelectedBook = ref(false);
25
25
  let setBookChanged: () => void;
26
26
  let readonly = !(appState.scopes & EScope.Admin);
27
27
  let isMobile = appState.isMobile && (appState.device != EDevice.iPad);
@@ -34,65 +34,66 @@
34
34
  if (authorsShort) {
35
35
  authors.splice(0, authors.length, ...authorsShort);
36
36
  }
37
- �f (booksService.selectedAuthorId) {
37
+ if (booksService.selectedAuthorId) {
38
+ selectedAuthor.value = authors.find ((x) => x.id == booksService.selectedAuthorId);
38
39
  getCurrentAuthor (booksService.selectedAuthorId, true)
39
40
  booksService.selectedAuthorId = 0;
40
41
  booksService.selectedBookId = 0;
41
42
  }
42
43
  }
43
44
  async function addAuthor() {
44
- if (!checkAuthor(author))
45
+ if (!checkAuthor(currentAuthor))
45
46
  return;
46
- const id = await booksService.addAuthor(author);
47
+ const id = await booksService.addAuthor(currentAuthor);
47
48
  if (id > 0) {
48
- author.id = id;
49
+ currentAuthor.id = id;
49
50
  mustAddAuthor.value = false;
50
51
  }
51
52
  else
52
53
  alert (`AddAuthor - error ${id}`);
53
54
  }
54
55
  async function updateAuthor() {
55
- if (!checkAuthor(author))
56
+ if (!checkAuthor(currentAuthor))
56
57
  return;
57
- const rc = await booksService.updateAuthor(author);
58
+ const rc = await booksService.updateAuthor(currentAuthor);
58
59
  if (rc)
59
60
  mustUpdateAuthor.value = false;
60
61
  else
61
62
  alert ('UpdateAuthor - error');
62
63
  }
63
64
  async function deleteAuthor() {
64
- if (!window.confirm(`Willst du ${author.surName} wirklich l�schen ?`))
65
+ if (!window.confirm(`Willst du ${currentAuthor.surName} wirklich l�schen ?`))
65
66
  return;
66
- const rc = await booksService.deleteAuthor(author.id);
67
+ const rc = await booksService.deleteAuthor(currentAuthor.id);
67
68
  if (rc) {
68
69
  mustUpdateAuthor.value = false;
69
70
  initAuthor ("");
70
71
  }
71
72
  else
72
- alert (`DeleteAuthor ${author.id} - error`);
73
+ alert (`DeleteAuthor ${currentAuthor.id} - error`);
73
74
  }
74
75
  function initAuthor(surName: string) {
75
- author.id = 0;
76
- author.surName = surName;
77
- author.givenName = "";
78
- author.yearOfBirth = 0;
79
- author.yearOfDeath = undefined;
80
- author.category = undefined;
81
- author.country = undefined;
82
- author.books = [];
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 = [];
83
84
  }
84
85
  async function getCurrentAuthor (id: number, withBooks: boolean) : Promise<boolean> {
85
86
  const authors = await booksService.getAuthors(undefined, undefined, withBooks, id);
86
87
  if (authors && authors.length > 0) {
87
88
  const a = authors[0];
88
- author.id = a.id;
89
- author.surName = a.surName;
90
- author.givenName = a.givenName;
91
- author.yearOfBirth = a.yearOfBirth;
92
- author.yearOfDeath = a.yearOfDeath;
93
- author.category = a.category;
94
- author.country = a.country;
95
- author.books = a.books ? a.books : [];
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 : [];
96
97
  return true;
97
98
  }
98
99
  else {
@@ -101,14 +102,14 @@
101
102
  }
102
103
  }
103
104
  async function authorNameChanged(arg: IAuthorShort | string) {
104
- showCurrentBook.value = false;
105
- currentBook.value = { id: 0, authorId: 0, title: ""};
105
+ showSelectedBook.value = false;
106
+ selectedBook.value = { id: 0, authorId: 0, title: ""};
106
107
  mustAddAuthor.value = typeof arg == 'string';
107
108
  if (!mustAddAuthor.value) {
108
109
  const authorShort = arg as IAuthorShort;
109
110
  const rc = await getCurrentAuthor (authorShort.id, true);
110
- if (rc && !author.country) {
111
- const rc = await getAuthorDataFromAI (author.surName, author.givenName);
111
+ if (rc && !currentAuthor.country) {
112
+ const rc = await getAuthorDataFromAI (currentAuthor.surName, currentAuthor.givenName);
112
113
  if (rc)
113
114
  mustUpdateAuthor.value = true;
114
115
  }
@@ -125,7 +126,7 @@
125
126
  }
126
127
  async function givenNameFocused(focus: boolean) {
127
128
  if (!focus && mustAddAuthor.value) {
128
- await getAuthorDataFromAI(author.surName, author.givenName);
129
+ await getAuthorDataFromAI(currentAuthor.surName, currentAuthor.givenName);
129
130
  }
130
131
  }
131
132
  function search () {
@@ -134,35 +135,35 @@
134
135
  router.push({ path: 'booksearch' });
135
136
  }
136
137
  async function addNewBook() {
137
- if (lastAllBooksId.value != author.id) {
138
- allBooks.value = await getAuthorBooksFromAI (author.surName, author.givenName, author.id);
139
- lastAllBooksId.value = author.id;
138
+ if (lastAllBooksId.value != currentAuthor.id) {
139
+ allBooks.value = await getAuthorBooksFromAI (currentAuthor.surName, currentAuthor.givenName, currentAuthor.id);
140
+ lastAllBooksId.value = currentAuthor.id;
140
141
  }
141
- currentBook.value = { id: 0, authorId: 0, title: ""};
142
- newBook = reactive<IBook>({ id: 0, authorId: author.id, title: "", rating: 0 });
142
+ selectedBook.value = { id: 0, authorId: 0, title: ""};
143
+ newBook = reactive<IBook>({ id: 0, authorId: currentAuthor.id, title: "", rating: 0 });
143
144
  showAddBookLine.value = true;
144
145
  }
145
146
  function cancelAddNewBook() {
146
147
  showAddBookLine.value = false;
147
148
  }
148
149
  async function selectBook(id: number, func: () => void) {
149
- if (currentBook.value.id == id) {
150
+ if (selectedBook.value.id == id) {
150
151
  return;
151
152
  }
152
153
  setBookChanged = func;
153
- if (author.books) {
154
- currentBook.value = author.books.find (x => x.id == id) as IBook;
155
- if (currentBook.value && !currentBook.value.description && !currentBook.value.comment) {
156
- const books = await booksService.getBooks (author.id, currentBook.value.id);
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);
157
158
  if (books && books.length > 0) {
158
- currentBook.value.description = books[0].description;
159
- currentBook.value.comment = books[0].comment;
159
+ selectedBook.value.description = books[0].description;
160
+ selectedBook.value.comment = books[0].comment;
160
161
  }
161
- showCurrentBook.value = true;
162
- if (!currentBook.value.description) {
163
- currentBook.value.description ="WAITING..."
164
- currentBook.value.description = await getBookDescriptionFromAI (author.surName, author.givenName, currentBook.value.title);
165
- if (currentBook.value.description && setBookChanged)
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)
166
167
  setBookChanged();
167
168
  }
168
169
  }
@@ -180,10 +181,10 @@
180
181
  const rc = await booksService.deleteBook (id);
181
182
  if (!rc)
182
183
  alert (`DeleteBook ${id}- error`);
183
- if (rc && author.books) {
184
- const idx = author.books.findIndex ((x) => x.id == id);
184
+ if (rc && currentAuthor.books) {
185
+ const idx = currentAuthor.books.findIndex ((x) => x.id == id);
185
186
  if (idx >= 0)
186
- author.books.splice (idx, 1);
187
+ currentAuthor.books.splice (idx, 1);
187
188
  }
188
189
  }
189
190
  async function saveBook(book: IBook) {
@@ -193,9 +194,9 @@
193
194
  const id = await booksService.addBook (book);
194
195
  if (id < 0)
195
196
  alert (`AddBook - error ${id}`);
196
- if (id > 0 && author.books) {
197
+ if (id > 0 && currentAuthor.books) {
197
198
  book.id = id;
198
- author.books.splice (0, 0, book);
199
+ currentAuthor.books.splice (0, 0, book);
199
200
  showAddBookLine.value = false;
200
201
  }
201
202
  }
@@ -269,14 +270,14 @@
269
270
  const prompt = `Geburtstag, Sterbetag, Geburtsland von ${givenName} ${surName} ?`;
270
271
  const result = await openAI.completeJson(prompt, schema) as any;
271
272
  if (result) {
272
- if (!author.yearOfBirth)
273
- author.yearOfBirth = getYear(result.geburtstag);
274
- if (!author.yearOfDeath)
275
- author.yearOfDeath = result.sterbetag ? getYear(result.sterbetag) : undefined;
276
- if (!author.category)
277
- author.category = booksService.categories[0];
278
- if (!author.country)
279
- author.country = result.geburtsland;
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;
280
281
  return true;
281
282
  }
282
283
  else {
@@ -350,80 +351,80 @@
350
351
  </script>
351
352
 
352
353
  <template>
353
- <v-container fluid class="bg-office" :style="heightStyle">
354
- <v-defaults-provider :defaults="{'VBtn':{'size':'large','variant':'flat','class':'bg-office'}}">
355
- <v-row v-if="isMobile" dense align="center">
356
- <v-col cols="6">Name</v-col>
357
- <v-col cols="5">Vorname</v-col>
358
- <v-col cols="1">
359
- <v-btn icon="$search" @click="search"></v-btn>
360
- </v-col>
361
- </v-row>
362
- <v-row v-else dense align="center">
363
- <v-col cols="2">Name</v-col>
364
- <v-col cols="2">Vorname</v-col>
365
- <v-col cols="1">Von</v-col>
366
- <v-col cols="1">Bis</v-col>
367
- <v-col cols="2">Kategorie</v-col>
368
- <v-col cols="2">Land</v-col>
369
- <v-col cols="2">
370
- <v-btn prepend-icon="$search" @click="search">Search</v-btn>
371
- </v-col>
372
- </v-row>
373
- <v-row v-if="isMobile" dense align="center">
374
- <v-col cols="6">
375
- <v-combobox v-model="selected" :items="authors" item-value="id" item-title="sN" hide-details density="compact" single-line @update:modelValue="authorNameChanged"></v-combobox>
376
- </v-col>
377
- <v-col cols="6">
378
- <v-text-field v-model="author.givenName" hide-details density="compact" @update:modelValue="fieldChanged" @update:focused="givenNameFocused"></v-text-field>
379
- </v-col>
380
- </v-row>
381
- <v-row v-else dense align="center">
382
- <v-col cols="2">
383
- <v-combobox v-model="selected" :items="authors" item-value="id" item-title="sN" hide-details density="compact" single-line @update:modelValue="authorNameChanged"></v-combobox>
384
- </v-col>
385
- <v-col cols="2">
386
- <v-text-field v-model="author.givenName" hide-details density="compact" @update:modelValue="fieldChanged" @update:focused="givenNameFocused"></v-text-field>
387
- </v-col>
388
- <v-col cols="1">
389
- <v-text-field v-model="author.yearOfBirth" hide-details density="compact" type="number" @update:modelValue="fieldChanged"></v-text-field>
390
- </v-col>
391
- <v-col cols="1">
392
- <v-text-field v-model="author.yearOfDeath" hide-details density="compact" type="number" @update:modelValue="fieldChanged"></v-text-field>
393
- </v-col>
394
- <v-col cols="2">
395
- <v-select v-model="author.category" :items="booksService.categories" hide-details density="compact" single-line @update:modelValue="fieldChanged"></v-select>
396
- </v-col>
397
- <v-col cols="2">
398
- <v-text-field v-model="author.country" hide-details density="compact" @update:modelValue="fieldChanged"></v-text-field>
399
- </v-col>
400
- <v-col cols="2">
401
- <v-btn v-if="mustAddAuthor" @click="addAuthor" :disabled="readonly" prepend-icon="$plus">AUTHOR</v-btn>
402
- <v-btn v-if="mustUpdateAuthor" @click="updateAuthor" :disabled="readonly" icon="$save"></v-btn>
403
- <v-btn v-if="author.id > 0" @click="deleteAuthor" :disabled="readonly" icon="$delete"></v-btn>
404
- </v-col>
405
- </v-row>
406
- <v-divider></v-divider>
407
- <v-row v-if="isMobile" dense align="center">
408
- <v-col cols="9">TITEL</v-col>
409
- <v-col cols="3">JAHR</v-col>
410
- </v-row>
411
- <v-row v-else dense align="center">
412
- <v-col cols="6">TITEL</v-col>
413
- <v-col cols="1">JAHR</v-col>
414
- <v-col cols="1">RATING</v-col>
415
- <v-col cols="2">STATUS</v-col>
416
- <v-col v-if="author.id" cols="2">
417
- <v-btn v-if="!showAddBookLine" @click="addNewBook" :disabled="readonly" prepend-icon="$plus">BOOK</v-btn>
418
- <v-btn v-if="showAddBookLine" @click="cancelAddNewBook" :disabled="readonly" icon="$cancel"></v-btn>
419
- </v-col>
420
- </v-row>
421
- <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>
422
- <book-line v-for="book in author.books" :key="book.id" :book="book" :flags="booksService.flags" :readonly="readonly" :ismobile="isMobile" @selectbook="selectBook" @deletebook="deleteBook" @savebook="saveBook"></book-line>
423
- <v-textarea v-if="showCurrentBook" clearable auto-grow variant="outlined" label="Beschreibung" :disabled="isMobile" class="pt-2" v-model="currentBook.description" @update:modelValue="descriptionChanged">
424
- </v-textarea>
425
- <v-textarea v-if="showCurrentBook" clearable auto-grow variant="outlined" label="Kommentar" :disabled="isMobile" v-model="currentBook.comment" @update:modelValue="descriptionChanged">
426
- </v-textarea>
354
+ <v-container fluid :style="heightStyle">
355
+ <v-defaults-provider :defaults="{'VBtn':{'size':'large','variant':'flat'}}">
356
+ <v-row v-if="isMobile" dense align="center" class="bg-office" >
357
+ <v-col cols="6">Name</v-col>
358
+ <v-col cols="5">Vorname</v-col>
359
+ <v-col cols="1">
360
+ <v-btn icon="$search" class="bg-office" @click="search"></v-btn>
361
+ </v-col>
362
+ </v-row>
363
+ <v-row v-else dense align="center" class="bg-office" >
364
+ <v-col cols="2">Name</v-col>
365
+ <v-col cols="2">Vorname</v-col>
366
+ <v-col cols="1">Von</v-col>
367
+ <v-col cols="1">Bis</v-col>
368
+ <v-col cols="2">Kategorie</v-col>
369
+ <v-col cols="2">Land</v-col>
370
+ <v-col cols="2">
371
+ <v-btn prepend-icon="$search" class="bg-office" @click="search">Search</v-btn>
372
+ </v-col>
373
+ </v-row>
374
+ <v-row v-if="isMobile" dense align="center" class="bg-office" >
375
+ <v-col cols="6">
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>
377
+ </v-col>
378
+ <v-col cols="6">
379
+ <v-text-field v-model="currentAuthor.givenName" hide-details density="compact" @update:modelValue="fieldChanged" @update:focused="givenNameFocused"></v-text-field>
380
+ </v-col>
381
+ </v-row>
382
+ <v-row v-else dense align="center" class="bg-office" >
383
+ <v-col cols="2">
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>
385
+ </v-col>
386
+ <v-col cols="2">
387
+ <v-text-field v-model="currentAuthor.givenName" hide-details density="compact" @update:modelValue="fieldChanged" @update:focused="givenNameFocused"></v-text-field>
388
+ </v-col>
389
+ <v-col cols="1">
390
+ <v-text-field v-model="currentAuthor.yearOfBirth" hide-details density="compact" type="number" @update:modelValue="fieldChanged"></v-text-field>
391
+ </v-col>
392
+ <v-col cols="1">
393
+ <v-text-field v-model="currentAuthor.yearOfDeath" hide-details density="compact" type="number" @update:modelValue="fieldChanged"></v-text-field>
394
+ </v-col>
395
+ <v-col cols="2">
396
+ <v-select v-model="currentAuthor.category" :items="booksService.categories" hide-details density="compact" single-line @update:modelValue="fieldChanged"></v-select>
397
+ </v-col>
398
+ <v-col cols="2">
399
+ <v-text-field v-model="currentAuthor.country" hide-details density="compact" @update:modelValue="fieldChanged"></v-text-field>
400
+ </v-col>
401
+ <v-col cols="2">
402
+ <v-btn v-if="mustAddAuthor" class="bg-office" @click="addAuthor" :disabled="readonly" prepend-icon="$plus">AUTHOR</v-btn>
403
+ <v-btn v-if="mustUpdateAuthor" class="bg-office" @click="updateAuthor" :disabled="readonly" icon="$save"></v-btn>
404
+ <v-btn v-if="currentAuthor.id > 0" class="bg-office" @click="deleteAuthor" :disabled="readonly" icon="$delete"></v-btn>
405
+ </v-col>
406
+ </v-row>
407
+ <v-divider></v-divider>
408
+ <v-row v-if="isMobile" dense align="center" class="bg-office" >
409
+ <v-col cols="9">TITEL</v-col>
410
+ <v-col cols="3">JAHR</v-col>
411
+ </v-row>
412
+ <v-row v-else dense align="center" class="bg-office" >
413
+ <v-col cols="6">TITEL</v-col>
414
+ <v-col cols="1">JAHR</v-col>
415
+ <v-col cols="1">RATING</v-col>
416
+ <v-col cols="2">STATUS</v-col>
417
+ <v-col v-if="currentAuthor.id" cols="2">
418
+ <v-btn v-if="!showAddBookLine" class="bg-office" @click="addNewBook" :disabled="readonly" prepend-icon="$plus">BOOK</v-btn>
419
+ <v-btn v-if="showAddBookLine" class="bg-office" @click="cancelAddNewBook" :disabled="readonly" icon="$cancel"></v-btn>
420
+ </v-col>
421
+ </v-row>
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="bg-office pt-2" v-model="selectedBook.description" @update:modelValue="descriptionChanged">
425
+ </v-textarea>
426
+ <v-textarea v-if="showSelectedBook" clearable auto-grow variant="outlined" label="Kommentar" :disabled="isMobile" class="bg-office" v-model="selectedBook.comment" @update:modelValue="descriptionChanged">
427
+ </v-textarea>
427
428
  </v-defaults-provider>
428
429
  </v-container>
429
430
  </template>
@@ -9,6 +9,7 @@
9
9
  const booksService = getBooksService() as BooksService;
10
10
  const authors = reactive<IAuthorShort[]>([]);
11
11
  const books = ref<IFullBook[]>([]);
12
+ const selectedBook = ref<IFullBook|null>(null);
12
13
  const selected = ref<IAuthorShort>({ id:0, gN: "", sN: "" });
13
14
  const title = ref("");
14
15
  const rating = ref(0);
@@ -31,6 +32,7 @@
31
32
  }
32
33
  }
33
34
  function select (book: IFullBook) {
35
+ selectedBook.value = book;
34
36
  booksService.selectedAuthorId = book.authorId;
35
37
  booksService.selectedBookId = book.bookId;
36
38
  }
@@ -80,7 +82,7 @@
80
82
  </v-col>
81
83
  </v-row>
82
84
  <v-divider></v-divider>
83
- <book-search-line v-for="book in books" :key="book.bookId" :book="book" :ismobile="isMobile" @selectbook="select(book)"></book-search-line>
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>
84
86
  </v-defaults-provider>
85
87
  </v-container>
86
88
  </template>