@christianriedl/media 1.0.183 → 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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@christianriedl/media",
3
- "version": "1.0.183",
3
+ "version": "1.0.184",
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>
@@ -82,4 +86,5 @@
82
86
  <v-btn v-if="showDelete" icon="$delete" :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 {
@@ -372,35 +373,35 @@
372
373
  </v-row>
373
374
  <v-row v-if="isMobile" dense align="center">
374
375
  <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-combobox v-model="selectedAuthor" :items="authors" item-value="id" item-title="sN" hide-details density="compact" single-line @update:modelValue="authorNameChanged"></v-combobox>
376
377
  </v-col>
377
378
  <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-text-field v-model="currentAuthor.givenName" hide-details density="compact" @update:modelValue="fieldChanged" @update:focused="givenNameFocused"></v-text-field>
379
380
  </v-col>
380
381
  </v-row>
381
382
  <v-row v-else dense align="center">
382
383
  <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-combobox v-model="selectedAuthor" :items="authors" item-value="id" item-title="sN" hide-details density="compact" single-line @update:modelValue="authorNameChanged"></v-combobox>
384
385
  </v-col>
385
386
  <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-text-field v-model="currentAuthor.givenName" hide-details density="compact" @update:modelValue="fieldChanged" @update:focused="givenNameFocused"></v-text-field>
387
388
  </v-col>
388
389
  <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-text-field v-model="currentAuthor.yearOfBirth" hide-details density="compact" type="number" @update:modelValue="fieldChanged"></v-text-field>
390
391
  </v-col>
391
392
  <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-text-field v-model="currentAuthor.yearOfDeath" hide-details density="compact" type="number" @update:modelValue="fieldChanged"></v-text-field>
393
394
  </v-col>
394
395
  <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-select v-model="currentAuthor.category" :items="booksService.categories" hide-details density="compact" single-line @update:modelValue="fieldChanged"></v-select>
396
397
  </v-col>
397
398
  <v-col cols="2">
398
- <v-text-field v-model="author.country" hide-details density="compact" @update:modelValue="fieldChanged"></v-text-field>
399
+ <v-text-field v-model="currentAuthor.country" hide-details density="compact" @update:modelValue="fieldChanged"></v-text-field>
399
400
  </v-col>
400
401
  <v-col cols="2">
401
402
  <v-btn v-if="mustAddAuthor" @click="addAuthor" :disabled="readonly" prepend-icon="$plus">AUTHOR</v-btn>
402
403
  <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-btn v-if="currentAuthor.id > 0" @click="deleteAuthor" :disabled="readonly" icon="$delete"></v-btn>
404
405
  </v-col>
405
406
  </v-row>
406
407
  <v-divider></v-divider>
@@ -413,16 +414,16 @@
413
414
  <v-col cols="1">JAHR</v-col>
414
415
  <v-col cols="1">RATING</v-col>
415
416
  <v-col cols="2">STATUS</v-col>
416
- <v-col v-if="author.id" cols="2">
417
+ <v-col v-if="currentAuthor.id" cols="2">
417
418
  <v-btn v-if="!showAddBookLine" @click="addNewBook" :disabled="readonly" prepend-icon="$plus">BOOK</v-btn>
418
419
  <v-btn v-if="showAddBookLine" @click="cancelAddNewBook" :disabled="readonly" icon="$cancel"></v-btn>
419
420
  </v-col>
420
421
  </v-row>
421
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>
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">
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">
424
425
  </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 v-if="showSelectedBook" clearable auto-grow variant="outlined" label="Kommentar" :disabled="isMobile" v-model="selectedBook.comment" @update:modelValue="descriptionChanged">
426
427
  </v-textarea>
427
428
  </v-defaults-provider>
428
429
  </v-container>
@@ -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>