Skip to content

Commit

Permalink
feat: WIP implementation of Client data model
Browse files Browse the repository at this point in the history
  • Loading branch information
jstarpl committed Nov 10, 2023
1 parent c18ea72 commit fbbffee
Show file tree
Hide file tree
Showing 11 changed files with 296 additions and 17 deletions.
Binary file modified .yarn/install-state.gz
Binary file not shown.
34 changes: 18 additions & 16 deletions packages/apps/client/.eslintrc.cjs
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
root: true,
env: { browser: true, es2020: true },
extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'plugin:react-hooks/recommended'],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': ['warn', { allowConstantExport: true }],
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': [
'warn', // or "error"
{
argsIgnorePattern: '^_',
varsIgnorePattern: '^_',
caughtErrorsIgnorePattern: '^_',
},
],
},
}
6 changes: 5 additions & 1 deletion packages/apps/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"devDependencies": {
"@types/react": "^18.2.36",
"@types/react-dom": "^18.2.14",
"@types/uuid": "^9",
"@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.10.0",
"@vitejs/plugin-react": "^4.1.1",
Expand All @@ -33,9 +34,12 @@
"@sofie-prompter-editor/shared-lib": "0.0.0",
"@sofie-prompter-editor/shared-model": "0.0.0",
"eventemitter3": "^5.0.1",
"mobx": "^6.10.2",
"mobx-react-lite": "^4.0.5",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"socket.io-client": "^4.7.2"
"socket.io-client": "^4.7.2",
"uuid": "^9.0.1"
},
"lint-staged": {
"*.{js,css,json,md,scss}": [
Expand Down
5 changes: 5 additions & 0 deletions packages/apps/client/src/lib/lib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import uuid from 'uuid';

export function randomId() {
return uuid.v4()
}
62 changes: 62 additions & 0 deletions packages/apps/client/src/model/UILine.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import { Part, PartDisplayType, PartId, ProtectedString, protectString } from 'packages/shared/model/dist'
import { RundownStore } from '../stores/RundownStore'
import { randomId } from '../lib/lib'
import { makeAutoObservable } from 'mobx'

export class UILine {
slug: string = ''

rank: number = 0

identifier: string | null = null

lineType: {
label: string

style: LineType
} | null = null

script: string | null = null

expectedDuration: number | null = null

isNew: boolean = false

ready: boolean = false

constructor(private store: RundownStore, public partId: PartId, public id = protectString<UILineId>(randomId())) {
makeAutoObservable(this)

void this.store
}

updateFromJson(json: Part) {
this.identifier = json.identifier ?? null
this.slug = json.label
this.rank = json.rank
this.script = json.scriptContents ?? null
this.isNew = json.isNew ?? false
this.expectedDuration = json.expectedDuration ?? null
this.lineType = {
label: json.display.label,
style: partDisplayTypeToLineTypeStyle(json.display.type),
}

this.ready = true
}

remove() {}
}

export type UILineId = ProtectedString<'UILineId', string>

function partDisplayTypeToLineTypeStyle(_type: PartDisplayType): LineType {
return LineType.VT
}

export enum LineType {
VT = 'vt',
LiveSpeak = 'liveSpeak',
Remote = 'remote',
Split = 'split',
}
50 changes: 50 additions & 0 deletions packages/apps/client/src/model/UIRundown.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { computed, makeAutoObservable, observable } from 'mobx'
import { ProtectedString, RundownPlaylist, RundownPlaylistId, protectString } from 'packages/shared/model/dist'
import { UISegment, UISegmentId } from './UISegment'
import { RundownStore } from '../stores/RundownStore'
import { randomId } from '../lib/lib'

export class UIRundown {
name: string = ''

ready: boolean = false

segments = observable.map<UISegmentId, UISegment>()

constructor(
private store: RundownStore,
public playlistId: RundownPlaylistId,
public id = protectString<UIRundownId>(randomId())
) {
makeAutoObservable(this, {
segmentIdsInOrder: computed,
})

void this.store

// get all segments
// this.store.connection.segment.find({
// query: {
// playlistId:
// }
// })

// register callbacks for events
// this.store.connection.segment.on('created')
}

updateFromJson(json: RundownPlaylist) {
this.name = json.label
this.ready = true
}

get segmentIdsInOrder(): UISegmentId[] {
return []
}

dispose(): void {
// unregister event handlers from services
}
}

export type UIRundownId = ProtectedString<'UIRundownId', string>
4 changes: 4 additions & 0 deletions packages/apps/client/src/model/UIRundownEntry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// a lightweight domain object for tracking rundowns without their contents
export class UIRundownEntry {

}
45 changes: 45 additions & 0 deletions packages/apps/client/src/model/UISegment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { computed, makeAutoObservable, observable, values } from 'mobx'
import { ProtectedString, Segment, SegmentId, protectString } from 'packages/shared/model/dist'
import { UILineId, UILine } from './UILine'
import { RundownStore } from '../stores/RundownStore'
import { randomId } from '../lib/lib'

export class UISegment {
rank: number = 0

name: string = ''

ready: boolean = false

lines = observable.map<UILineId, UILine>([])

constructor(
private store: RundownStore,
public segmentId: SegmentId,
public id = protectString<UISegmentId>(randomId())
) {
makeAutoObservable(this, {
lineIdsInOrder: computed,
})

// fetch owned parts and register event handlers for parts
}

updateFromJson(json: Segment) {
this.name = json.label
this.rank = json.rank

this.ready = true
}

get lineIdsInOrder(): UILineId[] {
return values(this.lines).slice().sort((a, b) => a.rank - b.rank).map((line) => line.id)
}

remove(): void {
this.store.openRundown?.segments.delete(this.id)
// unregister event handlers
}
}

export type UISegmentId = ProtectedString<'UISegmentId', string>
28 changes: 28 additions & 0 deletions packages/apps/client/src/stores/AppStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { makeAutoObservable, action } from 'mobx'
import { RundownStore } from './RundownStore'
import { APIConnection } from '../api/ApiConnection'

export class AppStore {
connected = false
rundownStore: RundownStore
connection = new APIConnection()

constructor() {
makeAutoObservable(this)
this.rundownStore = new RundownStore(this, this.connection)

this.connection.on(
'connected',
action('setConnected', () => {
this.connected = true
})
)

this.connection.on(
'disconnected',
action('setDisconnected', () => {
this.connected = false
})
)
}
}
35 changes: 35 additions & 0 deletions packages/apps/client/src/stores/RundownStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { makeAutoObservable, observable, action } from 'mobx'
import { RundownPlaylistId } from 'packages/shared/model/dist'
import { AppStore } from './AppStore'
import { APIConnection } from '../api/ApiConnection'
import { UIRundown } from '../model/UIRundown'
import { UIRundownEntry } from '../model/UIRundownEntry'

export class RundownStore {
showingOnlyScripts = false

allRundowns = observable.array<UIRundownEntry>()
openRundown: UIRundown | null = null

constructor(public appStore: AppStore, public connection: APIConnection) {
makeAutoObservable(this, {})

// get all rundowns
this.connection.playlist.on('created', () => {})
this.loadAllRudnowns()
}

loadAllRudnowns() {
this.connection.playlist.find().then(
action('receiveRundowns', () => {
// add UIRundownEntries to allRundowns
})
)
}

loadRundown(id: RundownPlaylistId) {
console.log(id)
// get a full rundown from backend and create a UIRundown object
// assign to openRundown
}
}
44 changes: 44 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1833,17 +1833,21 @@ __metadata:
"@sofie-prompter-editor/shared-model": "npm:0.0.0"
"@types/react": "npm:^18.2.36"
"@types/react-dom": "npm:^18.2.14"
"@types/uuid": "npm:^9"
"@typescript-eslint/eslint-plugin": "npm:^6.10.0"
"@typescript-eslint/parser": "npm:^6.10.0"
"@vitejs/plugin-react": "npm:^4.1.1"
eslint: "npm:^8.53.0"
eslint-plugin-react-hooks: "npm:^4.6.0"
eslint-plugin-react-refresh: "npm:^0.4.4"
eventemitter3: "npm:^5.0.1"
mobx: "npm:^6.10.2"
mobx-react-lite: "npm:^4.0.5"
react: "npm:^18.2.0"
react-dom: "npm:^18.2.0"
socket.io-client: "npm:^4.7.2"
typescript: "npm:^5.2.2"
uuid: "npm:^9.0.1"
vite: "npm:^4.5.0"
languageName: unknown
linkType: soft
Expand Down Expand Up @@ -2346,6 +2350,13 @@ __metadata:
languageName: node
linkType: hard

"@types/uuid@npm:^9":
version: 9.0.7
resolution: "@types/uuid@npm:9.0.7"
checksum: b329ebd4f9d1d8e08d4f2cc211be4922d70d1149f73d5772630e4a3acfb5170c6d37b3d7a39a0412f1a56e86e8a844c7f297c798b082f90380608bf766688787
languageName: node
linkType: hard

"@types/yargs-parser@npm:*":
version: 21.0.1
resolution: "@types/yargs-parser@npm:21.0.1"
Expand Down Expand Up @@ -7864,6 +7875,30 @@ __metadata:
languageName: node
linkType: hard

"mobx-react-lite@npm:^4.0.5":
version: 4.0.5
resolution: "mobx-react-lite@npm:4.0.5"
dependencies:
use-sync-external-store: "npm:^1.2.0"
peerDependencies:
mobx: ^6.9.0
react: ^16.8.0 || ^17 || ^18
peerDependenciesMeta:
react-dom:
optional: true
react-native:
optional: true
checksum: 6c8f69646ee9fb50155062c8a43e6d222a7b9dbd28f139648dcbb2a097d9ea660d643dd94529355e7f6926561e37c0206ca9e477f01784aedafbed607daceda6
languageName: node
linkType: hard

"mobx@npm:^6.10.2":
version: 6.10.2
resolution: "mobx@npm:6.10.2"
checksum: c874e3531047dcd1c0ffa7c118ecab2e1abebd924e3cf361bcfce4304e75529d8c0143b8b72e35e4592eed417b3186b755e56f4e03983461ba1816c1d47499e3
languageName: node
linkType: hard

"modify-values@npm:^1.0.1":
version: 1.0.1
resolution: "modify-values@npm:1.0.1"
Expand Down Expand Up @@ -10767,6 +10802,15 @@ __metadata:
languageName: node
linkType: hard

"use-sync-external-store@npm:^1.2.0":
version: 1.2.0
resolution: "use-sync-external-store@npm:1.2.0"
peerDependencies:
react: ^16.8.0 || ^17.0.0 || ^18.0.0
checksum: ac4814e5592524f242921157e791b022efe36e451fe0d4fd4d204322d5433a4fc300d63b0ade5185f8e0735ded044c70bcf6d2352db0f74d097a238cebd2da02
languageName: node
linkType: hard

"util-deprecate@npm:^1.0.1, util-deprecate@npm:~1.0.1":
version: 1.0.2
resolution: "util-deprecate@npm:1.0.2"
Expand Down

0 comments on commit fbbffee

Please sign in to comment.