Progress on forms overhaul: insert lib node broken
This commit is contained in:
@@ -72,14 +72,12 @@ let LibraryNodeSchema = new SimpleSchema({
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.variableName,
|
||||
},
|
||||
/* TODO: Disabled for now until image upload is working
|
||||
// Image to display when filling the slot
|
||||
slotFillImage: {
|
||||
type: String,
|
||||
optional: true,
|
||||
max: STORAGE_LIMITS.url,
|
||||
},
|
||||
*/
|
||||
// Fill more than one quantity in a slot, like feats and ability score
|
||||
// improvements, filtered out of UI if there isn't space in quantityExpected
|
||||
slotQuantityFilled: {
|
||||
|
||||
@@ -45,7 +45,10 @@
|
||||
<v-tab :disabled="!type">
|
||||
Create
|
||||
</v-tab>
|
||||
<v-tab :disabled="!type">
|
||||
<v-tab
|
||||
v-if="!hideLibraryTab"
|
||||
:disabled="!type"
|
||||
>
|
||||
Library
|
||||
</v-tab>
|
||||
</v-tabs>
|
||||
@@ -77,7 +80,10 @@
|
||||
/>
|
||||
</v-card-text>
|
||||
</v-tab-item>
|
||||
<v-tab-item :disabled="!type">
|
||||
<v-tab-item
|
||||
v-if="!hideLibraryTab"
|
||||
:disabled="!type"
|
||||
>
|
||||
<v-expansion-panels
|
||||
multiple
|
||||
inset
|
||||
@@ -222,6 +228,7 @@ export default {
|
||||
type: Object,
|
||||
default: undefined,
|
||||
},
|
||||
hideLibraryTab: Boolean,
|
||||
},
|
||||
reactiveProvide: {
|
||||
name: 'context',
|
||||
@@ -258,7 +265,6 @@ export default {
|
||||
this.changeType(this.type);
|
||||
},
|
||||
methods: {
|
||||
|
||||
propertyHelpChanged(value){
|
||||
Meteor.users.setPreference.call({
|
||||
preference: 'hidePropertySelectDialogHelp',
|
||||
@@ -291,10 +297,6 @@ export default {
|
||||
if (this.currentLimit >= this.countAll) return;
|
||||
this._subs.searchLibraryNodes.setData('limit', this.currentLimit + 32);
|
||||
},
|
||||
insert(){
|
||||
if (!this.selectedNodeIds.length) return;
|
||||
this.$store.dispatch('popDialogStack', this.selectedNodeIds);
|
||||
},
|
||||
changeType(type){
|
||||
this._subs.searchLibraryNodes.setData('type', type);
|
||||
if (!type) return;
|
||||
|
||||
@@ -208,7 +208,9 @@ export default {
|
||||
}
|
||||
});
|
||||
},
|
||||
change({path, value, ack}){
|
||||
change(arg) {
|
||||
const { path, value, ack } = arg;
|
||||
console.log('creaturePropDialogChangeHandler', arg);
|
||||
if (path && path[0] === 'equipped'){
|
||||
equipItem.call({_id: this.currentId, equipped: value}, ack);
|
||||
return;
|
||||
|
||||
@@ -28,15 +28,16 @@
|
||||
size="64"
|
||||
/>
|
||||
</div>
|
||||
<component
|
||||
:is="model.type + 'Form'"
|
||||
<property-form
|
||||
v-else-if="model && editing"
|
||||
:key="_id"
|
||||
class="library-node-form"
|
||||
:model="model"
|
||||
:embedded="embedded"
|
||||
@change="change"
|
||||
@push="push"
|
||||
@pull="pull"
|
||||
@add-child="addLibraryNode"
|
||||
/>
|
||||
<component
|
||||
:is="model.type + 'Viewer'"
|
||||
@@ -87,6 +88,7 @@
|
||||
pullFromLibraryNode,
|
||||
softRemoveLibraryNode,
|
||||
restoreLibraryNode,
|
||||
insertNode,
|
||||
} from '/imports/api/library/LibraryNodes.js';
|
||||
import duplicateLibraryNode from '/imports/api/library/methods/duplicateLibraryNode.js';
|
||||
import DialogBase from '/imports/client/ui/dialogStack/DialogBase.vue';
|
||||
@@ -103,15 +105,12 @@
|
||||
import { snackbar } from '/imports/client/ui/components/snackbars/SnackbarQueue.js';
|
||||
import getPropertyTitle from '/imports/client/ui/properties/shared/getPropertyTitle.js';
|
||||
import copyLibraryNodeTo from '/imports/api/library/methods/copyLibraryNodeTo.js';
|
||||
|
||||
let formIndex = {};
|
||||
for (let key in propertyFormIndex){
|
||||
formIndex[key + 'Form'] = propertyFormIndex[key];
|
||||
}
|
||||
|
||||
import { getHighestOrder } from '/imports/api/parenting/order.js';
|
||||
import { getUserTier } from '/imports/api/users/patreon/tiers.js';
|
||||
import PropertyForm from '/imports/client/ui/properties/PropertyForm.vue';
|
||||
let viewerIndex = {};
|
||||
for (let key in propertyViewerIndex){
|
||||
formIndex[key + 'Viewer'] = propertyViewerIndex[key];
|
||||
viewerIndex[key + 'Viewer'] = propertyViewerIndex[key];
|
||||
}
|
||||
|
||||
export default {
|
||||
@@ -119,7 +118,7 @@
|
||||
PropertyToolbar,
|
||||
PropertyIcon,
|
||||
DialogBase,
|
||||
...formIndex,
|
||||
PropertyForm,
|
||||
...viewerIndex,
|
||||
},
|
||||
props: {
|
||||
@@ -272,6 +271,44 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
addLibraryNode() {
|
||||
// Check tier has paid benefits
|
||||
let tier = getUserTier(Meteor.userId());
|
||||
if (!(tier && tier.paidBenefits)){
|
||||
this.$store.commit('pushDialogStack', {
|
||||
component: 'tier-too-low-dialog',
|
||||
elementId: 'insert-library-node-button',
|
||||
});
|
||||
return;
|
||||
}
|
||||
let parentPropertyId = this.model._id;
|
||||
this.$store.commit('pushDialogStack', {
|
||||
component: 'add-creature-property-dialog',
|
||||
elementId: 'insert-creature-property-btn',
|
||||
data: {
|
||||
parentDoc: this.model,
|
||||
creatureId: this.creatureId,
|
||||
hideLibraryTab: true,
|
||||
},
|
||||
callback(result){
|
||||
if (!result) return;
|
||||
let parentRef = {
|
||||
id: parentPropertyId,
|
||||
collection: 'libraryNodes',
|
||||
};
|
||||
let order = getHighestOrder({
|
||||
collection: LibraryNodes,
|
||||
ancestorId: parentRef.id,
|
||||
}) + 0.5;
|
||||
let creatureProperty = result;
|
||||
// Get order and parent
|
||||
creatureProperty.order = order;
|
||||
// Insert the property
|
||||
let id = insertNode.call({creatureProperty, parentRef});
|
||||
return `tree-node-${id}`;
|
||||
}
|
||||
});
|
||||
},
|
||||
remove(){
|
||||
let _id = this.currentId;
|
||||
softRemoveLibraryNode.call({_id});
|
||||
|
||||
@@ -11,27 +11,105 @@
|
||||
label="Name"
|
||||
style="flex-basis: 320px;"
|
||||
:value="model.name"
|
||||
@change="change('name', ...arguments)"
|
||||
@change="(value, ack) => $emit('change', {path: ['name'], value, ack})"
|
||||
/>
|
||||
<icon-color-menu
|
||||
:model="model"
|
||||
@change="$emit('change', $event)"
|
||||
@change="e => $emit('change', e)"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
<component
|
||||
:is="model.type"
|
||||
class="creature-property-form"
|
||||
class="creature-property-form mb-4"
|
||||
:model="model"
|
||||
@change="$emit('change', ...arguments)"
|
||||
@push="$emit('push', ...arguments)"
|
||||
@pull="$emit('pull', ...arguments)"
|
||||
@change="e => $emit('change', e)"
|
||||
@push="e => $emit('push', e)"
|
||||
@pull="e => $emit('pull', e)"
|
||||
>
|
||||
<form-section
|
||||
v-if="context.isLibraryForm"
|
||||
name="Library Options"
|
||||
>
|
||||
<v-row
|
||||
v-if="context.isLibraryForm"
|
||||
>
|
||||
<v-col
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<smart-select
|
||||
label="Slot Fill Type"
|
||||
style="flex-basis: 300px;"
|
||||
clearable
|
||||
hint="The property type that this slot filler pretends to be when being searched for by a slot"
|
||||
:items="slotTypes"
|
||||
:value="model.slotFillerType"
|
||||
@change="(value, ack) => $emit('change', {path: ['slotFillerType'], value, ack})"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<text-field
|
||||
label="Slot Fill Quantity"
|
||||
type="number"
|
||||
min="0"
|
||||
hint="How many properties this counts as when filling a slot"
|
||||
:value="model.slotQuantityFilled"
|
||||
@change="(value, ack) => $emit('change', {path: ['slotQuantityFilled'], value, ack})"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<text-field
|
||||
v-if="context.isLibraryForm"
|
||||
label="Condition"
|
||||
hint="A caclulation to determine if this property can be added to a character"
|
||||
placeholder="Always active"
|
||||
:value="model.slotFillerCondition"
|
||||
@change="(value, ack) => $emit('change', {path: ['slotFillerCondition'], value, ack})"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<text-field
|
||||
v-if="context.isLibraryForm"
|
||||
label="Condition Error Text"
|
||||
hint="Text to display if the condition isn't met"
|
||||
placeholder="Always active"
|
||||
:value="model.slotFillerConditionNote"
|
||||
@change="(value, ack) => $emit('change', {path: ['slotFillerConditionNote'], value, ack})"
|
||||
/>
|
||||
</v-col>
|
||||
<v-col
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<smart-combobox
|
||||
label="Library Tags"
|
||||
multiple
|
||||
chips
|
||||
deletable-chips
|
||||
hint="Used to let slots find this property in a library"
|
||||
:value="model.tags"
|
||||
@change="(value, ack) => $emit('change', {path: ['libraryTags'], value, ack})"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</form-section>
|
||||
</component>
|
||||
<v-divider
|
||||
class="mb-4"
|
||||
/>
|
||||
<v-divider inset />
|
||||
<v-row>
|
||||
<v-col
|
||||
cols="12"
|
||||
md="6"
|
||||
>
|
||||
<smart-combobox
|
||||
label="Tags"
|
||||
@@ -40,7 +118,7 @@
|
||||
deletable-chips
|
||||
hint="Tags let other properties target this property with interactions"
|
||||
:value="model.tags"
|
||||
@change="change('tags', ...arguments)"
|
||||
@change="(value, ack) => $emit('change', {path: ['tags'], value, ack})"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
@@ -71,7 +149,7 @@
|
||||
tile
|
||||
color="accent"
|
||||
data-id="insert-creature-property-btn"
|
||||
@click="$emit('add-child')"
|
||||
@click="$event=>$emit('add-child')"
|
||||
>
|
||||
<v-icon left>
|
||||
mdi-plus
|
||||
@@ -83,9 +161,15 @@
|
||||
tile
|
||||
color="accent"
|
||||
data-id="insert-creature-property-btn"
|
||||
@click="$emit('add-child')"
|
||||
@click="$event=>$emit('add-child')"
|
||||
>
|
||||
...Other
|
||||
<v-icon
|
||||
v-if="!suggestedChildren.length"
|
||||
left
|
||||
>
|
||||
mdi-plus
|
||||
</v-icon>
|
||||
{{ suggestedChildren.length ? '...Other' : 'Child' }}
|
||||
</v-btn>
|
||||
</outlined-input>
|
||||
</v-col>
|
||||
@@ -106,7 +190,13 @@ import IconColorMenu from '/imports/client/ui/properties/forms/shared/IconColorM
|
||||
import CreaturePropertiesTree from '/imports/client/ui/creature/creatureProperties/CreaturePropertiesTree.vue';
|
||||
import OutlinedInput from '/imports/client/ui/properties/viewers/shared/OutlinedInput.vue';
|
||||
import { getSuggestedChildren } from '/imports/constants/PROPERTIES.js';
|
||||
import PROPERTIES from '/imports/constants/PROPERTIES.js';
|
||||
|
||||
const slotTypes = [];
|
||||
for (let key in PROPERTIES) {
|
||||
slotTypes.push({ text: PROPERTIES[key].name, value: key });
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ComputedField,
|
||||
@@ -118,6 +208,9 @@ export default {
|
||||
OutlinedInput,
|
||||
...propertyFormIndex,
|
||||
},
|
||||
inject: {
|
||||
context: { default: {} }
|
||||
},
|
||||
props: {
|
||||
model: {
|
||||
type: [Object, Array],
|
||||
@@ -125,19 +218,28 @@ export default {
|
||||
},
|
||||
embedded: Boolean, // This dialog is embedded in a page
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
slotTypes,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
suggestedChildren() {
|
||||
if (!this.model?.type) return;
|
||||
return getSuggestedChildren(this.model.type);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
change(path, value, ack){
|
||||
if (!Array.isArray(path)){
|
||||
path = [path];
|
||||
mounted() {
|
||||
// Don't autofocus on mobile, it brings up the on-screen keyboard
|
||||
if (this.$vuetify.breakpoint.smAndDown) return;
|
||||
|
||||
setTimeout(() => {
|
||||
if (this.$refs.focusFirst && this.$refs.focusFirst.focus) {
|
||||
this.$refs.focusFirst.focus()
|
||||
}
|
||||
this.$emit('change', {path, value, ack});
|
||||
},
|
||||
}, 300);
|
||||
},
|
||||
methods: {
|
||||
selectSubProperty(_id){
|
||||
this.$store.commit('pushDialogStack', {
|
||||
component: 'creature-property-dialog',
|
||||
|
||||
@@ -172,6 +172,7 @@
|
||||
@change="change('reset', ...arguments)"
|
||||
/>
|
||||
</form-section>
|
||||
<slot />
|
||||
</form-sections>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -65,13 +65,15 @@
|
||||
:error-messages="errors.silent"
|
||||
@change="change('silent', ...arguments)"
|
||||
/>
|
||||
<form-section
|
||||
v-if="$slots.children"
|
||||
name="Children"
|
||||
standalone
|
||||
>
|
||||
<slot name="children" />
|
||||
</form-section>
|
||||
<form-sections>
|
||||
<form-section
|
||||
v-if="$slots.children"
|
||||
name="Children"
|
||||
>
|
||||
<slot name="children" />
|
||||
</form-section>
|
||||
<slot />
|
||||
</form-sections>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -259,6 +259,7 @@
|
||||
/>
|
||||
</div>
|
||||
</form-section>
|
||||
<slot />
|
||||
</form-sections>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -44,12 +44,14 @@
|
||||
:error-messages="errors.silent"
|
||||
@change="change('silent', ...arguments)"
|
||||
/>
|
||||
<form-section
|
||||
name="Children"
|
||||
standalone
|
||||
>
|
||||
<slot name="children" />
|
||||
</form-section>
|
||||
<form-sections>
|
||||
<form-section
|
||||
name="Children"
|
||||
>
|
||||
<slot name="children" />
|
||||
</form-section>
|
||||
<slot />
|
||||
</form-sections>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@
|
||||
@change="change('tags', ...arguments)"
|
||||
/>
|
||||
</form-section>
|
||||
<slot />
|
||||
</form-sections>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -1,31 +1,8 @@
|
||||
<template lang="html">
|
||||
<div class="folder-form">
|
||||
<div class="layout wrap">
|
||||
<text-field
|
||||
ref="focusFirst"
|
||||
label="Name"
|
||||
style="flex-basis: 300px;"
|
||||
:value="model.name"
|
||||
:error-messages="errors.name"
|
||||
@change="change('name', ...arguments)"
|
||||
/>
|
||||
<form-sections>
|
||||
<form-section
|
||||
v-if="$slots.children"
|
||||
name="Children"
|
||||
>
|
||||
<slot name="children" />
|
||||
</form-section>
|
||||
|
||||
<form-section name="Advanced">
|
||||
<smart-combobox
|
||||
label="Tags"
|
||||
multiple
|
||||
chips
|
||||
deletable-chips
|
||||
:value="model.tags"
|
||||
@change="change('tags', ...arguments)"
|
||||
/>
|
||||
<smart-switch
|
||||
label="Group children on a card"
|
||||
:value="model.groupStats"
|
||||
@@ -69,6 +46,7 @@
|
||||
</div>
|
||||
</v-expand-transition>
|
||||
</form-section>
|
||||
<slot />
|
||||
</form-sections>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -19,22 +19,12 @@ export default {
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
mounted(){
|
||||
// Don't autofocus on mobile, it brings up the on-screen keyboard
|
||||
if (this.$vuetify.breakpoint.smAndDown) return;
|
||||
|
||||
setTimeout(() => {
|
||||
if (this.$refs.focusFirst && this.$refs.focusFirst.focus){
|
||||
this.$refs.focusFirst.focus()
|
||||
}
|
||||
}, 300);
|
||||
},
|
||||
methods: {
|
||||
change(path, value, ack){
|
||||
if (!Array.isArray(path)){
|
||||
change(path, value, ack) {
|
||||
if (!Array.isArray(path)) {
|
||||
path = [path];
|
||||
}
|
||||
this.$emit('change', {path, value, ack});
|
||||
this.$emit('change', { path, value, ack });
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
<template lang="html">
|
||||
<div class="folder-viewer" />
|
||||
<div class="folder-viewer">
|
||||
<v-row
|
||||
dense
|
||||
align="stretch"
|
||||
justify="center"
|
||||
justify-sm="start"
|
||||
>
|
||||
<property-field
|
||||
name="Name"
|
||||
:value="model.name"
|
||||
/>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="js">
|
||||
|
||||
@@ -377,7 +377,11 @@ RouterFactory.configure(router => {
|
||||
|
||||
function redirectIfMaintenance(to, from, next) {
|
||||
if (!MAINTENANCE_MODE) return next();
|
||||
if (to?.path === '/admin' || to?.path === '/maintenance' || to?.path === '/sign-in') return next();
|
||||
if (
|
||||
to?.path === '/admin' ||
|
||||
to?.path === '/maintenance' ||
|
||||
to?.path === '/sign-in'
|
||||
) return next();
|
||||
Tracker.autorun((computation) => {
|
||||
if (userSubscription.ready()) {
|
||||
computation.stop();
|
||||
|
||||
@@ -170,6 +170,9 @@ const PROPERTIES = Object.freeze({
|
||||
helpText: 'A slot in the character sheet is used to specify that a property needs to be selected from a library to fill the slot. The slot can determine what tags it is looking for, and any subscribed library property with matching tags can fill the slot',
|
||||
suggestedParents: [],
|
||||
},
|
||||
/* Deprecated
|
||||
* Slot fillers are no longer suggested as possible property types,
|
||||
* but existing slot fillers are still supported for backwards compatibility
|
||||
slotFiller: {
|
||||
icon: 'mdi-power-plug-outline',
|
||||
name: 'Slot filler',
|
||||
@@ -177,6 +180,7 @@ const PROPERTIES = Object.freeze({
|
||||
helpText: 'A slot filler allows for more advanced logic when it attempts to fill a slot. It can masquarade as any property type, and calculate whether it should fill a slot or not.',
|
||||
suggestedParents: ['propertySlot'],
|
||||
},
|
||||
*/
|
||||
spellList: {
|
||||
icon: '$vuetify.icons.spell_list',
|
||||
name: 'Spell list',
|
||||
|
||||
@@ -25,15 +25,22 @@ Migrations.add({
|
||||
});
|
||||
|
||||
export function migratePropUp(bulk, prop) {
|
||||
let update;
|
||||
// If the prop is a slot filler with an image, move it
|
||||
if (prop.type === 'slotFiller' && typeof prop.picture === 'string') {
|
||||
update = { $set: {} };
|
||||
update.$set.slotFillImage = prop.picture;
|
||||
update.$unset = { picture: 1 };
|
||||
}
|
||||
// If there are tags, copy them to libraryTags and set findable flags
|
||||
if (Array.isArray(prop.tags) && prop.tags.length) {
|
||||
bulk.find({ _id: prop._id }).updateOne({
|
||||
$set: {
|
||||
libraryTags: prop.tags,
|
||||
fillSlots: true,
|
||||
searchable: true,
|
||||
},
|
||||
});
|
||||
update = update || { $set: {} };
|
||||
update.$set.libraryTags = prop.tags;
|
||||
update.$set.fillSlots = true;
|
||||
update.$set.searchable = true;
|
||||
}
|
||||
if (update) {
|
||||
bulk.find({ _id: prop._id }).updateOne(update);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,6 +58,33 @@ const emptyFolderExample = {
|
||||
}],
|
||||
};
|
||||
|
||||
const exampleSlotFiller = {
|
||||
_id: 'DXPYsHKF6888h3hZs',
|
||||
type: 'slotFiller',
|
||||
name: 'Slot Filler Example',
|
||||
'picture': 'https://url.to.pic',
|
||||
'tags': ['slot', 'tags'],
|
||||
'parent': {
|
||||
'collection': 'creatures',
|
||||
'id': 'm9sdCvs6iDf7qRaGv',
|
||||
},
|
||||
'ancestors': [{
|
||||
'collection': 'creatures',
|
||||
'id': 'm9sdCvs6iDf7qRaGv',
|
||||
}],
|
||||
};
|
||||
const expectedSlotFillerUpdate = {
|
||||
$set: {
|
||||
'libraryTags': ['slot', 'tags'],
|
||||
'fillSlots': true,
|
||||
'searchable': true,
|
||||
'slotFillImage': 'https://url.to.pic',
|
||||
},
|
||||
$unset: {
|
||||
picture: 1,
|
||||
},
|
||||
};
|
||||
|
||||
const DownMergeExample = {
|
||||
_id: 'DXPYsHKF6W8Hh3hZs',
|
||||
type: 'feature',
|
||||
@@ -104,6 +131,13 @@ describe('dbv2 Migrate library nodes', function () {
|
||||
assert.isUndefined(update, 'There should be no update on a prop with no tags');
|
||||
assert.equal(timesUpdate, 0, 'Update should be called zero times on a prop with no tags');
|
||||
});
|
||||
it('Migrates slot fillers up', function () {
|
||||
const bulk = stubBulk();
|
||||
migratePropUp(bulk, exampleSlotFiller);
|
||||
const { query, update } = bulk.result();
|
||||
assert.deepEqual(query, { _id: 'DXPYsHKF6888h3hZs' }, 'The query should match the id of the given prop');
|
||||
assert.deepEqual(update, expectedSlotFillerUpdate, 'The update should match the expected update');
|
||||
});
|
||||
it('Merges tags when down migrating', function () {
|
||||
const bulk = stubBulk();
|
||||
migratePropDown(bulk, DownMergeExample);
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
import './dbv1/dbv1.js';
|
||||
import './dbv2/dbv2.js';
|
||||
|
||||
Reference in New Issue
Block a user