imdone-core 1.45.1 → 1.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/adapters/file-gateway.js +22 -0
- package/lib/card.js +2 -0
- package/lib/config.js +12 -0
- package/lib/file.js +1 -0
- package/lib/migrate-config.js +19 -5
- package/lib/mixins/repo-fs-store.js +2 -1
- package/lib/plugins/archive-plugin.js +58 -0
- package/lib/plugins/plugin-manager.js +6 -2
- package/lib/project.js +50 -55
- package/lib/repository.js +11 -7
- package/package.json +1 -1
- package/cli.js +0 -225
- package/lib/cli/CliControler.js +0 -327
- package/lib/cli/MDStoryParser.js +0 -139
- package/lib/cli/ProjectConfigFactory.js +0 -114
- package/lib/cli/adapters/ApplicationContext.js +0 -6
- package/lib/cli/adapters/Errors.js +0 -8
- package/lib/cli/adapters/LogAdapter.js +0 -3
- package/lib/cli/adapters/StorageAdapter.js +0 -135
- package/lib/cli/domain/BacklogProject.js +0 -170
- package/lib/cli/domain/StoryProject.js +0 -67
- package/lib/cli/prompts/MarkdownPlanPrompt.js +0 -16
- package/lib/plugins/cli-backlog-plugin.js +0 -152
|
@@ -1,135 +0,0 @@
|
|
|
1
|
-
const simpleGit = require('simple-git')
|
|
2
|
-
const {changesExistError, ChangesExistError} = require('./Errors')
|
|
3
|
-
|
|
4
|
-
module.exports = class {
|
|
5
|
-
|
|
6
|
-
constructor(project) {
|
|
7
|
-
this.project = project
|
|
8
|
-
this.git = simpleGit(this.path)
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
get path() {
|
|
12
|
-
return this.project.path
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
get remote() {
|
|
16
|
-
return this.pluginConfig.remote
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
get defaultBranch() {
|
|
20
|
-
return this.pluginConfig.defaultBranch
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
get pluginConfig() {
|
|
24
|
-
return this.project.config.settings.plugins.CliBacklogPlugin
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
async initTaskUpdate(task) {
|
|
28
|
-
if (await this.changesExist()) {
|
|
29
|
-
throw new ChangesExistError('start a task')
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
await this.checkoutStoryBranch({task})
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async commitTaskUpdate(task) {
|
|
36
|
-
const taskBranchName = this.getTaskBranchName(task)
|
|
37
|
-
await this.project.addMetadata(task, 'branch', taskBranchName)
|
|
38
|
-
await this.git.add('.').commit(`Update task ${this.getTaskName(task)}`)
|
|
39
|
-
await this.git.push(this.remote)
|
|
40
|
-
await this.git.checkoutBranch(taskBranchName, this.getStoryBranchName({task}))
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
async initStoryPlan(storyId) {
|
|
44
|
-
if (await this.changesExist()) {
|
|
45
|
-
throw new ChangesExistError('plan a story')
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
await this.checkoutStoryBranch({storyId})
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
async saveStoryPlan(storyId) {
|
|
52
|
-
const storyBranchName = this.getStoryBranchName({storyId})
|
|
53
|
-
await this.git.add('.').commit(`Update story ${storyId}`)
|
|
54
|
-
await this.git.push(this.remote)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
getTaskName(task) {
|
|
58
|
-
return this.project.getTaskName(task)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
getStoryId(task) {
|
|
62
|
-
return this.project.getStoryId(task)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
getStoryBranchName({task, storyId}) {
|
|
66
|
-
return `${this.getStoryBranchPrefix({task, storyId})}/main`
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
getStoryBranchPrefix({task, storyId}) {
|
|
70
|
-
return `story/${storyId || this.getStoryId(task)}`
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
getTaskBranchName(task) {
|
|
74
|
-
const storyBranchPrefix = this.getStoryBranchPrefix({task})
|
|
75
|
-
const taskName = this.getTaskName(task)
|
|
76
|
-
return `${storyBranchPrefix}/task/${taskName}`
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
async getCurrentTask() {
|
|
80
|
-
const currentBranch = await this.getCurrentBranch()
|
|
81
|
-
const tasks = this.project.getTasks(`meta.branch="${currentBranch}"`)
|
|
82
|
-
return tasks && tasks.length == 1 && tasks[0]
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
async getCurrentBranch() {
|
|
86
|
-
return (await this.git.branchLocal()).current
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
async changesExist() {
|
|
90
|
-
return !(await this.git.status()).isClean()
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
async checkoutDefaultBranch() {
|
|
94
|
-
const defaultBranch = this.defaultBranch
|
|
95
|
-
await this.fetch()
|
|
96
|
-
await this.git.checkout(defaultBranch)
|
|
97
|
-
await this.pull()
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
async checkoutStoryBranch({task, storyId}) {
|
|
101
|
-
const storyBranchName = this.getStoryBranchName({task, storyId})
|
|
102
|
-
|
|
103
|
-
await this.checkoutDefaultBranch()
|
|
104
|
-
|
|
105
|
-
if (await this.branchExists(storyBranchName)) {
|
|
106
|
-
await this.git.checkout(storyBranchName)
|
|
107
|
-
await this.pull()
|
|
108
|
-
} else {
|
|
109
|
-
await this.git.checkoutBranch(
|
|
110
|
-
storyBranchName,
|
|
111
|
-
this.defaultBranch
|
|
112
|
-
)
|
|
113
|
-
await this.pushNewBranch(storyBranchName)
|
|
114
|
-
}
|
|
115
|
-
await this.git.merge([this.defaultBranch])
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async branchExists(branchName) {
|
|
119
|
-
const branches = await this.git.branchLocal()
|
|
120
|
-
return branches.all.includes(branchName)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async pull() {
|
|
124
|
-
await this.git.pull(this.remote)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async fetch() {
|
|
128
|
-
await this.git.fetch(this.remote)
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async pushNewBranch(branchName) {
|
|
132
|
-
await this.git.push(this.remote, branchName, {'--set-upstream': null})
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
}
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
const { createFileSystemProject } = require('../../project-factory')
|
|
2
|
-
const { resolve } = path = require('path')
|
|
3
|
-
const STORIES_DIR = 'stories'
|
|
4
|
-
const STORY_ID = 'story-id'
|
|
5
|
-
const TASK_ID = 'task-id'
|
|
6
|
-
const TODO = 'TODO'
|
|
7
|
-
const DOING = 'DOING'
|
|
8
|
-
const DONE = 'DONE'
|
|
9
|
-
const ORDER = 'order'
|
|
10
|
-
const UNGROUPED_TASKS = 'Ungrouped Tasks'
|
|
11
|
-
|
|
12
|
-
class BacklogProject {
|
|
13
|
-
constructor(projectPath, config, ApplicationContext = require('../adapters/ApplicationContext')) {
|
|
14
|
-
this.ApplicationContext = ApplicationContext
|
|
15
|
-
this.StorageAdapter = ApplicationContext().StorageAdapter
|
|
16
|
-
this.projectPath = resolve(projectPath)
|
|
17
|
-
this._config = config
|
|
18
|
-
this.project = null
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
get path() {
|
|
22
|
-
return this.projectPath
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
get name() {
|
|
26
|
-
return this.project.name
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
get defaultList() {
|
|
30
|
-
return this.config.getDefaultList()
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
get config() {
|
|
34
|
-
return this.project && this.project.config || this._config
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async init() {
|
|
38
|
-
this.project = createFileSystemProject({path: this.projectPath, config: this.config})
|
|
39
|
-
await this.project.init()
|
|
40
|
-
this.storageAdapter = new this.StorageAdapter(this)
|
|
41
|
-
return this
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
getStoryProjectPath(storyId) {
|
|
45
|
-
return getStoryProjectPath(this.path, storyId)
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async addStory(content) {
|
|
49
|
-
await this.addTaskToFile({list: TODO, content })
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
toStoryId(text) {
|
|
53
|
-
return this.project.sanitizeFileName(text)
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
removeList(list) {
|
|
57
|
-
return this.project.removeList(list)
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
getStoryIds() {
|
|
61
|
-
return [
|
|
62
|
-
...new Set(
|
|
63
|
-
this.project.getCards(`meta.${STORY_ID}=* AND tags=story`).map(({meta, text, list}) => ({text, list, storyId: meta[STORY_ID][0]}))
|
|
64
|
-
)
|
|
65
|
-
]
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
tasksToJson(tasks) {
|
|
69
|
-
return tasks.map(({text, type, list, meta, content, tags, context, description, source, beforeText, order}) =>
|
|
70
|
-
({
|
|
71
|
-
list,
|
|
72
|
-
type,
|
|
73
|
-
order,
|
|
74
|
-
path: source.path,
|
|
75
|
-
prefix: beforeText,
|
|
76
|
-
text,
|
|
77
|
-
content,
|
|
78
|
-
description,
|
|
79
|
-
tags,
|
|
80
|
-
context,
|
|
81
|
-
meta
|
|
82
|
-
})
|
|
83
|
-
)
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
getTaskName(task) {
|
|
87
|
-
return this.toStoryId(task.text)
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async startTask(taskId) {
|
|
91
|
-
await this.init()
|
|
92
|
-
|
|
93
|
-
const taskFilter = `meta.${TASK_ID}="${taskId}"`
|
|
94
|
-
const task = this.project.getAllCards(taskFilter)[0]
|
|
95
|
-
if (!task) throw new Error(`No task found with id ${taskId}`)
|
|
96
|
-
|
|
97
|
-
const storyId = task.meta[STORY_ID][0]
|
|
98
|
-
const storyFilter = `tags=story AND meta.${STORY_ID}="${storyId}"`
|
|
99
|
-
const story = this.project.getAllCards(storyFilter)[0]
|
|
100
|
-
|
|
101
|
-
await this.storageAdapter.initTaskUpdate(task)
|
|
102
|
-
await this.moveTask(task, DOING, 0)
|
|
103
|
-
await this.project.addMetadata(task, 'branch', this.storageAdapter.getTaskBranchName(task))
|
|
104
|
-
this.project.rollBackFileForTask(task)
|
|
105
|
-
await this.moveTask(story, DOING, 0)
|
|
106
|
-
await this.storageAdapter.commitTaskUpdate(task)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async saveStory(storyId) {
|
|
110
|
-
// // Switch to the story branch or create it
|
|
111
|
-
// await git.checkout(storyBranchName);
|
|
112
|
-
// await git.pull('origin', storyBranchName, { '--force': null });
|
|
113
|
-
|
|
114
|
-
// // Push the changes to the story branch with force
|
|
115
|
-
// await git.push('origin', storyBranchName, { '--force': null });
|
|
116
|
-
|
|
117
|
-
// // Return to the original branch
|
|
118
|
-
// await git.checkout(currentBranch);
|
|
119
|
-
|
|
120
|
-
// Merge the story branch into the current branch
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
async moveTask(task, list, order) {
|
|
125
|
-
return await this.project.moveTask(task, list, order)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
async addTaskToFile({path, list, tags, content, meta, contexts=[]}) {
|
|
129
|
-
return await this.project.addTaskToFile({path, list, tags, content, meta, contexts, useCardTemplate: true})
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
async addMetadata(task, key, value) {
|
|
133
|
-
return await this.project.addMetadata(task, key, value)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
getCurrentStoryId() {
|
|
137
|
-
const tasks = this.project.getAllCards(`tags = "story" AND list = "${DOING}"`)
|
|
138
|
-
if (tasks.length < 1) return
|
|
139
|
-
return this.getStoryId(tasks[0])
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
getStoryId(task) {
|
|
143
|
-
return task.meta[STORY_ID][0]
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
async getCurrentTask() {
|
|
147
|
-
return await this.storageAdapter.getCurrentTask()
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
function getStoryProjectPath(projectPath, storyId) {
|
|
152
|
-
return path.join(projectPath, STORIES_DIR, storyId)
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
BacklogProject.getStoryProjectPath = getStoryProjectPath
|
|
156
|
-
BacklogProject.createAndInit = async function(projectPath, config, ApplicationContext) {
|
|
157
|
-
return (await (new BacklogProject(projectPath, config, ApplicationContext)).init())
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
BacklogProject.constants = {
|
|
161
|
-
STORIES_DIR,
|
|
162
|
-
STORY_ID,
|
|
163
|
-
TASK_ID,
|
|
164
|
-
TODO,
|
|
165
|
-
DOING,
|
|
166
|
-
DONE,
|
|
167
|
-
ORDER,
|
|
168
|
-
UNGROUPED_TASKS
|
|
169
|
-
}
|
|
170
|
-
module.exports = BacklogProject
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
const path = require('path')
|
|
2
|
-
const BacklogProject = require('./BacklogProject')
|
|
3
|
-
const {
|
|
4
|
-
STORY_ID,
|
|
5
|
-
TASK_ID,
|
|
6
|
-
DONE,
|
|
7
|
-
DOING,
|
|
8
|
-
UNGROUPED_TASKS
|
|
9
|
-
} = BacklogProject.constants
|
|
10
|
-
|
|
11
|
-
class StoryProject extends BacklogProject {
|
|
12
|
-
constructor(projectPath, config, storyId, ApplicationContext = require('../adapters/ApplicationContext')) {
|
|
13
|
-
super(BacklogProject.getStoryProjectPath(projectPath, storyId), config, ApplicationContext)
|
|
14
|
-
this.storyId = storyId
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
async addTask({content, group = UNGROUPED_TASKS}) {
|
|
18
|
-
const file = await this.addTaskToFile({list: this.defaultList, content})
|
|
19
|
-
file.rollback().extractTasks(this.config)
|
|
20
|
-
const task = file.tasks[0]
|
|
21
|
-
if (group !== UNGROUPED_TASKS) {
|
|
22
|
-
await this.project.removeMetadata(task, 'group', UNGROUPED_TASKS)
|
|
23
|
-
await this.project.addMetadata(task, 'group', group)
|
|
24
|
-
}
|
|
25
|
-
return file.tasks[0]
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
async completeTask() {
|
|
29
|
-
const task = await this.getCurrentTask()
|
|
30
|
-
if (!task) throw new Error('No current task')
|
|
31
|
-
await this.project.moveTask(task, DONE)
|
|
32
|
-
return task
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
getTaskId(task) {
|
|
36
|
-
return task.meta[TASK_ID][0]
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
getTaskName(task) {
|
|
40
|
-
const ext = path.extname(task.file.path)
|
|
41
|
-
return path.basename(task.file.path, ext)
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
getTasks(filter) {
|
|
45
|
-
filter = filter ? ` AND ${filter}` : ''
|
|
46
|
-
return this.project.getAllCards('tags=task' + filter)
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
getTask(taskId) {
|
|
50
|
-
return this.project.getCards(`tags=task AND meta.${TASK_ID}="${taskId}"`)[0]
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
getStory() {
|
|
54
|
-
return this.project.getAllCards(`tags=story`)[0]
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
get name() {
|
|
58
|
-
return this.project.name
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
StoryProject.createAndInit = async function(projectPath, config, storyId, ApplicationContext) {
|
|
64
|
-
return (await (new StoryProject(projectPath, config, storyId, ApplicationContext)).init())
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
module.exports = StoryProject
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
const defaultStory = `# Story Title
|
|
2
|
-
|
|
3
|
-
Story description
|
|
4
|
-
`
|
|
5
|
-
module.exports.promptForMarkdownPlan = async function () {
|
|
6
|
-
const editor = (await import('@inquirer/editor')).default
|
|
7
|
-
|
|
8
|
-
return await editor({
|
|
9
|
-
message: 'Enter the story title and description markdown',
|
|
10
|
-
validate: function (text) {
|
|
11
|
-
if (!text) return 'Please enter a description'
|
|
12
|
-
return true
|
|
13
|
-
},
|
|
14
|
-
default: defaultStory
|
|
15
|
-
});
|
|
16
|
-
}
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
const Plugin = require('imdone-api')
|
|
2
|
-
const eol = require('eol')
|
|
3
|
-
const _path = require('path')
|
|
4
|
-
const {
|
|
5
|
-
dirname
|
|
6
|
-
} = require('path')
|
|
7
|
-
const { rmdir } = require('fs').promises
|
|
8
|
-
const {
|
|
9
|
-
UNGROUPED_TASKS,
|
|
10
|
-
STORY_ID,
|
|
11
|
-
ORDER
|
|
12
|
-
} = require('../cli/domain/BacklogProject').constants
|
|
13
|
-
const { newStoryProject } = require('../cli/ProjectConfigFactory')
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const generateRandomString = (length) => {
|
|
17
|
-
let result = '';
|
|
18
|
-
const characters =
|
|
19
|
-
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
20
|
-
const charactersLength = characters.length;
|
|
21
|
-
for (let i = 0; i < length; i++) {
|
|
22
|
-
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
|
23
|
-
}
|
|
24
|
-
return result;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
const PROJECT_TYPES = {
|
|
28
|
-
BACKLOG_PROJECT: 'BACKLOG_PROJECT',
|
|
29
|
-
STORY_PROJECT: 'STORY_PROJECT'
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
module.exports = class CliBacklogPlugin extends Plugin {
|
|
33
|
-
get projectType() {
|
|
34
|
-
return this.getSettings().projectType
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
get isStoryProject() {
|
|
38
|
-
return this.projectType === PROJECT_TYPES.STORY_PROJECT
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
get isBacklogProject() {
|
|
42
|
-
return this.projectType === PROJECT_TYPES.BACKLOG_PROJECT
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
get cardActionsMethod() {
|
|
46
|
-
return this.isStoryProject
|
|
47
|
-
? this.getStoryProjectCardActions
|
|
48
|
-
: this.isBacklogProject
|
|
49
|
-
? this.getBacklogProjectCardActions
|
|
50
|
-
: () => []
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
get boardActionsMethod() {
|
|
54
|
-
return this.isStoryProject
|
|
55
|
-
? this.getStoryProjectBoardActions
|
|
56
|
-
: this.isBacklogProject
|
|
57
|
-
? this.getBacklogProjectBoardActions
|
|
58
|
-
: () => []
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async onBeforeAddTask({path, list, meta, tags, contexts, content}) {
|
|
63
|
-
if (!this.isBacklogProject) return {path, content, meta, tags, contexts}
|
|
64
|
-
const project = this.project
|
|
65
|
-
const storyId = project.sanitizeFileName(eol.split(content)[0])
|
|
66
|
-
const storyProject = await newStoryProject({projectPath: project.path, storyId})
|
|
67
|
-
path = _path.join(storyProject.path, 'README.md')
|
|
68
|
-
meta.push({key: STORY_ID, value: storyId})
|
|
69
|
-
meta.push({key: ORDER, value: 0})
|
|
70
|
-
return {path, content, meta, tags, contexts}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async onAfterDeleteTask(task) {
|
|
74
|
-
if (!this.isBacklogProject) return
|
|
75
|
-
const project = this.project
|
|
76
|
-
await rmdir(dirname(task.fullPath), {recursive: true})
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
getStoryProjectBoardActions() {
|
|
80
|
-
const project = this.project
|
|
81
|
-
|
|
82
|
-
const groups = [...new Set(
|
|
83
|
-
project.getCards('meta.group = *').map((card) => card.meta.group && card.meta.group[0])
|
|
84
|
-
)].map(group => {
|
|
85
|
-
const name = group
|
|
86
|
-
const value = `"${group}"`
|
|
87
|
-
return { name, value}
|
|
88
|
-
})
|
|
89
|
-
const groupActions = [{name: 'All tasks', value: '*'}, ...groups].map(({name, value}) => {
|
|
90
|
-
const filterValue = encodeURIComponent(`meta.group = ${value} and tags = task`)
|
|
91
|
-
return {
|
|
92
|
-
name,
|
|
93
|
-
action: function () {
|
|
94
|
-
project.openUrl(`imdone://active.repo?filter=${filterValue}`)
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
})
|
|
98
|
-
const storyId = project.getAllCards('meta.story-id = *')[0].meta['story-id'][0]
|
|
99
|
-
const storiesDir = _path.dirname(project.path)
|
|
100
|
-
const backlogDir = _path.dirname(storiesDir)
|
|
101
|
-
const showStoryAction = {
|
|
102
|
-
name: 'Show story',
|
|
103
|
-
action: function () {
|
|
104
|
-
const query = encodeURIComponent(`allMeta.story-id="${storyId}"`)
|
|
105
|
-
project.openUrl(`imdone://${backlogDir}?filter=${query}`) // imdone:///Users/jesse/projects/imdone-projects/imdone-core/backlog?filter=allMeta.story-id="Board-action-to-show-backlog-from-story-project"
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
return [showStoryAction, ...groupActions]
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
getBacklogProjectBoardActions() {
|
|
113
|
-
return []
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
getStoryProjectCardActions(card) {
|
|
117
|
-
return []
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
getBacklogProjectCardActions(card) {
|
|
121
|
-
const fullPath = card.fullPath
|
|
122
|
-
const project = this.project
|
|
123
|
-
const storyProjectPath = dirname(fullPath)
|
|
124
|
-
const title = `Open story tasks`
|
|
125
|
-
return card.tags.includes('story') ? [
|
|
126
|
-
{
|
|
127
|
-
action: function () {
|
|
128
|
-
project.openUrl(`imdone://${storyProjectPath}`)
|
|
129
|
-
},
|
|
130
|
-
pack: 'fas',
|
|
131
|
-
icon: 'check-square',
|
|
132
|
-
title
|
|
133
|
-
}
|
|
134
|
-
] : []
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
getCardActions(card) {
|
|
138
|
-
return this.cardActionsMethod(card)
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
getBoardActions() {
|
|
142
|
-
return this.boardActionsMethod()
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
getCardProperties(task) {
|
|
146
|
-
return {
|
|
147
|
-
sid: generateRandomString(5),
|
|
148
|
-
projectName: this.project.name,
|
|
149
|
-
ungroupedTasks: UNGROUPED_TASKS
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
}
|