glib-web 4.18.2 → 4.20.0
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/actions/lists/append.js +23 -8
- package/components/_avatar.vue +19 -0
- package/components/avatar.vue +4 -9
- package/components/composable/date.js +15 -0
- package/components/fields/_buttonDate.vue +16 -9
- package/components/mixins/list/autoload.js +18 -8
- package/components/panels/column.vue +1 -1
- package/components/panels/list.vue +15 -9
- package/cypress/e2e/glib-web/dirtyState.cy.ts +19 -3
- package/cypress/e2e/glib-web/formDynamic.cy.ts +53 -0
- package/cypress/e2e/glib-web/window.cy.ts +14 -0
- package/index.js +2 -0
- package/package.json +1 -1
- package/templates/comment.vue +20 -6
- package/templates/thumbnail.vue +61 -20
- package/utils/http.js +3 -2
- package/utils/type.js +2 -2
package/actions/lists/append.js
CHANGED
|
@@ -1,15 +1,30 @@
|
|
|
1
|
+
import { nextTick } from "vue";
|
|
2
|
+
import { realComponent } from "../../components/helper";
|
|
3
|
+
|
|
1
4
|
export default class {
|
|
2
|
-
execute(
|
|
3
|
-
let
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
execute(spec, component) {
|
|
6
|
+
let target = component;
|
|
7
|
+
|
|
8
|
+
if (spec.targetId) {
|
|
9
|
+
target = realComponent(GLib.component.findById(spec.targetId));
|
|
6
10
|
}
|
|
7
11
|
|
|
8
|
-
if (!
|
|
9
|
-
console.warn(
|
|
10
|
-
return
|
|
12
|
+
if (!target) {
|
|
13
|
+
console.warn("Component ID not found", spec.targetId);
|
|
14
|
+
return;
|
|
11
15
|
}
|
|
12
16
|
|
|
13
|
-
|
|
17
|
+
target.action_appendRow(spec.row, spec.sectionIndex || 0);
|
|
18
|
+
|
|
19
|
+
nextTick(() => {
|
|
20
|
+
GLib.action.execute(spec.onAppend, component);
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
// if (!targetComponent.sections || !targetComponent.sections[0].rows) {
|
|
24
|
+
// console.warn('there is no sections or rows');
|
|
25
|
+
// return null;
|
|
26
|
+
// }
|
|
27
|
+
|
|
28
|
+
// targetComponent.sections[0].rows.push(properties.row);
|
|
14
29
|
}
|
|
15
30
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<common-badge :spec="spec">
|
|
3
|
+
<v-avatar :size="spec.size" :color="spec.backgroundColor || 'surface-variant'" :class="$classes()">
|
|
4
|
+
<p v-if="spec.initials" :style="{ color: spec.initials.color || 'white' }">{{ spec.initials.text }}</p>
|
|
5
|
+
<!-- Use `img` instead of `v-img` otherwise the rounded border will not work. -->
|
|
6
|
+
<!-- <img :style="$styles()" :src="spec.url || spec.base64Data" @click="$onClick()" /> -->
|
|
7
|
+
<v-img :style="$styles()" :class="$classes()" :src="spec.url || spec.base64Data" @click="$onClick()"
|
|
8
|
+
v-else></v-img>
|
|
9
|
+
</v-avatar>
|
|
10
|
+
</common-badge>
|
|
11
|
+
</template>
|
|
12
|
+
|
|
13
|
+
<script>
|
|
14
|
+
export default {
|
|
15
|
+
props: {
|
|
16
|
+
spec: { type: Object, required: true }
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
</script>
|
package/components/avatar.vue
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<common-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!-- <img :style="$styles()" :src="spec.url || spec.base64Data" @click="$onClick()" /> -->
|
|
7
|
-
<v-img :style="$styles()" :class="$classes()" :src="spec.url || spec.base64Data" @click="$onClick()"
|
|
8
|
-
v-else></v-img>
|
|
9
|
-
</v-avatar>
|
|
10
|
-
</common-badge>
|
|
2
|
+
<common-avatar :spec="spec" />
|
|
3
|
+
<!-- <div>
|
|
4
|
+
test
|
|
5
|
+
</div> -->
|
|
11
6
|
</template>
|
|
12
7
|
|
|
13
8
|
<script>
|
|
@@ -12,4 +12,19 @@ export function sanitize(val, type) {
|
|
|
12
12
|
default:
|
|
13
13
|
return val;
|
|
14
14
|
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function localeString(val, type, format) {
|
|
18
|
+
// Ref https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString
|
|
19
|
+
const fmt = Object.assign({ day: 'numeric', weekday: 'short', year: 'numeric', month: 'short', hour: 'numeric', minute: 'numeric', second: 'numeric', hour12: false }, format || {});
|
|
20
|
+
switch (type) {
|
|
21
|
+
case 'datetime-local':
|
|
22
|
+
return new Date(val).toLocaleString(undefined, fmt); // undefined mean use browser configuration
|
|
23
|
+
default:
|
|
24
|
+
delete fmt.hour;
|
|
25
|
+
delete fmt.minute;
|
|
26
|
+
delete fmt.second;
|
|
27
|
+
return new Date(val).toLocaleDateString(undefined, fmt);
|
|
28
|
+
}
|
|
29
|
+
|
|
15
30
|
}
|
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
<!-- eslint-disable vue/no-mutating-props -->
|
|
2
2
|
<template>
|
|
3
3
|
<div class="glib date-input-container" @click="showPicker">
|
|
4
|
-
<div v-if="template.type == 'plain'" class="glib date-button"
|
|
4
|
+
<div v-if="template.type == 'plain'" class="glib date-button">
|
|
5
5
|
<v-icon icon="calendar_today" class="calendar-icon"></v-icon>
|
|
6
6
|
<span class="date-text">{{ text }}</span>
|
|
7
7
|
</div>
|
|
8
|
-
<v-text-field v-else-if="template.type == 'text'" :
|
|
8
|
+
<v-text-field v-else-if="template.type == 'text'" :type="type" :color="gcolor" :label="spec.label" :hint="spec.hint"
|
|
9
9
|
:placeholder="spec.placeholder" :disabled="inputDisabled" :min="sanitizeValue(spec.min)"
|
|
10
|
-
:max="sanitizeValue(spec.max)" :
|
|
11
|
-
:density="$classes().includes('compact') ? 'compact' : 'default'" :clearable="spec.clearable"
|
|
12
|
-
|
|
10
|
+
:max="sanitizeValue(spec.max)" :style="$styles()"
|
|
11
|
+
:density="$classes().includes('compact') ? 'compact' : 'default'" :clearable="spec.clearable" :variant="variant"
|
|
12
|
+
validate-on="blur" persistent-placeholder :value="model" prepend-inner-icon="calendar_today" />
|
|
13
13
|
|
|
14
14
|
<input :name="fieldName" :type="type" class="date-input" ref="dateInput" @change="handleChanged"
|
|
15
15
|
:min="sanitizeValue(spec.min)" :max="sanitizeValue(spec.max)" :disabled="inputDisabled" :readonly="spec.readonly"
|
|
16
16
|
:value="model" />
|
|
17
|
+
|
|
18
|
+
<v-input :name="fieldName" :rules="$validation()" v-model="model" />
|
|
17
19
|
</div>
|
|
18
20
|
</template>
|
|
19
21
|
|
|
20
22
|
<script>
|
|
21
23
|
import { computed, ref, watch } from "vue";
|
|
22
|
-
import { sanitize } from "../composable/date";
|
|
24
|
+
import { sanitize, localeString } from "../composable/date";
|
|
23
25
|
import inputVariant from '../mixins/inputVariant';
|
|
26
|
+
import { isPresent } from "../../utils/type";
|
|
24
27
|
|
|
25
28
|
export default {
|
|
26
29
|
mixins: [inputVariant],
|
|
@@ -43,7 +46,11 @@ export default {
|
|
|
43
46
|
const template = ref(props.spec.template);
|
|
44
47
|
|
|
45
48
|
const dateInput = ref(null);
|
|
46
|
-
const text = computed(() =>
|
|
49
|
+
const text = computed(() => {
|
|
50
|
+
if (!isPresent(model.value) && props.spec.label) return props.spec.label;
|
|
51
|
+
|
|
52
|
+
return localeString(model.value, props.type, props.spec.format);
|
|
53
|
+
});
|
|
47
54
|
|
|
48
55
|
watch(props, (val) => {
|
|
49
56
|
model.value = sanitizeValue(val.spec.value);
|
|
@@ -69,8 +76,6 @@ export default {
|
|
|
69
76
|
|
|
70
77
|
<style>
|
|
71
78
|
.glib.date-input-container {
|
|
72
|
-
display: flex;
|
|
73
|
-
align-items: center;
|
|
74
79
|
position: relative;
|
|
75
80
|
width: 100%;
|
|
76
81
|
cursor: pointer;
|
|
@@ -82,6 +87,8 @@ export default {
|
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
.date-button {
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: center;
|
|
85
92
|
padding: 8px 12px;
|
|
86
93
|
background-color: #f3f5f7;
|
|
87
94
|
border-radius: 5px;
|
|
@@ -113,16 +113,26 @@ export default {
|
|
|
113
113
|
if (previousFirstRowIndex) {
|
|
114
114
|
// Pre-record the height to get an accurate value
|
|
115
115
|
const anchorHeight = this.$refs.topAnchor.clientHeight;
|
|
116
|
+
const body = this.$refs.body[0];
|
|
117
|
+
const oldBodyHeight = body.clientHeight;
|
|
116
118
|
|
|
117
119
|
this.$nextTick(() => {
|
|
118
|
-
const prependedBottomElement = this.$refs[
|
|
119
|
-
|
|
120
|
-
][0];
|
|
121
|
-
|
|
122
|
-
const top =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
// const prependedBottomElement = this.$refs[
|
|
121
|
+
// `row_0_${previousFirstRowIndex - 1}`
|
|
122
|
+
// ][0];
|
|
123
|
+
|
|
124
|
+
// const top =
|
|
125
|
+
// prependedBottomElement.offsetTop +
|
|
126
|
+
// prependedBottomElement.clientHeight -
|
|
127
|
+
// anchorHeight;
|
|
128
|
+
|
|
129
|
+
// const pageBody = Utils.history._pageBody;
|
|
130
|
+
|
|
131
|
+
// pageBody.scrollTop = top;
|
|
132
|
+
|
|
133
|
+
const newBodyHeight = body.clientHeight;
|
|
134
|
+
const prependedHeight = newBodyHeight - oldBodyHeight;
|
|
135
|
+
const top = body.offsetTop + prependedHeight - anchorHeight;
|
|
126
136
|
|
|
127
137
|
const pageBody = Utils.history._pageBody;
|
|
128
138
|
|
|
@@ -15,15 +15,17 @@
|
|
|
15
15
|
:data-dragSectionIndex="sectionIndex" :disabled="!$type.isObject(dragSupport)" @start="onDragStart"
|
|
16
16
|
@end="onDragEnd"> -->
|
|
17
17
|
|
|
18
|
-
<
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<
|
|
24
|
-
:
|
|
25
|
-
|
|
26
|
-
|
|
18
|
+
<div ref="body">
|
|
19
|
+
<draggable v-model="section.rows" ghost-class="ghost"
|
|
20
|
+
:group="dragSupport ? dragSupport.groupId || 'common' : 'common'" :data-dragListId="spec.id"
|
|
21
|
+
:data-dragSectionIndex="sectionIndex" :disabled="!$type.isObject(dragSupport)" @start="onDragStart"
|
|
22
|
+
@end="onDragEnd" item-key="id">
|
|
23
|
+
<template #item="{ element }">
|
|
24
|
+
<component :is="template(element)" :spec="element" :responsive-cols="spec.responsiveCols"
|
|
25
|
+
:data-dragRowId="element.id" />
|
|
26
|
+
</template>
|
|
27
|
+
</draggable>
|
|
28
|
+
</div>
|
|
27
29
|
|
|
28
30
|
<!-- <div v-for="(row, rowIndex) in section.rows" :key="`${sectionIndex}_${rowIndex}`"
|
|
29
31
|
:ref="`row_${sectionIndex}_${rowIndex}`" :data-dragRowId="row.id">
|
|
@@ -279,6 +281,10 @@ export default {
|
|
|
279
281
|
}
|
|
280
282
|
return count;
|
|
281
283
|
},
|
|
284
|
+
// Publicly invokable
|
|
285
|
+
action_appendRow(row, sectionIndex) {
|
|
286
|
+
this.sections[sectionIndex].rows.push(row);
|
|
287
|
+
}
|
|
282
288
|
},
|
|
283
289
|
};
|
|
284
290
|
</script>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { testPageUrl } from "../../helper"
|
|
2
2
|
const url = testPageUrl('dirty_state')
|
|
3
|
+
const prompt = 'Changes you made have not been saved. Are you sure?'
|
|
3
4
|
|
|
4
5
|
describe('dirtyState', () => {
|
|
5
6
|
it('can be disabled', () => {
|
|
@@ -20,7 +21,7 @@ describe('dirtyState', () => {
|
|
|
20
21
|
cy.contains('Male').click();
|
|
21
22
|
|
|
22
23
|
cy.on('window:confirm', (str) => {
|
|
23
|
-
cy.then(() => expect(str).to.equal(
|
|
24
|
+
cy.then(() => expect(str).to.equal(prompt))
|
|
24
25
|
return false;
|
|
25
26
|
})
|
|
26
27
|
|
|
@@ -45,7 +46,7 @@ describe('dirtyState', () => {
|
|
|
45
46
|
return true;
|
|
46
47
|
})
|
|
47
48
|
|
|
48
|
-
cy.then(() => expect(text).to.equal(
|
|
49
|
+
cy.then(() => expect(text).to.equal(prompt))
|
|
49
50
|
|
|
50
51
|
cy.contains('multiupload').click() // Try to navigate to another page
|
|
51
52
|
cy.get('h2').should('contain.text', 'MultiUpload')
|
|
@@ -65,11 +66,26 @@ describe('dirtyState', () => {
|
|
|
65
66
|
return false;
|
|
66
67
|
})
|
|
67
68
|
|
|
68
|
-
cy.then(() => expect(text).to.equal(
|
|
69
|
+
cy.then(() => expect(text).to.equal(prompt))
|
|
69
70
|
|
|
70
71
|
// dirty state is removed after second try
|
|
71
72
|
cy.go('back')
|
|
72
73
|
|
|
73
74
|
cy.get('h2').should('contain.text', 'MultiUpload')
|
|
74
75
|
})
|
|
76
|
+
|
|
77
|
+
it('trigger dirty prompt on windows/open updateExisting: true', () => {
|
|
78
|
+
cy.visit(url)
|
|
79
|
+
cy.contains('choice2').click() // make form dirty
|
|
80
|
+
cy.contains('navigate').click() // windows/open updateExisting: true
|
|
81
|
+
|
|
82
|
+
let text = ''
|
|
83
|
+
cy.on('window:confirm', (str) => {
|
|
84
|
+
text = str;
|
|
85
|
+
return false;
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
cy.then(() => expect(text).to.equal(prompt))
|
|
89
|
+
|
|
90
|
+
})
|
|
75
91
|
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { testPageUrl } from "../../helper"
|
|
2
|
+
const url = testPageUrl('form_dynamic')
|
|
3
|
+
|
|
4
|
+
describe('form dynamic', () => {
|
|
5
|
+
it('add, delete, and submit', () => {
|
|
6
|
+
cy.visit(url)
|
|
7
|
+
|
|
8
|
+
cy.get('.question:first').click().type(' edited')
|
|
9
|
+
cy.get('.answer_type:first').click()
|
|
10
|
+
cy.get('.v-overlay-container').contains('Yes no').click()
|
|
11
|
+
|
|
12
|
+
cy.contains('Add item').click()
|
|
13
|
+
|
|
14
|
+
cy.get('i.text-error').eq(1).click()
|
|
15
|
+
|
|
16
|
+
cy.contains('Confirm').click()
|
|
17
|
+
cy.contains('Submit').click()
|
|
18
|
+
|
|
19
|
+
const result = `Method: POST
|
|
20
|
+
Form Data:
|
|
21
|
+
{
|
|
22
|
+
"evaluation": {
|
|
23
|
+
"0": {
|
|
24
|
+
"error_message": "",
|
|
25
|
+
"question": "Punctuality edited",
|
|
26
|
+
"type": "yes_no",
|
|
27
|
+
"enabled": ""
|
|
28
|
+
},
|
|
29
|
+
"1": {
|
|
30
|
+
"_destroy": "1",
|
|
31
|
+
"error_message": "Wrong answer",
|
|
32
|
+
"question": "Quality of work",
|
|
33
|
+
"type": "rating",
|
|
34
|
+
"enabled": "true"
|
|
35
|
+
},
|
|
36
|
+
"2": {
|
|
37
|
+
"error_message": "Incompatible selection",
|
|
38
|
+
"question": "Satisfied?",
|
|
39
|
+
"type": "yes_no",
|
|
40
|
+
"enabled": ""
|
|
41
|
+
},
|
|
42
|
+
"3": {
|
|
43
|
+
"error_message": "",
|
|
44
|
+
"question": "",
|
|
45
|
+
"type": "rating",
|
|
46
|
+
"enabled": "true"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}`
|
|
50
|
+
|
|
51
|
+
cy.get('.unformatted').should('contain.text', result)
|
|
52
|
+
})
|
|
53
|
+
})
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { testPageUrl } from "../../helper"
|
|
2
|
+
const url = testPageUrl('window')
|
|
3
|
+
|
|
4
|
+
describe("window", () => {
|
|
5
|
+
it('windows/open updateExisting: true', () => {
|
|
6
|
+
cy.visit(url)
|
|
7
|
+
|
|
8
|
+
cy.contains('windows/open updateExisting: true').click()
|
|
9
|
+
|
|
10
|
+
cy.location().should((loc) => {
|
|
11
|
+
expect(loc.href).to.eq(testPageUrl('multiupload'))
|
|
12
|
+
})
|
|
13
|
+
})
|
|
14
|
+
})
|
package/index.js
CHANGED
|
@@ -46,6 +46,7 @@ import Component from "./components/component.vue";
|
|
|
46
46
|
import CommonIcon from "./components/_icon.vue";
|
|
47
47
|
import CommonBadge from "./components/_badge.vue";
|
|
48
48
|
// import CommonTooltip from "./components/_tooltip.vue";
|
|
49
|
+
import CommonAvatar from "./components/_avatar.vue";
|
|
49
50
|
import CommonButton from "./components/_button.vue";
|
|
50
51
|
import CommonChip from "./components/_chip.vue";
|
|
51
52
|
import CommonMessage from "./components/_message.vue";
|
|
@@ -55,6 +56,7 @@ import CommonTemplateMenu from "./templates/_menu.vue";
|
|
|
55
56
|
import RichButton from "./components/button.vue";
|
|
56
57
|
Vue.component("panels-vertical", VerticalPanel);
|
|
57
58
|
Vue.component("panels-responsive", ResponsivePanel);
|
|
59
|
+
Vue.component("common-avatar", CommonAvatar);
|
|
58
60
|
Vue.component("common-button", CommonButton);
|
|
59
61
|
Vue.component("common-icon", CommonIcon);
|
|
60
62
|
Vue.component("common-badge", CommonBadge);
|
package/package.json
CHANGED
package/templates/comment.vue
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
>{{
|
|
16
16
|
spec.subtitle
|
|
17
17
|
}}</v-card-title>
|
|
18
|
-
<v-avatar
|
|
18
|
+
<!-- <v-avatar
|
|
19
19
|
v-if="spec.imageUrl"
|
|
20
20
|
size="30px"
|
|
21
21
|
>
|
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
:src="spec.imageUrl"
|
|
24
24
|
alt="avatar"
|
|
25
25
|
/>
|
|
26
|
-
</v-avatar>
|
|
26
|
+
</v-avatar> -->
|
|
27
|
+
|
|
28
|
+
<common-avatar v-if="avatar" :spec="avatar" />
|
|
27
29
|
<v-card-title
|
|
28
30
|
v-if="spec.title"
|
|
29
31
|
class="font-weight-bold body-2 subtitle"
|
|
@@ -84,6 +86,14 @@ export default {
|
|
|
84
86
|
compiledText() {
|
|
85
87
|
return Utils.format.markdown(this.spec.subtitle);
|
|
86
88
|
},
|
|
89
|
+
avatar() {
|
|
90
|
+
// if (this.$type.isObject(this.spec.avatar)) {
|
|
91
|
+
// return Object.assign({ view: 'avatar' }, this.spec.avatar)
|
|
92
|
+
// };
|
|
93
|
+
return this.$type.ifObject(this.spec.avatar, val => {
|
|
94
|
+
return Object.assign({ view: 'avatar' }, val)
|
|
95
|
+
});
|
|
96
|
+
}
|
|
87
97
|
},
|
|
88
98
|
methods: {
|
|
89
99
|
$ready() {
|
|
@@ -153,9 +163,10 @@ export default {
|
|
|
153
163
|
display: grid;
|
|
154
164
|
|
|
155
165
|
// This is needed to prevent broken layout when the content is too short
|
|
156
|
-
grid-template-columns: 36px auto;
|
|
166
|
+
// grid-template-columns: 36px auto;
|
|
167
|
+
grid-template-columns: 0px auto;
|
|
157
168
|
|
|
158
|
-
grid-template-rows: 1fr auto 0.5fr;
|
|
169
|
+
// grid-template-rows: 1fr auto 0.5fr;
|
|
159
170
|
grid-column: 1/4;
|
|
160
171
|
|
|
161
172
|
> * {
|
|
@@ -188,6 +199,7 @@ export default {
|
|
|
188
199
|
color: #9e9e9e;
|
|
189
200
|
padding-top: 4px;
|
|
190
201
|
align-self: start;
|
|
202
|
+
overflow: visible;
|
|
191
203
|
}
|
|
192
204
|
|
|
193
205
|
> .v-avatar {
|
|
@@ -211,9 +223,9 @@ export default {
|
|
|
211
223
|
display: grid;
|
|
212
224
|
|
|
213
225
|
// This is needed to prevent broken layout when the content is too short
|
|
214
|
-
grid-template-columns: 36px auto 36px;
|
|
226
|
+
// grid-template-columns: 36px auto 36px;
|
|
215
227
|
|
|
216
|
-
grid-template-rows: 1fr auto 0.5fr;
|
|
228
|
+
// grid-template-rows: 1fr auto 0.5fr;
|
|
217
229
|
grid-column: 4/4;
|
|
218
230
|
|
|
219
231
|
> * {
|
|
@@ -247,6 +259,7 @@ export default {
|
|
|
247
259
|
color: #9e9e9e;
|
|
248
260
|
padding-top: 4px;
|
|
249
261
|
align-self: start;
|
|
262
|
+
// overflow: visible;
|
|
250
263
|
}
|
|
251
264
|
|
|
252
265
|
> .v-avatar {
|
|
@@ -263,6 +276,7 @@ export default {
|
|
|
263
276
|
grid-row: 1/2;
|
|
264
277
|
grid-column: 2/3;
|
|
265
278
|
padding: 0;
|
|
279
|
+
// overflow: visible;
|
|
266
280
|
}
|
|
267
281
|
}
|
|
268
282
|
</style>
|
package/templates/thumbnail.vue
CHANGED
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
</div>
|
|
26
26
|
|
|
27
27
|
<common-icon v-if="spec.icon" :spec="spec.icon" />
|
|
28
|
+
<common-avatar v-if="avatar" :spec="avatar" />
|
|
28
29
|
</div>
|
|
29
30
|
</template>
|
|
30
31
|
|
|
@@ -43,25 +44,30 @@
|
|
|
43
44
|
<common-icon :spec="spec.icon" />
|
|
44
45
|
</v-list-item-avatar>
|
|
45
46
|
</div> -->
|
|
47
|
+
<!-- <v-badge :color="'red'" :model-value="true">
|
|
48
|
+
<template v-slot:badge>2</template> -->
|
|
46
49
|
|
|
47
|
-
<
|
|
48
|
-
<
|
|
50
|
+
<common-badge :spec="spec">
|
|
51
|
+
<div>
|
|
52
|
+
<v-list-item-title class="title">{{ spec.title }}</v-list-item-title>
|
|
49
53
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
<v-list-item-subtitle v-if="spec.subsubtitle">{{
|
|
54
|
-
spec.subsubtitle
|
|
55
|
-
}}</v-list-item-subtitle>
|
|
54
|
+
<div class="subtitle" v-if="spec.subtitle">{{
|
|
55
|
+
spec.subtitle
|
|
56
|
+
}}</div>
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
<v-list-item-subtitle class="subsubtitle" v-if="spec.subsubtitle">{{
|
|
59
|
+
spec.subsubtitle
|
|
60
|
+
}}</v-list-item-subtitle>
|
|
61
|
+
<div v-if="hasChips" class="chips">
|
|
62
|
+
<template v-for="(item, index) in chips" :key="index">
|
|
63
|
+
<common-chip :spec="item" />
|
|
64
|
+
</template>
|
|
65
|
+
</div>
|
|
62
66
|
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
<panels-responsive v-if="spec.body" :spec="spec.body" />
|
|
68
|
+
</div>
|
|
69
|
+
</common-badge>
|
|
70
|
+
<!-- </v-badge> -->
|
|
65
71
|
|
|
66
72
|
<template v-slot:append>
|
|
67
73
|
<template v-for="(item, index) in spec.rightButtons" :key="index">
|
|
@@ -116,6 +122,11 @@ export default {
|
|
|
116
122
|
cssClasses() {
|
|
117
123
|
return this.$classes(this.spec, "templates/thumbnail");
|
|
118
124
|
},
|
|
125
|
+
avatar() {
|
|
126
|
+
return this.$type.ifObject(this.spec.avatar, val => {
|
|
127
|
+
return Object.assign({ view: 'avatar' }, val)
|
|
128
|
+
});
|
|
129
|
+
},
|
|
119
130
|
clickCondition() {
|
|
120
131
|
if (this.spec.onClick || this.spec.onLongPress) {
|
|
121
132
|
// This will show the clickable indication
|
|
@@ -201,12 +212,42 @@ export default {
|
|
|
201
212
|
}
|
|
202
213
|
|
|
203
214
|
.thumbnail {
|
|
204
|
-
|
|
205
215
|
// Override this when using the `right` property.
|
|
206
216
|
.item-content {
|
|
207
217
|
width: 100%;
|
|
218
|
+
|
|
219
|
+
&.v-list-item--density-default {
|
|
220
|
+
padding: 0;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
.v-list-item__content {
|
|
224
|
+
// This is the minimum padding required so that the badge doesn't get truncated.
|
|
225
|
+
padding: 5px 10px;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
.v-badge {
|
|
230
|
+
width: 100%;
|
|
231
|
+
|
|
232
|
+
// The rest of the classes can be scoped but unfortunately this one cannot.
|
|
233
|
+
.v-badge__wrapper {
|
|
234
|
+
width: 100%;
|
|
235
|
+
}
|
|
208
236
|
}
|
|
209
237
|
}
|
|
238
|
+
|
|
239
|
+
.title {
|
|
240
|
+
font-size: 1.1rem;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.subtitle {
|
|
244
|
+
opacity: 0.8;
|
|
245
|
+
// font-size: 0.97rem;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.subsubtitle {
|
|
249
|
+
margin-top: 5px;
|
|
250
|
+
}
|
|
210
251
|
</style>
|
|
211
252
|
|
|
212
253
|
<style lang="scss" scoped>
|
|
@@ -219,10 +260,10 @@ a.thumbnail {
|
|
|
219
260
|
.item-content {
|
|
220
261
|
display: flex;
|
|
221
262
|
|
|
222
|
-
&.v-list-item--density-default:not(.v-list-item--nav).v-list-item--one-line {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
}
|
|
263
|
+
// &.v-list-item--density-default:not(.v-list-item--nav).v-list-item--one-line {
|
|
264
|
+
// // padding-inline-start: 0;
|
|
265
|
+
// // padding-inline-end: 0;
|
|
266
|
+
// }
|
|
226
267
|
}
|
|
227
268
|
|
|
228
269
|
@media (min-width: 600px) {
|
package/utils/http.js
CHANGED
|
@@ -287,13 +287,14 @@ export default class {
|
|
|
287
287
|
}
|
|
288
288
|
|
|
289
289
|
static startIndicator(component) {
|
|
290
|
-
|
|
290
|
+
// Code below can be satisfied by components/set
|
|
291
|
+
// if (component) realComponent(component)._disabled = true;
|
|
291
292
|
this._showIndicator();
|
|
292
293
|
vueApp.isBusy = true;
|
|
293
294
|
}
|
|
294
295
|
|
|
295
296
|
static stopIndicator(component) {
|
|
296
|
-
if (component) realComponent(component)._disabled = false;
|
|
297
|
+
// if (component) realComponent(component)._disabled = false;
|
|
297
298
|
this._hideIndicator();
|
|
298
299
|
vueApp.isBusy = false;
|
|
299
300
|
}
|
package/utils/type.js
CHANGED
|
@@ -27,9 +27,9 @@ export function isNull(obj) {
|
|
|
27
27
|
|
|
28
28
|
export function ifObject(obj, ifCommand, elseCommand) {
|
|
29
29
|
if (isObject(obj)) {
|
|
30
|
-
ifCommand(obj);
|
|
30
|
+
return ifCommand(obj);
|
|
31
31
|
} else if (elseCommand) {
|
|
32
|
-
elseCommand();
|
|
32
|
+
return elseCommand();
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
export function ifHash(obj, ifCommand, elseCommand) {
|