frontend: remove large amounts of custom CSS
This commit is contained in:
parent
64b457d893
commit
9e820a0068
6 changed files with 97 additions and 150 deletions
14
README.md
14
README.md
|
@ -1,17 +1,15 @@
|
|||
## About
|
||||
|
||||
Twenty helps you manage projects with a solution that runs on your computer
|
||||
rather than in the cloud.
|
||||
Twenty helps you manage projects with a web application that
|
||||
runs on your computer rather than in the cloud.
|
||||
|
||||
## Features
|
||||
|
||||
* Provides a web application that helps you manage projects.
|
||||
* Provides a command-line utility to start / stop a web server, connect / disconnect a project.
|
||||
* Provides a command-line utility to start / stop a web server.
|
||||
* Connect / disconnect a project from the command line.
|
||||
* Works offline. Binds to `http//:localhost:2020` by default.
|
||||
* Lightweight: Ruby, and SQLite3 are the primary runtime dependencies.
|
||||
* Database: `~/.local/share/twenty/twenty.sqlite`.
|
||||
* Easy to install: `gem install twenty`.
|
||||
* Easy to use: `$ twenty up`.
|
||||
* Ruby, and SQLite3 are the primary runtime dependencies.
|
||||
* Easy to install, easy to use.
|
||||
|
||||
## Usage
|
||||
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
body .wrapper .group {
|
||||
@import "colors";
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.group-name {
|
||||
margin: 10px 0 10px 0;
|
||||
padding: 10px;
|
||||
background: $secondary-color;
|
||||
color: $primary-color;
|
||||
border-radius: 5px;
|
||||
|
||||
ul.tabs {
|
||||
list-style-type: none;
|
||||
display: flex;
|
||||
grid-gap: 15px;
|
||||
font-size: medium;
|
||||
|
||||
li.tab {
|
||||
height: 24px;
|
||||
width: 100px;
|
||||
a {
|
||||
display: block;
|
||||
background: $primary-color;
|
||||
color: $accent-color;
|
||||
border-radius: 5px;
|
||||
height: 100%;
|
||||
&:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
li.tab.active {
|
||||
a {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.group-items {
|
||||
min-height: 75px;
|
||||
|
||||
p.empty-group {
|
||||
padding-top: 2.5%;
|
||||
}
|
||||
|
||||
ul.items {
|
||||
li.item {
|
||||
display: flex;
|
||||
padding: 7.5px;
|
||||
border: 1px solid $primary-color;
|
||||
|
||||
select {
|
||||
height: 35px;
|
||||
padding: 10px;
|
||||
background: $primary-color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: $secondary-color;
|
||||
color: $primary-color;
|
||||
border-radius: 10px;
|
||||
border: 1px solid $secondary-color;
|
||||
|
||||
a {
|
||||
color: $primary-color;
|
||||
text-decoration: none;
|
||||
span {
|
||||
color: $primary-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
padding: 10px 10px 5px 0px;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.markdown {
|
||||
ul ,
|
||||
ul li,
|
||||
ul li.task-list-item input[type='checkbox']
|
||||
{
|
||||
padding: 0 !important;
|
||||
margin: 0 !important;
|
||||
}
|
||||
h1, h2, h3, h4, p {
|
||||
}
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
@import "fonts";
|
||||
@import "colors";
|
||||
@import "global";
|
||||
@import "groups";
|
||||
@import "layout";
|
||||
|
||||
*, *:before, *:after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, html body, .wrapper {
|
||||
html, html body {
|
||||
height: 100%;
|
||||
font-size: medium;
|
||||
}
|
||||
|
@ -18,13 +17,21 @@ body {
|
|||
font-weight: normal;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
color: $secondary-color;
|
||||
|
||||
.react-mount {
|
||||
padding-top: 25px;
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.secondary-hover {
|
||||
&:hover {
|
||||
@extend .no-underline;
|
||||
@extend .p-3;
|
||||
@extend .rounded;
|
||||
@extend .bg-secondary;
|
||||
@extend .text-primary;
|
||||
a, span {
|
||||
@extend .text-primary;
|
||||
@extend .no-underline;
|
||||
}
|
||||
h1, h2, h3, h4, h5 {
|
||||
font-size: medium;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,23 +19,23 @@ export function Group({ groupName, getItems }: Props) {
|
|||
}
|
||||
|
||||
return (
|
||||
<div className="group">
|
||||
<h1 className="group-name w-100">{groupName}</h1>
|
||||
<div className="group-items">
|
||||
<div>
|
||||
<h1 className="bg-secondary text-primary p-3 rounded">{groupName}</h1>
|
||||
<div>
|
||||
{items?.length ? (
|
||||
<ul className="items">
|
||||
<ul className="flex flex-wrap">
|
||||
{items.map((task: Task, key: number) => {
|
||||
const { updatedAt } = task;
|
||||
const datetime = DateTime.fromISO(updatedAt);
|
||||
const classes = {};
|
||||
const editHref = `/tasks/edit#id=${task.id}`;
|
||||
return (
|
||||
<li className={classnames("item", classes)} key={key}>
|
||||
<li className={classnames("flex flex-row p-3 secondary-hover w-full", classes)} key={key}>
|
||||
<div className="flex flex-wrap w-3/4">
|
||||
<div className="w-full">
|
||||
<a href={editHref}>
|
||||
<span>{task.title}</span>
|
||||
<span className="text-smaller text-secondary">
|
||||
<a className="no-underline text-accent block h-14" href={editHref}>
|
||||
<span className="block w-full">{task.title}</span>
|
||||
<span className="block w-full text-smaller text-secondary">
|
||||
{datetime.toFormat("dd LLL, yyyy")} at{" "}
|
||||
{datetime.toFormat("HH:mm")}
|
||||
</span>
|
||||
|
@ -50,7 +50,7 @@ export function Group({ groupName, getItems }: Props) {
|
|||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex justify-content-end w-25">
|
||||
<div className="flex h-12 w-1/4">
|
||||
<TaskStatusSelect task={task} />
|
||||
</div>
|
||||
</li>
|
||||
|
@ -58,13 +58,12 @@ export function Group({ groupName, getItems }: Props) {
|
|||
})}
|
||||
</ul>
|
||||
) : (
|
||||
<p className="empty-group">
|
||||
<p>
|
||||
There are no {groupName.toLowerCase()} tasks.
|
||||
<br />
|
||||
<a className="w-100" href="/tasks/new">
|
||||
Add a task
|
||||
</a>{" "}
|
||||
.
|
||||
</a> .
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
|
|
|
@ -1,23 +1,65 @@
|
|||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { Maybe } from "/types/schema";
|
||||
import classnames from "classnames";
|
||||
|
||||
const BASE_CLASSNAMES = [ "block", "w-3/4", "no-underline", "p-3"];
|
||||
const ACTIVE_CLASSNAMES = [...BASE_CLASSNAMES, "rounded", "bg-secondary", "text-primary" ].join(" ");
|
||||
const INACTIVE_CLASSNAMES = [...BASE_CLASSNAMES, "text-accent"].join(" ");
|
||||
const BASE_CLASSNAMES = ["block", "w-3/4", "no-underline", "p-3", "mt-2"];
|
||||
const ACTIVE_CLASSNAMES = [
|
||||
...BASE_CLASSNAMES,
|
||||
"rounded",
|
||||
"bg-secondary",
|
||||
"text-primary",
|
||||
].join(" ");
|
||||
const INACTIVE_CLASSNAMES = [...BASE_CLASSNAMES, "text-accent", "secondary-hover"].join(" ");
|
||||
|
||||
type Item = { text: string; href: string };
|
||||
type Bar = Record<string, Array<Item>>;
|
||||
|
||||
const find = (path: string, bar: Bar): Maybe<Item> => {
|
||||
let item: Maybe<Item> = null;
|
||||
Object.values(bar)
|
||||
.flat()
|
||||
.forEach(i => {
|
||||
if (i.href === path) {
|
||||
item = i;
|
||||
}
|
||||
});
|
||||
return item;
|
||||
};
|
||||
|
||||
export function NavBar() {
|
||||
const bar: Bar = {
|
||||
Tasks: [
|
||||
{ text: "All tasks", href: "/tasks/" },
|
||||
{ text: "New task", href: "/tasks/new/" },
|
||||
],
|
||||
Projects: [{ text: "All projects", href: "/projects" }],
|
||||
};
|
||||
const activeItem = find(location.pathname, bar);
|
||||
|
||||
return (
|
||||
<>
|
||||
{...Object.keys(bar).map(key => {
|
||||
const items = bar[key];
|
||||
return (
|
||||
<>
|
||||
<h1>{key}</h1>
|
||||
<ul>
|
||||
<h1>Tasks</h1>
|
||||
{...items.flatMap(item => {
|
||||
return (
|
||||
<li>
|
||||
<a className={ACTIVE_CLASSNAMES} href="/tasks">All tasks</a>
|
||||
</li>
|
||||
<li>
|
||||
<a className={INACTIVE_CLASSNAMES} href="/tasks/new">New task</a>
|
||||
</li>
|
||||
<h1>Projects</h1>
|
||||
<li>
|
||||
<a className={INACTIVE_CLASSNAMES} href="/projects">All projects</a>
|
||||
<a
|
||||
className={activeItem == item ? ACTIVE_CLASSNAMES : INACTIVE_CLASSNAMES}
|
||||
href={item.href}
|
||||
>
|
||||
{item.text}
|
||||
</a>
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
</ul>
|
||||
</>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -118,10 +118,9 @@ export function Task({ taskId }: { taskId?: number }) {
|
|||
</div>
|
||||
{isEditable ? (
|
||||
<>
|
||||
<div className="row textarea h-70">
|
||||
<div className="h-96 w-3/4">
|
||||
<textarea
|
||||
className="form h-100"
|
||||
placeholder="Add your description heren"
|
||||
className="w-full h-full"
|
||||
defaultValue={task?.content || DEFAULT_TASK_CONTENT}
|
||||
{...register("content", { required: true })}
|
||||
/>
|
||||
|
|
Loading…
Reference in a new issue