Skip to content

Commit

Permalink
Fix double collection error
Browse files Browse the repository at this point in the history
  • Loading branch information
Rustem Mussabekov committed Apr 17, 2024
1 parent 76f14be commit f0b0d78
Show file tree
Hide file tree
Showing 31 changed files with 747 additions and 17 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "app",
"version": "5.6.21",
"version": "5.6.22",
"description": "",
"author": "",
"license": "ISC",
Expand Down
8 changes: 8 additions & 0 deletions src/assets/icons/ai.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions src/co/collections/item/accentColor.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ export default connect(
}
}
}
)(function CollectionAccentColor({ color, theme, children }) {
)(function CollectionAccentColor({ color, theme, children, force }) {
let hsl = ''
try{ hsl = HexToHsl(color) }catch(e){}

return children(theme.app=='night' || !color ? emptyObj : {
return children((!force && theme.app=='night') || !color ? emptyObj : {
'--accent-color': color,
'--accent-hsl': hsl
})
Expand Down
29 changes: 17 additions & 12 deletions src/co/collections/item/blank.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,19 +25,24 @@ export default function CollectionsItemBlank({ _id, level, to, events: { onItemC
return cancel()

//create collection
setLoading(true)
setLoading(loading=>{
if (loading)
return loading

dispatch(
createFromBlank({ title }, (newItem)=>{
if (onItemClick)
onItemClick(newItem)
else
navigate(to.replace(_id, newItem._id))
}, e=>{
Error(e)
cancel()
})
)
dispatch(
createFromBlank({ title }, (newItem)=>{
if (onItemClick)
onItemClick(newItem)
else
navigate(to.replace(_id, newItem._id))
}, e=>{
Error(e)
cancel()
})
)

return true
})
}, [title, navigate, _id])

const onKeyUp = useCallback((e)=>{
Expand Down
3 changes: 2 additions & 1 deletion src/co/common/header/index.module.styl
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
}

> *:not(:last-child):not(.space) {
margin-right: var(--padding-small)
margin-right: var(--padding-mini)
}

&[data-no-shadow='true'] {
Expand All @@ -33,6 +33,7 @@

&[data-static='true'] {
position: static
z-index: auto
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/config/links.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ export default {
brokenLinks: {
modes: 'https://help.raindrop.io/troubleshooting/false-broken-links/#modes',
}
},
organize: {
index: 'https://help.raindrop.io/ai-organize'
}
},

Expand Down
10 changes: 10 additions & 0 deletions src/data/actions/predictions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import * as c from '../constants/predictions'

export const load = ()=>({
type: c.PREDICTIONS_LOAD_REQ
})

export const patch = (details)=>({
type: c.PREDICTION_PATCH,
...details
})
5 changes: 5 additions & 0 deletions src/data/constants/predictions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const
PREDICTIONS_LOAD_REQ = 'PREDICTIONS_LOAD_REQ',
PREDICTIONS_LOAD_SUCCESS = 'PREDICTIONS_LOAD_SUCCESS',
PREDICTIONS_LOAD_ERROR = 'PREDICTIONS_LOAD_ERROR',
PREDICTION_PATCH = 'PREDICTION_PATCH'
1 change: 1 addition & 0 deletions src/data/modules/persistConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export default {
'user',
'local',
'rate',
'predictions',
...(process.env.NODE_ENV == 'development' ? ['import'] : []),

//app specifics
Expand Down
4 changes: 3 additions & 1 deletion src/data/reducers/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ const initialState = Immutable({

browser_extension_mode: 'clipper',

acknowledge: []
acknowledge: [],

ai_organize: false
})

//this keys can be kept untouched on reset
Expand Down
2 changes: 2 additions & 0 deletions src/data/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import tags from './tags'
import covers from './covers'
import config from './config'
import oauth from './oauth'
import predictions from './predictions'
//import rate from './rate'
import _import from './import'

Expand All @@ -20,6 +21,7 @@ export default {
covers,
config,
oauth,
predictions,
//rate,
import: _import
}
64 changes: 64 additions & 0 deletions src/data/reducers/predictions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import Immutable from 'seamless-immutable'
import { REHYDRATE } from 'redux-persist/src/constants'
import * as c from '../constants/predictions'

const supportedKinds = ['move', 'tag', 'untag', 'mergetags']

export default function(state = initialState, action){switch (action.type) {
case REHYDRATE:{
const { predictions={} } = action.payload||{}

if (predictions.status == 'loaded')
return predictions

return state
}

case 'RESET':
return initialState

case c.PREDICTIONS_LOAD_REQ:{
return state
.set('status', 'loading')
}

case c.PREDICTIONS_LOAD_SUCCESS:{
const items = (action.items||[]).filter(item=>
supportedKinds.includes(item.kind)
)

return state
.set('status', 'loaded')
.set('items', items)
}

case c.PREDICTIONS_LOAD_ERROR:{
return state
.set('status', 'error')
.set('items', initialState.items)
}

case c.PREDICTION_PATCH: {
const { _id, ...props } = action

return state
.set('items', state.items.map(item=>{
if (item._id != _id)
return item

let patched = item
for(const key in props)
if (typeof item[key] != 'undefined')
patched = patched.set(key, props[key])
return patched
}))
}

default:
return state
}}

const initialState = Immutable({
status: 'idle', //idle|loading|loaded|error
items: []
})
2 changes: 2 additions & 0 deletions src/data/sagas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import tags from './tags'
import covers from './covers'
import config from './config'
import oauth from './oauth'
import predictions from './predictions'
import _import from './import'

//saga will be restart on case of failure, error intself will be send to sentry
Expand Down Expand Up @@ -46,6 +47,7 @@ const root = function* () {
tags,
covers,
oauth,
predictions,
_import,

common
Expand Down
23 changes: 23 additions & 0 deletions src/data/sagas/predictions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { put, takeLatest, call } from 'redux-saga/effects'
import * as c from '../constants/predictions'
import Api from '../modules/api'

export default function* () {
yield takeLatest(c.PREDICTIONS_LOAD_REQ, load)
}

function* load() {
try {
const { items } = yield call(Api.get, 'predictions?version=1')

yield put({
type: c.PREDICTIONS_LOAD_SUCCESS,
items
})
} catch (error) {
yield put({
type: c.PREDICTIONS_LOAD_ERROR,
error
})
}
}
9 changes: 9 additions & 0 deletions src/data/selectors/predictions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createSelector } from 'reselect'
import _ from 'lodash-es'

export const makeGroupped = ()=> createSelector(
[state=>state.predictions.items],
(items)=>{
return Object.entries(_.groupBy(items, 'kind'))
}
)
2 changes: 2 additions & 0 deletions src/routes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import Add from './add'
import Extension from './extension'
import My from './my'
import Join from './join'
import Organize from './organize'
import Settings from './settings'

const Router = target == 'web' ? BrowserRouter : HashRouter
Expand All @@ -28,6 +29,7 @@ export default function Pages() {
<Route path='add' element={<Add />} />
<Route path='my'>{My()}</Route>
<Route path='join/:token' element={<Join />} />
<Route path='organize' element={<Organize />} />
<Route path='settings'>{Settings()}</Route>
</Route>

Expand Down
8 changes: 8 additions & 0 deletions src/routes/my/sidebar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useCallback } from 'react'
import t from '~t'
import { useParams } from 'react-router-dom'

import { Link } from 'react-router-dom'
import Button from '~co/common/button'
import Icon from '~co/common/icon'
import Sidebar, { Header, Content } from '~co/screen/splitview/sidebar'
Expand Down Expand Up @@ -33,6 +34,13 @@ export default function PageMySidebar() {
<Sidebar>
<Header>
<Profile />

{/* <Button
as={Link}
title='Organize with AI'
to='/organize'>
<Icon name='ai' />
</Button> */}

<Button
title={`${t.s('createNewCollection')}\nShift+click: ${t.s('createSubFolder').toLowerCase()}`}
Expand Down
39 changes: 39 additions & 0 deletions src/routes/organize/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import s from './index.module.css'
import React from 'react'
import { useSelector } from 'react-redux'

import Screen from '~co/screen/basic'
import Header, { Title, FirstAction } from '~co/common/header'
import Button from '~co/common/button'
import { Link } from 'react-router-dom'
import Icon from '~co/common/icon'
import Intro from './intro'
import Predictions from './predictions'

export default function PageOrganize() {
const enabled = useSelector(state=>state.config.ai_organize)

return (
<Screen className={s.main} appSize='large'>
<Header className={s.header} data-solid>
<FirstAction className='svSidebarShowButton'>
<Button as={Link} to='/'>
<Icon name='back' />
</Button>
</FirstAction>

<Title>Organize with ✦ AI</Title>
</Header>

<div className={s.split} data-enabled={enabled}>
<Intro />

{enabled ? (
<div className={s.content}>
<Predictions />
</div>
) : null}
</div>
</Screen>
)
}
27 changes: 27 additions & 0 deletions src/routes/organize/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.main, .header {
background-color: var(--sidebar-background-color) !important;
}

.main {
display: flex;
flex-direction: column;
}

.split {
flex: 1;
display: grid;
grid-template-columns: 1fr;
}
.split[data-enabled="false"] {
align-items: center;
}

.content {
padding: var(--padding-large)
}

@media (min-width: 1000px) {
.split[data-enabled="true"] {
grid-template-columns: 400px 1fr;
}
}
Loading

0 comments on commit f0b0d78

Please sign in to comment.