Applied style rules to genocide all \t characters
This commit is contained in:
@@ -12,41 +12,46 @@
|
||||
|
||||
<script lang="js">
|
||||
export default {
|
||||
props: {
|
||||
wideColumns: Boolean,
|
||||
},
|
||||
props: {
|
||||
wideColumns: Boolean,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="css">
|
||||
.column-layout {
|
||||
column-count: 12;
|
||||
column-fill: balance;
|
||||
column-gap: 0;
|
||||
column-width: 240px;
|
||||
transform: translateZ(0);
|
||||
padding: 4px;
|
||||
}
|
||||
.column-layout.wide-columns {
|
||||
column-count: 12;
|
||||
column-fill: balance;
|
||||
column-gap: 0;
|
||||
column-width: 320px;
|
||||
transform: translateZ(0);
|
||||
padding: 4px;
|
||||
}
|
||||
.column-layout > div, .column-layout > span > div {
|
||||
/*
|
||||
.column-layout {
|
||||
column-count: 12;
|
||||
column-fill: balance;
|
||||
column-gap: 0;
|
||||
column-width: 240px;
|
||||
transform: translateZ(0);
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.column-layout.wide-columns {
|
||||
column-count: 12;
|
||||
column-fill: balance;
|
||||
column-gap: 0;
|
||||
column-width: 320px;
|
||||
transform: translateZ(0);
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.column-layout>div,
|
||||
.column-layout>span>div {
|
||||
/*
|
||||
Table and width set because firefox does not support break-inside: avoid
|
||||
*/
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
-webkit-backface-visibility: hidden;
|
||||
-webkit-transform: translateX(0);
|
||||
-webkit-column-break-inside: avoid;
|
||||
page-break-inside: avoid;
|
||||
break-inside: avoid;
|
||||
padding: 4px;
|
||||
}
|
||||
display: table;
|
||||
table-layout: fixed;
|
||||
width: 100%;
|
||||
backface-visibility: hidden;
|
||||
-webkit-backface-visibility: hidden;
|
||||
transform: translateX(0);
|
||||
-webkit-transform: translateX(0);
|
||||
-webkit-column-break-inside: avoid;
|
||||
page-break-inside: avoid;
|
||||
break-inside: avoid;
|
||||
padding: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -65,102 +65,103 @@
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
export default {
|
||||
inject: {
|
||||
context: { default: {} }
|
||||
export default {
|
||||
inject: {
|
||||
context: { default: {} }
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
props: {
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
open: Boolean,
|
||||
flat: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editValue: this.value,
|
||||
operation: 'set',
|
||||
hover: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
open: {
|
||||
immediate: true,
|
||||
handler(isOpen) {
|
||||
if (isOpen) this.resetData();
|
||||
},
|
||||
open: Boolean,
|
||||
flat: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editValue: this.value,
|
||||
operation: 'set',
|
||||
hover: false,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
open: {
|
||||
immediate: true,
|
||||
handler(isOpen) {
|
||||
if (isOpen) this.resetData();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
resetData(){
|
||||
this.editValue = this.value;
|
||||
this.operation = 'set';
|
||||
// this.$nextTick didn't work, using timeout instead did
|
||||
setTimeout(() => {
|
||||
if (this.$refs.editInput){
|
||||
this.$refs.editInput.focus();
|
||||
}
|
||||
}, 100);
|
||||
},
|
||||
cancelEdit() {
|
||||
this.$emit('close');
|
||||
},
|
||||
commitEdit() {
|
||||
this.editing = false;
|
||||
let value = +this.$refs.editInput.lazyValue;
|
||||
if (this.operation === 'add') {
|
||||
value = -value;
|
||||
}
|
||||
let type = this.operation === 'set' ? 'set' : 'increment';
|
||||
this.$emit('change', { type, value });
|
||||
},
|
||||
operationIcon(operation) {
|
||||
switch (operation) {
|
||||
case 'set':
|
||||
return 'mdi-forward';
|
||||
case 'add':
|
||||
return 'mdi-plus';
|
||||
case 'subtract':
|
||||
return 'mdi-minus';
|
||||
}
|
||||
},
|
||||
toggleAdd(){
|
||||
this.operation = (this.operation === 'add') ? 'set': 'add';
|
||||
},
|
||||
toggleSubtract(){
|
||||
this.operation = (this.operation === 'subtract') ? 'set': 'subtract';
|
||||
},
|
||||
keypress(event) {
|
||||
let digitsOnly = /[0-9]/;
|
||||
let key = event.key;
|
||||
if (key === '+') {
|
||||
this.toggleAdd();
|
||||
event.preventDefault();
|
||||
} else if (key === '-') {
|
||||
this.toggleSubtract();
|
||||
event.preventDefault();
|
||||
} else if (key === 'Enter') {
|
||||
this.commitEdit();
|
||||
} else if (!digitsOnly.test(key)){
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
input(value){
|
||||
if (+value < 0){
|
||||
this.editValue = -value;
|
||||
this.operation = 'subtract';
|
||||
},
|
||||
methods: {
|
||||
resetData() {
|
||||
this.editValue = this.value;
|
||||
this.operation = 'set';
|
||||
// this.$nextTick didn't work, using timeout instead did
|
||||
setTimeout(() => {
|
||||
if (this.$refs.editInput) {
|
||||
this.$refs.editInput.focus();
|
||||
}
|
||||
}, 100);
|
||||
},
|
||||
cancelEdit() {
|
||||
this.$emit('close');
|
||||
},
|
||||
commitEdit() {
|
||||
this.editing = false;
|
||||
let value = +this.$refs.editInput.lazyValue;
|
||||
if (this.operation === 'add') {
|
||||
value = -value;
|
||||
}
|
||||
}
|
||||
};
|
||||
let type = this.operation === 'set' ? 'set' : 'increment';
|
||||
this.$emit('change', { type, value });
|
||||
},
|
||||
operationIcon(operation) {
|
||||
switch (operation) {
|
||||
case 'set':
|
||||
return 'mdi-forward';
|
||||
case 'add':
|
||||
return 'mdi-plus';
|
||||
case 'subtract':
|
||||
return 'mdi-minus';
|
||||
}
|
||||
},
|
||||
toggleAdd() {
|
||||
this.operation = (this.operation === 'add') ? 'set' : 'add';
|
||||
},
|
||||
toggleSubtract() {
|
||||
this.operation = (this.operation === 'subtract') ? 'set' : 'subtract';
|
||||
},
|
||||
keypress(event) {
|
||||
let digitsOnly = /[0-9]/;
|
||||
let key = event.key;
|
||||
if (key === '+') {
|
||||
this.toggleAdd();
|
||||
event.preventDefault();
|
||||
} else if (key === '-') {
|
||||
this.toggleSubtract();
|
||||
event.preventDefault();
|
||||
} else if (key === 'Enter') {
|
||||
this.commitEdit();
|
||||
} else if (!digitsOnly.test(key)) {
|
||||
event.preventDefault();
|
||||
}
|
||||
},
|
||||
input(value) {
|
||||
if (+value < 0) {
|
||||
this.editValue = -value;
|
||||
this.operation = 'subtract';
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.filled.theme--light {
|
||||
background: #fff !important;
|
||||
}
|
||||
.filled.theme--dark {
|
||||
background: #424242 !important;
|
||||
}
|
||||
.filled.theme--light {
|
||||
background: #fff !important;
|
||||
}
|
||||
|
||||
.filled.theme--dark {
|
||||
background: #424242 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -8,20 +8,20 @@
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import { marked } from 'marked';
|
||||
import { marked } from 'marked';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
markdown: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
compiledMarkdown() {
|
||||
if (!this.markdown) return;
|
||||
return marked(this.markdown);
|
||||
},
|
||||
export default {
|
||||
props: {
|
||||
markdown: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
compiledMarkdown() {
|
||||
if (!this.markdown) return;
|
||||
return marked(this.markdown);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -27,54 +27,58 @@
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import isDarkColor from '/imports/ui/utility/isDarkColor.js';
|
||||
import getThemeColor from '/imports/ui/utility/getThemeColor.js';
|
||||
import CardHighlight from '/imports/ui/components/CardHighlight.vue';
|
||||
import isDarkColor from '/imports/ui/utility/isDarkColor.js';
|
||||
import getThemeColor from '/imports/ui/utility/getThemeColor.js';
|
||||
import CardHighlight from '/imports/ui/components/CardHighlight.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
CardHighlight,
|
||||
export default {
|
||||
components: {
|
||||
CardHighlight,
|
||||
},
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default() {
|
||||
return getThemeColor('secondary');
|
||||
},
|
||||
},
|
||||
props: {
|
||||
color: {
|
||||
type: String,
|
||||
default(){
|
||||
return getThemeColor('secondary');
|
||||
},
|
||||
},
|
||||
transparentToolbar: Boolean,
|
||||
},
|
||||
data(){ return {
|
||||
transparentToolbar: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
hovering: false,
|
||||
}},
|
||||
computed: {
|
||||
isDark(){
|
||||
return isDarkColor(this.color);
|
||||
},
|
||||
hasClickListener(){
|
||||
return this.$listeners && !!this.$listeners.click;
|
||||
},
|
||||
hasToolbarClickListener(){
|
||||
return this.$listeners && !!this.$listeners.toolbarclick;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hoverToolbar(val){
|
||||
this.hovering = this.$listeners &&
|
||||
!!this.$listeners.toolbarclick &&
|
||||
val;
|
||||
}
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isDark() {
|
||||
return isDarkColor(this.color);
|
||||
},
|
||||
hasClickListener() {
|
||||
return this.$listeners && !!this.$listeners.click;
|
||||
},
|
||||
hasToolbarClickListener() {
|
||||
return this.$listeners && !!this.$listeners.toolbarclick;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
hoverToolbar(val) {
|
||||
this.hovering = this.$listeners &&
|
||||
!!this.$listeners.toolbarclick &&
|
||||
val;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="css">
|
||||
.toolbar-card .v-toolbar__title {
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.toolbar-card {
|
||||
transition: box-shadow .4s cubic-bezier(0.25, 0.8, 0.25, 1);
|
||||
}
|
||||
|
||||
.toolbar-card.transparent-toolbar .theme--dark.v-toolbar.v-sheet {
|
||||
background-color: #303030;
|
||||
}
|
||||
|
||||
@@ -34,23 +34,26 @@ import SmartInput from '/imports/ui/components/global/SmartInputMixin.js';
|
||||
import { format } from 'date-fns';
|
||||
|
||||
export default {
|
||||
mixins: [SmartInput],
|
||||
data(){return {
|
||||
menu: false,
|
||||
};},
|
||||
computed: {
|
||||
formattedSafeValue(){
|
||||
return format(this.safeValue, 'YYYY-MM-DD')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
dateInput(e){
|
||||
this.menu = false;
|
||||
this.input(e);
|
||||
},
|
||||
},
|
||||
mixins: [SmartInput],
|
||||
data() {
|
||||
return {
|
||||
menu: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
formattedSafeValue() {
|
||||
return format(this.safeValue, 'YYYY-MM-DD')
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
dateInput(e) {
|
||||
this.menu = false;
|
||||
this.input(e);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -87,7 +87,7 @@ export default {
|
||||
SvgIcon,
|
||||
},
|
||||
mixins: [SmartInput],
|
||||
props: {
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Icon',
|
||||
@@ -96,39 +96,42 @@ export default {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
data(){return {
|
||||
menu: false,
|
||||
searchString: '',
|
||||
icons: [],
|
||||
};},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
menu: false,
|
||||
searchString: '',
|
||||
icons: [],
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
menu(value){
|
||||
if (value){
|
||||
menu(value) {
|
||||
if (value) {
|
||||
setTimeout(() => {
|
||||
if (this.$refs.iconSearchField){
|
||||
if (this.$refs.iconSearchField) {
|
||||
this.$refs.iconSearchField.$children[0].focus();
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
search(value, ack){
|
||||
methods: {
|
||||
search(value, ack) {
|
||||
this.searchString = value;
|
||||
this.icons = [];
|
||||
findIcons.call({search: value}, (error, result) => {
|
||||
findIcons.call({ search: value }, (error, result) => {
|
||||
ack(error);
|
||||
this.icons = result;
|
||||
});
|
||||
},
|
||||
select(icon){
|
||||
select(icon) {
|
||||
this.menu = false;
|
||||
this.change(icon);
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -21,34 +21,36 @@
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import SmartInput from '/imports/ui/components/global/SmartInputMixin.js';
|
||||
import SmartInput from '/imports/ui/components/global/SmartInputMixin.js';
|
||||
|
||||
export default {
|
||||
mixins: [SmartInput],
|
||||
props: {
|
||||
multiple: Boolean,
|
||||
},
|
||||
data(){ return {
|
||||
export default {
|
||||
mixins: [SmartInput],
|
||||
props: {
|
||||
multiple: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchInput: '',
|
||||
}},
|
||||
computed: {
|
||||
// Multiple combobox gets a long default debounce time while single
|
||||
// value gets a shorter one
|
||||
debounceTime() {
|
||||
if (Number.isFinite(this.debounce)){
|
||||
return this.debounce;
|
||||
} else if (Number.isFinite(this.context.debounceTime)){
|
||||
return this.context.debounceTime;
|
||||
} else {
|
||||
return this.multiple ? 1000 : 100;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
customChange(val){
|
||||
this.input(val);
|
||||
this.searchInput = '';
|
||||
},
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
// Multiple combobox gets a long default debounce time while single
|
||||
// value gets a shorter one
|
||||
debounceTime() {
|
||||
if (Number.isFinite(this.debounce)) {
|
||||
return this.debounce;
|
||||
} else if (Number.isFinite(this.context.debounceTime)) {
|
||||
return this.context.debounceTime;
|
||||
} else {
|
||||
return this.multiple ? 1000 : 100;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
customChange(val) {
|
||||
this.input(val);
|
||||
this.searchInput = '';
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -13,16 +13,18 @@ export default {
|
||||
context: { default: {} }
|
||||
},
|
||||
inheritAttrs: false,
|
||||
data(){ return {
|
||||
error: false,
|
||||
ackErrors: null,
|
||||
rulesErrors: null,
|
||||
focused: false,
|
||||
loading: false,
|
||||
dirty: false,
|
||||
safeValue: this.value,
|
||||
inputValue: this.value,
|
||||
};},
|
||||
data() {
|
||||
return {
|
||||
error: false,
|
||||
ackErrors: null,
|
||||
rulesErrors: null,
|
||||
focused: false,
|
||||
loading: false,
|
||||
dirty: false,
|
||||
safeValue: this.value,
|
||||
inputValue: this.value,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
value: [String, Number, Date, Array, Object, Boolean],
|
||||
errorMessages: [String, Array],
|
||||
@@ -34,11 +36,11 @@ export default {
|
||||
rules: Array,
|
||||
},
|
||||
watch: {
|
||||
focused(newFocus){
|
||||
focused(newFocus) {
|
||||
// If the value updated while we were focused, show it now on defocus
|
||||
// but not if we are waiting for our own writes to get persisted
|
||||
// and not if there is an error in our input
|
||||
if (!newFocus && !this.dirty && !this.error){
|
||||
if (!newFocus && !this.dirty && !this.error) {
|
||||
this.forceSafeValueUpdate();
|
||||
}
|
||||
// Start the loading bar on defocus if the input is dirty
|
||||
@@ -48,118 +50,118 @@ export default {
|
||||
!newFocus &&
|
||||
this.dirty &&
|
||||
!(this.rulesErrors && this.rulesErrors.length)
|
||||
){
|
||||
) {
|
||||
if (this.hasChangeListener) this.loading = true;
|
||||
}
|
||||
},
|
||||
dirty(newDirty){
|
||||
dirty(newDirty) {
|
||||
// Our changes were acknowledged, weren't in error, and we aren't focused,
|
||||
// make sure the internal value matches the database value
|
||||
if (!newDirty && !this.focused && !this.error){
|
||||
if (!newDirty && !this.focused && !this.error) {
|
||||
this.forceSafeValueUpdate();
|
||||
}
|
||||
},
|
||||
value(newValue){
|
||||
value(newValue) {
|
||||
if (
|
||||
!this.focused &&
|
||||
!(this.rulesErrors && this.rulesErrors.length)
|
||||
){
|
||||
) {
|
||||
this.safeValue = newValue;
|
||||
}
|
||||
},
|
||||
safeValue(){
|
||||
safeValue() {
|
||||
// The safe value only gets updated from the parent, so it must be valid
|
||||
this.error = false;
|
||||
this.ackErrors = null;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
input(val){
|
||||
input(val) {
|
||||
this.$emit('input', val);
|
||||
this.inputValue = val;
|
||||
this.dirty = true;
|
||||
|
||||
// Apply the rules if there are any
|
||||
this.rulesErrors = null;
|
||||
if (this.rules && this.rules.length){
|
||||
if (this.rules && this.rules.length) {
|
||||
this.rules.forEach(rule => {
|
||||
const result = rule(val);
|
||||
if (typeof result === 'string'){
|
||||
if (typeof result === 'string') {
|
||||
if (!this.rulesErrors) this.rulesErrors = [];
|
||||
this.rulesErrors.push(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (this.rulesErrors){
|
||||
if (this.rulesErrors) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.debouncedChange(val);
|
||||
},
|
||||
acknowledgeChange(error){
|
||||
acknowledgeChange(error) {
|
||||
this.loading = false;
|
||||
this.dirty = false;
|
||||
this.error = !!error;
|
||||
if (!error){
|
||||
this.ackErrors = null;
|
||||
} else if (typeof error === 'string'){
|
||||
this.ackErrors = error;
|
||||
} else if (error.reason){
|
||||
if (!error) {
|
||||
this.ackErrors = null;
|
||||
} else if (typeof error === 'string') {
|
||||
this.ackErrors = error;
|
||||
} else if (error.reason) {
|
||||
this.ackErrors = error.reason;
|
||||
} else if (error.message){
|
||||
} else if (error.message) {
|
||||
this.ackErrors = error.message;
|
||||
} else {
|
||||
this.ackErrors = 'Something went wrong'
|
||||
console.error(error);
|
||||
}
|
||||
this.ackErrors = 'Something went wrong'
|
||||
console.error(error);
|
||||
}
|
||||
},
|
||||
change(val){
|
||||
change(val) {
|
||||
this.dirty = true;
|
||||
if (this.hasChangeListener()) this.loading = true;
|
||||
this.$emit('change', val, this.acknowledgeChange);
|
||||
},
|
||||
hasChangeListener(){
|
||||
hasChangeListener() {
|
||||
return this.$listeners && this.$listeners.change;
|
||||
},
|
||||
forceSafeValueUpdate(){
|
||||
forceSafeValueUpdate() {
|
||||
// hack to force the value to update on the child component
|
||||
this.safeValue = null;
|
||||
this.$nextTick(() => this.safeValue = this.value);
|
||||
},
|
||||
focus(){
|
||||
focus() {
|
||||
this.$refs.input.focus();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
errors(){
|
||||
errors() {
|
||||
let errors = this.ackErrors ? [this.ackErrors] : [];
|
||||
if (Array.isArray(this.rulesErrors)){
|
||||
if (Array.isArray(this.rulesErrors)) {
|
||||
errors.push(...this.rulesErrors)
|
||||
}
|
||||
if (Array.isArray(this.errorMessages)){
|
||||
if (Array.isArray(this.errorMessages)) {
|
||||
errors.push(...this.errorMessages);
|
||||
} else if (typeof this.errorMessages === 'string' && this.errorMessages){
|
||||
} else if (typeof this.errorMessages === 'string' && this.errorMessages) {
|
||||
errors.push(this.errorMessages);
|
||||
}
|
||||
return errors;
|
||||
},
|
||||
isDisabled(){
|
||||
isDisabled() {
|
||||
return this.context.editPermission === false || this.disabled;
|
||||
},
|
||||
debounceTime() {
|
||||
if (Number.isFinite(this.debounce)){
|
||||
if (Number.isFinite(this.debounce)) {
|
||||
return this.debounce;
|
||||
} else if (Number.isFinite(this.context.debounceTime)){
|
||||
} else if (Number.isFinite(this.context.debounceTime)) {
|
||||
return this.context.debounceTime;
|
||||
} else {
|
||||
return 750;
|
||||
}
|
||||
},
|
||||
},
|
||||
created(){
|
||||
created() {
|
||||
this.debouncedChange = debounce(this.change, this.debounceTime);
|
||||
},
|
||||
beforeDestroy(){
|
||||
beforeDestroy() {
|
||||
this.debouncedChange.flush();
|
||||
},
|
||||
};
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import SmartInput from '/imports/ui/components/global/SmartInputMixin.js';
|
||||
import SmartInput from '/imports/ui/components/global/SmartInputMixin.js';
|
||||
|
||||
export default {
|
||||
mixins: [SmartInput],
|
||||
};
|
||||
export default {
|
||||
mixins: [SmartInput],
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import SmartInput from '/imports/ui/components/global/SmartInputMixin.js';
|
||||
import SmartInput from '/imports/ui/components/global/SmartInputMixin.js';
|
||||
|
||||
export default {
|
||||
mixins: [SmartInput],
|
||||
props: {
|
||||
autoGrow: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
export default {
|
||||
mixins: [SmartInput],
|
||||
props: {
|
||||
autoGrow: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -77,134 +77,149 @@
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
/**
|
||||
* TreeNode's are list item views of character properties. Every property which
|
||||
* can belong to the character is shown in the tree view of the character
|
||||
* the tree view shows off the full character structure, and where each part of
|
||||
* character comes from.
|
||||
**/
|
||||
import { canBeParent } from '/imports/api/parenting/parenting.js';
|
||||
import { getPropertyIcon } from '/imports/constants/PROPERTIES.js';
|
||||
import TreeNodeView from '/imports/ui/properties/treeNodeViews/TreeNodeView.vue';
|
||||
import { some } from 'lodash';
|
||||
/**
|
||||
* TreeNode's are list item views of character properties. Every property which
|
||||
* can belong to the character is shown in the tree view of the character
|
||||
* the tree view shows off the full character structure, and where each part of
|
||||
* character comes from.
|
||||
**/
|
||||
import { canBeParent } from '/imports/api/parenting/parenting.js';
|
||||
import { getPropertyIcon } from '/imports/constants/PROPERTIES.js';
|
||||
import TreeNodeView from '/imports/ui/properties/treeNodeViews/TreeNodeView.vue';
|
||||
import { some } from 'lodash';
|
||||
|
||||
export default {
|
||||
name: 'TreeNode',
|
||||
components: {
|
||||
TreeNodeView,
|
||||
export default {
|
||||
name: 'TreeNode',
|
||||
components: {
|
||||
TreeNodeView,
|
||||
},
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
group: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
organize: Boolean,
|
||||
children: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
getChildren: {
|
||||
type: Function,
|
||||
default: undefined,
|
||||
},
|
||||
selectedNode: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
selected: Boolean,
|
||||
startExpanded: Boolean,
|
||||
},
|
||||
data(){return {
|
||||
expanded: this.startExpanded || this.node._ancestorOfMatchedDocument ||
|
||||
group: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
organize: Boolean,
|
||||
children: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
getChildren: {
|
||||
type: Function,
|
||||
default: undefined,
|
||||
},
|
||||
selectedNode: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
selected: Boolean,
|
||||
startExpanded: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expanded: this.startExpanded || this.node._ancestorOfMatchedDocument ||
|
||||
some(this.selectedNode?.ancestors, ref => ref.id === this.node._id) ||
|
||||
false,
|
||||
}},
|
||||
computed: {
|
||||
hasChildren(){
|
||||
return this.children && !!this.children.length || this.lazy && !this.expanded;
|
||||
},
|
||||
showExpanded(){
|
||||
return this.expanded && (this.organize || this.hasChildren)
|
||||
},
|
||||
computedChildren(){
|
||||
let children = [];
|
||||
if (this.children){
|
||||
children.push(...this.children)
|
||||
}
|
||||
if (this.getChildren){
|
||||
children.push(...this.getChildren())
|
||||
}
|
||||
return children;
|
||||
},
|
||||
canExpand(){
|
||||
return canBeParent(this.node.type);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'node._ancestorOfMatchedDocument'(value){
|
||||
this.expanded = !!value ||
|
||||
some(this.selectedNode?.ancestors, ref => ref.id === this.node._id);
|
||||
},
|
||||
'selectedNode.ancestors'(value){
|
||||
this.expanded = !!some(value, ref => ref.id === this.node._id) || this.expanded;
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hasChildren() {
|
||||
return this.children && !!this.children.length || this.lazy && !this.expanded;
|
||||
},
|
||||
beforeCreate() {
|
||||
this.$options.components.TreeNodeList = require('./TreeNodeList.vue').default
|
||||
},
|
||||
methods: {
|
||||
icon(type){
|
||||
return getPropertyIcon(type);
|
||||
},
|
||||
}
|
||||
};
|
||||
showExpanded() {
|
||||
return this.expanded && (this.organize || this.hasChildren)
|
||||
},
|
||||
computedChildren() {
|
||||
let children = [];
|
||||
if (this.children) {
|
||||
children.push(...this.children)
|
||||
}
|
||||
if (this.getChildren) {
|
||||
children.push(...this.getChildren())
|
||||
}
|
||||
return children;
|
||||
},
|
||||
canExpand() {
|
||||
return canBeParent(this.node.type);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
'node._ancestorOfMatchedDocument'(value) {
|
||||
this.expanded = !!value ||
|
||||
some(this.selectedNode?.ancestors, ref => ref.id === this.node._id);
|
||||
},
|
||||
'selectedNode.ancestors'(value) {
|
||||
this.expanded = !!some(value, ref => ref.id === this.node._id) || this.expanded;
|
||||
},
|
||||
},
|
||||
beforeCreate() {
|
||||
this.$options.components.TreeNodeList = require('./TreeNodeList.vue').default
|
||||
},
|
||||
methods: {
|
||||
icon(type) {
|
||||
return getPropertyIcon(type);
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.rotate-90 {
|
||||
transform: rotate(90deg) translateZ(0);
|
||||
}
|
||||
.drag-area {
|
||||
box-shadow: -2px 0px 0px 0px #808080;
|
||||
margin-left: 0;
|
||||
min-height: 32px;
|
||||
}
|
||||
.handle {
|
||||
cursor: move;
|
||||
}
|
||||
.empty .drag-area {
|
||||
box-shadow: -2px 0px 0px 0px rgb(128, 128, 128, 0.4);
|
||||
}
|
||||
.empty .v-btn {
|
||||
opacity: 0.4;
|
||||
}
|
||||
.found {
|
||||
background: rgba(200, 0, 0, 0.1) !important;
|
||||
}
|
||||
.ghost {
|
||||
opacity: 0.5;
|
||||
background: rgba(251, 0, 0, 0.3);
|
||||
}
|
||||
.v-icon.v-icon--disabled {
|
||||
opacity: 0;
|
||||
}
|
||||
.v-icon {
|
||||
transition: none !important;
|
||||
}
|
||||
.theme--light .tree-node-title:hover {
|
||||
background-color: rgba(0,0,0,.04);
|
||||
}
|
||||
.theme--dark .tree-node-title:hover {
|
||||
background-color: rgba(255,255,255,.04);
|
||||
}
|
||||
.tree-node-title{
|
||||
transition: background ease 0.3s, color ease 0.15s;
|
||||
}
|
||||
.tree-node-title, .dummy-node {
|
||||
height: 40px;
|
||||
}
|
||||
.rotate-90 {
|
||||
transform: rotate(90deg) translateZ(0);
|
||||
}
|
||||
|
||||
.drag-area {
|
||||
box-shadow: -2px 0px 0px 0px #808080;
|
||||
margin-left: 0;
|
||||
min-height: 32px;
|
||||
}
|
||||
|
||||
.handle {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
.empty .drag-area {
|
||||
box-shadow: -2px 0px 0px 0px rgb(128, 128, 128, 0.4);
|
||||
}
|
||||
|
||||
.empty .v-btn {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
.found {
|
||||
background: rgba(200, 0, 0, 0.1) !important;
|
||||
}
|
||||
|
||||
.ghost {
|
||||
opacity: 0.5;
|
||||
background: rgba(251, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.v-icon.v-icon--disabled {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.v-icon {
|
||||
transition: none !important;
|
||||
}
|
||||
|
||||
.theme--light .tree-node-title:hover {
|
||||
background-color: rgba(0, 0, 0, .04);
|
||||
}
|
||||
|
||||
.theme--dark .tree-node-title:hover {
|
||||
background-color: rgba(255, 255, 255, .04);
|
||||
}
|
||||
|
||||
.tree-node-title {
|
||||
transition: background ease 0.3s, color ease 0.15s;
|
||||
}
|
||||
|
||||
.tree-node-title,
|
||||
.dummy-node {
|
||||
height: 40px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -33,102 +33,112 @@
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
import draggable from 'vuedraggable';
|
||||
import TreeNode from '/imports/ui/components/tree/TreeNode.vue';
|
||||
import { isParentAllowed } from '/imports/api/parenting/parenting.js';
|
||||
import draggable from 'vuedraggable';
|
||||
import TreeNode from '/imports/ui/components/tree/TreeNode.vue';
|
||||
import { isParentAllowed } from '/imports/api/parenting/parenting.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
draggable,
|
||||
TreeNode,
|
||||
},
|
||||
props: {
|
||||
node: Object,
|
||||
group: String,
|
||||
organize: Boolean,
|
||||
lazy: Boolean,
|
||||
children: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
selectedNode: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
ancestorsOfSelectedNode: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
startExpanded: Boolean,
|
||||
},
|
||||
data(){ return {
|
||||
expanded: this.startExpanded || false,
|
||||
export default {
|
||||
components: {
|
||||
draggable,
|
||||
TreeNode,
|
||||
},
|
||||
props: {
|
||||
node: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
group: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
organize: Boolean,
|
||||
lazy: Boolean,
|
||||
children: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
selectedNode: {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
ancestorsOfSelectedNode: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
startExpanded: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
expanded: this.startExpanded || false,
|
||||
displayedChildren: [],
|
||||
}},
|
||||
computed: {
|
||||
hasChildren(){
|
||||
return this.children && this.children.length;
|
||||
},
|
||||
showExpanded(){
|
||||
return this.expanded && (this.organize || this.hasChildren)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
children(value){
|
||||
this.displayedChildren = value;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
hasChildren() {
|
||||
return this.children && this.children.length;
|
||||
},
|
||||
showExpanded() {
|
||||
return this.expanded && (this.organize || this.hasChildren)
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
children(value) {
|
||||
this.displayedChildren = value;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.displayedChildren = this.children;
|
||||
},
|
||||
methods: {
|
||||
change({ added, moved }) {
|
||||
let event = moved || added;
|
||||
if (event) {
|
||||
let doc = event.element.node;
|
||||
let newIndex;
|
||||
if (event.newIndex === 0) {
|
||||
newIndex = -0.5;
|
||||
} else {
|
||||
if (event.newIndex < this.children.length) {
|
||||
let childAtNewIndex = this.children[event.newIndex];
|
||||
let indexOrder = childAtNewIndex.node.order;
|
||||
if (event.newIndex > event.oldIndex) {
|
||||
newIndex = indexOrder + 0.5;
|
||||
} else {
|
||||
newIndex = indexOrder - 0.5;
|
||||
}
|
||||
} else {
|
||||
let childBeforeNewIndex = this.children[event.newIndex - 1];
|
||||
newIndex = childBeforeNewIndex.node.order + 0.5;
|
||||
}
|
||||
}
|
||||
if (moved) {
|
||||
this.$emit('reordered', { doc, newIndex });
|
||||
} else if (added) {
|
||||
this.$emit('reorganized', { doc, parent: this.node, newIndex });
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted(){
|
||||
this.displayedChildren = this.children;
|
||||
move(evt) {
|
||||
let parentNode = evt.relatedContext.component.$parent.node
|
||||
let parentType = parentNode && parentNode.type || 'root';
|
||||
let childType = evt.draggedContext.element.node.type;
|
||||
let allowed = isParentAllowed({ parentType, childType });
|
||||
return allowed;
|
||||
},
|
||||
methods: {
|
||||
change({added, moved}){
|
||||
let event = moved || added;
|
||||
if (event){
|
||||
let doc = event.element.node;
|
||||
let newIndex;
|
||||
if (event.newIndex === 0){
|
||||
newIndex = -0.5;
|
||||
} else {
|
||||
if (event.newIndex < this.children.length){
|
||||
let childAtNewIndex = this.children[event.newIndex];
|
||||
let indexOrder = childAtNewIndex.node.order;
|
||||
if (event.newIndex > event.oldIndex){
|
||||
newIndex = indexOrder + 0.5;
|
||||
} else {
|
||||
newIndex = indexOrder - 0.5;
|
||||
}
|
||||
} else {
|
||||
let childBeforeNewIndex = this.children[event.newIndex - 1];
|
||||
newIndex = childBeforeNewIndex.node.order + 0.5;
|
||||
}
|
||||
}
|
||||
if (moved){
|
||||
this.$emit('reordered', {doc, newIndex});
|
||||
} else if (added){
|
||||
this.$emit('reorganized', {doc, parent: this.node, newIndex});
|
||||
}
|
||||
}
|
||||
},
|
||||
move(evt){
|
||||
let parentNode = evt.relatedContext.component.$parent.node
|
||||
let parentType = parentNode && parentNode.type || 'root';
|
||||
let childType = evt.draggedContext.element.node.type;
|
||||
let allowed = isParentAllowed({parentType, childType});
|
||||
return allowed;
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
.flip-list-leave-active {
|
||||
display: none;
|
||||
}
|
||||
.flip-list-move {
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
.no-move {
|
||||
transition: transform 0s;
|
||||
}
|
||||
.flip-list-leave-active {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.flip-list-move {
|
||||
transition: transform 0.5s;
|
||||
}
|
||||
|
||||
.no-move {
|
||||
transition: transform 0s;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user