mirror of
https://github.com/mattermost/focalboard.git
synced 2025-02-13 19:42:12 +02:00
Ran npm run fix
This commit is contained in:
parent
36a104f45b
commit
9255bd4ded
@ -69,6 +69,7 @@
|
||||
"rules": {
|
||||
"import/no-unresolved": 0, // ts handles this better
|
||||
"camelcase": 0,
|
||||
"semi": "off",
|
||||
"@typescript-eslint/naming-convention": [
|
||||
2,
|
||||
{
|
||||
|
@ -1,16 +1,16 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {
|
||||
BrowserRouter as Router,
|
||||
Switch,
|
||||
Route,
|
||||
Link,
|
||||
} from 'react-router-dom';
|
||||
} from 'react-router-dom'
|
||||
|
||||
import LoginPage from './pages/loginPage';
|
||||
import BoardPage from './pages/boardPage';
|
||||
import LoginPage from './pages/loginPage'
|
||||
import BoardPage from './pages/boardPage'
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
|
@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {BoardTree} from './boardTree';
|
||||
import mutator from './mutator';
|
||||
import {IBlock} from './octoTypes';
|
||||
import {Utils} from './utils';
|
||||
import {BoardTree} from './boardTree'
|
||||
import mutator from './mutator'
|
||||
import {IBlock} from './octoTypes'
|
||||
import {Utils} from './utils'
|
||||
|
||||
interface Archive {
|
||||
version: number
|
||||
@ -40,7 +40,7 @@ class Archiver {
|
||||
const date = new Date()
|
||||
const filename = `archive-${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}.octo`
|
||||
const link = document.createElement('a')
|
||||
link.style.display = 'none';
|
||||
link.style.display = 'none'
|
||||
|
||||
// const file = new Blob([content], { type: "text/json" })
|
||||
// link.href = URL.createObjectURL(file)
|
||||
@ -55,8 +55,8 @@ class Archiver {
|
||||
|
||||
static importFullArchive(onComplete?: () => void): void {
|
||||
const input = document.createElement('input')
|
||||
input.type = 'file';
|
||||
input.accept = '.octo';
|
||||
input.type = 'file'
|
||||
input.accept = '.octo'
|
||||
input.onchange = async () => {
|
||||
const file = input.files[0]
|
||||
const contents = await (new Response(file)).text()
|
||||
@ -72,16 +72,16 @@ class Archiver {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
});
|
||||
})
|
||||
|
||||
Utils.log(`Import ${filteredBlocks.length} filtered blocks.`)
|
||||
|
||||
await mutator.importFullArchive(filteredBlocks)
|
||||
Utils.log('Import completed')
|
||||
onComplete?.()
|
||||
};
|
||||
}
|
||||
|
||||
input.style.display = 'none';
|
||||
input.style.display = 'none'
|
||||
document.body.appendChild(input)
|
||||
input.click()
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {randomEmojiList} from './emojiList';
|
||||
import {randomEmojiList} from './emojiList'
|
||||
|
||||
class BlockIcons {
|
||||
static readonly shared = new BlockIcons()
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {IBlock} from '../octoTypes';
|
||||
import {Utils} from '../utils';
|
||||
import {IBlock} from '../octoTypes'
|
||||
import {Utils} from '../utils'
|
||||
|
||||
class Block implements IBlock {
|
||||
id: string = Utils.createGuid()
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Block} from './block';
|
||||
import {Block} from './block'
|
||||
|
||||
type PropertyType = 'text' | 'number' | 'select' | 'multiSelect' | 'date' | 'person' | 'file' | 'checkbox' | 'url' | 'email' | 'phone' | 'createdTime' | 'createdBy' | 'updatedTime' | 'updatedBy'
|
||||
|
||||
@ -34,7 +34,7 @@ class Board extends Block {
|
||||
|
||||
constructor(block: any = {}) {
|
||||
super(block)
|
||||
this.type = 'board';
|
||||
this.type = 'board'
|
||||
|
||||
if (block.fields?.cardProperties) {
|
||||
// Deep clone of card properties and their options
|
||||
@ -45,7 +45,7 @@ class Board extends Block {
|
||||
type: o.type,
|
||||
options: o.options ? o.options.map((option) => ({...option})) : [],
|
||||
}
|
||||
});
|
||||
})
|
||||
} else {
|
||||
this.cardProperties = []
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {FilterGroup} from '../filterGroup';
|
||||
import {FilterGroup} from '../filterGroup'
|
||||
|
||||
import {Block} from './block';
|
||||
import {Block} from './block'
|
||||
|
||||
type IViewType = 'board' | 'table' | 'calendar' | 'list' | 'gallery'
|
||||
type ISortOption = { propertyId: '__name' | string, reversed: boolean }
|
||||
@ -46,7 +46,7 @@ class BoardView extends Block {
|
||||
constructor(block: any = {}) {
|
||||
super(block)
|
||||
|
||||
this.type = 'view';
|
||||
this.type = 'view'
|
||||
|
||||
this.sortOptions = block.fields?.sortOptions?.map((o: ISortOption) => ({...o})) || [] // Deep clone
|
||||
this.visiblePropertyIds = block.fields?.visiblePropertyIds?.slice() || []
|
||||
@ -54,7 +54,7 @@ class BoardView extends Block {
|
||||
|
||||
// TODO: Remove this fixup code
|
||||
if (block.schema !== 1) {
|
||||
this.viewType = block.viewType || 'board';
|
||||
this.viewType = block.viewType || 'board'
|
||||
this.groupById = block.groupById
|
||||
this.sortOptions = block.sortOptions ? block.sortOptions.map((o: ISortOption) => ({...o})) : [] // Deep clone
|
||||
this.visiblePropertyIds = block.visiblePropertyIds ? block.visiblePropertyIds.slice() : []
|
||||
@ -62,7 +62,7 @@ class BoardView extends Block {
|
||||
}
|
||||
|
||||
if (!this.viewType) {
|
||||
this.viewType = 'board';
|
||||
this.viewType = 'board'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Block} from './block';
|
||||
import {Block} from './block'
|
||||
|
||||
class Card extends Block {
|
||||
get icon(): string {
|
||||
@ -19,7 +19,7 @@ class Card extends Block {
|
||||
|
||||
constructor(block: any = {}) {
|
||||
super(block)
|
||||
this.type = 'card';
|
||||
this.type = 'card'
|
||||
|
||||
this.properties = {...(block.fields?.properties || {})}
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Block} from './block';
|
||||
import {Block} from './block'
|
||||
|
||||
class CommentBlock extends Block {
|
||||
constructor(block: any = {}) {
|
||||
super(block)
|
||||
this.type = 'comment';
|
||||
this.type = 'comment'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {IOrderedBlock} from '../octoTypes';
|
||||
import {IOrderedBlock} from '../octoTypes'
|
||||
|
||||
import {Block} from './block';
|
||||
import {Block} from './block'
|
||||
|
||||
class ImageBlock extends Block implements IOrderedBlock {
|
||||
get order(): number {
|
||||
@ -21,7 +21,7 @@ class ImageBlock extends Block implements IOrderedBlock {
|
||||
|
||||
constructor(block: any = {}) {
|
||||
super(block)
|
||||
this.type = 'image';
|
||||
this.type = 'image'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {IOrderedBlock} from '../octoTypes';
|
||||
import {IOrderedBlock} from '../octoTypes'
|
||||
|
||||
import {Block} from './block';
|
||||
import {Block} from './block'
|
||||
|
||||
class TextBlock extends Block implements IOrderedBlock {
|
||||
get order(): number {
|
||||
@ -14,7 +14,7 @@ class TextBlock extends Block implements IOrderedBlock {
|
||||
|
||||
constructor(block: any = {}) {
|
||||
super(block)
|
||||
this.type = 'text';
|
||||
this.type = 'text'
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,14 +1,14 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Block} from './blocks/block';
|
||||
import {Board, IPropertyOption, IPropertyTemplate} from './blocks/board';
|
||||
import {BoardView} from './blocks/boardView';
|
||||
import {Card} from './blocks/card';
|
||||
import {CardFilter} from './cardFilter';
|
||||
import octoClient from './octoClient';
|
||||
import {IBlock} from './octoTypes';
|
||||
import {OctoUtils} from './octoUtils';
|
||||
import {Utils} from './utils';
|
||||
import {Block} from './blocks/block'
|
||||
import {Board, IPropertyOption, IPropertyTemplate} from './blocks/board'
|
||||
import {BoardView} from './blocks/boardView'
|
||||
import {Card} from './blocks/card'
|
||||
import {CardFilter} from './cardFilter'
|
||||
import octoClient from './octoClient'
|
||||
import {IBlock} from './octoTypes'
|
||||
import {OctoUtils} from './octoUtils'
|
||||
import {Utils} from './utils'
|
||||
|
||||
type Group = { option: IPropertyOption, cards: Card[] }
|
||||
|
||||
@ -154,7 +154,7 @@ class BoardTree {
|
||||
this.emptyGroupCards = this.cards.filter((o) => {
|
||||
const propertyValue = o.properties[groupByPropertyId]
|
||||
return !propertyValue || !this.groupByProperty.options.find((option) => option.value === propertyValue)
|
||||
});
|
||||
})
|
||||
|
||||
const propertyOptions = this.groupByProperty.options || []
|
||||
for (const option of propertyOptions) {
|
||||
@ -162,7 +162,7 @@ class BoardTree {
|
||||
filter((o) => {
|
||||
const propertyValue = o.properties[groupByPropertyId]
|
||||
return propertyValue && propertyValue === option.value
|
||||
});
|
||||
})
|
||||
|
||||
const group: Group = {
|
||||
option,
|
||||
@ -194,8 +194,8 @@ class BoardTree {
|
||||
if (sortOptions.length < 1) {
|
||||
Utils.log('Default sort')
|
||||
sortedCards = cards.sort((a, b) => {
|
||||
const aValue = a.title || '';
|
||||
const bValue = b.title || '';
|
||||
const aValue = a.title || ''
|
||||
const bValue = b.title || ''
|
||||
|
||||
// Always put empty values at the bottom
|
||||
if (aValue && !bValue) {
|
||||
@ -209,14 +209,14 @@ class BoardTree {
|
||||
}
|
||||
|
||||
return a.createAt - b.createAt
|
||||
});
|
||||
})
|
||||
} else {
|
||||
sortOptions.forEach((sortOption) => {
|
||||
if (sortOption.propertyId === '__name') {
|
||||
Utils.log('Sort by name')
|
||||
sortedCards = cards.sort((a, b) => {
|
||||
const aValue = a.title || '';
|
||||
const bValue = b.title || '';
|
||||
const aValue = a.title || ''
|
||||
const bValue = b.title || ''
|
||||
|
||||
// Always put empty values at the bottom, newest last
|
||||
if (aValue && !bValue) {
|
||||
@ -234,7 +234,7 @@ class BoardTree {
|
||||
result = -result
|
||||
}
|
||||
return result
|
||||
});
|
||||
})
|
||||
} else {
|
||||
const sortPropertyId = sortOption.propertyId
|
||||
const template = board.cardProperties.find((o) => o.id === sortPropertyId)
|
||||
@ -255,8 +255,8 @@ class BoardTree {
|
||||
return a.createAt - b.createAt
|
||||
}
|
||||
|
||||
const aValue = a.properties[sortPropertyId] || '';
|
||||
const bValue = b.properties[sortPropertyId] || '';
|
||||
const aValue = a.properties[sortPropertyId] || ''
|
||||
const bValue = b.properties[sortPropertyId] || ''
|
||||
let result = 0
|
||||
if (template.type === 'select') {
|
||||
// Always put empty values at the bottom
|
||||
@ -313,7 +313,7 @@ class BoardTree {
|
||||
result = -result
|
||||
}
|
||||
return result
|
||||
});
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {IPropertyTemplate} from './blocks/board';
|
||||
import {Card} from './blocks/card';
|
||||
import {FilterClause} from './filterClause';
|
||||
import {FilterGroup} from './filterGroup';
|
||||
import {Utils} from './utils';
|
||||
import {IPropertyTemplate} from './blocks/board'
|
||||
import {Card} from './blocks/card'
|
||||
import {FilterClause} from './filterClause'
|
||||
import {FilterGroup} from './filterGroup'
|
||||
import {Utils} from './utils'
|
||||
|
||||
class CardFilter {
|
||||
static applyFilterGroup(filterGroup: FilterGroup, templates: IPropertyTemplate[], cards: Card[]): Card[] {
|
||||
@ -89,7 +89,7 @@ class CardFilter {
|
||||
filters.forEach((filterClause) => {
|
||||
const p = this.propertyThatMeetsFilterClause(filterClause as FilterClause, templates)
|
||||
result[p.id] = p.value
|
||||
});
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Block} from './blocks/block';
|
||||
import {Card} from './blocks/card';
|
||||
import octoClient from './octoClient';
|
||||
import {IBlock, IOrderedBlock} from './octoTypes';
|
||||
import {OctoUtils} from './octoUtils';
|
||||
import {Block} from './blocks/block'
|
||||
import {Card} from './blocks/card'
|
||||
import octoClient from './octoClient'
|
||||
import {IBlock, IOrderedBlock} from './octoTypes'
|
||||
import {OctoUtils} from './octoUtils'
|
||||
|
||||
class CardTree {
|
||||
card: Card
|
||||
|
@ -1,14 +1,14 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {Block} from '../blocks/block';
|
||||
import {IPropertyTemplate} from '../blocks/board';
|
||||
import {Card} from '../blocks/card';
|
||||
import {Menu} from '../menu';
|
||||
import mutator from '../mutator';
|
||||
import {OctoUtils} from '../octoUtils';
|
||||
import {Utils} from '../utils';
|
||||
import {Block} from '../blocks/block'
|
||||
import {IPropertyTemplate} from '../blocks/board'
|
||||
import {Card} from '../blocks/card'
|
||||
import {Menu} from '../menu'
|
||||
import mutator from '../mutator'
|
||||
import {OctoUtils} from '../octoUtils'
|
||||
import {Utils} from '../utils'
|
||||
|
||||
type BoardCardProps = {
|
||||
card: Card
|
||||
@ -49,7 +49,7 @@ class BoardCard extends React.Component<BoardCardProps, BoardCardState> {
|
||||
optionsButtonRef.current.style.display = null
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
optionsButtonRef.current.style.display = 'none';
|
||||
optionsButtonRef.current.style.display = 'none'
|
||||
}}
|
||||
>
|
||||
<div
|
||||
@ -86,12 +86,12 @@ class BoardCard extends React.Component<BoardCardProps, BoardCardState> {
|
||||
switch (id) {
|
||||
case 'delete': {
|
||||
mutator.deleteBlock(card, 'delete card')
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'duplicate': {
|
||||
const newCard = Block.duplicate(card)
|
||||
mutator.insertBlock(newCard, 'duplicate card')
|
||||
break;
|
||||
break
|
||||
}
|
||||
default: {
|
||||
Utils.assertFailure(`Unhandled menu id: ${id}`)
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
onDrop?: (e: React.DragEvent<HTMLDivElement>) => void
|
||||
|
@ -1,28 +1,28 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {Archiver} from '../archiver';
|
||||
import {BlockIcons} from '../blockIcons';
|
||||
import {IPropertyOption} from '../blocks/board';
|
||||
import {Card} from '../blocks/card';
|
||||
import {BoardTree} from '../boardTree';
|
||||
import {CardFilter} from '../cardFilter';
|
||||
import ViewMenu from '../components/viewMenu';
|
||||
import {Constants} from '../constants';
|
||||
import {Menu as OldMenu} from '../menu';
|
||||
import mutator from '../mutator';
|
||||
import {OctoUtils} from '../octoUtils';
|
||||
import {Utils} from '../utils';
|
||||
import Menu from '../widgets/menu';
|
||||
import MenuWrapper from '../widgets/menuWrapper';
|
||||
import {Archiver} from '../archiver'
|
||||
import {BlockIcons} from '../blockIcons'
|
||||
import {IPropertyOption} from '../blocks/board'
|
||||
import {Card} from '../blocks/card'
|
||||
import {BoardTree} from '../boardTree'
|
||||
import {CardFilter} from '../cardFilter'
|
||||
import ViewMenu from '../components/viewMenu'
|
||||
import {Constants} from '../constants'
|
||||
import {Menu as OldMenu} from '../menu'
|
||||
import mutator from '../mutator'
|
||||
import {OctoUtils} from '../octoUtils'
|
||||
import {Utils} from '../utils'
|
||||
import Menu from '../widgets/menu'
|
||||
import MenuWrapper from '../widgets/menuWrapper'
|
||||
|
||||
import {BoardCard} from './boardCard';
|
||||
import {BoardColumn} from './boardColumn';
|
||||
import Button from './button';
|
||||
import {CardDialog} from './cardDialog';
|
||||
import {Editable} from './editable';
|
||||
import RootPortal from './rootPortal';
|
||||
import {BoardCard} from './boardCard'
|
||||
import {BoardColumn} from './boardColumn'
|
||||
import Button from './button'
|
||||
import {CardDialog} from './cardDialog'
|
||||
import {Editable} from './editable'
|
||||
import RootPortal from './rootPortal'
|
||||
|
||||
type Props = {
|
||||
boardTree?: BoardTree
|
||||
@ -404,7 +404,7 @@ class BoardComponent extends React.Component<Props, State> {
|
||||
this.setState({shownCard: card})
|
||||
}, async () => {
|
||||
this.setState({shownCard: undefined})
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
async propertyNameChanged(option: IPropertyOption, text: string) {
|
||||
@ -431,19 +431,19 @@ class BoardComponent extends React.Component<Props, State> {
|
||||
switch (id) {
|
||||
case 'exportBoardArchive': {
|
||||
Archiver.exportBoardTree(boardTree)
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'testAdd100Cards': {
|
||||
this.testAddCards(100)
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'testAdd1000Cards': {
|
||||
this.testAddCards(1000)
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'testRandomizeIcons': {
|
||||
this.testRandomizeIcons()
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -489,7 +489,7 @@ class BoardComponent extends React.Component<Props, State> {
|
||||
OldMenu.shared.options = selectProperties.map((o) => {
|
||||
const isVisible = activeView.visiblePropertyIds.includes(o.id)
|
||||
return {id: o.id, name: o.name, type: 'switch', isOn: isVisible}
|
||||
});
|
||||
})
|
||||
|
||||
OldMenu.shared.onMenuToggled = async (id: string, isOn: boolean) => {
|
||||
const property = selectProperties.find((o) => o.id === id)
|
||||
@ -503,7 +503,7 @@ class BoardComponent extends React.Component<Props, State> {
|
||||
newVisiblePropertyIds = [...activeView.visiblePropertyIds, id]
|
||||
}
|
||||
await mutator.changeViewVisibleProperties(activeView, newVisiblePropertyIds)
|
||||
};
|
||||
}
|
||||
OldMenu.shared.showAtElement(e.target as HTMLElement)
|
||||
}
|
||||
|
||||
@ -513,14 +513,14 @@ class BoardComponent extends React.Component<Props, State> {
|
||||
const selectProperties = boardTree.board.cardProperties.filter((o) => o.type === 'select')
|
||||
OldMenu.shared.options = selectProperties.map((o) => {
|
||||
return {id: o.id, name: o.name}
|
||||
});
|
||||
})
|
||||
OldMenu.shared.onMenuClicked = async (command: string) => {
|
||||
if (boardTree.activeView.groupById === command) {
|
||||
return
|
||||
}
|
||||
|
||||
await mutator.changeViewGroupById(boardTree.activeView, command)
|
||||
};
|
||||
}
|
||||
OldMenu.shared.showAtElement(e.target as HTMLElement)
|
||||
}
|
||||
|
||||
@ -567,7 +567,7 @@ class BoardComponent extends React.Component<Props, State> {
|
||||
|
||||
onSearchKeyDown(e: React.KeyboardEvent) {
|
||||
if (e.keyCode === 27) { // ESC: Clear search
|
||||
this.searchFieldRef.current.text = '';
|
||||
this.searchFieldRef.current.text = ''
|
||||
this.setState({...this.state, isSearching: false})
|
||||
this.props.setSearchText(undefined)
|
||||
e.preventDefault()
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import './button.scss';
|
||||
import './button.scss'
|
||||
|
||||
type Props = {
|
||||
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void
|
||||
|
@ -1,24 +1,24 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {BlockIcons} from '../blockIcons';
|
||||
import {Block} from '../blocks/block';
|
||||
import {Card} from '../blocks/card';
|
||||
import {TextBlock} from '../blocks/textBlock';
|
||||
import {BoardTree} from '../boardTree';
|
||||
import {CardTree} from '../cardTree';
|
||||
import {Menu as OldMenu, MenuOption} from '../menu';
|
||||
import mutator from '../mutator';
|
||||
import {OctoListener} from '../octoListener';
|
||||
import {IBlock, IOrderedBlock} from '../octoTypes';
|
||||
import {OctoUtils} from '../octoUtils';
|
||||
import {PropertyMenu} from '../propertyMenu';
|
||||
import {Utils} from '../utils';
|
||||
import {BlockIcons} from '../blockIcons'
|
||||
import {Block} from '../blocks/block'
|
||||
import {Card} from '../blocks/card'
|
||||
import {TextBlock} from '../blocks/textBlock'
|
||||
import {BoardTree} from '../boardTree'
|
||||
import {CardTree} from '../cardTree'
|
||||
import {Menu as OldMenu, MenuOption} from '../menu'
|
||||
import mutator from '../mutator'
|
||||
import {OctoListener} from '../octoListener'
|
||||
import {IBlock, IOrderedBlock} from '../octoTypes'
|
||||
import {OctoUtils} from '../octoUtils'
|
||||
import {PropertyMenu} from '../propertyMenu'
|
||||
import {Utils} from '../utils'
|
||||
|
||||
import Button from './button';
|
||||
import {Editable} from './editable';
|
||||
import {MarkdownEditor} from './markdownEditor';
|
||||
import Button from './button'
|
||||
import {Editable} from './editable'
|
||||
import {MarkdownEditor} from './markdownEditor'
|
||||
|
||||
type Props = {
|
||||
boardTree: BoardTree
|
||||
@ -45,7 +45,7 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
this.cardListener.open(this.props.card.id, async () => {
|
||||
await cardTree.sync()
|
||||
this.setState({cardTree})
|
||||
});
|
||||
})
|
||||
const cardTree = new CardTree(this.props.card.id)
|
||||
cardTree.sync().then(() => {
|
||||
this.setState({cardTree})
|
||||
@ -54,7 +54,7 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
this.titleRef.current.focus()
|
||||
}
|
||||
}, 0)
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -66,7 +66,7 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
}
|
||||
const {comments} = cardTree
|
||||
|
||||
const newCommentPlaceholderText = 'Add a comment...';
|
||||
const newCommentPlaceholderText = 'Add a comment...'
|
||||
|
||||
const backgroundRef = React.createRef<HTMLDivElement>()
|
||||
const newCommentRef = React.createRef<Editable>()
|
||||
@ -145,8 +145,8 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
const icon = card.icon
|
||||
|
||||
// TODO: Replace this placeholder
|
||||
const username = 'John Smith';
|
||||
const userImageUrl = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="fill: rgb(192, 192, 192);"><rect width="100" height="100" /></svg>';
|
||||
const username = 'John Smith'
|
||||
const userImageUrl = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" style="fill: rgb(192, 192, 192);"><rect width="100" height="100" /></svg>'
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -205,28 +205,28 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
menu.onNameChanged = (propertyName) => {
|
||||
Utils.log('menu.onNameChanged')
|
||||
mutator.renameProperty(board, propertyTemplate.id, propertyName)
|
||||
};
|
||||
}
|
||||
|
||||
menu.onMenuClicked = async (command) => {
|
||||
switch (command) {
|
||||
case 'type-text':
|
||||
await mutator.changePropertyType(board, propertyTemplate, 'text')
|
||||
break;
|
||||
break
|
||||
case 'type-number':
|
||||
await mutator.changePropertyType(board, propertyTemplate, 'number')
|
||||
break;
|
||||
break
|
||||
case 'type-createdTime':
|
||||
await mutator.changePropertyType(board, propertyTemplate, 'createdTime')
|
||||
break;
|
||||
break
|
||||
case 'type-updatedTime':
|
||||
await mutator.changePropertyType(board, propertyTemplate, 'updatedTime')
|
||||
break;
|
||||
break
|
||||
case 'type-select':
|
||||
await mutator.changePropertyType(board, propertyTemplate, 'select')
|
||||
break;
|
||||
break
|
||||
case 'delete':
|
||||
await mutator.deleteProperty(boardTree, propertyTemplate.id)
|
||||
break;
|
||||
break
|
||||
default:
|
||||
Utils.assertFailure(`Unhandled menu id: ${command}`)
|
||||
}
|
||||
@ -263,12 +263,12 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
switch (id) {
|
||||
case 'delete': {
|
||||
mutator.deleteBlock(activeComment)
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
OldMenu.shared.showAtElement(e.target as HTMLElement)
|
||||
};
|
||||
}
|
||||
|
||||
return (<div
|
||||
key={comment.id}
|
||||
@ -277,7 +277,7 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
optionsButtonRef.current.style.display = null
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
optionsButtonRef.current.style.display = 'none';
|
||||
optionsButtonRef.current.style.display = 'none'
|
||||
}}
|
||||
>
|
||||
<div className='comment-header'>
|
||||
@ -317,7 +317,7 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
}}
|
||||
onBlur={() => {
|
||||
if (!newCommentRef.current.text) {
|
||||
sendCommentButtonRef.current.style.display = 'none';
|
||||
sendCommentButtonRef.current.style.display = 'none'
|
||||
}
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
@ -366,14 +366,14 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
const order = cardTree.contents.length * 1000
|
||||
const block = new Block({type: 'text', parentId: card.id, order})
|
||||
await mutator.insertBlock(block, 'add text')
|
||||
break;
|
||||
break
|
||||
case 'image':
|
||||
Utils.selectLocalFile(
|
||||
(file) => {
|
||||
mutator.createImageBlock(card.id, file, cardTree.contents.length * 1000)
|
||||
},
|
||||
'.jpg,.jpeg,.png')
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
OldMenu.shared.showAtElement(e.target as HTMLElement)
|
||||
@ -427,7 +427,7 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
const newOrder = OctoUtils.getOrderBefore(previousBlock, cardTree.contents)
|
||||
Utils.log(`moveUp ${newOrder}`)
|
||||
mutator.changeOrder(block, newOrder, 'move up')
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'moveDown': {
|
||||
if (index >= cardTree.contents.length - 1) {
|
||||
@ -437,7 +437,7 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
const newOrder = OctoUtils.getOrderAfter(nextBlock, cardTree.contents)
|
||||
Utils.log(`moveDown ${newOrder}`)
|
||||
mutator.changeOrder(block, newOrder, 'move down')
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'insertAbove-text': {
|
||||
const newBlock = new TextBlock({parentId: card.id})
|
||||
@ -446,7 +446,7 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
newBlock.order = OctoUtils.getOrderBefore(block, cardTree.contents)
|
||||
Utils.log(`insert block ${block.id}, order: ${block.order}`)
|
||||
mutator.insertBlock(newBlock, 'insert card text')
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'insertAbove-image': {
|
||||
Utils.selectLocalFile(
|
||||
@ -455,11 +455,11 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
},
|
||||
'.jpg,.jpeg,.png')
|
||||
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'delete': {
|
||||
mutator.deleteBlock(block)
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -477,11 +477,11 @@ export default class CardDetail extends React.Component<Props, State> {
|
||||
switch (optionId) {
|
||||
case 'remove':
|
||||
mutator.changeIcon(card, undefined, 'remove icon')
|
||||
break;
|
||||
break
|
||||
case 'random':
|
||||
const newIcon = BlockIcons.shared.randomIcon()
|
||||
mutator.changeIcon(card, newIcon)
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
OldMenu.shared.showAtElement(e.target as HTMLElement)
|
||||
|
@ -1,14 +1,14 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {Card} from '../blocks/card';
|
||||
import {BoardTree} from '../boardTree';
|
||||
import mutator from '../mutator';
|
||||
import Menu from '../widgets/menu';
|
||||
import {Card} from '../blocks/card'
|
||||
import {BoardTree} from '../boardTree'
|
||||
import mutator from '../mutator'
|
||||
import Menu from '../widgets/menu'
|
||||
|
||||
import CardDetail from './cardDetail';
|
||||
import Dialog from './dialog';
|
||||
import CardDetail from './cardDetail'
|
||||
import Dialog from './dialog'
|
||||
|
||||
type Props = {
|
||||
boardTree: BoardTree
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import MenuWrapper from '../widgets/menuWrapper';
|
||||
import MenuWrapper from '../widgets/menuWrapper'
|
||||
|
||||
import Button from './button';
|
||||
import Button from './button'
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {Utils} from '../utils';
|
||||
import {Utils} from '../utils'
|
||||
|
||||
type Props = {
|
||||
onChanged: (text: string) => void
|
||||
@ -36,23 +36,23 @@ class Editable extends React.Component<Props, State> {
|
||||
const {isMarkdown} = this.props
|
||||
|
||||
if (!value) {
|
||||
this.elementRef.current.innerText = '';
|
||||
this.elementRef.current.innerText = ''
|
||||
} else {
|
||||
this.elementRef.current.innerHTML = isMarkdown ? Utils.htmlFromMarkdown(value) : Utils.htmlEncode(value)
|
||||
}
|
||||
|
||||
this._text = value || '';
|
||||
this._text = value || ''
|
||||
}
|
||||
|
||||
private elementRef = React.createRef<HTMLDivElement>()
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
this._text = props.text || '';
|
||||
this._text = props.text || ''
|
||||
}
|
||||
|
||||
componentDidUpdate(prevPros: Props, prevState: State) {
|
||||
this._text = this.props.text || '';
|
||||
this._text = this.props.text || ''
|
||||
}
|
||||
|
||||
focus() {
|
||||
@ -76,7 +76,7 @@ class Editable extends React.Component<Props, State> {
|
||||
if (text) {
|
||||
html = isMarkdown ? Utils.htmlFromMarkdown(text) : Utils.htmlEncode(text)
|
||||
} else {
|
||||
html = '';
|
||||
html = ''
|
||||
}
|
||||
|
||||
const element =
|
||||
@ -102,7 +102,7 @@ class Editable extends React.Component<Props, State> {
|
||||
|
||||
onBlur={async () => {
|
||||
const newText = this.elementRef.current.innerText
|
||||
const oldText = this.props.text || '';
|
||||
const oldText = this.props.text || ''
|
||||
if (newText !== oldText && onChanged) {
|
||||
onChanged(newText)
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {BoardTree} from '../boardTree';
|
||||
import {FilterClause, FilterCondition} from '../filterClause';
|
||||
import {FilterGroup} from '../filterGroup';
|
||||
import {Menu} from '../menu';
|
||||
import mutator from '../mutator';
|
||||
import {Utils} from '../utils';
|
||||
import {BoardTree} from '../boardTree'
|
||||
import {FilterClause, FilterCondition} from '../filterClause'
|
||||
import {FilterGroup} from '../filterGroup'
|
||||
import {Menu} from '../menu'
|
||||
import mutator from '../mutator'
|
||||
import {Utils} from '../utils'
|
||||
|
||||
type Props = {
|
||||
boardTree: BoardTree
|
||||
@ -42,7 +42,7 @@ class FilterComponent extends React.Component<Props> {
|
||||
>
|
||||
{filters.map((filter) => {
|
||||
const template = board.cardProperties.find((o) => o.id === filter.propertyId)
|
||||
const propertyName = template ? template.name : '(unknown)'; // TODO: Handle error
|
||||
const propertyName = template ? template.name : '(unknown)' // TODO: Handle error
|
||||
const key = `${filter.propertyId}-${filter.condition}-${filter.values.join(',')}`
|
||||
Utils.log(`FilterClause key: ${key}`)
|
||||
return (<div
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import EasyMDE from 'easymde';
|
||||
import React from 'react';
|
||||
import SimpleMDE from 'react-simplemde-editor';
|
||||
import EasyMDE from 'easymde'
|
||||
import React from 'react'
|
||||
import SimpleMDE from 'react-simplemde-editor'
|
||||
|
||||
import {Utils} from '../utils';
|
||||
import {Utils} from '../utils'
|
||||
|
||||
type Props = {
|
||||
onChanged: (text: string) => void
|
||||
@ -43,7 +43,7 @@ class MarkdownEditor extends React.Component<Props, State> {
|
||||
}
|
||||
|
||||
componentDidUpdate(prevPros: Props, prevState: State) {
|
||||
this.text = this.props.text || '';
|
||||
this.text = this.props.text || ''
|
||||
}
|
||||
|
||||
showEditor() {
|
||||
@ -123,7 +123,7 @@ class MarkdownEditor extends React.Component<Props, State> {
|
||||
events={{
|
||||
blur: () => {
|
||||
const newText = this.elementRef.current.state.value
|
||||
const oldText = this.props.text || '';
|
||||
const oldText = this.props.text || ''
|
||||
if (newText !== oldText && onChanged) {
|
||||
const newHtml = newText ? Utils.htmlFromMarkdown(newText) : Utils.htmlFromMarkdown(placeholderText || '')
|
||||
this.previewRef.current.innerHTML = newHtml
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
}
|
||||
|
@ -1,21 +1,21 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import {render} from '@testing-library/react';
|
||||
import '@testing-library/jest-dom';
|
||||
import React from 'react'
|
||||
import {render} from '@testing-library/react'
|
||||
import '@testing-library/jest-dom'
|
||||
|
||||
import RootPortal from './rootPortal';
|
||||
import RootPortal from './rootPortal'
|
||||
|
||||
describe('components/RootPortal', () => {
|
||||
beforeEach(() => {
|
||||
// Quick fix to disregard console error when unmounting a component
|
||||
console.error = jest.fn()
|
||||
});
|
||||
})
|
||||
|
||||
test('should match snapshot', () => {
|
||||
const rootPortalDiv = document.createElement('div')
|
||||
rootPortalDiv.id = 'root-portal';
|
||||
rootPortalDiv.id = 'root-portal'
|
||||
|
||||
const {getByText, container} = render(
|
||||
<RootPortal>
|
||||
@ -26,5 +26,5 @@ describe('components/RootPortal', () => {
|
||||
|
||||
expect(getByText('Testing Portal')).toBeVisible()
|
||||
expect(container).toMatchSnapshot()
|
||||
});
|
||||
})
|
||||
})
|
||||
|
@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import PropTypes from 'prop-types'
|
||||
|
||||
type Props = {
|
||||
children: React.ReactNode
|
||||
|
@ -1,14 +1,14 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {Archiver} from '../archiver';
|
||||
import {Board} from '../blocks/board';
|
||||
import {BoardTree} from '../boardTree';
|
||||
import Menu from '../widgets/menu';
|
||||
import MenuWrapper from '../widgets/menuWrapper';
|
||||
import mutator from '../mutator';
|
||||
import {WorkspaceTree} from '../workspaceTree';
|
||||
import {Archiver} from '../archiver'
|
||||
import {Board} from '../blocks/board'
|
||||
import {BoardTree} from '../boardTree'
|
||||
import Menu from '../widgets/menu'
|
||||
import MenuWrapper from '../widgets/menuWrapper'
|
||||
import mutator from '../mutator'
|
||||
import {WorkspaceTree} from '../workspaceTree'
|
||||
|
||||
type Props = {
|
||||
showBoard: (id: string) => void
|
||||
@ -29,7 +29,7 @@ class Sidebar extends React.Component<Props> {
|
||||
<div className='octo-sidebar'>
|
||||
{
|
||||
boards.map((board) => {
|
||||
const displayTitle = board.title || '(Untitled Board)';
|
||||
const displayTitle = board.title || '(Untitled Board)'
|
||||
return (
|
||||
<div
|
||||
key={board.id}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
onChanged: (isOn: boolean) => void
|
||||
@ -39,7 +39,7 @@ class Switch extends React.Component<Props, State> {
|
||||
const {style} = this.props
|
||||
const {isOn} = this.state
|
||||
|
||||
const className = isOn ? 'octo-switch on' : 'octo-switch';
|
||||
const className = isOn ? 'octo-switch on' : 'octo-switch'
|
||||
const element =
|
||||
(<div
|
||||
ref={this.elementRef}
|
||||
|
@ -1,26 +1,26 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {Archiver} from '../archiver';
|
||||
import {BlockIcons} from '../blockIcons';
|
||||
import {IPropertyTemplate} from '../blocks/board';
|
||||
import {Card} from '../blocks/card';
|
||||
import {BoardTree} from '../boardTree';
|
||||
import ViewMenu from '../components/viewMenu';
|
||||
import {CsvExporter} from '../csvExporter';
|
||||
import {Menu as OldMenu} from '../menu';
|
||||
import mutator from '../mutator';
|
||||
import {OctoUtils} from '../octoUtils';
|
||||
import {Utils} from '../utils';
|
||||
import Menu from '../widgets/menu';
|
||||
import MenuWrapper from '../widgets/menuWrapper';
|
||||
import {Archiver} from '../archiver'
|
||||
import {BlockIcons} from '../blockIcons'
|
||||
import {IPropertyTemplate} from '../blocks/board'
|
||||
import {Card} from '../blocks/card'
|
||||
import {BoardTree} from '../boardTree'
|
||||
import ViewMenu from '../components/viewMenu'
|
||||
import {CsvExporter} from '../csvExporter'
|
||||
import {Menu as OldMenu} from '../menu'
|
||||
import mutator from '../mutator'
|
||||
import {OctoUtils} from '../octoUtils'
|
||||
import {Utils} from '../utils'
|
||||
import Menu from '../widgets/menu'
|
||||
import MenuWrapper from '../widgets/menuWrapper'
|
||||
|
||||
import Button from './button';
|
||||
import {CardDialog} from './cardDialog';
|
||||
import {Editable} from './editable';
|
||||
import RootPortal from './rootPortal';
|
||||
import {TableRow} from './tableRow';
|
||||
import Button from './button'
|
||||
import {CardDialog} from './cardDialog'
|
||||
import {Editable} from './editable'
|
||||
import RootPortal from './rootPortal'
|
||||
import {TableRow} from './tableRow'
|
||||
|
||||
type Props = {
|
||||
boardTree?: BoardTree
|
||||
@ -322,7 +322,7 @@ class TableComponent extends React.Component<Props, State> {
|
||||
OldMenu.shared.options = selectProperties.map((o) => {
|
||||
const isVisible = activeView.visiblePropertyIds.includes(o.id)
|
||||
return {id: o.id, name: o.name, type: 'switch', isOn: isVisible}
|
||||
});
|
||||
})
|
||||
|
||||
OldMenu.shared.onMenuToggled = async (id: string, isOn: boolean) => {
|
||||
const property = selectProperties.find((o) => o.id === id)
|
||||
@ -336,7 +336,7 @@ class TableComponent extends React.Component<Props, State> {
|
||||
newVisiblePropertyIds = [...activeView.visiblePropertyIds, id]
|
||||
}
|
||||
await mutator.changeViewVisibleProperties(activeView, newVisiblePropertyIds)
|
||||
};
|
||||
}
|
||||
OldMenu.shared.showAtElement(e.target as HTMLElement)
|
||||
}
|
||||
|
||||
@ -356,11 +356,11 @@ class TableComponent extends React.Component<Props, State> {
|
||||
switch (id) {
|
||||
case 'exportCsv': {
|
||||
CsvExporter.exportTableCsv(boardTree)
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'exportBoardArchive': {
|
||||
Archiver.exportBoardTree(boardTree)
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -393,14 +393,14 @@ class TableComponent extends React.Component<Props, State> {
|
||||
{propertyId: templateId, reversed: false},
|
||||
]
|
||||
await mutator.changeViewSortOptions(activeView, newSortOptions)
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'sortDescending': {
|
||||
const newSortOptions = [
|
||||
{propertyId: templateId, reversed: true},
|
||||
]
|
||||
await mutator.changeViewSortOptions(activeView, newSortOptions)
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'insertLeft': {
|
||||
if (templateId !== '__name') {
|
||||
@ -422,20 +422,20 @@ class TableComponent extends React.Component<Props, State> {
|
||||
}
|
||||
case 'duplicate': {
|
||||
await mutator.duplicatePropertyTemplate(boardTree, templateId)
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'hide': {
|
||||
const newVisiblePropertyIds = activeView.visiblePropertyIds.filter((o) => o !== templateId)
|
||||
await mutator.changeViewVisibleProperties(activeView, newVisiblePropertyIds)
|
||||
break;
|
||||
break
|
||||
}
|
||||
case 'delete': {
|
||||
await mutator.deleteProperty(boardTree, templateId)
|
||||
break;
|
||||
break
|
||||
}
|
||||
default: {
|
||||
Utils.assertFailure(`Unexpected menu option: ${optionId}`)
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -489,7 +489,7 @@ class TableComponent extends React.Component<Props, State> {
|
||||
|
||||
onSearchKeyDown(e: React.KeyboardEvent) {
|
||||
if (e.keyCode === 27) { // ESC: Clear search
|
||||
this.searchFieldRef.current.text = '';
|
||||
this.searchFieldRef.current.text = ''
|
||||
this.setState({...this.state, isSearching: false})
|
||||
this.props.setSearchText(undefined)
|
||||
e.preventDefault()
|
||||
|
@ -1,15 +1,15 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {BoardTree} from '../boardTree';
|
||||
import {Card} from '../blocks/card';
|
||||
import mutator from '../mutator';
|
||||
import {OctoUtils} from '../octoUtils';
|
||||
import {BoardTree} from '../boardTree'
|
||||
import {Card} from '../blocks/card'
|
||||
import mutator from '../mutator'
|
||||
import {OctoUtils} from '../octoUtils'
|
||||
|
||||
import {Editable} from './editable';
|
||||
import {CardDialog} from './cardDialog';
|
||||
import RootPortal from './rootPortal';
|
||||
import {Editable} from './editable'
|
||||
import {CardDialog} from './cardDialog'
|
||||
import RootPortal from './rootPortal'
|
||||
|
||||
type Props = {
|
||||
boardTree: BoardTree
|
||||
@ -54,7 +54,7 @@ class TableRow extends React.Component<Props, State> {
|
||||
openButonRef.current.style.display = null
|
||||
}}
|
||||
onMouseLeave={() => {
|
||||
openButonRef.current.style.display = 'none';
|
||||
openButonRef.current.style.display = 'none'
|
||||
}}
|
||||
>
|
||||
<div className='octo-icontitle'>
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {Board} from '../blocks/board';
|
||||
import {BoardView} from '../blocks/boardView';
|
||||
import {BoardTree} from '../boardTree';
|
||||
import mutator from '../mutator';
|
||||
import {Utils} from '../utils';
|
||||
import Menu from '../widgets/menu';
|
||||
import {Board} from '../blocks/board'
|
||||
import {BoardView} from '../blocks/boardView'
|
||||
import {BoardTree} from '../boardTree'
|
||||
import mutator from '../mutator'
|
||||
import {Utils} from '../utils'
|
||||
import Menu from '../widgets/menu'
|
||||
|
||||
type Props = {
|
||||
boardTree?: BoardTree
|
||||
@ -36,8 +36,8 @@ export default class ViewMenu extends React.Component<Props> {
|
||||
const {board, boardTree, showView} = this.props
|
||||
Utils.log('addview-board')
|
||||
const view = new BoardView()
|
||||
view.title = 'Board View';
|
||||
view.viewType = 'board';
|
||||
view.title = 'Board View'
|
||||
view.viewType = 'board'
|
||||
view.parentId = board.id
|
||||
|
||||
const oldViewId = boardTree.activeView.id
|
||||
@ -50,7 +50,7 @@ export default class ViewMenu extends React.Component<Props> {
|
||||
},
|
||||
async () => {
|
||||
showView(oldViewId)
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
handleAddViewTable = async (id: string) => {
|
||||
@ -58,8 +58,8 @@ export default class ViewMenu extends React.Component<Props> {
|
||||
|
||||
Utils.log('addview-table')
|
||||
const view = new BoardView()
|
||||
view.title = 'Table View';
|
||||
view.viewType = 'table';
|
||||
view.title = 'Table View'
|
||||
view.viewType = 'table'
|
||||
view.parentId = board.id
|
||||
view.visiblePropertyIds = board.cardProperties.map((o) => o.id)
|
||||
|
||||
@ -73,7 +73,7 @@ export default class ViewMenu extends React.Component<Props> {
|
||||
},
|
||||
async () => {
|
||||
showView(oldViewId)
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -1,14 +1,14 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {BoardTree} from '../boardTree';
|
||||
import {Utils} from '../utils';
|
||||
import {WorkspaceTree} from '../workspaceTree';
|
||||
import {BoardTree} from '../boardTree'
|
||||
import {Utils} from '../utils'
|
||||
import {WorkspaceTree} from '../workspaceTree'
|
||||
|
||||
import {BoardComponent} from './boardComponent';
|
||||
import {Sidebar} from './sidebar';
|
||||
import {TableComponent} from './tableComponent';
|
||||
import {BoardComponent} from './boardComponent'
|
||||
import {Sidebar} from './sidebar'
|
||||
import {TableComponent} from './tableComponent'
|
||||
|
||||
type Props = {
|
||||
workspaceTree: WorkspaceTree
|
||||
@ -52,7 +52,7 @@ class WorkspaceComponent extends React.Component<Props> {
|
||||
showFilter={showFilter}
|
||||
setSearchText={setSearchText}
|
||||
showView={showView}
|
||||
/>);
|
||||
/>)
|
||||
}
|
||||
|
||||
case 'table': {
|
||||
@ -61,7 +61,7 @@ class WorkspaceComponent extends React.Component<Props> {
|
||||
showFilter={showFilter}
|
||||
setSearchText={setSearchText}
|
||||
showView={showView}
|
||||
/>);
|
||||
/>)
|
||||
}
|
||||
|
||||
default: {
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {MenuOption} from './menu';
|
||||
import {MenuOption} from './menu'
|
||||
|
||||
class Constants {
|
||||
static menuColors: MenuOption[] = [
|
||||
|
@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {BoardView} from './blocks/boardView';
|
||||
import {BoardTree} from './boardTree';
|
||||
import {OctoUtils} from './octoUtils';
|
||||
import {Utils} from './utils';
|
||||
import {BoardView} from './blocks/boardView'
|
||||
import {BoardTree} from './boardTree'
|
||||
import {OctoUtils} from './octoUtils'
|
||||
import {Utils} from './utils'
|
||||
|
||||
class CsvExporter {
|
||||
static exportTableCsv(boardTree: BoardTree, view?: BoardView) {
|
||||
@ -12,17 +12,17 @@ class CsvExporter {
|
||||
|
||||
const rows = CsvExporter.generateTableArray(boardTree, view)
|
||||
|
||||
let csvContent = 'data:text/csv;charset=utf-8,';
|
||||
let csvContent = 'data:text/csv;charset=utf-8,'
|
||||
|
||||
rows.forEach((row) => {
|
||||
const encodedRow = row.join(',')
|
||||
csvContent += encodedRow + '\r\n';
|
||||
csvContent += encodedRow + '\r\n'
|
||||
})
|
||||
|
||||
const filename = `${Utils.sanitizeFilename(viewToExport.title)}.csv`
|
||||
const encodedUri = encodeURI(csvContent)
|
||||
const link = document.createElement('a')
|
||||
link.style.display = 'none';
|
||||
link.style.display = 'none'
|
||||
link.setAttribute('href', encodedUri)
|
||||
link.setAttribute('download', filename)
|
||||
document.body.appendChild(link) // FireFox support
|
||||
@ -44,7 +44,7 @@ class CsvExporter {
|
||||
const row: string[] = []
|
||||
visibleProperties.forEach((template) => {
|
||||
row.push(template.name)
|
||||
});
|
||||
})
|
||||
rows.push(row)
|
||||
}
|
||||
|
||||
@ -52,7 +52,7 @@ class CsvExporter {
|
||||
const row: string[] = []
|
||||
visibleProperties.forEach((template) => {
|
||||
const propertyValue = card.properties[template.id]
|
||||
const displayValue = OctoUtils.propertyDisplayValue(card, propertyValue, template) || '';
|
||||
const displayValue = OctoUtils.propertyDisplayValue(card, propertyValue, template) || ''
|
||||
if (template.type === 'number') {
|
||||
const numericValue = propertyValue ? Number(propertyValue).toString() : undefined
|
||||
row.push(numericValue)
|
||||
@ -62,7 +62,7 @@ class CsvExporter {
|
||||
}
|
||||
})
|
||||
rows.push(row)
|
||||
});
|
||||
})
|
||||
|
||||
return rows
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Utils} from './utils';
|
||||
import {Utils} from './utils'
|
||||
|
||||
type FilterCondition = 'includes' | 'notIncludes' | 'isEmpty' | 'isNotEmpty'
|
||||
|
||||
@ -11,20 +11,20 @@ class FilterClause {
|
||||
|
||||
static filterConditionDisplayString(filterCondition: FilterCondition) {
|
||||
switch (filterCondition) {
|
||||
case 'includes': return 'includes';
|
||||
case 'includes': return 'includes'
|
||||
case 'notIncludes': return "doesn't include"
|
||||
case 'isEmpty': return 'is empty';
|
||||
case 'isNotEmpty': return 'is not empty';
|
||||
case 'isEmpty': return 'is empty'
|
||||
case 'isNotEmpty': return 'is not empty'
|
||||
default: {
|
||||
Utils.assertFailure()
|
||||
return '(unknown)';
|
||||
return '(unknown)'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
constructor(o: any = {}) {
|
||||
this.propertyId = o.propertyId || '';
|
||||
this.condition = o.condition || 'includes';
|
||||
this.propertyId = o.propertyId || ''
|
||||
this.condition = o.condition || 'includes'
|
||||
this.values = o.values?.slice() || []
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {FilterClause} from './filterClause';
|
||||
import {FilterClause} from './filterClause'
|
||||
|
||||
type FilterGroupOperation = 'and' | 'or'
|
||||
|
||||
@ -14,7 +14,7 @@ class FilterGroup {
|
||||
}
|
||||
|
||||
constructor(o: any = {}) {
|
||||
this.operation = o.operation || 'and';
|
||||
this.operation = o.operation || 'and'
|
||||
this.filters = o.filters ?
|
||||
o.filters.map((p: any) => {
|
||||
if (FilterGroup.isAnInstanceOf(p)) {
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
import App from './app';
|
||||
import App from './app'
|
||||
|
||||
ReactDOM.render(<App/>, document.getElementById('octo-tasks-app'))
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Utils} from './utils';
|
||||
import {Utils} from './utils'
|
||||
|
||||
type MenuOption = {
|
||||
id: string,
|
||||
@ -56,7 +56,7 @@ class Menu {
|
||||
const bodyRect = document.body.getBoundingClientRect()
|
||||
const rect = optionElement.getBoundingClientRect()
|
||||
this.showSubMenu(rect.right - bodyRect.left, rect.top - bodyRect.top, option.id)
|
||||
};
|
||||
}
|
||||
} else {
|
||||
if (option.icon) {
|
||||
let iconName: string
|
||||
@ -73,7 +73,7 @@ class Menu {
|
||||
|
||||
optionElement.onmouseenter = () => {
|
||||
this.hideSubMenu()
|
||||
};
|
||||
}
|
||||
optionElement.onclick = (e) => {
|
||||
if (this.onMenuClicked) {
|
||||
this.onMenuClicked(option.id, option.type)
|
||||
@ -81,14 +81,14 @@ class Menu {
|
||||
this.hide()
|
||||
e.stopPropagation()
|
||||
return false
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (option.type === 'color') {
|
||||
const colorbox = optionElement.insertBefore(Utils.htmlToElement('<div class="menu-colorbox"></div>'), optionElement.firstChild)
|
||||
colorbox.classList.add(option.id) // id is the css class name for the color
|
||||
} else if (option.type === 'switch') {
|
||||
const className = option.isOn ? 'octo-switch on' : 'octo-switch';
|
||||
const className = option.isOn ? 'octo-switch on' : 'octo-switch'
|
||||
const switchElement = optionElement.appendChild(Utils.htmlToElement(`<div class="${className}"></div>`))
|
||||
switchElement.appendChild(Utils.htmlToElement('<div class="octo-switch-inner"></div>'))
|
||||
switchElement.onclick = (e) => {
|
||||
@ -104,7 +104,7 @@ class Menu {
|
||||
}
|
||||
e.stopPropagation()
|
||||
return false
|
||||
};
|
||||
}
|
||||
optionElement.onclick = null
|
||||
}
|
||||
}
|
||||
@ -132,7 +132,7 @@ class Menu {
|
||||
this.onBodyClick = (e: MouseEvent) => {
|
||||
console.log('onBodyClick')
|
||||
this.hide()
|
||||
};
|
||||
}
|
||||
|
||||
this.onBodyKeyDown = (e: KeyboardEvent) => {
|
||||
console.log(`onBodyKeyDown, target: ${e.target}`)
|
||||
@ -199,7 +199,7 @@ class Menu {
|
||||
this.onMenuClicked(subMenuId, type)
|
||||
}
|
||||
this.hide()
|
||||
};
|
||||
}
|
||||
|
||||
this.subMenu.options = options
|
||||
this.subMenu.showAt(pageX, pageY)
|
||||
|
@ -1,16 +1,16 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Block} from './blocks/block';
|
||||
import {Board, IPropertyOption, IPropertyTemplate, PropertyType} from './blocks/board';
|
||||
import {BoardView, ISortOption} from './blocks/boardView';
|
||||
import {Card} from './blocks/card';
|
||||
import {ImageBlock} from './blocks/imageBlock';
|
||||
import {BoardTree} from './boardTree';
|
||||
import {FilterGroup} from './filterGroup';
|
||||
import octoClient from './octoClient';
|
||||
import {IBlock, IOrderedBlock} from './octoTypes';
|
||||
import undoManager from './undomanager';
|
||||
import {Utils} from './utils';
|
||||
import {Block} from './blocks/block'
|
||||
import {Board, IPropertyOption, IPropertyTemplate, PropertyType} from './blocks/board'
|
||||
import {BoardView, ISortOption} from './blocks/boardView'
|
||||
import {Card} from './blocks/card'
|
||||
import {ImageBlock} from './blocks/imageBlock'
|
||||
import {BoardTree} from './boardTree'
|
||||
import {FilterGroup} from './filterGroup'
|
||||
import octoClient from './octoClient'
|
||||
import {IBlock, IOrderedBlock} from './octoTypes'
|
||||
import undoManager from './undomanager'
|
||||
import {Utils} from './utils'
|
||||
|
||||
//
|
||||
// The Mutator is used to make all changes to server state
|
||||
@ -133,14 +133,14 @@ class Mutator {
|
||||
const changedBlocks: IBlock[] = [board]
|
||||
board.cardProperties.splice(index, 0, template)
|
||||
|
||||
let description = 'add property';
|
||||
let description = 'add property'
|
||||
|
||||
if (activeView.viewType === 'table') {
|
||||
oldBlocks.push(new BoardView(activeView))
|
||||
activeView.visiblePropertyIds.push(template.id)
|
||||
changedBlocks.push(activeView)
|
||||
|
||||
description = 'add column';
|
||||
description = 'add column'
|
||||
}
|
||||
|
||||
await undoManager.perform(
|
||||
@ -173,13 +173,13 @@ class Mutator {
|
||||
}
|
||||
board.cardProperties.splice(index + 1, 0, newTemplate)
|
||||
|
||||
let description = 'duplicate property';
|
||||
let description = 'duplicate property'
|
||||
if (activeView.viewType === 'table') {
|
||||
oldBlocks.push(new BoardView(activeView))
|
||||
activeView.visiblePropertyIds.push(newTemplate.id)
|
||||
changedBlocks.push(activeView)
|
||||
|
||||
description = 'duplicate column';
|
||||
description = 'duplicate column'
|
||||
}
|
||||
|
||||
await undoManager.perform(
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {IBlock} from './octoTypes';
|
||||
import {Utils} from './utils';
|
||||
import {IBlock} from './octoTypes'
|
||||
import {Utils} from './utils'
|
||||
|
||||
//
|
||||
// OctoClient is the client interface to the server APIs
|
||||
@ -23,7 +23,7 @@ class OctoClient {
|
||||
}
|
||||
|
||||
async exportFullArchive(): Promise<IBlock[]> {
|
||||
const path = '/api/v1/blocks/export';
|
||||
const path = '/api/v1/blocks/export'
|
||||
const response = await fetch(this.serverUrl + path)
|
||||
const blocks = (await response.json() || []) as IBlock[]
|
||||
this.fixBlocks(blocks)
|
||||
@ -34,7 +34,7 @@ class OctoClient {
|
||||
Utils.log(`importFullArchive: ${blocks.length} blocks(s)`)
|
||||
blocks.forEach((block) => {
|
||||
Utils.log(`\t ${block.type}, ${block.id}`)
|
||||
});
|
||||
})
|
||||
const body = JSON.stringify(blocks)
|
||||
return await fetch(this.serverUrl + '/api/v1/blocks/import', {
|
||||
method: 'POST',
|
||||
@ -55,7 +55,7 @@ class OctoClient {
|
||||
} else if (type) {
|
||||
path = `/api/v1/blocks?type=${encodeURIComponent(type)}`
|
||||
} else {
|
||||
path = '/api/v1/blocks';
|
||||
path = '/api/v1/blocks'
|
||||
}
|
||||
|
||||
const response = await fetch(this.serverUrl + path)
|
||||
@ -99,7 +99,7 @@ class OctoClient {
|
||||
const now = Date.now()
|
||||
blocks.forEach((block) => {
|
||||
block.updateAt = now
|
||||
});
|
||||
})
|
||||
return await this.insertBlocks(blocks)
|
||||
}
|
||||
|
||||
@ -122,7 +122,7 @@ class OctoClient {
|
||||
Utils.log(`insertBlocks: ${blocks.length} blocks(s)`)
|
||||
blocks.forEach((block) => {
|
||||
Utils.log(`\t ${block.type}, ${block.id}`)
|
||||
});
|
||||
})
|
||||
const body = JSON.stringify(blocks)
|
||||
return await fetch(this.serverUrl + '/api/v1/blocks', {
|
||||
method: 'POST',
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Utils} from './utils';
|
||||
import {Utils} from './utils'
|
||||
|
||||
//
|
||||
// OctoListener calls a handler when a block or any of its children changes
|
||||
@ -36,11 +36,11 @@ class OctoListener {
|
||||
ws.onopen = () => {
|
||||
Utils.log('OctoListener webSocket opened.')
|
||||
ws.send('{}')
|
||||
};
|
||||
}
|
||||
|
||||
ws.onerror = (e) => {
|
||||
Utils.logError(`OctoListener websocket onerror. data: ${e}`)
|
||||
};
|
||||
}
|
||||
|
||||
ws.onclose = (e) => {
|
||||
Utils.log(`OctoListener websocket onclose, code: ${e.code}, reason: ${e.reason}`)
|
||||
@ -64,7 +64,7 @@ class OctoListener {
|
||||
timeoutId = undefined
|
||||
onChange(message.blockId)
|
||||
}, this.notificationDelay)
|
||||
break;
|
||||
break
|
||||
default:
|
||||
Utils.logError(`Unexpected action: ${message.action}`)
|
||||
}
|
||||
|
@ -1,20 +1,20 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {Block} from './blocks/block';
|
||||
import {Board, IPropertyTemplate} from './blocks/board';
|
||||
import {BoardView, ISortOption} from './blocks/boardView';
|
||||
import {Card} from './blocks/card';
|
||||
import {CommentBlock} from './blocks/commentBlock';
|
||||
import {ImageBlock} from './blocks/imageBlock';
|
||||
import {TextBlock} from './blocks/textBlock';
|
||||
import {BoardTree} from './boardTree';
|
||||
import {Editable} from './components/editable';
|
||||
import {Menu} from './menu';
|
||||
import mutator from './mutator';
|
||||
import {IBlock, IOrderedBlock} from './octoTypes';
|
||||
import {Utils} from './utils';
|
||||
import {Block} from './blocks/block'
|
||||
import {Board, IPropertyTemplate} from './blocks/board'
|
||||
import {BoardView, ISortOption} from './blocks/boardView'
|
||||
import {Card} from './blocks/card'
|
||||
import {CommentBlock} from './blocks/commentBlock'
|
||||
import {ImageBlock} from './blocks/imageBlock'
|
||||
import {TextBlock} from './blocks/textBlock'
|
||||
import {BoardTree} from './boardTree'
|
||||
import {Editable} from './components/editable'
|
||||
import {Menu} from './menu'
|
||||
import mutator from './mutator'
|
||||
import {IBlock, IOrderedBlock} from './octoTypes'
|
||||
import {Utils} from './utils'
|
||||
|
||||
class OctoUtils {
|
||||
static propertyDisplayValue(block: IBlock, propertyValue: string | undefined, propertyTemplate: IPropertyTemplate) {
|
||||
@ -22,10 +22,10 @@ class OctoUtils {
|
||||
switch (propertyTemplate.type) {
|
||||
case 'createdTime':
|
||||
displayValue = Utils.displayDateTime(new Date(block.createAt))
|
||||
break;
|
||||
break
|
||||
case 'updatedTime':
|
||||
displayValue = Utils.displayDateTime(new Date(block.updateAt))
|
||||
break;
|
||||
break
|
||||
default:
|
||||
displayValue = propertyValue
|
||||
}
|
||||
@ -57,9 +57,9 @@ class OctoUtils {
|
||||
let element: JSX.Element
|
||||
|
||||
if (propertyTemplate.type === 'select') {
|
||||
let className = 'octo-button octo-propertyvalue';
|
||||
let className = 'octo-button octo-propertyvalue'
|
||||
if (!displayValue) {
|
||||
className += ' empty';
|
||||
className += ' empty'
|
||||
}
|
||||
|
||||
const showMenu = (clickedElement: HTMLElement) => {
|
||||
@ -72,9 +72,9 @@ class OctoUtils {
|
||||
menu.options.push(...propertyTemplate.options.map((o) => ({id: o.value, name: o.value})))
|
||||
menu.onMenuClicked = (optionId) => {
|
||||
mutator.changePropertyValue(card, propertyTemplate.id, optionId)
|
||||
};
|
||||
}
|
||||
menu.showAtElement(clickedElement)
|
||||
};
|
||||
}
|
||||
|
||||
element = (<div
|
||||
key={propertyTemplate.id}
|
||||
@ -151,7 +151,7 @@ class OctoUtils {
|
||||
name: o.name,
|
||||
icon: (sortOption?.propertyId === o.id) ? sortOption.reversed ? 'sortUp' : 'sortDown' : undefined,
|
||||
}
|
||||
});
|
||||
})
|
||||
Menu.shared.onMenuClicked = async (propertyId: string) => {
|
||||
let newSortOptions: ISortOption[] = []
|
||||
if (sortOption && sortOption.propertyId === propertyId) {
|
||||
@ -166,7 +166,7 @@ class OctoUtils {
|
||||
}
|
||||
|
||||
await mutator.changeViewSortOptions(activeView, newSortOptions)
|
||||
};
|
||||
}
|
||||
Menu.shared.showAtElement(e.target as HTMLElement)
|
||||
}
|
||||
|
||||
|
@ -1,18 +1,18 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
|
||||
import {BoardView} from '../blocks/boardView';
|
||||
import {BoardTree} from '../boardTree';
|
||||
import {CardTree} from '../cardTree';
|
||||
import {FilterComponent} from '../components/filterComponent';
|
||||
import {WorkspaceComponent} from '../components/workspaceComponent';
|
||||
import {FlashMessage} from '../flashMessage';
|
||||
import mutator from '../mutator';
|
||||
import {OctoListener} from '../octoListener';
|
||||
import {Utils} from '../utils';
|
||||
import {WorkspaceTree} from '../workspaceTree';
|
||||
import {BoardView} from '../blocks/boardView'
|
||||
import {BoardTree} from '../boardTree'
|
||||
import {CardTree} from '../cardTree'
|
||||
import {FilterComponent} from '../components/filterComponent'
|
||||
import {WorkspaceComponent} from '../components/workspaceComponent'
|
||||
import {FlashMessage} from '../flashMessage'
|
||||
import mutator from '../mutator'
|
||||
import {OctoListener} from '../octoListener'
|
||||
import {Utils} from '../utils'
|
||||
import {WorkspaceTree} from '../workspaceTree'
|
||||
|
||||
type Props = {
|
||||
}
|
||||
@ -166,7 +166,7 @@ export default class BoardPage extends React.Component<Props, State> {
|
||||
this.boardListener.open(boardId, (blockId: string) => {
|
||||
console.log(`octoListener.onChanged: ${blockId}`)
|
||||
this.sync(boardId)
|
||||
});
|
||||
})
|
||||
|
||||
this.sync(boardId, viewId)
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import {Archiver} from '../archiver';
|
||||
import {Board} from '../blocks/board';
|
||||
import Button from '../components/button';
|
||||
import octoClient from '../octoClient';
|
||||
import {IBlock} from '../octoTypes';
|
||||
import {Utils} from '../utils';
|
||||
import {Archiver} from '../archiver'
|
||||
import {Board} from '../blocks/board'
|
||||
import Button from '../components/button'
|
||||
import octoClient from '../octoClient'
|
||||
import {IBlock} from '../octoTypes'
|
||||
import {Utils} from '../utils'
|
||||
|
||||
type Props = {}
|
||||
|
||||
@ -35,7 +35,7 @@ export default class HomePage extends React.Component<Props, State> {
|
||||
importClicked = async () => {
|
||||
Archiver.importFullArchive(() => {
|
||||
this.loadBoards()
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
exportClicked = async () => {
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
import Button from '../components/button';
|
||||
import Button from '../components/button'
|
||||
|
||||
import './loginPage.scss';
|
||||
import './loginPage.scss'
|
||||
|
||||
type Props = {}
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {IPropertyTemplate, PropertyType} from './blocks/board';
|
||||
import {Menu} from './menu';
|
||||
import {Utils} from './utils';
|
||||
import {IPropertyTemplate, PropertyType} from './blocks/board'
|
||||
import {Menu} from './menu'
|
||||
import {Utils} from './utils'
|
||||
|
||||
class PropertyMenu extends Menu {
|
||||
static shared = new PropertyMenu()
|
||||
@ -31,12 +31,12 @@ class PropertyMenu extends Menu {
|
||||
|
||||
const nameTextbox = ul.appendChild(Utils.htmlToElement('<li class="menu-textbox"></li>'))
|
||||
this.nameTextbox = nameTextbox
|
||||
let propertyValue = this.property ? this.property.name : '';
|
||||
let propertyValue = this.property ? this.property.name : ''
|
||||
nameTextbox.innerText = propertyValue
|
||||
nameTextbox.contentEditable = 'true';
|
||||
nameTextbox.contentEditable = 'true'
|
||||
nameTextbox.onclick = (e) => {
|
||||
e.stopPropagation()
|
||||
};
|
||||
}
|
||||
nameTextbox.onblur = () => {
|
||||
if (nameTextbox.innerText !== propertyValue) {
|
||||
propertyValue = nameTextbox.innerText
|
||||
@ -47,7 +47,7 @@ class PropertyMenu extends Menu {
|
||||
}
|
||||
nameTextbox.onmouseenter = () => {
|
||||
this.hideSubMenu()
|
||||
};
|
||||
}
|
||||
nameTextbox.onkeydown = (e) => {
|
||||
if (e.keyCode === 13 || e.keyCode === 27) {
|
||||
nameTextbox.blur(); e.stopPropagation()
|
||||
@ -76,20 +76,20 @@ class PropertyMenu extends Menu {
|
||||
|
||||
private typeDisplayName(type: PropertyType): string {
|
||||
switch (type) {
|
||||
case 'text': return 'Text';
|
||||
case 'number': return 'Number';
|
||||
case 'select': return 'Select';
|
||||
case 'multiSelect': return 'Multi Select';
|
||||
case 'person': return 'Person';
|
||||
case 'file': return 'File or Media';
|
||||
case 'checkbox': return 'Checkbox';
|
||||
case 'url': return 'URL';
|
||||
case 'email': return 'Email';
|
||||
case 'phone': return 'Phone';
|
||||
case 'createdTime': return 'Created Time';
|
||||
case 'createdBy': return 'Created By';
|
||||
case 'updatedTime': return 'Updated Time';
|
||||
case 'updatedBy': return 'Updated By';
|
||||
case 'text': return 'Text'
|
||||
case 'number': return 'Number'
|
||||
case 'select': return 'Select'
|
||||
case 'multiSelect': return 'Multi Select'
|
||||
case 'person': return 'Person'
|
||||
case 'file': return 'File or Media'
|
||||
case 'checkbox': return 'Checkbox'
|
||||
case 'url': return 'URL'
|
||||
case 'email': return 'Email'
|
||||
case 'phone': return 'Phone'
|
||||
case 'createdTime': return 'Created Time'
|
||||
case 'createdBy': return 'Created By'
|
||||
case 'updatedTime': return 'Updated Time'
|
||||
case 'updatedBy': return 'Updated By'
|
||||
}
|
||||
Utils.assertFailure(`typeDisplayName, unhandled type: ${type}`)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import marked from 'marked';
|
||||
import marked from 'marked'
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
@ -122,10 +122,10 @@ class Utils {
|
||||
static setFavicon(icon?: string) {
|
||||
const href = icon ?
|
||||
`data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><text y=".9em" font-size="90">${icon}</text></svg>` :
|
||||
'';
|
||||
''
|
||||
const link = (document.querySelector("link[rel*='icon']") || document.createElement('link')) as HTMLLinkElement
|
||||
link.type = 'image/x-icon';
|
||||
link.rel = 'shortcut icon';
|
||||
link.type = 'image/x-icon'
|
||||
link.rel = 'shortcut icon'
|
||||
link.href = href
|
||||
document.getElementsByTagName('head')[0].appendChild(link)
|
||||
}
|
||||
@ -138,7 +138,7 @@ class Utils {
|
||||
const illegalCharacters = ['\\', '/', '?', ':', '<', '>', '*', '|', '"', '.']
|
||||
illegalCharacters.forEach((character) => {
|
||||
sanitizedFilename = sanitizedFilename.replace(character, '')
|
||||
});
|
||||
})
|
||||
return sanitizedFilename
|
||||
}
|
||||
|
||||
@ -146,14 +146,14 @@ class Utils {
|
||||
|
||||
static selectLocalFile(onSelect?: (file: File) => void, accept = '.jpg,.jpeg,.png'): void {
|
||||
const input = document.createElement('input')
|
||||
input.type = 'file';
|
||||
input.type = 'file'
|
||||
input.accept = accept
|
||||
input.onchange = async () => {
|
||||
const file = input.files![0]
|
||||
onSelect?.(file)
|
||||
};
|
||||
}
|
||||
|
||||
input.style.display = 'none';
|
||||
input.style.display = 'none'
|
||||
document.body.appendChild(input)
|
||||
input.click()
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
type MenuOptionProps = {
|
||||
id: string,
|
||||
|
@ -1,7 +1,7 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
|
||||
import React from 'react';
|
||||
import React from 'react'
|
||||
|
||||
type Props = {
|
||||
children?: React.ReactNode;
|
||||
|
@ -1,9 +1,9 @@
|
||||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
|
||||
// See LICENSE.txt for license information.
|
||||
import {Block} from './blocks/block';
|
||||
import {Board} from './blocks/board';
|
||||
import octoClient from './octoClient';
|
||||
import {OctoUtils} from './octoUtils';
|
||||
import {Block} from './blocks/block'
|
||||
import {Board} from './blocks/board'
|
||||
import octoClient from './octoClient'
|
||||
import {OctoUtils} from './octoUtils'
|
||||
|
||||
class WorkspaceTree {
|
||||
boards: Board[] = []
|
||||
|
Loading…
x
Reference in New Issue
Block a user