Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
c29e9f2
UI to edit text and numeric properties done.
CraigHawker Dec 1, 2022
2ea7824
Editing and saving of single-line-text and numeric properties works.
CraigHawker Dec 1, 2022
b800795
Limited text property entry to 100 chars.
CraigHawker Dec 1, 2022
a60396e
Comments. Regex fix.
CraigHawker Dec 1, 2022
d6083e7
Better UI for when save is disabled.
CraigHawker Dec 1, 2022
1a69dcc
Fixes for logic around numeric values.
CraigHawker Dec 1, 2022
9c0e70e
Booleans editable
CraigHawker Dec 1, 2022
6319037
Multi-line text properties work.
CraigHawker Dec 1, 2022
be57977
Can tab through items.
CraigHawker Dec 1, 2022
f8cd145
Dates work.
CraigHawker Dec 2, 2022
1debf73
Times work.
CraigHawker Dec 2, 2022
ec05b42
Required simple properties now validated.
CraigHawker Dec 2, 2022
0ddea2c
Timestamps work.
CraigHawker Dec 2, 2022
c801a24
Showed time picker for time values.
CraigHawker Dec 2, 2022
6ec690c
Removed seconds from time due to formatting issues.
CraigHawker Dec 2, 2022
51e0102
First attempt at dealing with date formatting and timezones.
CraigHawker Dec 2, 2022
4407a23
Exposed some methods on property value renderer
CraigHawker Dec 5, 2022
a9cb9be
Lookups working.
CraigHawker Dec 5, 2022
ae6f1c4
Some fixes.
CraigHawker Dec 5, 2022
78d3eef
Started splitting property value rendering logic.
CraigHawker Dec 6, 2022
c5edb08
Split renderers into different files.
CraigHawker Dec 6, 2022
f9cc5a3
Moved methods out from PropertyValueRenderer
CraigHawker Dec 6, 2022
fcf0b66
PropertyValueRenderer now correctly overridden by the specific type i…
CraigHawker Dec 6, 2022
427754f
Fix for multi-line text editor.
CraigHawker Dec 6, 2022
5cc27df
Stopped attempted render of MSLUs.
CraigHawker Dec 6, 2022
f54e81a
MSLU not quite there, but almost.
CraigHawker Dec 6, 2022
77874d6
MSLU functionality and UI working
CraigHawker Dec 7, 2022
be5f537
MSLU filtering works.
CraigHawker Dec 7, 2022
e1f1b3a
Update version numbers.
CraigHawker Dec 7, 2022
08e4664
Merge branch 'master' into editing
CraigHawker Dec 7, 2022
3d37633
Added warning to dashboard.
CraigHawker Dec 7, 2022
9bfbbe8
Merge branch 'master' into editing
CraigHawker Dec 7, 2022
8133c0f
Disabled automatic deployment.
CraigHawker Dec 7, 2022
c6e8b95
Can now turn editing on/off in the configuration.
CraigHawker Dec 7, 2022
de4fb3b
Ignored local ps1 file.
CraigHawker Dec 7, 2022
c552d9e
Added the ability to have a local deployment file.
CraigHawker Dec 7, 2022
afa0d6f
Potential fix for lookup value not rendering properly
CraigHawker Dec 9, 2022
314b1a3
Fix for incorrect font.
CraigHawker Dec 9, 2022
3765766
Fix for built-in Document class being marked as incorrect.
CraigHawker Dec 9, 2022
8da7ca3
Allowed rendering of some other built-in properties (Keywords, reposi…
CraigHawker Dec 9, 2022
0bae2c7
Removed class groups from metadata card.
CraigHawker Dec 9, 2022
31a7893
Enabled rendering of properties that are on the class, but not on the…
CraigHawker Dec 9, 2022
94741bf
Event now makes "this" correct.
CraigHawker Dec 9, 2022
e496053
Better approach to rendering the read-only values.
CraigHawker Dec 9, 2022
0a8492e
Changing class works
CraigHawker Dec 9, 2022
3403e43
Property deletion also works
CraigHawker Dec 9, 2022
81649b5
Version bump
CraigHawker Dec 9, 2022
3afe071
Created SingleObjectDashboard (dashboard that follows a single object…
CraigHawker Jan 12, 2023
45d27d8
wizard interface coming together.
CraigHawker Jan 17, 2023
7c3e518
A tab gets rendered.
CraigHawker Jan 23, 2023
87b90ef
Fix for duplicate version element.
CraigHawker Jan 25, 2023
0f14d84
Fix for null reference issue.
CraigHawker Jan 25, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -350,3 +350,4 @@ healthchecksdb
src/ViewAllMetadata/ViewAllMetadata.UIX.mfappx
*.mfappx
/src/Common/bundles
/src/UIHelpers/install-application.local.ps1
61 changes: 61 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,64 @@
These are some example UIX applications showing how commonly-requested functionality can be created and maintained by third parties.

**NOTE: This code is produced as an open-source sample. M-Files can provide no support on its use, nor can be held responsible for issues caused by its use or misuse.**

## Getting started

### Installation

This application is designed to be distributed via the compiled `UIHelpers.mfappx` file. This can be installed to the vault using [M-Files Admin](https://www.m-files.com/user-guide/latest/eng/Applications.html). The application must be built from the source code in this repository; M-Files does not distribute compiled versions.

### Configuration

Once installed, navigate to the vault's `Configuration` section, expand `Other Applications` and select `UI Helpers`. Selecting the `Configuration` tab will allow each module to be configured separately. Common module configuration includes:

* Whether the module is enabled or not.
* Which users can access the module (either by role - e.g. "all users with the full control role" - or by specifically allowing access to certain users or groups).
* Control over any UI components that the module contains (e.g. the default height/width of the popup window, which locations the UI component can be shown in, etc.).
* The ability to provide translations for common UI elements that are automatically applied based on the desktop language of the user.
* Logging.

## Available modules

### Show preview

This module allows users to view the preview of an object either in the "bottom pane" (below the listing) or in a popout window. This allows the user to view both the preview and metadata card at the same time.

By default this module is **not enabled**. When enabled it defaults to allowing **all users** to see the preview. These defaults can be changed in the configuration.

To start, ensure that the [module is activated and your user has access](#getting-started) then open M-Files Desktop, right-click on an object and select `Show preview`. The preview appears below the listing, but can be toggled to other locations using the icons in the Function Ribbon. The preview can be closed by clicking the `Close` button.

### View all metadata

This module allows users to view the metadata of an object without Metadata Card Configuration rules applied. This can be useful in some situations (e.g. to debug Metadata Card Configuration rules). **Note: Metadata Card Configuration rules should never be used instead of proper property-level permissions.**

By default this module is **not enabled**. When enabled it defaults to allowing **users with the full control of vault role** to see all metadata. These defaults can be changed in the configuration.

To start, ensure that the [module is activated and your user has access](#getting-started) then open M-Files Desktop, right-click on an object and select `View all metadata`. The raw metadata appears below the listing, but can be toggled to other locations using the icons in the Function Ribbon. The metadata card can be closed by clicking the `Close` button.

## Project structure

### UIHelpers.csproj

The core project that declares the various modules that are available. Each module consists of server-side components, held in this project, and optional client-side components, held in their own project.

### Common.csproj

A project containing common files for use in client-side (UIX) components. Individual files in the `src` folder can be linked as-is (although note that they may have dependencies), but the recommended approach is to link to the associated files in the `bundle` folder, which are created automatically on build. The definition for these bundled files can be seen in `bundleconfig.json`.

### ShowPreview.UIX.csproj

A pure-JavaScript UIX application that allows the user to view previews of the selected object.

* `app\shellui.js` contains the application entry point.
* `app\dashboard\dashboard.js` contains the dashboard entry point.
* `app\scripts\renderers\objectrenderer.js` contains the `render` method which is called when an object is selected, and which renders the preview itself.

### ViewAllMetadata.UIX.csproj

A pure-JavaScript UIX application that allows the user to view the metadata card of the selected object without any metadata card configuration rules applied.

* `app\shellui.js` contains the application entry point.
* `app\dashboard\dashboard.js` contains the dashboard entry point.
* `app\scripts\renderers\objectrenderer.js` contains the `render` method which is called when an object is selected, and which renders the properties to the screen.
* `app\scripts\renderers\*PropertyValueRenderer.js` contain renderers for different property data types.
24 changes: 17 additions & 7 deletions src/Common/Common.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="CleanAll">
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<_BundlerMinifierTaskAssembly Condition="'$(MSBuildRuntimeType)' == 'Core'">..\packages\BuildBundlerMinifier.3.2.449\tools\netstandard1.3\BundlerMinifier.dll</_BundlerMinifierTaskAssembly>
Expand Down Expand Up @@ -40,9 +40,22 @@
</Content>
<Content Include="src\dashboards\base-dashboard.css" />
<Content Include="src\ConfigurationManager.js" />
<Content Include="src\dashboards\images\arrow_drop_down_s1_grey.png" />
<Content Include="src\dashboards\images\create_s1_grey.png" />
<Content Include="src\dashboards\images\delete_s1_grey.png" />
<Content Include="src\dashboards\images\disable.png" />
<Content Include="src\dashboards\images\ellipsis_s1_grey.png" />
<Content Include="src\dashboards\images\enable.png" />
<Content Include="src\dashboards\images\filter_s1.png" />
<Content Include="src\dashboards\images\filter_s1.svg" />
<Content Include="src\dashboards\images\filter_s1_grey.png" />
<Content Include="src\dashboards\images\filter_s1_grey.svg" />
<Content Include="src\dashboards\images\icon-delete.png" />
<Content Include="src\dashboards\scripts\console-dashboard.js" />
<Content Include="src\console-shellui.js" />
<Content Include="src\dashboards\scripts\Dashboard.js" />
<Content Include="src\dashboards\scripts\Promise.polyfill.min.js" />
<Content Include="src\dashboards\scripts\setImmediate.js" />
<Content Include="src\Events.js" />
<Content Include="src\dashboards\images\bottom-pane.png" />
<Content Include="src\dashboards\images\icon-edit.png" />
Expand All @@ -51,6 +64,7 @@
<Content Include="src\json2.js" />
<Content Include="src\Orchestrator.js" />
<Content Include="src\dashboards\scripts\jquery-1.12.4.min.js" />
<Content Include="src\Promise.polyfill.shellui.js" />
<Content Include="src\SingleWindowOrchestrator.js" />
<Content Include="src\VaultStructureManager.js" />
<Content Include="src\WindowManager.js" />
Expand All @@ -59,16 +73,12 @@
<None Include="bundleconfig.json" />
<None Include="packages.config" />
</ItemGroup>
<Target Name="CleanAll">
<Target Name="Clean">
<RemoveDir Directories="out;bin;obj;bundles" />
<BundlerMinifier.BundlerBuildTask FileName="$(MSBuildProjectDirectory)\bundleconfig.json" />
</Target>
<Target Name="Build">
<BundlerMinifier.BundlerBuildTask FileName="$(MSBuildProjectDirectory)\bundleconfig.json" />
</Target>
<Target Name="BundleMinifyClean" AfterTargets="CoreClean">
<BundlerMinifier.BundlerCleanTask FileName="$(MSBuildProjectDirectory)\bundleconfig.json" />
</Target>
<Target Name="Rebuild" DependsOnTargets="CleanAll" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
Expand Down
5 changes: 4 additions & 1 deletion src/Common/bundleconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
"src/SingleWindowOrchestrator.js",
"src/ConfigurationManager.js",
"src/VaultStructureManager.js",
"src/WindowManager.js"
"src/WindowManager.js",
"src/Promise.polyfill.shellui.js"
]
},
{
"outputFileName": "bundles/common-dashboard.js",
"inputFiles": [
"src/dashboards/scripts/console-dashboard.js",
"src/dashboards/scripts/jquery-1.12.4.min.js",
"src/dashboards/scripts/setImmediate.js",
"src/dashboards/scripts/Promise.polyfill.min.js",
"src/Events.js",
"src/dashboards/scripts/Dashboard.js"
]
Expand Down
2 changes: 1 addition & 1 deletion src/Common/src/Events.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
eventListeners[eventType] = [];
for (var i = 0; i < eventListeners[eventType].length; i++)
if (typeof (eventListeners[eventType][i]) == "function")
eventListeners[eventType][i].apply(e, Array.prototype.slice.call(arguments, 1));
eventListeners[eventType][i].apply(this, Array.prototype.slice.call(arguments, 1));
}
}
94 changes: 94 additions & 0 deletions src/Common/src/Promise.polyfill.shellui.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
function Promise(fn)
{
var p = this;
var run = false;
var success = false;
var data = null;
var calledBack = false;
var thenCallbacks = [];
var catchCallbacks = [];

function resolve(d)
{
data = d;
calledBack = true;
success = true;
p.then();
}
function reject()
{
calledBack = true;
success = false;
p["catch"]();
}

function action()
{
try
{
run = true;
fn(resolve, reject);
}
catch (e)
{
console.log(e);
MFiles.ThrowError(MFiles.GetLongErrorDescription(e));
}
}

p.then = function (fn)
{
if (typeof fn == "function")
thenCallbacks.push(fn);

// Have we already run?
if (run)
{
// Sanity.
if (false == calledBack)
{
console.error("Promise execution did not call resolve or reject.");
}

// Was it successful?
if (success)
{
for (var i = 0; i < thenCallbacks.length; i++)
thenCallbacks[i](data);
}
return p;
}

return p;
}

p["catch"] = function (fn)
{
if (typeof fn == "function")
catchCallbacks.push(fn);

// Have we already run?
if (run)
{
// Sanity.
if (false == calledBack)
{
console.error("Promise execution did not call resolve or reject.");
}

// Was it unsuccessful?
if (!success)
{
for (var i = 0; i < catchCallbacks.length; i++)
catchCallbacks[i](data);
}
return p;
}

return p;
}

MFiles.SetTimer(50, action);

return p;
}
27 changes: 26 additions & 1 deletion src/Common/src/VaultStructureManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@

var propertyDefinitions = {};
var classes = {};
var valueLists = {};

t.getPropertyDefinition = function(propertyDefId)
t.getValueList = function (valueListId)
{
return valueLists[valueListId];
}

t.getPropertyDefinition = function (propertyDefId)
{
return propertyDefinitions[propertyDefId];
}
Expand Down Expand Up @@ -59,6 +65,25 @@
// Error checking permissions.
MFiles.ReportException(errorobj);
}
);

// Load all the value lists.
shellUI.Vault.Async.ValueListOperations.GetValueLists
(
function (output)
{
valueLists = {};
for (var i = 0; i < output.Count; i++)
{
var pd = output[i];
valueLists[pd.ID] = pd;
}
},
function (shorterror, longerror, errorobj)
{
// Error checking permissions.
MFiles.ReportException(errorobj);
}
);
}

Expand Down
12 changes: 6 additions & 6 deletions src/Common/src/WindowManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
var tabId = null;
var tabTitle = null;
var t = this;
var registrationCallback = null;
var selectionChangedCallback = null;
var bottomTab;
var sideTab;
var shown = false;
Expand Down Expand Up @@ -41,7 +41,7 @@

// Set the new location.
currentLocation = newLocation;
registrationCallback = null;
selectionChangedCallback = null;

// Update vault.
t.saveDefaultWindowSize();
Expand Down Expand Up @@ -188,9 +188,9 @@

// Define the data to send to the dashboard.
var customData = {
registrationCallback: function (fn)
selectionChangedCallback: function (fn)
{
registrationCallback = fn
selectionChangedCallback = fn
},
tabClosedCallback: t.close,
windowManager: orchestrator.getWindowManager(),
Expand All @@ -202,15 +202,15 @@
};

// If we have a function then try to call it.
if (registrationCallback && typeof (registrationCallback) == "function")
if (selectionChangedCallback && typeof (selectionChangedCallback) == "function")
{
try
{
// Show the item details.
var selectedItems = orchestrator.getSelectedItems()
if (null == selectedItems)
return false;
registrationCallback(selectedItems);
selectionChangedCallback(selectedItems);

switch (currentLocation)
{
Expand Down
26 changes: 17 additions & 9 deletions src/Common/src/dashboards/base-dashboard.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ head, body {

body {
padding: 10px;
font-family: Lato;
font-family: Lato, Segoe UI, Tahoma, Arial, sans-serif;
color: #767676;
}

Expand Down Expand Up @@ -72,15 +72,23 @@ button {
text-align: center;
}

button:hover, button:active, button.save:active, button.save:hover {
border-color: #318CCC;
background-color: #318CCC;
color: white;
}
button:hover, button:active, button.save:active, button.save:hover {
border-color: #318CCC;
background-color: #318CCC;
color: white;
}

button.save {
border-color: #318CCC;
color: #318CCC;
button.save {
border-color: #318CCC;
color: #318CCC;
}
button.save:disabled, button.save[disabled],
button.save:disabled:active, button.save:disabled:hover,
button.save[disabled]:active, button.save[disabled]:hover {
color: #CCC;
border-color: #CCC;
cursor: not-allowed;
background-color: white;
}

.buttonGroup.top {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/Common/src/dashboards/images/create_s1_grey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/Common/src/dashboards/images/delete_s1_grey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/Common/src/dashboards/images/disable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/Common/src/dashboards/images/enable.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/Common/src/dashboards/images/filter_s1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/Common/src/dashboards/images/filter_s1.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/Common/src/dashboards/images/filter_s1_grey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions src/Common/src/dashboards/images/filter_s1_grey.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/Common/src/dashboards/images/icon-delete.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading