Skip to content

Commit

Permalink
Merge pull request #171 from evandor/TAB-496-subfolders
Browse files Browse the repository at this point in the history
Tab 496 subfolders
  • Loading branch information
evandor authored Mar 9, 2024
2 parents d88cd0e + ba80f73 commit 7ccc4e9
Show file tree
Hide file tree
Showing 36 changed files with 1,036 additions and 539 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"@editorjs/editorjs": "^2.27.2",
"@editorjs/header": "^2.7.0",
"@extractus/feed-extractor": "^7.0.1",
"@intlify/unplugin-vue-i18n": "^2.0.0",
"@intlify/unplugin-vue-i18n": "^3.0.0",
"@mozilla/readability": "^0.5.0",
"@quasar/extras": "^1.16.6",
"@stripe/stripe-js": "^3.0.3",
Expand Down
47 changes: 0 additions & 47 deletions src/components/ExampleComponent2.vue

This file was deleted.

126 changes: 63 additions & 63 deletions src/components/UnassignedTabs.vue
Original file line number Diff line number Diff line change
@@ -1,63 +1,63 @@
<template>

<!-- @end="end"-->
<vue-draggable-next
:list="unassignedTabs()"
:group="{ name: 'tabs', pull: 'clone', put: false }"
:sort="true">

<div
class="col-12 q-pa-xs items-center justify-center" style="width:100%; max-width: 300px;cursor: move"
v-for="tab in unassignedTabs()"
:key="tab.id">

<OpenTabCard :tab="tab" />

</div>

</vue-draggable-next>

</template>

<script setup lang="ts">
import {Tab} from "src/models/Tab";
import OpenTabCard from "components/layouts/OpenTabCard.vue"
import _ from "lodash"
import {useTabsStore} from "src/stores/tabsStore"
import {VueDraggableNext} from 'vue-draggable-next'
const props = defineProps({
filter: {
type: String,
required: false
}
})
const tabsStore = useTabsStore()
function unassignedTabs(): Tab[] {
return _.filter(
tabsStore.pendingTabset?.tabs,
//@ts-ignore
(t: Tab) => {
if (props.filter && props.filter.trim().length > 0) {
const f = props.filter.toLowerCase()
const chromeTab = t.chromeTab
if (chromeTab && .title && .title.toLowerCase().indexOf(f) >= 0) {
return true
}
if (chromeTab && .url && .url.indexOf(f) >= 0) {
return true
}
if (t.name && t.name.toLowerCase().indexOf(f) >= 0) {
return true
}
return false
}
return true
})
}
</script>
<!--<template>-->

<!-- &lt;!&ndash; @end="end"&ndash;&gt;-->
<!-- <vue-draggable-next-->
<!-- :list="unassignedTabs()"-->
<!-- :group="{ name: 'tabs', pull: 'clone', put: false }"-->
<!-- :sort="true">-->

<!-- <div-->
<!-- class="col-12 q-pa-xs items-center justify-center" style="width:100%; max-width: 300px;cursor: move"-->
<!-- v-for="tab in unassignedTabs()"-->
<!-- :key="tab.id">-->

<!-- <OpenTabCard :tab="tab" />-->

<!-- </div>-->

<!-- </vue-draggable-next>-->

<!--</template>-->

<!--<script setup lang="ts">-->

<!--import {Tab} from "src/models/Tab";-->
<!--import OpenTabCard from "components/layouts/OpenTabCard.vue"-->
<!--import _ from "lodash"-->
<!--import {useTabsStore} from "src/stores/tabsStore"-->
<!--import {VueDraggableNext} from 'vue-draggable-next'-->

<!--const props = defineProps({-->
<!-- filter: {-->
<!-- type: String,-->
<!-- required: false-->
<!-- }-->
<!--})-->

<!--const tabsStore = useTabsStore()-->

<!--function unassignedTabs(): Tab[] {-->
<!-- return _.filter(-->
<!-- tabsStore.pendingTabset?.tabs,-->
<!-- //@ts-ignore-->
<!-- (t: Tab) => {-->

<!-- if (props.filter && props.filter.trim().length > 0) {-->
<!-- const f = props.filter.toLowerCase()-->
<!-- const chromeTab = t.chromeTab-->
<!-- if (chromeTab && .title && .title.toLowerCase().indexOf(f) >= 0) {-->
<!-- return true-->
<!-- }-->
<!-- if (chromeTab && .url && .url.indexOf(f) >= 0) {-->
<!-- return true-->
<!-- }-->
<!-- if (t.name && t.name.toLowerCase().indexOf(f) >= 0) {-->
<!-- return true-->
<!-- }-->
<!-- return false-->
<!-- }-->
<!-- return true-->
<!-- })-->
<!--}-->

<!--</script>-->
60 changes: 60 additions & 0 deletions src/components/dialogues/DeleteSubfolderDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<template>
<q-dialog ref="dialogRef" @hide="onDialogHide">
<div>
<q-card class="q-dialog-plugin" style="max-width:100%">
<q-card-section>
<div class="text-h6">Delete Folder</div>
</q-card-section>
<q-card-section>
<div class="text-body">Would you like to delete the folder: {{ props.folder.name }} (and existing subfolders)?</div>
</q-card-section>
<q-card-actions align="right">

<DialogButton label="Cancel" color="accent" v-close-popup/>
<DialogButton label="Delete"
type="submit"
:autofocus="true"
@keyup.enter="deleteFolder()"
@wasClicked="deleteFolder()"
v-close-popup/>

</q-card-actions>
</q-card>
</div>
</q-dialog>

</template>

<script lang="ts" setup>
import {QForm, useDialogPluginComponent} from 'quasar'
import {useCommandExecutor} from "src/services/CommandExecutor";
import {MarkTabsetDeletedCommand} from "src/domain/tabsets/MarkTabsetDeleted";
import {SidePanelView, useUiStore} from "stores/uiStore";
import DialogButton from "components/buttons/DialogButton.vue";
import {PropType, ref} from "vue";
import {Tabset} from "src/models/Tabset";
import {DeleteTabsetFolderCommand} from "src/domain/tabsets/DeleteTabsetFolderCommand";
defineEmits([
...useDialogPluginComponent.emits
])
const props = defineProps({
tabset: {type: Object as PropType<Tabset>, required: true},
folder: {type: Object as PropType<Tabset>, required: true}
})
const {dialogRef, onDialogHide} = useDialogPluginComponent()
const theForm = ref<QForm>(null as unknown as QForm)
const deleteFolder = () => useCommandExecutor().executeFromUi(new DeleteTabsetFolderCommand(props.tabset, props.folder))
.then((res: any) => {
useUiStore().sidePanelSetActiveView(SidePanelView.MAIN)
return res
})
</script>
29 changes: 29 additions & 0 deletions src/components/dialogues/NewSubfolderDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<template>
<q-dialog ref="dialogRef" @hide="onDialogHide">
<NewSubfolderDialogBody
:name="props.name"
:tabsetId="props.tabsetId"
:parentFolder="props.parentFolder"
/>
</q-dialog>
</template>

<script lang="ts" setup>
import {useDialogPluginComponent} from "quasar";
import NewTabsetDialogBody from "components/dialogues/helper/NewTabsetDialogBody.vue";
import NewSubfolderDialogBody from "components/dialogues/helper/NewSubfolderDialogBody.vue";
defineEmits([
...useDialogPluginComponent.emits
])
const props = defineProps({
name: {type: String, default: ""},
tabsetId: {type: String, required: true},
parentFolder: {type: String, required: false},
})
const {dialogRef, onDialogHide} = useDialogPluginComponent()
</script>
83 changes: 83 additions & 0 deletions src/components/dialogues/RenameSubfolderDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<template>
<q-dialog ref="dialogRef" @hide="onDialogHide">
<q-card class="q-dialog-plugin">
<q-card-section>
<div class="text-h6">Subfolder</div>
</q-card-section>
<q-card-section>
<div class="text-body">You can provide a new name for this subfolder</div>
</q-card-section>

<q-card-section class="q-pt-none">
<q-input dense v-model="newSubfolderName" autofocus @keydown.enter="updateSubfolder()"
error-message="Please do not use special Characters, maximum length is 32"
:error="!newSubfolderNameIsValid" />
</q-card-section>

<q-card-actions align="right" class="text-primary">
<q-btn label="Cancel" size="sm" color="accent" @click="onDialogCancel"/>
<q-btn label="Update" size="sm" color="warning"
:disable="disableSubmit()"
v-close-popup
@click="updateSubfolder()"/>
</q-card-actions>


</q-card>
</q-dialog>

</template>

<script lang="ts" setup>
import {computed, PropType, ref, watchEffect} from "vue";
import {useDialogPluginComponent} from "quasar";
import {useTabsStore} from "src/stores/tabsStore";
import {STRIP_CHARS_IN_USER_INPUT} from "boot/constants";
import {useCommandExecutor} from "src/services/CommandExecutor";
import {RenameWindowCommand} from "src/domain/tabsets/RenameWindow";
import {ExecutionResult} from "src/domain/ExecutionResult";
import {Tabset} from "src/models/Tabset";
import {RenameFolderCommand} from "src/domain/tabsets/RenameFolderCommand";
defineEmits([
...useDialogPluginComponent.emits
])
const props = defineProps({
tabset: {type: Object as PropType<Tabset>, required: true},
folder: {type: Object as PropType<Tabset>, required: true},
name: {type: String, default: ''}
})
const {dialogRef, onDialogOK, onDialogHide, onDialogCancel} = useDialogPluginComponent()
const tabsStore = useTabsStore()
const newSubfolderName = ref(props.name)
const newSubfolderNameExists = ref(false)
const hideWarning = ref(false)
watchEffect(() => {
newSubfolderNameExists.value = !!tabsStore.nameExistsInContextTabset(newSubfolderName.value);
})
const updateSubfolder = () => useCommandExecutor()
.executeFromUi(new RenameFolderCommand(props.tabset, props.folder, newSubfolderName.value))
// .then((result: ExecutionResult<string>) => {
// onDialogOK({ name: newSubfolderName.value })
// })
const newSubfolderNameIsValid = computed(() =>
newSubfolderName.value?.length <= 32 && !STRIP_CHARS_IN_USER_INPUT.test(newSubfolderName.value))
const disableSubmit = (): boolean => {
return newSubfolderName.value.trim().length === 0
}
</script>

<style lang="sass" scoped>
.my-input
max-width: 250px
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@ const importBookmarks = async () => {
const tabset = await createTabsetFrom(newTabsetName.value, bookmarkId.value)
await useTabsetService().saveTabset(tabset)
$q.loadingBar?.stop()
sendMsg('reload-tabset', {tabsetId: tabset.id})
sendMsg('sidepanel-switch-view', {view: 'main'})
return
}
Expand Down
Loading

0 comments on commit 7ccc4e9

Please sign in to comment.