Improved a news items
This commit is contained in:
parent
0c9249a4c8
commit
9bfb0f7a98
@ -1,3 +1,4 @@
|
||||
import { server } from "typescript";
|
||||
import { AuthenticationPage, AuthenticationRules } from "../pages/auth/auth";
|
||||
import { NewsData, NewsFeed } from "../pages/feed/news";
|
||||
import { NewsItem } from "../pages/feed/news-item";
|
||||
@ -69,7 +70,7 @@ export class ControllerAPI {
|
||||
|
||||
const result = await this.request<boolean>('/isAuthenticated', {
|
||||
method: 'GET',
|
||||
credentials: 'include' // Include cookies for authentication
|
||||
credentials: 'include'
|
||||
});
|
||||
return result;
|
||||
}
|
||||
@ -79,33 +80,37 @@ export class ControllerAPI {
|
||||
|
||||
const result = await this.request<NewsData[]>('/news', {
|
||||
method: 'GET',
|
||||
credentials: 'include' // Include cookies for authentication
|
||||
credentials: 'include'
|
||||
});
|
||||
if (!returnPage)
|
||||
return result;
|
||||
if (!newsFeed)
|
||||
newsFeed = new NewsFeed(result.map(x => new NewsItem(
|
||||
x.id,
|
||||
x.title,
|
||||
new Date(x.publishedAt),
|
||||
x.content,
|
||||
x.source,
|
||||
x.comments,
|
||||
x.likes,
|
||||
x.isAdult,
|
||||
x.isLiked
|
||||
)));
|
||||
newsFeed = new NewsFeed(result.map(feed => new NewsItem(feed)));
|
||||
return newsFeed;
|
||||
}
|
||||
|
||||
async getAuthRules(returnPage: boolean = false) : Promise<AuthenticationRules | AuthenticationPage> {
|
||||
const result = await this.request<AuthenticationRules>('/authenticationRules', {
|
||||
method: 'GET',
|
||||
credentials: 'include' // Include cookies for authentication
|
||||
credentials: 'include'
|
||||
});
|
||||
if (!returnPage) return result;
|
||||
if (!authPage)
|
||||
authPage = new AuthenticationPage(result);
|
||||
return authPage;
|
||||
}
|
||||
|
||||
async setLike(post: string | NewsData) : Promise<{ status: boolean, likes: number }> {
|
||||
if (typeof post === "object")
|
||||
post = post.id;
|
||||
|
||||
return await this.request<{ status: boolean, likes: number }>('/setLike', {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
body: JSON.stringify({ post }),
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -6,11 +6,11 @@ import { NewsFeed } from "./pages/feed/news";
|
||||
import { AuthenticationPage } from "./pages/auth/auth";
|
||||
import { DefaultElement } from "./pages/default-element";
|
||||
|
||||
/*declare global {
|
||||
declare global {
|
||||
interface Window {
|
||||
selectedStyle: SupportedStyles;
|
||||
api: ControllerAPI;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
const styleLinker : {
|
||||
selectedStyle: SupportedStyles
|
||||
} = {
|
||||
@ -28,16 +28,16 @@ const currentStyle: () => SupportedStyles = () => styleLinker.selectedStyle;
|
||||
}
|
||||
}
|
||||
|
||||
const api : ControllerAPI = new ControllerAPI();
|
||||
window.api = new ControllerAPI();
|
||||
|
||||
async function authInit() {
|
||||
console.log("User is authenticated");
|
||||
return await api.getNews(true) as NewsFeed;
|
||||
return await window.api.getNews(true) as NewsFeed;
|
||||
}
|
||||
|
||||
async function logInInit () {
|
||||
console.log("User isn't authenticated");
|
||||
return await api.getAuthRules(true) as AuthenticationPage;
|
||||
return await window.api.getAuthRules(true) as AuthenticationPage;
|
||||
}
|
||||
|
||||
async function changeStyleLogic (activeElement: DefaultElement, navbar: DefaultElement) {
|
||||
@ -67,7 +67,7 @@ async function main() {
|
||||
navbar.style = currentStyle;
|
||||
|
||||
let activeElement: DefaultElement;
|
||||
if (await api.isAuthenticated()) {
|
||||
if (await window.api.isAuthenticated()) {
|
||||
activeElement = await authInit();
|
||||
} else {
|
||||
activeElement = await logInInit();
|
||||
|
||||
@ -4,7 +4,7 @@ import { GefestI } from "../modules/Gefest/primitives/i";
|
||||
import { SupportedStyles } from "../styles";
|
||||
|
||||
type FontAwesomeGroup = "fas" | "far" | "fab"; // e.g. "fas fa-home"
|
||||
export type FontAwesomeIcon = `${FontAwesomeGroup} fa-${string}`;
|
||||
export type FontAwesomeIconType = `${FontAwesomeGroup} fa-${string}`;
|
||||
|
||||
export abstract class DefaultElement extends GefestElement {
|
||||
style: SupportedStyles | (() => SupportedStyles) | null = null;
|
||||
@ -26,4 +26,21 @@ export class DefaultRoundedButton extends DefaultElement {
|
||||
this.addClass("rounded-circle");
|
||||
this.addClass("border");
|
||||
}
|
||||
}
|
||||
|
||||
export class FontAwesomeIcon extends DefaultElement {
|
||||
constructor(icon: FontAwesomeIconType) {
|
||||
super("");
|
||||
this.ignoreStyleClasses.add("bg-light");
|
||||
this.ignoreStyleClasses.add("bg-dark");
|
||||
this.addClass(icon);
|
||||
}
|
||||
}
|
||||
|
||||
export class DefaultButton extends DefaultElement {
|
||||
constructor(content: (GefestElement | string)[] | string) {
|
||||
super(content);
|
||||
this.addClass("btn");
|
||||
this.addClass("btn-outline-secondary");
|
||||
}
|
||||
}
|
||||
@ -1,12 +1,13 @@
|
||||
import { DefaultElement } from "../default-element";
|
||||
import { DefaultButton, DefaultElement, FontAwesomeIcon, FontAwesomeIconType } from "../default-element";
|
||||
import { GefestHeader } from "../../modules/Gefest/primitives/header";
|
||||
import { GefestSmall } from "../../modules/Gefest/primitives/small";
|
||||
import { GefestElement } from "../../modules/Gefest/element";
|
||||
import { GefestP } from "../../modules/Gefest/primitives/p";
|
||||
import { NewsSource } from "./news";
|
||||
import { NewsData, NewsSource } from "./news";
|
||||
import { GefestA } from "../../modules/Gefest/primitives/a";
|
||||
import { GefestI } from "../../modules/Gefest/primitives/i";
|
||||
import { GefestImg } from "../../modules/Gefest/primitives/img";
|
||||
import { GefestEngine } from "../../modules/Gefest/engine";
|
||||
|
||||
function dateItemFormater (value: number | string, isMonth = false) {
|
||||
const MONTHS = [
|
||||
@ -63,21 +64,13 @@ class CardBodyBS5 extends DefaultElement {
|
||||
|
||||
export class NewsItem extends DefaultElement {
|
||||
constructor(
|
||||
id: string,
|
||||
title: string,
|
||||
publishDate: Date,
|
||||
content: string,
|
||||
source: NewsSource,
|
||||
commentsCount: number,
|
||||
likesCount: Number,
|
||||
isAdult: boolean,
|
||||
isLiked: boolean,
|
||||
newsData: NewsData
|
||||
) {
|
||||
const header = new GefestHeader(title, 2);
|
||||
const header = new GefestHeader(newsData.title, 2);
|
||||
header.addClass("card-title");
|
||||
const published = new GefestSmall(formatDate(publishDate) + " " + getSourceLnk(source, id));
|
||||
const published = new GefestSmall(formatDate(new Date(newsData.publishedAt)) + " " + getSourceLnk(newsData.source, newsData.id));
|
||||
published.addClass("published-text");
|
||||
const contentParagraph = new GefestP(content);
|
||||
const contentParagraph = new GefestP(newsData.content);
|
||||
contentParagraph.addClass("card-text");
|
||||
|
||||
const splitter = new (class extends DefaultElement {
|
||||
@ -91,12 +84,115 @@ export class NewsItem extends DefaultElement {
|
||||
protected htmlTag: string = "hr";
|
||||
});
|
||||
|
||||
const actions = new (class extends DefaultElement {
|
||||
constructor() {
|
||||
const commentsCounter = new (class extends GefestElement {
|
||||
comments: number = 0;
|
||||
constructor() {
|
||||
super([]);
|
||||
}
|
||||
|
||||
protected wrapHTML(): string {
|
||||
return ` ${this.comments}`;
|
||||
}
|
||||
});
|
||||
commentsCounter.comments = newsData.comments;
|
||||
|
||||
const comments = new DefaultButton([
|
||||
new FontAwesomeIcon("fas fa-comment"),
|
||||
commentsCounter
|
||||
]);
|
||||
|
||||
const likeBtn = new (class extends DefaultButton {
|
||||
private status: boolean;
|
||||
private likes: number;
|
||||
|
||||
constructor() {
|
||||
const likedIco = new FontAwesomeIcon("fas fa-heart");
|
||||
const unlikedIco = new FontAwesomeIcon("far fa-heart");
|
||||
|
||||
const likesCounter = new (class extends GefestElement {
|
||||
likes: number = 0;
|
||||
constructor() {
|
||||
super([]);
|
||||
}
|
||||
|
||||
protected wrapHTML(): string {
|
||||
return ` ${this.likes}`;
|
||||
}
|
||||
});
|
||||
super([
|
||||
likedIco, unlikedIco,
|
||||
likesCounter
|
||||
]);
|
||||
this.likes = newsData.likes;
|
||||
this.status = newsData.isLiked;
|
||||
likesCounter.likes = newsData.likes;
|
||||
|
||||
const setStatus = () => {
|
||||
likedIco.isHidden = !this.status;
|
||||
unlikedIco.isHidden = this.status;
|
||||
this.update();
|
||||
};
|
||||
setStatus();
|
||||
|
||||
this.onClick = async () => {
|
||||
likesCounter.likes = this.status ? --this.likes : ++this.likes;
|
||||
|
||||
// TODO: Dirty code, fix it
|
||||
this.status = !this.status;
|
||||
setStatus();
|
||||
const result = await window.api.setLike(newsData);
|
||||
this.status = result.status;
|
||||
likesCounter.likes = result.likes;
|
||||
this.likes = result.likes;
|
||||
setStatus();
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
super([
|
||||
comments, likeBtn
|
||||
]);
|
||||
this.addClass("btn-group");
|
||||
}
|
||||
});
|
||||
const views = new (class extends DefaultElement {
|
||||
constructor() {
|
||||
const lookedShow = new (class extends GefestElement {
|
||||
views: number = 0;
|
||||
constructor() {
|
||||
super([]);
|
||||
}
|
||||
protected wrapHTML(content: string): string {
|
||||
return `${this.views} `;
|
||||
}
|
||||
});
|
||||
lookedShow.views = newsData.looked;
|
||||
|
||||
super([
|
||||
lookedShow,
|
||||
new FontAwesomeIcon("fas fa-eye"),
|
||||
]);
|
||||
}
|
||||
});
|
||||
|
||||
super([
|
||||
new CardBodyBS5([
|
||||
header,
|
||||
published,
|
||||
contentParagraph,
|
||||
splitter,
|
||||
new (class extends DefaultElement {
|
||||
constructor() {
|
||||
super([actions, views]);
|
||||
[
|
||||
"d-flex",
|
||||
"justify-content-between",
|
||||
"align-items-center"
|
||||
].forEach(c => this.addClass(c));
|
||||
}
|
||||
}),
|
||||
])
|
||||
]);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { NewsItem } from "./news-item";
|
||||
import { DefaultElement, FontAwesomeIcon } from "../default-element";
|
||||
import { DefaultElement, FontAwesomeIcon, FontAwesomeIconType } from "../default-element";
|
||||
import { GefestHeader } from "../../modules/Gefest/primitives/header";
|
||||
import { UserType } from "../../api/user-info";
|
||||
import { GefestElement } from "../../modules/Gefest/element";
|
||||
@ -11,15 +11,8 @@ export function isNewsUI (element : GefestElement): boolean {
|
||||
element instanceof NewsUserInterfaceCard;
|
||||
}
|
||||
class NewsUserInterfaceBtn extends DefaultElement {
|
||||
constructor(icon: FontAwesomeIcon) {
|
||||
const fontawesomeIcon = new (class extends GefestI {
|
||||
constructor () {
|
||||
super("");
|
||||
this.ignoreStyleClasses.add("bg-light");
|
||||
this.ignoreStyleClasses.add("bg-dark");
|
||||
}
|
||||
});
|
||||
fontawesomeIcon.addClass(icon);
|
||||
constructor(icon: FontAwesomeIconType) {
|
||||
const fontawesomeIcon = new FontAwesomeIcon(icon);
|
||||
|
||||
super([fontawesomeIcon]);
|
||||
this.ignoreStyleClasses.add("bg-light");
|
||||
@ -143,6 +136,7 @@ export interface NewsData {
|
||||
publishedAt : string;
|
||||
comments: number;
|
||||
likes: number;
|
||||
looked: number;
|
||||
isAdult: boolean;
|
||||
isLiked: boolean;
|
||||
}
|
||||
@ -1,12 +1,11 @@
|
||||
import { GefestA } from "../modules/Gefest/primitives/a";
|
||||
import { GefestI } from "../modules/Gefest/primitives/i";
|
||||
import { DefaultElement, FontAwesomeIcon } from "./default-element";
|
||||
import { DefaultElement, FontAwesomeIcon, FontAwesomeIconType } from "./default-element";
|
||||
|
||||
|
||||
class NavbarButton extends DefaultElement {
|
||||
constructor(icon: FontAwesomeIcon) {
|
||||
const iconElement = new GefestI("");
|
||||
iconElement.addClass(icon);
|
||||
constructor(icon: FontAwesomeIconType) {
|
||||
const iconElement = new FontAwesomeIcon(icon);
|
||||
const elementA = new GefestA([
|
||||
iconElement
|
||||
]);
|
||||
|
||||
@ -18,8 +18,20 @@ router.get('/isAuthenticated', (req, res) => {
|
||||
|
||||
router.get('/news', authRequired, (req, res) => {
|
||||
const newsList : NewsItem[] = getTestNews();
|
||||
const response = new ApiResponse<NewsItem[]>(newsList);
|
||||
const response = new ApiResponse(newsList);
|
||||
return res.json(response.getAnswer());
|
||||
});
|
||||
|
||||
router.post('/setLike', authRequired, (req, res) => {
|
||||
if (req.body?.post || typeof req.body.post !== "string") {
|
||||
// TODO: Some actions with API
|
||||
const testResponse = new ApiResponse({ status: true, likes: 1 });
|
||||
return res.json(testResponse.getAnswer());
|
||||
}
|
||||
return res.status(400).json((new ApiResponse({
|
||||
code: "MISSING_REQUIRED",
|
||||
message: "Missed required param: post(string) at JSON body",
|
||||
})).getAnswer());
|
||||
});
|
||||
|
||||
export default router;
|
||||
@ -32,6 +32,7 @@ export interface NewsItem {
|
||||
content : string;
|
||||
source: NewsSource;
|
||||
publishedAt : Date;
|
||||
looked: number;
|
||||
comments: number;
|
||||
likes: number;
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 1,
|
||||
isAdult: false,
|
||||
@ -27,6 +28,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -41,6 +43,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -55,6 +58,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -69,6 +73,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -83,6 +88,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -97,6 +103,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -111,6 +118,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -125,6 +133,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -139,6 +148,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -153,6 +163,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -167,6 +178,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
@ -181,6 +193,7 @@ export function getTestNews (): NewsItem[] {
|
||||
name: "Test Destination",
|
||||
type: "system",
|
||||
},
|
||||
looked: 1,
|
||||
comments: 0,
|
||||
likes: 0,
|
||||
isAdult: false,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user