Merge pull request #209 from vlad0337187/feature/allow-collections-importing

Work in Progress: feature/allow-collections-importing
This commit is contained in:
Liyas Thomas
2019-10-24 19:14:12 +05:30
committed by GitHub
14 changed files with 780 additions and 383 deletions

View File

@@ -1,14 +1,13 @@
<template> <template>
<div> <div>
<modal v-if="show" @close="hideModel"> <modal v-if="show" @close="hideModal">
<div slot="header"> <div slot="header">
<ul> <ul>
<li> <li>
<div class="flex-wrap"> <div class="flex-wrap">
<h3 class="title" v-if='!newCollection.hasOwnProperty("collectionIndex")'>New Collection</h3> <h3 class="title">New Collection</h3>
<h3 class="title" v-if='newCollection.hasOwnProperty("collectionIndex")'>Edit Collection</h3>
<div> <div>
<button class="icon" @click="hideModel" > <button class="icon" @click="hideModal" >
<i class="material-icons">close</i> <i class="material-icons">close</i>
</button> </button>
</div> </div>
@@ -19,21 +18,17 @@
<div slot="body"> <div slot="body">
<ul> <ul>
<li> <li>
<input type="text" v-model="newCollection.name" placeholder="My New Collection" /> <input type="text" v-model="name" placeholder="My New Collection" />
</li> </li>
</ul> </ul>
</div> </div>
<div slot="footer"> <div slot="footer">
<ul> <ul>
<li> <li>
<button class="icon" @click="addNewCollection" v-if='!newCollection.hasOwnProperty("collectionIndex")'> <button class="icon" @click="addNewCollection">
<i class="material-icons">add</i> <i class="material-icons">add</i>
<span>Create</span> <span>Create</span>
</button> </button>
<button class="icon" @click="saveCollection" v-if='newCollection.hasOwnProperty("collectionIndex")'>
<i class="material-icons">save</i>
<span>Save</span>
</button>
</li> </li>
</ul> </ul>
</div> </div>
@@ -47,47 +42,22 @@ import modal from "../../components/modal";
export default { export default {
props: { props: {
show: Boolean, show: Boolean,
editingCollection: Object,
}, },
components: { components: {
modal, modal,
}, },
data() { data() {
return { return {
newCollection: { name: undefined,
name: '',
folders: [],
requests: [],
},
} }
}, },
watch: {
show() {
if (!this.editingCollection.collectionIndex) return;
this.newCollection = Object.assign({}, this.editingCollection);
},
},
methods: { methods: {
addNewCollection() { addNewCollection() {
const newCollection = Object.assign({}, this.newCollection); this.$store.commit('postwoman/addNewCollection', { name: this.$data.name })
this.$emit('new-collection', newCollection); this.$emit('hide-modal')
this.newCollection = {
name: '',
folders: [],
requests: [],
};
}, },
saveCollection() { hideModal() {
const savedCollection = Object.assign({}, this.newCollection); this.$emit('hide-modal')
this.$emit('saved-collection', savedCollection);
this.newCollection = {
name: '',
folders: [],
requests: [],
};
},
hideModel() {
this.$emit('hide-model');
}, },
}, },
}; };

View File

@@ -4,10 +4,9 @@
<ul> <ul>
<li> <li>
<div class="flex-wrap"> <div class="flex-wrap">
<h3 class="title" v-if='!newFolder.hasOwnProperty("folderIndex")'>New Folder</h3> <h3 class="title">New Folder</h3>
<h3 class="title" v-if='newFolder.hasOwnProperty("folderIndex")'>Edit Folder</h3>
<div> <div>
<button class="icon" @click="hideModel"> <button class="icon" @click="hideModal">
<i class="material-icons">close</i> <i class="material-icons">close</i>
</button> </button>
</div> </div>
@@ -18,21 +17,17 @@
<div slot="body"> <div slot="body">
<ul> <ul>
<li> <li>
<input type="text" v-model="newFolder.name" placeholder="My New Folder" /> <input type="text" v-model="name" placeholder="My New Folder" />
</li> </li>
</ul> </ul>
</div> </div>
<div slot="footer"> <div slot="footer">
<ul> <ul>
<li> <li>
<button class="icon" @click="addNewFolder" v-if='!newFolder.hasOwnProperty("folderIndex")'> <button class="icon" @click="addNewFolder">
<i class="material-icons">add</i> <i class="material-icons">add</i>
<span>Create</span> <span>Create</span>
</button> </button>
<button class="icon" @click="saveFolder" v-if='newFolder.hasOwnProperty("folderIndex")'>
<i class="material-icons">save</i>
<span>Save</span>
</button>
</li> </li>
</ul> </ul>
</div> </div>
@@ -44,45 +39,25 @@ import modal from "../../components/modal";
export default { export default {
props: { props: {
show: Boolean, show : Boolean,
editingFolder: Object, collection : Object,
collectionIndex : Number,
}, },
components: { components: {
modal, modal,
}, },
data() { data() {
return { return {
newFolder: { name: undefined,
name: '',
requests: [],
},
} }
}, },
watch: {
show() {
if (!this.editingFolder.folderIndex) return;
this.newFolder = Object.assign({}, this.editingFolder);
},
},
methods: { methods: {
addNewFolder() { addNewFolder() {
const newFolder = Object.assign({}, this.newFolder); this.$store.commit('postwoman/addNewFolder', { folder: { name: this.$data.name }, collectionIndex: this.$props.collectionIndex })
this.$emit('new-folder', newFolder); this.hideModal()
this.newFolder = {
name: '',
requests: [],
};
}, },
saveFolder() { hideModal() {
const savedFolder = Object.assign({}, this.newFolder); this.$emit('hide-modal')
this.$emit('saved-folder', savedFolder);
this.newFolder = {
name: '',
requests: [],
};
},
hideModel() {
this.$emit('hide-model');
}, },
}, },
}; };

View File

@@ -1,14 +1,5 @@
<template> <template>
<div> <div>
<addFolder
v-bind:show="showModal"
v-on:new-folder="addNewFolder"
v-on:hide-model='toggleModal'
v-bind:editing-folder="selectedFolder"
v-on:saved-folder="savedFolder"
>
</addFolder>
<div class="flex-wrap"> <div class="flex-wrap">
<div> <div>
<button class="icon" @click="toggleShowChildren"> <button class="icon" @click="toggleShowChildren">
@@ -22,10 +13,10 @@
<button class="icon" @click="removeCollection" v-tooltip="'Delete collection'"> <button class="icon" @click="removeCollection" v-tooltip="'Delete collection'">
<i class="material-icons">delete</i> <i class="material-icons">delete</i>
</button> </button>
<button class="icon" @click="editCollection" v-tooltip="'Edit collection'"> <button class="icon" @click="$emit('edit-collection')" v-tooltip="'Edit collection'">
<i class="material-icons">create</i> <i class="material-icons">create</i>
</button> </button>
<button class="icon" @click="toggleModal" v-tooltip="'New Folder'"> <button class="icon" @click="$emit('add-folder')" v-tooltip="'New Folder'">
<i class="material-icons">create_new_folder</i> <i class="material-icons">create_new_folder</i>
</button> </button>
</div> </div>
@@ -35,10 +26,11 @@
<ul> <ul>
<li v-for="(folder, index) in collection.folders" :key="folder.name"> <li v-for="(folder, index) in collection.folders" :key="folder.name">
<folder <folder
:folder="folder" v-bind:folder = "folder"
:folderIndex="index" v-bind:folderIndex = "index"
:collection-index="collectionIndex" v-bind:collection-index = "collectionIndex"
v-on:edit-folder="editFolder" v-on:edit-folder = "editFolder(collectionIndex, folder, index)"
v-on:edit-request = "$emit('edit-request', $event)"
/> />
</li> </li>
<li v-if="(collection.folders.length === 0) && (collection.requests.length === 0)"> <li v-if="(collection.folders.length === 0) && (collection.requests.length === 0)">
@@ -49,10 +41,11 @@
<ul> <ul>
<li v-for="(request, index) in collection.requests" :key="index"> <li v-for="(request, index) in collection.requests" :key="index">
<request <request
:request="request" v-bind:request = "request"
:collection-index="collectionIndex" v-bind:collection-index = "collectionIndex"
:folder-index="-1" v-bind:folder-index = "-1"
:request-index="index" v-bind:request-index = "index"
v-on:edit-request = "$emit('edit-request', { request, collectionIndex, folderIndex: undefined, requestIndex: index })"
></request> ></request>
</li> </li>
</ul> </ul>
@@ -74,62 +67,36 @@
</style> </style>
<script> <script>
import folder from './folder'; import folder from './folder';
import addFolder from "./addFolder";
import request from './request'; import request from './request';
export default { export default {
components: { components: {
folder, folder,
addFolder,
request, request,
}, },
props: { props: {
collectionIndex: Number, collectionIndex : Number,
collection: Object, collection : Object,
}, },
data () { data () {
return { return {
showChildren: false, showChildren : false,
showModal: false, selectedFolder : {},
selectedFolder: {},
}; };
}, },
methods: { methods: {
toggleShowChildren() { toggleShowChildren() {
this.showChildren = !this.showChildren; this.showChildren = !this.showChildren;
}, },
toggleModal() {
this.showModal = !this.showModal;
},
addNewFolder(newFolder) {
this.$store.commit('postwoman/addFolder', {
collectionIndex: this.collectionIndex,
folder: newFolder,
});
this.showModal = false;
},
editCollection() {
this.$emit('edit-collection', {
collectionIndex: this.collectionIndex,
collection: this.collection,
});
},
removeCollection() { removeCollection() {
if (!confirm("Are you sure you want to remove this collection?")) return; if (!confirm("Are you sure you want to remove this collection?")) return;
this.$store.commit('postwoman/removeCollection', { this.$store.commit('postwoman/removeCollection', {
collectionIndex: this.collectionIndex, collectionIndex: this.collectionIndex,
}); });
}, },
editFolder(payload) { editFolder(collectionIndex, folder, folderIndex) {
const { folder, collectionIndex, folderIndex } = payload; this.$emit('edit-folder', { collectionIndex, folder, folderIndex })
this.selectedFolder = Object.assign({ collectionIndex, folderIndex }, folder);
this.showModal = true;
},
savedFolder(savedFolder) {
this.$store.commit('postwoman/saveFolder', { savedFolder });
this.showModal = false;
this.selectedFolder = {};
}, },
} }
}; };

View File

@@ -0,0 +1,67 @@
<template>
<div>
<modal v-if="show" @close="hideModel">
<div slot='header'>
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">Edit Collection</h3>
<div>
<button class="icon" @click="hideModel" >
<i class="material-icons">close</i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div slot="body">
<ul>
<li>
<input type="text" v-model="name" v-bind:placeholder="editingCollection.name" />
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="saveCollection">
<i class="material-icons">save</i>
<span>Save</span>
</button>
</li>
</ul>
</div>
</modal>
</div>
</template>
<script>
import modal from "../../components/modal";
export default {
props: {
show : Boolean,
editingCollection : Object,
editingCollectionIndex : Number,
},
components: {
modal,
},
data() {
return {
name: undefined,
}
},
methods: {
saveCollection() {
const collectionUpdated = { ...this.$props.editingCollection, name: this.$data.name }
this.$store.commit('postwoman/editCollection', { collection: collectionUpdated, collectionIndex: this.$props.editingCollectionIndex })
this.$emit('hide-modal');
},
hideModel() {
this.$emit('hide-modal');
},
},
};
</script>

View File

@@ -0,0 +1,70 @@
<template>
<modal v-if="show" @close="show = false">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">Edit Folder</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div slot="body">
<ul>
<li>
<input type="text" v-model="name" v-bind:placeholder="folder.name" />
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="editFolder">
<i class="material-icons">add</i>
<span>Save</span>
</button>
</li>
</ul>
</div>
</modal>
</template>
<script>
import modal from "../../components/modal";
export default {
props: {
show : Boolean,
collection : Object,
collectionIndex : Number,
folder : Object,
folderIndex : Number,
},
components: {
modal,
},
data() {
return {
name: undefined,
}
},
methods: {
editFolder() {
this.$store.commit('postwoman/editFolder', {
collectionIndex : this.$props.collectionIndex,
folder : { ...this.$props.folder, name: this.$data.name },
folderIndex : this.$props.folderIndex,
})
this.hideModal()
},
hideModal() {
this.$emit('hide-modal')
},
},
};
</script>

View File

@@ -0,0 +1,132 @@
<!--
Made this component to be separate from `saveRequest` as it handles request editing
only related to it's positioning and naming inside of collections.
-->
<template>
<div>
<modal v-if="show" @close="hideModal">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">Edit Request</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div slot="body">
<ul>
<li>
<input type="text" v-model="requestUpdateData.name" v-bind:placeholder="request.name" />
<select type="text" v-model="requestUpdateData.collectionIndex" >
<option
v-for="(collection, index) in $store.state.postwoman.collections"
:key = "index"
:value = "index">
{{ collection.name }}
</option>
</select>
<select type="text" v-model="requestUpdateData.folderIndex">
<option
:key = "undefined"
:value = "undefined">
</option>
<option
v-for="(folder, index) in folders"
:key = "index"
:value = "index">
{{ folder.name }}
</option>
</select>
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="saveRequest">
<i class="material-icons">save</i>
<span>Save</span>
</button>
</li>
</ul>
</div>
</modal>
</div>
</template>
<script>
import modal from "../../components/modal";
export default {
props: {
show : Boolean,
collectionIndex : Number,
folderIndex : Number,
request : Object,
requestIndex : Number,
},
components: {
modal,
},
data() {
return {
requestUpdateData : {
name : undefined,
collectionIndex : undefined,
folderIndex : undefined,
},
}
},
watch: {
'requestUpdateData.collectionIndex': function resetFolderIndex() {
// if user choosen some folder, than selected other collection, which doesn't have any folders
// than `requestUpdateData.folderIndex` won't be reseted
this.$data.requestUpdateData.folderIndex = undefined
},
},
computed: {
folders() {
const userSelectedAnyCollection = this.$data.requestUpdateData.collectionIndex !== undefined
if (!userSelectedAnyCollection) return []
return this.$store.state.postwoman.collections[this.$data.requestUpdateData.collectionIndex].folders
},
},
methods: {
saveRequest() {
const userSelectedAnyCollection = this.$data.requestUpdateData.collectionIndex !== undefined
const requestUpdated = {
...this.$props.request,
name : this.$data.requestUpdateData.name || this.$props.request.name,
collection : userSelectedAnyCollection ? this.$data.requestUpdateData.collectionIndex : this.$props.collectionIndex,
folder : this.$data.requestUpdateData.folderIndex,
}
// pass data separately to don't depend on request's collection, folder fields
// probably, they should be deprecated because they don't describe request itself
this.$store.commit('postwoman/editRequest', {
requestOld : this.$props.request,
requestOldCollectionIndex : this.$props.collectionIndex,
requestOldFolderIndex : this.$props.folderIndex,
requestOldIndex : this.$props.requestIndex,
requestNew : requestUpdated,
requestNewCollectionIndex : requestUpdated.collection,
requestNewFolderIndex : requestUpdated.folder,
});
this.hideModal()
},
hideModal() {
this.$emit('hide-modal')
},
},
};
</script>

View File

@@ -23,10 +23,11 @@
<ul> <ul>
<li v-for="(request, index) in folder.requests" :key="index"> <li v-for="(request, index) in folder.requests" :key="index">
<request <request
:request="request" v-bind:request = "request"
:collection-index="collectionIndex" v-bind:collection-index = "collectionIndex"
:folder-index="folderIndex" v-bind:folder-index = "folderIndex"
:request-index="index" v-bind:request-index = "index"
v-on:edit-request = "$emit('edit-request', { request, collectionIndex, folderIndex, requestIndex: index })"
></request> ></request>
</li> </li>
<li v-if="folder.requests.length === 0"> <li v-if="folder.requests.length === 0">
@@ -55,9 +56,9 @@ import request from './request';
export default { export default {
props: { props: {
folder: Object, folder : Object,
collectionIndex: Number, collectionIndex : Number,
folderIndex: Number, folderIndex : Number,
}, },
components: { components: {
request, request,
@@ -82,11 +83,7 @@ export default {
}); });
}, },
editFolder() { editFolder() {
this.$emit('edit-folder', { this.$emit('edit-folder')
collectionIndex: this.collectionIndex,
folderIndex: this.folderIndex,
folder: this.folder,
});
}, },
} }
}; };

View File

@@ -5,7 +5,7 @@
<ul> <ul>
<li> <li>
<div class="flex-wrap"> <div class="flex-wrap">
<h3 class="title">Export Collections</h3> <h3 class="title">Import / Export Collections</h3>
<div> <div>
<button class="icon" @click="hideModel"> <button class="icon" @click="hideModel">
<i class="material-icons">close</i> <i class="material-icons">close</i>
@@ -21,6 +21,20 @@
</div> </div>
<div slot="footer"> <div slot="footer">
<ul> <ul>
<li>
<button class="icon" @click="openDialogChooseFileToReplaceWith">
<i class="material-icons">get_app</i>
<span>Replace with JSON</span>
<input type="file" @change="replaceWithJSON" style="display: none;" ref="inputChooseFileToReplaceWith">
</button>
</li>
<li>
<button class="icon" @click="openDialogChooseFileToImportFrom">
<i class="material-icons">get_app</i>
<span>Import from JSON</span>
<input type="file" @change="importFromJSON" style="display: none;" ref="inputChooseFileToImportFrom">
</button>
</li>
<li> <li>
<button class="icon" @click="exportJSON"> <button class="icon" @click="exportJSON">
<i class="material-icons">get_app</i> <i class="material-icons">get_app</i>
@@ -50,7 +64,31 @@ export default {
}, },
methods: { methods: {
hideModel() { hideModel() {
this.$emit('hide-model'); this.$emit('hide-modal');
},
openDialogChooseFileToReplaceWith() {
this.$refs.inputChooseFileToReplaceWith.click();
},
openDialogChooseFileToImportFrom() {
this.$refs.inputChooseFileToImportFrom.click();
},
replaceWithJSON() {
let reader = new FileReader();
reader.onload = (event) => {
let content = event.target.result;
let collections = JSON.parse(content);
this.$store.commit('postwoman/replaceCollections', collections);
};
reader.readAsText(this.$refs.inputChooseFileToReplaceWith.files[0]);
},
importFromJSON() {
let reader = new FileReader();
reader.onload = (event) => {
let content = event.target.result;
let collections = JSON.parse(content);
this.$store.commit('postwoman/importCollections', collections);
};
reader.readAsText(this.$refs.inputChooseFileToImportFrom.files[0]);
}, },
exportJSON() { exportJSON() {
let text = this.collectionJson; let text = this.collectionJson;

View File

@@ -1,27 +1,64 @@
<!--
TODO:
- probably refactor and pass event arguments to modals directly without unpacking
-->
<template> <template>
<div class="collections-wrapper"> <div class="collections-wrapper">
<addCollection <addCollection
v-bind:show="showAddModel" v-bind:show = "showModalAdd"
v-on:new-collection="addNewCollection" v-on:hide-modal = 'displayModalAdd(false)'
v-on:hide-model='toggleModal'
v-bind:editing-collection="selectedCollection"
v-on:saved-collection="savedCollection"
> >
</addCollection> </addCollection>
<editCollection
<exportCollection :show="showExportModal" v-on:hide-model='toggleExport'></exportCollection> v-bind:show = "showModalEdit"
v-bind:editingCollection = "editingCollection"
v-bind:editingCollectionIndex = "editingCollectionIndex"
v-on:hide-modal = 'displayModalEdit(false)'
>
</editCollection>
<addFolder
v-bind:show = "showModalAddFolder"
v-bind:collection = "editingCollection"
v-bind:collectionIndex = "editingCollectionIndex"
v-on:hide-modal = 'displayModalAddFolder(false)'
>
</addFolder>
<editFolder
v-bind:show = "showModalEditFolder"
v-bind:collection = "editingCollection"
v-bind:collectionIndex = "editingCollectionIndex"
v-bind:folder = "editingFolder"
v-bind:folderIndex = "editingFolderIndex"
v-on:hide-modal = 'displayModalEditFolder(false)'
>
</editFolder>
<editRequest
v-bind:show = "showModalEditRequest"
v-bind:collectionIndex = "editingCollectionIndex"
v-bind:folderIndex = "editingFolderIndex"
v-bind:request = "editingRequest"
v-bind:requestIndex = "editingRequestIndex"
v-on:hide-modal = "displayModalEditRequest(false)"
>
</editRequest>
<importExportCollections
v-bind:show = "showModalImportExport"
v-on:hide-modal = 'displayModalImportExport(false)'
>
</importExportCollections>
<div class='flex-wrap'> <div class='flex-wrap'>
<div> <div>
<button class="icon" @click="toggleModal"> <button class="icon" @click="displayModalAdd(true)">
<i class="material-icons">add</i> <i class="material-icons">add</i>
<span>New</span> <span>New</span>
</button> </button>
</div> </div>
<div> <div>
<button class="icon" @click="toggleExport"> <button class="icon" @click="displayModalImportExport(true)">
<i class="material-icons">import_export</i> <i class="material-icons">import_export</i>
<span>Export</span> <span>Import / Export</span>
</button> </button>
</div> </div>
</div> </div>
@@ -29,10 +66,14 @@
<ul> <ul>
<li v-for="(collection, index) in collections" :key="collection.name"> <li v-for="(collection, index) in collections" :key="collection.name">
<collection <collection
:collection-index="index" v-bind:collection-index = "index"
:collection="collection" v-bind:collection = "collection"
v-on:edit-collection="editCollection" v-on:edit-collection = "editCollection(collection, index)"
></collection> v-on:add-folder = "addFolder(collection, index)"
v-on:edit-folder = "editFolder($event)"
v-on:edit-request = "editRequest($event)"
>
</collection>
</li> </li>
<li v-if="collections.length === 0"> <li v-if="collections.length === 0">
<label>Collections are empty</label> <label>Collections are empty</label>
@@ -49,48 +90,110 @@
</style> </style>
<script> <script>
import addCollection from "./addCollection"; import addCollection from "./addCollection";
import exportCollection from "./exportCollection"; import addFolder from "./addFolder";
import collection from './collection' import collection from './collection'
import editCollection from "./editCollection";
import editFolder from "./editFolder";
import editRequest from "./editRequest";
import importExportCollections from "./importExportCollections";
export default { export default {
components: { components: {
collection,
addCollection, addCollection,
exportCollection, addFolder,
collection,
editCollection,
editFolder,
editRequest,
importExportCollections,
}, },
data() { data() {
return { return {
showAddModel: false, showModalAdd : false,
showExportModal: false, showModalEdit : false,
selectedCollection: {}, showModalImportExport : false,
showModalAddFolder : false,
showModalEditFolder : false,
showModalEditRequest : false,
editingCollection : undefined,
editingCollectionIndex : undefined,
editingFolder : undefined,
editingFolderIndex : undefined,
editingRequest : undefined,
editingRequestIndex : undefined,
} }
}, },
computed: { computed: {
collections () { collections () {
return this.$store.state.postwoman.collections; return this.$store.state.postwoman.collections
} }
}, },
methods: { methods: {
toggleModal() { displayModalAdd(shouldDisplay) {
this.showAddModel = !this.showAddModel; this.showModalAdd = shouldDisplay
}, },
toggleExport() { displayModalEdit(shouldDisplay) {
this.showExportModal = !this.showExportModal; this.showModalEdit = shouldDisplay
if (!shouldDisplay)
this.resetSelectedData()
}, },
addNewCollection(newCollection) { displayModalImportExport(shouldDisplay) {
this.$store.commit('postwoman/addCollection', newCollection); this.showModalImportExport = shouldDisplay
this.showAddModel = false;
}, },
editCollection(payload) { displayModalAddFolder(shouldDisplay) {
const { collection, collectionIndex } = payload; this.showModalAddFolder = shouldDisplay
this.selectedCollection = Object.assign({ collectionIndex }, collection);
this.showAddModel = true; if (!shouldDisplay)
this.resetSelectedData()
}, },
savedCollection(savedCollection) { displayModalEditFolder(shouldDisplay) {
this.$store.commit('postwoman/saveCollection', { savedCollection }); this.showModalEditFolder = shouldDisplay
this.showAddModel = false;
this.selectedCollection = {}; if (!shouldDisplay)
this.resetSelectedData()
},
displayModalEditRequest(shouldDisplay) {
this.showModalEditRequest = shouldDisplay
if (!shouldDisplay)
this.resetSelectedData()
},
editCollection(collection, collectionIndex) {
this.$data.editingCollection = collection
this.$data.editingCollectionIndex = collectionIndex
this.displayModalEdit(true)
},
addFolder(collection, collectionIndex) {
this.$data.editingCollection = collection
this.$data.editingCollectionIndex = collectionIndex
this.displayModalAddFolder(true)
},
editFolder(payload) {
const { collectionIndex, folder, folderIndex } = payload
this.$data.editingCollection = collection
this.$data.editingCollectionIndex = collectionIndex
this.$data.editingFolder = folder
this.$data.editingFolderIndex = folderIndex
this.displayModalEditFolder(true)
},
editRequest(payload) {
const { request, collectionIndex, folderIndex, requestIndex } = payload
this.$data.editingCollectionIndex = collectionIndex
this.$data.editingFolderIndex = folderIndex
this.$data.editingRequest = request
this.$data.editingRequestIndex = requestIndex
this.displayModalEditRequest(true)
},
resetSelectedData() {
this.$data.editingCollection = undefined
this.$data.editingCollectionIndex = undefined
this.$data.editingFolder = undefined
this.$data.editingFolderIndex = undefined
this.$data.editingRequest = undefined
this.$data.editingRequestIndex = undefined
}, },
}, },
} }

View File

@@ -7,10 +7,10 @@
</button> </button>
</div> </div>
<div> <div>
<button class="icon" @click="removeRequest" v-tooltip="'Delete collection'"> <button class="icon" @click="removeRequest" v-tooltip="'Delete request'">
<i class="material-icons">delete</i> <i class="material-icons">delete</i>
</button> </button>
<button class="icon" @click="editRequest" v-tooltip="'Edit request'"> <button class="icon" @click="$emit('edit-request')" v-tooltip="'Edit request'">
<i class="material-icons">edit</i> <i class="material-icons">edit</i>
</button> </button>
</div> </div>
@@ -33,25 +33,21 @@
<script> <script>
export default { export default {
props: { props: {
request: Object, request : Object,
collectionIndex: Number, collectionIndex : Number,
folderIndex: Number, folderIndex : Number,
requestIndex: Number, requestIndex : Number,
}, },
methods: { methods: {
selectRequest() { selectRequest() {
this.$store.commit('postwoman/selectRequest', { request: this.request }); this.$store.commit('postwoman/selectRequest', { request: this.request });
}, },
editRequest() {
this.request.requestIndex = this.requestIndex;
this.$store.commit('postwoman/editRequest', { request: this.request });
},
removeRequest() { removeRequest() {
if (!confirm("Are you sure you want to remove this request?")) return; if (!confirm("Are you sure you want to remove this request?")) return;
this.$store.commit('postwoman/removeRequest', { this.$store.commit('postwoman/removeRequest', {
collectionIndex: this.collectionIndex, collectionIndex : this.collectionIndex,
folderIndex: this.folderIndex, folderIndex : this.folderIndex,
requestIndex: this.requestIndex, requestIndex : this.requestIndex,
}); });
}, },
}, },

View File

@@ -1,158 +0,0 @@
<template>
<div>
<modal v-if="show" @close="hideModel">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title" v-if='!request.hasOwnProperty("requestIndex")'>New Request</h3>
<h3 class="title" v-if='request.hasOwnProperty("requestIndex")'>Edit Request</h3>
<div>
<button class="icon" @click="hideModel">
<i class="material-icons">close</i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div slot="body">
<ul>
<li>
<input type="text" v-model="request.name" placeholder="My New Request" />
<select type="text" v-model="request.collection" >
<option
v-for="collection in collections"
:key="collection.collectionIndex"
:value="collection.collectionIndex">
{{ collection.name }}
</option>
</select>
<select type="text" v-model="request.folder" >
<option
v-for="folder in folders"
:key="folder.folderIndex"
:value="folder.folderIndex">
{{ folder.name }}
</option>
</select>
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="addRequest" v-if='!request.hasOwnProperty("requestIndex")'>
<i class="material-icons">add</i>
<span>Create</span>
</button>
<button class="icon" @click="saveRequest" v-if='request.hasOwnProperty("requestIndex")'>
<i class="material-icons">save</i>
<span>Save</span>
</button>
</li>
</ul>
</div>
</modal>
</div>
</template>
<script>
import modal from "../../components/modal";
export default {
props: {
show: Boolean,
editingRequest: Object,
},
components: {
modal,
},
data() {
return {
request: {
name: '',
collection: '',
folder: -1,
},
}
},
watch: {
show() {
this.request = Object.assign(this.request, this.editingRequest);
},
'request.collection': function (newValue, oldValue) {
if (!oldValue) return;
if (newValue === oldValue) {
delete this.request.oldCollection;
return;
}
this.request.oldFolder = this.request.folder;
this.request.folder = -1;
this.request.oldCollection = oldValue;
},
'request.folder': function (newValue, oldValue) {
if (!oldValue) return;
if (newValue === oldValue) {
delete this.request.oldFolder;
return;
}
this.request.oldFolder = oldValue;
}
},
computed: {
collections() {
return this.$store.state.postwoman.collections
.map((collection, index) => {
return {
name: collection.name,
collectionIndex: index,
};
});
},
folders() {
if (this.request.collection === '') return []
return this.$store.state.postwoman.collections[this.request.collection].folders
.map((folder, index) => {
return {
name: folder.name,
folderIndex: index,
};
});
}
},
methods: {
addRequest() {
const request = Object.assign({}, this.request);
this.$store.commit('postwoman/addRequest', {
request,
});
this.request = {
name: '',
collection: '',
folder: '',
};
this.hideModel();
},
saveRequest() {
const savedRequest = Object.assign({}, this.request);
this.$store.commit('postwoman/saveRequest', {
request: savedRequest,
});
this.request = {
name: '',
collection: '',
folder: '',
};
this.hideModel();
},
hideModel() {
this.$emit('hide-model');
},
},
};
</script>

View File

@@ -0,0 +1,158 @@
<template>
<div>
<modal v-if="show" @close="hideModal">
<div slot="header">
<ul>
<li>
<div class="flex-wrap">
<h3 class="title">Save Request As</h3>
<div>
<button class="icon" @click="hideModal">
<i class="material-icons">close</i>
</button>
</div>
</div>
</li>
</ul>
</div>
<div slot="body">
<ul>
<li>
<input type="text" v-model="requestData.name" v-bind:placeholder="defaultRequestName" />
<select type="text" v-model="requestData.collectionIndex" >
<option
v-for="(collection, index) in $store.state.postwoman.collections"
:key = "index"
:value = "index">
{{ collection.name }}
</option>
</select>
<select type="text" v-model="requestData.folderIndex" >
<option
:key = "undefined"
:value = "undefined">
</option>
<option
v-for="(folder, index) in folders"
:key = "index"
:value = "index">
{{ folder.name }}
</option>
</select>
<select type="text" v-model="requestData.requestIndex" >
<option
:key = "undefined"
:value = "undefined">
</option>
<option
v-for ="(folder, index) in requests"
:key = "index"
:value = "index">
{{ folder.name }}
</option>
</select>
</li>
</ul>
</div>
<div slot="footer">
<ul>
<li>
<button class="icon" @click="saveRequestAs">
<i class="material-icons">save</i>
<span>Save</span>
</button>
</li>
</ul>
</div>
</modal>
</div>
</template>
<script>
import modal from "../../components/modal";
export default {
props: {
show : Boolean,
editingRequest : Object,
},
components: {
modal,
},
data() {
return {
defaultRequestName : 'My New Request',
requestData : {
name : undefined,
collectionIndex : undefined,
folderIndex : undefined,
requestIndex : undefined,
},
}
},
watch: {
'requestData.collectionIndex': function resetFolderAndRequestIndex() {
// if user choosen some folder, than selected other collection, which doesn't have any folders
// than `requestUpdateData.folderIndex` won't be reseted
this.$data.requestData.folderIndex = undefined
this.$data.requestData.requestIndex = undefined
},
'requestData.folderIndex': function resetRequestIndex() {
this.$data.requestData.requestIndex = undefined
},
},
computed: {
folders() {
const userSelectedAnyCollection = this.$data.requestData.collectionIndex !== undefined
if (!userSelectedAnyCollection) return []
return this.$store.state.postwoman.collections[this.$data.requestData.collectionIndex].folders
},
requests() {
const userSelectedAnyCollection = this.$data.requestData.collectionIndex !== undefined
if (!userSelectedAnyCollection) return []
const userSelectedAnyFolder = this.$data.requestData.folderIndex !== undefined
if (userSelectedAnyFolder) {
const collection = this.$store.state.postwoman.collections[this.$data.requestData.collectionIndex]
const folder = collection.folders[this.$data.requestData.folderIndex]
const requests = folder.requests
return requests
}
else {
const collection = this.$store.state.postwoman.collections[this.$data.requestData.collectionIndex]
const requests = collection.requests
return requests
}
}
},
methods: {
saveRequestAs() {
const userDidntSpecifyCollection = this.$data.requestData.collectionIndex === undefined
if (userDidntSpecifyCollection) {
this.$toast.error('please, specify collection first', { icon: 'error' })
return
}
const requestUpdated = {
...this.$props.editingRequest,
name : this.$data.requestData.name || this.$data.defaultRequestName,
collection : this.$data.requestData.collectionIndex,
}
this.$store.commit('postwoman/saveRequestAs', {
request : requestUpdated,
collectionIndex : this.$data.requestData.collectionIndex,
folderIndex : this.$data.requestData.folderIndex,
requestIndex : this.$data.requestData.requestIndex,
});
this.hideModal();
},
hideModal() {
this.$emit('hide-modal');
this.$emit('hide-model'); // for backward compatibility // TODO: use fixed event
},
},
};
</script>

View File

@@ -1,10 +1,10 @@
<template> <template>
<div class="page"> <div class="page">
<save-request <save-request-as
v-bind:show="showRequestModal" v-bind:show="showRequestModal"
v-on:hide-model='hideRequestModal' v-on:hide-model='hideRequestModal'
v-bind:editing-request='editRequest' v-bind:editing-request='editRequest'
></save-request> ></save-request-as>
<pw-modal v-if="showModal" @close="showModal = false"> <pw-modal v-if="showModal" @close="showModal = false">
<div slot="header"> <div slot="header">
<ul> <ul>
@@ -364,7 +364,7 @@
import toggle from "../components/toggle"; import toggle from "../components/toggle";
import modal from "../components/modal"; import modal from "../components/modal";
import collections from '../components/collections'; import collections from '../components/collections';
import saveRequest from '../components/collections/saveRequest'; import saveRequestAs from '../components/collections/saveRequestAs';
import parseCurlCommand from '../assets/js/curlparser.js'; import parseCurlCommand from '../assets/js/curlparser.js';
import hljs from 'highlight.js'; import hljs from 'highlight.js';
import 'highlight.js/styles/dracula.css'; import 'highlight.js/styles/dracula.css';
@@ -428,7 +428,7 @@
history, history,
autocomplete, autocomplete,
collections, collections,
saveRequest, saveRequestAs,
}, },
data() { data() {
return { return {

View File

@@ -1,3 +1,5 @@
import Vue from 'vue'
export const SETTINGS_KEYS = [ export const SETTINGS_KEYS = [
/** /**
* The CSS class that should be applied to the root element. * The CSS class that should be applied to the root element.
@@ -42,14 +44,14 @@ export const SETTINGS_KEYS = [
]; ];
export const state = () => ({ export const state = () => ({
settings: {}, settings : {},
collections: [{ collections : [{
name: 'My First Collection', name : 'My First Collection',
folders: [], folders : [],
requests: [], requests : [],
}], }],
selectedRequest: {}, selectedRequest : {},
editingRequest: {}, editingRequest : {},
}); });
export const mutations = { export const mutations = {
@@ -68,8 +70,27 @@ export const mutations = {
state.settings[key] = value; state.settings[key] = value;
}, },
addCollection (state, newCollection) { replaceCollections (state, collections) {
state.collections.push(newCollection); state.collections = collections;
},
importCollections (state, collections) {
state.collections = [...state.collections, ...collections];
let index = 0;
for (let collection of collections) {
collection.collectionIndex = index;
index += 1;
}
},
addNewCollection (state, collection) {
state.collections.push({
name : '',
folders : [],
requests : [],
...collection,
})
}, },
removeCollection (state, payload) { removeCollection (state, payload) {
@@ -77,14 +98,23 @@ export const mutations = {
state.collections.splice(collectionIndex, 1) state.collections.splice(collectionIndex, 1)
}, },
saveCollection (state, payload) { editCollection (state, payload) {
const { savedCollection } = payload; const { collection, collectionIndex } = payload
state.collections[savedCollection.collectionIndex] = savedCollection; state.collections[collectionIndex] = collection
}, },
addFolder (state, payload) { addNewFolder (state, payload) {
const { collectionIndex, folder } = payload; const { collectionIndex, folder } = payload;
state.collections[collectionIndex].folders.push(folder); state.collections[collectionIndex].folders.push({
name : '',
requests : [],
...folder,
});
},
editFolder (state, payload) {
const { collectionIndex, folder, folderIndex } = payload;
Vue.set(state.collections[collectionIndex].folders, folderIndex, folder)
}, },
removeFolder (state, payload) { removeFolder (state, payload) {
@@ -92,14 +122,9 @@ export const mutations = {
state.collections[collectionIndex].folders.splice(folderIndex, 1) state.collections[collectionIndex].folders.splice(folderIndex, 1)
}, },
saveFolder (state, payload) {
const { savedFolder } = payload;
state.collections[savedFolder.collectionIndex].folders[savedFolder.folderIndex] = savedFolder;
},
addRequest (state, payload) { addRequest (state, payload) {
const { request } = payload; const { request } = payload;
// Request that is directly attached to collection // Request that is directly attached to collection
if (request.folder === -1) { if (request.folder === -1) {
state.collections[request.collection].requests.push(request); state.collections[request.collection].requests.push(request);
@@ -109,6 +134,67 @@ export const mutations = {
state.collections[request.collection].folders[request.folder].requests.push(request); state.collections[request.collection].folders[request.folder].requests.push(request);
}, },
editRequest (state, payload) {
const {
requestOld,
requestOldCollectionIndex,
requestOldFolderIndex,
requestOldIndex,
requestNew,
requestNewCollectionIndex,
requestNewFolderIndex,
} = payload
const changedCollection = requestOldCollectionIndex !== requestNewCollectionIndex
const changedFolder = requestOldFolderIndex !== requestNewFolderIndex
const changedPlace = changedCollection || changedFolder
// set new request
if (requestNewFolderIndex !== undefined)
Vue.set(state.collections[requestNewCollectionIndex].folders[requestNewFolderIndex].requests, requestOldIndex, requestNew)
else
Vue.set(state.collections[requestNewCollectionIndex].requests, requestOldIndex, requestNew)
// remove old request
if (changedPlace) {
if (requestOldFolderIndex !== undefined)
state.collections[requestOldCollectionIndex].folders[requestOldFolderIndex].requests.splice(requestOldIndex, 1)
else
state.collections[requestOldCollectionIndex].requests.splice(requestOldIndex, 1)
}
},
saveRequestAs (state, payload) {
const {
request,
collectionIndex,
folderIndex,
requestIndex,
} = payload
const specifiedCollection = collectionIndex !== undefined
const specifiedFolder = folderIndex !== undefined
const specifiedRequest = requestIndex !== undefined
if (specifiedCollection && specifiedFolder && specifiedRequest)
Vue.set(state.collections[collectionIndex].folders[folderIndex].requests, requestIndex, request)
else if (specifiedCollection && specifiedFolder && !specifiedRequest) {
const requests = state.collections[collectionIndex].folders[folderIndex].requests
const lastRequestIndex = requests.length - 1;
Vue.set(requests, lastRequestIndex + 1, request)
}
else if (specifiedCollection && !specifiedFolder && specifiedRequest) {
const requests = state.collections[collectionIndex].requests
Vue.set(requests,requestIndex, request)
}
else if (specifiedCollection && !specifiedFolder && !specifiedRequest) {
const requests = state.collections[collectionIndex].requests
const lastRequestIndex = requests.length - 1;
Vue.set(requests, lastRequestIndex + 1, request)
}
},
saveRequest (state, payload) { saveRequest (state, payload) {
const { request } = payload; const { request } = payload;
@@ -126,14 +212,14 @@ export const mutations = {
delete request.oldCollection; delete request.oldCollection;
delete request.oldFolder; delete request.oldFolder;
// Request that is directly attached to collection // Request that is directly attached to collection
if (request.folder === -1) { if (request.folder === -1) {
state.collections[request.collection].requests[request.requestIndex] = request; Vue.set(state.collections[request.collection].requests, request.requestIndex, request)
return return
} }
state.collections[request.collection].folders[request.folder].requests[request.requestIndex] = request; Vue.set(state.collections[request.collection].folders[request.folder].requests, request.requestIndex, request)
}, },
removeRequest (state, payload) { removeRequest (state, payload) {
@@ -152,8 +238,4 @@ export const mutations = {
state.selectedRequest = Object.assign({}, payload.request); state.selectedRequest = Object.assign({}, payload.request);
}, },
editRequest (state, payload) {
state.editingRequest = Object.assign({}, payload.request);
},
}; };