WorkingGroupsCommandBase.ts 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. import ExitCodes from '../ExitCodes'
  2. import { flags } from '@oclif/command'
  3. import { AvailableGroups, GroupMember, OpeningDetails, ApplicationDetails } from '../Types'
  4. import chalk from 'chalk'
  5. import { memberHandle } from '../helpers/display'
  6. import WorkingGroupCommandBase from './WorkingGroupCommandBase'
  7. /**
  8. * Abstract base class for commands related to all working groups
  9. */
  10. export default abstract class WorkingGroupsCommandBase extends WorkingGroupCommandBase {
  11. static flags = {
  12. group: flags.enum({
  13. char: 'g',
  14. description:
  15. 'The working group context in which the command should be executed\n' +
  16. `Available values are: ${AvailableGroups.join(', ')}.`,
  17. required: false,
  18. options: [...AvailableGroups],
  19. }),
  20. ...WorkingGroupCommandBase.flags,
  21. }
  22. async promptForApplicationsToAccept(opening: OpeningDetails): Promise<number[]> {
  23. const acceptedApplications = await this.simplePrompt<number[]>({
  24. message: 'Select succesful applicants',
  25. type: 'checkbox',
  26. choices: opening.applications.map((a) => ({
  27. name: ` ${a.applicationId}: ${memberHandle(a.member)}`,
  28. value: a.applicationId,
  29. })),
  30. })
  31. return acceptedApplications
  32. }
  33. async getOpeningForLeadAction(id: number): Promise<OpeningDetails> {
  34. const opening = await this.getApi().groupOpening(this.group, id)
  35. if (!opening.type.isOfType('Regular')) {
  36. this.error('A lead can only manage Regular openings!', { exit: ExitCodes.AccessDenied })
  37. }
  38. return opening
  39. }
  40. // An alias for better code readibility in case we don't need the actual return value
  41. validateOpeningForLeadAction = this.getOpeningForLeadAction
  42. async getApplicationForLeadAction(id: number): Promise<ApplicationDetails> {
  43. const application = await this.getApi().groupApplication(this.group, id)
  44. const opening = await this.getApi().groupOpening(this.group, application.openingId)
  45. if (!opening.type.isOfType('Regular')) {
  46. this.error('A lead can only manage Regular opening applications!', { exit: ExitCodes.AccessDenied })
  47. }
  48. return application
  49. }
  50. async getWorkerForLeadAction(id: number, requireStakeProfile = false): Promise<GroupMember> {
  51. const groupMember = await this.getApi().groupMember(this.group, id)
  52. const groupLead = await this.getApi().groupLead(this.group)
  53. if (groupLead?.workerId.eq(groupMember.workerId)) {
  54. this.error('A lead cannot manage his own role this way!', { exit: ExitCodes.AccessDenied })
  55. }
  56. if (requireStakeProfile && !groupMember.stake) {
  57. this.error('This worker has no associated role stake profile!', { exit: ExitCodes.InvalidInput })
  58. }
  59. return groupMember
  60. }
  61. // Helper for better TS handling.
  62. // We could also use some magic with conditional types instead, but those don't seem be very well supported yet.
  63. async getWorkerWithStakeForLeadAction(id: number): Promise<GroupMember & Required<Pick<GroupMember, 'stake'>>> {
  64. return (await this.getWorkerForLeadAction(id, true)) as GroupMember & Required<Pick<GroupMember, 'stake'>>
  65. }
  66. async init(): Promise<void> {
  67. await super.init()
  68. const { flags } = this.parse(this.constructor as typeof WorkingGroupsCommandBase)
  69. if (flags.group) {
  70. this._group = flags.group
  71. }
  72. this.log(chalk.magentaBright('Current Group: ' + this.group))
  73. }
  74. }