Skip to content

Instantly share code, notes, and snippets.

@mynameistechno
Created September 18, 2019 21:00
Show Gist options
  • Save mynameistechno/1358a986c0d573631270230666930b38 to your computer and use it in GitHub Desktop.
Save mynameistechno/1358a986c0d573631270230666930b38 to your computer and use it in GitHub Desktop.
Scanner order
diff --git a/client/pages/fileset.js b/client/pages/fileset.js
index 3e454dbd..0a074421 100644
--- a/client/pages/fileset.js
+++ b/client/pages/fileset.js
@@ -43,6 +43,7 @@ function create(opts: DefaultPageOptions): Observable {
filesetId: hg.value(''),
uri: hg.value(''),
fileset: hg.varhash({}),
+ scanners: hg.array([]),
filesetFilesMeta: hg.varhash({}),
relatedFilesets: relatedFilesets.create(options),
messages,
@@ -415,6 +416,31 @@ function renderScannerRow(
);
}
+const getScannerGroup = ({attributes: {deprecated, is_default}}) => {
+ if (is_default && !deprecated) {
+ return 'active_default';
+ } else if (!deprecated) {
+ return 'active';
+ }
+ return 'deprecated';
+};
+
+function getFilesetScanners(state: Snapshot): ApiScannerRow[] {
+ const filesetScanners = api.getRelatedResourceIdentifiers(
+ state.fileset,
+ 'scanners'
+ );
+ const {active_default, active, deprecated} = R.groupBy(getScannerGroup)(
+ state.scanners
+ );
+ const orderedScanners = [
+ ...R.sortBy(R.path(['attributes', 'name']))(active_default),
+ ...R.sortBy(R.path(['attributes', 'name']))(active),
+ ...R.sortBy(R.path(['attributes', 'name']))(deprecated)
+ ];
+ return orderedScanners.map(({id}) => filesetScanners.find(x => x.id === id));
+}
+
function renderScannerTable(state: Snapshot): VDomElement {
const fileMetaInfo = api.getRelatedResourceIdentifierMeta(
state.fileset,
@@ -422,9 +448,7 @@ function renderScannerTable(state: Snapshot): VDomElement {
);
const totalFiles = fileMetaInfo ? fileMetaInfo.count : 0;
const ignoredFiles = fileMetaInfo ? fileMetaInfo.ignored_file_count : 0;
-
- const rows = api.getRelatedResourceIdentifiers(state.fileset, 'scanners');
- const renderedRows = rows.map(row =>
+ const renderedRows = getFilesetScanners(state).map(row =>
renderScannerRow(row, totalFiles, ignoredFiles, state.filesetId)
);
const rowsInTbody = h('tbody', renderedRows);
@@ -803,6 +827,7 @@ function getFileset(state: Observable, request: Request): RequestObject {
function getFilesetSuccess(state: Observable, resp: Object) {
state.fileset.set(resp.data);
+ state.scanners.set(api.getIncludedResourceByType(resp.included, 'scanners'));
state.uri.set(resp.data.attributes.uri);
state.status.set('loaded');
}
@mynameistechno
Copy link
Author

mynameistechno commented Sep 18, 2019

const getScannerGroup = ({
  attributes: {deprecated, is_default}
}: {
  attributes: Scanner
}): string => {
  if (is_default && !deprecated) {
    return 'active_default';
  } else if (!deprecated) {
    return 'active';
  }
  return 'deprecated';
};

function getFilesetScanners(state: Snapshot): ApiScannerRow[] {
  const filesetScanners = api.getRelatedResourceIdentifiers(
    state.fileset,
    'scanners'
  );
  const {active_default, active, deprecated} = R.groupBy(getScannerGroup)(
    state.scanners
  );
  const orderedScanners = [
    ...R.sortBy(R.path(['attributes', 'name']))(active_default),
    ...R.sortBy(R.path(['attributes', 'name']))(active),
    ...R.sortBy(R.path(['attributes', 'name']))(deprecated)
  ];
  return orderedScanners.map(({id}) => filesetScanners.find(x => x.id === id));
}

@mynameistechno
Copy link
Author

diff --git a/client/pages/fileset.js b/client/pages/fileset.js
index 3e454dbd..f26bc03d 100644
--- a/client/pages/fileset.js
+++ b/client/pages/fileset.js
@@ -43,6 +43,7 @@ function create(opts: DefaultPageOptions): Observable {
     filesetId: hg.value(''),
     uri: hg.value(''),
     fileset: hg.varhash({}),
+    scanners: hg.array([]),
     filesetFilesMeta: hg.varhash({}),
     relatedFilesets: relatedFilesets.create(options),
     messages,
@@ -378,6 +379,7 @@ function renderFlagCharts(frel: Object, state: Snapshot): VDomElement {
   ]);
 }
 
+type ScannerGroup = 'active_default' | 'active' | 'deprecated';
 type ApiFlagCount = {
   new?: string
 };
@@ -388,7 +390,8 @@ type ApiScannerRow = {
     scanned_file_count: number,
     file_count_by_state: ApiFlagCount,
     flag_count_by_state: ApiFlagCount
-  }
+  },
+  group: ScannerGroup
 };
 
 function renderScannerRow(
@@ -403,7 +406,10 @@ function renderScannerRow(
   const unscannedFiles = totalFiles - scannedFiles - ignoredFiles;
   return h(
     'tr',
-    {attributes: {'data-e2e-id': `${scannerName}-by-scanner-row`}},
+    {
+      attributes: {'data-e2e-id': `${scannerName}-by-scanner-row`},
+      className: `scanner-group-${row.group}`
+    },
     [
       h('td', fsFilterAnchor(filesetId, 'scanner', scannerName)),
       h('td.barred', utils.addCommas(totalFiles)),
@@ -415,6 +421,50 @@ function renderScannerRow(
   );
 }
 
+type JSONAPIScanner = {id: string, attributes: Scanner};
+
+const getScannerGroup = ({
+  attributes: {deprecated, is_default}
+}: JSONAPIScanner): ScannerGroup => {
+  if (is_default && !deprecated) {
+    return 'active_default';
+  } else if (!deprecated) {
+    return 'active';
+  }
+  return 'deprecated';
+};
+
+type GetScannerForSummaryCreator = JSONAPIScanner => ?ApiScannerRow;
+
+const getScannerForSummaryCreator = (
+  fileset: Snapshot
+): GetScannerForSummaryCreator => (
+  orderedScanner: JSONAPIScanner
+): ?ApiScannerRow => {
+  const filesetScanners = api.getRelatedResourceIdentifiers(
+    fileset,
+    'scanners'
+  );
+  const scanner = filesetScanners.find(x => x.id === orderedScanner.id);
+  if (scanner) {
+    return {...scanner, group: getScannerGroup(orderedScanner)};
+  }
+  return scanner;
+};
+
+const sortGroup = (group: ScannerGroup): Scanner[] =>
+  R.sortBy(R.path(['attributes', 'name']))(group);
+
+function getFilesetScanners(state: Snapshot): ApiScannerRow[] {
+  const groups = R.groupBy(getScannerGroup)(state.scanners);
+  const createScannerForSummary = getScannerForSummaryCreator(state.fileset);
+  return R.pipe(
+    R.map(group => sortGroup(groups[group])),
+    R.flatten,
+    R.map(createScannerForSummary)
+  )(['active_default', 'active', 'deprecated']);
+}
+
 function renderScannerTable(state: Snapshot): VDomElement {
   const fileMetaInfo = api.getRelatedResourceIdentifierMeta(
     state.fileset,
@@ -422,9 +472,7 @@ function renderScannerTable(state: Snapshot): VDomElement {
   );
   const totalFiles = fileMetaInfo ? fileMetaInfo.count : 0;
   const ignoredFiles = fileMetaInfo ? fileMetaInfo.ignored_file_count : 0;
-
-  const rows = api.getRelatedResourceIdentifiers(state.fileset, 'scanners');
-  const renderedRows = rows.map(row =>
+  const renderedRows = getFilesetScanners(state).map(row =>
     renderScannerRow(row, totalFiles, ignoredFiles, state.filesetId)
   );
   const rowsInTbody = h('tbody', renderedRows);
@@ -803,6 +851,7 @@ function getFileset(state: Observable, request: Request): RequestObject {
 
 function getFilesetSuccess(state: Observable, resp: Object) {
   state.fileset.set(resp.data);
+  state.scanners.set(api.getIncludedResourceByType(resp.included, 'scanners'));
   state.uri.set(resp.data.attributes.uri);
   state.status.set('loaded');
 }
diff --git a/server/css/fileset.styl b/server/css/fileset.styl
index ddb66df1..7f7c4d1c 100644
--- a/server/css/fileset.styl
+++ b/server/css/fileset.styl
@@ -154,5 +154,4 @@
 
 .related-filesets-list-container {
   max-height: 200px;
-}
-
+}
\ No newline at end of file

@mynameistechno
Copy link
Author

type JSONAPIScanner = {id: string, attributes: Scanner};

const getScannerGroup = ({
  attributes: {deprecated, is_default}
}: JSONAPIScanner): ScannerGroup => {
  if (is_default && !deprecated) {
    return 'active_default';
  } else if (!deprecated) {
    return 'active';
  }
  return 'deprecated';
};

type GetScannerForSummaryCreator = JSONAPIScanner => ?ApiScannerRow;

const getScannerForSummaryCreator = (
  fileset: Snapshot
): GetScannerForSummaryCreator => (
  orderedScanner: JSONAPIScanner
): ?ApiScannerRow => {
  const filesetScanners = api.getRelatedResourceIdentifiers(
    fileset,
    'scanners'
  );
  const scanner = filesetScanners.find(x => x.id === orderedScanner.id);
  if (scanner) {
    return {...scanner, group: getScannerGroup(orderedScanner)};
  }
  return scanner;
};

const sortGroup = (group: ScannerGroup): Scanner[] =>
  R.sortBy(R.path(['attributes', 'name']))(group);

function getFilesetScanners(state: Snapshot): ApiScannerRow[] {
  const groups = R.groupBy(getScannerGroup)(state.scanners);
  const createScannerForSummary = getScannerForSummaryCreator(state.fileset);
  return R.pipe(
    R.map(group => sortGroup(groups[group])),
    R.flatten,
    R.map(createScannerForSummary)
  )(['active_default', 'active', 'deprecated']);
}

@mynameistechno
Copy link
Author

It might be a little cryptic but getScannerForSummaryCreator is a function that returns a function. It returns a closure (because it keeps the fileset variable bound).

@mynameistechno
Copy link
Author

mynameistechno commented Sep 19, 2019

Actually if i use function instead of anonymous functions it's a bit clearer. I also put filesetScanners in the enclosing function so api.getRelatedResourceIdentifiers is only called once. Use the below for getScannerForSummaryCreator

function getScannerForSummaryCreator(
  fileset: Snapshot
): GetScannerForSummaryCreator {
  const filesetScanners = api.getRelatedResourceIdentifiers(
    fileset,
    'scanners'
  );
  return function createScannerForSummary(
    orderedScanner: JSONAPIScanner
  ): ?ApiScannerRow {
    const scanner = filesetScanners.find(x => x.id === orderedScanner.id);
    if (scanner) {
      return {...scanner, group: getScannerGroup(orderedScanner)};
    }
  };
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment