mirror of
https://github.com/aelve/guide.git
synced 2024-12-22 20:31:31 +03:00
[GD-11] split Item component
This commit is contained in:
parent
e87bf6d9f0
commit
17ce6ba7b2
3
front/public/arrow-thick-bottom.svg
Normal file
3
front/public/arrow-thick-bottom.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
|
||||
<path d="M2 0v5h-2l3.03 3 2.97-3h-2v-5h-2z" transform="translate(1)" />
|
||||
</svg>
|
After Width: | Height: | Size: 160 B |
3
front/public/arrow-thick-top.svg
Normal file
3
front/public/arrow-thick-top.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
|
||||
<path d="M2.97 0l-2.97 3h2v5h2v-5h2l-3.03-3z" transform="translate(1)" />
|
||||
</svg>
|
After Width: | Height: | Size: 162 B |
4
front/public/cog.svg
Normal file
4
front/public/cog.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
|
||||
<path d="M3.5 0l-.5 1.19c-.1.03-.19.08-.28.13l-1.19-.5-.72.72.5 1.19c-.05.1-.09.18-.13.28l-1.19.5v1l1.19.5c.04.1.08.18.13.28l-.5 1.19.72.72 1.19-.5c.09.04.18.09.28.13l.5 1.19h1l.5-1.19c.09-.04.19-.08.28-.13l1.19.5.72-.72-.5-1.19c.04-.09.09-.19.13-.28l1.19-.5v-1l-1.19-.5c-.03-.09-.08-.19-.13-.28l.5-1.19-.72-.72-1.19.5c-.09-.04-.19-.09-.28-.13l-.5-1.19h-1zm.5 2.5c.83 0 1.5.67 1.5 1.5s-.67 1.5-1.5 1.5-1.5-.67-1.5-1.5.67-1.5 1.5-1.5z"
|
||||
/>
|
||||
</svg>
|
After Width: | Height: | Size: 528 B |
3
front/public/rss_alt.svg
Normal file
3
front/public/rss_alt.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
|
||||
<path d="M0 0v2c3.33 0 6 2.67 6 6h2c0-4.41-3.59-8-8-8zm0 3v2c1.67 0 3 1.33 3 3h2c0-2.75-2.25-5-5-5zm0 3v2h2c0-1.11-.9-2-2-2z" />
|
||||
</svg>
|
After Width: | Height: | Size: 217 B |
3
front/public/x.svg
Normal file
3
front/public/x.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="8" height="8" viewBox="0 0 8 8">
|
||||
<path d="M1.41 0l-1.41 1.41.72.72 1.78 1.81-1.78 1.78-.72.69 1.41 1.44.72-.72 1.81-1.81 1.78 1.81.69.72 1.44-1.44-.72-.69-1.81-1.78 1.81-1.81.72-.72-1.44-1.41-.69.72-1.78 1.78-1.81-1.78-.72-.72z" />
|
||||
</svg>
|
After Width: | Height: | Size: 287 B |
@ -25,11 +25,18 @@ class Category extends Component {
|
||||
return (
|
||||
<div>
|
||||
<If condition={this.state.cat !== undefined}>
|
||||
<div className="cat-header">
|
||||
<a href={mkLink(this.state.cat)} className="category-title">{this.state.cat.title}</a>
|
||||
<span className="group">{this.state.cat.group}</span>
|
||||
<span className="text-button"><a href="#">edit</a></span>
|
||||
<span className="text-button"><a href="#">delete</a></span>
|
||||
<div className="category-info">
|
||||
<h2>
|
||||
<span className="controls">
|
||||
<a href="#" className="category-feed">
|
||||
<img src="/rss_alt.svg" title="category-feed" alt="category feed"/>
|
||||
</a>
|
||||
</span>
|
||||
<a href={mkLink(this.state.cat)} className="category-title">{this.state.cat.title}</a>
|
||||
<span className="group">{this.state.cat.group}</span>
|
||||
<span className="text-button"><a href="#">edit</a></span>
|
||||
<span className="text-button"><a href="#">delete</a></span>
|
||||
</h2>
|
||||
</div>
|
||||
<div id={"category-notes-"+this.state.cat.uid} className="category-notes">
|
||||
<div className="noscript-shown shown normal section">
|
||||
@ -38,20 +45,60 @@ class Category extends Component {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
{ this.state.cat.items
|
||||
.map(item => <Item key={item.uid} {...item}/>)
|
||||
}
|
||||
</div>
|
||||
<div>{
|
||||
this.state.cat.items
|
||||
.map(item => <Item key={item.uid} {...item}/>)
|
||||
}</div>
|
||||
</If>
|
||||
<style jsx>{`
|
||||
.cat-header {
|
||||
.Item {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.category-info {
|
||||
display:flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.cat-header span {
|
||||
|
||||
.category-info span {
|
||||
margin-left: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.text-button {
|
||||
font-size: 10pt;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.text-button::before {content: "[";}
|
||||
.text-button::after {content: "]";}
|
||||
|
||||
.text-button > a:visited {color: #008ACE;}
|
||||
h1 > a:visited {color: #008ACE;}
|
||||
|
||||
.category-info .group {
|
||||
font-size: 60%;
|
||||
font-weight: normal;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.category {
|
||||
margin-top: 3em;
|
||||
}
|
||||
|
||||
.category-title {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.category-info .controls {
|
||||
margin-right: 0.5em;
|
||||
vertical-align: -1px;
|
||||
}
|
||||
|
||||
.category-info .controls img {
|
||||
opacity: 0.3;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
`}
|
||||
</style>
|
||||
</div>
|
||||
|
@ -1,3 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
class Header extends Component {
|
||||
@ -15,7 +17,7 @@ class Header extends Component {
|
||||
.subtitle {
|
||||
font-weight: 500;
|
||||
color: #e03;
|
||||
margin-top: 0.4em;
|
||||
margin-top: 0.8em;
|
||||
margin-bottom: 2em;
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,112 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import ReactMarkdown from 'react-markdown';
|
||||
import * as T from '../types';
|
||||
import { mkHackageUrl } from '../utils/index';
|
||||
import { ItemInfo } from './Item/index';
|
||||
|
||||
class Item extends Component {
|
||||
render() {
|
||||
const item : T.Item = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<section>
|
||||
<h1>{this.props.name}</h1>
|
||||
<p>{this.props.kind.tag} {this.props.link}</p>
|
||||
<div dangerouslySetInnerHTML={{__html: this.props.ecosystem.html}}/>
|
||||
<ReactMarkdown source={this.props.notes.text}/>
|
||||
</section>
|
||||
<ItemInfo className="item-info" {...item} />
|
||||
<div className="item-body">
|
||||
<div className="item-description">
|
||||
<strong>Summary</strong>
|
||||
<ReactMarkdown className="notes-like" source={item.description.text} />
|
||||
</div>
|
||||
<div className="pros-cons-wrapper">
|
||||
<div className="item-traits">
|
||||
<div className="traits-groups-container">
|
||||
<div className="traits-group">
|
||||
<strong>Pros</strong>
|
||||
<ul>
|
||||
{item.pros.map(p =>
|
||||
<li key={p.uid}>
|
||||
<ReactMarkdown className="section normal editable shown noscript-shown"
|
||||
source={p.content.text}/>
|
||||
</li>) }
|
||||
</ul>
|
||||
</div>
|
||||
<div className="traits-group">
|
||||
<strong>Cons</strong>
|
||||
<ul>
|
||||
{item.cons.map(c =>
|
||||
<li key={c.uid}>
|
||||
<ReactMarkdown className="section normal editable shown noscript-shown"
|
||||
source={ c.content.text}/>
|
||||
</li>) }
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="ecosystem-wrapper">
|
||||
<div className="item-ecosystem">
|
||||
<div className="noscript-shown show normal section">
|
||||
<strong>Ecosystem</strong>
|
||||
<div className="notes-like" dangerouslySetInnerHTML={{__html: item.ecosystem.html}}/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="notes-wrapper">
|
||||
<div className="item-notes">
|
||||
<a href="">
|
||||
<strong>Notes</strong>
|
||||
</a>
|
||||
<div className="shown collapsed section">
|
||||
<ReactMarkdown source={item.notes.text}/>
|
||||
</div>
|
||||
<div className="noscript-shown expanded section">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<style>{`
|
||||
.item-info {
|
||||
background-color: #D6D6D6;
|
||||
}
|
||||
.item-info {
|
||||
padding-bottom: 12px;
|
||||
padding: 10px 15px;
|
||||
}
|
||||
|
||||
.item-body {
|
||||
padding-top: 5px;
|
||||
}
|
||||
.item-traits,
|
||||
.item-notes,
|
||||
.item-description,
|
||||
.item-ecosystem {
|
||||
padding: 10px 15px 20px 15px;
|
||||
}
|
||||
.item-traits {
|
||||
display:flex;
|
||||
}
|
||||
|
||||
.traits-groups-container {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin: 0px -15px;
|
||||
}
|
||||
|
||||
.traits-group {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
padding: 0px 15px;
|
||||
}
|
||||
|
||||
.traits-group > ul {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.traits-group > ul li {
|
||||
margin: 10px 0px;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
0
front/src/components/Item/ItemBody.js
Normal file
0
front/src/components/Item/ItemBody.js
Normal file
102
front/src/components/Item/ItemInfo.js
Normal file
102
front/src/components/Item/ItemInfo.js
Normal file
@ -0,0 +1,102 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
import * as T from '../../types';
|
||||
import { mkHackageUrl } from '../../utils/index';
|
||||
|
||||
class ItemInfo extends Component {
|
||||
render() {
|
||||
const item : T.Item = this.props;
|
||||
|
||||
return (
|
||||
<div className="item-info">
|
||||
<div className="section normal shown noscript-shown">
|
||||
<div>
|
||||
<a className="anchor" href={item.link}>#</a>
|
||||
</div>
|
||||
<div>
|
||||
<span className="item-name">{item.name + " "}
|
||||
( <a href={mkHackageUrl(item)}>Hackage</a> )
|
||||
</span>
|
||||
</div>
|
||||
<div className="item-group">
|
||||
{item.kind.tag}
|
||||
</div>
|
||||
<div className="controls">
|
||||
<span>
|
||||
<a href="#" className="move-item-up">
|
||||
<img src="/arrow-thick-top.svg" alt="move item up" title="move item up"/>
|
||||
</a>
|
||||
<a>
|
||||
<img src="/arrow-thick-bottom.svg" alt="move item down" title="move item down"/>
|
||||
</a>
|
||||
</span>
|
||||
<span>
|
||||
<a href="#" className="edit-item-info">
|
||||
<img src="/cog.svg" alt="edit item info" title="edit item info"/>
|
||||
</a>
|
||||
</span>
|
||||
<span>
|
||||
<a href="#" className="delete-item">
|
||||
<img src="/x.svg" alt="delete item" title="delete item"/>
|
||||
</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<style jsx>{`
|
||||
a.anchor {
|
||||
margin-right: 0.5em;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display:flex;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.controls > span {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* on big screens we don't want to wrap the controls */
|
||||
@media (min-width: 480px) {
|
||||
.controls {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.controls > span:first-child {
|
||||
padding-right: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
.controls img {
|
||||
opacity: 0.4;
|
||||
height: 20px;
|
||||
position: relative;
|
||||
bottom: -3px;
|
||||
}
|
||||
|
||||
.section.normal {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.item-info-edit-form label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.item-info-edit-form {
|
||||
margin-top: 15px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.item-group {
|
||||
padding-left: 2em;
|
||||
}
|
||||
`}</style>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { ItemInfo }
|
6
front/src/components/Item/index.js
Normal file
6
front/src/components/Item/index.js
Normal file
@ -0,0 +1,6 @@
|
||||
import { ItemInfo } from './ItemInfo';
|
||||
|
||||
|
||||
module.exports = {
|
||||
ItemInfo
|
||||
}
|
@ -1,3 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import React, { Component } from 'react';
|
||||
|
||||
class Search extends Component {
|
||||
|
@ -1,7 +1,19 @@
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
padding: 0px 15px;
|
||||
padding-top: 2em;
|
||||
margin: auto;
|
||||
max-width: 800px;
|
||||
font-family: sans-serif;
|
||||
line-height: 120%;
|
||||
}
|
||||
|
||||
/* Making the footer stick to the bottom of the screen */
|
||||
|
||||
body {
|
||||
display: flex;
|
||||
min-height: 100vh;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
|
@ -18,7 +18,7 @@ export type Description = {
|
||||
html : string
|
||||
};
|
||||
|
||||
export type Valoration = {
|
||||
export type Trait = {
|
||||
uid : string,
|
||||
content : Description,
|
||||
};
|
||||
@ -44,8 +44,8 @@ export type Item = {
|
||||
prosDeleted : Array<String>,
|
||||
notes : Note,
|
||||
description: Description,
|
||||
pros : Array<Valoration>,
|
||||
cons : Array<Valoration>
|
||||
pros : Array<Trait>,
|
||||
cons : Array<Trait>
|
||||
};
|
||||
|
||||
export type Cat = {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// @flow
|
||||
|
||||
function checkStatus(response) {
|
||||
function checkStatus(response : Response) {
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return response;
|
||||
} else {
|
||||
@ -8,7 +8,7 @@ function checkStatus(response) {
|
||||
}
|
||||
}
|
||||
|
||||
function parseJSON(response) {
|
||||
function parseJSON(response : Response) {
|
||||
return response.json();
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,5 @@
|
||||
// @flow
|
||||
|
||||
import { fetchData } from './fetchData';
|
||||
import * as T from '../types';
|
||||
|
||||
@ -8,9 +10,11 @@ function extractUid(link : string) {
|
||||
|
||||
const mkLink = (cat : T.Cat) => cat.title.toLowerCase() + "-" + cat.uid;
|
||||
|
||||
const mkHackageUrl = (item : T.Item) => "https://hackage.haskell.org/package/" + item.kind.hackageName;
|
||||
|
||||
module.exports = {
|
||||
fetchData,
|
||||
extractUid,
|
||||
mkLink
|
||||
mkLink,
|
||||
mkHackageUrl
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user