Skip to content

Instantly share code, notes, and snippets.

@kmelve
Created November 25, 2019 22:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kmelve/d6cc00beaa99f0d70030133077369720 to your computer and use it in GitHub Desktop.
Save kmelve/d6cc00beaa99f0d70030133077369720 to your computer and use it in GitHub Desktop.
Proof of Concept Kanban tool for Sanity Studio
import styled from "styled-components";
export const Wrapper = styled.div`
font-family: 'Open Sans', sans-serif;
display: flex;
flex: 1;
flex-direction: column;
`;
export const RowWrapper = styled.div`
display: flex;
flex-basis: 100%;
flex-direction: column;
justify-content: space-between;
`;
export const InfoWrapper = styled.div`
display: flex;
flex-direction: row;
`;
export const Label = styled.span`
font-weight: 600;
font-size: 14px;
color: #607389;
margin-right: 5px;
`;
export const Value = styled.span`
font-size: 14px;
color: #607389;
`;
export const Title = styled.span`
font-size: 21px;
color: #607389;
font-weight: 600;
align-self: center;
`;
import React from 'react'
import MyTool from './MyTool'
import MyToolIcon from './MyToolIcon'
export default {
title: 'Kanban',
name: 'mytool',
icon: MyToolIcon,
component: MyTool
}
export const kanbanStyles = {
cardWrapper: {
borderRadius: 2,
border: "1px solid rgba(96,115,137,0.12)",
backgroundColor: "#ffffff",
boxShadow: "none",
padding: "9px 9px 0px 9px",
minHeight: 40,
marginBottom: 8
},
columnStyle: {
backgroundColor: "rgba(96,115,137,0.04)",
padding: 10,
borderRadius: 2,
borderLeft: "1px solid rgba(96, 115, 137, 0.12)",
borderRight: "1px solid rgba(96, 115, 137, 0.12)",
borderBottom: "1px solid rgba(96, 115, 137, 0.12)",
paddingBottom: 0,
transition: "background-color 0.1s ease, opacity 0.1s ease",
userSelect: "none"
},
columnHeaderStyle: {
backgroundColor: "rgba(96,115,137,0.04)"
},
columnTitleStyle: {
fontWeight: 600,
fontSize: 14,
color: "#607389",
marginRight: 5
}
};
import React from 'react'
import client from 'part:@sanity/base/client'
import ReactKanban from 'react-kanban-dnd';
const columns = [
]
const query = `{
"draft": *[_type == "post" && editorial == "draft"],
"published": *[_type == "post" && editorial == "published"],
"review": *[_type == "post" && editorial == "review"],
}`
// Sanity uses CSS modules for styling. We import a stylesheet and get an
// object where the keys matches the class names defined in the CSS file and
// the values are a unique, generated class name. This allows you to write CSS
// with only your components in mind without any conflicting class names.
// See https://github.com/css-modules/css-modules for more info.
import styles from './MyTool.css'
import kanbanStyles from './kanbanStyles'
import {
RowWrapper,
InfoWrapper,
Label,
Value,
Wrapper,
Title
} from "./components";
class MyTool extends React.Component {
state = {
columns: []
}
prepareColumns = docs => {
console.log(docs)
const columns = Object.keys(docs).map(column => {
return {
id: column,
title: column,
rows: docs[column].map(row => ({id: row._id, ...row}))
}
})
return columns
}
onDragEnd = props => console.log(props)
onDragStart = props => console.log(props)
onDragEnd = props => {
console.log(props)
const {draggableId, destination} = props
client.patch(draggableId).set({editorial: destination.droppableId}).commit().then(console.log)
}
renderCard = row => (
<RowWrapper>
<InfoWrapper>
<Label>Title:</Label>
<Value>{row.title}</Value>
</InfoWrapper>
<InfoWrapper>
<Label>Last updated:</Label>
<Value>{new Date(row._updatedAt).toLocaleString()}</Value>
</InfoWrapper>
</RowWrapper>
);
componentDidMount() {
client.fetch(query).then(this.prepareColumns).then(columns => this.setState({columns}))
}
render() {
const { columns }= this.state || []
if (!columns || !columns.length) {
return <div>No documents founds</div>
}
return (
<div className={styles.container}>
<ReactKanban
onDragEnd={this.onDragEnd}
onDragStart={this.onDragStart}
renderCard={this.renderCard}
columns={columns}
cardWrapperStyle={styles.cardWrapper}
columnStyle={styles.columnStyle}
columnHeaderStyle={styles.columnHeaderStyle}
/>
</div>
)
}
}
export default MyTool
import React from 'react'
/**
* Couple of things to note:
* - width and height is set to 1em
* - fill is `currentColor` - this will ensure that the icon looks uniform and
* that the hover/active state works. You can of course render anything you
* would like here, but for plugins that are to be used in more than one
* studio, we suggest these rules are followed
**/
export default () => (
<svg xmlns='http://www.w3.org/2000/svg' width="1em" height="1em" viewBox='0 0 128 128' fill="currentColor">
<rect x='9.455' y='24.709' width='16.726' height='10.766' />
<rect x='9.455' y='40.869' width='16.726' height='10.766' />
<rect x='9.455' y='57.03' width='16.726' height='10.765' />
<rect x='40.346' y='24.709' width='16.726' height='10.766' />
<rect x='40.346' y='40.869' width='16.726' height='10.766' />
<rect x='40.346' y='57.03' width='16.726' height='10.765' />
<rect x='71.236' y='24.709' width='16.727' height='10.766' />
<rect x='102.127' y='24.709' width='16.727' height='10.766' />
<rect x='71.236' y='40.869' width='16.727' height='10.766' />
<path d='M118.304,14.408H9.695C4.349,14.408,0,18.757,0,24.104v79.792c0,5.348,4.349,9.696,9.695,9.696h108.608 c5.348,0,9.696-4.349,9.696-9.696V24.104C128,18.757,123.651,14.408,118.304,14.408z M65.212,19.256h28.365v89.488H65.212V19.256z M62.789,108.744H34.423V19.256h28.365V108.744z M4.848,103.896V24.104c0-2.674,2.174-4.848,4.848-4.848H32v89.488H9.695 C7.022,108.744,4.848,106.568,4.848,103.896z M123.152,103.896c0,2.673-2.176,4.849-4.849,4.849H96.001V19.256h22.303 c2.673,0,4.849,2.174,4.849,4.848V103.896z'
/>
</svg>
)
{
"parts": [
{
"implements": "part:@sanity/base/tool",
"path": "./index.js"
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment