mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-09-24 14:31:41 +00:00
2.4.0 (#3522)
* [ADF-2914] support for number range patterns (#3282) * support for number range patterns * fix memory leak for tag actions * [ADF-2824] Reviewed docs for core and content services (#3290) * [ADF-2824] Reviewed card view docs * [ADF-2824] Reviewed doc for core and content services * [ADF-2824] Added class name exception to prop script * [ADF-2843] added tooltip for create new folder and edit folder icons … (#3286) * [ADF-2843] added tooltip for create new folder and edit folder icons from Content Service * [ADF-2843] added translation for tooltip * Update content-metadata.component.md * [ADF_NOISSUE] Fix styling and sidenav layout fixes (#3291) * Fix styling and sidenav layout fixes * Revert packagr conflicting mods * [ADF-2905] Added JSDocs for process services (#3292) * [ADF-2905] Added JSDocs for process services * [ADF-2905] Added missing return value in tasklist service * [ADF-2916] number range form validator added (#3279) * number range form validator added * tests added * [ADF-2626] added preserved state functionality for sidenav component (#3278) * [ADF-2626] added preserved state functionality for sidenav component * [ADF-2626] changed logic for preserving the sidenav component state * [ADF-2626] added missing curly brace } * [ADF-2626] small changes on logic based on pr comments * [ADF-2843] added tooltip for create folder and edit folder icons from Content Services * Revert "[ADF-2843] added tooltip for create folder and edit folder icons from Content Services" This reverts commitd5a7abb65b
. * [ADF-2626] changed casting * [ADF-2626] updated documentation with event * [ADF-2626] removed app-config pipe because it was not being used * [ADF-2328] filtering support for facets and categories (#3293) * filtering support for facets and categories * fix tests * update variable names * [ADF-2973] Angular pipe to get application configuration settings (#3301) * app config pipe * update docs * [ADF-2849] Search Date Range - Set the format of the date from config (#3288) * format date chosen from the datePicker's calendar * format date on focusout event * fix tests & some code refactoring * more validation messages * unit tests * fix typecast error * move "dateFormat" to be part of the "date range" widget settings block * fix error on Moment "...Type 'moment.Moment' is not assignable to type 'moment.Moment'. Two different types with this name exist, but they are unrelated. Property 'isLocal' is missing in type 'Moment'..." * moment - use old version * change script - use recent version of moment * Added the working-with-nodes-api-service tutorial. (#3295) * [ADF-2826] added a check for duplicate permission add (#3265) * [ADF-2556] first step to create add people or group to permissions * [ADF-2556] creating a dialog with user results * [ADF-2556] integrated service for add and remove permission from node * [ADF-2556] fixed behaviour and style for add user group * [ADF-2556] added some refactoring for dialog service * [ADF-2556] refactoring the dependencies of the components * [ADF-2556] added some fix and a new key for dialog * [ADF-2556] start adding test for node permission service * [ADF-2556] added test for add permission panel component * [ADf-2556] adding tests for new add permission component * [ADF-2556] fixed tests and added documentation * [ADF-2556] fixed documentation for add-node components * [ADF-2556] added peer review changes * [ADF-2826] added a check for duplicate permission add * [ADF-2826] removed fdescribe * [ADF-2826] applied peer review changes * [ADF-2930] general purpose "Empty Page" component (#3296) * empty content component * fix selector name * style fixes * cleanup code * docs for empty content * update docs * update docs * use typography for icon * layout fixes for Login (ported from ACA) * fix aot crash * fix tslint error and add and block if tslint give error in the pipeline * [ADF-2892] Sidenav now prevents closing itself when ESC key is pressed (#3302) * [ADF-2892] Sidenav now closes when clicking outside of it * [ADF-2892] Sidevan now prevents closing itself when ESC key is pressed * Fix for a technical bug, which prevents the proper usage of the expanded output event. (#3304) * [ADF-NO-PRIVATE] renoved private property which breaks AOT (#3305) * [ADF-2975] New input for File Upload Button component (#3299) * new nodeType input * unit tests * content type fix * remove package-lock.json files * [ADF-2699] added localisation for time ago pipe (#3298) * [ADF-2699] added localisation to the time-ago pipe * [ADF-2699] added lang to time ago pipe * [ADF-2699] added localisation for time ago pipe * [ADF-2699] removed fdescribe * [ADF-2699] removed comments * [ADF-2699] removed useless default values * fix css scope for search filter * fix aot error * fix ID show rancher script update * Addition to the preparation of the environment. (#3306) * Added the working-with-nodes-api-service tutorial. * Added the 'Alfresco Example Content Application' paragraph to the 'Preparing the development environment' tutorial. * [ADF-2843] added tooltips for all the buttons in toolbar (#3297) * [ADF-2843] added tooltip for create new folder and edit folder icons from Content Service * [ADF-2843] added translation for tooltip * [ADF-2843] added tooltips for all the buttons in toolbar * [ADF-2843] discard package-lock * [ADF-2832] discard changes to package-lock * [ADF-2843] discarded changes from package-lock * [ADF-2843] added tooltip for list view button * [ADF-2912] added group everyone as constant result for add permissions (#3266) * [ADF-2556] first step to create add people or group to permissions * [ADF-2556] creating a dialog with user results * [ADF-2556] integrated service for add and remove permission from node * [ADF-2556] fixed behaviour and style for add user group * [ADF-2556] added some refactoring for dialog service * [ADF-2556] refactoring the dependencies of the components * [ADF-2556] added some fix and a new key for dialog * [ADF-2556] start adding test for node permission service * [ADF-2556] added test for add permission panel component * [ADf-2556] adding tests for new add permission component * [ADF-2556] fixed tests and added documentation * [ADF-2556] fixed documentation for add-node components * [ADF-2556] added peer review changes * [ADF-2912] added group everyone as constant result for add permissions * [ADF-2912] readded jsdoc * fix search filter styles (#3313) * [ADF-2978] added a check when locally set permission is undefined (#3307) * [ADF-2969] Moved doc tools to new tools folder (#3314) * [ADF-2969] Moved doc tools to new tools folder * [ADF-2969] Added files missing from schematic * [ADF-2969] Added missing files to schematic * [ADF-2813] set default sorting (#3311) * [ADF-2891] decoupled search service love (#3312) * Added the tutorial 'Creating your JavaScript application using alfresco-js-api'. (#3310) * Added the working-with-nodes-api-service tutorial. * Added the 'Alfresco Example Content Application' paragraph to the 'Preparing the development environment' tutorial. * Added the tutorial 'Creating your JavaScript application using alfresco-js-api'. * Added the image of the tutorial. * Typo in 'creating-javascript-app-using-alfresco-js-api.md' Typo in 'Prerequisites'. * Typos in 'creating-javascript-app-using-alfresco-js-api.md' Two small typos. * Wrong sentence in 'creating-javascript-app-using-alfresco-js-api.md' ...into Angular applications, but it is "framework agnostic". * Typo on 'creating-javascript-app-using-alfresco-js-api.md'. ...and Angular... * [ADF-2888] UX doesn't respect the Sidenav specifiactions (#3303) * [ADF-2771] Sidebar action menu component - UX review * Add a input property to set the width of sidebar-action-menu. * [ADF-2888] UX doesn't respect the Sidenav specifiactions * Add a input property to set the width of sidebar-action-menu. * remove search configuration enforcement (#3315) * [ADF-2986] try to pick the start value from local storage before the standard default (#3318) * [ADF-2912] group everyone is always visible even for no search result (#3316) * [ADF-2826] fixed wrong parsing for error message (#3317) * [ADF-2739] Improved breadcrumb logic (#3287) * [ADF-2739] Long names in breadcrumb fixed * [ADF-2739] Updated styles * [ADF-2739] Fixing @mixin for breadcrumb * [ADF-2739] Waiting for changes in demo-shell * [ADF-2739] Fixed @mixin * [ADF-2739] Fixed issue related to breadcrumb position * [ADF-2739] Improved ngOnChanges call for breadcrumb * [ADF-2739] Fixed issues with lint * [ADF-2739] Removed comment in dropdown breadcrumb component file * [ADF-2739] Changed recalculateNodes method from public to protected * pipeline-update (#3309) * deploy PR script * [ADF-2967] fixed create new task navigation (#3322) * [ADF-2967] fixed create new task navigation * [ADF-2967] removed extra variables * [ADF-2967] removed unused methods * [ADF-2961] support for protocol substition in app config files (#3324) * support for protocol substition in app config files * Update app-config.service.spec.ts * Update app-config.service.spec.ts * [ADF-2925] Required and invalid validators added (#3277) * test added * tests clean * test added * tslint clean * test name changed * update tests * Added the tutorial 'Working with the Nodes API Service'. (#3319) * [ADF-2979] Updated props script to avoid copying missing JSDocs (#3327) * [ADF-2979] Updated tools to ignore blank JSDocs for inputs/outputs * [ADF-2979] Bug fixes for handling missing tables, etc * [ADF-2989] updated documentation with multiple node example (#3328) * [ADF-2503] conditional visibility for content actions (#3325) * conditional visibility for content actions * fix typo * workaround for "target: all" * [ADF-2821] move module sidebar action menu (#3321) * move module sidebar action menu * fix core import test * remove sidebar module * skip error * skiperror old versions * [ADF-2995] Permissions - Consumer should be able to upload a new version for his file on a private site (#3326) * check node permission instead of parent * tests * Fix sidenav action icons (#3331) * Only the username form control should be emitted (#3333) * about component (#3337) * [ADF-2563] Improve versioning functionality (#3335) * change input with textarea * update file version use now the update content API * provide way to test read only mode version list * fix test * test fix * [ADF-2997] The meaning of the range fields is not clear (#3338) * [ADF-2997] restrict 'to' field not to allow dates in the future * [ADF-2997] more clear labels for start and end date fields the translation team will decide what will be the best values for the date fields * [ADF-3000] Update the documentation by adding the steps of date format custom configuration. (#3339) * [ADF-3028] i18n support for title service (#3342) * i18n support for title service * cleanup tests * update tests * fixed constraint for viewer name width (#3343) * (demo shell) login css fixes (#3344) * [ADF-1997] override custom form widgets by default (#3346) * override custom form widgets by default * update tests * [ADF-2979] Updated doc tools to avoid erasing MD docs with blank JSDocs in services (#3347) * [ADF-2979] Update to ignore blank JSDocs for method signature * [ADF-2979] Finished adding blank JSDoc check for services * [ADF-2131] Search sorting (#3334) * sorting configuration * detect primary sorting and use with document list * search results sorting * docs update * unit tests and code updates * update code * update code * generic sorting picker, test updates * ability to switch off client side sorting * update docs for document list * [ADF-2884] Task List - Custom apps display all tasks (#3329) * [ADF-2884] Handled filterParam input change Changed component selector * [ADF-2884] Modified/Added tests * [ADF-2884] Deprecated old selectors * [ADF-2884] Added deprecated version * [ADF-2884] Improved filter finding condition * update project permissions change * [ADF-2984] Show date invalid message on search date range picker (#3323) * [ADF-2984] Show date invalid message on search date range picker * [ADF-2984] test that required format is displayed when date input is invalid * [ADF-2984] More space above buttons * dummy commit * restore deleted breadcrumb code * [ADF-2753] New error component (#3336) * [ADF-1938] Overflowing text in reports section fidex * [ADF-1938] Long names in report section now fit * [ADF-1938] Reverted changes in container widget * [ADF-2753] New error component created * [ADF-2753] Unit test for Error Content Component * Deleting unused files * Deleting unused files * Deleting unused files * [ADF-2753] Documentation added * [ADF-2753] Fixed minor bugs * [ADF-2753] Authentication not needed to view error * add error handler * tslint fix * router app component * remove unused import * fix import modules * limit to 404 * destroy fixture after any test * misspelling error * breadcrumb bug fixes (#3348) * [ADF-2726] fixed save content for external repository (#3341) * [ADF-2726] start fixing the show of files loaded from CS * [ADF-2726] start fixing the show of files loaded from CS * [ADF-2726] fixed save content for external repository| * [ADF-2726] fixed save content for external repository| * [ADF-2726] reeanabled and fixed the tests * [ADF-2726] reeanabled and fixed the tests * [ADF-2726] added tests for attach file widget and activiti alfresco service * [ADF-2726] added tests for attach file widget and activiti alfresco service * [ADF-2726] fixed test * fix like test * fix typo in the resource key (#3352) * fix failing tests replace ajax with spy * remove fdescribe * [ADF-3040] Replaced doc template engine to fix whitespace issues (#3356) * replace jasmine ajax with spy in rating tests * fix breadcrumb align in object picker (#3353) * fix no content node display (#3351) * Broken links and missing images for two tutorials. (#3357) * Broken links and missing images for two tutorials. * Replaced .html with .md extensions Replaced .html with .md extensions. * Typo in Prerequi(si)tes Typo in Prerequi(si)tes. * [ADF-2988] fix logo change (#3362) * [ADF-3055] fix bug with page size for facet fields (#3359) * fix bug with page size for facet fields * move page size to a constant * move const inside the scope * test fixes * [ADF-2923] button type added (#3358) * button type added * remove unnecessary code * [ADF-2608] added a fix to handle selection on slow connection problem (#3350) * [ADF-2608] added a fix to handle selection on slow connection problem * [ADF-2608] fixed test for datatable * Added an import command to the 'Adding a new view' tutorial. (#3366) * remove redundant logic (#3361) * [ADF-2679] Reviewed latest tutorial content (#3371) * [ADF-2679] Initial review of new tutorial content * [ADF-2679] Reviewed the latest tutorials * [ADF-2679] Initial review of new tutorial content * [ADF-2679] Reviewed the latest tutorials * [ADF-2832] Demo-shell, Fix Task filter dropdown menu alignment (#3294) * [ADF-2832] changed height to auto for task filter dropdown header * [ADF-2832] change selector with classes * [ADF-2832] changed selector * [ADF-2832] removed unnecessary css * [ADF-2832] added class and changed selector * [ADF-2832] added adf-prefix * [ADF-2927] search filter enhancements (#3365) * search filter enhancements * reset button for facet queries * update code and tests * remove unused type * restore code missing after rebase * [ADF-2764] Updated doc files with latest script features (#3368) * [ADF-2764] Updated doc files with latest script features * [ADF-2764] Rebuilt full index instead of just content services index * [ADF-2985] Demo shell - Provide an easy way to test the security issue (#3354) * Provide an easy way to test the security issue * use logService * first part random test fix (#3376) fixing random test executions first part * fix form radio test * [ADF-3065] TaskList component - Deprecate the processDefinitionKey (#3369) * Deprecate the processDefinitionKey property. remove unused tasklist code. It was needed with the old pagination component * Remove nosense test * Use adf version * [ADF-2999] readded form validation icon (#3367) * [ADF-2999] readded form validation icon * [ADF-2999] fixed broken test * Added the tutorial 'Basic theming'. (#3378) * [ADF-2854] Fix demoshell task/process filter and routing (#3360) * Fix demoshell task/process filter and routing * Use the correct js api model * Fix unit test * search filter now remembers original user query (#3384) * [ADF-2319] added a check for delete checklist button (#3382) * [ADF-2238] removed created by property (#3380) * [ADF-2238] removed created by property * [ADF-2238] added a condition to avoid checklist delete for completed task * Revert "[ADF-2238] added a condition to avoid checklist delete for completed task" This reverts commitfc2227ea04
. * bold font for checked boxes (#3381) * [ADF-2774] fixed message bus, background and language dropdowns that were hidden by the toolbar (#3379) * [ADF-2764] Applied new doc tool features to core library (#3383) * [ADF-2824] Added and reviewed some content services docs (#3385) * revert changes (#3387) * Added the 'Content metadata component' tutorial. (#3386) * update package settings and lock file (#3389) * minor layout fix for search facet buttons * [ADF-2857] fixed message for date and date time widget (#3370) * [ADF-2764] Updated process services docs with latest features (#3390) * [ADF-2977] made language change persistenr (#3373) * [ADF-3041] TaskList Component - Empty State issue. (#3345) * [DW-635] Empty State Component * [DW-635] Empty State Component * [DW-635] Empty state Issue * [DW-635] Use empty state component and custom empty directive * [ADF-3041] Documentation for TaskList Component - Empty State issue. * [ADF-3088] move sorting picker to a separate module (#3396) * move sorting picker to a separate module * update translation mock * [ADF-3087] Clarified section about adding/replacing keys in i18n guide (#3392) * [ADF-3087] Clarified section about adding/replacing keys * [ADF-3087] Corrected information in i18n and translation service docs * [ADF-3068] ADF Sidenav/Toolbar - Ux background colour review (#3401) * [ADF-2824] Reviewed docs for new components in 2.4 (#3400) * [ADF-3042] Use the custom date adapter from adf-core on Search Date Range widget (#3394) -fix localization -fix tests -show parse error * [ADF-3053] breadcrumb fixes (#3406) * translate breadcrumb root in demo shell * optional "max items" feature and style fixes * should not be restricted by default * style updates * toolbar and breadcrumb layout fixes * breadcrumb demo and testing page * full toolbar scenario * fix translation issue with the dropdown and custom root * a11y fixes * fix issue with duplicate id, remove unused attribute * [ADF-2627] Icons-only mode for Info Drawer (#3398) * tab with icon * docs * test * add option without login docker publish * fix publish script * move docker push outside login * fix random test failing part 2 (#3395) * fix random failing test core search/comment/auth/user * fix node delete directive * fix lint issues * node restore fix * fix comment test * remove fdescribe * fix tests and tslint * fix upload test * unsubscribe success event task test * copy comment object during test * use the data pipe performance improvement and standard usage * uncomment random test * fix comment date random failing test * disposable unsubscribe * fix start process * remove fdescribe * change start process test and remove commented code * fix error event check double click * clone object form test * refactor date time test * fix service mock * fix test dropdown and context * git hook lint * fix language test * unsubscribe documentlist event test * fix disposable error * fix console log service error document list * unusbscribe search test * clear input field * remove wrong test * [ADF-2754] People Widget - Refactoring style and logic (#3349) * observable logic added * tests added & bug fixed * onkeyup removed * isValidUser method removed * tslint fix * test added * comments fixed * check if input value is string * remove console log err from document list test * [ADF-3082] Task Filter - Custom Task filters don't work (#3402) * [ADF-3082] Custom Task filters don't work. * Added an sorting input to the datatable. * Updated documentation for the recent changes. * Added testcases for the recent changes. * [ADF-3082] Custom Task filters don't work * Added a sorting input to the datatable * Added testcases to the recent changes. * Updated doc for the recent changes. * * Refactored task/process list dataSort. * * Refactored process/task list datasort method * remove console log error from version list and content node selector test stubbing necessary method * [ADF-3041] - Task List Empty State Issue (#3408) * fix demo shell gallery view switch (#3413) * [ADF-2541] reset datatable selection when rows are changed from code (#3410) * reset selection when rows are replaced from code * code fixes * unit test updates * visualise selection count for testing purposes * make row selection api public * remove question mark from the event name * remove pdfviewer thumbnail console log test error * fix conflict link creation id (#3412) * [ADF-2753] Error Component throwing default error fixed (#3364) * [ADF-1938] Overflowing text in reports section fidex * [ADF-1938] Long names in report section now fit * [ADF-1938] Reverted changes in container widget * [ADF-2753] New error component created * [ADF-2753] Unit test for Error Content Component * Deleting unused files * Deleting unused files * Deleting unused files * [ADF-2753] Documentation added * [ADF-2753] Error Component throwing default error fixed * [ADF-2753] White space removed * [ADF-2753] Removed unnecessary files and updated trnaslation file * [ADF-2753] Changed link for button in error component * [ADF-2753] Updated doc file * [ADF-2753] Removed fdescribe * [ADF-2753] Improved code coverage * fix error AppTitle service test log * fix gallery view demo shell route * [ADF-3095] ability to intercept, pause and resume upload process (#3416) * prevent and resume upload process * upload fixes and confirmation dialog demo * ability to toggle the upload confirmation demo * fix tests * unit tests * docs update * remove deprecation * fix test name * [ADF-2698] Date and time Widget - UTC vs local time issue (#3393) * [ADF-2698] Date and time Widget - UTC vs local time issue * [ADF-2698] add unit test to check that the format for min and max values is correct * [ADF-2698] test behavior * [ADF-3102] added lazy loading for tab content to fix animations (#3418) * [ADF-2764] Fixed union type display glitches in property tables (#3419) * [ADF-2764] Test commit to fix handling of union types in Github docs * [ADF-2764] Fixed union type error in component docs * [ADF-2593] z-index fix for search bar (#3409) * [ADF-2593] * [ADF-2593] Removed unnecessary style attributes * [ADF-3111] pagination is not showed when automation test are running (#3420) * [ADF-3108] Search - facetQueries panel renders when not defined in configuration (#3417) * show facetQueries based on configuration definition * tests * FacetQueries is defined * [ADF-3039] Task List - Enanchement (#3404) * * Created DataColumnSchemaAssembler component to get column schema from html and app.config.json * Removed column related method from tasklist. * * Removed data property from the tasklist component * Using rows input property instead of data input property of the datatable * * Renamed DataColumnSchemaAssembler to DataTableSchema * Refactored DataTableSchema component * * Changed schem property into an input schemaColumns property in dataTable component * * Added selectFirstRow input property to select a first row of datatable * Removed unnecessary method from tasklist component * * Added test case for the recent changes * Added mock object for the tasklist spec * * Added testcases for recent changes in the datatable component * * Updated datatable and tasklist document for the recent changes * * Refactored process-service and task list component * Updated datatable document. * [ADF-3039] Task List - Enanchement * Changed schemaColumn name to columns * Updated datatable documentation. * data input Annotated with @deprecated in the tasklist component * * Added an sorting input to the datatable. * Updated datatable and tasklist documentation * Added method to get current sorting order. * * After rebasing * * Revert sorting changes * * After rebase * * fixed conflicts * * Fixed failing testcase after rebased. * update toolbar docs (#3423) * Add custom data holder for CardViewItems (#3422) * [ADF-3115] a11y fixes (#3424) * a11y fixes for search input * a11y fixes for pagination * a11y fixes for content actions * [ADF-3118] translation support for notification service (snackbars) (#3427) * translation support for snackbar * unit tests * [ADF-2438] fixed thumbnails height (#3407) * [ADF-2438] calculate thumbnail height * [ADF-2438] send height to parent element * [ADF-2438] add width to css * [ADF-2438] moved height and width logic to parent component * [ADF-2438] added height and width logic to parent component * [ADF-2438] fixed failing test * demo translation for search radio * [ADF-2710] removed default shared link creation at the opening (#3430) * [ADF-2999] added a way to test the validation icon on demo shell (#3431) * [ADF-2754] People component tests fixed and style improvement (#3414) * tests fixed and style * show people test fixed * error message test fixed * [ADF-3131] fix selection order for DT/DL (#3433) * fix selection order for DT/DL * remove fit * [ADF-3066] ProcessList Component - Empty State issue. (#3434) * [ADF-3093] Added style checking tool for en.json translation file (#3428) * [ADF-3093] Started li18nt VS Code extension * [ADF-3093] Started work on UI style lint tool for VSCode * [ADF-3093] Added UI style rules up to sg0006 * [ADF-3093] Added remaining style rules * [ADF-3093] Added docs and command line tool * [ADF-3093] Removed Microsoft notices and updated licences to Apache-2.0 * [ADF-3133] Fixed inconsistency in doc example (#3436) * [ADF-2753] Fixed routing and second button showing up (#3421) * [ADF-1938] Overflowing text in reports section fidex * [ADF-1938] Long names in report section now fit * [ADF-1938] Reverted changes in container widget * [ADF-2753] New error component created * [ADF-2753] Unit test for Error Content Component * Deleting unused files * Deleting unused files * Deleting unused files * [ADF-2753] Documentation added * [ADF-2753] Removed unnecessary files and updated trnaslation file * [] * [ADF-2753] Fixed routing and second button showing up * [ADF-2753] Fixed typo * [ADF-2753] Fixed view loading before variables * [ADF-2753] Missing whitespace * [ADF-2753] Added test for route params * [ADF-2753] Changed getData function name to getTranslations * [ADF-fix date widget test] Fixing a randomly failing test (#3439) * group uploaded files into single batch, IE fixes (#3438) * [ADF-3067] App-list Empty State. (#3432) * extend demo shell upload example to button * [ADF-2764] Added new type linker features and applied them to core docs (#3442) * [ADF-2764] Added basic support for composite and external types * [ADF-2764] Added new type linker features and applied to core docs * notification service demo and testing area (#3443) * notification service demo and testing area * fix typo * fix viewer title style (#3445) * [ADF-3132] TaskList empty state doesn't respect the specification (#3440) * [ADF-3134] fix increasing search calls issue (#3444) * [ADF-2764] Applied new type linker features to content services docs (#3446) * [ADF-3062] dual api support for Favorites (#3447) * dual api support for Favorites * unit test * ADF-2974] New Buttons Menu component version (#3429) * [ADF-2974] Buttons injected from parent html component * [ADF-2974] New version of buttons menu component * [ADF-2974] Updated unit tests * [ADF-2974] Updated documentation * [ADF-2974] Removed unused variable * [ADF-2974] Fixed failing test at analytics report parameters * [ADF-2974] Removed fdescribe * [ADF-2974] Moved mock inside testing file for buttons menu component * extend breadcrumb testing page (demo shell) * [ADF-3142] Added missing info about 'remember me' in login docs (#3448) * [ADF-3120] fixed sorting for tasklist and process list (#3435) * [ADF-3120] fixed sorting for tasklist and process list * [ADF-3120] removed commented code * [ADF-3120] fixing another randomly failing test * [ADF-2764] Applied new type linker features to proc services docs (#3449) * (demo shell) fix memory leak with search results * [ADF-2795] SSO implicitflow (#3332) * Enable OAUTH2 * Create SSO services * SSO improvements * Rollback sso login change * Add SSO configuration from Setting component * Refactoring * Remove login ECM/BPM toggle and move use the userpreference instead of store * fix host setting unit test * Fix unit test missing instance * use the Js api oauth * add logout component and clean sso not used class * fix dependencies cicle * add translation settings * fix style setting page * clean * JS APi should receive the oauth config from the userPreference and not from the config file * change login if SSO is present * missing spaces * add sso test in login component * add logout directive new properties test * Improve host setting and remove library reference * fix login test * Remove unused code * Fix authentication unit test * fix authguard unit test * fix csrf check login component * fix unit test core and demo shell * remove * simple filtering for datatable (#3453) * [ADF-3150] Moved all doc tool config settings to doctool.config.json (#3455) * [ADF-3150] Moved undoc stoplist to doc config file * [ADF-3150] Moved config to doctools.config.json and removed obsolete scripts * fixes for memory leaks and multiple subscriptions (#3456) * fix content action memory leaks * memory leak fixes for demo shell * [no-issue] error image resolver mimetype should not be part of datatable (#3415) * move error image custom logic form datatable to documentlist * change travis * [fix-test-log] added optional function to data row interface * [no-issue] fixed datatable tests * [no-issue] fixing tests * [ADF-2859] conditional evaluation of disabled state for content actions (#3450) * react on [disabled] binding changes * [disabled] binding updates for context menu items * evaluating disabled state with a function * unit test * restore original description * remove irrelevant test * fix tests * fix test * remove not used events in demo shell host setting components * [ADF-3156] App config default ALL (BPM and ECM) provider (#3460) * Use as default provider ALL (BPM and ECM) * Default host OAUTH * removing wrong fdescribe (#3461) * [ADF-3123] removed default choice for the first radio button (#3462) * Fix host component (#3463) * [ADF-2824] Doc review and minor changes to review checker tool (#3466) * restore historical selection order (#3467) * restore historical selection order * fix test * [ADF-2859] fixes for the conditional visibility and disabled states (#3465) * fixes for the conditional visibility and disabled states * update docs * cleanup code * remove unused code * [LOC-61] i18n 2.4.0 (#3468) * i18n 2.4.0 * missing part * revert development config * [ADF-3144] Error component displayed when closing file viewer in process tab (#3469) * [ADF-3173] [Task List] - Empty list message is not translated (#3471) * Added a missing translation keys. * Fix dropdown panel in viewer toolbar because of z-index (#3472) * [ADF-3162] Setting component - Should be able to render the providers passed as input (#3464) * Be able to change the available providers values * Add deprecated tag * add default providers * Fix empty OAuth and selected providers Improve the documentation * Fix BPM guard to check SSO condition * Add the oauthConfig again * SSO or Basic otpion auth setting change * fix host settings sso/basic add login documentation * remove test string * fix auth guard test * dispose upload emitter test events * remove space * exclude failing test * Update ADF packages version 2.4.0-beta13 (#3475) * [ADF-2824] Reviewed search docs for 2.4 (#3477) * [ADF-2824] Moved search widget docs into separate pages * [ADF-2824] Separated search widget page and added search filter service docs * [ADF-2824] Updated new search docs with doc tools * Remove unused field (#3480) * Fix default SSO config not filled in (#3479) * [ADF-3175] renabling upload on single target folder row (#3473) * [ADF-3191] Not able to login only to BPM or ECM (#3478) * disable random test * host setting component reset JS-API * reload api after user prefrence change * remove replicate reset * missing semicolon * deprecate provider property * remove trailing space * check new value before to set * [ADF-3198] Updated index files + minor doc updates (#3482) * [ADF-3200] custom Extension filter - file with different extension is uploaded with drag and drop * [ADF-3181] Auth Guard - redirect by string url (#3474) * redirect by string url * auth guard tests fix * revise * [ADF-3196] fixed task selection and double click (#3484) * [ADF-3191] Fix userprefrence oauth2 (#3488) * remove user preference setting save * fix host setting test * remove userPreferences test * fix title service test * remove unused imports * restore input align * fix service import in test tag rating * [ADF-3210] Typo People Search (#3487) * remove vscode changes * [ADF-3196] [Task list / Process list] - The 'Task details' are not diplayed for the selected Task (#3483) * [ADF-3196] [Task list / Process list] - The 'Task details' are not displayed for the selected Task * * After rebase * [ADF-3176] Fixed permissionsissue when editing metadata (#3476) * [ADF-3217] reset previous search settings (#3490) * reset previous search settings * unit test * remove fit * [ADF-3196] fixed selection of first tasklist element (#3491) * [ADF-3196] [Task list / Process list] - The 'Task details' are not displayed for the selected Task * * After rebase * [ADF-3196] fixed selection for fist element * [ADF-3212] Upload version buttons wrapping fixed (#3492) * Update ADF packages version 2.4.0-beta14 (#3493) * demo shell host setting component login redirect after setting * remove old auth test not valid anymore * fix translations (#3497) * [ADF-3203] Fixed doc tools bugs from Linux run and added verbose option (#3496) * [ADF-3912] Setting Component - Return as default BASIC authType (#3495) * Return as default BASIC authType * remove the commented line * [ADF-3190] Fix rerendering issue with content-meta-data (#3494) * Fix rerendering issue with content-meta-data * Fix indentation * [ADF-3198] Index and tutorial content review (#3500) * [ADF-3198] Fixed glitches in doc index files and tools * [ADF-3198] Reviewed new tutorial content and fixed index glitches * [ADF-3198] Fixed host settings component brief description * [ADF-3223] Restore message directive files fix (#3499) * fix restore notification * improve path specification property * fix lint and document issues * fix test * remove unused import * [ADF-3226] remove Double behaviour setting allow download and comment (#3502) * fix restore notification * improve path specification property * fix lint and document issues * fix test * remove unused import * remove double behavior allowComments and allowDonload can be set only thorough input property * [ADF-3233] fixed demo shell filtering for files on drag&drop] (#3504) * [ADF-3232] fixing retrieving for ecm user via site service (#3506) * [ADF-3176] file content reload fixed (#3501) * file content reload fixed * refactoring & layout fix * resolve indentation problems * missing semicolon * [ADF-3224] move ticket store logic in js-api (#3505) * move ticket store logic in js-api * remove space * fix test * fix tests * [ADF-3212] Fixed permission issues when updating version (#3503) * [ADF-3213] Fixed permission issues when updating version * [ADF-3212] fixed test for PR * allowableOperations include viewer get node * update demo shell with metadata demo * undo ADF-3176 changes * fix login oauth cookie problem (#3508) * fix login don't check the cookie in oauth2 * fix test * check boolean storage * fix provider check * clean local storage before auth test * fix missing pdf viewer update when scale is the same (#3510) * [ADF-3239] Fixed deprecated property descriptions (#3509) * [ADF-3239] Changed deprecated properties to include full description * [ADF-3239] Updated deprecated properties of affected doc files * [ADF-3239] Fixed badly formatted doc comment in tasklist * [ADF-3229] people widget list reseted if empty input (#3507) * list reseted when input is empty * test added * [ADF-3242] removed filter for string in example log component (#3511) * [ADF-3242] removed filter for string in example log component * [ADF-3242] added try catch for circular dependency objects * [ADF-3242] added try catch and removed error message * invalidate session in host setting internal component instead to logout * remove unused import * use i18n key for "Permission" label * [ADF-3198] Final doc checks for release (#3513) * [ADF-3198] Doc link check for release * [ADF-3198] Updated main index doc page * remove invalidation session because is concern of the js-api * check 401 and redirect demo shell (#3516) * [ADF-3248] fixed readonly status for people widget (#3512) * [ADF-3248] fixed readonly status for people widget * [ADF-3248] fixed test people widget * [ADF-3248] added readonly test * [ADF-3251] Authentication Service - Check if used loggedin based on the provider (#3515) * check if loggedin based on the provider * Fix unit tests * remove 404 check in demo shell * [ADF-3262] Remove avoidable css style from task/process list component (#3518) * [ADF-3230] Changes to stop doc tools from updating files unnecessarily (#3519) * [ADF-3230] Added basic change detector to doc tools * [ADF-3230] Updates to type linker to fix before/after inconsistencies * [ADF-3230] Fixed comparison error caused by adjacent text blocks * [ADF-3230] Added basic change detector to doc tools * [ADF-3230] Updates to type linker to fix before/after inconsistencies * [ADF-3230] Fixed comparison error caused by adjacent text blocks * [ADF-3230] Modified props tool to remove spaces from union types * [ADF-3230] Made ToC tool before/after state consistent * [ADF-3265] Updated index script to remove brief desc links (#3520) * bump 2.4.0 version
This commit is contained in:
@@ -1,7 +1,8 @@
|
||||
<div
|
||||
*ngIf="data" class="full-width"
|
||||
[class.adf-data-table-card]="display === 'gallery'"
|
||||
[class.adf-data-table]="display === 'list'">
|
||||
[class.adf-data-table]="display === 'list'"
|
||||
[class.adf-data-table--empty]="isEmpty()">
|
||||
<div *ngIf="isHeaderVisible()" class="adf-datatable-header">
|
||||
<div class="adf-datatable-row" *ngIf="display === 'list'">
|
||||
<!-- Actions (left) -->
|
||||
@@ -54,10 +55,10 @@
|
||||
[ngStyle]="rowStyle"
|
||||
[ngClass]="getRowStyle(row)"
|
||||
(keyup)="onRowKeyUp(row, $event)">
|
||||
|
||||
<!-- Actions (left) -->
|
||||
<div *ngIf="actions && actionsPosition === 'left'" class="adf-datatable-table-cell">
|
||||
<button mat-icon-button [matMenuTriggerFor]="menu"
|
||||
[title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate"
|
||||
[attr.id]="'action_menu_left_' + idx"
|
||||
[attr.data-automation-id]="'action_menu_' + idx">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
@@ -91,22 +92,26 @@
|
||||
<div *ngIf="!col.template" class="cell-container">
|
||||
<ng-container [ngSwitch]="col.type">
|
||||
<div *ngSwitchCase="'image'" class="cell-value">
|
||||
<mat-icon *ngIf="isIconValue(row, col)">{{ asIconValue(row, col) }}</mat-icon>
|
||||
<mat-icon class="adf-datatable-selected"
|
||||
*ngIf="!isIconValue(row, col) && row.isSelected" svgIcon="selected">
|
||||
<mat-icon *ngIf="isIconValue(row, col); else no_iconvalue">{{ asIconValue(row, col) }}
|
||||
</mat-icon>
|
||||
|
||||
<img *ngIf="!isIconValue(row, col) && !row.isSelected"
|
||||
alt="{{ iconAltTextKey(data.getValue(row, col)) | translate }}"
|
||||
src="{{ data.getValue(row, col) }}"
|
||||
(error)="onImageLoadingError($event, row.obj.entry.content.mimeType)">
|
||||
<ng-template #no_iconvalue>
|
||||
<mat-icon class="adf-datatable-selected"
|
||||
*ngIf="row.isSelected; else no_selected_row" svgIcon="selected">
|
||||
</mat-icon>
|
||||
<ng-template #no_selected_row>
|
||||
<img
|
||||
alt="{{ iconAltTextKey(data.getValue(row, col)) | translate }}"
|
||||
src="{{ data.getValue(row, col) }}"
|
||||
(error)="onImageLoadingError($event, row)">
|
||||
</ng-template>
|
||||
</ng-template>
|
||||
</div>
|
||||
<div *ngSwitchCase="'icon'" class="cell-value">
|
||||
<span class="sr-only">{{ iconAltTextKey(data.getValue(row, col)) | translate }}</span>
|
||||
<mat-icon>{{ data.getValue(row, col) }}</mat-icon>
|
||||
</div>
|
||||
<div *ngSwitchCase="'date'" class="cell-value"
|
||||
[attr.data-automation-id]="'date_' + data.getValue(row, col)">
|
||||
[attr.data-automation-id]="'date_' + (data.getValue(row, col) | date: 'medium') ">
|
||||
<adf-date-cell
|
||||
[data]="data"
|
||||
[column]="col"
|
||||
@@ -158,6 +163,7 @@
|
||||
<div *ngIf="actions && actionsPosition === 'right'"
|
||||
class="adf-datatable-table-cell alfresco-datatable__actions-cell">
|
||||
<button mat-icon-button [matMenuTriggerFor]="menu"
|
||||
[title]="'ADF-DATATABLE.CONTENT-ACTIONS.TOOLTIP' | translate"
|
||||
[attr.id]="'action_menu_right_' + idx"
|
||||
[attr.data-automation-id]="'action_menu_' + idx">
|
||||
<mat-icon>more_vert</mat-icon>
|
||||
@@ -200,7 +206,7 @@
|
||||
<div *ngIf="loading"
|
||||
[class.adf-datatable-row]="display === 'list'"
|
||||
[class.adf-data-table-card-loading]="display === 'gallery'">
|
||||
<div class="adf-datatable-table-cell" >
|
||||
<div class="adf-datatable-table-cell">
|
||||
<ng-template *ngIf="loadingTemplate"
|
||||
ngFor [ngForOf]="[data]"
|
||||
[ngForTemplate]="loadingTemplate">
|
||||
|
@@ -14,14 +14,9 @@
|
||||
$data-table-selection-color: mat-color($background, 'selected-button') !default;
|
||||
$data-table-dividers: 1px solid $data-table-divider-color !default;
|
||||
$data-table-row-height: 56px !default;
|
||||
// $data-table-last-row-height: 56px !default;
|
||||
// $data-table-header-height: 56px !default;
|
||||
$data-table-column-spacing: 36px !default;
|
||||
$data-table-column-padding: $data-table-column-spacing / 2;
|
||||
// $data-table-card-header-height: 64px !default;
|
||||
// $data-table-card-title-top: 20px !default;
|
||||
$data-table-card-padding: 24px !default;
|
||||
// $data-table-button-padding-right: 16px !default;
|
||||
$data-table-cell-top: $data-table-card-padding / 2;
|
||||
$data-table-drag-border: 1px dashed rgb(68, 138, 255);
|
||||
|
||||
@@ -170,6 +165,7 @@
|
||||
border-collapse: collapse;
|
||||
white-space: nowrap;
|
||||
font-size: $data-table-font-size;
|
||||
background-color: mat-color($background, card);
|
||||
|
||||
/* Firefox fixes */
|
||||
border-collapse: unset;
|
||||
@@ -394,6 +390,8 @@
|
||||
.ellipsis-cell {
|
||||
.cell-container {
|
||||
height: 100%;
|
||||
display: inline-grid;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.cell-container > * {
|
||||
@@ -458,16 +456,36 @@
|
||||
}
|
||||
|
||||
.adf-upload__dragging {
|
||||
& > td {
|
||||
border-top: $data-table-drag-border;
|
||||
border-bottom: $data-table-drag-border;
|
||||
& > div {
|
||||
border-top: $data-table-drag-border !important;
|
||||
border-bottom: $data-table-drag-border !important;
|
||||
border-color: $data-table-drag-border;
|
||||
|
||||
&:first-child {
|
||||
border-left: $data-table-drag-border;
|
||||
border-color: $data-table-drag-border;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-right: $data-table-drag-border;
|
||||
border-right: $data-table-drag-border !important;
|
||||
border-color: $data-table-drag-border;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.adf-data-table--empty {
|
||||
@include flex-column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
.adf-datatable-body {
|
||||
.adf-datatable-row {
|
||||
background-color: mat-color($background, card);
|
||||
|
||||
&:hover, &:focus {
|
||||
background-color: unset;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -15,19 +15,33 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { SimpleChange } from '@angular/core';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { SimpleChange, NO_ERRORS_SCHEMA, QueryList } from '@angular/core';
|
||||
import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
|
||||
import { MatCheckboxChange } from '@angular/material';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { DataTableModule } from '../../datatable.module';
|
||||
import { MaterialModule } from '../../../material.module';
|
||||
import { DataColumn } from '../../data/data-column.model';
|
||||
import { DataRow } from '../../data/data-row.model';
|
||||
import { DataSorting } from '../../data/data-sorting.model';
|
||||
import { ObjectDataColumn } from '../../data/object-datacolumn.model';
|
||||
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
|
||||
|
||||
import { DataTableComponent } from './datatable.component';
|
||||
import { setupTestBed } from '../../../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
||||
import { DataColumnListComponent } from '../../../data-column/data-column-list.component';
|
||||
import { DataColumnComponent } from '../../../data-column/data-column.component';
|
||||
|
||||
class FakeDataRow implements DataRow {
|
||||
isDropTarget = false;
|
||||
isSelected = true;
|
||||
hasValue(key: any) {
|
||||
return true;
|
||||
}
|
||||
getValue() {
|
||||
return '1';
|
||||
}
|
||||
imageErrorResolver() {
|
||||
return './assets/images/ft_ic_miscellaneous.svg';
|
||||
}
|
||||
}
|
||||
|
||||
describe('DataTable', () => {
|
||||
|
||||
@@ -35,15 +49,12 @@ describe('DataTable', () => {
|
||||
let dataTable: DataTableComponent;
|
||||
let element: any;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule,
|
||||
DataTableModule,
|
||||
MaterialModule
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
setupTestBed({
|
||||
imports: [
|
||||
CoreTestingModule
|
||||
],
|
||||
schemas: [ NO_ERRORS_SCHEMA ]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(DataTableComponent);
|
||||
@@ -51,6 +62,45 @@ describe('DataTable', () => {
|
||||
element = fixture.debugElement.nativeElement;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should preserve the historical selection order', () => {
|
||||
dataTable.data = new ObjectDataTableAdapter(
|
||||
[{ id: 0 }, { id: 1 }, { id: 2 }],
|
||||
[ new ObjectDataColumn({ key: 'id' })]
|
||||
);
|
||||
|
||||
const rows = dataTable.data.getRows();
|
||||
|
||||
dataTable.selectRow(rows[2], true);
|
||||
dataTable.selectRow(rows[0], true);
|
||||
dataTable.selectRow(rows[1], true);
|
||||
|
||||
const selection = dataTable.selection;
|
||||
expect(selection[0].getValue('id')).toBe(2);
|
||||
expect(selection[1].getValue('id')).toBe(0);
|
||||
expect(selection[2].getValue('id')).toBe(1);
|
||||
});
|
||||
|
||||
it('should update schema if columns change', fakeAsync(() => {
|
||||
|
||||
dataTable.columnList = new DataColumnListComponent();
|
||||
dataTable.columnList.columns = new QueryList<DataColumnComponent>();
|
||||
dataTable.data = new ObjectDataTableAdapter([], []);
|
||||
|
||||
spyOn(dataTable.data, 'setColumns').and.callThrough();
|
||||
|
||||
dataTable.ngAfterContentInit();
|
||||
dataTable.columnList.columns.reset([new DataColumnComponent()]);
|
||||
dataTable.columnList.columns.notifyOnChanges();
|
||||
|
||||
tick(100);
|
||||
|
||||
expect(dataTable.data.setColumns).toHaveBeenCalled();
|
||||
}));
|
||||
|
||||
it('should use the cardview style if cardview is true', () => {
|
||||
let newData = new ObjectDataTableAdapter(
|
||||
[
|
||||
@@ -189,6 +239,46 @@ describe('DataTable', () => {
|
||||
expect(element.querySelector('[data-automation-id="text_FAKE"]')).not.toBeNull();
|
||||
});
|
||||
|
||||
it('should set rows to the data when rows defined', () => {
|
||||
const dataRows =
|
||||
[
|
||||
{ name: 'test1' },
|
||||
{ name: 'test2' },
|
||||
{ name: 'test3' },
|
||||
{ name: 'test4' }
|
||||
];
|
||||
dataTable.data = new ObjectDataTableAdapter([],
|
||||
[new ObjectDataColumn({ key: 'name' })]
|
||||
);
|
||||
|
||||
dataTable.ngOnChanges({
|
||||
rows: new SimpleChange(null, dataRows, false)
|
||||
});
|
||||
fixture.detectChanges();
|
||||
|
||||
const rows = dataTable.data.getRows();
|
||||
expect(rows[0].getValue('name')).toEqual('test1');
|
||||
expect(rows[1].getValue('name')).toEqual('test2');
|
||||
});
|
||||
|
||||
it('should set custom sort order', () => {
|
||||
const dataSortObj = new DataSorting('dummayName', 'asc');
|
||||
const dataRows =
|
||||
[
|
||||
{ name: 'test1' },
|
||||
{ name: 'test2' },
|
||||
{ name: 'test3' },
|
||||
{ name: 'test4' }
|
||||
];
|
||||
dataTable.sorting = [ 'dummayName', 'asc' ];
|
||||
dataTable.ngOnChanges({
|
||||
rows: new SimpleChange(null, dataRows, false)
|
||||
});
|
||||
fixture.detectChanges();
|
||||
const dataSort = dataTable.data.getSorting();
|
||||
expect(dataSort).toEqual(dataSortObj);
|
||||
});
|
||||
|
||||
it('should reset selection on mode change', () => {
|
||||
spyOn(dataTable, 'resetSelection').and.callThrough();
|
||||
|
||||
@@ -213,25 +303,89 @@ describe('DataTable', () => {
|
||||
expect(dataTable.resetSelection).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should select only one row with [single] selection mode', () => {
|
||||
it('should select the row where isSelected is true', () => {
|
||||
dataTable.rows = [
|
||||
{ name: 'TEST1' },
|
||||
{ name: 'FAKE2' },
|
||||
{ name: 'TEST2', isSelected : true },
|
||||
{ name: 'FAKE2' }];
|
||||
dataTable.data = new ObjectDataTableAdapter([],
|
||||
[new ObjectDataColumn({ key: 'name' })]
|
||||
);
|
||||
fixture.detectChanges();
|
||||
const rows = dataTable.data.getRows();
|
||||
expect(rows[0].isSelected).toBeFalsy();
|
||||
expect(rows[1].isSelected).toBeFalsy();
|
||||
expect(rows[2].isSelected).toBeTruthy();
|
||||
expect(rows[3].isSelected).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should not select any row when isSelected is not defined', () => {
|
||||
const dataRows =
|
||||
[
|
||||
{ name: 'TEST1' },
|
||||
{ name: 'FAKE2' },
|
||||
{ name: 'TEST2' }
|
||||
];
|
||||
dataTable.data = new ObjectDataTableAdapter(dataRows,
|
||||
[new ObjectDataColumn({ key: 'name' })]
|
||||
);
|
||||
|
||||
dataTable.ngOnChanges({
|
||||
rows: new SimpleChange(null, dataRows, false)
|
||||
});
|
||||
fixture.detectChanges();
|
||||
|
||||
const rows = dataTable.data.getRows();
|
||||
expect(rows[0].isSelected).toBeFalsy();
|
||||
expect(rows[1].isSelected).toBeFalsy();
|
||||
expect(rows[2].isSelected).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should select only one row with [single] selection mode', (done) => {
|
||||
dataTable.selectionMode = 'single';
|
||||
dataTable.data = new ObjectDataTableAdapter(
|
||||
[
|
||||
{ name: '1' },
|
||||
{ name: '1', isSelected: true },
|
||||
{ name: '2' }
|
||||
],
|
||||
[ new ObjectDataColumn({ key: 'name'}) ]
|
||||
[new ObjectDataColumn({ key: 'name' })]
|
||||
);
|
||||
const rows = dataTable.data.getRows();
|
||||
|
||||
dataTable.ngOnChanges({});
|
||||
dataTable.onRowClick(rows[0], null);
|
||||
expect(rows[0].isSelected).toBeTruthy();
|
||||
expect(rows[1].isSelected).toBeFalsy();
|
||||
|
||||
dataTable.onRowClick(rows[1], null);
|
||||
expect(rows[0].isSelected).toBeFalsy();
|
||||
expect(rows[1].isSelected).toBeTruthy();
|
||||
dataTable.rowClick.subscribe((event) => {
|
||||
expect(rows[0].isSelected).toBeFalsy();
|
||||
expect(rows[1].isSelected).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
|
||||
dataTable.onRowClick(rows[1], new MouseEvent('click'));
|
||||
});
|
||||
|
||||
it('should select only one row with [single] selection mode and key modifier', (done) => {
|
||||
dataTable.selectionMode = 'single';
|
||||
dataTable.data = new ObjectDataTableAdapter(
|
||||
[
|
||||
{ name: '1', isSelected: true },
|
||||
{ name: '2' }
|
||||
],
|
||||
[new ObjectDataColumn({ key: 'name' })]
|
||||
);
|
||||
const rows = dataTable.data.getRows();
|
||||
|
||||
dataTable.ngOnChanges({});
|
||||
|
||||
dataTable.rowClick.subscribe((event) => {
|
||||
expect(rows[0].isSelected).toBeFalsy();
|
||||
expect(rows[1].isSelected).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
|
||||
dataTable.onRowClick(rows[1], new MouseEvent('click', {
|
||||
metaKey: true
|
||||
}));
|
||||
});
|
||||
|
||||
it('should select only one row with [single] selection mode pressing enter key', () => {
|
||||
@@ -278,67 +432,67 @@ describe('DataTable', () => {
|
||||
expect(rows[1].isSelected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not unselect the row with [single] selection mode', () => {
|
||||
it('should NOT unselect the row with [single] selection mode', (done) => {
|
||||
dataTable.selectionMode = 'single';
|
||||
dataTable.data = new ObjectDataTableAdapter(
|
||||
[
|
||||
{ name: '1' },
|
||||
{ name: '1', isSelected: true },
|
||||
{ name: '2' }
|
||||
],
|
||||
[ new ObjectDataColumn({ key: 'name'}) ]
|
||||
[new ObjectDataColumn({ key: 'name' })]
|
||||
);
|
||||
const rows = dataTable.data.getRows();
|
||||
|
||||
dataTable.ngOnChanges({});
|
||||
dataTable.onRowClick(rows[0], null);
|
||||
expect(rows[0].isSelected).toBeTruthy();
|
||||
expect(rows[1].isSelected).toBeFalsy();
|
||||
|
||||
dataTable.rowClick.subscribe((event) => {
|
||||
expect(rows[0].isSelected).toBeTruthy();
|
||||
expect(rows[1].isSelected).toBeFalsy();
|
||||
done();
|
||||
});
|
||||
dataTable.onRowClick(rows[0], null);
|
||||
expect(rows[0].isSelected).toBeTruthy();
|
||||
expect(rows[1].isSelected).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should unselect the row with [multiple] selection mode and modifier key', () => {
|
||||
it('should unselect the row with [multiple] selection mode and modifier key', (done) => {
|
||||
dataTable.selectionMode = 'multiple';
|
||||
dataTable.data = new ObjectDataTableAdapter(
|
||||
[ { name: '1' } ],
|
||||
[ new ObjectDataColumn({ key: 'name'}) ]
|
||||
[{ name: '1', isSelected: true }],
|
||||
[new ObjectDataColumn({ key: 'name' })]
|
||||
);
|
||||
const rows = dataTable.data.getRows();
|
||||
rows[0].isSelected = true;
|
||||
|
||||
dataTable.ngOnChanges({});
|
||||
dataTable.onRowClick(rows[0], null);
|
||||
expect(rows[0].isSelected).toBeTruthy();
|
||||
dataTable.rowClick.subscribe(() => {
|
||||
expect(rows[0].isSelected).toBeFalsy();
|
||||
done();
|
||||
});
|
||||
|
||||
dataTable.onRowClick(rows[0], null);
|
||||
expect(rows[0].isSelected).toBeTruthy();
|
||||
|
||||
dataTable.onRowClick(rows[0], <any> { metaKey: true, preventDefault() {} });
|
||||
expect(rows[0].isSelected).toBeFalsy();
|
||||
dataTable.onRowClick(rows[0], <any> { metaKey: true, preventDefault() { } });
|
||||
});
|
||||
|
||||
it('should select multiple rows with [multiple] selection mode', () => {
|
||||
it('should select multiple rows with [multiple] selection mode and modifier key', (done) => {
|
||||
dataTable.selectionMode = 'multiple';
|
||||
dataTable.data = new ObjectDataTableAdapter(
|
||||
[
|
||||
{ name: '1' },
|
||||
{ name: '1', isSelected: true },
|
||||
{ name: '2' }
|
||||
],
|
||||
[ new ObjectDataColumn({ key: 'name'}) ]
|
||||
[new ObjectDataColumn({ key: 'name' })]
|
||||
);
|
||||
const rows = dataTable.data.getRows();
|
||||
rows[0].isSelected = true;
|
||||
|
||||
const event = new MouseEvent('click', {
|
||||
metaKey: true
|
||||
});
|
||||
|
||||
dataTable.selection.push(rows[0]);
|
||||
dataTable.ngOnChanges({});
|
||||
dataTable.onRowClick(rows[0], event);
|
||||
dataTable.rowClick.subscribe(() => {
|
||||
expect(rows[0].isSelected).toBeTruthy();
|
||||
expect(rows[1].isSelected).toBeTruthy();
|
||||
done();
|
||||
});
|
||||
dataTable.onRowClick(rows[1], event);
|
||||
|
||||
expect(rows[0].isSelected).toBeTruthy();
|
||||
expect(rows[1].isSelected).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should put actions menu to the right by default', () => {
|
||||
@@ -385,15 +539,6 @@ describe('DataTable', () => {
|
||||
expect(table.data).toEqual(jasmine.any(ObjectDataTableAdapter));
|
||||
});
|
||||
|
||||
it('should load data table on onChange', () => {
|
||||
let table = new DataTableComponent(null, null);
|
||||
let data = new ObjectDataTableAdapter([], []);
|
||||
|
||||
expect(table.data).toBeUndefined();
|
||||
table.ngOnChanges({'data': new SimpleChange('123', data, true)});
|
||||
expect(table.data).toEqual(data);
|
||||
});
|
||||
|
||||
it('should initialize with custom data', () => {
|
||||
let data = new ObjectDataTableAdapter([], []);
|
||||
dataTable.data = data;
|
||||
@@ -591,6 +736,22 @@ describe('DataTable', () => {
|
||||
expect(dataTable.isSelectAllChecked).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should reset selection upon data rows change', () => {
|
||||
let data = new ObjectDataTableAdapter([{}, {}, {}], []);
|
||||
|
||||
dataTable.data = data;
|
||||
dataTable.multiselect = true;
|
||||
dataTable.ngAfterContentInit();
|
||||
dataTable.onSelectAllClick(<MatCheckboxChange> { checked: true });
|
||||
|
||||
expect(dataTable.selection.every(entry => entry.isSelected));
|
||||
|
||||
data.setRows([]);
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(dataTable.selection.every(entry => !entry.isSelected));
|
||||
});
|
||||
|
||||
it('should update rows on "select all" click', () => {
|
||||
let data = new ObjectDataTableAdapter([{}, {}, {}], []);
|
||||
let rows = data.getRows();
|
||||
@@ -720,9 +881,9 @@ describe('DataTable', () => {
|
||||
src: 'missing-image'
|
||||
}
|
||||
};
|
||||
|
||||
const row = new FakeDataRow();
|
||||
dataTable.fallbackThumbnail = '<fallback>';
|
||||
dataTable.onImageLoadingError(event);
|
||||
dataTable.onImageLoadingError(event, row);
|
||||
expect(event.target.src).toBe(dataTable.fallbackThumbnail);
|
||||
});
|
||||
|
||||
@@ -733,23 +894,12 @@ describe('DataTable', () => {
|
||||
src: originalSrc
|
||||
}
|
||||
};
|
||||
|
||||
const row = new FakeDataRow();
|
||||
dataTable.fallbackThumbnail = null;
|
||||
dataTable.onImageLoadingError(event);
|
||||
dataTable.onImageLoadingError(event, row);
|
||||
expect(event.target.src).toBe('./assets/images/ft_ic_miscellaneous.svg' );
|
||||
});
|
||||
|
||||
it('should replace image source with icon if fallback is not available and mimeType is provided', () => {
|
||||
let event = <any> {
|
||||
target: {
|
||||
src: 'missing-image'
|
||||
}
|
||||
};
|
||||
|
||||
dataTable.onImageLoadingError(event, 'image/png');
|
||||
expect(event.target.src).toBe('./assets/images/ft_ic_raster_image.svg');
|
||||
});
|
||||
|
||||
it('should not get cell tooltip when row is not provided', () => {
|
||||
const col = <DataColumn> { key: 'name', type: 'text' };
|
||||
expect(dataTable.getCellTooltip(null, col)).toBeNull();
|
||||
@@ -787,20 +937,6 @@ describe('DataTable', () => {
|
||||
expect(dataTable.getCellTooltip(row, col)).toBeNull();
|
||||
});
|
||||
|
||||
it('should cache the rows menu', () => {
|
||||
let emitted = 0;
|
||||
dataTable.showRowActionsMenu.subscribe(() => { emitted++; });
|
||||
|
||||
const column = <DataColumn> {};
|
||||
const row = <DataRow> { getValue: function (key: string) { return 'id'; } };
|
||||
|
||||
dataTable.getRowActions(row, column);
|
||||
dataTable.getRowActions(row, column);
|
||||
dataTable.getRowActions(row, column);
|
||||
|
||||
expect(emitted).toBe(1);
|
||||
});
|
||||
|
||||
it('should reset the menu cache after rows change', () => {
|
||||
let emitted = 0;
|
||||
dataTable.showRowActionsMenu.subscribe(() => { emitted++; });
|
||||
|
@@ -17,19 +17,16 @@
|
||||
|
||||
import {
|
||||
AfterContentInit, Component, ContentChild, DoCheck, ElementRef, EventEmitter, Input,
|
||||
IterableDiffers, OnChanges, Output, SimpleChange, SimpleChanges, TemplateRef, ViewEncapsulation
|
||||
IterableDiffers, OnChanges, Output, SimpleChange, SimpleChanges, TemplateRef, ViewEncapsulation, OnDestroy
|
||||
} from '@angular/core';
|
||||
import { MatCheckboxChange } from '@angular/material';
|
||||
import { Subscription } from 'rxjs/Subscription';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import { Observer } from 'rxjs/Observer';
|
||||
import { Subscription, Observable, Observer } from 'rxjs/Rx';
|
||||
import { DataColumnListComponent } from '../../../data-column/data-column-list.component';
|
||||
import { DataColumn } from '../../data/data-column.model';
|
||||
import { DataRowEvent } from '../../data/data-row-event.model';
|
||||
import { DataRow } from '../../data/data-row.model';
|
||||
import { DataSorting } from '../../data/data-sorting.model';
|
||||
import { DataTableAdapter } from '../../data/datatable-adapter';
|
||||
import { ThumbnailService } from '../../../services/thumbnail.service';
|
||||
|
||||
import { ObjectDataRow } from '../../data/object-datarow.model';
|
||||
import { ObjectDataTableAdapter } from '../../data/object-datatable-adapter';
|
||||
@@ -50,7 +47,7 @@ export enum DisplayMode {
|
||||
templateUrl: './datatable.component.html',
|
||||
encapsulation: ViewEncapsulation.None
|
||||
})
|
||||
export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck {
|
||||
export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck, OnDestroy {
|
||||
|
||||
@ContentChild(DataColumnListComponent)
|
||||
columnList: DataColumnListComponent;
|
||||
@@ -67,6 +64,16 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
@Input()
|
||||
rows: any[] = [];
|
||||
|
||||
/** Define the sort order of the datatable. Possible values are :
|
||||
* [`created`, `desc`], [`created`, `asc`], [`due`, `desc`], [`due`, `asc`]
|
||||
*/
|
||||
@Input()
|
||||
sorting: any[] = [];
|
||||
|
||||
/** The columns that the datatable will show. */
|
||||
@Input()
|
||||
columns: any[] = [];
|
||||
|
||||
/** Row selection mode. Can be none, `single` or `multiple`. For `multiple` mode,
|
||||
* you can use Cmd (macOS) or Ctrl (Win) modifier key to toggle selection for multiple rows.
|
||||
*/
|
||||
@@ -144,6 +151,9 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
@Input()
|
||||
noPermission: boolean = false;
|
||||
|
||||
@Input()
|
||||
rowMenuCacheEnabled = true;
|
||||
|
||||
noContentTemplate: TemplateRef<any>;
|
||||
noPermissionTemplate: TemplateRef<any>;
|
||||
loadingTemplate: TemplateRef<any>;
|
||||
@@ -154,17 +164,16 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
private clickObserver: Observer<DataRowEvent>;
|
||||
private click$: Observable<DataRowEvent>;
|
||||
|
||||
private schema: DataColumn[] = [];
|
||||
|
||||
private differ: any;
|
||||
private rowMenuCache: object = {};
|
||||
|
||||
private subscriptions: Subscription[] = [];
|
||||
private singleClickStreamSub: Subscription;
|
||||
private multiClickStreamSub: Subscription;
|
||||
private dataRowsChanged: Subscription;
|
||||
|
||||
constructor(private elementRef: ElementRef,
|
||||
differs: IterableDiffers,
|
||||
private thumbnailService?: ThumbnailService) {
|
||||
differs: IterableDiffers) {
|
||||
if (differs) {
|
||||
this.differ = differs.find([]).create(null);
|
||||
}
|
||||
@@ -172,6 +181,13 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
}
|
||||
|
||||
ngAfterContentInit() {
|
||||
if (this.columnList) {
|
||||
this.subscriptions.push(
|
||||
this.columnList.columns.changes.subscribe(() => {
|
||||
this.setTableSchema();
|
||||
})
|
||||
);
|
||||
}
|
||||
this.setTableSchema();
|
||||
}
|
||||
|
||||
@@ -182,6 +198,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
this.initTable();
|
||||
} else {
|
||||
this.data = changes['data'].currentValue;
|
||||
this.resetSelection();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -199,6 +216,10 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
this.resetSelection();
|
||||
this.emitRowSelectionEvent('row-unselect', null);
|
||||
}
|
||||
|
||||
if (this.isPropertyChanged(changes['sorting'])) {
|
||||
this.setTableSorting(changes['sorting'].currentValue);
|
||||
}
|
||||
}
|
||||
|
||||
ngDoCheck() {
|
||||
@@ -213,7 +234,13 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
}
|
||||
|
||||
convertToRowsData(rows: any []): ObjectDataRow[] {
|
||||
return rows.map(row => new ObjectDataRow(row));
|
||||
return rows.map(row => new ObjectDataRow(row, row.isSelected));
|
||||
}
|
||||
|
||||
convertToDataSorting(sorting: any[]): DataSorting {
|
||||
if (sorting && sorting.length > 0) {
|
||||
return new DataSorting(sorting[0], sorting[1]);
|
||||
}
|
||||
}
|
||||
|
||||
private initAndSubscribeClickStream() {
|
||||
@@ -225,6 +252,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
|
||||
this.singleClickStreamSub = singleClickStream.subscribe((obj: DataRowEvent[]) => {
|
||||
let event: DataRowEvent = obj[0];
|
||||
this.handleRowSelection(event.value, <MouseEvent | KeyboardEvent> event.event);
|
||||
this.rowClick.emit(event);
|
||||
if (!event.defaultPrevented) {
|
||||
this.elementRef.nativeElement.dispatchEvent(
|
||||
@@ -258,14 +286,18 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
private unsubscribeClickStream() {
|
||||
if (this.singleClickStreamSub) {
|
||||
this.singleClickStreamSub.unsubscribe();
|
||||
this.singleClickStreamSub = null;
|
||||
}
|
||||
if (this.multiClickStreamSub) {
|
||||
this.multiClickStreamSub.unsubscribe();
|
||||
this.multiClickStreamSub = null;
|
||||
}
|
||||
}
|
||||
|
||||
private initTable() {
|
||||
this.data = new ObjectDataTableAdapter(this.rows, this.schema);
|
||||
this.data = new ObjectDataTableAdapter(this.rows, this.columns);
|
||||
this.setTableSorting(this.sorting);
|
||||
this.resetSelection();
|
||||
this.rowMenuCache = {};
|
||||
}
|
||||
|
||||
@@ -273,29 +305,48 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
return this.data === undefined || this.data === null;
|
||||
}
|
||||
|
||||
private setTableRows(rows) {
|
||||
private setTableRows(rows: any[]) {
|
||||
if (this.data) {
|
||||
this.resetSelection();
|
||||
this.data.setRows(this.convertToRowsData(rows));
|
||||
}
|
||||
}
|
||||
|
||||
private setTableSchema() {
|
||||
if (this.columnList && this.columnList.columns) {
|
||||
this.schema = this.columnList.columns.map(c => <DataColumn> c);
|
||||
let schema = [];
|
||||
if (!this.columns || this.columns.length === 0) {
|
||||
schema = this.getSchemaFromHtml();
|
||||
} else {
|
||||
schema = this.columns.concat(this.getSchemaFromHtml());
|
||||
}
|
||||
|
||||
if (this.data && this.schema && this.schema.length > 0) {
|
||||
this.data.setColumns(this.schema);
|
||||
this.columns = schema;
|
||||
|
||||
if (this.data && this.columns && this.columns.length > 0) {
|
||||
this.data.setColumns(this.columns);
|
||||
}
|
||||
}
|
||||
|
||||
private setTableSorting(sorting) {
|
||||
if (this.data) {
|
||||
this.data.setSorting(this.convertToDataSorting(sorting));
|
||||
}
|
||||
}
|
||||
|
||||
public getSchemaFromHtml(): any {
|
||||
let schema = [];
|
||||
if (this.columnList && this.columnList.columns && this.columnList.columns.length > 0) {
|
||||
schema = this.columnList.columns.map(c => <DataColumn> c);
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
onRowClick(row: DataRow, e: MouseEvent) {
|
||||
if (e) {
|
||||
e.preventDefault();
|
||||
}
|
||||
|
||||
if (row) {
|
||||
this.handleRowSelection(row, e);
|
||||
const dataRowEvent = new DataRowEvent(row, e, this);
|
||||
this.clickObserver.next(dataRowEvent);
|
||||
}
|
||||
@@ -317,7 +368,12 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
|
||||
if (this.isMultiSelectionMode()) {
|
||||
const modifier = e && (e.metaKey || e.ctrlKey);
|
||||
const newValue = modifier ? !row.isSelected : true;
|
||||
let newValue: boolean;
|
||||
if (this.selection.length === 1) {
|
||||
newValue = !row.isSelected;
|
||||
} else {
|
||||
newValue = modifier ? !row.isSelected : true;
|
||||
}
|
||||
const domEventName = newValue ? 'row-select' : 'row-unselect';
|
||||
|
||||
if (!modifier) {
|
||||
@@ -335,7 +391,7 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
if (rows && rows.length > 0) {
|
||||
rows.forEach(r => r.isSelected = false);
|
||||
}
|
||||
this.selection.splice(0);
|
||||
this.selection = [];
|
||||
}
|
||||
this.isSelectAllChecked = false;
|
||||
}
|
||||
@@ -424,15 +480,14 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
this.emitRowSelectionEvent(domEventName, row);
|
||||
}
|
||||
|
||||
onImageLoadingError(event: Event, mimeType?: string) {
|
||||
|
||||
onImageLoadingError(event: Event, row: DataRow) {
|
||||
if (event) {
|
||||
let element = <any> event.target;
|
||||
|
||||
if (this.fallbackThumbnail) {
|
||||
element.src = this.fallbackThumbnail;
|
||||
} else {
|
||||
element.src = this.thumbnailService.getMimeTypeIcon(mimeType);
|
||||
element.src = row.imageErrorResolver(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -477,6 +532,9 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
if (!this.rowMenuCache[id]) {
|
||||
let event = new DataCellEvent(row, col, []);
|
||||
this.showRowActionsMenu.emit(event);
|
||||
if (!this.rowMenuCacheEnabled) {
|
||||
return event.value.actions;
|
||||
}
|
||||
this.rowMenuCache[id] = event.value.actions;
|
||||
}
|
||||
|
||||
@@ -523,11 +581,10 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
}
|
||||
}
|
||||
|
||||
private selectRow(row: DataRow, value: boolean) {
|
||||
selectRow(row: DataRow, value: boolean) {
|
||||
if (row) {
|
||||
row.isSelected = value;
|
||||
const idx = this.selection.indexOf(row);
|
||||
|
||||
if (value) {
|
||||
if (idx < 0) {
|
||||
this.selection.push(row);
|
||||
@@ -551,8 +608,8 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
}
|
||||
|
||||
getSortableColumns() {
|
||||
return this.data.getColumns().filter((currentColum) => {
|
||||
return currentColum.sortable === true;
|
||||
return this.data.getColumns().filter(column => {
|
||||
return column.sortable === true;
|
||||
});
|
||||
}
|
||||
|
||||
@@ -585,4 +642,16 @@ export class DataTableComponent implements AfterContentInit, OnChanges, DoCheck
|
||||
});
|
||||
this.elementRef.nativeElement.dispatchEvent(domEvent);
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.unsubscribeClickStream();
|
||||
|
||||
this.subscriptions.forEach(s => s.unsubscribe());
|
||||
this.subscriptions = [];
|
||||
|
||||
if (this.dataRowsChanged) {
|
||||
this.dataRowsChanged.unsubscribe();
|
||||
this.dataRowsChanged = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -15,18 +15,38 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { DataTableCellComponent } from './datatable-cell.component';
|
||||
import { UserPreferencesService, UserPreferenceValues } from '../../../services/user-preferences.service';
|
||||
|
||||
@Component({
|
||||
selector: 'adf-date-cell',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
|
||||
template: `
|
||||
<ng-container>
|
||||
<span [title]="tooltip">{{value}}</span>
|
||||
<span title="{{ tooltip | date:'medium' }}" *ngIf="column?.format === 'timeAgo' else standard_date">
|
||||
{{ value | adfTimeAgo: currentLocale }}
|
||||
</span>
|
||||
</ng-container>
|
||||
<ng-template #standard_date>
|
||||
<span title="{{ tooltip | date:'medium' }}">
|
||||
{{ value | date:'medium' }}
|
||||
</span>
|
||||
</ng-template>
|
||||
`,
|
||||
encapsulation: ViewEncapsulation.None,
|
||||
host: { class: 'adf-date-cell' }
|
||||
})
|
||||
export class DateCellComponent extends DataTableCellComponent {}
|
||||
export class DateCellComponent extends DataTableCellComponent {
|
||||
|
||||
currentLocale;
|
||||
|
||||
constructor(userPreferenceService: UserPreferencesService) {
|
||||
super();
|
||||
|
||||
userPreferenceService.select(UserPreferenceValues.Locale).subscribe((locale) => {
|
||||
this.currentLocale = locale;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -17,21 +17,25 @@
|
||||
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { EmptyListComponent } from './empty-list.component';
|
||||
import { setupTestBed } from '../../../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
||||
|
||||
describe('EmptyListComponentComponent', () => {
|
||||
let component: EmptyListComponent;
|
||||
let fixture: ComponentFixture<EmptyListComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [
|
||||
EmptyListComponent
|
||||
]
|
||||
}).compileComponents();
|
||||
setupTestBed({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EmptyListComponent);
|
||||
component = fixture.componentInstance;
|
||||
}));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should be defined', () => {
|
||||
expect(component).toBeDefined();
|
||||
|
@@ -16,11 +16,12 @@
|
||||
*/
|
||||
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { ObjectDataTableAdapter } from './../../data/object-datatable-adapter';
|
||||
import { ObjectDataColumn } from './../../data/object-datacolumn.model';
|
||||
|
||||
import { LocationCellComponent } from './location-cell.component';
|
||||
import { setupTestBed } from '../../../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../../../testing/core.testing.module';
|
||||
|
||||
describe('LocationCellComponent', () => {
|
||||
let component: LocationCellComponent;
|
||||
@@ -29,16 +30,11 @@ describe('LocationCellComponent', () => {
|
||||
let rowData;
|
||||
let columnData;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule
|
||||
],
|
||||
declarations: [
|
||||
LocationCellComponent
|
||||
]
|
||||
}).compileComponents();
|
||||
setupTestBed({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
|
||||
beforeEach(async(() => {
|
||||
fixture = TestBed.createComponent(LocationCellComponent);
|
||||
component = fixture.componentInstance;
|
||||
}));
|
||||
@@ -69,6 +65,10 @@ describe('LocationCellComponent', () => {
|
||||
component.row = dataTableAdapter.getRows()[0];
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should set displayText', () => {
|
||||
fixture.detectChanges();
|
||||
|
||||
|
@@ -19,6 +19,10 @@ export interface DataRow {
|
||||
isSelected: boolean;
|
||||
isDropTarget?: boolean;
|
||||
cssClass?: string;
|
||||
|
||||
hasValue(key: string): boolean;
|
||||
|
||||
getValue(key: string): any;
|
||||
|
||||
imageErrorResolver?(event: Event): any;
|
||||
}
|
||||
|
80
lib/core/datatable/data/data-table.schema.ts
Normal file
80
lib/core/datatable/data/data-table.schema.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { ContentChild, Input } from '@angular/core';
|
||||
import { AppConfigService } from '../../app-config/app-config.service';
|
||||
import { DataColumnListComponent } from '../../data-column/data-column-list.component';
|
||||
import { DataColumn } from './data-column.model';
|
||||
import { ObjectDataColumn } from './object-datacolumn.model';
|
||||
|
||||
export abstract class DataTableSchema {
|
||||
|
||||
@ContentChild(DataColumnListComponent) columnList: DataColumnListComponent;
|
||||
|
||||
/** Custom preset column schema in JSON format. */
|
||||
@Input()
|
||||
presetColumn: string;
|
||||
|
||||
columns: any;
|
||||
|
||||
private layoutPresets = {};
|
||||
|
||||
constructor(private appConfigService: AppConfigService,
|
||||
protected presetKey: string,
|
||||
protected presetsModel: any) { }
|
||||
|
||||
public createDatatableSchema(): void {
|
||||
this.loadLayoutPresets();
|
||||
if (!this.columns || this.columns.length === 0) {
|
||||
this.columns = this.mergeJsonAndHtmlSchema();
|
||||
}
|
||||
}
|
||||
|
||||
public loadLayoutPresets(): void {
|
||||
const externalSettings = this.appConfigService.get(this.presetKey, null);
|
||||
if (externalSettings) {
|
||||
this.layoutPresets = Object.assign({}, this.presetsModel, externalSettings);
|
||||
} else {
|
||||
this.layoutPresets = this.presetsModel;
|
||||
}
|
||||
}
|
||||
|
||||
public mergeJsonAndHtmlSchema(): any {
|
||||
let customSchemaColumns = [];
|
||||
customSchemaColumns = this.getSchemaFromConfig(this.presetColumn).concat(this.getSchemaFromHtml(this.columnList));
|
||||
if (customSchemaColumns.length === 0) {
|
||||
customSchemaColumns = this.getDefaultLayoutPreset();
|
||||
}
|
||||
return customSchemaColumns;
|
||||
}
|
||||
|
||||
public getSchemaFromHtml(columnList: DataColumnListComponent): any {
|
||||
let schema = [];
|
||||
if (columnList && columnList.columns && columnList.columns.length > 0) {
|
||||
schema = columnList.columns.map(c => <DataColumn> c);
|
||||
}
|
||||
return schema;
|
||||
}
|
||||
|
||||
public getSchemaFromConfig(presetColoumn: string): DataColumn[] {
|
||||
return presetColoumn ? (this.layoutPresets[presetColoumn]).map(col => new ObjectDataColumn(col)) : [];
|
||||
}
|
||||
|
||||
private getDefaultLayoutPreset(): DataColumn[] {
|
||||
return (this.layoutPresets['default']).map(col => new ObjectDataColumn(col));
|
||||
}
|
||||
}
|
@@ -18,8 +18,11 @@
|
||||
import { DataColumn } from './data-column.model';
|
||||
import { DataRow } from './data-row.model';
|
||||
import { DataSorting } from './data-sorting.model';
|
||||
import { Subject } from 'rxjs/Rx';
|
||||
|
||||
export interface DataTableAdapter {
|
||||
rowsChanged?: Subject<Array<DataRow>>;
|
||||
|
||||
selectedRow: DataRow;
|
||||
getRows(): Array<DataRow>;
|
||||
setRows(rows: Array<DataRow>): void;
|
||||
|
@@ -35,4 +35,8 @@ export class ObjectDataRow implements DataRow {
|
||||
hasValue(key: string): boolean {
|
||||
return this.getValue(key) !== undefined;
|
||||
}
|
||||
|
||||
imageErrorResolver(event: Event): string {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
@@ -15,15 +15,13 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { DatePipe } from '@angular/common';
|
||||
|
||||
import { TimeAgoPipe } from '../../pipes';
|
||||
import { DataColumn } from './data-column.model';
|
||||
import { DataRow } from './data-row.model';
|
||||
import { ObjectDataRow } from './object-datarow.model';
|
||||
import { ObjectDataColumn } from './object-datacolumn.model';
|
||||
import { DataSorting } from './data-sorting.model';
|
||||
import { DataTableAdapter } from './datatable-adapter';
|
||||
import { Subject } from 'rxjs/Subject';
|
||||
|
||||
// Simple implementation of the DataTableAdapter interface.
|
||||
export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
@@ -33,6 +31,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
private _columns: DataColumn[];
|
||||
|
||||
selectedRow: DataRow;
|
||||
rowsChanged: Subject<Array<DataRow>>;
|
||||
|
||||
static generateSchema(data: any[]) {
|
||||
let schema = [];
|
||||
@@ -78,6 +77,8 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
this.sort(sortable[0].key, 'asc');
|
||||
}
|
||||
}
|
||||
|
||||
this.rowsChanged = new Subject<Array<DataRow>>();
|
||||
}
|
||||
|
||||
getRows(): Array<DataRow> {
|
||||
@@ -87,6 +88,7 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
setRows(rows: Array<DataRow>) {
|
||||
this._rows = rows || [];
|
||||
this.sort();
|
||||
this.rowsChanged.next(this._rows);
|
||||
}
|
||||
|
||||
getColumns(): Array<DataColumn> {
|
||||
@@ -107,14 +109,6 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
|
||||
let value = row.getValue(col.key);
|
||||
|
||||
if (col.type === 'date') {
|
||||
try {
|
||||
return this.formatDate(col, value);
|
||||
} catch (err) {
|
||||
console.error(`Error parsing date ${value} to format ${col.format}`);
|
||||
}
|
||||
}
|
||||
|
||||
if (col.type === 'icon') {
|
||||
const icon = row.getValue(col.key);
|
||||
return icon;
|
||||
@@ -123,21 +117,6 @@ export class ObjectDataTableAdapter implements DataTableAdapter {
|
||||
return value;
|
||||
}
|
||||
|
||||
formatDate(col: DataColumn, value: any): string {
|
||||
if (col.type === 'date') {
|
||||
const format = col.format || 'medium';
|
||||
if (format === 'timeAgo') {
|
||||
const timeAgoPipe = new TimeAgoPipe();
|
||||
return timeAgoPipe.transform(value);
|
||||
} else {
|
||||
const datePipe = new DatePipe('en-US');
|
||||
return datePipe.transform(value, format);
|
||||
}
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
getSorting(): DataSorting {
|
||||
return this._sorting;
|
||||
}
|
||||
|
@@ -37,6 +37,7 @@ import { LocationCellComponent } from './components/datatable/location-cell.comp
|
||||
import { LoadingContentTemplateDirective } from './directives/loading-template.directive';
|
||||
import { NoContentTemplateDirective } from './directives/no-content-template.directive';
|
||||
import { NoPermissionTemplateDirective } from './directives/no-permission-template.directive';
|
||||
import { EmptyCustomContentDirective } from './directives/empty-custom-content.directive';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
@@ -60,7 +61,8 @@ import { NoPermissionTemplateDirective } from './directives/no-permission-templa
|
||||
LocationCellComponent,
|
||||
NoContentTemplateDirective,
|
||||
NoPermissionTemplateDirective,
|
||||
LoadingContentTemplateDirective
|
||||
LoadingContentTemplateDirective,
|
||||
EmptyCustomContentDirective
|
||||
],
|
||||
exports: [
|
||||
DataTableComponent,
|
||||
@@ -74,7 +76,8 @@ import { NoPermissionTemplateDirective } from './directives/no-permission-templa
|
||||
LocationCellComponent,
|
||||
NoContentTemplateDirective,
|
||||
NoPermissionTemplateDirective,
|
||||
LoadingContentTemplateDirective
|
||||
LoadingContentTemplateDirective,
|
||||
EmptyCustomContentDirective
|
||||
]
|
||||
})
|
||||
export class DataTableModule {}
|
||||
|
@@ -0,0 +1,24 @@
|
||||
/*!
|
||||
* @license
|
||||
* Copyright 2016 Alfresco Software, Ltd.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { Directive } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: 'adf-empty-custom-content'
|
||||
})
|
||||
|
||||
export class EmptyCustomContentDirective {}
|
@@ -15,44 +15,32 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { DataTableCellComponent } from '../components/datatable/datatable-cell.component';
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { DataTableComponent } from '../components/datatable/datatable.component';
|
||||
import { DateCellComponent } from '../components/datatable/date-cell.component';
|
||||
import { FileSizeCellComponent } from '../components/datatable/filesize-cell.component';
|
||||
import { LocationCellComponent } from '../components/datatable/location-cell.component';
|
||||
import { MaterialModule } from '../../material.module';
|
||||
import { LoadingContentTemplateDirective } from './loading-template.directive';
|
||||
import { setupTestBed } from '../../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
|
||||
describe('LoadingContentTemplateDirective', () => {
|
||||
|
||||
let fixture: ComponentFixture<DataTableComponent>;
|
||||
let dataTable: DataTableComponent;
|
||||
let directive: LoadingContentTemplateDirective;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule,
|
||||
MaterialModule
|
||||
],
|
||||
declarations: [
|
||||
DataTableComponent,
|
||||
DataTableCellComponent,
|
||||
LocationCellComponent,
|
||||
LoadingContentTemplateDirective,
|
||||
DateCellComponent,
|
||||
FileSizeCellComponent
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
setupTestBed({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
let fixture = TestBed.createComponent(DataTableComponent);
|
||||
fixture = TestBed.createComponent(DataTableComponent);
|
||||
dataTable = fixture.componentInstance;
|
||||
directive = new LoadingContentTemplateDirective(dataTable);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('applies template to the datatable', () => {
|
||||
const template: any = 'test template';
|
||||
directive.template = template;
|
||||
|
@@ -15,44 +15,32 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { DataTableCellComponent } from '../components/datatable/datatable-cell.component';
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { DataTableComponent } from '../components/datatable/datatable.component';
|
||||
import { DateCellComponent } from '../components/datatable/date-cell.component';
|
||||
import { FileSizeCellComponent } from '../components/datatable/filesize-cell.component';
|
||||
import { LocationCellComponent } from '../components/datatable/location-cell.component';
|
||||
import { MaterialModule } from '../../material.module';
|
||||
import { NoContentTemplateDirective } from './no-content-template.directive';
|
||||
import { setupTestBed } from '../../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
|
||||
describe('NoContentTemplateDirective', () => {
|
||||
|
||||
let fixture: ComponentFixture<DataTableComponent>;
|
||||
let dataTable: DataTableComponent;
|
||||
let directive: NoContentTemplateDirective;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule,
|
||||
MaterialModule
|
||||
],
|
||||
declarations: [
|
||||
DataTableComponent,
|
||||
DataTableCellComponent,
|
||||
DateCellComponent,
|
||||
NoContentTemplateDirective,
|
||||
LocationCellComponent,
|
||||
FileSizeCellComponent
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
setupTestBed({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
let fixture = TestBed.createComponent(DataTableComponent);
|
||||
fixture = TestBed.createComponent(DataTableComponent);
|
||||
dataTable = fixture.componentInstance;
|
||||
directive = new NoContentTemplateDirective(dataTable);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('applies template to the datatable', () => {
|
||||
const template: any = 'test template';
|
||||
directive.template = template;
|
||||
|
@@ -15,44 +15,32 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { async, TestBed } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { DataTableCellComponent } from '../components/datatable/datatable-cell.component';
|
||||
import { TestBed, ComponentFixture } from '@angular/core/testing';
|
||||
import { DataTableComponent } from '../components/datatable/datatable.component';
|
||||
import { DateCellComponent } from '../components/datatable/date-cell.component';
|
||||
import { FileSizeCellComponent } from '../components/datatable/filesize-cell.component';
|
||||
import { LocationCellComponent } from '../components/datatable/location-cell.component';
|
||||
import { MaterialModule } from '../../material.module';
|
||||
import { NoPermissionTemplateDirective } from './no-permission-template.directive';
|
||||
import { setupTestBed } from '../../testing/setupTestBed';
|
||||
import { CoreTestingModule } from '../../testing/core.testing.module';
|
||||
|
||||
describe('NoPermissionTemplateDirective', () => {
|
||||
|
||||
let fixture: ComponentFixture<DataTableComponent>;
|
||||
let dataTable: DataTableComponent;
|
||||
let directive: NoPermissionTemplateDirective;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule,
|
||||
MaterialModule
|
||||
],
|
||||
declarations: [
|
||||
DataTableComponent,
|
||||
DataTableCellComponent,
|
||||
DateCellComponent,
|
||||
NoPermissionTemplateDirective,
|
||||
LocationCellComponent,
|
||||
FileSizeCellComponent
|
||||
]
|
||||
}).compileComponents();
|
||||
}));
|
||||
setupTestBed({
|
||||
imports: [CoreTestingModule]
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
let fixture = TestBed.createComponent(DataTableComponent);
|
||||
fixture = TestBed.createComponent(DataTableComponent);
|
||||
dataTable = fixture.componentInstance;
|
||||
directive = new NoPermissionTemplateDirective(dataTable);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
fixture.destroy();
|
||||
});
|
||||
|
||||
it('should apply template to the datatable', () => {
|
||||
const template: any = 'test template';
|
||||
directive.template = template;
|
||||
|
@@ -35,9 +35,11 @@ export * from './components/datatable/date-cell.component';
|
||||
export * from './components/datatable/empty-list.component';
|
||||
export * from './components/datatable/filesize-cell.component';
|
||||
export * from './components/datatable/location-cell.component';
|
||||
export * from './data/data-table.schema';
|
||||
|
||||
export * from './directives/loading-template.directive';
|
||||
export * from './directives/no-content-template.directive';
|
||||
export * from './directives/no-permission-template.directive';
|
||||
export * from './directives/empty-custom-content.directive';
|
||||
|
||||
export * from './datatable.module';
|
||||
|
Reference in New Issue
Block a user