From 195e1da3812a9e708e01ca99e9eadc0b53e65a38 Mon Sep 17 00:00:00 2001 From: Cale McCollough Date: Thu, 22 Feb 2024 15:39:49 -0800 Subject: [PATCH] Popup: Upgrade dummy session logger buttons to component #102.A --- Extension/App/Popup.tsx | 117 +++-------------- Extension/Ctlr/Background.ts | 4 +- Extension/Ctlr/UseModelState.ts | 35 ++++++ Extension/Model/index.ts | 154 +++++++++++++---------- Extension/View/MissionClock.tsx | 5 - Extension/View/MissionSelector.tsx | 132 +++++++++---------- Extension/View/SessionPunchClockView.tsx | 101 +++++++++++++++ tsconfig.json | 4 +- 8 files changed, 316 insertions(+), 236 deletions(-) create mode 100644 Extension/Ctlr/UseModelState.ts delete mode 100644 Extension/View/MissionClock.tsx create mode 100644 Extension/View/SessionPunchClockView.tsx diff --git a/Extension/App/Popup.tsx b/Extension/App/Popup.tsx index b4520bd..0132ba2 100644 --- a/Extension/App/Popup.tsx +++ b/Extension/App/Popup.tsx @@ -3,125 +3,40 @@ import React, { useEffect, useState } from 'react' import { createRoot } from 'react-dom/client' import { - ModelConfigSync, ModelConfigSyncGet, - ModelConfigSyncInit, - ModelConfigSyncSet, + ModelConfigLocal, ModelConfigLocalGet, ModelConfigLocalInit, + ModelConfigLocalSet, + ModelConfigSync, ModelConfigSyncGet, ModelConfigSyncInit, ModelConfigSyncSet, ModelSyndicateGet } from '../Model' -import MissionSelector from '../View/MissionSelector' -const { TimestampSeconds } = require('linearid') - -function SessionNumberChange(session_number: number, config: ModelConfigSync) { - if(session_number < 0) return - ModelConfigSyncSet({ ...config, session: session_number }) -} +import SessionPunchClockView from '../View/SessionPunchClockView' // Browser extension popup widget. const Popup = () => { console.log('>Popup') // Live Coding AStartupMCC #39.F Add: Can clock and off to dummy... - const [Config, ConfigSet] = useState(ModelConfigSyncInit) - const [MissionHeading, MissionHeadingSet] = useState('') - const [SessionHeading, SessionHeadingSet] = useState('') + const [ConfigSync, ConfigSyncSet] = useState(ModelConfigSyncInit) + const [ConfigLocal, ConfigLocalSet] = useState(ModelConfigLocalInit) const [Syndicate, SyndicateSet ] = useState({}) const [IsSaving, IsSavingSet] = useState(false) useEffect(() => { console.log('[useEffect]') - ModelConfigSyncGet().then(options_new => ConfigSet(options_new)) - ModelSyndicateGet().then(syndicate_new => SyndicateSet(syndicate_new)) + ModelConfigSyncGet().then(state => ConfigSyncSet(state)) + ModelConfigLocalGet().then(state => ConfigLocalSet(state)) + ModelSyndicateGet().then(state => SyndicateSet(state)) }, []) - if (Config == null) return
Config == null
- let { account, mission, mission_ids, repo, session, session_ids } = Config + if (ConfigSync == null) return
Config == null
+ let { account, mission_ids, repo, session, session_ids } = ConfigSync if (session == undefined) return
Config members undefined
- const [SessionNumber, SessionNumberSet] = useState(0) - - function MissionHeadingUpdate (focus_headline: string) { - MissionHeadingSet(focus_headline) - } - - function SessionHeadingUpdate (focus_headline: string) { - SessionHeadingSet(focus_headline) - } - - function TimesheetPunchHandle () { - if (session == undefined) return - const Time = TimestampSeconds() - const TimeText = new Date(Time * 1000) - if(session == 0) { // End Session - console.log('Clocking on to Session #' + SessionNumber + ' at ' + TimeText) - //@todo Integrate with GitHub to create Session Tickets. - const ConfigNew = {...(Config as ModelConfigSync), session: SessionNumber} - ModelConfigSyncSet(ConfigNew) - ConfigSet(ConfigNew) - } else if (session < 0) { // Stop Break - const S = -session - console.log('Stopping break from Session #' + S + ' at ' + TimeText) - const ConfigNew = {...(Config as ModelConfigSync), session: S} - ModelConfigSyncSet(ConfigNew) - ConfigSet(ConfigNew) - } else { // -> Session > 0 - console.log('Clocking off from Session #' + session + ' at ' + TimeText) - const ConfigNew = {...(Config as ModelConfigSync), session: 0} - ModelConfigSyncSet(ConfigNew) - ConfigSet(ConfigNew) - } - } - - function TimesheetBreakStartHandle () { - if (session == undefined) return - let time = TimestampSeconds() - console.log('Starting break from Session #' + session + ' at ' + new Date(time * 1000)) - const ConfigNew = {...(Config as ModelConfigSync), session: -session} - ModelConfigSyncSet(ConfigNew) - ConfigSet(ConfigNew) - } return
- -

Account: {account} #{Math.abs(session)}

Repo: {repo}

-

Mission: #{Math.abs(mission)}

-

Heading: {session_ids ?? '' + mission_ids}

-
- { session == 0 && <> - - SessionNumberSet(event.target.valueAsNumber) } - disabled={ IsSaving } - /> - - } - { session > 0 && <> - - - } - { session < 0 && - - } - { session == 0 &&
- Session and Mission Heading: - SessionHeadingUpdate(event.target.value) } - disabled={ IsSaving } - /> - Mission heading: - MissionHeadingUpdate(event.target.value) } - disabled={ IsSaving } - /> -
- } -
+

Mission: #{mission_ids}

+

Heading: {session_ids}

+
+
} diff --git a/Extension/Ctlr/Background.ts b/Extension/Ctlr/Background.ts index 9ad87ce..ad85670 100644 --- a/Extension/Ctlr/Background.ts +++ b/Extension/Ctlr/Background.ts @@ -5,6 +5,8 @@ ModelConfigSyncGet, ModelConfigSyncSet, ModelIssueInit, ModelIssueSet, ModelMissionInit, ModelMissionSet, ModelSessionInit, ModelSessionSet, ModelSyndicateInit, ModelSyndicateSet } from '../Model' +import { ASessionInit } from '../../Lib/Model' + console.log("[Background.ts]") chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { @@ -29,7 +31,7 @@ chrome.runtime.onInstalled.addListener(() => { CommandStructureSet(CommandStructureInit) ModelIssueSet(ModelIssueInit) ModelMissionSet(ModelMissionInit) - ModelSessionSet(ModelSessionInit) + ModelSessionSet(ASessionInit) ModelSyndicateSet(ModelSyndicateInit) chrome.alarms.create("Update", { diff --git a/Extension/Ctlr/UseModelState.ts b/Extension/Ctlr/UseModelState.ts new file mode 100644 index 0000000..0bd0732 --- /dev/null +++ b/Extension/Ctlr/UseModelState.ts @@ -0,0 +1,35 @@ +// Copyright AStartup; license at https://github.com/AStarStartup/AStartupMCC + +'use client' + +import { AIssueTicket } from '../../Lib/Model' +import { DataAccess } from '../../Lib/Model/IDB' +import { ModelIssueSet } from '../Model' + +export default function UseModelState(account: string, repo: string) { + let db_name: string = account + '/' + repo + let store_name: string = 'Issues' + const idb = new DataAccess(db_name, store_name); + + function ModelStateReducer(state, action: object) { + switch (action['verb']) { + case 'SelectIssue': { + const UID = action['uid'] + if(UID == undefined) return + const Issue = idb.Get(UID) + ModelIssueSet({ ...state, issue: Issue }) + return state + } + case 'SelectMission': { + const UID = action['uid'] + if(UID == undefined) return + const Issue = idb.Get(UID) + ModelIssueSet({ ...state, mission: Issue }) + return state + } + default: return state + } + } + + return [ idb, ModelStateReducer ] +} diff --git a/Extension/Model/index.ts b/Extension/Model/index.ts index dbf3a3a..6f0136b 100644 --- a/Extension/Model/index.ts +++ b/Extension/Model/index.ts @@ -1,5 +1,7 @@ // Copyright AStartup; license at https://github.com/AStartupMCC +import { ASession } from '../../Lib/Model' + export const UsernameInit = 'CookingWithCale' // Model configuration settings that get synced with the browser. @@ -8,7 +10,6 @@ export type ModelConfigSync = { content_scripts: boolean //< Content scripts enabled. me?: string //< The user's Username. metric_units?: boolean //< Standard (true) or Imperial units. - mission: number //< Current mission number. mission_ids?: string //< Current mission ID string. repo?: string //< Current repo. session?: number //< Current session number (zero means clocked out). @@ -21,53 +22,35 @@ export type ModelConfigLocal = { modal_state: number //< State of the modal. // Options modal_visible: boolean //< Modal is visible flag. + mission: number //< Selected mission number. + repo?: string //< Selected repo. + session?: number //< Selected session number. } -const SessionFocusLengthMax = 100 //< Max length of a session focus heading. - -// The Global App Model state. +// An Incident Command System or similar structure meta model. +export type ACommandStructure = { + uid: string //< 128-bit linear id. + idx: number //< 64-bit packed inode index. + name: string //< Command structure name. + key: string //< The unique key of the command structure. + description: string //< Description of the command structure. + contacts: string //< Point contacts. + date_created: Date //< Date created. + date_modified: Date //< Date modified. + meta: object //< Command structure meta model. +} + +// The global app model state. export type ModelState = { config_sync?: ModelConfigSync //< Synced model config settings. config_local?: ModelConfigLocal //< Local model config settings. command_structure?: Object //< Meta model for the incident command structure. - issue?: Object //< The current issue. - mission?: Object //< The current mission. - session?: Object //< Current session. - syndicate?: Object //< All of the GitHubAccounts in the syndicate. -} - -export type AMission = { - push_count: number //< Number of times this project has bee pushed. -} - -export type AProject = { - push_count: number //< Number of times this project has bee pushed. -} - -export type ACrew = { - handle: string //< This syndicate member's unique handle. -} - -export type ACommandRole = { - master: string, //< Role master's handle. - contact: Object, //< Contact information for this role. - supervisor_roles: string[], //< List of supervisor roles. -} - -export type ACommandStructure = { - rules: ACommandRole[] //< List of the roles in the ICS. -} - -// @todo Document that if the master is an null then it is the IC. If it's an -// empty string then it's unfilled. - -export const ARoles = {} - -export type ASession = { - projects: Object //< Projects worked on in this session. - issues: Object //< Missions - log: Object //< Log for this session/... -} + issue?: Object //< Current issue. + mission?: Object //< Current mission. + repo?: RepoGitHub //< Current repository. + session?: ASession //< Current session. + syndicate?: Object //< GitHub accounts in the syndicate. +}//< Projects worked on in this session. export type ContentFeed = { title: string //< Title of the feed. @@ -132,13 +115,15 @@ export const ModelConfigSyncInit: ModelConfigSync = { session_ids: '', account: 'AStarStartup', repo: 'AStartupMCC', - mission: 0, mission_ids: '' } export const ModelConfigLocalInit: ModelConfigLocal = { modal_visible: false, modal_state: 0, + mission: 0, + repo: '', + session: 0, } // Unpacks the account/repo#MissionNumber.ChildMission from the input string. @@ -218,6 +203,25 @@ export function MissionStringUnpack(input: string) { return [ account, repo, parseInt(mission_number), child_mission ] } +export function MissionSelectedString(syndicate: Object, account: string, repo: string, + mission: number) { + let result = 'Error in MissionSelectedString' + result = syndicate[account]?.['Repos']?.[repo]?.['issues_open']?. + [mission.toString()] + return '#' + mission + ' ' + result + // const Account = syndicate[account] + // if(Account == undefined) return 'Account == undefined' + // const Repos = Account['Repos'] + // if(Repos == undefined) return 'Repos == undefined' + // const Repo = Account[repo] + // if(Repo == undefined) return 'Repo == undefined' + // const IssuesOpen = Account['issues_open'] + // if(IssuesOpen == undefined) return 'IssuesOpen == undefined' + // const MissionTitle = Account[mission.toString()] + // if(MissionTitle == undefined) return 'IssuesOpen[mission] == undefined' + // return '#' + mission + ' ' + MissionTitle +} + // The vanilla Incident Command System Structure. export const CommandStructureInit = { 'command_roles': { @@ -268,9 +272,12 @@ export type GitHubIssue = { open: boolean //< Open (true) or closed (false). } -export type GitHubRepo = { - visibility: boolean //< visibility: public (true) or private (false). - issues_open: Object //< All of the open issue tickets. +export type RepoGitHub = { + account: string //< Repo account. + name: string //< Repo name. + visibility: boolean //< Visibility: public (true) or private (false). + issue_count: number //< The number of issues in the ITS. + issue_count_open: number //< All of the open issue tickets. } export type GitHubAccount = { @@ -364,13 +371,6 @@ export const ModelSyndicateInit: Object = { }, "visibility": false }, - "Typecraft": { - "issues_open": { - "1": "Session.Next.Monday", - "2": "Session.Next.Tuesday" - }, - "visibility": false - }, } }, "CookingWithCale": { @@ -680,7 +680,7 @@ export function ModelConfigSyncSet(config: ModelConfigSync): Promise { export function CommandStructureGet(): Promise { const keys: ModelKeys[] = ['command_structure'] return new Promise((resolve) => { - chrome.storage.local.get(keys, (state: ModelState) => { + chrome.storage.sync.get(keys, (state: ModelState) => { resolve(state.command_structure ?? CommandStructureInit) }) }) @@ -691,7 +691,35 @@ export function CommandStructureSet(command_structure: Object): Promise { command_structure, } return new Promise((resolve) => { - chrome.storage.local.set(Values, () => { + chrome.storage.sync.set(Values, () => { + resolve() + }) + }) +} + +export const RepoGithubDefault: RepoGitHub = { + account: '', + name: '', + visibility: false, + issue_count: 0, + issue_count_open: 0, +} + +export function ModelRepoGet(): Promise { + const keys: ModelKeys[] = ['repo'] + return new Promise((resolve) => { + chrome.storage.sync.get(keys, (state: ModelState) => { + resolve(state.repo ?? RepoGithubDefault) + }) + }) +} + +export function ModelRepoSet(repo: RepoGitHub): Promise { + const Values: ModelState = { + repo, + } + return new Promise((resolve) => { + chrome.storage.sync.set(Values, () => { resolve() }) }) @@ -700,7 +728,7 @@ export function CommandStructureSet(command_structure: Object): Promise { export function ModelIssueGet(): Promise { const keys: ModelKeys[] = ['issue'] return new Promise((resolve) => { - chrome.storage.local.get(keys, (state: ModelState) => { + chrome.storage.sync.get(keys, (state: ModelState) => { resolve(state.issue ?? {}) }) }) @@ -711,7 +739,7 @@ export function ModelIssueSet(issue: Object): Promise { issue, } return new Promise((resolve) => { - chrome.storage.local.set(Values, () => { + chrome.storage.sync.set(Values, () => { resolve() }) }) @@ -720,7 +748,7 @@ export function ModelIssueSet(issue: Object): Promise { export function ModelMissionGet(): Promise { const keys: ModelKeys[] = ['mission'] return new Promise((resolve) => { - chrome.storage.local.get(keys, (state: ModelState) => { + chrome.storage.sync.get(keys, (state: ModelState) => { resolve(state.mission ?? {}) }) }) @@ -737,18 +765,18 @@ export function ModelMissionSet(mission: Object): Promise { mission, } return new Promise((resolve) => { - chrome.storage.local.set(Values, () => { + chrome.storage.sync.set(Values, () => { resolve() }) }) } -export function ModelSessionSet(session: Object): Promise { +export function ModelSessionSet(session: ASession): Promise { const Values: ModelState = { session, } return new Promise((resolve) => { - chrome.storage.local.set(Values, () => { + chrome.storage.sync.set(Values, () => { resolve() }) }) @@ -757,7 +785,7 @@ export function ModelSessionSet(session: Object): Promise { export function ModelSyndicateGet(): Promise { const keys: ModelKeys[] = ['syndicate'] return new Promise((resolve) => { - chrome.storage.local.get(keys, (state: ModelState) => { + chrome.storage.sync.get(keys, (state: ModelState) => { resolve(state.syndicate ?? ModelSyndicateInit) }) }) @@ -768,7 +796,7 @@ export function ModelSyndicateSet(syndicate: Object): Promise { syndicate, } return new Promise((resolve) => { - chrome.storage.local.set(Values, () => { + chrome.storage.sync.set(Values, () => { resolve() }) }) diff --git a/Extension/View/MissionClock.tsx b/Extension/View/MissionClock.tsx deleted file mode 100644 index a431e23..0000000 --- a/Extension/View/MissionClock.tsx +++ /dev/null @@ -1,5 +0,0 @@ -// Copyright AStartup; license at https://github.com/AStarStartup/AStartupMCC - -export default function MissionClock() { - -} diff --git a/Extension/View/MissionSelector.tsx b/Extension/View/MissionSelector.tsx index c727e05..3b3ddc3 100644 --- a/Extension/View/MissionSelector.tsx +++ b/Extension/View/MissionSelector.tsx @@ -1,53 +1,18 @@ // Copyright AStartup; license at https://github.com/AStarStartup/AStartupMCC -import React, { useState } from 'react' -import { ModelConfigSync, ModelConfigSyncSet } from '../Model' +import React from 'react' +import { RepoGitHub, ModelConfigSync, ModelConfigSyncSet +} from '../Model' const { LLIDNextHex } = require('linearid') -// Checks if the issue_num_title starts off with #mission_number_string (i.e #123). -export function IssueIsSelected(issue_num_title: string, mission_number_string: string) { - const MLength = mission_number_string.length - //if(MLength < 1 || issue_num_title.length <= MLength) return false; - // Example issue_is_selected: "ABC" or "A123" or "#123 Working example" - let issue_is_selected = issue_num_title[0] != '#' && MLength < 1 - && issue_num_title.length <= MLength - //if(!issue_is_selected) return issue_is_selected - let i = 0 - for(; i < MLength; ++i) { - if(issue_num_title[i + 1] != mission_number_string[i]) { - issue_is_selected = false - break - } - } - return issue_is_selected && issue_num_title[i + 1] == ' ' -} - -export default function MissionSelector(props: { - Config : ModelConfigSync - ConfigSet: (o: ModelConfigSync) => void - Syndicate: object - }) { - - const { Config, ConfigSet, Syndicate } = props - let { account, mission, repo } = Config - console.log('MissionSelector: account:"' + account + '" repo:"' + repo - + '" mission:"' + mission + '"') - console.log('Config:') - console.log(Config) - console.log("Syndicate:") - console.log(Syndicate) - console.log("repo:") - console.log(repo) - - let repos: string[] = [] - let issues: string[] = [] - - //const [ Account, AccountSet ] = useState(Config.account) - +export function ListReposAndIssues(Syndicate: object, account: string, + repo: string) { + let repo_names: string[] = [] + let issue_id_strings: string[] = [] console.log('Iterating through Syndicates...') Object.entries(Syndicate || {}).forEach(([account_key, account_value]) => { - if(account != account_key && account != 'All') return + if(account != account_key && account != 'All') return [[], []] console.log('Processing entries for account:' + account + ' s_key:' + account_key) //Accounts.push(key) let Repos = Object(account_value)['Repos'] @@ -57,7 +22,7 @@ export default function MissionSelector(props: { console.log('Repos:') console.log(Repos) console.log('Iterating through Repos:') - repos.push(repo ?? '.github') + repo_names.push(repo ?? '.github') Object.entries(Repos || {}).forEach(([repo_key, repo_value]) => { console.log('key:"' + repo_key + '" + repo_value:') console.log(repo_value) @@ -67,22 +32,63 @@ export default function MissionSelector(props: { console.log('my_issues:') console.log(repo_issues) Object.entries(repo_issues || {}).map(([issue_key, issue_value]) => { - issues.push('#' + issue_key + ' ' + issue_value) + issue_id_strings.push('#' + issue_key + ' ' + issue_value) console.log("'#' + key2 + ' ' + value2:" + '#' + issue_key + ' ' + issue_value) }) } else { - repos.push(repo_key) + repo_names.push(repo_key) } }) console.log('Done!') }) console.log("repos:") - console.log(repos) + console.log(repo_names) console.log("issues:") - console.log(issues) + console.log(issue_id_strings) + return [repo_names, issue_id_strings] +} +// Checks if the issue_num_title starts off with #mission_number_string (i.e #123). +export function IssueIsSelected(issue_num_title: string, mission_number_string: string) { + const MLength = mission_number_string.length + //if(MLength < 1 || issue_num_title.length <= MLength) return false; + // Example issue_is_selected: "ABC" or "A123" or "#123 Working example" + let issue_is_selected = issue_num_title[0] != '#' && MLength < 1 + && issue_num_title.length <= MLength + //if(!issue_is_selected) return issue_is_selected + let i = 0 + for(; i < MLength; ++i) { + if(issue_num_title[i + 1] != mission_number_string[i]) { + issue_is_selected = false + break + } + } + return issue_is_selected && issue_num_title[i + 1] == ' ' +} + +export default function MissionSelector(props: { + ConfigSync : ModelConfigSync + ConfigSyncSet: (o: ModelConfigSync) => void + Syndicate: object + }) { + + const { ConfigSync, ConfigSyncSet, Syndicate } = props + let { account, mission_ids, repo } = ConfigSync + console.log('MissionSelector: account:"' + account + '" repo:"' + repo + + '" mission:"' + mission_ids + '"') + console.log('Config:') + console.log(ConfigSync) + console.log("Syndicate:") + console.log(Syndicate) + console.log("repo:") + console.log(repo) + + if(account == undefined || repo == undefined || mission_ids == undefined) + return
Config == null
+ + let [repos, issues] = ListReposAndIssues(Syndicate, account, repo) return
@@ -90,11 +96,10 @@ export default function MissionSelector(props: { { + onChange={e => { console.log("Changing Repo:" + e.target.value) - const ConfigNew = {...Config, account: Config.account, repo: e.target.value} + const ConfigNew = {...ConfigSync, account: ConfigSync.account, repo: e.target.value} ModelConfigSyncSet(ConfigNew).then(() => { - ConfigSet(ConfigNew) + ConfigSyncSet(ConfigNew) }) - }} value={account}> + }} value={repo}> { repos.map((key) => ( - ))}
-
- - { console.log(e.target.value); - const ConfigNew = {...Config, mission_ids: e.target.value} + const ConfigNew = {...ConfigSync, mission_ids: e.target.value} ModelConfigSyncSet(ConfigNew).then(() => { - ConfigSet(ConfigNew) + ConfigSyncSet(ConfigNew) }) - }} value={mission}> + }} value={mission_ids}> { issues.map((issue_num_title) => ( - diff --git a/Extension/View/SessionPunchClockView.tsx b/Extension/View/SessionPunchClockView.tsx new file mode 100644 index 0000000..8656874 --- /dev/null +++ b/Extension/View/SessionPunchClockView.tsx @@ -0,0 +1,101 @@ +// Copyright AStartup; license at https://github.com/AStartupMCC + +import React, { useState } from 'react' +const { TimestampSeconds } = require('linearid') +import MissionSelector from './MissionSelector' +import { ModelConfigSync, ModelConfigSyncSet } from '../Model' + +export default function SessionPunchClockViewView(props: { + ConfigSync : ModelConfigSync + ConfigSyncSet: (o: ModelConfigSync) => void + IsSaving: boolean + Syndicate: object +}) { + const { ConfigSync, ConfigSyncSet, IsSaving, Syndicate } = props + let { session } = ConfigSync + if(session == undefined) return
undefined
+ const [MissionHeading, MissionHeadingSet] = useState('') + const [SessionHeading, SessionHeadingSet] = useState('') + const [SessionNumber, SessionNumberSet] = useState(0) + + function TimesheetPunchHandle () { + if (session == undefined) return + const Time = TimestampSeconds() + const TimeText = new Date(Time * 1000) + if(session == 0) { // End Session + console.log('Clocking on to Session #' + SessionNumber + ' at ' + TimeText) + //@todo Integrate with GitHub to create Session Tickets. + const ConfigNew = {...(ConfigSync as ModelConfigSync), session: SessionNumber} + ModelConfigSyncSet(ConfigNew) + ConfigSyncSet(ConfigNew) + } else if (session < 0) { // Stop Break + const S = -session + console.log('Stopping break from Session #' + S + ' at ' + TimeText) + const ConfigNew = {...(ConfigSync as ModelConfigSync), session: S} + ModelConfigSyncSet(ConfigNew) + ConfigSyncSet(ConfigNew) + } else { // -> Session > 0 + console.log('Clocking off from Session #' + session + ' at ' + TimeText) + const ConfigNew = {...(ConfigSync as ModelConfigSync), session: 0} + ModelConfigSyncSet(ConfigNew) + ConfigSyncSet(ConfigNew) + } + } + + function TimesheetBreakStartHandle () { + if (session == undefined) return + let time = TimestampSeconds() + console.log('Starting break from Session #' + session + ' at ' + new Date(time * 1000)) + const ConfigNew = {...(ConfigSync as ModelConfigSync), session: -session} + ModelConfigSyncSet(ConfigNew) + ConfigSyncSet(ConfigNew) + } + + function MissionHeadingUpdate (focus_headline: string) { + MissionHeadingSet(focus_headline) + } + + function SessionHeadingUpdate (focus_headline: string) { + SessionHeadingSet(focus_headline) + } + + return
+ { session == 0 && <> + + SessionNumberSet(e.target.valueAsNumber) } + disabled={ IsSaving } + /> + + } + { session > 0 && <> + + + } + { session < 0 && + + } + { session == 0 &&
+ Session and Mission Heading: + SessionHeadingUpdate(event.target.value) } + disabled={ IsSaving } + /> + Mission heading: + MissionHeadingUpdate(event.target.value) } + disabled={ IsSaving } + /> +
+ } + +
+} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index 5046719..dbb4f4f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -88,7 +88,7 @@ // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + "strictPropertyInitialization": false, /* Check for class properties that are declared but not set in the constructor. */ // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ @@ -107,6 +107,6 @@ // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ "skipLibCheck": true /* Skip type checking all .d.ts files. */ }, - "include": ["Extension/**/*.ts", "Extension/**/*.tsx"], + "include": ["Extension/**/*.ts", "Extension/**/*.tsx", "Lib/Model/IDB.ts", "Extension/Ctlr/UseModelState.ts"], "exclude": ["node_modules", "Test"] }