From b24e460ec76ccd5b4e1ab94dae71a5629e621265 Mon Sep 17 00:00:00 2001 From: Dmitriy Pleshevskiy Date: Wed, 22 Jun 2022 00:35:55 +0300 Subject: [PATCH] add works from github --- public/styles/main.css | 23 ++++- public/styles/main.css.map | 2 +- styles/atoms/typography.scss | 27 +++++ styles/base/reset.scss | 11 +- translates/eng.ts | 2 +- translates/rus.ts | 2 +- views/pages/works.ts | 192 ++++++++++++++++++++++++++++++++--- views/uikit/link.ts | 23 +++-- 8 files changed, 251 insertions(+), 31 deletions(-) diff --git a/public/styles/main.css b/public/styles/main.css index 40fc96a..f14a31f 100644 --- a/public/styles/main.css +++ b/public/styles/main.css @@ -9,6 +9,7 @@ --default-color-error: #b00008; --default-color-success: #417505; --color-brand-blue: #1966df; + --color-brand-faded-blue: #f5f5ff; --color-graphite: #212121; --color-warm-gray: #757575; --color-pale: #b6b6b6; @@ -326,7 +327,7 @@ svg:not(:root) { margin-right: auto; } -.pad-0x5, .main-menu > a { +.pad-0x5, .main-menu > a, .responsive-typography th, .responsive-typography td { padding: 0.5rem; } @@ -460,6 +461,26 @@ svg:not(:root) { .responsive-typography li + li { margin-top: 0.5rem; } +.responsive-typography table { + table-layout: fixed; + border-collapse: collapse; + line-height: 1.5; +} +.responsive-typography thead { + background-color: var(--color-brand-faded-blue); +} +.responsive-typography tbody tr { + border-top: solid 1px var(--color-pale); +} +.responsive-typography th, .responsive-typography td { + text-align: initial; +} +.responsive-typography th:not(:first-of-type), .responsive-typography td:not(:first-of-type) { + border-left: solid 1px var(--color-pale); +} +.responsive-typography td:nth-child(n+3) { + color: var(--color-warm-gray); +} .anim, .main-menu > a, a, .anim::before, .main-menu > a::before, a::before, .anim::after, .main-menu > a::after, a::after { transition: all 0.2s ease-in-out; diff --git a/public/styles/main.css.map b/public/styles/main.css.map index d18ed41..0a88c23 100644 --- a/public/styles/main.css.map +++ b/public/styles/main.css.map @@ -1 +1 @@ -{"version":3,"sourceRoot":"","sources":["../../styles/base/reset.scss","../../styles/base/layout.scss","../../styles/atoms/sizes.scss","../../styles/atoms/white-spaces.scss","../../styles/mixins/white-spaces.scss","../../styles/atoms/flex.scss","../../styles/mixins/flex.scss","../../styles/atoms/typography.scss","../../styles/atoms/misc.scss","../../styles/uikit/main-menu.scss","../../styles/uikit/dropdown.scss"],"names":[],"mappings":";AAEA;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;EAGE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAKF;EACE;EACA;;AAEA;EAEE;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;AAAA;AAAA;EAIE;EACA;;;AAGF;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;AAAA;EAGE;EACA;;;AAGF;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;EAEE;;;AAGF;EACE;EACA;;;AAGF;AAAA;EAEE;;;AAGF;EACE;EACA;;;AAGF;AAAA;AAAA;AAAA;EAIE;EACA;;;AAGF;EACE;;;AAGF;AAAA;EAEE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AAKA;EACE;;;AAIJ;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;ACxSF;EAEE;;;ACTF;EAAe;;;AACf;EAAe;;;AACf;EAAe;;;AACf;EAAU;;;AAEV;EAAa;;;AACb;EAAa;;;AACb;EAAa;;;ACPb;ECQgB;EAAmB;;;ADNnC;ECQmB;;;ADPnB;ECWqB;EAEA;;;ADZrB;ECSqB;EAEA;;;AAInB;EAfmB;;;AAmBnB;EAlBmB;;;AAkBnB;EAlBmB;;;ACLrB;ECCE;EACA;EACA;EAWA;EACA;EACA;EACA;EA4CA;EACA;EACA;EAoCA;EACA;EACA;;;ADpGF;ECAE;EACA;EACA;EAWA;EACA;EACA;EACA;EAmEA;EACA;EACA;EAaA;EACA;EACA;;;ADnGF;ECDE;EACA;EACA;EAmBA;EACA;EACA;EACA;EAoCA;EACA;EACA;EAoCA;EACA;EACA;;;ADlGF;ECFE;EACA;EACA;EAmBA;EACA;EACA;EACA;EAoCA;EACA;EACA;EAsDA;EACA;EACA;;;ADlHF;ECuCE,kBDvCsB;ECwCtB,UDxCsB;ECyCtB,MDzCsB;;;AEHtB;EACE;EACA;;AAGF;EACE;EACA;;AAMA;EAGE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAIJ;AAAA;AAAA;EAGE;;AAGF;EACE;;;ACnDJ;EACE;;;ACGA;EAIE;EACA;EACA;EACA;;AAEA;EAEE;EACA;;;ACfN;AAAA;AAAA;AAAA;AAAA;AAMA;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAMJ;EACE;;AAGF;EACE","file":"main.css"} \ No newline at end of file +{"version":3,"sourceRoot":"","sources":["../../styles/base/reset.scss","../../styles/base/layout.scss","../../styles/atoms/sizes.scss","../../styles/atoms/white-spaces.scss","../../styles/mixins/white-spaces.scss","../../styles/atoms/flex.scss","../../styles/mixins/flex.scss","../../styles/atoms/typography.scss","../../styles/atoms/misc.scss","../../styles/uikit/main-menu.scss","../../styles/uikit/dropdown.scss"],"names":[],"mappings":";AAEA;EAEE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EAEA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;EAEA;EACA;EACA;EACA;EACA;EACA;;;AAGF;AAAA;AAAA;EAGE;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;;;AAGF;EACE;;;AAKF;EACE;EACA;;AAEA;EAEE;;;AAIJ;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;AAAA;AAAA;AAAA;EAIE;EACA;;;AAGF;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;AAAA;EAGE;EACA;;;AAGF;AAAA;AAAA;AAAA;EAIE;;;AAGF;AAAA;EAEE;;;AAGF;EACE;EACA;;;AAGF;AAAA;EAEE;;;AAGF;EACE;EACA;;;AAGF;AAAA;AAAA;AAAA;EAIE;EACA;;;AAGF;EACE;;;AAGF;AAAA;EAEE;EACA;;;AAGF;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AAKA;EACE;;;AAIJ;EACE;EACA;EACA;;;AAGF;EACE;EACA;EACA;;;AAGF;EACE;;;AAGF;EACE;;;AAGF;EACE;EACA;;;ACzSF;EAEE;;;ACTF;EAAe;;;AACf;EAAe;;;AACf;EAAe;;;AACf;EAAU;;;AAEV;EAAa;;;AACb;EAAa;;;AACb;EAAa;;;ACPb;ECQgB;EAAmB;;;ADNnC;ECQmB;;;ADPnB;ECWqB;EAEA;;;ADZrB;ECSqB;EAEA;;;AAInB;EAfmB;;;AAmBnB;EAlBmB;;;AAkBnB;EAlBmB;;;ACLrB;ECCE;EACA;EACA;EAWA;EACA;EACA;EACA;EA4CA;EACA;EACA;EAoCA;EACA;EACA;;;ADpGF;ECAE;EACA;EACA;EAWA;EACA;EACA;EACA;EAmEA;EACA;EACA;EAaA;EACA;EACA;;;ADnGF;ECDE;EACA;EACA;EAmBA;EACA;EACA;EACA;EAoCA;EACA;EACA;EAoCA;EACA;EACA;;;ADlGF;ECFE;EACA;EACA;EAmBA;EACA;EACA;EACA;EAoCA;EACA;EACA;EAsDA;EACA;EACA;;;ADlHF;ECuCE,kBDvCsB;ECwCtB,UDxCsB;ECyCtB,MDzCsB;;;AEHtB;EACE;EACA;;AAGF;EACE;EACA;;AAMA;EAGE;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;;AAGF;EACE;;AAIJ;AAAA;AAAA;EAGE;;AAGF;EACE;;AAGF;EACE;EACA;EACA;;AAGF;EACE;;AAGF;EACE;;AAGF;EAEE;;AAEA;EACE;;AAIJ;EACE;;;AC9EJ;EACE;;;ACGA;EAIE;EACA;EACA;EACA;;AAEA;EAEE;EACA;;;ACfN;AAAA;AAAA;AAAA;AAAA;AAMA;EACE;EACA;;AAEA;EACE;EACA;;AAGF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAGF;EACE;EACA;EACA;EACA;EACA;;AAIJ;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;;AAEA;EACE;;AAMJ;EACE;;AAGF;EACE","file":"main.css"} \ No newline at end of file diff --git a/styles/atoms/typography.scss b/styles/atoms/typography.scss index 7f09240..1e8d797 100644 --- a/styles/atoms/typography.scss +++ b/styles/atoms/typography.scss @@ -52,6 +52,33 @@ margin-top: 0.5rem; } + table { + table-layout: fixed; + border-collapse: collapse; + line-height: 1.5; + } + + thead { + background-color: var(--color-brand-faded-blue); + } + + tbody tr { + border-top: solid 1px var(--color-pale); + } + + th, td { + @extend .pad-0x5; + text-align: initial; + + &:not(:first-of-type) { + border-left: solid 1px var(--color-pale); + } + } + + td:nth-child(n+3) { + color: var(--color-warm-gray) + } + } diff --git a/styles/base/reset.scss b/styles/base/reset.scss index afd7c18..7ce99f3 100644 --- a/styles/base/reset.scss +++ b/styles/base/reset.scss @@ -11,11 +11,12 @@ --default-color-error: #b00008; --default-color-success: #417505; // Project Colors - --color-brand-blue: #1966df; - --color-graphite: #212121; - --color-warm-gray: #757575; - --color-pale: #b6b6b6; - --color-faded: #e0e0e0; + --color-brand-blue: #1966df; + --color-brand-faded-blue: #f5f5ff; + --color-graphite: #212121; + --color-warm-gray: #757575; + --color-pale: #b6b6b6; + --color-faded: #e0e0e0; // Layout --max-content-width: #{$page-max-width + px}; --min-content-width: #{$page-min-width + px}; diff --git a/translates/eng.ts b/translates/eng.ts index 19fefed..c0ca844 100644 --- a/translates/eng.ts +++ b/translates/eng.ts @@ -3,7 +3,7 @@ import { Translations } from "./rus.ts"; export default { About: "About", Works: "Works", - My_latest_works: "My latest works", + Chronological: "Chronological", Source_code: "Source code", Page_not_found: "Page not found", Internal_server_error: "Internal server error", diff --git a/translates/rus.ts b/translates/rus.ts index 5cca3d6..296d269 100644 --- a/translates/rus.ts +++ b/translates/rus.ts @@ -1,7 +1,7 @@ export const rus = { About: "Обо мне", Works: "Работы", - My_latest_works: "Мои последние работы", + Chronological: "Хронология", Source_code: "Исходный код", Page_not_found: "Страница не найдена", Internal_server_error: "Внутренняя ошибка сервера", diff --git a/views/pages/works.ts b/views/pages/works.ts index 2c9f376..b057d97 100644 --- a/views/pages/works.ts +++ b/views/pages/works.ts @@ -3,30 +3,190 @@ import { AnyNode, E } from "ren/node.ts"; import { classNames } from "ren/attrs.ts"; import { Context } from "../../context.ts"; import { H3 } from "../uikit/typo.ts"; +import { Link, RepoLink } from "../uikit/link.ts"; -const ul = E.bind(null, "ul", []); -const li = E.bind(null, "li", []); +const tr = E.bind(null, "tr", []); +const td = E.bind(null, "td", []); +const th = E.bind(null, "th", []); export function WorksPage(ctx: Context): AnyNode { return PageLayout(ctx, [ E("div", classNames("content-width gap-v-1x5 responsive-typography"), [ - H3(ctx.tr.My_latest_works), - ul([ - li([RepoLink("paren", "/pleshevskiy/paren")]), - li([RepoLink("hwt", "github.com/pleshevskiy/hwt")]), - li([RepoLink("sonic-channel", "github.com/pleshevskiy/sonic-channel")]), - li([RepoLink("migra", "github.com/pleshevskiy/migra")]), - li([RepoLink("itconfig", "/pleshevskiy/itconfig")]), + H3(ctx.tr.Chronological), + E("table", [], [ + E("thead", [], [ + tr([ + th("Name"), + th("Description"), + th("Role"), + th("Stack"), + th("Start"), + th("Status"), + ]), + ]), + E("tbody", [], [ + tr([ + td([RepoLink("paren", "/pleshevskiy/paren")]), + td("Library for parsing and rendering information."), + td("author"), + td("TS, Deno"), + td("2022"), + td(`${Status.ActiveDeveloped}, ${Status.Experimental}`), + ]), + tr([ + td([RepoLink("hwt", "//github.com/pleshevskiy/hwt")]), + td( + "healthy workaholic timer – A tool that keeps you from breaking your health by working all day.", + ), + td("author"), + td("Rust"), + td("2022"), + td(Status.ActiveDeveloped), + ]), + tr([ + td([RepoLink("migra", "//github.com/pleshevskiy/migra")]), + td("Simple SQL migration manager for your project."), + td("author"), + td("Rust"), + td("2021"), + td(Status.AsIs), + ]), + tr([ + td([ + RepoLink( + "ood_persistence", + "//github.com/pleshevskiy/ood_persistence", + ), + ]), + td( + "Asynchronous and synchronous interfaces and persistence implementations for your OOD architecture ", + ), + td("author"), + td("Rust"), + td("2021"), + td(`${Status.Deprecated}, ${Status.Experimental}`), + ]), + tr([ + td([ + RepoLink( + "espruino-starter", + "//github.com/pleshevskiy/espruino-starter", + ), + ]), + td( + "Quickly start creating your new project on the espruino board or a board based on it.", + ), + td("author"), + td("JS"), + td("2021"), + td(Status.AsIs), + ]), + tr([ + td([ + RepoLink( + "sonic-channel", + "//github.com/pleshevskiy/sonic-channel", + ), + ]), + td("Rust client for sonic search backend."), + td("author"), + td("Rust"), + td("2020"), + td(Status.PassivelyMaintained), + ]), + tr([ + td([ + RepoLink( + "react-rest-request", + "//github.com/pleshevskiy/react-rest-request", + ), + ]), + td("Minimalistic REST API client for React inspired by Apollo."), + td("author"), + td("TS, React"), + td("2020"), + td(Status.AsIs), + ]), + tr([ + td([RepoLink("itconfig", "/pleshevskiy/itconfig")]), + td( + "Easy build a configs from environment variables and use it in globally.", + ), + td("author"), + td("Rust"), + td("2019"), + td(Status.PassivelyMaintained), + ]), + tr([ + td([ + Link("Cabinet Master Progress", { + href: "https://cabinet.masterprogress.ru", + }), + ]), + td( + "Student's cabinet of the educational center Master Progress (SSR + SPA)", + ), + td("Tech lead"), + td("Python, Flask, React"), + td("2019"), + td(Status.PassivelyMaintained), + ]), + tr([ + td([ + Link("Master Progress", { href: "https://masterprogress.ru" }), + ]), + td( + "Main website of the educational center Master Progress (SSR + Forms)", + ), + td("Tech lead"), + td("Python, Flask"), + td("2018"), + td(Status.PassivelyMaintained), + ]), + tr([ + td([RepoLink("ictmpl", "//github.com/pleshevskiy/ictmpl")]), + td("Generate projects from templates"), + td("author"), + td("Python"), + td("2018"), + td(Status.AsIs), + ]), + tr([ + td([RepoLink("jjcrypto", "//github.com/pleshevskiy/ictmpl")]), + td("Javascript encoder and decoder"), + td("author"), + td("PHP"), + td("2015"), + td(Status.AsIs), + ]), + ]), ]), ]), ]); } -export function RepoLink(name: string, repo: string): AnyNode { - const gitBase = new URL("https://git.pleshevski.ru"); - return E("a", { - target: "_blank", - href: new URL(repo, gitBase).toString(), - rel: "external nofollow noopener noreferrer", - }, name); +enum Status { + // New features are being added and bugs are being fixed. + ActiveDeveloped = "actively-developed", + + // There are no plans for new features, but the maintainer intends to respond + // to issues that get filed. + PassivelyMaintained = "passively-maintained", + + // The package is feature complete, the maintainer does not intend to continue + // working on it or providing support, but it works for the purposes it was + // designed for. + AsIs = "as-is", + + // The author wants to share it with the community but is not intending to + // meet anyone's particular use case. + Experimental = "experimental", + + // The current maintainer would like to transfer the package to someone else. + LookingForMaintainer = "looking-for-maintainer", + + // The maintainer does not recommend using this package (the description of the + // package can describe why, there could be a better solution available or + // there could be problems with the package that the author does not want to fix). + Deprecated = "deprecated", } diff --git a/views/uikit/link.ts b/views/uikit/link.ts index 1c3f7d1..2be2575 100644 --- a/views/uikit/link.ts +++ b/views/uikit/link.ts @@ -3,13 +3,24 @@ import { AnyNode, Attrs, E } from "ren/node.ts"; export function RepoLink(name: string, repo: string): AnyNode { const gitBase = new URL("https://git.pleshevski.ru"); - return Link(name, { - target: "_blank", - href: new URL(repo, gitBase).toString(), - rel: "external nofollow noopener noreferrer", - }); + return Link(name, { href: new URL(repo, gitBase).toString() }); } -export function Link(text: string, attrs: Attrs | Attrs[]): AnyNode { +export function Link( + text: string, + sourceAttrs: Attrs | Attrs[], +): AnyNode { + const attrs = Array.isArray(sourceAttrs) ? sourceAttrs : [sourceAttrs]; + const isExternal = attrs.some((attr) => + typeof attr.href === "string" && attr.href?.startsWith("http") + ); + + if (isExternal) { + attrs.push({ + target: "_blank", + rel: "external nofollow noopener noreferrer", + }); + } + return E("a", attrs, text); }