Skip to content
Commits on Source (17)
{
"name": "laboite-blog-front",
"description": "laboite blog service frontend",
"version": "1.7.0",
"version": "1.8.0-testing.1",
"license": "EUPL-1.2",
"author": "EOLE/PCLL <team@eole.education> - DINUM",
"type": "module",
"scripts": {
"start-dev": "npm-run-all --parallel server css-watch dev",
"init-dev": "yarn && cd ../laboite-blog-api && yarn",
"dev": "dotenv_config_path=.env NODE_OPTIONS='-r dotenv/config' svelte-kit dev --port 4000",
"build": "yarn css-build && svelte-kit build",
"dev": "dotenv_config_path=.env NODE_OPTIONS='-r dotenv/config' vite --port 4000",
"build": "yarn css-build && vite build",
"server": "cd ../laboite-blog-api && dotenv_config_path=.env NODE_OPTIONS='-r dotenv/config' yarn start",
"export": "svelte-kit build",
"export": "vite build",
"start": "node build",
"validate": "svelte-check",
"css-build": "node-sass --omit-source-map-url src/utils/theme/index.scss src/utils/theme/index.css",
......@@ -30,7 +30,8 @@
"prettier": "^2.7.1",
"prettier-plugin-svelte": "^2.7.0",
"sanitize-html": "^2.10.0",
"svelte-i18n": "^3.4.0"
"svelte-i18n": "^3.4.0",
"vite": "^4.3.9"
},
"devDependencies": {
"@babel/core": "^7.17.10",
......@@ -52,5 +53,8 @@
"svelte": "^3.48.0",
"svelte-check": "^2.7.0",
"svelte-preprocess": "^4.10.6"
},
"resolutions": {
"semver": "^7.5.2"
}
}
......@@ -10,13 +10,13 @@
<meta name="licence" content="EUPL-1.2" />
<script defer src="/fonts/js/all.min.js"></script>
%svelte.head%
%sveltekit.head%
<link rel="stylesheet" type="text/css" href="/global.css" />
<link rel="manifest" href="manifest.json" crossorigin="use-credentials" />
<link rel="icon" type="image/png" href="/puce_eole.png" />
</head>
<body>
<div id="app">%svelte.body%</div>
<div id="app">%sveltekit.body%</div>
</body>
</html>
......@@ -3,7 +3,7 @@
import {onMount} from 'svelte';
import fetcher from 'isomorphic-fetch';
import {_} from 'svelte-i18n';
import {session} from '$app/stores';
import {page} from '$app/stores';
export let academy = {};
let total;
......@@ -13,7 +13,9 @@
const where = {structure: academy._id};
const response = await fetcher(
`${$session.env.API_HOST}/articles/count?where=${JSON.stringify(where)}`,
`${$page.data.env.API_HOST}/articles/count?where=${JSON.stringify(
where,
)}`,
);
const {count} = await response.json();
......
......@@ -9,7 +9,7 @@
import codeSyntaxHighlight from '@toast-ui/editor-plugin-code-syntax-highlight';
import tableMergedCell from '@toast-ui/editor-plugin-table-merged-cell';
import {onMount} from 'svelte';
import {session} from '$app/stores';
import {page} from '$app/stores';
import {modifiedColorSyntax} from '../../utils/functions/modifiedPlugin';
......@@ -24,7 +24,7 @@
};
const umlOptions = {
rendererURL:
$session.env.UML_SERVER || 'https://www.plantuml.com/plantuml/png/',
$page.data.env.UML_SERVER || 'https://www.plantuml.com/plantuml/png/',
};
umlPlugin = [uml, umlOptions];
new Viewer({
......
<script>
import fetcher from "isomorphic-fetch";
import { session } from "$app/stores";
import fetcher from 'isomorphic-fetch';
import {page} from '$app/stores';
import { _ } from "svelte-i18n";
import BigLink from "../common/BigLink.svelte";
import Avatar from "./Avatar.svelte";
import {_} from 'svelte-i18n';
import BigLink from '../common/BigLink.svelte';
import Avatar from './Avatar.svelte';
export let author;
let academy = {};
......@@ -13,7 +13,7 @@
const fetchAcademy = async currentAuthor => {
if (currentAuthor?.structure) {
const responseAcademy = await fetcher(
`${$session.env.API_HOST}/structures/${currentAuthor.structure}`
`${$page.data.env.API_HOST}/structures/${currentAuthor.structure}`,
);
academy = await responseAcademy.json();
}
......@@ -25,28 +25,28 @@
<div class="media">
<div class="media-left">
<Avatar
firstName={author?.firstName || "?"}
avatar={author?.avatar || ""}
firstName={author?.firstName || '?'}
avatar={author?.avatar || ''}
/>
</div>
<div class="media-content">
<p class="title is-4">
{author?.firstName || $_("components.AuthorIdCard.unknownFirstname")}
{author?.lastName || $_("components.AuthorIdCard.unknownLastname")}
{author?.firstName || $_('components.AuthorIdCard.unknownFirstname')}
{author?.lastName || $_('components.AuthorIdCard.unknownLastname')}
</p>
<p class="subtitle is-6">{academy.name || ""}</p>
<p class="subtitle is-6">{academy.name || ''}</p>
</div>
</div>
</div>
{#if author}
<div class="content">
<p class="title is-6">
{$_("components.AuthorIdCard.articles")}:
{$_('components.AuthorIdCard.articles')}:
{author.articlesCount}
</p>
<BigLink
link="/authors/{author._id}"
text={$_("components.AuthorIdCard.all_articles")}
text={$_('components.AuthorIdCard.all_articles')}
/>
</div>
{/if}
......
......@@ -5,20 +5,20 @@
import BigLink from '../common/BigLink.svelte';
import FavoritesButton from '../common/FavoritesButton.svelte';
import Avatar from './Avatar.svelte';
import {session} from '$app/stores';
import {page} from '$app/stores';
export let author;
let academy = {};
onMount(async () => {
const responseAcademy = await fetcher(
`${$session.env.API_HOST}/structures/${author.structure}`,
`${$page.data.env.API_HOST}/structures/${author.structure}`,
);
academy = await responseAcademy.json();
});
</script>
<div class="column is-full ">
<div class="column is-full">
<div class="media box">
<figure class="media-left">
<Avatar firstName={author.firstName} avatar={author.avatar} />
......
......@@ -5,7 +5,7 @@
import Avatar from '../authors/Avatar.svelte';
import BigLink from '../common/BigLink.svelte';
import {onMount} from 'svelte';
import {session} from '$app/stores';
import {page} from '$app/stores';
import FavoritesButton from '../common/FavoritesButton.svelte';
export let group;
export let isFavorite;
......@@ -14,7 +14,7 @@
onMount(async () => {
const results = await fetchData({
host: $session.env.API_HOST,
host: $page.data.env.API_HOST,
order: 'createdAt DESC',
fields: {content: false},
count: true,
......
......@@ -2,7 +2,7 @@
import {onMount} from 'svelte';
import fetcher from 'isomorphic-fetch';
import {_} from 'svelte-i18n';
import {session} from '$app/stores';
import {page} from '$app/stores';
import {favoritesAcademy} from '../../utils/functions/stores';
import SingleAcademy from '../academies/SingleAcademy.svelte';
......@@ -11,7 +11,7 @@
let academy = {};
onMount(async () => {
const responseAcademy = await fetcher(
`${$session.env.API_HOST}/structures/${$favoritesAcademy}`,
`${$page.data.env.API_HOST}/structures/${$favoritesAcademy}`,
);
academy = await responseAcademy.json();
});
......
......@@ -6,13 +6,13 @@
import SingleAcademy from '../academies/SingleAcademy.svelte';
import Divider from '../common/Divider.svelte';
import {fetchData} from '../../utils/api/methods';
import {session} from '$app/stores';
import {page} from '$app/stores';
let academies = [];
onMount(async () => {
const where = {_id: {inq: $lastAcademies}};
const {items} = await fetchData({
host: $session.env.API_HOST,
host: $page.data.env.API_HOST,
limit: 4,
order: 'name DESC',
apiurl: 'structures',
......
......@@ -6,14 +6,14 @@
import {onMount} from 'svelte';
import {lastRead} from '../../utils/functions/stores';
import Loader from '../common/Loader.svelte';
import {session} from '$app/stores';
import {page} from '$app/stores';
let articles = [];
let loading = true;
onMount(async () => {
const {items} = await fetchData({
host: $session.env.API_HOST,
host: $page.data.env.API_HOST,
limit: 4,
order: 'createdAt DESC',
fields: {content: false},
......
<script>
import {_} from 'svelte-i18n';
import {onMount} from 'svelte';
import {getStores, session} from '$app/stores';
import fetcher from "isomorphic-fetch";
import {page} from '$app/stores';
import fetcher from 'isomorphic-fetch';
import Loader from '../common/Loader.svelte';
const {page} = getStores();
let settings = {
maintenance: null,
textMaintenance: '',
legal: { external: false, link: '', content: '' },
accessibility: { external: false, link: '', content: '' },
gcu: { external: false, link: '', content: '' },
personalData: { external: false, link: '', content: '' },
};
maintenance: null,
textMaintenance: '',
legal: {external: false, link: '', content: ''},
accessibility: {external: false, link: '', content: ''},
gcu: {external: false, link: '', content: ''},
personalData: {external: false, link: '', content: ''},
};
let loading = true;
onMount(async () => {
const appsettings = await fetcher(`${$session.env.API_HOST}/appsettings`)
settings = await appsettings.json()
const appsettings = await fetcher(`${$page.data.env.API_HOST}/appsettings`);
settings = await appsettings.json();
loading = false;
});
......@@ -28,32 +26,31 @@
text: $_('links.legal'),
path: settings.legal.external
? settings.legal.link
: `${$session.env.LABOITE_HOST}/legal/legalnotice`,
: `${$page.data.env.LABOITE_HOST}/legal/legalnotice`,
},
{
text: $_('links.accessibility'),
path: settings.accessibility.external
? settings.accessibility.link
: `${$session.env.LABOITE_HOST}/legal/accessibility`,
: `${$page.data.env.LABOITE_HOST}/legal/accessibility`,
},
{
text: $_('links.gcu'),
path: settings.gcu.external
? settings.gcu.link
: `${$session.env.LABOITE_HOST}/legal/conditions`,
: `${$page.data.env.LABOITE_HOST}/legal/conditions`,
},
{
text: $_('links.personalData'),
path: settings.personalData.external
? settings.personalData.link
: `${$session.env.LABOITE_HOST}/legal/personal-data`,
: `${$page.data.env.LABOITE_HOST}/legal/personal-data`,
},
];
</script>
<nav class="navbar is-primary" aria-label="main navigation">
<div class="navbar-menu is-active">
{#if loading}
<Loader message={$_('loading')} />
{/if}
......@@ -64,7 +61,7 @@
class:is-active={$page.url.pathname === path}
class="navbar-item"
target="_blank"
href="{path}"
href={path}
>
{$_(text)}
</a>
......
import {waitLocale} from 'svelte-i18n';
export async function load(args) {
waitLocale();
return args.data;
}
/** @type {import('./$types').LayoutServerLoad} */
export async function load() {
// previously stored in session (deprecated)
// https://github.com/sveltejs/kit/discussions/5883
const {API_HOST, LABOITE_HOST, UML_SERVER} = process.env;
return {
env: {API_HOST, LABOITE_HOST, UML_SERVER},
};
}
<script context="module">
import {waitLocale, _, locale} from 'svelte-i18n';
import '../utils/theme/index.css';
export async function load(args) {
waitLocale();
return args;
}
</script>
<script defer src="./fonts/js/all.min.js">
import '../utils/theme/index.css';
import {_, locale} from 'svelte-i18n';
import {getMaintenance} from '../utils/api/methods';
import {getStores} from '$app/stores';
import '../utils/locales/index';
import Nav from '../components/navigation/Nav.svelte';
import Footer from '../components/navigation/Footer.svelte';
import {trackLocation} from '../utils/functions/locationTracker';
import Loader from '../components/common/Loader.svelte';
import {onMount} from 'svelte';
import {onMount, beforeUpdate} from 'svelte';
import {language} from '../utils/functions/stores';
export let data;
let maintenance = {maintenance: false, textMaintenance: ''};
onMount(() => {
if (!$language) {
language.set($locale.split('-')[0]);
......@@ -26,6 +22,10 @@
}
});
beforeUpdate(async () => {
maintenance = await getMaintenance(data.env.API_HOST);
});
trackLocation();
const {navigating} = getStores();
......@@ -38,7 +38,14 @@
{/if}
<main class="container">
<slot />
{#if !!maintenance.maintenance}
<div class="maintenance">
<h1>{$_('maintenance')}</h1>
<p>{maintenance.textMaintenance}</p>
</div>
{:else}
<slot />
{/if}
</main>
<Footer />
......@@ -52,7 +59,14 @@
display: none;
}
:global(h1, h2, h3, h4, h5, h6, .title) {
:global(.maintenance) {
text-align: center;
border: rgba(255, 0, 0, 0.7) solid 5px;
padding: 3vh;
border-radius: 15px;
}
:global(h1, h2, h3, h4, h5, h6, .title, .maintenance) {
font-family: 'WorkSansBold' !important;
}
......
import {fetchData} from '../utils/api/methods';
export async function load({parent}) {
const {env} = await parent();
const {items: articles, response} = await fetchData({
host: env.API_HOST,
limit: 4,
order: 'createdAt DESC',
fields: {content: false},
count: false,
apiurl: 'articles',
where: {draft: {neq: true}},
include: [
{
relation: 'user',
scope: {
fields: {
username: false,
structure: false,
articlesCount: false,
},
},
},
],
});
return {
status: response.status,
articles,
};
}
<script context="module">
import {fetchData} from '../utils/api/methods';
export async function load({session}) {
const {items: articles, response} = await fetchData({
host: session.env.API_HOST,
limit: 4,
order: 'createdAt DESC',
fields: {content: false},
count: false,
apiurl: 'articles',
where: {draft: {neq: true}},
include: [
{
relation: 'user',
scope: {
fields: {
username: false,
structure: false,
articlesCount: false,
},
},
},
],
});
return {
status: response.status,
props: {
articles,
},
};
}
</script>
<!-- svelte-ignore missing-declaration -->
<script>
import {_} from 'svelte-i18n';
import PageTransition from '../components/common/PageTransition.svelte';
......@@ -46,19 +12,18 @@
lastAcademies,
lastRead,
} from '../utils/functions/stores';
export let articles;
export let data;
</script>
<svelte:head>
<title>{$_('title')}</title>
<title>{$_('title')} - {__APP_VERSION__}</title>
</svelte:head>
<PageTransition>
{#if $favoritesAcademy}
<FavoriteAcademy />
{/if}
<LastPublished {articles} />
<LastPublished articles={data.articles} />
{#if $lastRead.length}
<LastRead />
{/if}
......
import {fetchData} from '../../utils/api/methods';
export async function load({parent}) {
const fields = {};
const order = 'name ASC';
const apiurl = 'structures';
const {env} = await parent();
const {items} = await fetchData({
host: env.API_HOST,
limit: 100,
order,
fields,
apiurl,
});
return {
structures: items,
};
}
<script context="module">
import {fetchData} from '../../utils/api/methods';
export async function load({session}) {
const fields = {};
const order = 'name ASC';
const apiurl = 'structures';
const {items} = await fetchData({
host: session.env.API_HOST,
limit: 100,
order,
fields,
apiurl,
});
return {
props: {
structures: items,
},
};
}
</script>
<script>
import {_} from 'svelte-i18n';
import Divider from '../../components/common/Divider.svelte';
import SingleAcademy from '../../components/academies/SingleAcademy.svelte';
import PageTransition from '../../components/common/PageTransition.svelte';
export let structures = [];
export let data;
</script>
<svelte:head>
......@@ -43,7 +19,7 @@
</div>
<Divider />
<div class="columns is-multiline">
{#each structures as academy}
{#each data.structures as academy}
<div class="column is-half is-full-mobile">
<SingleAcademy {academy} />
</div>
......
import fetcher from 'isomorphic-fetch';
import {fetchData} from '../../../utils/api/methods';
export async function load({params, parent}) {
const {env} = await parent();
const responseAcademy = await fetcher(
`${env.API_HOST}/structures/${params._id}`,
);
const academy = await responseAcademy.json();
const {items: authors, response} = await fetchData({
host: env.API_HOST,
limit: 6,
order: 'articlesCount DESC',
fields: {},
count: false,
apiurl: 'authors',
where: {articlesCount: {gt: 0}, structure: academy._id},
});
const {items: articles} = await fetchData({
host: env.API_HOST,
limit: 4,
order: 'createdAt DESC',
fields: {content: false},
count: false,
apiurl: 'articles',
where: {structure: academy._id, draft: {neq: true}},
include: [
{
relation: 'user',
scope: {
fields: {
username: false,
structure: false,
articlesCount: false,
},
},
},
],
});
return {
status: response.status,
authors,
articles,
academy,
params,
};
}