diff --git a/lib/files.js b/lib/files.js
index 093b9b5..160ae22 100644
--- a/lib/files.js
+++ b/lib/files.js
@@ -128,17 +128,17 @@ class Files
describe()
{
// Set up
- const result = {}
+ const result = {}
result.count = this.count
- result.items = {}
+ result.items = []
// Each file
for(const _filePath in this.items)
{
const file = this.items[_filePath]
- result.items[_filePath] = file.describe()
+ result.items.push(file.describe())
}
return result
diff --git a/site/src/components/application/script.js b/site/src/components/application/script.js
index dafe547..a0389d0 100644
--- a/site/src/components/application/script.js
+++ b/site/src/components/application/script.js
@@ -1,5 +1,6 @@
import Connexion from '@/components/connexion'
import ProjectsHub from '@/components/projects-hub'
+import Project from '@/components/project'
export default
{
@@ -8,7 +9,8 @@ export default
components:
{
Connexion,
- ProjectsHub
+ ProjectsHub,
+ Project
},
data()
@@ -27,7 +29,7 @@ export default
project()
{
- return this.$store.state.currentProject
+ return this.$store.state.project
}
},
diff --git a/site/src/components/application/template.html b/site/src/components/application/template.html
index 085c035..0a05315 100644
--- a/site/src/components/application/template.html
+++ b/site/src/components/application/template.html
@@ -2,7 +2,5 @@
{{ counter }}
-
- {{ project.name }}
-
+
\ No newline at end of file
diff --git a/site/src/components/connexion/script.js b/site/src/components/connexion/script.js
index 689f432..d1b05ac 100644
--- a/site/src/components/connexion/script.js
+++ b/site/src/components/connexion/script.js
@@ -4,19 +4,71 @@ export default
{
name: 'connexion',
+ computed:
+ {
+ project()
+ {
+ return this.$store.state.project
+ }
+ },
+
+ watch:
+ {
+ project: 'onProjectChange'
+ },
+
created()
{
- this.url = `${process.env.NODE_ENV === 'production' ? '' : 'http://localhost:1571'}/projects`
- this.socket = socketIoClient(this.url)
+ const projectsUrl = `${process.env.NODE_ENV === 'production' ? '' : 'http://localhost:1571'}/projects`
+ this.projectsSocket = socketIoClient(projectsUrl)
- this.socket.on('connect', () =>
+ this.projectsSocket.on('connect', () =>
{
- console.log('connected')
+ // console.log('projects connected')
})
- this.socket.on('update_projects', (data) =>
+ this.projectsSocket.on('update_projects', (data) =>
{
+ // console.log('update_projects', data)
this.$store.commit('updateProjects', data.all)
})
+ },
+
+ methods:
+ {
+ onProjectChange(value)
+ {
+ const projectURL = `${process.env.NODE_ENV === 'production' ? '' : 'http://localhost:1571'}/project/${value.slug}`
+
+ this.projectSocket = socketIoClient(projectURL)
+
+ this.projectSocket.on('connect', () =>
+ {
+ // console.log('project connected')
+ })
+
+ this.projectSocket.on('update_project', (data) =>
+ {
+ // console.log('update_project', data)
+ this.$store.commit('updateFiles', data.files.items)
+ })
+
+ this.projectSocket.on('create_file', (data) =>
+ {
+ // console.log('create_file', data)
+ this.$store.commit('createFile', data)
+ })
+
+ this.projectSocket.on('delete_file', (data) =>
+ {
+ // console.log('delete_file', data)
+ this.$store.commit('deleteFile', data)
+ })
+
+ this.projectSocket.on('createVersion', (data) =>
+ {
+ // console.log('createVersion', data)
+ })
+ }
}
}
\ No newline at end of file
diff --git a/site/src/components/files-tree-file/index.vue b/site/src/components/files-tree-file/index.vue
new file mode 100644
index 0000000..a6fe49a
--- /dev/null
+++ b/site/src/components/files-tree-file/index.vue
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/site/src/components/files-tree-file/script.js b/site/src/components/files-tree-file/script.js
new file mode 100644
index 0000000..eeadae4
--- /dev/null
+++ b/site/src/components/files-tree-file/script.js
@@ -0,0 +1,18 @@
+export default
+{
+ name: 'files-tree-file',
+
+ props:
+ {
+ depth: { type: Number, default: 0 },
+ content: { type: Object }
+ },
+
+ created()
+ {
+ },
+
+ methods:
+ {
+ }
+}
\ No newline at end of file
diff --git a/site/src/components/files-tree-file/style.styl b/site/src/components/files-tree-file/style.styl
new file mode 100644
index 0000000..e69de29
diff --git a/site/src/components/files-tree-file/template.html b/site/src/components/files-tree-file/template.html
new file mode 100644
index 0000000..bc4d6e3
--- /dev/null
+++ b/site/src/components/files-tree-file/template.html
@@ -0,0 +1,5 @@
+
+
+ {{ content.name }}
+
+
\ No newline at end of file
diff --git a/site/src/components/files-tree-folder/index.vue b/site/src/components/files-tree-folder/index.vue
new file mode 100644
index 0000000..a6fe49a
--- /dev/null
+++ b/site/src/components/files-tree-folder/index.vue
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/site/src/components/files-tree-folder/script.js b/site/src/components/files-tree-folder/script.js
new file mode 100644
index 0000000..2ec245f
--- /dev/null
+++ b/site/src/components/files-tree-folder/script.js
@@ -0,0 +1,24 @@
+import FilesTreeFile from '@/components/files-tree-file'
+export default
+{
+ name: 'files-tree-folder',
+
+ components:
+ {
+ FilesTreeFile
+ },
+
+ props:
+ {
+ depth: { type: Number, default: 0 },
+ content: { type: Object }
+ },
+
+ created()
+ {
+ },
+
+ methods:
+ {
+ }
+}
\ No newline at end of file
diff --git a/site/src/components/files-tree-folder/style.styl b/site/src/components/files-tree-folder/style.styl
new file mode 100644
index 0000000..e69de29
diff --git a/site/src/components/files-tree-folder/template.html b/site/src/components/files-tree-folder/template.html
new file mode 100644
index 0000000..bd36e35
--- /dev/null
+++ b/site/src/components/files-tree-folder/template.html
@@ -0,0 +1,7 @@
+
+
+ {{ content.name }}
+
+
+
+
\ No newline at end of file
diff --git a/site/src/components/files-tree/index.vue b/site/src/components/files-tree/index.vue
new file mode 100644
index 0000000..a6fe49a
--- /dev/null
+++ b/site/src/components/files-tree/index.vue
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/site/src/components/files-tree/script.js b/site/src/components/files-tree/script.js
new file mode 100644
index 0000000..d50cfde
--- /dev/null
+++ b/site/src/components/files-tree/script.js
@@ -0,0 +1,60 @@
+import FilesTreeFile from '@/components/files-tree-file'
+import FilesTreeFolder from '@/components/files-tree-folder'
+import FileTree from '@/utils/FileTree'
+
+// const fileTree = new FileTree({ autoWash: true })
+// fileTree.addFolder('./toto', { hey: 'hoy' })
+// fileTree.addFolder('./toto/uhuh', { hey: 'a' })
+// fileTree.addFolder('./lorem')
+// fileTree.addFile('./test-1.txt')
+// fileTree.addFile('./test-2.txt')
+
+// window.setInterval(() =>
+// {
+// fileTree.addFile('./toto/uhuh/' + new Date())
+// fileTree.removeFolder('./lorem')
+// fileTree.removeFile('./test-1.txt')
+// }, 1000)
+
+export default
+{
+ name: 'files-tree',
+
+ components:
+ {
+ FilesTreeFile,
+ FilesTreeFolder
+ },
+
+ data()
+ {
+ return {}
+ },
+
+ computed:
+ {
+ files()
+ {
+ return this.$store.state.files
+ }
+ },
+
+ watch:
+ {
+ files: 'onFilesChange'
+ },
+
+ created()
+ {
+ },
+
+ methods:
+ {
+ onFilesChange(newValue, oldValue)
+ {
+ console.log('onFilesChange')
+ console.log(newValue)
+ console.log(oldValue)
+ }
+ }
+}
\ No newline at end of file
diff --git a/site/src/components/files-tree/style.styl b/site/src/components/files-tree/style.styl
new file mode 100644
index 0000000..e69de29
diff --git a/site/src/components/files-tree/template.html b/site/src/components/files-tree/template.html
new file mode 100644
index 0000000..c2aaad2
--- /dev/null
+++ b/site/src/components/files-tree/template.html
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/site/src/components/project/index.vue b/site/src/components/project/index.vue
new file mode 100644
index 0000000..a6fe49a
--- /dev/null
+++ b/site/src/components/project/index.vue
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/site/src/components/project/script.js b/site/src/components/project/script.js
new file mode 100644
index 0000000..a71250d
--- /dev/null
+++ b/site/src/components/project/script.js
@@ -0,0 +1,27 @@
+import FilesTree from '@/components/files-tree'
+
+export default
+{
+ name: 'project',
+
+ components:
+ {
+ FilesTree
+ },
+
+ computed:
+ {
+ project()
+ {
+ return this.$store.state.project
+ }
+ },
+
+ created()
+ {
+ },
+
+ methods:
+ {
+ }
+}
\ No newline at end of file
diff --git a/site/src/components/project/style.styl b/site/src/components/project/style.styl
new file mode 100644
index 0000000..e69de29
diff --git a/site/src/components/project/template.html b/site/src/components/project/template.html
new file mode 100644
index 0000000..56262ca
--- /dev/null
+++ b/site/src/components/project/template.html
@@ -0,0 +1,4 @@
+
+ {{ project.name }}
+
+
\ No newline at end of file
diff --git a/site/src/components/projects-hub/script.js b/site/src/components/projects-hub/script.js
index 06fc99d..d00e5c0 100644
--- a/site/src/components/projects-hub/script.js
+++ b/site/src/components/projects-hub/script.js
@@ -19,7 +19,7 @@ export default
{
onProjectClick(projectSlug)
{
- this.$store.commit('setCurrentProject', projectSlug)
+ this.$store.commit('setProject', projectSlug)
}
}
}
\ No newline at end of file
diff --git a/site/src/store.js b/site/src/store.js
index 471b758..6f44b51 100644
--- a/site/src/store.js
+++ b/site/src/store.js
@@ -1,27 +1,34 @@
import Vue from 'vue'
import Vuex from 'vuex'
+import FileTree from '@/utils/FileTree'
+
Vue.use(Vuex)
export default new Vuex.Store({
state:
{
projects: {},
- currentProject: null
+ project: null,
+ files: new FileTree({ autoWash: true }),
+ file: null
},
mutations:
{
+ /**
+ * Projects
+ */
updateProjects(state, data)
{
state.projects = data
// Has a current project
- if(state.currentProject)
+ if(state.project)
{
// Current project has been removed
if(typeof state.projects[data] === 'undefined')
{
- state.currentProject = null
+ state.project = null
}
}
@@ -33,7 +40,7 @@ export default new Vuex.Store({
// If only one project, set has current
if(projectKeys.length === 1)
{
- state.currentProject = state.projects[projectKeys[0]]
+ state.project = state.projects[projectKeys[0]]
}
}
},
@@ -43,13 +50,36 @@ export default new Vuex.Store({
state.projects.push(data)
},
- setCurrentProject(state, data)
+ setProject(state, data)
{
// Test of project exist
if(typeof state.projects[data] !== 'undefined')
{
- state.currentProject = state.projects[data]
+ state.project = state.projects[data]
}
+ },
+
+ /**
+ * Files
+ */
+ updateFiles(state, data)
+ {
+ state.files = new FileTree({ autoWash: true })
+
+ for(const file of data)
+ {
+ state.files.addFile(file.path.full, file)
+ }
+ },
+
+ createFile(state, data)
+ {
+ state.files.addFile(data.path.full, data)
+ },
+
+ deleteFile(state, data)
+ {
+ state.files.removeFile(data.path.full)
}
}
})
\ No newline at end of file
diff --git a/site/src/utils/FileTree.js b/site/src/utils/FileTree.js
new file mode 100644
index 0000000..07bd2bf
--- /dev/null
+++ b/site/src/utils/FileTree.js
@@ -0,0 +1,688 @@
+class FileTree
+{
+ /**
+ * Create tree and add ./ folder
+ * @param {Object} _options
+ * @param {Boolean} _options.auto_wash - Should clean empty folder on removes
+ */
+ constructor(_options = {})
+ {
+ // Options
+ this.autoWash = typeof _options.autoWash === 'undefined' ? false : _options.autoWash
+
+ // Set up
+ this.folders = []
+ this.addFolder('.', {})
+ }
+
+ /**
+ * Clean path
+ * @param {String} _path - Path to clean
+ * @return {String} Cleaned path
+ */
+ cleanPath(_path = '')
+ {
+ // Errors
+ if(typeof _path !== 'string')
+ {
+ console.warn('cleanPath: _path should be a string')
+ return false
+ }
+
+ let path = _path
+
+ // Trim
+ path = path.trim()
+
+ // Repeating `/`
+ path = path.replace(/\/+/g, '/')
+
+ // Ending `/`
+ path = path.replace(/\/$/, '')
+
+ console.log(path)
+
+ // Starting `.`
+ path = path.replace(/^\./, '')
+
+ // Starting `/`
+ path = path.replace(/^\//, '')
+
+ path = './' + path
+
+ return path
+ }
+
+ /**
+ * Add a folder
+ * Can create nested folder in one path
+ * @param {String} _path - Path to the folder (start with `./`)
+ * @param {Object} _data - Properties to add to the folder
+ * @returns {Object} Created folder
+ */
+ addFolder(_path = '', _data = {})
+ {
+ // Errors
+ if(typeof _path !== 'string')
+ {
+ console.warn('addFolder: _path should be a string')
+ return false
+ }
+ if(typeof _data !== 'object')
+ {
+ console.warn('addFolder: _data should be an object')
+ return false
+ }
+
+ // Set up
+ const path = this.cleanPath(_path)
+ const pathParts = path.split('/')
+
+ let folders = this.folders
+ let folder = null
+
+ // Each path part
+ for(const _part of pathParts)
+ {
+ const index = folders.findIndex((folder) => _part === folder.name)
+
+ // Already exist
+ if(index !== -1)
+ {
+ folder = folders[index]
+ folders = folder.folders
+ }
+
+ // Folder doesn't exist
+ else
+ {
+ // Create folder
+ folder = {
+ folders: [],
+ files: [],
+ name: _part,
+ data: _data
+ }
+
+ // Save
+ folders.push(folder)
+ folders = folder.folders
+ }
+ }
+
+ // Return
+ return folder
+ }
+
+ /**
+ * Add a file
+ * Will create folders if needed
+ * @param {String} _path - Path to the folder (start with `./`)
+ * @param {Object} _data - Properties to add to the file
+ * @returns {Object} Created file
+ */
+ addFile(_path = '', _data = {})
+ {
+ // Errors
+ if(typeof _path !== 'string')
+ {
+ console.warn('addFile: _path should be a string')
+ return false
+ }
+ if(typeof _data !== 'object')
+ {
+ console.warn('addFile: _data should be an object')
+ return false
+ }
+
+ // Set up
+ const path = this.cleanPath(_path)
+ const pathParts = path.split('/')
+ const filePart = pathParts.pop()
+
+ // Create folder
+ const folder = this.addFolder(pathParts.join('/'))
+
+ // Create file
+ const file = {
+ name: filePart,
+ data: _data
+ }
+
+ // Save
+ folder.files.push(file)
+
+ return file
+ }
+
+ /**
+ * Remove folder
+ * Will delete contained folders and contained files
+ * @param {String} _path - Folder to delete (start with `./`)
+ * @returns {Boolean} Folder deleted or not
+ */
+ removeFolder(_path = '')
+ {
+ // Recursive emptying
+ const emptyFolder = function(folder)
+ {
+ // Delete folders
+ for(const _folderKey in folder.folders)
+ {
+ const _folder = folder.folders[_folderKey]
+
+ emptyFolder(_folder)
+
+ folder.folders.splice(_folderKey, 1)
+
+ // Callback
+ if(typeof _folder.data.onRemove === 'function')
+ {
+ _folder.data.onRemove.apply(this, [_folder])
+ }
+ }
+
+ // Delete files
+ for(const _fileKey in folder.files)
+ {
+ const _file = folder.files[_fileKey]
+
+ folder.files.splice(_fileKey, 1)
+
+ // Callback
+ if(typeof _file.data.onRemove === 'function')
+ {
+ _file.data.onRemove.apply(this, [_file])
+ }
+ }
+ }
+
+ // Errors
+ if(typeof _path !== 'string')
+ {
+ console.warn('removeFolder: _path should be a string')
+ return false
+ }
+
+ // Set up
+ const path = this.cleanPath(_path)
+ const pathParts = path.split('/')
+ const folderPart = pathParts.pop()
+
+ let folders = this.folders
+ let folder = null
+
+ // Each path part
+ for(const _part of pathParts)
+ {
+ const index = folders.findIndex((folder) => _part === folder.name)
+
+ // Found
+ if(index !== -1)
+ {
+ folder = folders[index]
+ folders = folder.folders
+ }
+
+ // Not found
+ else
+ {
+ folder = null
+ folders = null
+ break
+ }
+ }
+
+ // Found
+ const index = folders.findIndex((folder) => folderPart === folder.name)
+ if(folders && index !== -1)
+ {
+ const folder = folders[index]
+
+ // Delete
+ emptyFolder(folder)
+ folders.splice(index, 1)
+
+ // Callback
+ if(typeof folder.data.onRemove === 'function')
+ {
+ folder.data.onRemove.apply(this, [folder])
+ }
+
+ // Auto wash
+ if(this.autoWash)
+ {
+ this.removeEmptyFolders()
+ }
+
+ return true
+ }
+
+ return false
+ }
+
+ /**
+ * Remove file
+ * Will delete contained folders and contained files
+ * @param {String} _path - File to delete (start with `./`)
+ * @returns {Boolean} File deleted or not
+ */
+ removeFile(_path = '')
+ {
+ // Errors
+ if(typeof _path !== 'string')
+ {
+ console.warn('removeFile: _path should be a string')
+ return false
+ }
+
+ // Set up
+ const path = this.cleanPath(_path)
+ const pathParts = path.split('/')
+ const filePart = pathParts.pop()
+
+ let folders = this.folders
+ let folder = null
+
+ // Each path part
+ for(const _part of pathParts)
+ {
+ const index = folders.findIndex((folder) => _part === folder.name)
+
+ // Found
+ if(index !== -1)
+ {
+ folder = folders[index]
+ folders = folder.folders
+ }
+
+ // Not found
+ else
+ {
+ folder = null
+ folders = null
+ break
+ }
+ }
+
+ // Folder found
+ if(folders && folder)
+ {
+ const index = folder.files.findIndex((file) => filePart === file.name)
+
+ // File found
+ if(index !== -1)
+ {
+ const file = folder.files[index]
+
+ // Delete
+ folder.files.splice(index, 1)
+
+ // Auto wash
+ if(this.autoWash)
+ {
+ this.removeEmptyFolders()
+ }
+
+ // Callback
+ if(typeof file.data.onRemove === 'function')
+ {
+ file.data.onRemove.apply(this, [file])
+ }
+
+ return true
+ }
+ }
+
+ return false
+ }
+
+ /**
+ * Get file
+ * @param {String} _path - Path to file
+ * @returns {Object} File
+ */
+ getFile(_path = '')
+ {
+ // Errors
+ if(typeof _path !== 'string')
+ {
+ console.warn('getFile: _path should be a string')
+ return false
+ }
+
+ // Set up
+ const path = this.cleanPath(_path)
+ const pathParts = path.split('/')
+ const filePart = pathParts.pop()
+
+ let folders = this.folders
+ let folder = null
+
+ // Each path part
+ for(const _part of pathParts)
+ {
+ const index = folders.findIndex((folder) => _part === folder.name)
+
+ // Found
+ if(index !== -1)
+ {
+ folder = folders[index]
+ folders = folder.folders
+ }
+
+ // Not found
+ else
+ {
+ folder = null
+ folders = null
+ break
+ }
+ }
+
+ // Folder found
+ if(folders && folder)
+ {
+ const index = folder.files.findIndex((file) => filePart === file.name)
+
+ if(index !== -1)
+ {
+ const file = folder.files[index]
+ return file
+ }
+ }
+
+ return false
+ }
+
+ /**
+ * Get folder
+ * @param {String} _path - Path to folder
+ * @returns {Object} Folder
+ */
+ getFolder(_path = '')
+ {
+ // Errors
+ if(typeof _path !== 'string')
+ {
+ console.warn('getFolder: _path should be a string')
+ return false
+ }
+
+ // Set up
+ const path = this.cleanPath(_path)
+ const pathParts = path.split('/')
+
+ let folders = this.folders
+ let folder = null
+
+ // Each path part
+ for(const _part of pathParts)
+ {
+ const index = folders.findIndex((folder) => _part === folder.name)
+
+ // Found
+ if(index !== -1)
+ {
+ folder = folders[index]
+ folders = folder.folders
+ }
+
+ // Folder doesn't exist
+ else
+ {
+ return false
+ }
+ }
+
+ // Return
+ return folder
+ }
+
+ /**
+ * Browse every folders and remove empty ones
+ * @return {Number} Number of removed folders
+ */
+ removeEmptyFolders()
+ {
+ // Set up
+ let removedCount = 0
+
+ // Recursive remove
+ const canRemoveFolder = function(folder)
+ {
+ // Each folder inside current folder
+ for(const _folderKey in folder.folders)
+ {
+ // Try to remove folder
+ const _folder = folder.folders[_folderKey]
+ const canRemove = canRemoveFolder(_folder)
+
+ // Remove folder
+ if(canRemove)
+ {
+ removedCount++
+
+ // Delete
+ folder.folders.splice(_folderKey, 1)
+
+ // Callback
+ if(typeof _folder.data.onRemove === 'function')
+ {
+ _folder.data.onRemove.apply(this, [_folder])
+ }
+ }
+ }
+
+ // Can be removed
+ const folderKeys = Object.keys(folder.folders)
+ const filesKeys = Object.keys(folder.files)
+
+ if(folderKeys.length === 0 && filesKeys.length === 0)
+ {
+ return true
+ }
+ else
+ {
+ return false
+ }
+ }
+
+ // Try from ./
+ canRemoveFolder(this.folders[0])
+
+ return removedCount
+ }
+
+ /**
+ * Describe the tree in ASCII (├ ─ │ └)
+ * @param {Boolean} _log - Directly log to console
+ * @param {Boolean} _colored - Colored tree (only work well in Chrome)
+ * @return {String} Tree
+ */
+ describe(_log = false, _colored = false)
+ {
+ // Set up
+ const depth = 0
+ const styles = []
+
+ let stringTree = ''
+
+ const addToString = function(value = '', type = null)
+ {
+ if(_colored)
+ {
+ stringTree += '%c'
+
+ switch(type)
+ {
+ case 'structure':
+ styles.push('color:#999;')
+ break
+
+ case 'folder':
+ styles.push('color:#999;')
+ break
+ case 'file':
+ styles.push('color:#333;font-weight:bold;')
+ break
+
+ default:
+ styles.push('')
+ break
+ }
+ }
+
+ stringTree += value
+ }
+
+ // Recursive describe
+ const describeFolder = function(folder, depth, last = [])
+ {
+ // Each folders
+ for(let i = 0; i < folder.folders.length; i++)
+ {
+ // Set up
+ const _folder = folder.folders[i]
+
+ // Add to tree string
+ addToString('\n')
+
+ for(let j = 0; j < depth; j++)
+ {
+ if(j === depth - 1)
+ {
+ if(i === folder.folders.length - 1 && folder.files.length === 0)
+ {
+ addToString(' └', 'structure')
+ }
+ else
+ {
+ addToString(' ├', 'structure')
+ }
+ }
+ else
+ {
+ if(last[j])
+ {
+ addToString(' ', 'structure')
+ }
+ else
+ {
+ addToString(' │', 'structure')
+ }
+ }
+ }
+
+ addToString('─', 'structure')
+ addToString(_folder.name, 'folder')
+ addToString('/', 'structure')
+
+ // Last
+ last.push(i === folder.folders.length - 1 && folder.files.length === 0)
+
+ // Continue
+ describeFolder(_folder, depth + 1, last)
+ }
+
+ // Each files
+ for(let i = 0; i < folder.files.length; i++)
+ {
+ // Set up
+ const _file = folder.files[i]
+
+ // Add to tree string
+ stringTree += '\n'
+
+ for(let j = 0; j < depth; j++)
+ {
+ if(j === depth - 1)
+ {
+ if(i === folder.files.length - 1)
+ {
+ addToString(' └', 'structure')
+ }
+ else
+ {
+ addToString(' ├', 'structure')
+ }
+ }
+ else
+ {
+ if(last[j])
+ {
+ addToString(' ', 'structure')
+ }
+ else
+ {
+ addToString(' │', 'structure')
+ }
+ }
+ }
+
+ addToString('─', 'structure')
+ addToString(_file.name, 'file')
+ }
+ }
+
+ // Describe from ./
+ addToString('.', 'folder')
+ addToString('/', 'structure')
+ describeFolder(this.folders[0], depth + 1)
+
+ // Log
+ if(_log)
+ {
+ console.log(...[stringTree].concat(styles))
+ }
+
+ return stringTree
+ }
+}
+
+
+// /**
+// * Tests
+// */
+// const filesTree = new FileTree()
+
+// filesTree.addFolder('./hey/hoy', { active: false, notifs: 0 })
+// filesTree.addFolder('./hey/hoy/toto', { active: false, notifs: 0 })
+// filesTree.addFolder('./hey/hoy/tata', { active: false, notifs: 0 })
+
+// filesTree.addFile('./test-1.txt', { active: false, notifs: 0 })
+// filesTree.addFile('./hey/hoy/test-2.txt', { active: false, notifs: 0 })
+// filesTree.addFile('./hey/hoy/test-3.txt', { active: false, notifs: 0 })
+// filesTree.addFile('./hey/hoy/tata/test-4.txt', { active: false, notifs: 0 })
+// filesTree.addFile('./hey/hoy/toto/test-5.txt', { active: false, notifs: 0 })
+
+// filesTree.addFile('./hey/hoy/toto/test-6.txt', {
+// active: false,
+// notifs: 0,
+// onRemove: (file) =>
+// {
+// console.log('removed file :', file)
+// }
+// })
+// filesTree.removeFile('./hey/hoy/toto/test-6.txt')
+
+// filesTree.addFolder('./pwet', {
+// onRemove: (folder) =>
+// {
+// console.log('removed folder :', folder)
+// }
+// })
+// filesTree.addFolder('./pwet/uh', {
+// onRemove: (folder) =>
+// {
+// console.log('removed folder :', folder)
+// }
+// })
+// filesTree.removeFolder('./pwet')
+
+// filesTree.removeFile('./hey/hoy/test-2.txt')
+// filesTree.removeFolder('./hey')
+
+// filesTree.describe(true, true)
+
+export default FileTree
\ No newline at end of file