Skip to content

Commit 492d4c1

Browse files
committed
feat: make collaboration settings app public
1 parent eb57ec3 commit 492d4c1

5 files changed

Lines changed: 229 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[main]
2+
host = https://www.transifex.com
3+
4+
[o:opencloud-eu:p:opencloud-eu:r:web-office-settings]
5+
file_filter = locale/<lang>/app.po
6+
minimum_perc = 0
7+
resource_name = web-office-settings
8+
source_file = template.pot
9+
source_lang = en
10+
type = PO
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"name": "web-app-office-settings",
3+
"version": "0.0.0",
4+
"private": true,
5+
"description": "OpenCloud Web collaboration settings",
6+
"license": "AGPL-3.0",
7+
"peerDependencies": {
8+
"@opencloud-eu/design-system": "workspace:^",
9+
"@opencloud-eu/web-pkg": "workspace:*",
10+
"@vueuse/core": "^14.0.0",
11+
"vue3-gettext": "^4.0.0-beta.1"
12+
}
13+
}
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
<template>
2+
<main class="flex app-content size-full rounded-l-xl">
3+
<app-loading-spinner v-if="fontsLoading" />
4+
<template v-else>
5+
<div class="flex w-full flex-1 h-full flex-nowrap sm:flex-wrap">
6+
<div class="relative grid grid-cols-1 flex-1 focus:outline-0 h-full overflow-y-auto gap-0">
7+
<div class="outline-0 z-0 flex flex-col">
8+
<div class="py-1 px-4 top-0 z-20 bg-role-surface" :class="{ sticky: isSticky }">
9+
<div class="flex justify-between items-center h-12">
10+
<oc-breadcrumb id="admin-settings-breadcrumb" :items="breadcrumbs" />
11+
</div>
12+
<div class="flex">
13+
<h1>{{ $gettext('Manage Fonts') }}</h1>
14+
</div>
15+
<div class="flex">
16+
<oc-file-input
17+
v-model="files"
18+
fileTypes=".ttf,.otf"
19+
:multiple="true"
20+
:label="$gettext('Select font')"
21+
class="my-6"
22+
/>
23+
</div>
24+
</div>
25+
<oc-table-simple>
26+
<oc-table-head>
27+
<oc-table-tr>
28+
<oc-table-th>{{ $gettext('Name') }}</oc-table-th>
29+
<oc-table-th>{{ $gettext('Preview') }}</oc-table-th>
30+
<oc-table-th class="hidden md:table-cell">{{ $gettext('Version') }}</oc-table-th>
31+
<oc-table-th class="hidden md:table-cell">{{ $gettext('Designer') }}</oc-table-th>
32+
</oc-table-tr>
33+
</oc-table-head>
34+
<oc-table-body>
35+
<oc-table-tr v-for="font in fontsData" :key="font.family">
36+
<oc-table-td>{{ font.family }}</oc-table-td>
37+
<oc-table-td
38+
><img :src="`/collaboration/fonts/preview/${font.file}`" alt=""
39+
/></oc-table-td>
40+
<oc-table-td class="hidden md:table-cell">{{ font.version }}</oc-table-td>
41+
<oc-table-td class="hidden md:table-cell">{{ font.designer }}</oc-table-td>
42+
<oc-table-td class="text-right">
43+
<oc-button :aria-label="$gettext('Delete')" @click="deleteFont(font)">
44+
<oc-icon name="delete-bin" fill-type="line" size="small" />
45+
</oc-button>
46+
</oc-table-td>
47+
</oc-table-tr>
48+
</oc-table-body>
49+
</oc-table-simple>
50+
</div>
51+
</div>
52+
</div>
53+
</template>
54+
</main>
55+
</template>
56+
57+
<script setup lang="ts">
58+
import {
59+
useClientService,
60+
AppLoadingSpinner,
61+
useMessages,
62+
useIsTopBarSticky
63+
} from '@opencloud-eu/web-pkg'
64+
import { useAsyncState } from '@vueuse/core'
65+
import { computed, ref, watch } from 'vue'
66+
import { useGettext } from 'vue3-gettext'
67+
import { BreadcrumbItem } from '@opencloud-eu/design-system/helpers'
68+
69+
interface Font {
70+
file: string
71+
family: string
72+
copyright: string
73+
version: string
74+
trademark: string
75+
manufacturer: string
76+
designer: string
77+
description: string
78+
vendor_url: string
79+
designer_url: string
80+
license: string
81+
license_url: string
82+
uri: string
83+
}
84+
85+
const { $gettext } = useGettext()
86+
const { showErrorMessage } = useMessages()
87+
const { isSticky } = useIsTopBarSticky()
88+
const breadcrumbs = computed<BreadcrumbItem[]>(() => [
89+
{
90+
text: $gettext('Office')
91+
}
92+
])
93+
94+
const httpClient = useClientService().httpAuthenticated
95+
const {
96+
state: fontsData,
97+
execute: refreshFonts,
98+
isLoading: fontsLoading
99+
} = useAsyncState(async (): Promise<Font[]> => {
100+
try {
101+
const {
102+
data: { fonts }
103+
} = await httpClient.get<{ fonts: Font[] }>('/collaboration/fonts')
104+
await new Promise((resolve) => setTimeout(resolve, 500)) // prevent flickering
105+
return fonts
106+
} catch (e) {
107+
console.error(e)
108+
showErrorMessage({
109+
title: $gettext('Failed to load fonts'),
110+
errors: [e]
111+
})
112+
}
113+
}, null)
114+
115+
const files = ref<FileList>()
116+
watch(files, async (newFiles) => {
117+
await Promise.all(
118+
Array.from(newFiles).map(async (file) => {
119+
const formData = new FormData()
120+
formData.append('font', file)
121+
try {
122+
await httpClient.post('/collaboration/fonts/manage/', formData)
123+
} catch (e) {
124+
console.error(e)
125+
showErrorMessage({
126+
title: $gettext('Failed to update fonts'),
127+
errors: [e]
128+
})
129+
}
130+
131+
await refreshFonts()
132+
})
133+
)
134+
})
135+
136+
const deleteFont = async (font: Font) => {
137+
try {
138+
await httpClient.delete(`/collaboration/fonts/manage/${font.file}`)
139+
} catch (e) {
140+
console.error(e)
141+
showErrorMessage({
142+
title: $gettext('Failed to delete font'),
143+
errors: [e]
144+
})
145+
}
146+
await refreshFonts()
147+
}
148+
</script>
149+
150+
<style scoped>
151+
@reference '@opencloud-eu/design-system/tailwind';
152+
153+
th,
154+
td {
155+
@apply p-4;
156+
}
157+
</style>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import { defineWebApplication, SidebarNavExtension } from '@opencloud-eu/web-pkg'
2+
import translations from '../l10n/translations.json'
3+
import { useGettext } from 'vue3-gettext'
4+
import { computed } from 'vue'
5+
import App from './App.vue'
6+
7+
export default defineWebApplication({
8+
setup() {
9+
const { $gettext } = useGettext()
10+
const appId = 'admin-settings/office'
11+
const appInfo = {
12+
name: $gettext('Office Settings'),
13+
id: appId
14+
}
15+
const extensions = computed<SidebarNavExtension[]>(() => [
16+
{
17+
id: 'com.github.opencloud-eu.web.admin-settings.left-nav.office',
18+
extensionPointIds: ['app.admin-settings.navItems'],
19+
type: 'sidebarNav',
20+
navItem: {
21+
isVisible: () => true,
22+
name: $gettext('Office'),
23+
icon: 'attachment',
24+
route: {
25+
path: `/${appId}`
26+
}
27+
}
28+
}
29+
])
30+
const routes = [
31+
{
32+
path: '/',
33+
name: 'office',
34+
component: App,
35+
meta: {
36+
title: $gettext('Office Settings'),
37+
authContext: 'user'
38+
}
39+
}
40+
]
41+
return {
42+
appInfo,
43+
routes,
44+
extensions,
45+
translations
46+
}
47+
}
48+
})

0 commit comments

Comments
 (0)