Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
jdurrant
binana
Commits
123afe60
Commit
123afe60
authored
Mar 13, 2022
by
jdurrant
Browse files
Working towards compatibility with updated file-loading system.
parent
1ff8d3dd
Changes
53
Expand all
Hide whitespace changes
Inline
Side-by-side
CHANGES.md
View file @
123afe60
# Changes
## 2.2
1.
Updated file loader system.
## 2.1
1.
Web-browser app: changes to how interactions are displayed.
...
...
web_app/package-lock.json
View file @
123afe60
This diff is collapsed.
Click to expand it.
web_app/package.json
View file @
123afe60
...
...
@@ -15,6 +15,7 @@
"devDependencies"
:
{
"@types/file-saver"
:
"^2.0.1"
,
"@types/jquery"
:
"^3.5.4"
,
"@types/jszip"
:
"^3.4.1"
,
"clean-webpack-plugin"
:
"^3.0.0"
,
"closure-webpack-plugin"
:
"^2.3.0"
,
"copy-webpack-plugin"
:
"^5.1.2"
,
...
...
@@ -44,7 +45,8 @@
"bootstrap-vue"
:
"^2.21.2"
,
"file-saver"
:
"^2.0.5"
,
"google-closure-compiler"
:
"^20210601.0.0"
,
"jszip"
:
"^3.5.0"
,
"jszip"
:
"^3.7.1"
,
"localforage"
:
"^1.10.0"
,
"markdown-it"
:
"^12.2.0"
,
"neo-blessed"
:
"^0.2.0"
,
"popper.js"
:
"^1.16.1"
,
...
...
web_app/src/BINANA.worker.ts
View file @
123afe60
...
...
@@ -29,6 +29,8 @@ self.onmessage = function(e) {
params
.
push
(
paramVal
);
}
debugger
;
binana
[
"
run
"
](
params
);
// Get the output.
...
...
web_app/src/UI/FileLoaderSystem/Common/CommonProps.VueFuncs.ts
0 → 100644
View file @
123afe60
// Released under the Apache 2.0 License. See LICENSE.md or go to
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 2022
// Jacob D. Durrant.
// A place to put properties that are common to multiple components.
// Common to mol-loader, and file loaders.
export
var
commonMultipleFilesProps
=
{
"
multipleFiles
"
:
{
"
type
"
:
Boolean
,
"
default
"
:
false
},
"
saveMultipleFilesToDatabase
"
:
{
// Saves copies of files to database for use elsewhere (even after page
// reload). But I can imagine scenarios when you'd want to load multiple
// files without realoading the page, so false by default.
"
type
"
:
Boolean
,
"
default
"
:
false
},
}
// Properties common to file load, from PDB, from URL, etc.
export
var
commonFileLoaderProps
=
{
"
id
"
:
{
"
type
"
:
String
,
"
required
"
:
false
},
"
required
"
:
{
"
type
"
:
Boolean
,
"
default
"
:
true
,
},
"
accept
"
:
{
"
type
"
:
String
,
"
default
"
:
""
,
// e.g., ".pdbqt, .out, .pdb"
},
"
convert
"
:
{
"
type
"
:
String
,
"
default
"
:
""
,
// e.g., ".sdf, .mol2"
},
"
valid
"
:
{
"
type
"
:
Boolean
,
"
default
"
:
true
}
}
export
var
commonProteinEditingProps
=
{
"
allowAtomExtract
"
:
{
"
type
"
:
Boolean
,
"
default
"
:
false
},
"
allowAtomDelete
"
:
{
"
type
"
:
Boolean
,
"
default
"
:
true
}
}
// Used in both queue-catcher and queue-controller.
export
var
commonQueueProps
=
{
"
trigger
"
:
{
"
type
"
:
Boolean
,
"
default
"
:
false
,
"
required
"
:
true
},
"
countDownSeconds
"
:
{
"
type
"
:
Number
,
"
default
"
:
5
},
"
molLoaderIds
"
:
{
"
type
"
:
Array
,
"
required
"
:
true
},
"
outputZipFilename
"
:
{
"
type
"
:
String
,
"
default
"
:
"
output.zip
"
}
}
\ No newline at end of file
web_app/src/UI/FileLoaderSystem/Common/FileLoaderFormGroup.Vue/FileLoaderFormGroup.Vue.ts
View file @
123afe60
// This file is released under the Apache 2.0 License. See
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 202
1
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 202
2
// Jacob D. Durrant.
import
{
addCSS
}
from
"
../Utils
"
;
...
...
@@ -54,9 +54,9 @@ export function setupFileLoaderFormGroup(): void {
:label="label"
:label-for="id"
:id="'input-group-' + id"
:style="styl"
label-cols="0"
label-cols-
xl="1
"
:style="styl
+ ';max-width:none !important;'
"
:
label-cols="
label ? 12 :
0"
:
label-cols-
sm="label ? 2 : 0
"
>
<slot></slot>
<small
...
...
@@ -75,7 +75,10 @@ export function setupFileLoaderFormGroup(): void {
</span>
`
,
"
props
"
:
{
"
label
"
:
String
,
"
label
"
:
{
"
type
"
:
String
,
"
default
"
:
undefined
},
"
id
"
:
String
,
"
styl
"
:
String
,
"
description
"
:
String
,
...
...
@@ -91,7 +94,6 @@ export function setupFileLoaderFormGroup(): void {
"
methods
"
:
{},
"
mounted
"
()
{
addCSS
(
`.file-loader-form-group .col-form-label { hyphens: auto; }`
);
// max-width: 100px !important;
}
})
}
web_app/src/UI/FileLoaderSystem/Common/FileLoaderTextInput.ts
View file @
123afe60
// This file is released under the Apache 2.0 License. See
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 202
1
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 202
2
// Jacob D. Durrant.
declare
var
Vue
;
...
...
@@ -20,20 +20,33 @@ export function setupFileLoaderTextInput(): void {
};
},
"
methods
"
:
{
/**
* Runs when the file is loaded.
* @returns void
*/
"
onLoad
"
():
void
{
this
.
$emit
(
"
onLoad
"
,
this
[
"
value
"
]);
},
/**
* Detect keypress to submit on enter.
* @param {KeyboardEvent} e
* @returns void
*/
"
keydown
"
(
e
:
KeyboardEvent
):
void
{
if
(
e
.
key
===
"
Enter
"
)
{
this
[
"
onLoad
"
]();
}
},
/**
* Detect keyup for v-bind.
* @param {KeyboardEvent} e
* @returns void
*/
"
keyup
"
(
e
:
KeyboardEvent
)
:
void
{
this
.
$emit
(
"
input
"
,
this
[
"
localValue
"
]);
}
// "clearText"(): void {
// this["val"] = "";
// }
},
"
template
"
:
/*html*/
`
<b-input-group>
...
...
web_app/src/UI/FileLoaderSystem/Common/Interfaces.ts
View file @
123afe60
// This file is released under the Apache 2.0 License. See
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 202
1
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 202
2
// Jacob D. Durrant.
import
{
ISelection
,
ParentMol
}
from
"
../Mols/ParentMol
"
;
export
interface
IVueXVar
{
name
:
string
;
val
:
any
;
}
export
interface
IConvert
extends
IFileInfo
{
onConvertDone
:
Function
;
export
interface
IConvert
extends
IFileInfo
{
onConvertDone
:
Function
;
// Must return IFileInfo
onConvertCancel
:
Function
;
}
export
interface
IFileInfo
{
filename
:
string
;
fileContents
:
string
;
// onConvertDone: IConvert;
// convertedResolveFunc?: Function;
// convertedRejectFunc?: Function;
// id?: string; // associated component id
mol
:
ParentMol
;
}
export
interface
IFileLoadError
{
...
...
@@ -26,20 +24,32 @@ export interface IFileLoadError {
body
:
string
;
}
// export interface IFileFromTextField {
// placeholder: string;
// tabName: string;
// loadFunc: Function
// onSuccess: Function;
// onError: Function;
// }
export
interface
IAllFiles
{
selectedFilename
:
string
;
allFiles
:
{[
key
:
string
]:
string
};
// filename => contents
}
export
interface
IResidueInfo
{
residueId
:
string
[],
residuePdbLines
:
string
export
interface
IExtractInfo
{
selection
:
ISelection
[],
pdbLines
:
string
,
origFilename
:
string
,
suggestedNewFilename
:
string
}
/**
* Converts ISelection to a string for labelling.
* @param {ISelection} sel
* @returns string
*/
export
function
iSelectionToStr
(
sel
:
ISelection
):
string
{
if
(
sel
[
"
chains
"
]
&&
!
sel
[
"
resnames
"
]
&&
!
sel
[
"
resids
"
])
{
// Only has chain.
return
"
Chain:
"
+
sel
[
"
chains
"
];
}
let
prts
=
[];
if
(
sel
[
"
resnames
"
])
{
prts
.
push
(
sel
[
"
resnames
"
]);
}
if
(
sel
[
"
resids
"
])
{
prts
.
push
(
sel
[
"
resids
"
]);
}
if
(
sel
[
"
chains
"
])
{
prts
.
push
(
sel
[
"
chains
"
]);
}
return
prts
.
join
(
"
:
"
);
}
\ No newline at end of file
web_app/src/UI/FileLoaderSystem/Common/SmallPillBtn.Vue/README.md
0 → 100644
View file @
123afe60
You can omit this if this component is registered globally (lots of other
components you use might already be using this one).
\ No newline at end of file
web_app/src/UI/FileLoaderSystem/Common/SmallPillBtn.Vue/index.ts
0 → 100644
View file @
123afe60
// This file is released under the Apache 2.0 License. See
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 2022
// Jacob D. Durrant.
declare
var
Vue
;
/** An object containing the vue-component computed functions. */
let
computedFunctions
=
{}
/**
* Setup the small-pill-btn Vue commponent.
* @returns void
*/
export
function
setupSmallPillBtn
():
void
{
Vue
.
component
(
'
small-pill-btn
'
,
{
/**
* Get the data associated with this component.
* @returns any The data.
*/
"
data
"
:
function
()
{
return
{}
},
"
computed
"
:
computedFunctions
,
"
template
"
:
/* html */
`
<b-button
pill :variant="actionStyling === 'delete' ? 'secondary' : 'outline-secondary'" size="sm"
class="py-0 px-1"
style="line-height:14px; font-size:90%; margin-right:2px;"
@click="onClick"
>
<span
v-if="actionStyling === 'extract'"
style="display:inline-block; transform: scaleX(-1);">➚
</span>
<span v-else>✖</span>
<slot></slot>
</b-button>
<!-- style="line-height:14px; font-size:80%;" -->
`
,
"
props
"
:
{
"
actionStyling
"
:
{
"
type
"
:
String
,
"
default
"
:
"
delete
"
// Can also be "extract"
}
},
"
methods
"
:
{
"
onClick
"
():
void
{
this
.
$emit
(
"
click
"
);
}
},
"
mounted
"
()
{}
})
}
web_app/src/UI/FileLoaderSystem/Common/Utils.ts
View file @
123afe60
// This file is released under the Apache 2.0 License. See
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 202
1
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 202
2
// Jacob D. Durrant.
import
{
getMol
}
from
"
../Mols
"
;
import
{
ParentMol
}
from
"
../Mols/ParentMol
"
;
import
{
IFileInfo
,
IFileLoadError
}
from
"
./Interfaces
"
;
/**
* Takes a string of extensions and returns an array of extensions.
* @param {string} exts A string containing a list of extensions separated by
* commas.
* @returns array
*/
export
function
extsStrToList
(
exts
:
string
):
string
[]
{
return
exts
.
toLowerCase
()
...
...
@@ -14,19 +22,103 @@ export function extsStrToList(exts: string): string[] {
);
}
export
function
getExt
(
filename
:
string
):
string
{
/**
* Given a filename, return the basename of the file
* @param {string} filename The filename to get the basename of.
* @param {boolean} [extensive=true] If true, considers multi-component
* extensions (e.g., .pdb.txt).
* @returns {string}
*/
export
function
getBasename
(
filename
:
string
,
extensive
=
true
):
string
{
let
ext
=
getExt
(
filename
,
extensive
);
return
filename
.
substring
(
0
,
filename
.
length
-
ext
.
length
-
1
);
}
/**
* Given a filename, return the extension of the file
* @param {string} filename The filename to get the extension from.
* @param {boolean} [extensive=true] If true, considers multi-component
* extensions (e.g., .pdb.txt).
* @returns {string}
*/
export
function
getExt
(
filename
:
string
,
extensive
=
true
):
string
{
if
(
filename
===
undefined
)
{
return
""
;
}
let
fileNameParts
=
filename
.
toLowerCase
().
split
(
/
\.
/g
);
let
ext
=
fileNameParts
[
fileNameParts
.
length
-
1
];
if
(
extensive
)
{
for
(
let
i
=
fileNameParts
.
length
-
2
;
i
>
0
;
i
--
)
{
// Note that because length -2 and i > 0 (not i > -1), doesn't get
// last (always included) or first (never included) parts. Assuming
// here that if any part has more than four characters, no longer
// extension. This is an arbitrary choice.
let
prt
=
fileNameParts
[
i
];
if
(
prt
.
length
>
4
)
{
break
;
}
ext
=
prt
+
"
.
"
+
ext
;
}
}
return
ext
;
}
/**
* Get the type of a file given the extension.
* @param {string} ext The extension.
* @param {string[]} [choices=undefined] The file-type options.
* @returns {string} The detected type (one of the elements ni choices, if it's
* given).
*/
export
function
getFileTypeFromExt
(
ext
:
string
,
choices
:
string
[]
=
undefined
):
string
{
// Remove first letter from ext if it is "."
if
(
ext
.
substring
(
0
,
1
)
===
"
.
"
)
{
ext
=
ext
.
substring
(
1
);
}
// Get the extension parts
let
extPrts
=
ext
.
split
(
/
\.
/g
);
if
(
choices
===
undefined
)
{
return
extPrts
.
pop
().
toLowerCase
();
}
// Choices need to be lower case
let
choicesLowerCase
=
choices
.
map
(
c
=>
c
.
toLowerCase
());
// In windows, text files often have the ".txt" extension, even if they are
// other formats (e.g., pdb.txt).
if
(
extPrts
[
extPrts
.
length
-
1
]
===
"
txt
"
)
{
// But if txt is one of the choicesLowerCase, choose that.
if
(
choicesLowerCase
.
indexOf
(
"
txt
"
)
!==
-
1
)
{
return
"
txt
"
;
}
extPrts
.
pop
();
}
let
lastExtPrt
=
extPrts
.
pop
();
let
idx
=
choicesLowerCase
.
indexOf
(
lastExtPrt
);
if
(
idx
===
-
1
)
{
// Not one of the choicesLowerCase
return
undefined
;
}
return
choices
[
idx
];
}
// let fileType = getFileTypeFromExt(".pdb.txt", ["pdb"]);
// fileType = getFileTypeFromExt(".pdb.txt", ["pdb", "txt"]);
// fileType = getFileTypeFromExt(".pdb", ["pdb"]);
// fileType = getFileTypeFromExt(".pdb", undefined);
/**
* Given a file object, returns a promise that resolves the text
* in that file.
* @param {*} fileObj The file object.
* @returns Promise
*/
export
function
getFileObjContents
(
fileObj
):
Promise
<
any
>
{
export
function
getFileObjContents
(
fileObj
):
Promise
<
string
>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
var
fr
=
new
FileReader
();
fr
.
onload
=
()
=>
{
...
...
@@ -35,17 +127,15 @@ export function getFileObjContents(fileObj): Promise<any> {
resolve
(
new
TextDecoder
(
"
utf-8
"
).
decode
(
data
));
};
fr
.
readAsArrayBuffer
(
fileObj
);
// Reset the show non-protein atom's link.
// if (this["id"] === "receptor") {
// this.$store.commit("setVar", {
// name: "showKeepProteinOnlyLink",
// val: true,
// });
// }
});
}
/**
* Loads a remote file and sends it to the relevant Vue component.
* @param {string} url The URL of the remote file to load.
* @param {*} vueComp The Vue component.
* @returns {Promise<boolean>}
*/
export
function
loadRemote
(
url
:
string
,
vueComp
:
any
):
Promise
<
boolean
>
{
let
urlUpper
=
url
.
toUpperCase
();
if
(
...
...
@@ -77,7 +167,7 @@ export function loadRemote(url: string, vueComp: any): Promise<boolean> {
let
filesInfo
:
IFileInfo
[]
=
[{
filename
:
flnm
,
fileContents
:
text
mol
:
getMol
(
flnm
,
text
)
}
as
IFileInfo
]
let
allFilesLoaded
=
vueComp
.
onFilesLoaded
(
filesInfo
);
...
...
@@ -95,10 +185,10 @@ export function loadRemote(url: string, vueComp: any): Promise<boolean> {
})
}
export
function
deepCopy
(
obj
:
any
):
any
{
return
JSON
.
parse
(
JSON
.
stringify
(
obj
));
}
/**
* Add a CSS string to the document's head
* @param {string} css The CSS to be added to the page.
*/
export
function
addCSS
(
css
:
string
):
void
{
document
.
head
.
appendChild
(
Object
.
assign
(
document
.
createElement
(
"
style
"
),
{
...
...
@@ -106,8 +196,20 @@ export function addCSS(css: string): void {
}));
}
/**
* Takes a string and converts it to lowercase, replaces any non-alphanumeric
* characters with dashes, and replaces any double dashes with a single dash.
* @param {string} complexString The string to be slugified.
* @returns {string}
*/
export
function
slugify
(
complexString
:
string
):
string
{
// With help from codex
var
slug
=
complexString
.
toLowerCase
().
replace
(
/
[^
a-z0-9
]
+/g
,
'
-
'
);
slug
=
slug
.
replace
(
/
\-\-
/g
,
"
-
"
);
return
slug
;
}
\ No newline at end of file
}
export
function
deepCopy
(
obj
:
any
):
any
{
return
Object
.
assign
({},
obj
);
}
web_app/src/UI/FileLoaderSystem/FileLoader/Setup.ts
deleted
100644 → 0
View file @
1ff8d3dd
// This file is released under the Apache 2.0 License. See
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 2021
// Jacob D. Durrant.
import
*
as
FileLoaderVue
from
"
./FileLoader.Vue
"
;
import
{
FileLoaderInputPlugin
}
from
"
./Plugins/FileLoaderInput.Vue
"
;
import
{
PDBIDInputPlugin
}
from
"
./Plugins/PDBIDInput
"
;
import
{
URLInputPlugin
}
from
"
./Plugins/URLInput
"
;
export
function
setupFileLoader
()
{
// Always load all plugins. Whether they are displayed will be specified
// within vue.js, but just always load them all.
FileLoaderVue
.
setup
([
new
FileLoaderInputPlugin
().
setup
(),
new
PDBIDInputPlugin
().
setup
(),
new
URLInputPlugin
().
setup
()
]);
}
\ No newline at end of file
web_app/src/UI/FileLoaderSystem/FileList.Vue/Methods.VueFuncs.ts
→
web_app/src/UI/FileLoaderSystem/
MolLoader.Vue/
FileList.Vue/Methods.VueFuncs.ts
View file @
123afe60
// This file is released under the Apache 2.0 License. See
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 202
1
// https://opensource.org/licenses/Apache-2.0 for full details. Copyright 202
2
// Jacob D. Durrant.
import
{
deepCopy
}
from
"
../Common/Utils
"
;
/** An object containing the vue-component methods functions. */
export
let
fileLoaderFileListMethodsFunctions
=
{
"
fileDismissed
"
(
filename
)
{
// removeFileFromDatabase(this["id"], filename, this["associatedFileLoaderComponent"])
let
files
=
deepCopy
(
this
[
"
value
"
]);
let
keys
=
Object
.
keys
(
files
);
/**
* Remove a loaded file and select the next file.
* @param {string} filename The name of the file to dismiss.
*/
"
fileDismissed
"
(
filename
:
string
)
{
let
keys
=
Object
.
keys
(
this
[
"
value
"
]);
let
idx
=
keys
.
indexOf
(
filename
);
let
newIdx
=
(
idx
===
0
)
?
idx
+
1
:
idx
-
1
;
let
newFilename
=
keys
[
newIdx
];
this
[
"
fileNameClicked
"
](
newFilename
);
delete
files
[
filename
];
// delete files[filename];
this
.
$delete
(
this
[
"
value
"
],
filename
);
this
.
$emit
(
"
input
"
,
files
);
this
.
$emit
(
"
input
"
,
this
[
"
value
"
]
);
this
.
$emit
(
"
onSelectedFilenameChange
"
,
newFilename
);
// this.$nextTick(() => {
// this.$emit("onRequestRemoveFile", filename);
// });
},
/**
* Clears all entries in the list
*/
"
clearAll
"
():
void
{
// Clears all entries in the list.
// this.$emit("onRequestRemoveAllFiles");
this
.
$emit
(
"
input
"
,
{});
this
.
$emit
(
"
onSelectedFilenameChange
"
,
""
);
// clearAllInDatabase(this["id"]);