feat: history section

This commit is contained in:
Liyas Thomas
2021-07-07 23:28:42 +00:00
committed by GitHub
parent 7c8ab6fd4a
commit 6635d449a5
24 changed files with 199 additions and 308 deletions

View File

@@ -33,6 +33,10 @@
@apply h-4;
}
.hide-scrollbar::-webkit-scrollbar {
@apply hidden;
}
::selection {
@apply bg-accent;
@apply text-primary;
@@ -214,17 +218,8 @@ input[type="checkbox"] {
}
}
.error:not(input),
.disabled:not(input),
[disabled] {
@apply bg-error;
@apply text-secondaryLight;
@apply fill-current;
@apply cursor-not-allowed;
}
.info-response {
@apply text-yellow-400;
@apply text-pink-400;
}
.success-response {
@@ -232,7 +227,7 @@ input[type="checkbox"] {
}
.redir-response {
@apply text-pink-400;
@apply text-yellow-400;
}
.cl-error-response {

View File

@@ -41,7 +41,7 @@
// Text color
--secondary-color: theme("colors.gray.600");
// Light Text color
--secondary-light-color: theme("colors.gray.500");
--secondary-light-color: theme("colors.gray.400");
// Dark Text color
--secondary-dark-color: theme("colors.gray.700");
// Border color

View File

@@ -1,5 +1,5 @@
<template>
<header class="flex container items-center justify-between p-2 flex-1">
<header class="flex items-center justify-between p-2 flex-1">
<div class="inline-flex space-x-2 items-center flex-shrink-0">
<AppLogo class="h-6" />
</div>

View File

@@ -1,5 +1,5 @@
<template>
<section :id="label.toLowerCase()" class="flex flex-col">
<section :id="label.toLowerCase()">
<slot></slot>
</section>
</template>

View File

@@ -5,17 +5,10 @@
v-for="(navigation, index) in primaryNavigation"
:key="`navigation-${index}`"
:to="localePath(navigation.target)"
class="
p-4
flex-col flex-1
hover:bg-primaryDark hover:text-secondaryDark
items-center
justify-center
transition
"
class="nav-link"
>
<i class="material-icons opacity-75">{{ navigation.icon }}</i>
<span class="mt-2 text-xs font-semibold">{{ navigation.title }}</span>
<i class="material-icons">{{ navigation.icon }}</i>
<span>{{ navigation.title }}</span>
</nuxt-link>
</nav>
</aside>
@@ -40,7 +33,34 @@ export default {
</script>
<style scoped lang="scss">
.active {
@apply text-accent;
.nav-link {
@apply p-4;
@apply flex-col;
@apply flex-1;
@apply hover:bg-primaryDark;
@apply hover:text-secondaryDark;
@apply items-center;
@apply justify-center;
@apply transition;
.material-icons {
@apply transition-opacity;
@apply opacity-50;
}
span {
@apply mt-2;
@apply text-xs;
@apply font-semibold;
}
&.active {
@apply text-accent;
@apply hover:text-accent;
.material-icons {
@apply opacity-100;
}
}
}
</style>

View File

@@ -15,7 +15,7 @@
:class="[
color
? `text-${color}-500 hover:text-${color}-600 focus:text-${color}-600`
: 'hover:text-secondaryDark focus:text-secondaryDark',
: 'text-secondaryLight hover:text-secondary focus:text-secondary',
label ? 'px-3 rounded-lg' : 'px-2 rounded-full',
rounded ? 'rounded-full' : 'rounded-lg',
{ 'opacity-50 cursor-not-allowed': disabled },

View File

@@ -129,7 +129,6 @@ export default Vue.extend({
this.$toast.error(this.$t("deleted").toString(), {
icon: "delete",
})
this.confirmRemove = false
},
},
})

View File

@@ -212,7 +212,6 @@ export default {
collectionIndex: this.collectionIndex,
collectionID: this.collection.id,
})
this.confirmRemove = false
},
dropEvent({ dataTransfer }) {
this.dragging = !this.dragging

View File

@@ -213,7 +213,6 @@ export default {
collectionIndex: this.collectionIndex,
collectionID: this.collection.id,
})
this.confirmRemove = false
},
expandCollection(collectionID) {
this.$emit("expand-collection", collectionID)

View File

@@ -196,7 +196,6 @@ export default {
icon: "delete",
})
this.$emit("update-team-collections")
this.confirmRemove = false
})
.catch((error) => {
// Error

View File

@@ -17,8 +17,8 @@
v-tippy="{ theme: 'tooltip' }"
:title="!entry.star ? $t('add_star') : $t('remove_star')"
data-testid="star_button"
:class="{ stared: entry.star }"
:icon="entry.star ? 'star' : 'star_border'"
color="yellow"
@click.native="$emit('toggle-star')"
/>
<ButtonSecondary
@@ -130,9 +130,3 @@ export default {
},
}
</script>
<style scoped lang="scss">
.stared {
color: #f8e81c !important;
}
</style>

View File

@@ -1,19 +1,24 @@
<template>
<AppSection label="history" class="bg-green-200">
<div class="flex">
<AppSection label="history">
<div class="flex sticky top-10 shadow-sm">
<input
v-model="filterText"
aria-label="Search"
type="search"
class="px-4 py-2 text-xs flex flex-1"
class="px-4 py-2 text-xs flex flex-1 focus:outline-none border-divider"
:placeholder="$t('search')"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
data-testid="clear_history"
:disabled="history.length === 0"
icon="clear_all"
:title="$t('clear_all')"
@click.native="confirmRemove = true"
/>
</div>
<div
class="divide-y overflow-auto divide-dashed divide-divider"
:class="{ filled: filteredHistory.length }"
>
<ul v-for="(entry, index) in filteredHistory" :key="`entry-${index}`">
<div class="flex flex-col">
<div v-for="(entry, index) in filteredHistory" :key="`entry-${index}`">
<HistoryRestCard
v-if="page == 'rest'"
:id="index"
@@ -31,56 +36,32 @@
@delete-entry="deleteHistory(entry)"
@use-entry="useHistory(entry)"
/>
</ul>
</div>
<p :class="{ hidden: filteredHistory.length != 0 || history.length === 0 }">
{{ $t("nothing_found") }} "{{ filterText }}"
</p>
<p v-if="history.length === 0">
<i class="material-icons">schedule</i> {{ $t("history_empty") }}
</p>
<div v-if="history.length !== 0" class="rounded-b-lg bg-primaryLight">
<div
v-if="!isClearingHistory"
class="flex items-center justify-between flex-1"
>
<ButtonSecondary
data-testid="clear_history"
:disabled="history.length === 0"
icon="clear_all"
:label="$t('clear_all')"
@click.native="enableHistoryClearing"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="!showMore ? $t('show_more') : $t('hide_more')"
:icon="!showMore ? 'unfold_more' : 'unfold_less'"
@click.native="toggleCollapse()"
/>
</div>
<div v-else class="flex items-center justify-between flex-1">
<span class="flex items-center">
<i class="material-icons mx-2">help_outline</i>
{{ $t("are_you_sure") }}
</span>
<div>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('yes')"
data-testid="confirm_clear_history"
icon="done"
@click.native="clearHistory"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="$t('no')"
data-testid="reject_clear_history"
icon="close"
@click.native="disableHistoryClearing"
/>
</div>
</div>
</div>
<div
:class="{ hidden: filteredHistory.length != 0 || history.length === 0 }"
class="flex items-center text-secondaryLight flex-col p-4 justify-center"
>
<i class="material-icons opacity-50 pb-2">manage_search</i>
<span class="text-xs">
{{ $t("nothing_found") }} "{{ filterText }}"
</span>
</div>
<div
v-if="history.length === 0"
class="flex items-center text-secondaryLight flex-col p-4 justify-center"
>
<i class="material-icons opacity-50 pb-2">schedule</i>
<span class="text-xs">
{{ $t("history_empty") }}
</span>
</div>
<SmartConfirmModal
:show="confirmRemove"
:title="$t('are_you_sure_remove_history')"
@hide-modal="confirmRemove = false"
@resolve="clearHistory"
/>
</AppSection>
</template>
@@ -103,9 +84,8 @@ export default {
data() {
return {
filterText: "",
showFilter: false,
isClearingHistory: false,
showMore: false,
confirmRemove: false,
}
},
subscriptions() {
@@ -132,8 +112,6 @@ export default {
if (this.page === "rest") clearRESTHistory()
else clearGraphqlHistory()
this.isClearingHistory = false
this.$toast.error(this.$t("history_deleted"), {
icon: "delete",
})
@@ -149,16 +127,6 @@ export default {
icon: "delete",
})
},
enableHistoryClearing() {
if (!this.history || !this.history.length) return
this.isClearingHistory = true
},
disableHistoryClearing() {
this.isClearingHistory = false
},
toggleCollapse() {
this.showMore = !this.showMore
},
toggleStar(entry) {
if (this.page === "rest") toggleRESTHistoryEntryStar(entry)
else toggleGraphqlHistoryEntryStar(entry)

View File

@@ -1,126 +1,44 @@
<template>
<div>
<div class="flex">
<span
class="p-2 m-2 truncate inline-flex cursor-pointer items-center text-sm"
:class="entryStatus.className"
:style="{ '--status-code': entry.status }"
@click="$emit('use-entry')"
>
{{ `${entry.method} \xA0 • \xA0 ${entry.status}` }}
<div class="flex group">
<span
class="
font-mono font-bold
flex
justify-center
items-center
text-xs
w-12
mx-2
truncate
"
:class="entryStatus.className"
:style="{ '--status-code': entry.status }"
@click="$emit('use-entry')"
>
{{ entry.method }}
</span>
<span class="py-3 pr-3 flex flex-1 min-w-0 text-secondaryLight text-xs">
<span class="truncate">
{{ `${entry.url}${entry.path}` }}
</span>
<li>
<input
:aria-label="$t('token_req_name')"
type="text"
readonly
:value="entry.name"
:placeholder="$t('empty_req_name')"
class="input cursor-pointer text-sm bg-transparent"
@click="$emit('use-entry')"
/>
</li>
<span>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="!entry.star ? $t('add_star') : $t('remove_star')"
data-testid="star_button"
:class="{ stared: entry.star }"
:icon="entry.star ? 'star' : 'star_border'"
@click.native="$emit('toggle-star')"
/>
</span>
<!-- <li>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }" title="{
content: !entry.usesScripts
? 'No pre-request script'
: 'Used pre-request script'
}"
>
<i class="material-icons">
{{ !entry.usesScripts ? "http" : "code" }}
</i>
</li> -->
<tippy ref="options" tabindex="-1" trigger="click" theme="popover" arrow>
<template #trigger>
<TabPrimary
v-tippy="{ theme: 'tooltip' }"
:title="$t('options')"
icon="more_vert"
/>
</template>
<SmartItem
data-testid="restore_history_entry"
:aria-label="$t('edit')"
icon="restore"
:label="$t('restore')"
@click.native="
$emit('use-entry')
$refs.options.tippy().hide()
"
/>
<SmartItem
data-testid="delete_history_entry"
:aria-label="$t('delete')"
icon="delete"
:label="$t('delete')"
@click.native="
$emit('delete-entry')
$refs.options.tippy().hide()
"
/>
</tippy>
</div>
<div class="flex">
<li>
<input
:aria-label="$t('url')"
type="text"
readonly
:value="`${entry.url}${entry.path}`"
:placeholder="$t('no_url')"
class="input pt-0 mt-0 text-sm bg-transparent text-secondaryLight"
/>
</li>
</div>
<transition name="fade">
<div v-if="showMore" class="flex">
<li>
<input
v-tippy="{ theme: 'tooltip' }"
title="entry.date"
:aria-label="$t('time')"
type="text"
readonly
:value="entry.time"
class="input pt-0 mt-0 text-sm bg-transparent text-secondaryLight"
/>
</li>
<li>
<input
:aria-label="$t('duration')"
type="text"
readonly
:value="`Duration: ${entry.duration}ms`"
:placeholder="$t('no_duration')"
class="input pt-0 mt-0 text-sm bg-transparent text-secondaryLight"
/>
</li>
<!-- <li>
<input class="input"
:aria-label="$t('prerequest_script')"
type="text"
readonly
:value="entry.preRequestScript"
:placeholder="$t('no_prerequest_script')"
class="pt-0 mt-0 text-sm bg-transparent text-secondaryLight"
/>
</li> -->
</div>
</transition>
</span>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
data-testid="delete_history_entry"
icon="delete"
:title="$t('delete')"
class="group-hover:inline-flex hidden"
color="red"
@click.native="$emit('delete-entry')"
/>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
:title="!entry.star ? $t('add_star') : $t('remove_star')"
:class="{ 'group-hover:inline-flex hidden': !entry.star }"
:icon="entry.star ? 'star' : 'star_border'"
color="yellow"
@click.native="$emit('toggle-star')"
/>
</div>
</template>
@@ -132,11 +50,6 @@ export default {
entry: { type: Object, default: () => {} },
showMore: Boolean,
},
data() {
return {
expand: false,
}
},
computed: {
entryStatus() {
const foundStatusGroup = findStatusGroup(this.entry.status)
@@ -149,9 +62,3 @@ export default {
},
}
</script>
<style scoped lang="scss">
.stared {
color: #f8e81c !important;
}
</style>

View File

@@ -43,6 +43,7 @@ export default {
},
resolve() {
this.$emit("resolve")
this.$emit("hide-modal")
},
},
}

View File

@@ -1,5 +1,5 @@
<template>
<div v-show="isActive">
<div v-show="active">
<slot></slot>
</div>
</template>
@@ -18,18 +18,12 @@ export default {
data() {
return {
isActive: false,
active: false,
}
},
// computed: {
// href() {
// return `#${this.label.toLowerCase().replace(/ /g, "-")}`
// },
// },
mounted() {
this.isActive = this.selected
this.active = this.selected
},
}
</script>

View File

@@ -1,13 +1,13 @@
<template>
<div class="tabs-wrapper bg-blue-300">
<div class="tabs" :class="styles">
<div class="flex flex-col flex-nowrap relative flex-1">
<div class="tabs hide-scrollbar" :class="styles">
<div class="flex w-0">
<div class="inline-flex">
<button
v-for="(tab, index) in tabs"
:key="index"
class="tab"
:class="{ 'is-active': tab.isActive }"
:class="{ active: tab.active }"
:tabindex="0"
@keyup.enter="selectTab(tab)"
@click="selectTab(tab)"
@@ -20,7 +20,7 @@
</div>
</div>
</div>
<div class="tabs-details">
<div>
<slot></slot>
</div>
</div>
@@ -48,7 +48,7 @@ export default {
methods: {
selectTab({ id }) {
this.tabs.forEach((tab) => {
tab.isActive = tab.id === id
tab.active = tab.id === id
})
this.$emit("tab-changed", id)
},
@@ -57,47 +57,61 @@ export default {
</script>
<style scoped lang="scss">
.tabs-wrapper {
.tabs {
@apply flex;
@apply flex-col;
@apply flex-nowrap;
@apply flex-1;
@apply whitespace-nowrap;
@apply overflow-auto;
@apply bg-primary;
.tabs {
&::after {
@apply absolute;
@apply inset-x-0;
@apply bottom-0;
@apply bg-dividerLight;
@apply z-1;
@apply h-0.5;
content: "";
}
.tab {
@apply flex;
@apply flex-1;
@apply whitespace-nowrap;
@apply overflow-auto;
@apply items-center;
@apply justify-center;
@apply px-4;
@apply py-3;
@apply text-secondary;
@apply font-semibold;
@apply text-xs;
@apply cursor-pointer;
@apply transition;
@apply hover:text-secondaryDark;
@apply focus:text-secondaryDark;
@apply focus:outline-none;
@apply relative;
.tab {
@apply flex;
@apply items-center;
@apply justify-center;
@apply px-4;
@apply py-2;
@apply text-secondaryLight;
@apply font-semibold;
@apply text-xs;
@apply cursor-pointer;
@apply transition;
@apply border-b-2;
@apply border-transparent;
@apply rounded-t-lg;
&::after {
@apply absolute;
@apply inset-x-0;
@apply bottom-0;
@apply bg-dividerLight;
@apply z-2;
@apply h-0.5;
.material-icons {
@apply mr-4;
}
content: "";
}
&:hover {
@apply text-secondaryDark;
}
&:focus {
@apply text-secondaryDark;
@apply outline-none;
}
&.is-active {
@apply text-accent;
@apply border-accent;
.material-icons {
@apply mr-4;
}
&.active {
@apply text-accent;
@apply border-accent;
&::after {
@apply bg-accent;
}
}
}

View File

@@ -61,7 +61,7 @@ describe("tab", () => {
selected: true,
},
{
isActive: true,
active: true,
}
)
@@ -76,7 +76,7 @@ describe("tab", () => {
id: "testid",
},
{
isActive: false,
active: false,
}
)

View File

@@ -50,7 +50,7 @@ describe("tabs", () => {
wrapper.vm.selectTab({ id: "tab2" })
await wrapper.vm.$nextTick()
expect(wrapper.vm.$data.tabs[1].$data.isActive).toEqual(true)
expect(wrapper.vm.$data.tabs[1].$data.active).toEqual(true)
})
test("switched tab page is rendered and the other page is not rendered", async () => {
@@ -60,8 +60,8 @@ describe("tabs", () => {
wrapper.vm.selectTab({ id: "tab2" })
await wrapper.vm.$nextTick()
expect(wrapper.vm.$data.tabs[0].$data.isActive).toEqual(false)
expect(wrapper.vm.$data.tabs[1].$data.isActive).toEqual(true)
expect(wrapper.vm.$data.tabs[2].$data.isActive).toEqual(false)
expect(wrapper.vm.$data.tabs[0].$data.active).toEqual(false)
expect(wrapper.vm.$data.tabs[1].$data.active).toEqual(true)
expect(wrapper.vm.$data.tabs[2].$data.active).toEqual(false)
})
})

View File

@@ -183,7 +183,7 @@
"restore": "Restore",
"add_star": "Add star",
"remove_star": "Remove star",
"nothing_found": "Nothing found",
"nothing_found": "Nothing found for",
"replace_current": "Replace current",
"replace_json": "Replace with JSON",
"preserve_current": "Preserve current",
@@ -281,6 +281,7 @@
"tests": "Tests",
"create_new_collection": "Create new collection",
"create_new_environment": "Create new environment",
"are_you_sure_remove_history": "Are you sure you want to remove all History?",
"are_you_sure_remove_collection": "Are you sure you want to remove this Collection?",
"are_you_sure_remove_folder": "Are you sure you want to remove this folder?",
"are_you_sure_remove_request": "Are you sure you want to remove this request?",

View File

@@ -6,23 +6,23 @@
<Pane
v-if="!hideNavigationPane"
style="width: auto"
class="overflow-auto"
class="hide-scrollbar overflow-auto"
>
<AppSidenav />
</Pane>
<Pane class="flex flex-1 overflow-auto">
<Splitpanes horizontal :dbl-click-splitter="false">
<Pane v-if="!zenMode" style="height: auto" class="overflow-auto">
<Pane v-if="!zenMode" style="height: auto">
<AppHeader />
</Pane>
<Pane class="flex flex-1 overflow-auto">
<nuxt class="container" :hide-right-pane="hideRightPane" />
<nuxt class="flex flex-1" :hide-right-pane="hideRightPane" />
</Pane>
</Splitpanes>
</Pane>
</Splitpanes>
</Pane>
<Pane style="height: auto" class="overflow-auto">
<Pane style="height: auto">
<div class="flex justify-between">
<div>
<ButtonSecondary

View File

@@ -172,10 +172,12 @@
/>
</div>
<div class="flex flex-1">
<span>
<ButtonSecondary
:title="$t('import_curl')"
icon="import_export"
/>
@click.native="showCurlImportModal = !showCurlImportModal"
v-tippy="{ theme: 'tooltip' }"
/>
<ButtonSecondary
@click.native="showCodegenModal = !showCodegenModal"
:disabled="!isValidURL"
@@ -597,9 +599,9 @@
</Pane>
</Splitpanes>
</Pane>
<Pane max-size="35" min-size="20" class="overflow-auto">
<aside class="h-full bg-yellow-200">
<SmartTabs>
<Pane max-size="35" min-size="20" class="overflow-auto hide-scrollbar">
<aside class="h-full">
<SmartTabs styles="sticky top-0">
<SmartTab :id="'history'" :label="$t('history')" :selected="true">
<History
:page="'rest'"

View File

@@ -1,5 +1,5 @@
<template>
<div class="flex container flex-col min-h-screen">
<div class="flex flex-col min-h-screen">
<span v-if="signingInWithEmail">{{ $t("loading") }}</span>
<span v-else>{{ $t("waiting_for_connection") }}</span>
<pre v-if="error">{{ error }}</pre>

View File

@@ -150,9 +150,7 @@
<div>
<ButtonSecondary
v-tippy="{ theme: 'tooltip' }"
title="
`${$t('run_query')} (${getSpecialKey()}-Enter)`
"
:title="`${$t('run_query')} (${getSpecialKey()}-Enter)`"
class="button"
icon="play_arrow"
@click.native="runQuery()"

View File

@@ -33,4 +33,5 @@ export default defineConfig({
icon: "var(--font-icon)",
},
},
safelist: "text-red-500 text-red-600",
})