Skip to content

Commit

Permalink
Merge branch 'unified-desktop-gui' into feat/settings-footer
Browse files Browse the repository at this point in the history
  • Loading branch information
elevatebart committed Nov 10, 2021
2 parents 13fbff7 + 5165a8e commit 053e9bc
Show file tree
Hide file tree
Showing 26 changed files with 820 additions and 56 deletions.
2 changes: 1 addition & 1 deletion packages/app/src/layouts/default.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<template>
<div class="h-screen overflow-hidden flex flex-row">
<main class="h-screen min-w-0 flex-1 border-t border-gray-200 lg:flex">
<main class="h-screen min-w-0 flex-1 lg:flex">
<section
aria-labelledby="primary-heading"
class="min-w-0 flex-1 h-full flex flex-col overflow-hidden lg:order-last"
Expand Down
9 changes: 9 additions & 0 deletions packages/app/src/navigation/KeyboardBindingsModal.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import KeyboardBindingsModal from './KeyboardBindingsModal.vue'

describe('SidebarNavigationRow', () => {
it('renders something', () => {
cy.mount(() => {
return <KeyboardBindingsModal show />
})
})
})
65 changes: 65 additions & 0 deletions packages/app/src/navigation/KeyboardBindingsModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<template>
<StandardModal
class="transition duration-200 transition-all"
:click-outside="false"
variant="bare"
:title="t('sideBar.keyboardShortcuts.title')"
:model-value="show"
data-cy="switch-modal"
help-link=""
@update:model-value="emits('close')"
>
<ul class="m-24px w-384px">
<li
v-for="binding in keyBindings"
:key="binding.key.join('-')"
class="flex items-center h-24px my-16px"
>
<p class="flex-grow text-gray-700 text-16px leading-24px">
{{ binding.description }}
</p>
<span
v-for="key in binding.key"
:key="key"
class="inline-block rounded-sm border border-gray-100 bg-gray-50 h-24px w-24px text-indigo-500 text-14px leading-20px text-center ml-8px"
>
{{ key }}
</span>
</li>
</ul>
</StandardModal>
</template>

<script lang="ts" setup>
import StandardModal from '@cy/components/StandardModal.vue'
import { useI18n } from '@cy/i18n'
const { t } = useI18n()
defineProps<{
show: boolean
}>()
const emits = defineEmits<{
(eventName: 'close'): void
}>()
const keyBindings = [
{
key: ['r'],
description: t('sideBar.keyboardShortcuts.rerun'),
},
{
key: ['s'],
description: t('sideBar.keyboardShortcuts.stop'),
},
{
key: ['f'],
description: t('sideBar.keyboardShortcuts.toggle'),
},
{
key: ['', 'b'] as const,
description: t('sideBar.keyboardShortcuts.collapse'),
},
]
</script>
31 changes: 30 additions & 1 deletion packages/app/src/navigation/SidebarNavigation.vue
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,28 @@
/>
</RouterLink>
</nav>
<SidebarTooltip
class="cursor-pointer inline-block rounded
absolute right-0 bottom-0
p-7px m-16px w-32px
border border-transparent hover:border-gray-500
transform transition-all duration-300"
:class="{ '-translate-y-48px': !mainStore.navBarExpanded }"
:disabled="mainStore.navBarExpanded"
:popper-top-offset="-4"
@click="bindingsOpen = true"
>
<i-cy-command-key_x16
class="w-16px h-16px icon-dark-gray-500"
/>
<template #popper>
{{ t('sideBar.keyboardShortcuts.title') }}
</template>
<KeyboardBindingsModal
:show="bindingsOpen"
@close="bindingsOpen = false"
/>
</SidebarTooltip>
<img
:src="CypressLogo"
class="w-32px h-32px m-16px"
Expand All @@ -77,17 +99,22 @@
</template>

<script lang="ts" setup>
import { ref } from 'vue'
import { gql, useQuery } from '@urql/vue'
import SidebarNavigationRow from './SidebarNavigationRow.vue'
import SwitchTestingTypeButton from './SwitchTestingTypeButton.vue'
import KeyboardBindingsModal from './KeyboardBindingsModal.vue'
import CodeIcon from '~icons/cy/code-editor_x24'
import RunsIcon from '~icons/cy/runs_x24'
import SettingsIcon from '~icons/cy/settings_x24'
import SidebarTooltip from './SidebarTooltip.vue'
import HideDuringScreenshot from '../runner/screenshot/HideDuringScreenshot.vue'
import { useMainStore } from '../store'
import { SideBarNavigationDocument } from '../generated/graphql'
import CypressLogo from '@packages/frontend-shared/src/assets/logos/cypress_s.png'
import HideDuringScreenshot from '../runner/screenshot/HideDuringScreenshot.vue'
import { useI18n } from '@cy/i18n'

const { t } = useI18n()

const navigation = [
{ name: 'Home', icon: CodeIcon, href: '/' },
Expand All @@ -107,6 +134,8 @@ query SideBarNavigation {

const query = useQuery({ query: SideBarNavigationDocument })

const bindingsOpen = ref(false)

const mainStore = useMainStore()

</script>
4 changes: 2 additions & 2 deletions packages/app/src/runs/RunsEmpty.vue
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
<TerminalPrompt
class="-ml-16px"
command="git add cypress.config.js"
:project-name="projectName"
:project-folder-name="projectName"
/>
</li>
<li class="mt-24px">
Expand All @@ -40,7 +40,7 @@
<TerminalPrompt
class="-ml-16px"
:command="recordCommand"
:project-name="projectName"
:project-folder-name="projectName"
/>
</li>
</ol>
Expand Down
47 changes: 39 additions & 8 deletions packages/app/src/specs/InlineSpecList.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
<template>
<div class="w-300px overflow-x-hidden h-full">
<InlineSpecListRow
v-for="spec in specs"
:key="spec.node.id"
:spec="spec.node"
:selected="isCurrentSpec(spec)"
<div class="w-280px">
<InlineSpecListHeader
v-model:tab="tab"
v-model:search="search"
/>
<div class="h-[calc(100vh-65px)] overflow-y-auto overflow-x-hidden pt-16px">
<template v-if="tab === 'file-list'">
<InlineSpecListRow
v-for="spec in specs"
:key="spec.node.id"
:spec="spec.node"
:selected="isCurrentSpec(spec)"
/>
</template>
<template v-else>
<div class="text-white">
FileTree not implemented
</div>
</template>
</div>
</div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { computed, ref } from 'vue'
import { gql } from '@urql/vue'
import type { SpecNode_InlineSpecListFragment, Specs_InlineSpecListFragment } from '../generated/graphql'
import { useSpecStore } from '../store'
import InlineSpecListHeader from './InlineSpecListHeader.vue'
import InlineSpecListRow from './InlineSpecListRow.vue'
gql`
Expand Down Expand Up @@ -52,5 +66,22 @@ const isCurrentSpec = (spec: SpecNode_InlineSpecListFragment) => {
return spec.node.relative === specStore.activeSpec?.relative
}
const specs = computed(() => props.gql.specs?.edges || [])
const tab = ref('file-list')
const search = ref('')
const specs = computed(() => {
if (!search.value) {
return props.gql.specs?.edges || []
}
return (
props.gql.specs?.edges.filter((edge) => {
return (
edge.node.fileName.toLowerCase() +
edge.node.specFileExtension.toLowerCase()
).includes(search.value.toLocaleLowerCase())
}) || []
)
})
</script>
50 changes: 50 additions & 0 deletions packages/app/src/specs/InlineSpecListHeader.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import InlineSpecListHeader from './InlineSpecListHeader.vue'
import { ref } from 'vue'

describe('InlineSpecListHeader', () => {
beforeEach(() => {
const search = ref('')
const tab = ref('file-list')
const onAddSpec = cy.spy().as('new-spec')

cy.wrap(search).as('search')
cy.wrap(tab).as('tab')

const methods = {
search: search.value,
'onUpdate:search': (val: string) => {
search.value = val
},
tab: tab.value,
'onUpdate:tab': (val: string) => {
tab.value = val
},
onAddSpec,
}

cy.mount(() =>
(<div class="bg-gray-1000">
<InlineSpecListHeader {...methods} />
</div>))
})

it('should allow search', () => {
const searchString = 'my/component.cy.tsx'

cy.get('input')
.type(searchString, { delay: 0 })
.get('@search').its('value').should('eq', searchString)
})

it('should toggle radio group', () => {
cy.get('[data-cy="file-tree-radio-option"]')
.click()
.get('@tab').its('value').should('eq', 'file-tree')
})

it('should emit add spec', () => {
cy.get('[data-cy="runner-spec-list-add-spec"]').click()
.get('@new-spec')
.should('have.been.called')
})
})
116 changes: 116 additions & 0 deletions packages/app/src/specs/InlineSpecListHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<template>
<div class="h-64px items-center gap-8px mx-16px border-b-1 border-gray-900 grid grid-cols-[minmax(0,1fr),63px,24px]">
<div class="relative items-center group">
<div class="absolute inset-y-0 flex items-center pointer-events-none">
<i-cy-magnifying-glass_x16
:class="inputFocused ? 'icon-dark-gray-200' : 'icon-dark-gray-900'"
class="icon-light-gray-1000"
/>
</div>
<input
class="
w-full
bg-gray-1000
pl-6
text-gray-500
placeholder-gray-700
font-light
outline-none
"
placeholder="Search Specs"
:value="search"
@focus="inputFocused = true"
@blur="inputFocused = false"
@input="onInput"
>
</div>
<RadioGroup
:model-value="tab"
class="flex border-1 border-gray-900 rounded-md h-24px w-64px text-md cursor-pointer"
@update:model-value="emit('update:tab', $event)"
>
<RadioGroupOption
v-slot="{ checked }"
as="template"
value="file-list"
data-cy="file-list-radio-option"
>
<div
class="flex flex-1 items-center justify-center outline-none"
:class="{ 'bg-gray-900': checked }"
>
<i-cy-file-list
:class="checked ? 'icon-dark-gray-200' : 'icon-dark-gray-700'"
/>
</div>
</RadioGroupOption>
<RadioGroupOption
v-slot="{ checked }"
as="template"
value="file-tree"
data-cy="file-tree-radio-option"
>
<div
class="flex flex-1 items-center justify-center outline-none"
:class="{ 'bg-gray-900': checked }"
>
<i-cy-file-tree
:class="checked ? 'icon-dark-gray-200' : 'icon-dark-gray-700'"
/>
</div>
</RadioGroupOption>
</RadioGroup>
<button
class="
border-1 border-gray-900
h-24px
w-24px
rounded-md
add-button
outline-none
flex
items-center
justify-center
"
data-cy="runner-spec-list-add-spec"
@click="emit('addSpec')"
>
<i-cy-add-small_x16 class="icon-light-gray-50 icon-dark-gray-200" />
</button>
</div>
</template>

<script lang="ts" setup>
import Input from '@cy/components/Input.vue'
import Button from '@cy/components/Button.vue'
import { ref } from 'vue'
import { RadioGroup, RadioGroupOption } from '@headlessui/vue'
defineProps<{tab: string, search: string}>()
const emit = defineEmits<{
(e: 'update:tab', tab: string): void
(e: 'update:search', search: string): void
(e: 'addSpec'): void
}>()
const inputFocused = ref(false)
const onInput = (e: Event) => {
const value = (e.target as HTMLInputElement).value
emit('update:search', value)
}
</script>

<style>
/** Windi box shadows are dark, so styles are for lighter box shadows */
.add-button {
transition: box-shadow 0.3s ease-in-out;
}
.add-button:hover {
box-shadow: 0 0 4px rgba(191, 194, 212, 0.6);
}
</style>
Loading

0 comments on commit 053e9bc

Please sign in to comment.