Commit 410d034d authored by Yorrd's avatar Yorrd
Browse files

feat: doku

parent b0526aaa
Pipeline #1377 passed with stages
in 10 minutes and 35 seconds
......@@ -6,6 +6,11 @@ import { RenderProps } from 'imports/git_modules/base/reactive-lit-element';
import { BehaviorSubject } from 'rxjs';
import { AdornisDialog } from '@adornis/adornis-components/a-dialog';
/**
* Displays the botbar with Impressum and Datenschutz
* Not currently in use
*/
@element('ccb-botbar')
export class ccbBotbar extends EmotionMixin(ScopingElement) {
public render() {
......
......@@ -10,6 +10,11 @@ import '@adornis/chat/client/a-chat';
import { AdornisChat } from '@adornis/chat/client/a-chat';
import { AdornisInput } from 'imports/git_modules/forms/a-input';
/**
* Chatintegration for the webpage
* Currently not in use!
*/
@element('ccb-chat')
export class CCBChat extends EmotionMixin(ScopingElement) {
public render() {
......
......@@ -10,6 +10,10 @@ import { format } from 'path';
import { AdornisUser } from 'imports/git_modules/users/db';
import { listenDevice, BreakPoint } from 'imports/git_modules/base/window-size';
/**
* Displays answers from the chatbot on the webpage for better clarity and easy-of-use
*/
@element('ccb-content-view')
export class ccbContentView extends EmotionMixin(ScopingElement) {
@rerender public content = AdornisRouter.get('content').pipe(
......@@ -47,7 +51,7 @@ export class ccbContentView extends EmotionMixin(ScopingElement) {
>
<ccb-text>${content.country}</ccb-text>
<ccb-text>${unsafeHTML(content.Antwort)}</ccb-text>
<ccb-text style="${content.Ansprechpartner == null ? 'display: none' : ''}"
<ccb-text style="${content.Ansprechpartner === undefined ? 'display: none' : ''}"
>Falls du weitere Fragen zu diesen Thema hast, kann dir ${content.Ansprechpartner} bestimmt
weiterhelfen.</ccb-text
>
......
import { element, html, ScopingElement, exposeAttribute, rerender } from '@adornis/base';
import { Loader } from '@adornis/adornis-components/loader';
import { spacing } from '@adornis/design/generate-base/tokens';
import { createEmotionComponent, EmotionMixin } from 'imports/git_modules/design';
import { RenderProps } from 'imports/git_modules/base/reactive-lit-element';
import { BehaviorSubject } from 'rxjs';
import { isAbsolute } from 'path';
const backgroundImgStyle = { width: '100%', height: '100%' };
@element('background-img')
class BackgroundImage extends EmotionMixin(ScopingElement) {
@exposeAttribute @rerender public src = new BehaviorSubject('');
public render({ src }: RenderProps<BackgroundImage>) {
return html`
<img src="${src}" class=${this.css(backgroundImgStyle)} />
`;
}
}
@element('ccb-landingpage')
export class ccbLandingpage extends EmotionMixin(ScopingElement) {
public render() {
return html`
<a-box fullsize>
<background-img src="/martin-sanchez-SL1co_Etck8-unsplash.jpg"></background-img>
<a-box
padding="md"
fullsize
vertical
centeraligned
style="position: absolute; top: 10%; left: 748px; z-index: 2; max-width: 424px; max-height: 280px; margin: auto; background-color: white"
><ccb-h1>Corona Legal Chatbot</ccb-h1>
<ccb-text style="padding: ${spacing.lg} 0"
>Unser Chatbot beantwortet deine rechtlichen Fragen rund um Banken-/Kapitalmarktrecht, Gesellschaftsrecht,
Handels-und Vertriebsrecht, Gewerberaummietrecht, Arbeitsrecht und Insolvenzrecht</ccb-text
>
<ccb-button
horizontal
centerjustified
centeraligned
class="${this.css({
cursor: 'pointer',
borderStyle: 'solid',
borderColor: 'green',
borderRadius: '24px',
})}"
href="https://t.me/coronalegalchatbot"
>Los gehts!</ccb-button
>
</a-box></a-box
>
`;
}
}
......@@ -7,8 +7,11 @@ import { BehaviorSubject } from 'rxjs';
import { AdornisUser } from '@adornis/users/db';
import { map } from 'rxjs/operators';
/**
* Displays the topbar with menu, logo and logout.
*/
const smallImgStyle = { width: '50px', height: '50px' };
// createEmotionComponent('a-small-img', smallImgStyle);
@element('a-small-img')
class ASmallImage extends EmotionMixin(ScopingElement) {
......
/**
* Definition of a basic color scheme
*/
export const colors = {
primary: '#c73734ff',
secondary: 'white',
......
......@@ -12,13 +12,15 @@ import { RenderProps } from '@adornis/base/reactive-lit-element';
import './ccb-topbar';
import './ccb-botbar';
import './ccb-datenschutz';
import './ccb-landingpage';
import './ccb-chat';
import './ccb-admin';
import './ccb-contents-admin';
import './ccb-landing-page';
import './ccb-content-view';
/**
* Entry element which uses AdornisLayout to simply use sidebars and topbars.
*/
@element('main-element')
export class MainElement extends Loader(AdornisLayout) {
public refreshOnScrollDown = false;
......@@ -26,25 +28,15 @@ export class MainElement extends Loader(AdornisLayout) {
public topBarHeight = '85px';
public botBarHeight = '32px';
// public render(renderProps: RenderProps<MainElement>) {
// return html`
// ${AdornisRouter.get('page').pipe(
// map(page =>
// page
// ? super.render(renderProps)
// : html`
// <ccb-landing-page></ccb-landing-page>
// `,
// ),
// )}
// `;
// }
public topBar() {
return html`
<ccb-topbar @toggle-sidebar="${() => this.toggleLeftSidebar()}"></ccb-topbar>
`;
}
/**
* Displays the left sidebar and its submenus
*/
public leftSidebar() {
return html`
<div class="${this.css({ height: '100%', background: 'white', paddingTop: '12px' })}">
......@@ -97,6 +89,9 @@ export class MainElement extends Loader(AdornisLayout) {
`;
}
/**
* defines content and decides what to display depending on the current route and whether the user is logged in or not
*/
public content() {
return html`
${Meteor.absoluteUrl().includes('livelinks')
......@@ -130,10 +125,6 @@ export class MainElement extends Loader(AdornisLayout) {
return html`
<ccb-datenschutz></ccb-datenschutz>
`;
case 'landingpage':
return html`
<ccb-landingpage></ccb-landingpage>
`;
case 'content':
return html`
<ccb-content-view></ccb-content-view>
......@@ -165,8 +156,6 @@ export class MainElement extends Loader(AdornisLayout) {
}
private performLogin(username: string) {
console.log('perfom login', username);
AdornisUser.requestLogin(username, 'demoAccountPassword').catch(async () => {
await AdornisUser.registerUser(username, 'demoAccountPassword');
AdornisUser.requestLogin(username, 'demoAccountPassword');
......
import { Entity, Field } from '@adornis/baseql/decorators';
import { AdornisUser } from '@adornis/users/db';
/**
* Typescript definitions for basic users in MongoDB collection `adornisuser`
*/
@Entity()
export class CCBUser extends AdornisUser {
public static _name = 'CCBUser';
......
......@@ -7,6 +7,9 @@ import { AdornisEntity } from '@adornis/baseql/entities/adornis.type';
import { isClient, isServer } from '@adornis/baseql/isServer-isClient';
import { AdornisFile, files } from '@adornis/file-utils/db';
/**
* Database index for fallback answer querying
*/
if (isServer()) files._ensureIndex({ Rechtsgebiet: 'text', Frage: 'text', Antwort: 'text', Ansprechpartner: 'text' });
export enum Country {
......@@ -24,14 +27,11 @@ export class Rating extends AdornisEntity {
public createdAt!: Date;
}
@Entity({
// collection: contents,
// publish: (user: AdornisUser) => {
// console.log('publish for user_id: ', user?._id);
// if (!user) return nothingSelector;
// return { createdBy: user._id };
// },
})
/**
* Typescript typings for database connection using AdornisEngine BaseQL to MongoDB
* Every `Field` corresponds to a property in the MongoDB collection
*/
@Entity({})
export class Content extends AdornisFile {
public static _name = 'Content';
......
import { FilesCollection } from 'meteor/ostrio:files';
import { WebApp } from 'meteor/webapp';
import { stat } from 'fs';
import { join } from 'path';
import { IncomingMessage, ServerResponse } from 'http';
import { NextFunction } from 'connect';
// TODO astronomy
export enum Flag {
TRANSPARENT = 't',
HIGH_DPI = 'd',
// the following will be ignored in request
NO_INTERSECTION = '0',
FROM_DATABASE = '1',
}
export const Files = new FilesCollection({
debug: false,
collectionName: 'Files',
allowClientCode: false, // Disallow remove files from Client
storagePath() {
if (!process.env.DATADIR) throw new Error('Please set the DATADIR env var');
return `${process.env.DATADIR}`;
},
onBeforeUpload(file: any) {
// Allow upload files under 5GB
if (file.size <= 1024 * 1024 * 1024 * 5) {
return true;
}
return 'Please upload file, with size equal or less than 5120MB';
},
responseHeaders(responseCode: string, fileRef: any, versionRef: any) {
const headers: Header = {};
switch (responseCode) {
case '206':
headers.Pragma = 'private';
headers.Trailer = 'expires';
headers['Transfer-Encoding'] = 'chunked';
break;
case '400':
headers['Cache-Control'] = 'no-cache';
break;
case '416':
headers['Content-Range'] = `bytes */${versionRef.size}`;
break;
case '200':
break;
default:
console.error(`unknown return status code: ${responseCode}`);
}
headers.Connection = 'keep-alive';
headers['Content-Type'] = versionRef.type || 'application/octet-stream';
headers['Accept-Ranges'] = 'bytes';
headers['Access-Control-Allow-Origin'] = 'http://localhost:12360'; // <-- Custom header
return headers;
},
interceptDownload(http: { request: IncomingMessage; response: ServerResponse }, fileRef: any, version: string) {
const isImage = ['image/jpeg', 'image/png', 'image/webp'].includes(fileRef['mime-type']);
if (!isImage) return false;
(async () => {
await getTransformer(fileRef.path, version, http.request.headers.accept!.includes('image/webp'), http.response);
})();
return true;
},
});
if (Meteor.isServer) {
Meteor.publish('Files', (ids: string[]) => {
if (!ids || !ids.length) return [];
return Files.find({ _id: { $in: ids } }).cursor;
});
}
const getTransformer = async (fullPath: string, version: string, webp: boolean, response: ServerResponse) => {
const sharp = await import('sharp');
if (!sharp) throw new Error('sharp is not installed');
// make transformer
let transformer = sharp().background({ r: 0, g: 0, b: 0, alpha: 0 });
const flags = (version.split('-')[1] || '').split('');
version = version.split('-')[0];
switch (version) {
case 'original':
// will only apply sharp()
break;
default:
const sizes = version.split('x').map(x => +x * (flags.includes('d') ? 2 : 1));
// || undefined in order to transform zero to null, zero doesnt make sense
const [width, height] = sizes;
if (!isNaN(width) || !isNaN(height)) {
transformer = transformer.resize(width || undefined, height || undefined).embed();
if (flags.includes(Flag.CROP)) transformer = transformer.crop();
}
}
// make webp if we can
const format: 'webp' | 'png' | 'jpeg' = webp ? 'webp' : flags.includes('t') ? 'png' : 'jpeg';
// @ts-ignore this is fine
transformer = transformer[format]();
response.setHeader('Content-Type', 'image/' + format);
const { createReadStream, access, F_OK } = await import('fs');
access(fullPath, F_OK, err => {
if (err) return response.end('file doesnt exist');
createReadStream(fullPath)
.pipe(transformer)
.pipe(response);
});
};
// create entry point /img/version/path for the /public images so that they can be converted automatically
if (Meteor.isServer) {
WebApp.connectHandlers.use('/img/', (req: IncomingMessage, res: ServerResponse, next: NextFunction) => {
const version = req.url!.split('/').slice(0, 2)[1];
const path = req
.url!.split('/')
.slice(2)
.join('/');
const fullPath = join(process.cwd(), '../web.browser/app/', path);
stat(fullPath, async (err, result) => {
if (err || !result) {
// tslint:disable-next-line:no-console
console.warn('no image found here, trying to resume normal operations');
next();
} else {
getTransformer(fullPath, version, (req.headers.accept || '').includes('image/webp'), res);
}
});
});
}
import { registerFileUpload } from '@adornis/file-utils/server';
/**
* Registers a server which accepts POST requests to simply upload files
*/
registerFileUpload({});
// no database definitions but some default actions
// Meteor.startup(() => {
//
// });
import { setTokenTTL } from 'imports/git_modules/users/server';
Meteor.publish('userData', () => Meteor.users.find());
if (!Meteor.users.findOne({ username: 'TestUser' }))
Accounts.createUser({
username: 'TestUser',
password: 'test',
profile: {
name: 'Test Nutzer',
},
});
setTokenTTL(Infinity);
import { Meteor } from 'meteor/meteor';
Meteor.methods({});
// onPageLoad(async sink => {
// // sink.appendToBody(new Main());
// sink.appendToBody(`
// <style>
// #loaderWrapper {
// position: fixed;
// top: 0;
// left: 0;
// bottom: 0;
// right: 0;
// width: 100vw;
// height: 100vh;
// z-index: 1;
// display: flex;
// align-items: center;
// }
// #loaderWrapper.fadeout {
// animation-name: fadeOut;
// animation-duration: 0.5s;
// pointer-events: none;
// opacity: 0;
// }
// #loaderWrapper.fadein {
// animation-name: fadeIn;
// animation-duration: 0.5s;
// opacity: 1;
// }
// #loader {
// width: 10%;
// height: 10%;
// margin: auto;
// }
// #loader #img {
// height: 100%;
// width: auto;
// }
// </style>
// <div id="loaderWrapper" style="background: white">
// <div id="loader">
// <img id="img" src="/loader.svg"></img>
// </div>
// </div>`);
// });
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment