@cloudron/pankow 3.4.0 → 3.4.2
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/components/Checkbox.vue +1 -1
- package/components/Dialog.vue +8 -1
- package/components/FormGroup.vue +4 -0
- package/components/MenuItem.vue +18 -2
- package/components/SingleSelect.vue +2 -0
- package/components/TableView.vue +92 -88
- package/package.json +5 -5
- package/style.css +1 -2
- package/utils.js +8 -4
package/components/Checkbox.vue
CHANGED
package/components/Dialog.vue
CHANGED
|
@@ -112,7 +112,6 @@ defineExpose({ open, close });
|
|
|
112
112
|
<div ref="dialog" class="pankow-dialog" v-bind="$attrs" :class="{ 'pankow-dialog-center': center }" v-show="visible" @keydown.esc="onDismiss" tabindex="0" :style="mergedStyle">
|
|
113
113
|
<div class="pankow-dialog-header" v-show="title">
|
|
114
114
|
{{ title }}
|
|
115
|
-
<Icon v-show="showX" icon="fa-solid fa-xmark" style="cursor: pointer;" @click="onReject"/>
|
|
116
115
|
</div>
|
|
117
116
|
<div class="pankow-dialog-body" ref="dialogBody" :class="{ 'pankow-dialog-body-no-header': !title, 'pankow-dialog-body-no-buttons': !(rejectLabel || confirmLabel) }">
|
|
118
117
|
<slot></slot>
|
|
@@ -123,6 +122,7 @@ defineExpose({ open, close });
|
|
|
123
122
|
<Button :[rejectStyle]="!!rejectStyle" @click="onReject" v-show="rejectLabel" :disabled="!rejectActive">{{ rejectLabel }}</Button>
|
|
124
123
|
<Button :[confirmStyle]="!!confirmStyle" @click="onConfirm" v-show="confirmLabel" :loading="confirmBusy" :disabled="confirmBusy || !confirmActive">{{ confirmLabel }}</Button>
|
|
125
124
|
</div>
|
|
125
|
+
<Icon v-if="showX" class="pankow-dialog-x-close" icon="fa-solid fa-xmark" style="cursor: pointer;" @click="onReject"/>
|
|
126
126
|
</div>
|
|
127
127
|
</Transition>
|
|
128
128
|
</div>
|
|
@@ -159,6 +159,13 @@ defineExpose({ open, close });
|
|
|
159
159
|
outline: none;
|
|
160
160
|
}
|
|
161
161
|
|
|
162
|
+
.pankow-dialog-x-close {
|
|
163
|
+
position: absolute;
|
|
164
|
+
font-size: 20px;
|
|
165
|
+
top: 15px;
|
|
166
|
+
right: 15px;
|
|
167
|
+
}
|
|
168
|
+
|
|
162
169
|
.pankow-dialog-center {
|
|
163
170
|
top: 50%;
|
|
164
171
|
transform: translateX(-50%) translateY(-50%);
|
package/components/FormGroup.vue
CHANGED
package/components/MenuItem.vue
CHANGED
|
@@ -44,7 +44,8 @@ function onActivated() {
|
|
|
44
44
|
<template>
|
|
45
45
|
<div class="pankow-menu-item" :class="{'pankow-menu-item-disabled': isDisabled }" @click.stop="onActivated" :separator="item.separator" v-if="isVisible" tabindex="0" @keydown.enter.stop="onActivated" @keydown.space.stop="onActivated">
|
|
46
46
|
<Checkbox v-model="item.checked" v-if="item.checkbox" style="margin-right: 4px; display: inline-flex;"/>
|
|
47
|
-
<span :style="{ width: (hasIcons && !item.checkbox) ? '29px' : 0 }"><Icon v-show="hasIcons" :icon="item.icon"/></span>{{ item.label }}
|
|
47
|
+
<span v-if="!item.separator" :style="{ width: (hasIcons && !item.checkbox) ? '29px' : 0 }"><Icon v-show="hasIcons" :icon="item.icon"/></span>{{ item.label }}
|
|
48
|
+
<div class="pankow-menu-item-separator-line" v-if="item.separator"></div>
|
|
48
49
|
</div>
|
|
49
50
|
</template>
|
|
50
51
|
|
|
@@ -89,10 +90,25 @@ function onActivated() {
|
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
.pankow-menu-item[separator] {
|
|
92
|
-
|
|
93
|
+
color: #666;
|
|
93
94
|
padding: 0;
|
|
94
95
|
margin: 5px 13px;
|
|
96
|
+
font-size: 12px;
|
|
97
|
+
font-weight: bold;
|
|
98
|
+
gap: 5px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.pankow-menu-item[separator]:focus,
|
|
102
|
+
.pankow-menu-item[separator]:hover {
|
|
103
|
+
color: #666;
|
|
104
|
+
cursor: unset;
|
|
105
|
+
background-color: unset;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.pankow-menu-item-separator-line {
|
|
95
109
|
height: 1px;
|
|
110
|
+
background-color: #c3c3c3;
|
|
111
|
+
flex-grow: 1;
|
|
96
112
|
}
|
|
97
113
|
|
|
98
114
|
.pankow-menu-item-with-icons {
|
package/components/TableView.vue
CHANGED
|
@@ -1,3 +1,94 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
|
|
3
|
+
import { onMounted, ref, watchEffect } from 'vue';
|
|
4
|
+
import ProgressBar from './ProgressBar.vue';
|
|
5
|
+
import Icon from './Icon.vue';
|
|
6
|
+
|
|
7
|
+
const emits = defineEmits(['row-click']);
|
|
8
|
+
|
|
9
|
+
const props = defineProps({
|
|
10
|
+
model: Array,
|
|
11
|
+
busy: false,
|
|
12
|
+
placeholder: 'empty',
|
|
13
|
+
columns: Object,
|
|
14
|
+
hover: {
|
|
15
|
+
type: Boolean,
|
|
16
|
+
default: true
|
|
17
|
+
},
|
|
18
|
+
defaultSortBy: String,
|
|
19
|
+
defaultSortOrder: {
|
|
20
|
+
type: String,
|
|
21
|
+
default: 'asc',
|
|
22
|
+
validator(value, props) {
|
|
23
|
+
return [ 'asc', 'desc' ].includes(value);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const SORT_ORDER = {
|
|
29
|
+
ASC: 'asc',
|
|
30
|
+
DESC: 'desc',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const sortOrder = ref(SORT_ORDER.ASC);
|
|
34
|
+
const sortBy = ref(null);
|
|
35
|
+
const sortedItems = ref([]);
|
|
36
|
+
|
|
37
|
+
watchEffect(() => {
|
|
38
|
+
sort(props.model);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const finalBusy = ref(false);
|
|
42
|
+
let busyTimeout;
|
|
43
|
+
|
|
44
|
+
watchEffect(() => {
|
|
45
|
+
if (props.busy) {
|
|
46
|
+
busyTimeout = setTimeout(() => { finalBusy.value = true; }, 1000);
|
|
47
|
+
} else {
|
|
48
|
+
clearTimeout(busyTimeout);
|
|
49
|
+
finalBusy.value = false;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
function sort() {
|
|
54
|
+
sortedItems.value = props.model.sort((a, b) => {
|
|
55
|
+
let sort = 0;
|
|
56
|
+
|
|
57
|
+
if (!props.columns[sortBy.value]) return 0;
|
|
58
|
+
if (!props.columns[sortBy.value].sort) return 0;
|
|
59
|
+
|
|
60
|
+
if (typeof props.columns[sortBy.value].sort === 'function') {
|
|
61
|
+
sort = props.columns[sortBy.value].sort(a[sortBy.value], b[sortBy.value], a, b);
|
|
62
|
+
} else {
|
|
63
|
+
if (a[sortBy.value] < b[sortBy.value]) sort = -1;
|
|
64
|
+
else sort = 1;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
return sort *= (sortOrder.value === SORT_ORDER.DESC ? -1 : 1);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function toggleSort(key) {
|
|
72
|
+
if (!props.columns[key].sort) return;
|
|
73
|
+
|
|
74
|
+
if (sortBy.value === key) sortOrder.value = sortOrder.value === SORT_ORDER.ASC ? SORT_ORDER.DESC : SORT_ORDER.ASC;
|
|
75
|
+
else sortBy.value = key;
|
|
76
|
+
|
|
77
|
+
sort();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function onRowClick(item) {
|
|
81
|
+
emits('row-click', item);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
onMounted(() => {
|
|
85
|
+
sortBy.value = props.defaultSortBy;
|
|
86
|
+
sortOrder.value = props.defaultSortOrder;
|
|
87
|
+
sort(props.model);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
</script>
|
|
91
|
+
|
|
1
92
|
<template>
|
|
2
93
|
<div class="pankow-table-scroll-wrapper">
|
|
3
94
|
<div class="pankow-table-wrapper">
|
|
@@ -12,7 +103,7 @@
|
|
|
12
103
|
</tr>
|
|
13
104
|
</thead>
|
|
14
105
|
<tbody>
|
|
15
|
-
<tr v-if="busy"><td :colspan="Object.keys(columns).length" style="text-align: center; padding: 20px;"><ProgressBar mode="indeterminate" :show-label="false" :slim="true"/></td></tr>
|
|
106
|
+
<tr v-if="busy"><td :colspan="Object.keys(columns).length" style="text-align: center; padding: 20px;"><ProgressBar mode="indeterminate" :show-label="false" :slim="true" v-show="finalBusy"/></td></tr>
|
|
16
107
|
<tr v-else-if="!busy && sortedItems.length === 0"><td :colspan="Object.keys(columns).length" class="pankow-table-placeholder">{{ placeholder }}</td></tr>
|
|
17
108
|
<tr v-else class="pankow-table-row" :class="{ 'pankow-table-row-with-hover': hover }" v-for="item in sortedItems" @click="onRowClick(item)">
|
|
18
109
|
<td class="pankow-table-cell" v-for="column in Object.keys(columns)" :style="{ width: typeof columns[column].width === 'string' ? columns[column].width : 'auto' }" :class="{ 'pankow-table-cell-hide-mobile': columns[column].hideMobile, 'pankow-table-cell-nowrap': columns[column].nowrap }">
|
|
@@ -26,93 +117,6 @@
|
|
|
26
117
|
</div>
|
|
27
118
|
</template>
|
|
28
119
|
|
|
29
|
-
<script>
|
|
30
|
-
|
|
31
|
-
import ProgressBar from './ProgressBar.vue';
|
|
32
|
-
import Icon from './Icon.vue';
|
|
33
|
-
|
|
34
|
-
const SORT_ORDER = {
|
|
35
|
-
ASC: 'asc',
|
|
36
|
-
DESC: 'desc',
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
export default {
|
|
40
|
-
name: 'TableView',
|
|
41
|
-
emits: ['row-click'],
|
|
42
|
-
components: {
|
|
43
|
-
Icon,
|
|
44
|
-
ProgressBar,
|
|
45
|
-
},
|
|
46
|
-
data() {
|
|
47
|
-
return {
|
|
48
|
-
SORT_ORDER,
|
|
49
|
-
sortOrder: SORT_ORDER.ASC,
|
|
50
|
-
sortBy: null,
|
|
51
|
-
sortedItems: Array
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
props: {
|
|
55
|
-
model: Array,
|
|
56
|
-
busy: false,
|
|
57
|
-
placeholder: 'empty',
|
|
58
|
-
columns: Object,
|
|
59
|
-
hover: {
|
|
60
|
-
type: Boolean,
|
|
61
|
-
default: true
|
|
62
|
-
},
|
|
63
|
-
defaultSortBy: String,
|
|
64
|
-
defaultSortOrder: {
|
|
65
|
-
type: String,
|
|
66
|
-
default: SORT_ORDER.ASC,
|
|
67
|
-
validator(value, props) {
|
|
68
|
-
return [ SORT_ORDER.ASC, SORT_ORDER.DESC ].includes(value);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
watch: {
|
|
73
|
-
model(newModel, oldModel) {
|
|
74
|
-
this.sort(newModel);
|
|
75
|
-
}
|
|
76
|
-
},
|
|
77
|
-
mounted() {
|
|
78
|
-
this.sortBy = this.defaultSortBy;
|
|
79
|
-
this.sortOrder = this.defaultSortOrder;
|
|
80
|
-
this.sort(this.model);
|
|
81
|
-
},
|
|
82
|
-
methods: {
|
|
83
|
-
sort() {
|
|
84
|
-
this.sortedItems = this.model.sort((a, b) => {
|
|
85
|
-
let sort = 0;
|
|
86
|
-
|
|
87
|
-
if (!this.columns[this.sortBy]) return 0;
|
|
88
|
-
if (!this.columns[this.sortBy].sort) return 0;
|
|
89
|
-
|
|
90
|
-
if (typeof this.columns[this.sortBy].sort === 'function') {
|
|
91
|
-
sort = this.columns[this.sortBy].sort(a[this.sortBy], b[this.sortBy], a, b);
|
|
92
|
-
} else {
|
|
93
|
-
if (a[this.sortBy] < b[this.sortBy]) sort = -1;
|
|
94
|
-
else sort = 1;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
return sort *= (this.sortOrder === SORT_ORDER.DESC ? -1 : 1);
|
|
98
|
-
});
|
|
99
|
-
},
|
|
100
|
-
toggleSort(key) {
|
|
101
|
-
if (!this.columns[key].sort) return;
|
|
102
|
-
|
|
103
|
-
if (this.sortBy === key) this.sortOrder = this.sortOrder === SORT_ORDER.ASC ? SORT_ORDER.DESC : SORT_ORDER.ASC;
|
|
104
|
-
else this.sortBy = key;
|
|
105
|
-
|
|
106
|
-
this.sort();
|
|
107
|
-
},
|
|
108
|
-
onRowClick(item) {
|
|
109
|
-
this.$emit('row-click', item);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
</script>
|
|
115
|
-
|
|
116
120
|
<style>
|
|
117
121
|
|
|
118
122
|
.pankow-table-scroll-wrapper {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudron/pankow",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "3.4.
|
|
4
|
+
"version": "3.4.2",
|
|
5
5
|
"description": "",
|
|
6
6
|
"main": "index.js",
|
|
7
7
|
"types": "types/index.d.ts",
|
|
@@ -17,14 +17,14 @@
|
|
|
17
17
|
"license": "ISC",
|
|
18
18
|
"dependencies": {
|
|
19
19
|
"@fontsource/inter": "^5.2.8",
|
|
20
|
-
"@fortawesome/fontawesome-free": "^7.0
|
|
20
|
+
"@fortawesome/fontawesome-free": "^7.1.0",
|
|
21
21
|
"filesize": "^11.0.13",
|
|
22
|
-
"monaco-editor": "^0.
|
|
22
|
+
"monaco-editor": "^0.54.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@vitejs/plugin-vue": "^6.0.1",
|
|
26
|
-
"typescript": "^5.9.
|
|
27
|
-
"vite": "^7.1.
|
|
26
|
+
"typescript": "^5.9.3",
|
|
27
|
+
"vite": "^7.1.9",
|
|
28
28
|
"vue": "^3.5.22"
|
|
29
29
|
}
|
|
30
30
|
}
|
package/style.css
CHANGED
|
@@ -94,7 +94,7 @@ input {
|
|
|
94
94
|
--pankow-input-border-color-hover: #ced4da;
|
|
95
95
|
|
|
96
96
|
--pankow-color-background: #1b1e21;
|
|
97
|
-
--pankow-color-background-hover:
|
|
97
|
+
--pankow-color-background-hover: #1f2326;
|
|
98
98
|
|
|
99
99
|
--pankow-dialog-background-color: #32383e;
|
|
100
100
|
--pankow-dialog-backdrop-color: rgba(0,0,0,.7);
|
|
@@ -164,7 +164,6 @@ select:focus {
|
|
|
164
164
|
textarea {
|
|
165
165
|
font-size: 14px;
|
|
166
166
|
color: var(--pankow-text-color);
|
|
167
|
-
margin: 6px 0;
|
|
168
167
|
background-color: var(--pankow-input-background-color);
|
|
169
168
|
padding: 6px;
|
|
170
169
|
border-radius: var(--pankow-border-radius);
|
package/utils.js
CHANGED
|
@@ -105,27 +105,31 @@ function prettyDate(value) {
|
|
|
105
105
|
|
|
106
106
|
function formatDate(format, value) {
|
|
107
107
|
const formatters = {
|
|
108
|
-
'hh:mm A': new Intl.DateTimeFormat(
|
|
108
|
+
'hh:mm A': new Intl.DateTimeFormat(undefined, {
|
|
109
109
|
hour: '2-digit',
|
|
110
110
|
minute: '2-digit',
|
|
111
111
|
hour12: true
|
|
112
112
|
}),
|
|
113
|
-
'hh:mm:ss A': new Intl.DateTimeFormat(
|
|
113
|
+
'hh:mm:ss A': new Intl.DateTimeFormat(undefined, {
|
|
114
114
|
hour: '2-digit',
|
|
115
115
|
minute: '2-digit',
|
|
116
116
|
second: '2-digit',
|
|
117
117
|
hour12: true
|
|
118
118
|
}),
|
|
119
|
-
'DD MMM': new Intl.DateTimeFormat(
|
|
119
|
+
'DD MMM': new Intl.DateTimeFormat(undefined, {
|
|
120
120
|
day: '2-digit',
|
|
121
121
|
month: 'short'
|
|
122
122
|
}),
|
|
123
|
-
'DD MMM hh:mm A': new Intl.DateTimeFormat(
|
|
123
|
+
'DD MMM hh:mm A': new Intl.DateTimeFormat(undefined, {
|
|
124
124
|
day: '2-digit',
|
|
125
125
|
month: 'short',
|
|
126
126
|
hour: '2-digit',
|
|
127
127
|
minute: '2-digit',
|
|
128
128
|
hour12: true
|
|
129
|
+
}),
|
|
130
|
+
'DD MMM': new Intl.DateTimeFormat(undefined, { // force this to get month first
|
|
131
|
+
day: '2-digit',
|
|
132
|
+
month: 'short'
|
|
129
133
|
})
|
|
130
134
|
};
|
|
131
135
|
|