@christianriedl/media 1.0.173 → 1.0.175

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.173",
3
+ "version": "1.0.175",
4
4
  "description": "RIC media interfaces",
5
5
 
6
6
  "main": "dist/index.js",
@@ -2,7 +2,7 @@
2
2
  import { ref } from 'vue';
3
3
  import { IBook } from '@christianriedl/media';
4
4
 
5
- const props = defineProps<{ book: IBook, add?: boolean, allbooks?: IBook[] }>();
5
+ const props = defineProps<{ book: IBook, add?: boolean, readonly?: 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,
@@ -52,7 +52,15 @@
52
52
  </script>
53
53
 
54
54
  <template>
55
- <v-row dense align="center" :class="cls" @click="onSelect" >
55
+ <v-row v-if="props.ismobile" dense align="center" :class="cls" @click="onSelect" >
56
+ <v-col cols="9" >
57
+ <v-text-field v-model="book.title" hide-details density="compact" ></v-text-field>
58
+ </v-col>
59
+ <v-col cols="3" >
60
+ <v-text-field v-model="book.year" hide-details density="compact" ></v-text-field>
61
+ </v-col>
62
+ </v-row>
63
+ <v-row v-else dense align="center" :class="cls" @click="onSelect" >
56
64
  <v-col v-if="props.add" cols="6" >
57
65
  <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>
58
66
  </v-col>
@@ -66,8 +74,8 @@
66
74
  <v-rating hover clearable :length="5" :size="32" :model-value="book.rating" active-color="primary" @update:modelValue="ratingChanged" />
67
75
  </v-col>
68
76
  <v-col cols="2">
69
- <v-btn v-if="showDelete" icon="$delete" @click="onDelete"></v-btn>
70
- <v-btn v-if="showSave" icon="$save" @click="onSave"></v-btn>
77
+ <v-btn v-if="showDelete" icon="$delete" :disabled="props.readonly" @click="onDelete"></v-btn>
78
+ <v-btn v-if="showSave" icon="$save" :disabled="props.readonly" @click="onSave"></v-btn>
71
79
  </v-col>
72
80
  </v-row>
73
81
  </template>
@@ -1,10 +1,10 @@
1
1
  <script setup lang="ts">
2
2
  import { inject, ref, reactive, onMounted, onUnmounted, computed, StyleValue } from 'vue';
3
- import { IAppState, appStateSymbol, getOpenAISymbol, IOpenAIService, ICompleteData } from '@christianriedl/utils';
3
+ import { IAppState, appStateSymbol, getOpenAISymbol, IOpenAIService, ICompleteData, EScope, EDevice } from '@christianriedl/utils';
4
4
  import { BooksService, getBooksSymbol, IAuthorShort, IAuthor, IBook } from '@christianriedl/media';
5
5
  import BookLine from '../components/BookLine.vue';
6
6
 
7
- const appState = inject(appStateSymbol)!;
7
+ const appState = inject(appStateSymbol)!;
8
8
  const getBooksService = inject(getBooksSymbol)!;
9
9
  const booksService = getBooksService() as BooksService;
10
10
  const getOpenAI = inject(getOpenAISymbol)!;
@@ -21,8 +21,10 @@
21
21
  const showAddBookLine = ref(false);
22
22
  const showCurrentBook = ref(false);
23
23
  let setBookChanged: () => void;
24
-
24
+ let readonly = !(appState.scopes & EScope.Admin);
25
+ let isMobile = appState.isMobile && (appState.device != EDevice.iPad);
25
26
  const heightStyle = computed<StyleValue>(() => { return { height: appState.bodyHeight.value + "px", overflowY: "auto" } });
27
+
26
28
  start();
27
29
 
28
30
  async function start() {
@@ -32,23 +34,35 @@
32
34
  }
33
35
  }
34
36
  async function addAuthor() {
37
+ if (!checkAuthor(author))
38
+ return;
35
39
  const id = await booksService.addAuthor(author);
36
40
  if (id > 0) {
37
41
  author.id = id;
38
42
  mustAddAuthor.value = false;
39
43
  }
44
+ else
45
+ alert (`AddAuthor - error ${id}`);
40
46
  }
41
47
  async function updateAuthor() {
48
+ if (!checkAuthor(author))
49
+ return;
42
50
  const rc = await booksService.updateAuthor(author);
43
51
  if (rc)
44
52
  mustUpdateAuthor.value = false;
53
+ else
54
+ alert ('UpdateAuthor - error');
45
55
  }
46
56
  async function deleteAuthor() {
57
+ if (!window.confirm(`Willst du ${author.surName} wirklich l�schen ?`))
58
+ return;
47
59
  const rc = await booksService.deleteAuthor(author.id);
48
60
  if (rc) {
49
61
  mustUpdateAuthor.value = false;
50
62
  initAuthor ("");
51
63
  }
64
+ else
65
+ alert (`DeleteAuthor ${author.id} - error`);
52
66
  }
53
67
  function initAuthor(surName: string) {
54
68
  author.id = 0;
@@ -59,7 +73,7 @@
59
73
  author.country = undefined;
60
74
  author.books = [];
61
75
  }
62
- async function getAuthor (id: number, withBooks: boolean) : Promise<boolean> {
76
+ async function getCurrentAuthor (id: number, withBooks: boolean) : Promise<boolean> {
63
77
  const authors = await booksService.getAuthors(undefined, undefined, withBooks, id);
64
78
  if (authors && authors.length > 0) {
65
79
  const a = authors[0];
@@ -77,13 +91,13 @@
77
91
  return false;
78
92
  }
79
93
  }
80
- async function nameChanged(arg: IAuthorShort | string) {
94
+ async function authorNameChanged(arg: IAuthorShort | string) {
81
95
  showCurrentBook.value = false;
82
96
  currentBook.value = { id: 0, authorId: 0, title: ""};
83
97
  mustAddAuthor.value = typeof arg == 'string';
84
98
  if (!mustAddAuthor.value) {
85
99
  const authorShort = arg as IAuthorShort;
86
- const rc = await getAuthor (authorShort.id, true);
100
+ const rc = await getCurrentAuthor (authorShort.id, true);
87
101
  }
88
102
  else {
89
103
  initAuthor (arg as string);
@@ -100,7 +114,7 @@
100
114
  await getAuthorDataFromAI(author.surName, author.givenName);
101
115
  }
102
116
  }
103
- async function addBook() {
117
+ async function addNewBook() {
104
118
  if (lastAllBooksId.value != author.id) {
105
119
  allBooks.value = await getAuthorBooksFromAI (author.surName, author.givenName, author.id);
106
120
  lastAllBooksId.value = author.id;
@@ -108,7 +122,7 @@
108
122
  newBook = reactive<IBook>({ id: 0, authorId: author.id, title: "", rating: 0 });
109
123
  showAddBookLine.value = true;
110
124
  }
111
- function cancelAddBook() {
125
+ function cancelAddNewBook() {
112
126
  showAddBookLine.value = false;
113
127
  }
114
128
  async function selectBook(id: number, func: () => void) {
@@ -141,8 +155,12 @@
141
155
 
142
156
  }
143
157
  async function deleteBook(id: number) {
158
+ if (!window.confirm(`Willst du das Buch wirklich l�schen ?`))
159
+ return;
144
160
  setBookChanged = () => {};
145
161
  const rc = await booksService.deleteBook (id);
162
+ if (!rc)
163
+ alert (`DeleteBook ${id}- error`);
146
164
  if (rc && author.books) {
147
165
  const idx = author.books.findIndex ((x) => x.id == id);
148
166
  if (idx >= 0)
@@ -150,8 +168,12 @@
150
168
  }
151
169
  }
152
170
  async function saveBook(book: IBook) {
171
+ if (!checkBook(book))
172
+ return;
153
173
  if (showAddBookLine.value) {
154
174
  const id = await booksService.addBook (book);
175
+ if (id < 0)
176
+ alert (`AddBook - error ${id}`);
155
177
  if (id > 0 && author.books) {
156
178
  book.id = id;
157
179
  author.books.splice (0, 0, book);
@@ -160,7 +182,47 @@
160
182
  }
161
183
  else {
162
184
  const rc = await booksService.updateBook (book);
185
+ if (!rc)
186
+ alert ('UpdateBook - error');
187
+ }
188
+ }
189
+ function checkAuthor (author: IAuthor): boolean {
190
+ if (!author.surName || !author.givenName) {
191
+ alert("Vor oder Nachname fehlt !");
192
+ return false;
163
193
  }
194
+ if (author.surName.length >= 64 || author.givenName.length >= 64) {
195
+ alert("Vor oder Nachname zu lang (>64) !");
196
+ return false;
197
+ }
198
+ if (author.country && author.country.length >= 64) {
199
+ alert("Geburtsland zu lang (>64) !");
200
+ return false;
201
+ }
202
+ return true;
203
+ }
204
+ function checkBook (book: IBook): boolean {
205
+ if (!book.title) {
206
+ alert("Titel fehlt !");
207
+ return false;
208
+ }
209
+ if (book.title.length >= 256) {
210
+ alert("Titel zu lang (>256) !");
211
+ return false;
212
+ }
213
+ if (!book.authorId) {
214
+ alert("Autor fehlt !");
215
+ return false;
216
+ }
217
+ if (book.description && book.description.length >= 4000) {
218
+ alert("Beschreibung zu lang (>4000) !");
219
+ return false;
220
+ }
221
+ if (book.comment && book.comment.length >= 1024) {
222
+ alert("Kommentar zu lang (>1024) !");
223
+ return false;
224
+ }
225
+ return true;
164
226
  }
165
227
  async function getAuthorDataFromAI(surName: string, givenName: string) {
166
228
  const schema =
@@ -264,16 +326,28 @@
264
326
  <template>
265
327
  <v-container fluid class="bg-office" :style="heightStyle">
266
328
  <v-defaults-provider :defaults="{'VBtn':{'size':'large','variant':'flat','class':'bg-office'}}">
267
- <v-row dense align="center">
329
+ <v-row v-if="isMobile" dense align="center">
330
+ <v-col cols="6">Name</v-col>
331
+ <v-col cols="6">Vorname</v-col>
332
+ </v-row>
333
+ <v-row v-else dense align="center">
268
334
  <v-col cols="2">Name</v-col>
269
335
  <v-col cols="2">Vorname</v-col>
270
336
  <v-col cols="2">Von</v-col>
271
337
  <v-col cols="2">Bis</v-col>
272
338
  <v-col cols="2">Land</v-col>
273
339
  </v-row>
274
- <v-row dense align="center">
340
+ <v-row v-if="isMobile" dense align="center">
341
+ <v-col cols="6">
342
+ <v-combobox v-model="selected" :items="authors" item-value="id" item-title="sN" hide-details density="compact" single-line @update:modelValue="authorNameChanged"></v-combobox>
343
+ </v-col>
344
+ <v-col cols="6">
345
+ <v-text-field v-model="author.givenName" hide-details density="compact" @update:modelValue="fieldChanged" @update:focused="givenNameFocused"></v-text-field>
346
+ </v-col>
347
+ </v-row>
348
+ <v-row v-else dense align="center">
275
349
  <v-col cols="2">
276
- <v-combobox v-model="selected" :items="authors" item-value="id" item-title="sN" hide-details density="compact" single-line @update:modelValue="nameChanged"></v-combobox>
350
+ <v-combobox v-model="selected" :items="authors" item-value="id" item-title="sN" hide-details density="compact" single-line @update:modelValue="authorNameChanged"></v-combobox>
277
351
  </v-col>
278
352
  <v-col cols="2">
279
353
  <v-text-field v-model="author.givenName" hide-details density="compact" @update:modelValue="fieldChanged" @update:focused="givenNameFocused"></v-text-field>
@@ -288,26 +362,30 @@
288
362
  <v-text-field v-model="author.country" hide-details density="compact" @update:modelValue="fieldChanged"></v-text-field>
289
363
  </v-col>
290
364
  <v-col cols="2">
291
- <v-btn v-if="mustAddAuthor" @click="addAuthor" append-icon="$plus">AUTHOR</v-btn>
292
- <v-btn v-if="mustUpdateAuthor" @click="updateAuthor" icon="$save"></v-btn>
293
- <v-btn v-if="author.id > 0" @click="deleteAuthor" icon="$delete"></v-btn>
365
+ <v-btn v-if="mustAddAuthor" @click="addAuthor" :disabled="readonly" append-icon="$plus">AUTHOR</v-btn>
366
+ <v-btn v-if="mustUpdateAuthor" @click="updateAuthor" :disabled="readonly" icon="$save"></v-btn>
367
+ <v-btn v-if="author.id > 0" @click="deleteAuthor" :disabled="readonly" icon="$delete"></v-btn>
294
368
  </v-col>
295
369
  </v-row>
296
370
  <v-divider></v-divider>
297
- <v-row dense align="center">
298
- <v-col cols="6">TITEL</v-col>
371
+ <v-row v-if="isMobile" dense align="center">
372
+ <v-col cols="7">TITEL</v-col>
299
373
  <v-col cols="2">JAHR</v-col>
300
- <v-col cols="2">RATING</v-col>
374
+ <v-col cols="3">RATING</v-col>
375
+ </v-row>
376
+ <v-row v-else dense align="center">
377
+ <v-col cols="9">TITEL</v-col>
378
+ <v-col cols="3">JAHR</v-col>
301
379
  <v-col v-if="author.id" cols="2">
302
- <v-btn v-if="!showAddBookLine" @click="addBook" append-icon="$plus">BOOK</v-btn>
303
- <v-btn v-if="showAddBookLine" @click="cancelAddBook" icon="$cancel"></v-btn>
380
+ <v-btn v-if="!showAddBookLine" @click="addNewBook" :disabled="readonly" append-icon="$plus">BOOK</v-btn>
381
+ <v-btn v-if="showAddBookLine" @click="cancelAddNewBook" :disabled="readonly" icon="$cancel"></v-btn>
304
382
  </v-col>
305
383
  </v-row>
306
- <book-line v-if="showAddBookLine" :book="newBook" :add="true" :allbooks="allBooks" @selectbook="selectBook" @deletebook="deleteBook" @savebook="saveBook"></book-line>
307
- <book-line v-for="book in author.books" :key="book.id" :book="book" @selectbook="selectBook" @deletebook="deleteBook" @savebook="saveBook"></book-line>
308
- <v-textarea v-if="showCurrentBook" clearable auto-grow variant="outlined" label="Description" v-model="currentBook.description" @update:modelValue="descriptionChanged">
384
+ <book-line v-if="showAddBookLine" :book="newBook" :add="true" :allbooks="allBooks" :readonly="readonly" :ismobile="isMobile" @selectbook="selectBook" @deletebook="deleteBook" @savebook="saveBook"></book-line>
385
+ <book-line v-for="book in author.books" :key="book.id" :book="book" :readonly="readonly" :ismobile="isMobile" @selectbook="selectBook" @deletebook="deleteBook" @savebook="saveBook"></book-line>
386
+ <v-textarea v-if="showCurrentBook" class="pt-2"clearable auto-grow variant="outlined" label="Beschreibung" v-model="currentBook.description" @update:modelValue="descriptionChanged">
309
387
  </v-textarea>
310
- <v-textarea v-if="showCurrentBook" clearable auto-grow variant="outlined" label="Comment" v-model="currentBook.comment" @update:modelValue="descriptionChanged">
388
+ <v-textarea v-if="showCurrentBook" clearable auto-grow variant="outlined" label="Kommentar" v-model="currentBook.comment" @update:modelValue="descriptionChanged">
311
389
  </v-textarea>
312
390
  </v-defaults-provider>
313
391
  </v-container>