mirror of https://github.com/Lissy93/dashy.git
✨ Implements move, copy and delete item, and delete section functionality
This commit is contained in:
parent
f398a374e7
commit
31e172befb
|
@ -244,7 +244,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Overide form element colors, so that config menu can be themed by user */
|
/* Overide form element colors, so that config menu can be themed by user */
|
||||||
input, button, {
|
input, button {
|
||||||
color: var(--config-settings-color);
|
color: var(--config-settings-color);
|
||||||
border: 1px solid var(--config-settings-color);
|
border: 1px solid var(--config-settings-color);
|
||||||
background: none;
|
background: none;
|
||||||
|
|
|
@ -115,6 +115,7 @@ export default {
|
||||||
background: var(--interactive-editor-background-darker);
|
background: var(--interactive-editor-background-darker);
|
||||||
border-radius: var(--curve-factor);
|
border-radius: var(--curve-factor);
|
||||||
box-shadow: 0px 0px 3px var(--interactive-editor-color);
|
box-shadow: 0px 0px 3px var(--interactive-editor-color);
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
span {
|
span {
|
||||||
font-family: var(--font-monospace);
|
font-family: var(--font-monospace);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<Select
|
<Select
|
||||||
v-model="selectedSection"
|
v-model="selectedSection"
|
||||||
:options="sectionList"
|
:options="sectionList"
|
||||||
:initialOption="currentSection"
|
:initialOption="selectedSection"
|
||||||
label="Destination"
|
label="Destination"
|
||||||
/>
|
/>
|
||||||
<Radio
|
<Radio
|
||||||
|
@ -84,15 +84,19 @@ export default {
|
||||||
return sectionName;
|
return sectionName;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
this.selectedSection = this.currentSection;
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
save() {
|
save() {
|
||||||
const item = this.$store.getters.getItemById(this.itemId);
|
const item = this.$store.getters.getItemById(this.itemId);
|
||||||
// Copy item to new section
|
// Copy item to new section
|
||||||
const copyPayload = { item, toSection: this.selectedSection };
|
const copyPayload = { item, toSection: this.selectedSection, appendTo: this.appendTo };
|
||||||
this.$store.commit(StoreKeys.COPY_ITEM, copyPayload);
|
this.$store.commit(StoreKeys.COPY_ITEM, copyPayload);
|
||||||
// Remove item from previous section
|
// Remove item from previous section
|
||||||
if (this.operation === 'Move') {
|
if (this.operation === 'Move') {
|
||||||
// TODO: Remove
|
const payload = { itemId: this.itemId, sectionName: this.currentSection };
|
||||||
|
this.$store.commit(StoreKeys.REMOVE_ITEM, payload);
|
||||||
}
|
}
|
||||||
this.close();
|
this.close();
|
||||||
},
|
},
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
@launchItem="launchItem"
|
@launchItem="launchItem"
|
||||||
@openItemSettings="openItemSettings"
|
@openItemSettings="openItemSettings"
|
||||||
@openMoveItemMenu="openMoveItemMenu"
|
@openMoveItemMenu="openMoveItemMenu"
|
||||||
|
@openDeleteItem="openDeleteItem"
|
||||||
/>
|
/>
|
||||||
<MoveItemTo v-if="isEditMode" :itemId="id" />
|
<MoveItemTo v-if="isEditMode" :itemId="id" />
|
||||||
<EditItem v-if="editMenuOpen" :itemId="id" @closeEditMenu="closeEditMenu" />
|
<EditItem v-if="editMenuOpen" :itemId="id" @closeEditMenu="closeEditMenu" />
|
||||||
|
@ -293,11 +294,19 @@ export default {
|
||||||
lastUsed[itemId] = new Date().getTime();
|
lastUsed[itemId] = new Date().getTime();
|
||||||
localStorage.setItem(localStorageKeys.LAST_USED, JSON.stringify(lastUsed));
|
localStorage.setItem(localStorageKeys.LAST_USED, JSON.stringify(lastUsed));
|
||||||
},
|
},
|
||||||
|
/* Open the modal for moving/ copying item to other section */
|
||||||
openMoveItemMenu() {
|
openMoveItemMenu() {
|
||||||
this.$modal.show(`${modalNames.MOVE_ITEM_TO}-${this.id}`);
|
this.$modal.show(`${modalNames.MOVE_ITEM_TO}-${this.id}`);
|
||||||
this.$store.commit(StoreKeys.SET_MODAL_OPEN, true);
|
this.$store.commit(StoreKeys.SET_MODAL_OPEN, true);
|
||||||
this.closeContextMenu();
|
this.closeContextMenu();
|
||||||
},
|
},
|
||||||
|
/* Deletes the current item from the state */
|
||||||
|
openDeleteItem() {
|
||||||
|
const parentSection = this.$store.getters.getParentSectionOfItem(this.id);
|
||||||
|
const payload = { itemId: this.id, sectionName: parentSection.name };
|
||||||
|
this.$store.commit(StoreKeys.REMOVE_ITEM, payload);
|
||||||
|
this.closeContextMenu();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// If ststus checking is enabled, then check service status
|
// If ststus checking is enabled, then check service status
|
||||||
|
|
|
@ -37,7 +37,7 @@
|
||||||
<MoveIcon />
|
<MoveIcon />
|
||||||
<span>{{ $t('menu.move-item') }}</span>
|
<span>{{ $t('menu.move-item') }}</span>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="isEditMode">
|
<li v-if="isEditMode" @click="openDeleteItem()">
|
||||||
<BinIcon />
|
<BinIcon />
|
||||||
<span>{{ $t('menu.remove-item') }}</span>
|
<span>{{ $t('menu.remove-item') }}</span>
|
||||||
</li>
|
</li>
|
||||||
|
@ -92,6 +92,9 @@ export default {
|
||||||
openMoveMenu() {
|
openMoveMenu() {
|
||||||
this.$emit('openMoveItemMenu');
|
this.$emit('openMoveItemMenu');
|
||||||
},
|
},
|
||||||
|
openDeleteItem() {
|
||||||
|
this.$emit('openDeleteItem');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
v-click-outside="closeContextMenu"
|
v-click-outside="closeContextMenu"
|
||||||
@openEditSection="openEditSection"
|
@openEditSection="openEditSection"
|
||||||
@navigateToSection="navigateToSection"
|
@navigateToSection="navigateToSection"
|
||||||
|
@removeSection="removeSection"
|
||||||
/>
|
/>
|
||||||
</Collapsable>
|
</Collapsable>
|
||||||
</template>
|
</template>
|
||||||
|
@ -217,6 +218,12 @@ export default {
|
||||||
this.$modal.hide(modalNames.EDIT_SECTION);
|
this.$modal.hide(modalNames.EDIT_SECTION);
|
||||||
this.$store.commit(StoreKeys.SET_MODAL_OPEN, false);
|
this.$store.commit(StoreKeys.SET_MODAL_OPEN, false);
|
||||||
},
|
},
|
||||||
|
/* Deletes current section, in local state */
|
||||||
|
removeSection() {
|
||||||
|
const payload = { sectionIndex: this.index, sectionName: this.title };
|
||||||
|
this.$store.commit(StoreKeys.REMOVE_SECTION, payload);
|
||||||
|
this.closeContextMenu();
|
||||||
|
},
|
||||||
/* Open custom context menu, and set position */
|
/* Open custom context menu, and set position */
|
||||||
openContextMenu(e) {
|
openContextMenu(e) {
|
||||||
this.contextMenuOpen = true;
|
this.contextMenuOpen = true;
|
||||||
|
|
|
@ -12,11 +12,7 @@
|
||||||
<EditIcon />
|
<EditIcon />
|
||||||
<span>{{ $t('context-menus.section.edit-section') }}</span>
|
<span>{{ $t('context-menus.section.edit-section') }}</span>
|
||||||
</li>
|
</li>
|
||||||
<li v-if="isEditMode">
|
<li v-if="isEditMode" @click="removeSection">
|
||||||
<MoveIcon />
|
|
||||||
<span>{{ $t('context-menus.section.move-section') }}</span>
|
|
||||||
</li>
|
|
||||||
<li v-if="isEditMode">
|
|
||||||
<BinIcon />
|
<BinIcon />
|
||||||
<span>{{ $t('context-menus.section.remove-section') }}</span>
|
<span>{{ $t('context-menus.section.remove-section') }}</span>
|
||||||
</li>
|
</li>
|
||||||
|
@ -29,14 +25,12 @@
|
||||||
// Import icons for each element
|
// Import icons for each element
|
||||||
import EditIcon from '@/assets/interface-icons/config-edit-json.svg';
|
import EditIcon from '@/assets/interface-icons/config-edit-json.svg';
|
||||||
import BinIcon from '@/assets/interface-icons/interactive-editor-remove.svg';
|
import BinIcon from '@/assets/interface-icons/interactive-editor-remove.svg';
|
||||||
import MoveIcon from '@/assets/interface-icons/interactive-editor-move-to.svg';
|
|
||||||
import SameTabOpenIcon from '@/assets/interface-icons/open-current-tab.svg';
|
import SameTabOpenIcon from '@/assets/interface-icons/open-current-tab.svg';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ContextMenu',
|
name: 'ContextMenu',
|
||||||
components: {
|
components: {
|
||||||
EditIcon,
|
EditIcon,
|
||||||
MoveIcon,
|
|
||||||
BinIcon,
|
BinIcon,
|
||||||
SameTabOpenIcon,
|
SameTabOpenIcon,
|
||||||
},
|
},
|
||||||
|
@ -62,6 +56,9 @@ export default {
|
||||||
openEditSectionMenu() {
|
openEditSectionMenu() {
|
||||||
this.$emit('openEditSection');
|
this.$emit('openEditSection');
|
||||||
},
|
},
|
||||||
|
removeSection() {
|
||||||
|
this.$emit('removeSection');
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
39
src/store.js
39
src/store.js
|
@ -19,7 +19,9 @@ const {
|
||||||
UPDATE_PAGE_INFO,
|
UPDATE_PAGE_INFO,
|
||||||
UPDATE_APP_CONFIG,
|
UPDATE_APP_CONFIG,
|
||||||
UPDATE_SECTION,
|
UPDATE_SECTION,
|
||||||
|
REMOVE_SECTION,
|
||||||
COPY_ITEM,
|
COPY_ITEM,
|
||||||
|
REMOVE_ITEM,
|
||||||
} = Keys;
|
} = Keys;
|
||||||
|
|
||||||
const store = new Vuex.Store({
|
const store = new Vuex.Store({
|
||||||
|
@ -59,6 +61,15 @@ const store = new Vuex.Store({
|
||||||
});
|
});
|
||||||
return item;
|
return item;
|
||||||
},
|
},
|
||||||
|
getParentSectionOfItem: (state, getters) => (itemId) => {
|
||||||
|
let foundSection;
|
||||||
|
getters.sections.forEach((section) => {
|
||||||
|
section.items.forEach((item) => {
|
||||||
|
if (item.id === itemId) foundSection = section;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return foundSection;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
[UPDATE_CONFIG](state, config) {
|
[UPDATE_CONFIG](state, config) {
|
||||||
|
@ -103,18 +114,44 @@ const store = new Vuex.Store({
|
||||||
newConfig.sections[sectionIndex] = sectionData;
|
newConfig.sections[sectionIndex] = sectionData;
|
||||||
state.config = newConfig;
|
state.config = newConfig;
|
||||||
},
|
},
|
||||||
|
[REMOVE_SECTION](state, payload) {
|
||||||
|
const { sectionIndex, sectionName } = payload;
|
||||||
|
const newConfig = { ...state.config };
|
||||||
|
if (newConfig.sections[sectionIndex].name === sectionName) {
|
||||||
|
newConfig.sections.splice(sectionIndex, 1);
|
||||||
|
}
|
||||||
|
state.config = newConfig;
|
||||||
|
},
|
||||||
[COPY_ITEM](state, payload) {
|
[COPY_ITEM](state, payload) {
|
||||||
const { item, toSection } = payload;
|
const { item, toSection, appendTo } = payload;
|
||||||
const config = { ...state.config };
|
const config = { ...state.config };
|
||||||
const newItem = { ...item };
|
const newItem = { ...item };
|
||||||
config.sections.forEach((section) => {
|
config.sections.forEach((section) => {
|
||||||
if (section.name === toSection) {
|
if (section.name === toSection) {
|
||||||
|
if (appendTo === 'Begining') {
|
||||||
|
section.items.unshift(newItem);
|
||||||
|
} else {
|
||||||
section.items.push(newItem);
|
section.items.push(newItem);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
config.sections = applyItemId(config.sections);
|
config.sections = applyItemId(config.sections);
|
||||||
state.config = config;
|
state.config = config;
|
||||||
},
|
},
|
||||||
|
[REMOVE_ITEM](state, payload) {
|
||||||
|
const { itemId, sectionName } = payload;
|
||||||
|
const config = { ...state.config };
|
||||||
|
config.sections.forEach((section) => {
|
||||||
|
if (section.name === sectionName) {
|
||||||
|
section.items.forEach((item, index) => {
|
||||||
|
if (item.id === itemId) {
|
||||||
|
section.items.splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
state.config = config;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
/* Called when app first loaded. Reads config and sets state */
|
/* Called when app first loaded. Reads config and sets state */
|
||||||
|
|
|
@ -30,7 +30,7 @@ export const sanitize = (string) => {
|
||||||
const makeItemId = (sectionStr, itemStr, index) => {
|
const makeItemId = (sectionStr, itemStr, index) => {
|
||||||
const charSum = sectionStr.split('').map((a) => a.charCodeAt(0)).reduce((x, y) => x + y);
|
const charSum = sectionStr.split('').map((a) => a.charCodeAt(0)).reduce((x, y) => x + y);
|
||||||
const itemTitleStr = itemStr.replace(/\s+/g, '-').replace(/[^a-zA-Z ]/g, '').toLowerCase();
|
const itemTitleStr = itemStr.replace(/\s+/g, '-').replace(/[^a-zA-Z ]/g, '').toLowerCase();
|
||||||
return `${index}_${charSum}_${itemTitleStr}_${Math.random()}`;
|
return `${index}_${charSum}_${itemTitleStr}}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Given an array of sections, apply a unique ID to each item, and return modified array */
|
/* Given an array of sections, apply a unique ID to each item, and return modified array */
|
||||||
|
|
|
@ -9,7 +9,9 @@ const KEY_NAMES = [
|
||||||
'UPDATE_PAGE_INFO',
|
'UPDATE_PAGE_INFO',
|
||||||
'UPDATE_APP_CONFIG',
|
'UPDATE_APP_CONFIG',
|
||||||
'UPDATE_SECTION',
|
'UPDATE_SECTION',
|
||||||
|
'REMOVE_SECTION',
|
||||||
'COPY_ITEM',
|
'COPY_ITEM',
|
||||||
|
'REMOVE_ITEM',
|
||||||
];
|
];
|
||||||
|
|
||||||
// Convert array of key names into an object, and export
|
// Convert array of key names into an object, and export
|
||||||
|
|
Loading…
Reference in New Issue