@hostlink/nuxt-light 0.0.106 → 0.0.107

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/module.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "name": "light",
3
3
  "configKey": "light",
4
- "version": "0.0.106"
4
+ "version": "0.0.107"
5
5
  }
@@ -10,6 +10,7 @@ const props = defineProps({
10
10
  type: String,
11
11
  default: null
12
12
  }
13
+
13
14
  });
14
15
 
15
16
 
@@ -174,7 +174,12 @@ onMounted(() => {
174
174
  <template>
175
175
  <q-card bordered flat style="min-width:360px;max-width: 400px;" class="fixed-center">
176
176
  <q-card-section>
177
- <q-img :src="light.getCompanyLogo()" class="full-width" />
177
+ <q-img :src="light.getCompanyLogo()" class="full-width">
178
+ <template v-slot:error>
179
+ <q-img src="https://raw.githubusercontent.com/HostLink/.github/master/profile/logo.webp" class="full-width" />
180
+ </template>
181
+ </q-img>
182
+
178
183
  <div class="text-h6">
179
184
  {{ light.getCompany() }}
180
185
  </div>
@@ -1,8 +1,19 @@
1
1
  <script setup lang="ts">
2
- import { useQuasar, QTable, is } from 'quasar';
2
+ import { useQuasar, QTable } from 'quasar';
3
3
  import { ref, computed, onMounted, useSlots, useAttrs } from "vue";
4
4
  import { t, q, useLight, GQLFieldBuilder, model } from '../';
5
5
  import { toQuery } from '@hostlink/light';
6
+ import { type QTableColumn } from 'quasar';
7
+
8
+ // extends QTableColumn
9
+ export interface LTableColumn extends QTableColumn {
10
+ searchable?: boolean,
11
+ searchType?: string,
12
+ searchOptions?: Array<any> | Function,
13
+ searchMultiple?: boolean,
14
+ gqlField?: string | Array<string> | Object,
15
+ backgroundColor?: string | Function
16
+ }
6
17
 
7
18
  const errors = ref<InstanceType<any>>([]);
8
19
 
@@ -13,18 +24,7 @@ const props = defineProps({
13
24
  default: false
14
25
  },
15
26
  columns: {
16
- type: Array<{
17
- label: string,
18
- name: string,
19
- align?: "left" | "right" | "center" | undefined,
20
- sortable?: boolean,
21
- searchable?: boolean,
22
- searchType?: string,
23
- searchOptions?: Array<any> | Function,
24
- searchMultiple?: boolean,
25
- field?: string | Object,
26
- gqlField?: string | Array<string> | Object,
27
- }>
27
+ type: Array<LTableColumn>
28
28
  },
29
29
  actions: {
30
30
  type: Array,
@@ -109,25 +109,7 @@ if (props.columns) {
109
109
  }
110
110
  }
111
111
 
112
- const renderColumns = computed(() => {
113
- if (props.columns == undefined) return undefined;
114
-
115
- let cols = [];
116
- if (props.actions.length > 0) {
117
- cols = [
118
- {
119
- name: "_actions",
120
- align: "left"
121
- },
122
- ...props.columns ?? []
123
- ]
124
- } else {
125
- cols = props.columns;
126
- }
127
- return cols;
128
- })
129
-
130
- interface LTableRequest {
112
+ export interface LTableRequest {
131
113
  sort: string,
132
114
  fields: Array<string>,
133
115
  gql: {
@@ -481,8 +463,35 @@ const isDark = computed(() => {
481
463
  return light.theme == "dark";
482
464
  })
483
465
 
466
+ const hasRowExpand = computed(() => {
467
+ return ss.indexOf("row-expand") >= 0;
468
+ })
469
+
470
+ const hasActions = computed(() => {
471
+ return props.actions.length > 0;
472
+ })
473
+
474
+ const getCellStyle = (col: any, row: any) => {
475
+ const style: any = {};
476
+ if (col.whiteSpace) {
477
+ style.whiteSpace = col.whiteSpace;
478
+ }
479
+ if (col.backgroundColor) {
480
+ if (typeof col.backgroundColor == "function") {
481
+ style.backgroundColor = col.backgroundColor(row);
482
+ } else {
483
+ style.backgroundColor = col.backgroundColor;
484
+ }
485
+
486
+ }
487
+ return style;
488
+
489
+
490
+ }
491
+
484
492
  </script>
485
493
 
494
+
486
495
  <template>
487
496
  <template v-if="errors.length > 0">
488
497
  <div class="q-gutter-sm">
@@ -507,9 +516,67 @@ const isDark = computed(() => {
507
516
 
508
517
 
509
518
  <q-table v-bind="attrs" :row-key="rowKey" :loading="loading" :rows="rows" ref="table" @request="onRequest"
510
- :rows-per-page-label="$t(props.rowsPerPageLabel)" :columns="renderColumns"
511
- :rows-per-page-options="rowsPerPageOptions" :selection="selection" v-model:pagination="pagination" :filter="filter"
512
- :no-data-label="$t('No data available')" :loading-label="$t('Loading...')">
519
+ :rows-per-page-label="$t(props.rowsPerPageLabel)" :columns="columns" :rows-per-page-options="rowsPerPageOptions"
520
+ :selection="selection" v-model:pagination="pagination" :filter="filter" :no-data-label="$t('No data available')"
521
+ :loading-label="$t('Loading...')">
522
+
523
+
524
+ <!-- template v-for="s in ss" v-slot:[s]="props">
525
+ <slot :name="s" v-bind="props"></slot>
526
+ </template -->
527
+
528
+ <template #header="props">
529
+ <q-tr :props="props">
530
+ <q-th v-if="hasRowExpand" auto-width></q-th>
531
+ <q-th v-if="hasActions" auto-width></q-th>
532
+ <q-th v-for="col in props.cols" :key="col.name" :props="props">{{ col.label }}</q-th>
533
+ </q-tr>
534
+ </template>
535
+
536
+ <template #body="props">
537
+ <q-tr :props="props">
538
+ <q-td v-if="hasRowExpand" auto-width>
539
+ <q-btn :class="{ 'text-grey-8': !isDark }" flat round dense
540
+ :icon="props.expand ? 'sym_o_expand_more' : 'sym_o_expand_less'"
541
+ @click="props.expand = !props.expand"></q-btn>
542
+ </q-td>
543
+
544
+ <q-td v-if="hasActions" auto-width>
545
+ <div :class="{ 'text-grey-8': !isDark }">
546
+
547
+ <l-view-btn v-if="actionView && props.row.canView"
548
+ :to="`/${modelName}/${props.row[primaryKey]}/view`" />
549
+
550
+ <l-edit-btn v-if="activeEdit && props.row.canUpdate"
551
+ :to="`/${modelName}/${props.row[primaryKey]}/edit`" />
552
+
553
+ <l-delete-btn v-if="actionDelete && props.row.canDelete"
554
+ @submit="onDelete(props.row[primaryKey])"></l-delete-btn>
555
+
556
+ <slot name="actions" v-bind="props"></slot>
557
+ </div>
558
+
559
+ </q-td>
560
+
561
+ <template v-for="col in props.cols">
562
+ <template v-if="ss.indexOf('body-cell-' + col.name) >= 0">
563
+ <slot :name="'body-cell-' + col.name" v-bind="props"></slot>
564
+ </template>
565
+ <template v-else>
566
+ <q-td :key="col.name" :props="props" :auto-width="col.autoWidth ?? false"
567
+ :style="getCellStyle(col, props.row)"><template v-if="col.to" class="bg-primary">
568
+ <l-link :to="col.to(props.row)">{{ col.value }}</l-link>
569
+ </template><template v-else>{{ col.value }}</template></q-td>
570
+ </template>
571
+ </template>
572
+ </q-tr>
573
+ <q-tr v-show="props.expand" :props="props">
574
+ <q-td colspan="100%">
575
+ <slot name="row-expand" v-bind="props"></slot>
576
+ </q-td>
577
+ </q-tr>
578
+ </template>
579
+
513
580
 
514
581
  <template #top-right="props" v-if="fullscreen || searchable">
515
582
  <q-input v-if="searchable" outlined dense debounce="300" v-model="filter" placeholder="Search">
@@ -522,44 +589,21 @@ const isDark = computed(() => {
522
589
  @click="props.toggleFullscreen" class="q-ml-md" />
523
590
  </template>
524
591
 
525
- <template v-for="s in ss" v-slot:[s]="props">
526
- <slot :name="s" v-bind="props"></slot>
527
- </template>
528
592
 
529
- <template v-for="col in toColumns" v-slot:[col.slot_name]="props">
593
+ <!-- template v-for="col in toColumns" v-slot:[col.slot_name]="props">
530
594
  <q-td :props="props">
531
595
  <l-link :to="col.to(props.row)">
532
596
  {{ col.field(props.row) }}
533
597
  </l-link>
534
598
  </q-td>
535
- </template>
536
-
537
- <template #body-cell-_actions="props">
538
- <q-td :props="props" auto-width>
539
- <div :class="{ 'text-grey-8': !isDark }">
540
-
541
- <l-view-btn v-if="actionView && props.row.canView"
542
- :to="`/${modelName}/${props.row[primaryKey]}/view`" />
543
-
544
- <l-edit-btn v-if="activeEdit && props.row.canUpdate"
545
- :to="`/${modelName}/${props.row[primaryKey]}/edit`" />
546
-
547
- <l-delete-btn v-if="actionDelete && props.row.canDelete"
548
- @submit="onDelete(props.row[primaryKey])"></l-delete-btn>
549
-
550
- <slot name="actions" v-bind="props"></slot>
551
- </div>
552
- </q-td>
553
- </template>
554
-
555
-
599
+ </template -->
556
600
 
557
601
 
558
602
  <template #top-row="props" v-if="hasSearch && isServerSide">
559
603
  <q-tr>
560
- <q-td v-if="selection != 'none'" auto-width>
561
-
562
- </q-td>
604
+ <q-td v-if="selection != 'none'" auto-width />
605
+ <q-td v-if="hasRowExpand" auto-width />
606
+ <q-td v-if="hasActions" auto-width />
563
607
  <q-td v-for="col in props.cols">
564
608
  <template v-if="col.searchable">
565
609
 
@@ -570,7 +614,8 @@ const isDark = computed(() => {
570
614
 
571
615
  <template v-if="col.searchType == 'select'">
572
616
  <q-select dense v-model="filters[col.name]" @update:model-value="onFilters" clearable
573
- :options="col.searchOptions" emit-value map-options :multiple="col.searchMultiple" />
617
+ options-dense :options="col.searchOptions" emit-value map-options
618
+ :multiple="col.searchMultiple" />
574
619
 
575
620
  </template>
576
621
 
@@ -0,0 +1,50 @@
1
+ <script setup>
2
+ import { useSlots } from "vue";
3
+
4
+ const slots = useSlots();
5
+
6
+ const ss = Object.entries(slots).map(([key, value]) => {
7
+ return key;
8
+ });
9
+
10
+
11
+
12
+ </script>
13
+ <template>
14
+ <q-table row-key="name">
15
+
16
+ <template #header="props">
17
+
18
+
19
+ <q-tr :props="props">
20
+
21
+ <q-th auto-width key="_expand" :props="{
22
+ colsMap: {
23
+ _expand: {
24
+ align: 'right'
25
+ }
26
+ }
27
+ }">1</q-th>
28
+
29
+ <q-th auto-width key="_actions">act</q-th>
30
+ <q-th v-for="col in props.cols" :key="col.name" :props="props">{{ col.label }}</q-th>
31
+ </q-tr>
32
+ </template>
33
+
34
+ <template #body="props">
35
+
36
+ <q-tr :props="props">
37
+ <template v-for="col in props.cols">
38
+ <slot v-if="slots['body-cell-' + col.name]" :name="'body-cell-' + col.name" v-bind="props"
39
+ :key="col.name"></slot>
40
+ <template v-else>
41
+ <q-td :props="props" :key="col.name">
42
+ {{ col.name }}
43
+ {{ col.value }}</q-td>
44
+ </template>
45
+ </template>
46
+ </q-tr>
47
+
48
+ </template>
49
+ </q-table>
50
+ </template>
@@ -1,10 +1,7 @@
1
- declare const _default: (name: string) => {
2
- name: string;
3
- update(id: number, data: Object): Promise<any>;
4
- delete(id: number): Promise<any>;
5
- add(data: Object): Promise<any>;
6
- fields(fields: string[]): import("@hostlink/light").ModelField[];
7
- get(filters: any, fields: import("@hostlink/light").Fields): Promise<any>;
8
- list(filters: any, fields: import("@hostlink/light").Fields): Promise<any>;
9
- };
1
+ import { model } from "@hostlink/light";
2
+ import type { LTableColumn } from "../components/l-table.vue";
3
+ interface LModel extends ReturnType<typeof model> {
4
+ columns(fields: string[]): Array<LTableColumn>;
5
+ }
6
+ declare const _default: (name: string) => LModel;
10
7
  export default _default;
@@ -15,5 +15,4 @@ export default (name) => {
15
15
  return columns;
16
16
  }
17
17
  });
18
- return m;
19
18
  };
@@ -4,7 +4,7 @@ const columns = model('EventLog').columns(['eventlog_id', 'class', 'id', 'action
4
4
  </script>
5
5
  <template>
6
6
  <l-page>
7
- <l-table @request="$event.loadObjects('EventLog')" :columns="columns" sort-by="eventlog_id:desc"
7
+ <l-table fullscreen @request="$event.loadObjects('EventLog')" :columns="columns" sort-by="eventlog_id:desc"
8
8
  :actions="['view']">
9
9
 
10
10
  </l-table>
@@ -2,13 +2,6 @@
2
2
  import { model } from "#imports"
3
3
  import { ref } from 'vue'
4
4
  const columns = model("MailLog").columns(["maillog_id", "from", "to", "subject", "created_time"])
5
-
6
-
7
- columns.push({
8
- label: "Content",
9
- name: "_act",
10
- gqlField: ["body"]
11
- })
12
5
  const show = ref(false)
13
6
  const content = ref("")
14
7
  </script>
@@ -22,18 +15,11 @@ const content = ref("")
22
15
  </q-card-section>
23
16
  </l-card>
24
17
  </q-dialog>
25
- <l-table row-key="maillog_id" @request="$event.loadObjects('MailLog')" :columns="columns" sort-by="maillog_id:desc">
26
-
27
- <template #body-cell-_act="props">
28
- <q-td :props="props">
29
- <l-btn @click="
30
- content = props.row.body;
31
- show = true" label="Show" icon="sym_o_visibility">
32
- </l-btn>
33
-
34
-
35
- </q-td>
18
+ <l-table row-key="maillog_id" @request="$event.loadObjects('MailLog', {}, ['body'])" :columns="columns"
19
+ sort-by="maillog_id:desc" >
36
20
 
21
+ <template #row-expand="props">
22
+ <iframe width="100%" height="300px" :srcdoc="props.row.body" frameborder="0"></iframe>
37
23
  </template>
38
24
 
39
25
  </l-table>
@@ -1,9 +1,22 @@
1
1
  <script setup>
2
- import { q } from '../../'
2
+ import { q } from '#imports'
3
3
  const system = await q("system", ["server"])
4
+
5
+ const columns = [
6
+ {
7
+ name: "name",
8
+ label: "Name"
9
+ },
10
+ {
11
+ name: "value",
12
+ label: "Value",
13
+ whiteSpace: "pre-wrap"
14
+ },
15
+ ]
16
+
4
17
  </script>
5
18
  <template>
6
19
  <l-page>
7
- <q-table :rows="system.server" :rows-per-page-options="[0]" hide-pagination flat bordered></q-table>
20
+ <l-table :rows="system.server" :columns="columns" :rows-per-page-options="[0]" hide-pagination></l-table>
8
21
  </l-page>
9
22
  </template>
@@ -14,8 +14,8 @@ const status = ref("0");
14
14
 
15
15
  <l-tabs v-model="status">
16
16
  <l-tab label="Active" name="0">
17
- <l-table row-key="user_id" @request="onRequest" :columns="columns" :actions="['view', 'edit', 'delete']">
18
- </l-table>
17
+ <l-table row-key="user_id" @request="onRequest" :columns="columns"
18
+ :actions="['view', 'edit', 'delete']"></l-table>
19
19
  </l-tab>
20
20
  <l-tab label="Inactive" name="1">
21
21
  <l-table row-key="user_id" @request="onRequest" :columns="columns" :actions="['view', 'edit', 'delete']">
@@ -3,6 +3,7 @@ declare const _default: {
3
3
  label: string;
4
4
  sortable: boolean;
5
5
  searchable: boolean;
6
+ autoWidth: boolean;
6
7
  };
7
8
  class: {
8
9
  label: string;
@@ -2,7 +2,8 @@ export default {
2
2
  eventlog_id: {
3
3
  label: "EventLog ID",
4
4
  sortable: true,
5
- searchable: true
5
+ searchable: true,
6
+ autoWidth: true
6
7
  },
7
8
  class: {
8
9
  label: "Class",
@@ -4,6 +4,7 @@ declare const _default: {
4
4
  sortable: boolean;
5
5
  searchable: boolean;
6
6
  searchType: string;
7
+ autoWidth: boolean;
7
8
  };
8
9
  from: {
9
10
  label: string;
@@ -3,7 +3,8 @@ export default {
3
3
  label: "ID",
4
4
  sortable: true,
5
5
  searchable: true,
6
- searchType: "number"
6
+ searchType: "number",
7
+ autoWidth: true
7
8
  },
8
9
  from: {
9
10
  label: "From",
@@ -3,6 +3,7 @@ declare const _default: {
3
3
  label: string;
4
4
  sortable: boolean;
5
5
  searchable: boolean;
6
+ style: string;
6
7
  };
7
8
  first_name: {
8
9
  label: string;
@@ -44,5 +45,13 @@ declare const _default: {
44
45
  }[];
45
46
  format: (value: any) => string;
46
47
  };
48
+ test: {
49
+ label: string;
50
+ name: string;
51
+ to: (row: any) => string;
52
+ gqlField: string[];
53
+ field: (row: any) => any;
54
+ backgroundColor: (row: any) => "primary" | undefined;
55
+ };
47
56
  };
48
57
  export default _default;
@@ -2,7 +2,17 @@ export default {
2
2
  username: {
3
3
  label: "Username",
4
4
  sortable: true,
5
- searchable: true
5
+ searchable: true,
6
+ style: "white-space: nowrap;"
7
+ /* backgroundColor: (row: any) => {
8
+
9
+
10
+ if (row.username == "admin") {
11
+ return "red";
12
+ } else {
13
+ return "white";
14
+ }
15
+ } */
6
16
  },
7
17
  first_name: {
8
18
  label: "First name",
@@ -45,13 +55,17 @@ export default {
45
55
  format: (value) => {
46
56
  return ["Active", "Inactive"][value];
47
57
  }
48
- }
49
- /* ,
58
+ },
50
59
  test: {
51
- label: "Test",
52
- name: "_test",
53
- to: (row: any) => `/User/${row.user_id}/view`,
54
- gqlField: ["user_id", "first_name"],
55
- field: (row: any) => row.first_name,
56
- } */
60
+ label: "Test",
61
+ name: "_test",
62
+ to: (row) => `/User/${row.user_id}/view`,
63
+ gqlField: ["user_id", "first_name"],
64
+ field: (row) => row.first_name,
65
+ backgroundColor: (row) => {
66
+ if (row.username == "admin") {
67
+ return "primary";
68
+ }
69
+ }
70
+ }
57
71
  };
@@ -3,6 +3,7 @@ declare const _default: {
3
3
  label: string;
4
4
  sortable: boolean;
5
5
  searchable: boolean;
6
+ autoWidth: boolean;
6
7
  };
7
8
  username: {
8
9
  label: string;
@@ -29,11 +30,13 @@ declare const _default: {
29
30
  label: string;
30
31
  value: string;
31
32
  }[];
33
+ autoWidth: boolean;
32
34
  };
33
35
  user_agent: {
34
36
  label: string;
35
37
  sortable: boolean;
36
38
  searchable: boolean;
39
+ whiteSpace: string;
37
40
  };
38
41
  };
39
42
  export default _default;
@@ -2,7 +2,8 @@ export default {
2
2
  userlog_id: {
3
3
  label: "ID",
4
4
  sortable: true,
5
- searchable: true
5
+ searchable: true,
6
+ autoWidth: true
6
7
  },
7
8
  username: {
8
9
  label: "User",
@@ -34,11 +35,13 @@ export default {
34
35
  label: "FAIL",
35
36
  value: "FAIL"
36
37
  }
37
- ]
38
+ ],
39
+ autoWidth: true
38
40
  },
39
41
  user_agent: {
40
42
  label: "User agent",
41
43
  sortable: true,
42
- searchable: true
44
+ searchable: true,
45
+ whiteSpace: "pre-line"
43
46
  }
44
47
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hostlink/nuxt-light",
3
- "version": "0.0.106",
3
+ "version": "0.0.107",
4
4
  "description": "HostLink Nuxt Light Framework",
5
5
  "repository": "@hostlink/nuxt-light",
6
6
  "license": "MIT",