mirror of
https://github.com/YunoHost/yunohost-portal.git
synced 2024-09-03 20:06:23 +02:00
linting
This commit is contained in:
parent
61c57b876e
commit
0491bd638d
6 changed files with 206 additions and 210 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
- This is a based on [Nuxt v3](https://nuxt.com/)
|
- This is a based on [Nuxt v3](https://nuxt.com/)
|
||||||
|
|
||||||
### Setup
|
### Setup
|
||||||
|
|
||||||
- I'm doing all this from inside a YunoHost LXC
|
- I'm doing all this from inside a YunoHost LXC
|
||||||
- You may want to open port 3000 (or disable the firewall) to access the dev server
|
- You may want to open port 3000 (or disable the firewall) to access the dev server
|
||||||
|
|
|
@ -1,31 +1,32 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="p-10 min-h-screen">
|
<div class="p-10 min-h-screen">
|
||||||
<div class="container mx-auto p-4">
|
<div class="container mx-auto p-4">
|
||||||
<slot />
|
<slot />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<footer class="container fixed bottom-10 mx-10 pr-10 text-gray-400">
|
||||||
|
<slot name="footer">
|
||||||
|
<div class="flex flex-row items-end">
|
||||||
|
<!-- FIXME: wrap this in an if: connected somehow ? -->
|
||||||
|
<nav class="grow space-x-5 border-t mr-10 border-gray-500">
|
||||||
|
<a>Edit my profile</a>
|
||||||
|
<a href="//yunohost.org/docs" target="_blank">Documentation</a>
|
||||||
|
<a href="//yunohost.org/help" target="_blank">Help</a>
|
||||||
|
<a href="/yunohost/admin/" target="_blank">Administration</a>
|
||||||
|
</nav>
|
||||||
|
<img class="flex-none mr-10" src="/assets/img/logo-white.svg" />
|
||||||
</div>
|
</div>
|
||||||
<footer class="container fixed bottom-10 mx-10 pr-10 text-gray-400">
|
</slot>
|
||||||
<slot name="footer">
|
</footer>
|
||||||
<div class="flex flex-row items-end">
|
</div>
|
||||||
<!-- FIXME: wrap this in an if: connected somehow ? -->
|
|
||||||
<nav class="grow space-x-5 border-t mr-10 border-gray-500">
|
|
||||||
<a>Edit my profile</a>
|
|
||||||
<a href="//yunohost.org/docs" target="_blank">Documentation</a>
|
|
||||||
<a href="//yunohost.org/help" target="_blank">Help</a>
|
|
||||||
<a href="/yunohost/admin/" target="_blank">Administration</a>
|
|
||||||
</nav>
|
|
||||||
<img class="flex-none mr-10" src="/assets/img/logo-white.svg" />
|
|
||||||
</div>
|
|
||||||
</slot>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
font-family: 'Source Sans 3';
|
font-family: 'Source Sans 3';
|
||||||
@apply bg-gray-700 text-gray-200;
|
@apply bg-gray-700 text-gray-200;
|
||||||
}
|
}
|
||||||
.btn {
|
.btn {
|
||||||
@apply py-2 px-4 rounded;
|
@apply py-2 px-4 rounded;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -3,17 +3,13 @@ export default defineNuxtConfig({
|
||||||
ssr: false,
|
ssr: false,
|
||||||
app: {
|
app: {
|
||||||
baseURL: '/yunohost/sso',
|
baseURL: '/yunohost/sso',
|
||||||
buildAssetsDir: '/assets/'
|
buildAssetsDir: '/assets/',
|
||||||
},
|
},
|
||||||
modules: [
|
modules: ['@nuxtjs/tailwindcss', 'nuxt-icon', '@nuxtjs/google-fonts'],
|
||||||
'@nuxtjs/tailwindcss',
|
|
||||||
'nuxt-icon',
|
|
||||||
"@nuxtjs/google-fonts",
|
|
||||||
],
|
|
||||||
devtools: { enabled: true },
|
devtools: { enabled: true },
|
||||||
googleFonts: {
|
googleFonts: {
|
||||||
families: {
|
families: {
|
||||||
'Source+Sans+3': [500, 900]
|
'Source+Sans+3': [500, 900],
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
|
|
210
pages/index.vue
210
pages/index.vue
|
@ -1,117 +1,105 @@
|
||||||
<template #main>
|
<script setup lang="ts">
|
||||||
<div>
|
const apiEndpoint = useApiEndpoint()
|
||||||
<div class="flex flex-row items-center min-w-full">
|
const isLoggedIn = useIsLoggedIn()
|
||||||
<span class="flex-none pr-5 ">
|
let me = {}
|
||||||
<Icon name="mdi:account-circle" size="5em" class="text-gray-500" />
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div class="grow">
|
const { data, error } = await useFetch(apiEndpoint + '/me', {
|
||||||
<h2 class="text-2xl font-extrabold leading-none tracking-tight">{{ me.username }}</h2>
|
credentials: 'include',
|
||||||
<h3>{{ me.fullname }}</h3>
|
})
|
||||||
<h4 class="opacity-50">{{ me.mail }}</h4>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="flex-none">
|
if (error.value && error.value.statusCode >= 400) {
|
||||||
<button class="btn bg-gray-800" @click.prevent="logout">
|
isLoggedIn.value = false // FIXME : not confident this actually mutates the state ...
|
||||||
<Icon name="mdi:logout" class="text-gray-500" />
|
// FIXME : we probably want different handlings between 401/403, 500, 502, ...
|
||||||
Logout
|
await navigateTo('/login')
|
||||||
</button>
|
} else {
|
||||||
</div>
|
me = data.value
|
||||||
</div>
|
|
||||||
|
|
||||||
<div id="apps" class="p-10">
|
Object.keys(me.apps).forEach((appId) => {
|
||||||
|
const appTileColors = [
|
||||||
<div v-if="Object.keys(me.apps).length == 0">
|
'red',
|
||||||
<em class="text-gray-400">There is no app to list here, either because no web app yet is installed on the server, or because you don't have access to any. Please check with the admins of the server for more infos!</em>
|
'orange',
|
||||||
</div>
|
'yellow',
|
||||||
|
'lime',
|
||||||
<ul class="flex space-x-4">
|
'green',
|
||||||
<!-- NB : because of the usage of dynamic colors, gotta force tailwind to expose those, cf 'safelisting' -->
|
'teal',
|
||||||
<li v-for="app in me.apps" :class="'text-center leading-none p-5 card h-32 w-32 bg-' + app.color + '-500'">
|
'indigo',
|
||||||
<a>
|
'sky',
|
||||||
<div class="text-6xl font-extrabold">{{ app.label.substring(0, 2) }}</div>
|
'purple',
|
||||||
<span class="leading-tight">{{ app.label }}</span>
|
'rose',
|
||||||
</a>
|
]
|
||||||
</li>
|
const randomColorNumber =
|
||||||
|
parseInt(me.apps[appId].label, 36) % appTileColors.length
|
||||||
<!--
|
me.apps[appId].color = appTileColors[randomColorNumber]
|
||||||
<li class="text-center leading-none p-5 card h-32 w-32 bg-rose-500">
|
})
|
||||||
<a class="">
|
}
|
||||||
<div class="text-6xl font-extrabold">My</div>
|
|
||||||
<span class="leading-tight">My Webapp</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="text-center leading-none p-5 card h-32 w-32 bg-indigo-500">
|
|
||||||
<a class="">
|
|
||||||
<div class="text-6xl font-extrabold">Ne</div>
|
|
||||||
<span class="">Nextcloud</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="text-center leading-none p-5 card h-32 w-32 bg-yellow-500">
|
|
||||||
<a class="">
|
|
||||||
<div class="text-6xl font-extrabold">Ra</div>
|
|
||||||
<span class="">Rainloop</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
<li class="text-center leading-none p-5 card h-32 w-32 bg-green-500">
|
|
||||||
<a class="">
|
|
||||||
<div class="text-6xl font-extrabold">Et</div>
|
|
||||||
<span class="">Etherpad MyPads</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
-->
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
const apiEndpoint = useApiEndpoint()
|
|
||||||
let isLoggedIn = useIsLoggedIn()
|
|
||||||
let me = {};
|
|
||||||
|
|
||||||
const { data, error } = await useFetch(
|
|
||||||
apiEndpoint + "/me",
|
|
||||||
{credentials: 'include'}
|
|
||||||
)
|
|
||||||
|
|
||||||
if (error.value && error.value.statusCode >= 400) {
|
|
||||||
|
|
||||||
isLoggedIn = false; // FIXME : not confident this actually mutates the state ...
|
|
||||||
// FIXME : we probably want different handlings between 401/403, 500, 502, ...
|
|
||||||
await navigateTo('/login')
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
me = data.value
|
|
||||||
|
|
||||||
Object.keys(me.apps).map(function(app_id, index) {
|
|
||||||
var app_tile_colors = ['red', 'orange', 'yellow', 'lime', 'green', 'teal', 'indigo', 'sky', 'purple', 'rose']
|
|
||||||
var randomColorNumber = parseInt(me.apps[app_id].label, 36) % app_tile_colors.length;
|
|
||||||
me.apps[app_id].color = app_tile_colors[randomColorNumber]
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(me.apps)
|
|
||||||
|
|
||||||
async function logout() {
|
|
||||||
|
|
||||||
const { data, error } = await useFetch(apiEndpoint + "/logout", {
|
|
||||||
method: 'GET',
|
|
||||||
credentials: 'include'
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error.value && error.value.statusCode != 200) {
|
|
||||||
// FIXME : display an error or something
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// FIXME : meh, turns out the cookie is still valid after successfully calling the route for some reason ... !?
|
|
||||||
|
|
||||||
isLoggedIn = false; // FIXME : not confident this actually mutates the state ...
|
|
||||||
await navigateTo('/login')
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
async function logout() {
|
||||||
|
const { error } = await useFetch(apiEndpoint + '/logout', {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: 'include',
|
||||||
|
})
|
||||||
|
|
||||||
|
if (error.value && error.value.statusCode !== 200) {
|
||||||
|
// FIXME : display an error or something
|
||||||
|
} else {
|
||||||
|
// FIXME : meh, turns out the cookie is still valid after successfully calling the route for some reason ... !?
|
||||||
|
isLoggedIn.value = false // FIXME : not confident this actually mutates the state ...
|
||||||
|
await navigateTo('/login')
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="flex flex-row items-center min-w-full">
|
||||||
|
<span class="flex-none pr-5">
|
||||||
|
<Icon name="mdi:account-circle" size="5em" class="text-gray-500" />
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="grow">
|
||||||
|
<h2 class="text-2xl font-extrabold leading-none tracking-tight">
|
||||||
|
{{ me.username }}
|
||||||
|
</h2>
|
||||||
|
<h3>{{ me.fullname }}</h3>
|
||||||
|
<h4 class="opacity-50">{{ me.mail }}</h4>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex-none">
|
||||||
|
<button class="btn bg-gray-800" @click.prevent="logout">
|
||||||
|
<Icon name="mdi:logout" class="text-gray-500" />
|
||||||
|
Logout
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="apps" class="p-10">
|
||||||
|
<div v-if="Object.keys(me.apps).length == 0">
|
||||||
|
<em class="text-gray-400"
|
||||||
|
>There is no app to list here, either because no web app yet is
|
||||||
|
installed on the server, or because you don't have access to any.
|
||||||
|
Please check with the admins of the server for more infos!</em
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul class="flex space-x-4">
|
||||||
|
<!-- NB : because of the usage of dynamic colors, gotta force tailwind to expose those, cf 'safelisting' -->
|
||||||
|
<li
|
||||||
|
v-for="app in me.apps"
|
||||||
|
:key="app.id"
|
||||||
|
:class="
|
||||||
|
'text-center leading-none p-5 card h-32 w-32 bg-' +
|
||||||
|
app.color +
|
||||||
|
'-500'
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<a>
|
||||||
|
<div class="text-6xl font-extrabold">
|
||||||
|
{{ app.label.substring(0, 2) }}
|
||||||
|
</div>
|
||||||
|
<span class="leading-tight">{{ app.label }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
137
pages/login.vue
137
pages/login.vue
|
@ -1,67 +1,78 @@
|
||||||
<template>
|
<script setup lang="ts">
|
||||||
<div class="w-80 mx-auto pt-20">
|
const apiEndpoint = useApiEndpoint()
|
||||||
<img class="flex-none mx-auto w-1/2 p-5" src="/assets/img/logo-white.svg" />
|
const isLoggedIn = useIsLoggedIn()
|
||||||
<form method="POST" @submit.prevent="login">
|
|
||||||
<div class="flex items-center mb-6">
|
|
||||||
<div class="w-1/6">
|
|
||||||
<label class="pl-3" for="login-username">
|
|
||||||
<Icon name="mdi:account-circle" size="2em" class="text-gray-400" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="">
|
|
||||||
<input class="text-gray-700 rounded py-2 px-4" id="login-username" type="text" placeholder="username" v-model="form.username">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center mb-6">
|
|
||||||
<div class="w-1/6">
|
|
||||||
<label class="pl-3" for="login-password">
|
|
||||||
<Icon name="mdi:lock" size="2em" class="text-gray-400" />
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="">
|
|
||||||
<input class="text-gray-700 rounded py-2 px-4" id="login-password" type="password" placeholder="******************" v-model="form.password">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="flex items-center">
|
|
||||||
<div class="w-full">
|
|
||||||
<button class="w-full bg-indigo-500 hover:bg-indigo-400 font-bold py-2 px-4 rounded" type="submit">
|
|
||||||
Connect
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<!-- <template #footer></template> -->
|
const form = {
|
||||||
|
username: '',
|
||||||
|
password: '',
|
||||||
|
}
|
||||||
|
|
||||||
<script setup>
|
async function login() {
|
||||||
const apiEndpoint = useApiEndpoint();
|
const { error } = await useFetch(apiEndpoint + '/login', {
|
||||||
let isLoggedIn = useIsLoggedIn();
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'X-Requested-With': '',
|
||||||
|
},
|
||||||
|
method: 'POST',
|
||||||
|
credentials: 'include',
|
||||||
|
body: { credentials: form.username + ':' + form.password },
|
||||||
|
})
|
||||||
|
|
||||||
let form = {
|
if (error.value && error.value.statusCode !== 200) {
|
||||||
username: "",
|
// FIXME : display an error or something
|
||||||
password: ""
|
} else {
|
||||||
}
|
isLoggedIn.value = true // FIXME : not confident this actually mutates the state ...
|
||||||
|
await navigateTo('/')
|
||||||
async function login() {
|
}
|
||||||
|
}
|
||||||
const { data, error } = await useFetch(apiEndpoint + "/login", {
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
"X-Requested-With": ""
|
|
||||||
},
|
|
||||||
method: 'POST',
|
|
||||||
credentials: 'include',
|
|
||||||
body: { credentials: form.username + ":" + form.password }
|
|
||||||
});
|
|
||||||
|
|
||||||
if (error.value && error.value.statusCode != 200) {
|
|
||||||
// FIXME : display an error or something
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
isLoggedIn = true; // FIXME : not confident this actually mutates the state ...
|
|
||||||
await navigateTo('/')
|
|
||||||
}
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="w-80 mx-auto pt-20">
|
||||||
|
<img class="flex-none mx-auto w-1/2 p-5" src="/assets/img/logo-white.svg" />
|
||||||
|
<form method="POST" @submit.prevent="login">
|
||||||
|
<div class="flex items-center mb-6">
|
||||||
|
<div class="w-1/6">
|
||||||
|
<label class="pl-3" for="login-username">
|
||||||
|
<Icon name="mdi:account-circle" size="2em" class="text-gray-400" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<input
|
||||||
|
id="login-username"
|
||||||
|
v-model="form.username"
|
||||||
|
class="text-gray-700 rounded py-2 px-4"
|
||||||
|
type="text"
|
||||||
|
placeholder="username"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center mb-6">
|
||||||
|
<div class="w-1/6">
|
||||||
|
<label class="pl-3" for="login-password">
|
||||||
|
<Icon name="mdi:lock" size="2em" class="text-gray-400" />
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="">
|
||||||
|
<input
|
||||||
|
id="login-password"
|
||||||
|
v-model="form.password"
|
||||||
|
class="text-gray-700 rounded py-2 px-4"
|
||||||
|
type="password"
|
||||||
|
placeholder="******************"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="w-full">
|
||||||
|
<button
|
||||||
|
class="w-full bg-indigo-500 hover:bg-indigo-400 font-bold py-2 px-4 rounded"
|
||||||
|
type="submit"
|
||||||
|
>
|
||||||
|
Connect
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
|
@ -5,5 +5,5 @@ module.exports = {
|
||||||
{
|
{
|
||||||
pattern: /bg-.*-500/,
|
pattern: /bg-.*-500/,
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue