Added svg icons, currently only for items
This commit is contained in:
@@ -17,6 +17,7 @@ import {
|
||||
renewDocIds
|
||||
} from '/imports/api/parenting/parenting.js';
|
||||
import {setDocToLastOrder} from '/imports/api/parenting/order.js';
|
||||
import { storedIconsSchema } from '/imports/api/icons/Icons.js';
|
||||
|
||||
let CreatureProperties = new Mongo.Collection('creatureProperties');
|
||||
|
||||
@@ -36,6 +37,10 @@ let CreaturePropertySchema = new SimpleSchema({
|
||||
type: Boolean,
|
||||
optional: true,
|
||||
},
|
||||
icon: {
|
||||
type: storedIconsSchema,
|
||||
optional: true,
|
||||
}
|
||||
});
|
||||
|
||||
for (let key in propertySchemasIndex){
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import SimpleSchema from 'simpl-schema';
|
||||
import { ValidatedMethod } from 'meteor/mdg:validated-method';
|
||||
import { assertAdmin } from '/imports/api/sharing/sharingPermissions.js';
|
||||
|
||||
let Icons = new Mongo.Collection('icons');
|
||||
|
||||
iconsSchema = new SimpleSchema({
|
||||
let iconsSchema = new SimpleSchema({
|
||||
name: {
|
||||
type: String,
|
||||
unique: true,
|
||||
@@ -33,21 +35,57 @@ if (Meteor.isServer) {
|
||||
});
|
||||
}
|
||||
|
||||
const storedIconsSchema = new SimpleSchema({
|
||||
name: {
|
||||
type: String,
|
||||
},
|
||||
shape: {
|
||||
type: String,
|
||||
},
|
||||
});
|
||||
|
||||
Icons.attachSchema(iconsSchema);
|
||||
|
||||
/*
|
||||
console.warn("Write Icons is not secure, disable before deployment")
|
||||
// This method does not validate icons against the schema, use wisely;
|
||||
const writeIcons = new ValidatedMethod({
|
||||
name: 'writeIcons',
|
||||
name: 'icons.methods.write',
|
||||
validate: null,
|
||||
run(icons){
|
||||
assertAdmin(this.userId);
|
||||
if (Meteor.isServer){
|
||||
this.unblock();
|
||||
Icons.rawCollection().insert(icons, {ordered: false});
|
||||
}
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
export { writeIcons };
|
||||
const findIcons = new ValidatedMethod({
|
||||
name: 'icons.methods.find',
|
||||
validate: new SimpleSchema({
|
||||
search: {
|
||||
type: String,
|
||||
max: 30,
|
||||
optional: true,
|
||||
},
|
||||
}).validator(),
|
||||
run({search}){
|
||||
if (!search) return [];
|
||||
if (!Meteor.isServer) return;
|
||||
return Icons.find(
|
||||
{ $text: {$search: search} },
|
||||
{
|
||||
// relevant documents have a higher score.
|
||||
fields: {
|
||||
score: { $meta: 'textScore' }
|
||||
},
|
||||
// `score` property specified in the projection fields above.
|
||||
sort: {
|
||||
score: { $meta: 'textScore' }
|
||||
}
|
||||
}
|
||||
).fetch();
|
||||
}
|
||||
})
|
||||
|
||||
export { writeIcons, findIcons, storedIconsSchema };
|
||||
export default Icons;
|
||||
|
||||
@@ -113,3 +113,17 @@ export function assertDocViewPermission(doc, userId){
|
||||
let root = getRoot(doc);
|
||||
assertViewPermission(root, userId);
|
||||
}
|
||||
|
||||
export function assertAdmin(userId){
|
||||
assertIdValid(userId);
|
||||
let user = Meteor.users.findOne(userId, {fields: {roles: 1}});
|
||||
if (!user){
|
||||
throw new Meteor.Error('Permission denied',
|
||||
'UserId does not match any existing user');
|
||||
}
|
||||
let isAdmin = user.roles && user.roles.includes('admin')
|
||||
if (!isAdmin){
|
||||
throw new Meteor.Error('Permission denied',
|
||||
'User does not have the admin role');
|
||||
}
|
||||
}
|
||||
|
||||
120
app/imports/ui/components/global/IconPicker.vue
Normal file
120
app/imports/ui/components/global/IconPicker.vue
Normal file
@@ -0,0 +1,120 @@
|
||||
<template lang="html">
|
||||
<v-menu
|
||||
v-model="menu"
|
||||
:close-on-content-click="false"
|
||||
lazy
|
||||
transition="slide-y-transition"
|
||||
min-width="290px"
|
||||
style="overflow-y: auto;"
|
||||
>
|
||||
<template #activator="{ on }">
|
||||
<div class="layout row align-center">
|
||||
<v-label>{{ label }}</v-label>
|
||||
<v-btn
|
||||
:loading="loading"
|
||||
large
|
||||
icon
|
||||
v-on="on"
|
||||
>
|
||||
<svg-icon
|
||||
v-if="safeValue && safeValue.shape"
|
||||
large
|
||||
:shape="safeValue.shape"
|
||||
/>
|
||||
<v-icon
|
||||
v-else
|
||||
large
|
||||
>
|
||||
highlight_alt
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
<v-card>
|
||||
<v-card-text>
|
||||
<div class="layout row">
|
||||
<text-field
|
||||
ref="iconSearchField"
|
||||
label="Search icons"
|
||||
append-icon="search"
|
||||
clearable
|
||||
:value="searchString"
|
||||
@change="search"
|
||||
/>
|
||||
<v-btn
|
||||
icon
|
||||
@click="select()"
|
||||
>
|
||||
<v-icon>
|
||||
cancel
|
||||
</v-icon>
|
||||
</v-btn>
|
||||
</div>
|
||||
<v-layout
|
||||
row
|
||||
wrap
|
||||
style="max-height: 400px; overflow-y: auto;"
|
||||
>
|
||||
<v-scale-transition
|
||||
group
|
||||
hide-on-leave
|
||||
>
|
||||
<v-btn
|
||||
v-for="icon in icons"
|
||||
:key="icon._id"
|
||||
icon
|
||||
large
|
||||
@click="select(icon)"
|
||||
>
|
||||
<svg-icon
|
||||
:shape="icon.shape"
|
||||
x-large
|
||||
/>
|
||||
</v-btn>
|
||||
</v-scale-transition>
|
||||
</v-layout>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-menu>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SvgIcon from '/imports/ui/components/global/SvgIcon.vue';
|
||||
import SmartInput from '/imports/ui/components/global/SmartInputMixin.js';
|
||||
import { findIcons } from '/imports/api/icons/Icons.js';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SvgIcon,
|
||||
},
|
||||
mixins: [SmartInput],
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: 'Icon',
|
||||
},
|
||||
},
|
||||
data(){return {
|
||||
menu: false,
|
||||
searchString: '',
|
||||
icons: [],
|
||||
};},
|
||||
methods: {
|
||||
search(value, ack){
|
||||
this.searchString = value;
|
||||
this.icons = [];
|
||||
findIcons.call({search: value}, (error, result) => {
|
||||
ack(error);
|
||||
this.icons = result;
|
||||
});
|
||||
},
|
||||
select(icon){
|
||||
this.menu = false;
|
||||
this.change(icon);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
</style>
|
||||
@@ -23,7 +23,7 @@ export default {
|
||||
inputValue: this.value,
|
||||
};},
|
||||
props: {
|
||||
value: [String, Number, Date, Array, Boolean],
|
||||
value: [String, Number, Date, Array, Object, Boolean],
|
||||
errorMessages: [String, Array],
|
||||
disabled: Boolean,
|
||||
},
|
||||
|
||||
89
app/imports/ui/components/global/SvgIcon.vue
Normal file
89
app/imports/ui/components/global/SvgIcon.vue
Normal file
@@ -0,0 +1,89 @@
|
||||
<template lang="html">
|
||||
<i
|
||||
aria-hidden
|
||||
role="img"
|
||||
class="v-icon"
|
||||
:class="themeClasses"
|
||||
:style="color && `color: ${color}`"
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512"
|
||||
:style="`height: ${size}; width: ${size}`"
|
||||
>
|
||||
<path
|
||||
:d="shape"
|
||||
/>
|
||||
</svg>
|
||||
</i>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const SIZE_MAP = {
|
||||
xSmall: '12px',
|
||||
small: '16px',
|
||||
default: '24px',
|
||||
medium: '28px',
|
||||
large: '36px',
|
||||
xLarge: '40px',
|
||||
}
|
||||
export default {
|
||||
inject: {
|
||||
theme: {
|
||||
default: {
|
||||
isDark: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
props: {
|
||||
shape: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
xSmall: Boolean,
|
||||
small: Boolean,
|
||||
medium: Boolean,
|
||||
large: Boolean,
|
||||
xLarge: Boolean,
|
||||
},
|
||||
computed: {
|
||||
isDark () {
|
||||
if (this.dark === true) {
|
||||
// explicitly dark
|
||||
return true
|
||||
} else if (this.light === true) {
|
||||
// explicitly light
|
||||
return false
|
||||
} else {
|
||||
// inherit from parent, or default false if there is none
|
||||
return this.theme.isDark
|
||||
}
|
||||
},
|
||||
themeClasses() {
|
||||
return {
|
||||
'theme--dark': this.isDark,
|
||||
'theme--light': !this.isDark,
|
||||
}
|
||||
},
|
||||
size() {
|
||||
if (this.xSmall) return SIZE_MAP['xSmall'];
|
||||
if (this.small) return SIZE_MAP['small'];
|
||||
if (this.medium) return SIZE_MAP['medium'];
|
||||
if (this.large) return SIZE_MAP['large'];
|
||||
if (this.xLarge) return SIZE_MAP['xLarge'];
|
||||
return SIZE_MAP['default'];
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="css" scoped>
|
||||
svg {
|
||||
color: inherit;
|
||||
fill: currentColor;
|
||||
}
|
||||
</style>
|
||||
@@ -1,17 +1,21 @@
|
||||
import Vue from 'vue';
|
||||
// Global components
|
||||
import DatePicker from '/imports/ui/components/global/DatePicker.vue';
|
||||
import IconPicker from '/imports/ui/components/global/IconPicker.vue';
|
||||
import TextField from '/imports/ui/components/global/TextField.vue';
|
||||
import TextArea from '/imports/ui/components/global/TextArea.vue';
|
||||
import SmartSelect from '/imports/ui/components/global/SmartSelect.vue';
|
||||
import SmartCombobox from '/imports/ui/components/global/SmartCombobox.vue';
|
||||
import SmartCheckbox from '/imports/ui/components/global/SmartCheckbox.vue';
|
||||
import SmartSwitch from '/imports/ui/components/global/SmartSwitch.vue';
|
||||
import SvgIcon from '/imports/ui/components/global/SvgIcon.vue';
|
||||
|
||||
Vue.component('DatePicker', DatePicker);
|
||||
Vue.component('IconPicker', IconPicker);
|
||||
Vue.component('TextField', TextField);
|
||||
Vue.component('TextArea', TextArea);
|
||||
Vue.component('SmartSelect', SmartSelect);
|
||||
Vue.component('SmartCombobox', SmartCombobox);
|
||||
Vue.component('SmartCheckbox', SmartCheckbox);
|
||||
Vue.component('SmartSwitch', SmartSwitch);
|
||||
Vue.component('SvgIcon', SvgIcon);
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
:flat="flat"
|
||||
>
|
||||
<property-icon
|
||||
:type="model && model.type"
|
||||
:model="model"
|
||||
class="mr-2"
|
||||
/>
|
||||
<v-toolbar-title v-if="model">
|
||||
|
||||
@@ -8,47 +8,17 @@
|
||||
align-center
|
||||
>
|
||||
<upload-btn
|
||||
:file-changed-callback="fileChanged"
|
||||
title="Metadata JSON"
|
||||
@file-update="metadataFileChanged"
|
||||
/>
|
||||
<v-text-field
|
||||
ref="iconSearchField"
|
||||
label="Search"
|
||||
append-icon="search"
|
||||
@click:append="updateSearchString"
|
||||
@keydown.enter="updateSearchString"
|
||||
<upload-btn
|
||||
title="Sprite JSON"
|
||||
@file-update="fileChanged"
|
||||
/>
|
||||
<icon-picker
|
||||
:value="testIcon"
|
||||
@change="testIconChange"
|
||||
/>
|
||||
<v-container
|
||||
grid-list-md
|
||||
fill-height
|
||||
>
|
||||
<v-layout
|
||||
row
|
||||
wrap
|
||||
>
|
||||
<v-flex
|
||||
v-for="icon in icons"
|
||||
:key="icon._id._str || icon._id"
|
||||
xs3
|
||||
md2
|
||||
xl1
|
||||
>
|
||||
<v-card>
|
||||
<v-card-title class="title">
|
||||
{{ icon.name }}
|
||||
</v-card-title>
|
||||
<v-card-text>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 512 512"
|
||||
><path
|
||||
fill="#000"
|
||||
:d="icon.shape"
|
||||
/></svg>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</v-layout>
|
||||
</v-card-text>
|
||||
</v-card>
|
||||
@@ -57,29 +27,31 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import importIcons from '/imports/ui/icons/importIcons.js';
|
||||
import Icons from '/imports/api/icons/Icons.js';
|
||||
import {importIcons, importIconMetadata} from '/imports/ui/icons/importIcons.js';
|
||||
import IconPicker from '/imports/ui/components/global/IconPicker.vue';
|
||||
import UploadButton from 'vuetify-upload-button';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
IconPicker,
|
||||
UploadBtn: UploadButton,
|
||||
},
|
||||
data(){ return {
|
||||
searchString: '',
|
||||
testIcon: undefined,
|
||||
}},
|
||||
methods: {
|
||||
fileChanged (file) {
|
||||
importIcons(file);
|
||||
},
|
||||
updateSearchString(){
|
||||
this.searchString = this.$refs.iconSearchField.internalValue;
|
||||
metadataFileChanged(file){
|
||||
importIconMetadata(file);
|
||||
},
|
||||
},
|
||||
meteor: {
|
||||
$subscribe: {
|
||||
searchIcons() {
|
||||
return [this.searchString];
|
||||
},
|
||||
},
|
||||
icons(){
|
||||
return Icons.find({}, { sort: [['score', 'desc']] });
|
||||
testIconChange(value, ack){
|
||||
setTimeout(() => {
|
||||
this.testIcon = value;
|
||||
ack();
|
||||
}, 1000);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,31 +1,50 @@
|
||||
import { writeIcons } from '/imports/api/icons/Icons.js';
|
||||
|
||||
/*
|
||||
* Import a SVG sprite file. All the icons must contain one id and one path with a
|
||||
* single 'd' attribute.
|
||||
* Import a SVG sprite file.
|
||||
*
|
||||
* A svg sprite file can be created by downloading the entire archive of
|
||||
* https://game-icons.net/ then using the search function with *.svg to copy
|
||||
* all the individual files into a single directory, and then using the npm
|
||||
* sprite-generator to run `svg-sprite-generate -d icons -o sprite.svg` to save
|
||||
* the sprite file.
|
||||
* all the individual files into a single directory, and then using
|
||||
* `npm i -g svg-sprite-generator` `npm i -g xml-js`
|
||||
* run `svg-sprite-generate -d icons -o sprite.xml`
|
||||
* run `xml-js sprite.xml --out sprite.json --compact true `
|
||||
* to save the sprite file as json.
|
||||
*/
|
||||
let metadata;
|
||||
|
||||
export default function importIcons(file){
|
||||
let id, d, icons = [];
|
||||
export function importIcons(file){
|
||||
let reader = new FileReader();
|
||||
if (! metadata) throw 'No metadata to build with';
|
||||
|
||||
reader.onload = function(){
|
||||
reader.result.match(/i?d="([^"])+"/gi).forEach(s => {
|
||||
if (s[0] === 'i'){
|
||||
id = s.slice(4, -1);
|
||||
} else if (s[0] === 'd'){
|
||||
d = s.slice(3, -1);
|
||||
icons.push ({_id: Random.id(), name: id, shape: d});
|
||||
}
|
||||
let data = JSON.parse(reader.result);
|
||||
let icons = [];
|
||||
data.svg.symbol.forEach(iconData => {
|
||||
let name = iconData._attributes.id;
|
||||
let shape = iconData.path[1]._attributes.d;
|
||||
let icon = metadata[name] || {};
|
||||
icon._id = Random.id();
|
||||
icon.name = name;
|
||||
icon.shape = shape;
|
||||
icons.push(icon);
|
||||
});
|
||||
writeIcons.call(icons);
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
};
|
||||
}
|
||||
|
||||
// Get metadata here:
|
||||
// https://gist.github.com/ThaumRystra/ffb264dea8c32e15de95f775596194a4
|
||||
// It is probably out of date though
|
||||
export function importIconMetadata(file){
|
||||
let reader = new FileReader();
|
||||
|
||||
reader.onload = function(){
|
||||
metadata = JSON.parse(reader.result);
|
||||
console.log(metadata);
|
||||
};
|
||||
|
||||
reader.readAsText(file);
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
flat
|
||||
>
|
||||
<property-icon
|
||||
:type="selectedNode && selectedNode.type"
|
||||
:model="selectedNode"
|
||||
class="mr-2"
|
||||
/>
|
||||
<div class="title">
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
<template lang="html">
|
||||
<div class="item-form">
|
||||
<div class="layout column align-center">
|
||||
<smart-switch
|
||||
label="Equipped"
|
||||
class="no-flex"
|
||||
:value="model.equipped"
|
||||
:error-messages="errors.equipped"
|
||||
@change="change('equipped', ...arguments)"
|
||||
/>
|
||||
<div class="layout row justify-space-around">
|
||||
<div>
|
||||
<icon-picker
|
||||
label="Icon"
|
||||
:value="model.icon"
|
||||
:error-messages="errors.icon"
|
||||
@change="change('icon', ...arguments)"
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<smart-switch
|
||||
label="Equipped"
|
||||
:value="model.equipped"
|
||||
:error-messages="errors.equipped"
|
||||
@change="change('equipped', ...arguments)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="layout row wrap">
|
||||
<text-field
|
||||
@@ -66,12 +75,14 @@
|
||||
name="Advanced"
|
||||
standalone
|
||||
>
|
||||
<!--
|
||||
<smart-switch
|
||||
label="Show increment buttons"
|
||||
:value="model.showIncrement"
|
||||
:error-messages="errors.showIncrement"
|
||||
@change="change('showIncrement', ...arguments)"
|
||||
/>
|
||||
-->
|
||||
<smart-combobox
|
||||
label="Tags"
|
||||
class="mr-2"
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
<template lang="html">
|
||||
<v-icon :color="color">
|
||||
<svg-icon
|
||||
v-if="model.icon"
|
||||
:shape="model.icon.shape"
|
||||
:color="color"
|
||||
/>
|
||||
<v-icon
|
||||
v-else
|
||||
:color="color"
|
||||
>
|
||||
{{ icon }}
|
||||
</v-icon>
|
||||
</template>
|
||||
@@ -9,12 +17,18 @@ import { getPropertyIcon } from '/imports/constants/PROPERTIES.js';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
type: String,
|
||||
color: String,
|
||||
model: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: undefined,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
icon(){
|
||||
return getPropertyIcon(this.type);
|
||||
return getPropertyIcon(this.model && this.model.type);
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="layout row align-center justify-start">
|
||||
<property-icon
|
||||
class="mr-2"
|
||||
:type="model.type"
|
||||
:model="model"
|
||||
:class="selected && 'primary--text'"
|
||||
:color="model.color"
|
||||
/>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="layout row align-center justify-start">
|
||||
<property-icon
|
||||
class="mr-2"
|
||||
:type="model.type"
|
||||
:model="model"
|
||||
:color="model.color"
|
||||
:class="selected && 'primary--text'"
|
||||
/>
|
||||
|
||||
@@ -1,11 +1,18 @@
|
||||
<template lang="html">
|
||||
<div class="layout row align-center justify-start">
|
||||
<property-icon
|
||||
class="mr-2"
|
||||
:model="model"
|
||||
:color="model.color"
|
||||
:class="selected && 'primary--text'"
|
||||
/>
|
||||
<v-icon
|
||||
v-if="model.equipped"
|
||||
class="mr-2"
|
||||
:class="selected && 'primary--text'"
|
||||
:color="model.color"
|
||||
small
|
||||
>
|
||||
{{ model.equipped ? 'check_box' : 'check_box_outline_blank' }}
|
||||
pan_tool
|
||||
</v-icon>
|
||||
<div
|
||||
class="text-no-wrap text-truncate"
|
||||
|
||||
@@ -14,7 +14,8 @@ import CharacterSheetToolbarItems from '/imports/ui/creature/character/Character
|
||||
import CharacterSheetToolbarExtension from '/imports/ui/creature/character/CharacterSheetToolbarExtension.vue';
|
||||
import SignIn from '/imports/ui/pages/SignIn.vue' ;
|
||||
import Register from '/imports/ui/pages/Register.vue';
|
||||
import Friends from '/imports/ui/pages/Friends.vue' ;
|
||||
import IconAdmin from '/imports/ui/icons/IconAdmin.vue';
|
||||
//import Friends from '/imports/ui/pages/Friends.vue' ;
|
||||
import Feedback from '/imports/ui/pages/Feedback.vue' ;
|
||||
import Account from '/imports/ui/pages/Account.vue' ;
|
||||
import InviteSuccess from '/imports/ui/pages/InviteSuccess.vue' ;
|
||||
@@ -48,6 +49,24 @@ function ensureLoggedIn(to, from, next){
|
||||
});
|
||||
}
|
||||
|
||||
function ensureAdmin(to, from, next){
|
||||
Tracker.autorun((computation) => {
|
||||
if (userSubscription.ready()){
|
||||
computation.stop();
|
||||
const user = Meteor.user();
|
||||
if (user){
|
||||
if (user.roles && user.roles.includes('admin')){
|
||||
next()
|
||||
} else {
|
||||
next({name: 'home'});
|
||||
}
|
||||
} else {
|
||||
next({ name: 'signIn', query: { redirect: to.path} });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function claimInvite(to, from, next){
|
||||
Tracker.autorun((computation) => {
|
||||
if (userSubscription.ready()){
|
||||
@@ -222,19 +241,13 @@ RouterFactory.configure(factory => {
|
||||
meta: {
|
||||
title: 'Patreon Tier Too Low',
|
||||
},
|
||||
},{
|
||||
path: '/icon-admin',
|
||||
name: 'iconAdmin',
|
||||
component: IconAdmin,
|
||||
beforeEnter: ensureAdmin,
|
||||
},
|
||||
]);
|
||||
// Icon admin routes
|
||||
if (Meteor.isDevelopment){
|
||||
let IconAdmin = require('/imports/ui/icons/IconAdmin.vue').default;
|
||||
factory.addRoutes([
|
||||
{
|
||||
path: '/icon-admin',
|
||||
name: 'iconAdmin',
|
||||
component: IconAdmin,
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
// Not found route has lowest priority
|
||||
|
||||
971
app/package-lock.json
generated
971
app/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -41,7 +41,7 @@
|
||||
"vue-router": "^3.1.6",
|
||||
"vuedraggable": "^2.23.2",
|
||||
"vuetify": "^1.5.24",
|
||||
"vuetify-upload-button": "^1.2.2",
|
||||
"vuetify-upload-button": "^2.0.2",
|
||||
"vuex": "^3.1.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
Reference in New Issue
Block a user