浏览代码

Update forms

Project is set up from new Node version.
master
父节点
当前提交
ca2f32a9b7
共有 19 个文件被更改,包括 7282 次插入7393 次删除
  1. +1
    -1
      REQUIREMENTS.md
  2. +1
    -0
      packages/app-web/src/components/molecules/forms/ActionButton/index.tsx
  3. +1
    -0
      packages/app-web/src/components/molecules/forms/NumericInput/index.tsx
  4. +1
    -0
      packages/app-web/src/components/molecules/forms/TextArea/index.tsx
  5. +1
    -0
      packages/app-web/src/components/molecules/forms/TextInput/index.tsx
  6. +1
    -0
      packages/app-web/src/components/molecules/forms/ToggleButton/index.tsx
  7. +26
    -0
      packages/app-web/src/components/molecules/presentation/Avatar/index.tsx
  8. +22
    -1
      packages/app-web/src/components/molecules/presentation/Card/index.tsx
  9. +114
    -0
      packages/app-web/src/components/organisms/presentation/BasicLayout/index.tsx
  10. +5
    -80
      packages/app-web/src/components/templates/BrowseRingtones/index.tsx
  11. +2
    -4
      packages/app-web/src/components/templates/CreateRingtone/index.test.tsx
  12. +12
    -84
      packages/app-web/src/components/templates/CreateRingtone/index.tsx
  13. +4
    -4
      packages/app-web/src/data/layout.ts
  14. +18
    -8
      packages/app-web/src/modules/ringtone/endpoints.ts
  15. +4
    -4
      packages/app-web/src/pages/_app.tsx
  16. +2
    -2
      packages/app-web/src/pages/my/create/ringtones/[id].tsx
  17. +1
    -2
      packages/app-web/src/pages/my/create/ringtones/index.tsx
  18. +6568
    -6728
      packages/app-web/yarn.lock
  19. +498
    -475
      packages/service-core/yarn.lock

+ 1
- 1
REQUIREMENTS.md 查看文件

@@ -15,7 +15,7 @@
- [ ] In the front-end, the client provides a ringtone ID to request a ringtone from the back-end.
- [ ] In the back-end, the server sends the ringtone data to the front-end.
- As a client, I want to browse ringtones.
- [ ] In the front-end, the client provides optional skip and take arguments to request multiple ringtones from the
- [X] In the front-end, the client provides optional skip and take arguments to request multiple ringtones from the
back-end.
- [X] In the back-end, the server sends the ringtones to the front-end.
- As a client, I want to view the ringtones made by a composer.


+ 1
- 0
packages/app-web/src/components/molecules/forms/ActionButton/index.tsx 查看文件

@@ -18,6 +18,7 @@ const Base = styled('div')({
height: '100%',
borderRadius: 'inherit',
boxSizing: 'border-box',
opacity: 0.5,
},
})



+ 1
- 0
packages/app-web/src/components/molecules/forms/NumericInput/index.tsx 查看文件

@@ -18,6 +18,7 @@ const Base = styled('div')({
height: '100%',
borderRadius: 'inherit',
boxSizing: 'border-box',
opacity: 0.5,
},
})



+ 1
- 0
packages/app-web/src/components/molecules/forms/TextArea/index.tsx 查看文件

@@ -17,6 +17,7 @@ const Base = styled('div')({
height: '100%',
borderRadius: 'inherit',
boxSizing: 'border-box',
opacity: 0.5,
},
})



+ 1
- 0
packages/app-web/src/components/molecules/forms/TextInput/index.tsx 查看文件

@@ -18,6 +18,7 @@ const Base = styled('div')({
height: '100%',
borderRadius: 'inherit',
boxSizing: 'border-box',
opacity: 0.5,
},
})



+ 1
- 0
packages/app-web/src/components/molecules/forms/ToggleButton/index.tsx 查看文件

@@ -19,6 +19,7 @@ const Base = styled('div')({
borderRadius: 'inherit',
boxSizing: 'border-box',
pointerEvents: 'none',
opacity: 0.5,
},
})



+ 26
- 0
packages/app-web/src/components/molecules/presentation/Avatar/index.tsx 查看文件

@@ -0,0 +1,26 @@
import styled from 'styled-components';
import {FC} from 'react';

const Base = styled('img')({
objectFit: 'cover',
objectPosition: 'center',
width: '3rem',
height: '3rem',
borderRadius: '50%',
})

type Props = {
src: string,
}

const Avatar: FC<Props> = ({
src,
}) => {
return (
<Base
src={src}
/>
)
}

export default Avatar

+ 22
- 1
packages/app-web/src/components/molecules/presentation/Card/index.tsx 查看文件

@@ -6,6 +6,20 @@ const Base = styled('div')({
position: 'relative',
padding: '1rem',
boxSizing: 'border-box',
'::before': {
content: "''",
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
boxSizing: 'border-box',
borderRadius: 'inherit',
pointerEvents: 'none',
backgroundColor: 'white',
mixBlendMode: 'screen',
opacity: 0.125,
},
'::after': {
content: "''",
position: 'absolute',
@@ -17,9 +31,14 @@ const Base = styled('div')({
borderRadius: 'inherit',
pointerEvents: 'none',
border: '1px solid',
opacity: 0.5,
},
})

const Content = styled('div')({
position: 'relative',
})

type Props = {
className?: string,
}
@@ -32,7 +51,9 @@ const Card: FC<Props> = ({
<Base
{...etcProps}
>
{children}
<Content>
{children}
</Content>
</Base>
)
}


+ 114
- 0
packages/app-web/src/components/organisms/presentation/BasicLayout/index.tsx 查看文件

@@ -0,0 +1,114 @@
import {LeftSidebarWithMenu} from '@theoryofnekomata/viewfinder';
import Brand from '../../../molecules/brand/Brand';
import Link from '../../../molecules/navigation/Link';
import OmnisearchForm from '../../forms/Omnisearch';
import {moreLinkMenuItem, sidebarMenuItems} from '../../../../data/layout';
import {FC, FormEventHandler} from 'react';
import {Session} from '@auth0/nextjs-auth0';
import styled from 'styled-components';
import Avatar from '../../../molecules/presentation/Avatar';

const TopBarComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
position: 'relative',
'::before': {
content: "''",
position: 'absolute',
bottom: 0,
left: 0,
width: '100%',
height: '0.0625rem',
pointerEvents: 'none',
backgroundColor: 'currentcolor',
opacity: 0.25,
},
})

const SidebarMenuComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
'::before': {
content: "''",
position: 'absolute',
top: 0,
right: 0,
height: '100%',
width: '0.0625rem',
pointerEvents: 'none',
backgroundColor: 'currentcolor',
opacity: 0.25,
},
})

type Props = {
onSearch?: FormEventHandler,
session?: Partial<Session>,
}

const BasicLayout: FC<Props> = ({
onSearch,
session,
children,
}) => {
return (
<LeftSidebarWithMenu.Layout
brand={
<Brand />
}
userLink={
<Link
href={{
query: {
popup: 'user',
},
}}
>
<Avatar
src={session.user.picture}
/>
</Link>
}
topBarComponent={TopBarComponent}
sidebarMenuComponent={SidebarMenuComponent}
topBarCenter={
<OmnisearchForm
labels={{
form: 'Search',
query: 'Query',
}}
onSubmit={onSearch}
action="/api/a/search"
/>
}
linkComponent={({ url, icon, label, }) => (
<Link
href={url}
>
<LeftSidebarWithMenu.SidebarMenuContainer>
<LeftSidebarWithMenu.SidebarMenuItemIcon>
{icon}
</LeftSidebarWithMenu.SidebarMenuItemIcon>
{label}
</LeftSidebarWithMenu.SidebarMenuContainer>
</Link>
)}
moreLinkMenuItem={moreLinkMenuItem}
moreLinkComponent={({ url, icon, label, }) => (
<Link
href={url}
>
<LeftSidebarWithMenu.MoreSidebarMenuContainer>
<LeftSidebarWithMenu.MoreSidebarMenuItemIcon>
{icon}
</LeftSidebarWithMenu.MoreSidebarMenuItemIcon>
{label}
</LeftSidebarWithMenu.MoreSidebarMenuContainer>
</Link>
)}
sidebarMenuItems={sidebarMenuItems}
>
{children}
</LeftSidebarWithMenu.Layout>
)
}

export default BasicLayout

+ 5
- 80
packages/app-web/src/components/templates/BrowseRingtones/index.tsx 查看文件

@@ -1,32 +1,14 @@
import {FC, FormEventHandler} from 'react';
import styled from 'styled-components';
import { LeftSidebarWithMenu } from '@theoryofnekomata/viewfinder'
import Brand from '../../molecules/brand/Brand';
import Link from '../../molecules/navigation/Link';
import OmnisearchForm from '../../organisms/forms/Omnisearch';
import {Session} from '@auth0/nextjs-auth0';
import {models} from '@tonality/library-common';
import RingtoneCardDisplay from '../../organisms/presentation/RingtoneCardDisplay';
import Card from '../../molecules/presentation/Card';
import {moreLinkMenuItem, sidebarMenuItems} from '../../../data/layout';
import ActionButton from '../../molecules/forms/ActionButton';
import NumericInput from '../../molecules/forms/NumericInput';

const TopBarComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
})

const SidebarMenuComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
})

const Avatar = styled('img')({
objectFit: 'cover',
objectPosition: 'center',
width: '3rem',
height: '3rem',
borderRadius: '50%',
})
import BasicLayout from '../../organisms/presentation/BasicLayout';

const CardList = styled('div')({
display: 'grid',
@@ -96,66 +78,9 @@ const BrowseRingtonesTemplate: FC<Props> = ({
loading,
}) => {
return (
<LeftSidebarWithMenu.Layout
brand={
<Brand />
}
userLink={
<Link
href={{
query: {
popup: 'user',
},
}}
>
{
session
&& (
<Avatar
src={session.user.picture}
/>
)
}
</Link>
}
topBarComponent={TopBarComponent}
sidebarMenuComponent={SidebarMenuComponent}
topBarCenter={
<OmnisearchForm
labels={{
form: 'Search',
query: 'Query',
}}
onSubmit={onSearch}
action="/api/a/search"
/>
}
linkComponent={({ url, icon, label, }) => (
<Link
href={url}
>
<LeftSidebarWithMenu.SidebarMenuContainer>
<LeftSidebarWithMenu.SidebarMenuItemIcon>
{icon}
</LeftSidebarWithMenu.SidebarMenuItemIcon>
{label}
</LeftSidebarWithMenu.SidebarMenuContainer>
</Link>
)}
moreLinkMenuItem={moreLinkMenuItem}
moreLinkComponent={({ url, icon, label, }) => (
<Link
href={url}
>
<LeftSidebarWithMenu.MoreSidebarMenuContainer>
<LeftSidebarWithMenu.MoreSidebarMenuItemIcon>
{icon}
</LeftSidebarWithMenu.MoreSidebarMenuItemIcon>
{label}
</LeftSidebarWithMenu.MoreSidebarMenuContainer>
</Link>
)}
sidebarMenuItems={sidebarMenuItems}
<BasicLayout
onSearch={onSearch}
session={session}
>
<LeftSidebarWithMenu.ContentContainer>
{
@@ -230,7 +155,7 @@ const BrowseRingtonesTemplate: FC<Props> = ({
)
}
</LeftSidebarWithMenu.ContentContainer>
</LeftSidebarWithMenu.Layout>
</BasicLayout>
)
}



+ 2
- 4
packages/app-web/src/components/templates/CreateRingtone/index.test.tsx 查看文件

@@ -5,10 +5,8 @@ describe('template for creating ringtones', () => {
it('should render without crashing', () => {
expect(() => render(
<CreateRingtoneTemplate
composerRingtones={[]}
composer={{
name: 'TheoryOfNekomata',
id: '00000000-0000-0000-000000000000',
session={{
user: {},
}}
/>
)).not.toThrow()


+ 12
- 84
packages/app-web/src/components/templates/CreateRingtone/index.tsx 查看文件

@@ -1,46 +1,26 @@
import {FC, FormEventHandler} from 'react'
import styled from 'styled-components'
import {Session} from '@auth0/nextjs-auth0'
import { LeftSidebarWithMenu } from '@theoryofnekomata/viewfinder'
import {models} from '@tonality/library-common'
import CreateRingtoneForm from '../../organisms/forms/CreateRingtone'
import Link from '../../molecules/navigation/Link'
import OmnisearchForm from '../../organisms/forms/Omnisearch'
import Brand from '../../molecules/brand/Brand'
import {moreLinkMenuItem, sidebarMenuItems} from '../../../data/layout';

const TopBarComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
})

const SidebarMenuComponent = styled('div')({
backgroundColor: 'var(--color-bg, white)',
})
import BasicLayout from '../../organisms/presentation/BasicLayout';

const Padding = styled('div')({
margin: '2rem 0',
})

const Avatar = styled('img')({
objectFit: 'cover',
objectPosition: 'center',
width: '3rem',
height: '3rem',
borderRadius: '50%',
})

type Props = {
onSearch?: FormEventHandler,
onSubmit?: FormEventHandler,
session: Partial<Session>,
currentRingtone?: models.Ringtone,
updateTempo: ({ songRef, dataRef, setTempo, }) => (...args: unknown[]) => void,
updateView: ({ setNoteGlyph, setRestGlyph, noteGlyphs, restGlyphs, }) => (...args: unknown[]) => void,
addRest: ({ formRef, dataRef, songRef, }) => (...args: unknown[]) => void,
addNote: ({ dataRef, formRef, songRef, soundManagerRef, }) => (...args: unknown[]) => void,
togglePlayback: ({ formRef, songRef, soundManagerRef, setPlayTimestamp, setPlaying, }) => (...args: unknown[]) => void,
updateSong: ({ formRef, songRef, }) => (...args: unknown[]) => void,
play: ({ dataRef, playing, setPlaying, playTimestamp, }) => void,
updateTempo?: ({ songRef, dataRef, setTempo, }) => (...args: unknown[]) => void,
updateView?: ({ setNoteGlyph, setRestGlyph, noteGlyphs, restGlyphs, }) => (...args: unknown[]) => void,
addRest?: ({ formRef, dataRef, songRef, }) => (...args: unknown[]) => void,
addNote?: ({ dataRef, formRef, songRef, soundManagerRef, }) => (...args: unknown[]) => void,
togglePlayback?: ({ formRef, songRef, soundManagerRef, setPlayTimestamp, setPlaying, }) => (...args: unknown[]) => void,
updateSong?: ({ formRef, songRef, }) => (...args: unknown[]) => void,
play?: ({ dataRef, playing, setPlaying, playTimestamp, }) => void,
}

const CreateRingtoneTemplate: FC<Props> = ({
@@ -57,61 +37,9 @@ const CreateRingtoneTemplate: FC<Props> = ({
play,
}) => {
return (
<LeftSidebarWithMenu.Layout
brand={
<Brand />
}
userLink={
<Link
href={{
query: {
popup: 'user',
},
}}
>
<Avatar
src={session.user.picture}
/>
</Link>
}
topBarComponent={TopBarComponent}
sidebarMenuComponent={SidebarMenuComponent}
topBarCenter={
<OmnisearchForm
labels={{
form: 'Search',
query: 'Query',
}}
onSubmit={onSearch}
action="/api/a/search"
/>
}
linkComponent={({ url, icon, label, }) => (
<Link
href={url}
>
<LeftSidebarWithMenu.SidebarMenuContainer>
<LeftSidebarWithMenu.SidebarMenuItemIcon>
{icon}
</LeftSidebarWithMenu.SidebarMenuItemIcon>
{label}
</LeftSidebarWithMenu.SidebarMenuContainer>
</Link>
)}
moreLinkMenuItem={moreLinkMenuItem}
moreLinkComponent={({ url, icon, label, }) => (
<Link
href={url}
>
<LeftSidebarWithMenu.MoreSidebarMenuContainer>
<LeftSidebarWithMenu.MoreSidebarMenuItemIcon>
{icon}
</LeftSidebarWithMenu.MoreSidebarMenuItemIcon>
{label}
</LeftSidebarWithMenu.MoreSidebarMenuContainer>
</Link>
)}
sidebarMenuItems={sidebarMenuItems}
<BasicLayout
onSearch={onSearch}
session={session}
>
<Padding>
<CreateRingtoneForm
@@ -136,7 +64,7 @@ const CreateRingtoneTemplate: FC<Props> = ({
play={play}
/>
</Padding>
</LeftSidebarWithMenu.Layout>
</BasicLayout>
)
}



+ 4
- 4
packages/app-web/src/data/layout.ts 查看文件

@@ -2,7 +2,7 @@ export const sidebarMenuItems = [
{
id: 'browse',
label: 'Browse',
icon: 'B',
icon: '🔍',
url: {
pathname: '/',
},
@@ -10,7 +10,7 @@ export const sidebarMenuItems = [
{
id: 'compose',
label: 'Compose',
icon: 'C',
icon: '🎵',
url: {
pathname: '/my/create/ringtones',
},
@@ -18,7 +18,7 @@ export const sidebarMenuItems = [
{
id: 'bin',
label: 'Bin',
icon: 'B',
icon: '🗑',
url: {
pathname: '/my/bin',
},
@@ -27,6 +27,6 @@ export const sidebarMenuItems = [

export const moreLinkMenuItem = {
label: 'More',
icon: 'M',
icon: '···',
url: {},
}

+ 18
- 8
packages/app-web/src/modules/ringtone/endpoints.ts 查看文件

@@ -15,14 +15,24 @@ export const get = (id: string): FetchClientParams => ({
url: ['', 'api', 'ringtones', encodeURIComponent(id)].join('/'),
})

export const browse = ({ skip, take, }: { skip?: number, take?: number }): FetchClientParams => ({
method: Method.GET,
url: ['', 'api', 'ringtones'].join('/'),
query: {
skip: typeof skip === 'number' ? skip.toString() : undefined,
take: typeof take === 'number' ? take.toString() : undefined,
},
})
export const browse = ({ skip, take, }: { skip?: number, take?: number }): FetchClientParams => {
const params: FetchClientParams = {
method: Method.GET,
url: ['', 'api', 'ringtones'].join('/'),
}

if (Number.isFinite(skip) || Number.isFinite(take)) {
params.query = {}
if (Number.isFinite(skip)) {
params.query.skip = skip.toString()
}
if (Number.isFinite(take)) {
params.query.take = take.toString()
}
}

return params
}

export const update = (id: string) => (body: Partial<models.Ringtone>): FetchClientParams => ({
method: Method.PATCH,


+ 4
- 4
packages/app-web/src/pages/_app.tsx 查看文件

@@ -2,8 +2,8 @@ import { createGlobalStyle } from 'styled-components'

const GlobalStyle = createGlobalStyle({
':root': {
'--color-bg': 'white',
'--color-fg': 'black',
'--color-bg': '#eee',
'--color-fg': '#333',
color: 'var(--color-fg, black)',
backgroundColor: 'var(--color-bg, white)',
fontFamily: 'system-ui, sans-serif',
@@ -16,8 +16,8 @@ const GlobalStyle = createGlobalStyle({
},
'@media (prefers-color-scheme: dark)': {
':root': {
'--color-bg': 'black',
'--color-fg': 'white',
'--color-bg': '#222',
'--color-fg': '#eee',
color: 'var(--color-fg, white)',
backgroundColor: 'var(--color-bg, black)',
},


+ 2
- 2
packages/app-web/src/pages/my/create/ringtones/[id].tsx 查看文件

@@ -2,12 +2,12 @@ import {GetServerSideProps, NextPage} from 'next'
import {getSession, Session, withPageAuthRequired} from '@auth0/nextjs-auth0';
import {useEffect, useState} from 'react';
import {models} from '@tonality/library-common'
import {useRouter} from 'next/router';
import CreateRingtoneTemplate from '../../../../components/templates/CreateRingtone'
import RingtoneClient from '../../../../modules/ringtone/client'
import WaveOscillator from '../../../../utils/sound/WaveOscillator'
import SoundManager from '../../../../utils/sound/SoundManager'
import ComposerClient from '../../../../modules/composer/client'
import {useRouter} from 'next/router';

type Props = {
session: Partial<Session>,
@@ -82,7 +82,7 @@ export const getServerSideProps: GetServerSideProps = withPageAuthRequired({
},
}
},
returnTo: '/my/create/ringtone'
returnTo: '/my/create/ringtones'
})

export default Page

+ 1
- 2
packages/app-web/src/pages/my/create/ringtones/index.tsx 查看文件

@@ -1,7 +1,6 @@
import {GetServerSideProps, NextPage} from 'next'
import {getSession, Session, withPageAuthRequired} from '@auth0/nextjs-auth0';
import {useEffect, useState} from 'react';
import {models} from '@tonality/library-common'
import CreateRingtoneTemplate from '../../../../components/templates/CreateRingtone'
import RingtoneClient from '../../../../modules/ringtone/client'
import WaveOscillator from '../../../../utils/sound/WaveOscillator'
@@ -69,7 +68,7 @@ export const getServerSideProps: GetServerSideProps = withPageAuthRequired({
},
}
},
returnTo: '/my/create/ringtone'
returnTo: '/my/create/ringtones'
})

export default Page

+ 6568
- 6728
packages/app-web/yarn.lock
文件差异内容过多而无法显示
查看文件


+ 498
- 475
packages/service-core/yarn.lock
文件差异内容过多而无法显示
查看文件


正在加载...
取消
保存