Skip to content

Commit 80400c1

Browse files
authored
Merge pull request #338 from owncloud/mm_fix-advanced-search-translations
MM: fix(advanced-search): detect OCR status + align UI with ODS
2 parents 7d27670 + e9f1646 commit 80400c1

15 files changed

Lines changed: 796 additions & 506 deletions

File tree

packages/web-app-advanced-search/src/components/FilterChip.vue

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
<template>
2-
<span class="filter-chip" :class="categoryClass" role="group">
2+
<oc-tag rounded class="filter-chip" :class="categoryClass" type="span">
33
<span class="chip-label">{{ filter.label }}:</span>
44
<span class="chip-value">{{ filter.value }}</span>
5-
<button
5+
<oc-button
6+
appearance="raw"
7+
variation="passive"
8+
size="small"
69
class="chip-remove"
710
:aria-label="$gettext('Remove filter') + ': ' + filter.label + ' ' + filter.value"
811
@click="emit('remove')"
912
>
10-
<span aria-hidden="true">×</span>
11-
</button>
12-
</span>
13+
<oc-icon name="close" size="xsmall" />
14+
</oc-button>
15+
</oc-tag>
1316
</template>
1417

1518
<script setup lang="ts">
@@ -32,11 +35,8 @@ const categoryClass = computed(() => `chip-${props.filter.category}`)
3235

3336
<style scoped>
3437
.filter-chip {
35-
display: inline-flex;
36-
align-items: center;
3738
gap: 0.25rem;
3839
padding: 0.25rem 0.5rem;
39-
border-radius: 16px;
4040
font-size: 0.8125rem;
4141
background: var(--oc-color-background-muted, #e8e8e8);
4242
color: var(--oc-color-text-default, #333);
@@ -49,12 +49,12 @@ const categoryClass = computed(() => `chip-${props.filter.category}`)
4949
5050
.chip-photo {
5151
background: rgba(156, 39, 176, 0.15);
52-
color: #9c27b0;
52+
color: #6a1b9a;
5353
}
5454
5555
.chip-text {
5656
background: rgba(46, 125, 50, 0.15);
57-
color: #2e7d32;
57+
color: var(--oc-color-swatch-success-default, #2e7d32);
5858
}
5959
6060
.chip-label {
@@ -75,12 +75,8 @@ const categoryClass = computed(() => `chip-${props.filter.category}`)
7575
width: 1.25rem;
7676
height: 1.25rem;
7777
margin-left: 0.25rem;
78-
background: transparent;
79-
border: none;
8078
border-radius: 50%;
8179
cursor: pointer;
82-
font-size: 1rem;
83-
line-height: 1;
8480
color: inherit;
8581
opacity: 0.7;
8682
}
@@ -89,5 +85,4 @@ const categoryClass = computed(() => `chip-${props.filter.category}`)
8985
background: rgba(0, 0, 0, 0.1);
9086
opacity: 1;
9187
}
92-
9388
</style>
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
<template>
2+
<div class="item-filter" :class="`item-filter-${label.toLowerCase().replace(/\s+/g, '-')}`">
3+
<oc-filter-chip
4+
:filter-label="label"
5+
:selected-item-names="selectedItemNames"
6+
:close-on-click="!allowCustom"
7+
@clear-filter="clear"
8+
@show-drop="onShowDrop"
9+
>
10+
<div v-if="allowCustom" class="filter-select-custom">
11+
<input
12+
:id="`filter-custom-${label.toLowerCase().replace(/\s+/g, '-')}`"
13+
ref="customInput"
14+
type="text"
15+
class="filter-select-custom-input"
16+
:value="customText"
17+
:placeholder="customPlaceholder || label"
18+
:aria-label="customPlaceholder || label"
19+
@input="customText = ($event.target as HTMLInputElement).value"
20+
@keyup.enter="applyCustom"
21+
@click.stop
22+
/>
23+
<button
24+
v-if="customText"
25+
type="button"
26+
class="oc-button oc-rounded oc-button-s oc-button-justify-content-center oc-button-gap-m oc-button-primary oc-button-primary-filled filter-select-custom-apply"
27+
@click.stop="applyCustom"
28+
>
29+
<span>OK</span>
30+
</button>
31+
</div>
32+
<oc-list class="item-filter-list">
33+
<li v-for="opt in filteredOptions" :key="String(opt.value)" class="oc-my-xs">
34+
<oc-button
35+
class="item-filter-list-item oc-flex oc-flex-middle oc-width-1-1 oc-p-xs oc-flex-between"
36+
:class="{ 'item-filter-list-item-active': String(opt.value) === String(modelValue) }"
37+
justify-content="space-between"
38+
appearance="raw"
39+
@click="select(opt.value)"
40+
>
41+
<div class="oc-flex oc-flex-middle oc-text-truncate">
42+
<oc-checkbox
43+
size="large"
44+
class="item-filter-checkbox oc-mr-s"
45+
:label="opt.label"
46+
:model-value="String(opt.value) === String(modelValue)"
47+
:label-hidden="true"
48+
@update:model-value="select(opt.value)"
49+
@click.stop
50+
/>
51+
<div v-if="opt.icon">
52+
<oc-icon :name="opt.icon" :color="opt.iconColor" size="large" />
53+
</div>
54+
<div class="oc-text-truncate oc-ml-s">
55+
<span>{{ opt.label }}</span>
56+
</div>
57+
</div>
58+
<div class="oc-flex">
59+
<oc-icon
60+
v-if="String(opt.value) === String(modelValue)"
61+
name="check"
62+
/>
63+
</div>
64+
</oc-button>
65+
</li>
66+
</oc-list>
67+
</oc-filter-chip>
68+
</div>
69+
</template>
70+
71+
<script setup lang="ts">
72+
import { ref, computed, nextTick } from 'vue'
73+
74+
const props = withDefaults(defineProps<{
75+
modelValue: string | number
76+
options: Array<{ value: string | number; label: string; icon?: string; iconColor?: string }>
77+
label: string
78+
defaultValue?: string | number
79+
ariaLabel?: string
80+
allowCustom?: boolean
81+
customPlaceholder?: string
82+
}>(), {
83+
defaultValue: undefined,
84+
ariaLabel: undefined,
85+
allowCustom: false,
86+
customPlaceholder: undefined,
87+
})
88+
89+
const emit = defineEmits<{
90+
(e: 'update:modelValue', value: string | number): void
91+
}>()
92+
93+
const customInput = ref<HTMLInputElement>()
94+
const customText = ref('')
95+
96+
const selectedItemNames = computed(() => {
97+
if (props.defaultValue === undefined) return []
98+
if (String(props.modelValue) === String(props.defaultValue)) return []
99+
const selected = props.options.find(o => String(o.value) === String(props.modelValue))
100+
if (selected) return [selected.label]
101+
if (props.modelValue) return [String(props.modelValue)]
102+
return []
103+
})
104+
105+
const filteredOptions = computed(() => {
106+
if (!props.allowCustom || !customText.value) return props.options
107+
const search = customText.value.toLowerCase()
108+
return props.options.filter(o => String(o.label).toLowerCase().includes(search))
109+
})
110+
111+
function select(value: string | number) {
112+
emit('update:modelValue', value)
113+
customText.value = ''
114+
}
115+
116+
function applyCustom() {
117+
if (customText.value.trim()) {
118+
emit('update:modelValue', customText.value.trim())
119+
customText.value = ''
120+
}
121+
}
122+
123+
function clear() {
124+
if (props.defaultValue !== undefined) {
125+
emit('update:modelValue', props.defaultValue)
126+
}
127+
customText.value = ''
128+
}
129+
130+
function onShowDrop() {
131+
customText.value = ''
132+
if (props.allowCustom) {
133+
nextTick(() => customInput.value?.focus())
134+
}
135+
}
136+
</script>
137+
138+
<style lang="scss">
139+
.item-filter {
140+
&-list {
141+
li {
142+
&:first-child {
143+
margin-top: 0 !important;
144+
}
145+
&:last-child {
146+
margin-bottom: 0 !important;
147+
}
148+
}
149+
150+
&-item {
151+
line-height: 1.5;
152+
gap: 8px;
153+
154+
&:hover,
155+
&-active {
156+
background-color: var(--oc-color-background-hover) !important;
157+
}
158+
}
159+
}
160+
}
161+
162+
.filter-select-custom {
163+
display: flex;
164+
gap: 4px;
165+
padding: 0 4px 8px;
166+
border-bottom: 1px solid var(--oc-color-border, #e0e0e0);
167+
margin-bottom: 4px;
168+
}
169+
170+
.filter-select-custom-input {
171+
flex: 1;
172+
padding: 6px 10px;
173+
border: 1px solid var(--oc-color-border, #ccc);
174+
border-radius: 4px;
175+
font-size: var(--oc-font-size-xsmall, 0.75rem);
176+
font-family: inherit;
177+
background: var(--oc-color-background-default, #fff);
178+
color: var(--oc-color-text-default, #333);
179+
outline: none;
180+
}
181+
182+
.filter-select-custom-input:focus {
183+
border-color: var(--oc-color-swatch-primary-default, #0070c0);
184+
}
185+
186+
.filter-select-custom-apply {
187+
flex-shrink: 0;
188+
}
189+
</style>

packages/web-app-advanced-search/src/components/ResultContextMenu.vue

Lines changed: 9 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,21 @@
11
<template>
22
<Teleport to="body">
33
<div v-if="visible" ref="menuRef" class="context-menu" :style="menuPosition">
4-
<button class="menu-item" @click="handleAction('download')">
5-
<span class="menu-icon">⬇️</span>
4+
<button class="oc-button-reset menu-item" @click="handleAction('download')">
5+
<span class="oc-icon oc-icon-m oc-icon-passive" aria-hidden="true"><svg fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M3 19H21V21H3V19ZM13 13.172L19.071 7.1L20.485 8.514L12 17L3.515 8.514L4.929 7.1L11 13.172V2H13V13.172Z" /></svg></span>
66
<span>{{ $gettext('Download') }}</span>
77
</button>
8-
<button class="menu-item" @click="handleAction('openInFiles')">
9-
<span class="menu-icon">📁</span>
8+
<button class="oc-button-reset menu-item" @click="handleAction('openInFiles')">
9+
<span class="oc-icon oc-icon-m oc-icon-passive" aria-hidden="true"><svg fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M10 6V8H5V19H16V14H18V20C18 20.5523 17.5523 21 17 21H4C3.44772 21 3 20.5523 3 20V7C3 6.44772 3.44772 6 4 6H10ZM21 3V11H19V6.413L11.207 14.207L9.793 12.793L17.585 5H13V3H21Z" /></svg></span>
1010
<span>{{ $gettext('Open in Files') }}</span>
1111
</button>
12-
<button class="menu-item" @click="handleAction('copyLink')">
13-
<span class="menu-icon">🔗</span>
12+
<button class="oc-button-reset menu-item" @click="handleAction('copyLink')">
13+
<span class="oc-icon oc-icon-m oc-icon-passive" aria-hidden="true"><svg fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M17 7H13V5H17C19.7614 5 22 7.23858 22 10C22 12.7614 19.7614 15 17 15H13V13H17C18.6569 13 20 11.6569 20 10C20 8.34315 18.6569 7 17 7ZM7 17H11V19H7C4.23858 19 2 16.7614 2 14C2 11.2386 4.23858 9 7 9H11V11H7C5.34315 11 4 12.3431 4 14C4 15.6569 5.34315 17 7 17ZM8 13H16V11H8V13Z" /></svg></span>
1414
<span>{{ $gettext('Copy Link') }}</span>
1515
</button>
1616
<div class="menu-divider"></div>
17-
<button class="menu-item menu-item-danger" @click="handleAction('delete')">
18-
<span class="menu-icon">🗑️</span>
17+
<button class="oc-button-reset menu-item menu-item-danger" @click="handleAction('delete')">
18+
<span class="oc-icon oc-icon-m oc-icon-passive" aria-hidden="true"><svg fill="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path d="M17 6H22V8H20V21C20 21.5523 19.5523 22 19 22H5C4.44772 22 4 21.5523 4 21V8H2V6H7V3C7 2.44772 7.44772 2 8 2H16C16.5523 2 17 2.44772 17 3V6ZM18 8H6V20H18V8ZM9 11H11V17H9V11ZM13 11H15V17H13V11ZM9 4V6H15V4H9Z" /></svg></span>
1919
<span>{{ $gettext('Delete') }}</span>
2020
</button>
2121
</div>
@@ -193,10 +193,8 @@ onUnmounted(() => {
193193
gap: 0.75rem;
194194
width: 100%;
195195
padding: 0.6rem 1rem;
196-
border: none;
197-
background: none;
198196
cursor: pointer;
199-
font-size: 0.875rem;
197+
font-size: var(--oc-font-size-default, 0.875rem);
200198
color: var(--oc-color-text-default, #333);
201199
text-align: left;
202200
transition: background 0.15s;
@@ -214,15 +212,9 @@ onUnmounted(() => {
214212
background: rgba(200, 0, 0, 0.1);
215213
}
216214
217-
.menu-icon {
218-
width: 1.25rem;
219-
text-align: center;
220-
}
221-
222215
.menu-divider {
223216
height: 1px;
224217
background: var(--oc-color-border, #e0e0e0);
225218
margin: 0.5rem 0;
226219
}
227-
228220
</style>

0 commit comments

Comments
 (0)