task.tsx 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /**
  2. * Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. import { PluginUIComponent } from './base';
  7. import { OrderedMap } from 'immutable';
  8. import { TaskManager } from '../mol-plugin/util/task-manager';
  9. import { filter } from 'rxjs/operators';
  10. import { Progress } from '../mol-task';
  11. import { IconButton } from './controls/common';
  12. import { CancelSvg } from './controls/icons';
  13. export class BackgroundTaskProgress extends PluginUIComponent<{ }, { tracked: OrderedMap<number, TaskManager.ProgressEvent> }> {
  14. componentDidMount() {
  15. const hideOverlay = !!this.plugin.spec.components?.hideTaskOverlay;
  16. this.subscribe(this.plugin.events.task.progress.pipe(filter(e => e.level === 'background' && (hideOverlay || !e.useOverlay))), e => {
  17. this.setState({ tracked: this.state.tracked.set(e.id, e) });
  18. });
  19. this.subscribe(this.plugin.events.task.finished, ({ id }) => {
  20. this.setState({ tracked: this.state.tracked.delete(id) });
  21. });
  22. }
  23. state = { tracked: OrderedMap<number, TaskManager.ProgressEvent>() };
  24. render() {
  25. return <div className='msp-background-tasks'>
  26. {this.state.tracked.valueSeq().map(e => <ProgressEntry key={e!.id} event={e!} />)}
  27. </div>;
  28. }
  29. }
  30. class ProgressEntry extends PluginUIComponent<{ event: TaskManager.ProgressEvent }> {
  31. abort = () => {
  32. this.plugin.managers.task.requestAbort(this.props.event.progress.root.progress.taskId, 'User Request');
  33. }
  34. render() {
  35. const root = this.props.event.progress.root;
  36. const subtaskCount = countSubtasks(this.props.event.progress.root) - 1;
  37. const pr = root.progress.isIndeterminate
  38. ? void 0
  39. : <>[{root.progress.current}/{root.progress.max}]</>;
  40. const subtasks = subtaskCount > 0
  41. ? <>[{subtaskCount} subtask(s)]</>
  42. : void 0;
  43. return <div className='msp-task-state'>
  44. <div>
  45. {root.progress.canAbort && <IconButton svg={CancelSvg} onClick={this.abort} title='Abort' />}
  46. <div>
  47. {root.progress.message} {pr} {subtasks}
  48. </div>
  49. </div>
  50. </div>;
  51. }
  52. }
  53. function countSubtasks(progress: Progress.Node) {
  54. if (progress.children.length === 0) return 1;
  55. let sum = 0;
  56. for (const c of progress.children) sum += countSubtasks(c);
  57. return sum;
  58. }
  59. export class OverlayTaskProgress extends PluginUIComponent<{ }, { tracked: OrderedMap<number, TaskManager.ProgressEvent> }> {
  60. componentDidMount() {
  61. this.subscribe(this.plugin.events.task.progress.pipe(filter(e => !!e.useOverlay)), e => {
  62. this.setState({ tracked: this.state.tracked.set(e.id, e) });
  63. });
  64. this.subscribe(this.plugin.events.task.finished, ({ id }) => {
  65. this.setState({ tracked: this.state.tracked.delete(id) });
  66. });
  67. }
  68. state = { tracked: OrderedMap<number, TaskManager.ProgressEvent>() };
  69. render() {
  70. if (this.state.tracked.size === 0) return null;
  71. return <div className='msp-overlay-tasks'>
  72. {this.state.tracked.valueSeq().map(e => <ProgressEntry key={e!.id} event={e!} />)}
  73. </div>;
  74. }
  75. }