mirror of
				https://gitlab.ub.uni-bielefeld.de/sfb1288inf/nopaque.git
				synced 2025-11-04 12:22:47 +00:00 
			
		
		
		
	Use enums where appropriate. This commit includes new migrations that are NOT compatible with older nopaque instances
This commit is contained in:
		@@ -31,7 +31,7 @@ class App {
 | 
			
		||||
        iconPrefix = '<i class="error-color-text left material-icons">error</i>';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'job':
 | 
			
		||||
        iconPrefix = '<i class="left nopaque-icons">J</i>';
 | 
			
		||||
        iconPrefix = '<i class="left nopaque-icon">J</i>';
 | 
			
		||||
        break;
 | 
			
		||||
      default:
 | 
			
		||||
        iconPrefix = '<i class="left material-icons">notifications</i>';
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ class JobStatusNotifier {
 | 
			
		||||
      .filter(operation => re.test(operation.path));
 | 
			
		||||
    for (operation of filteredPatch) {
 | 
			
		||||
      [match, jobId] = operation.path.match(re);
 | 
			
		||||
      app.flash(`[<a href="/jobs/${jobId}">${app.users[this.userId].jobs[jobId].title}</a>] New status: ${operation.value}`, 'job');
 | 
			
		||||
      app.flash(`[<a href="/jobs/${jobId}">${app.users[this.userId].jobs[jobId].title}</a>] New status: <span class="nopaque-job-status-text" data-job-status="${operation.value}"></span>`, 'job');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -67,30 +67,29 @@ class CorpusDisplay extends RessourceDisplay {
 | 
			
		||||
    let element;
 | 
			
		||||
    let elements;
 | 
			
		||||
 | 
			
		||||
    this.setElements(this.displayElement.querySelectorAll('.corpus-status'), status);
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.analyse-corpus-trigger')
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.corpus-analyse-trigger')
 | 
			
		||||
    for (element of elements) {
 | 
			
		||||
      if (['analysing', 'prepared', 'start analysis'].includes(status)) {
 | 
			
		||||
      if (['BUILT', 'STARTING_ANALYSIS_SESSION', 'RUNNING_ANALYSIS_SESSION', 'CANCELING_ANALYSIS_SESSION'].includes(status)) {
 | 
			
		||||
        element.classList.remove('disabled');
 | 
			
		||||
      } else {
 | 
			
		||||
        element.classList.add('disabled');
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.build-corpus-trigger');
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.corpus-build-trigger');
 | 
			
		||||
    for (element of elements) {
 | 
			
		||||
      if (status === 'unprepared' && Object.values(app.users[this.userId].corpora[this.corpusId].files).length > 0) {
 | 
			
		||||
      if (status === 'UNPREPARED' && Object.values(app.users[this.userId].corpora[this.corpusId].files).length > 0) {
 | 
			
		||||
        element.classList.remove('disabled');
 | 
			
		||||
      } else {
 | 
			
		||||
        element.classList.add('disabled');
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.status');
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.corpus-status');
 | 
			
		||||
    for (element of elements) {
 | 
			
		||||
      element.dataset.status = status;
 | 
			
		||||
      element.dataset.corpusStatus = status;
 | 
			
		||||
    }
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.status-spinner');
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.corpus-status-spinner');
 | 
			
		||||
    for (element of elements) {
 | 
			
		||||
      if (['submitted', 'queued', 'running', 'canceling', 'start analysis', 'stop analysis'].includes(status)) {
 | 
			
		||||
      if (['SUBMITTED', 'QUEUED', 'BUILDING', 'STARTING_ANALYSIS_SESSION', 'CANCELING_ANALYSIS_SESSION'].includes(status)) {
 | 
			
		||||
        element.classList.remove('hide');
 | 
			
		||||
      } else {
 | 
			
		||||
        element.classList.add('hide');
 | 
			
		||||
 
 | 
			
		||||
@@ -57,23 +57,21 @@ class JobDisplay extends RessourceDisplay {
 | 
			
		||||
    let element;
 | 
			
		||||
    let elements;
 | 
			
		||||
 | 
			
		||||
    this.setElements(this.displayElement.querySelectorAll('.job-status'), status);
 | 
			
		||||
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.status');
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.job-status');
 | 
			
		||||
    for (element of elements) {
 | 
			
		||||
      element.dataset.status = status;
 | 
			
		||||
      element.dataset.jobStatus = status;
 | 
			
		||||
    }
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.status-spinner');
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.job-status-spinner');
 | 
			
		||||
    for (element of elements) {
 | 
			
		||||
      if (['complete', 'failed'].includes(status)) {
 | 
			
		||||
      if (['COMPLETED', 'FAILED'].includes(status)) {
 | 
			
		||||
        element.classList.add('hide');
 | 
			
		||||
      } else {
 | 
			
		||||
        element.classList.remove('hide');
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.restart-job-trigger');
 | 
			
		||||
    elements = this.displayElement.querySelectorAll('.job-restart-trigger');
 | 
			
		||||
    for (element of elements) {
 | 
			
		||||
      if (['complete', 'failed'].includes(status)) {
 | 
			
		||||
      if (['COMPLETED', 'FAILED'].includes(status)) {
 | 
			
		||||
        element.classList.remove('hide');
 | 
			
		||||
      } else {
 | 
			
		||||
        element.classList.add('hide');
 | 
			
		||||
 
 | 
			
		||||
@@ -5,31 +5,31 @@ class CorpusFileList extends RessourceList {
 | 
			
		||||
        <td><span class="filename"></span></td>
 | 
			
		||||
        <td><span class="author"></span></td>
 | 
			
		||||
        <td><span class="title"></span></td>
 | 
			
		||||
        <td><span class="publishing_year"></span></td>
 | 
			
		||||
        <td><span class="publishing-year"></span></td>
 | 
			
		||||
        <td class="right-align">
 | 
			
		||||
          <a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
          <a class="action-button btn-floating service-color darken tooltipped waves-effect waves-light" data-action="download" data-position="top" data-service="corpus-analysis" data-tooltip="View"><i class="material-icons">file_download</i></a>
 | 
			
		||||
          <a class="action-button btn-floating service-color darken tooltipped waves-effect waves-light" data-action="view" data-position="top" data-service="corpus-analysis" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
          <a class="action-button btn-floating tooltipped nopaque-service-color darken waves-effect waves-light" data-action="download" data-position="top" data-service="corpus-analysis" data-tooltip="View"><i class="material-icons">file_download</i></a>
 | 
			
		||||
          <a class="action-button btn-floating tooltipped nopaque-service-color darken waves-effect waves-light" data-action="view" data-position="top" data-service="corpus-analysis" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
        </td>
 | 
			
		||||
      </tr>
 | 
			
		||||
    `.trim(),
 | 
			
		||||
    ressourceMapper: corpusFile => {
 | 
			
		||||
      return {
 | 
			
		||||
        id: corpusFile.id,
 | 
			
		||||
        author: corpusFile.author,
 | 
			
		||||
        creationDate: corpusFile.creation_date,
 | 
			
		||||
        filename: corpusFile.filename,
 | 
			
		||||
        publishingYear: corpusFile.publishing_year,
 | 
			
		||||
        title: corpusFile.title
 | 
			
		||||
        'id': corpusFile.id,
 | 
			
		||||
        'author': corpusFile.author,
 | 
			
		||||
        'creation-date': corpusFile.creation_date,
 | 
			
		||||
        'filename': corpusFile.filename,
 | 
			
		||||
        'publishing-year': corpusFile.publishing_year,
 | 
			
		||||
        'title': corpusFile.title
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    sortValueName: 'creationDate',
 | 
			
		||||
    sortValueName: 'creation-date',
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      {data: ['id']},
 | 
			
		||||
      {data: ['creationDate']},
 | 
			
		||||
      {data: ['creation-date']},
 | 
			
		||||
      'author',
 | 
			
		||||
      'filename',
 | 
			
		||||
      'publishingYear',
 | 
			
		||||
      'publishing-year',
 | 
			
		||||
      'title'
 | 
			
		||||
    ]
 | 
			
		||||
  };
 | 
			
		||||
@@ -125,7 +125,7 @@ class CorpusFileList extends RessourceList {
 | 
			
		||||
          re = new RegExp(`^/users/${this.userId}/corpora/${this.corpusId}/files/([A-Za-z0-9]*)/(author|filename|publishing_year|title)$`);
 | 
			
		||||
          if (re.test(operation.path)) {
 | 
			
		||||
            [match, corpusFileId, valueName] = operation.path.match(re);
 | 
			
		||||
            this.replace(corpusFileId, valueName, operation.value);
 | 
			
		||||
            this.replace(corpusFileId, valueName.replace('_', '-'), operation.value);
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
 
 | 
			
		||||
@@ -2,29 +2,29 @@ class CorpusList extends RessourceList {
 | 
			
		||||
  static options = {
 | 
			
		||||
    item: `
 | 
			
		||||
      <tr class="hoverable">
 | 
			
		||||
        <td><a class="btn-floating disabled"><i class="material-icons service-color darken" data-service="corpus-analysis">book</i></a></td>
 | 
			
		||||
        <td><a class="btn-floating disabled"><i class="material-icons nopaque-service-color darken" data-service="corpus-analysis">book</i></a></td>
 | 
			
		||||
        <td><b class="title"></b><br><i class="description"></i></td>
 | 
			
		||||
        <td><span class="badge new status status-color status-text" data-badge-caption=""></span></td>
 | 
			
		||||
        <td><span class="status badge new nopaque-corpus-status-color nopaque-corpus-status-text" data-badge-caption=""></span></td>
 | 
			
		||||
        <td class="right-align">
 | 
			
		||||
          <a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
          <a class="action-button btn-floating service-color darken tooltipped waves-effect waves-light" data-action="view" data-position="top" data-service="corpus-analysis" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
          <a class="action-button btn-floating nopaque-service-color darken tooltipped waves-effect waves-light" data-action="view" data-position="top" data-service="corpus-analysis" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
        </td>
 | 
			
		||||
      </tr>
 | 
			
		||||
    `.trim(),
 | 
			
		||||
    ressourceMapper: corpus => {
 | 
			
		||||
      return {
 | 
			
		||||
        id: corpus.id,
 | 
			
		||||
        creationDate: corpus.creation_date,
 | 
			
		||||
        description: corpus.description,
 | 
			
		||||
        status: corpus.status,
 | 
			
		||||
        title: corpus.title
 | 
			
		||||
        'id': corpus.id,
 | 
			
		||||
        'creation-date': corpus.creation_date,
 | 
			
		||||
        'description': corpus.description,
 | 
			
		||||
        'status': corpus.status,
 | 
			
		||||
        'title': corpus.title
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    sortValueName: 'creationDate',
 | 
			
		||||
    sortValueName: 'creation-date',
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      {data: ['id']},
 | 
			
		||||
      {data: ['creationDate']},
 | 
			
		||||
      {name: 'status', attr: 'data-status'},
 | 
			
		||||
      {data: ['creation-date']},
 | 
			
		||||
      {name: 'status', attr: 'data-corpus-status'},
 | 
			
		||||
      'description',
 | 
			
		||||
      'title'
 | 
			
		||||
    ]
 | 
			
		||||
 
 | 
			
		||||
@@ -10,13 +10,17 @@ class JobInputList extends RessourceList {
 | 
			
		||||
    `.trim(),
 | 
			
		||||
    ressourceMapper: jobInput => {
 | 
			
		||||
      return {
 | 
			
		||||
        id: jobInput.id,
 | 
			
		||||
        creationDate: jobInput.creation_date,
 | 
			
		||||
        filename: jobInput.filename
 | 
			
		||||
        'id': jobInput.id,
 | 
			
		||||
        'creation-date': jobInput.creation_date,
 | 
			
		||||
        'filename': jobInput.filename
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    sortValueName: 'creationDate',
 | 
			
		||||
    valueNames: [{data: ['id']}, {data: ['creationDate']}, 'filename']
 | 
			
		||||
    sortValueName: 'creation-date',
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      {data: ['id']},
 | 
			
		||||
      {data: ['creation-date']},
 | 
			
		||||
      'filename'
 | 
			
		||||
    ]
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,36 +1,36 @@
 | 
			
		||||
class JobList extends RessourceList {
 | 
			
		||||
  static options = {
 | 
			
		||||
    item: `
 | 
			
		||||
      <tr class="hoverable service-color lighten">
 | 
			
		||||
        <td><a class="btn-floating disabled"><i class="nopaque-icons service-color darken serviceDuplicate1 service-icon"></i></a></td>
 | 
			
		||||
      <tr class="hoverable nopaque-service-color lighten">
 | 
			
		||||
        <td><a class="btn-floating disabled"><i class="service-1 nopaque-icon nopaque-service-color darken nopaque-service-icon"></i></a></td>
 | 
			
		||||
        <td><b class="title"></b><br><i class="description"></i></td>
 | 
			
		||||
        <td><span class="badge new status status-color status-text" data-badge-caption=""></span></td>
 | 
			
		||||
        <td><span class="status badge new nopaque-job-status-color nopaque-job-status-text" data-badge-caption=""></span></td>
 | 
			
		||||
        <td class="right-align">
 | 
			
		||||
          <a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
          <a class="action-button btn-floating serviceDuplicate2 service-color darken tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
          <a class="service-2 action-button btn-floating nopaque-service-color darken tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
        </td>
 | 
			
		||||
      </tr>
 | 
			
		||||
    `.trim(),
 | 
			
		||||
    ressourceMapper: job => {
 | 
			
		||||
      return {
 | 
			
		||||
        id: job.id,
 | 
			
		||||
        creationDate: job.creation_date,
 | 
			
		||||
        description: job.description,
 | 
			
		||||
        service: job.service,
 | 
			
		||||
        serviceDuplicate1: job.service,
 | 
			
		||||
        serviceDuplicate2: job.service,
 | 
			
		||||
        status: job.status,
 | 
			
		||||
        title: job.title
 | 
			
		||||
        'id': job.id,
 | 
			
		||||
        'creation-date': job.creation_date,
 | 
			
		||||
        'description': job.description,
 | 
			
		||||
        'service': job.service,
 | 
			
		||||
        'service-1': job.service,
 | 
			
		||||
        'service-2': job.service,
 | 
			
		||||
        'status': job.status,
 | 
			
		||||
        'title': job.title
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    sortValueName: 'creationDate',
 | 
			
		||||
    sortValueName: 'creation-date',
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      {data: ['id']},
 | 
			
		||||
      {data: ['creationDate']},
 | 
			
		||||
      {data: ['creation-date']},
 | 
			
		||||
      {data: ['service']},
 | 
			
		||||
      {name: 'serviceDuplicate1', attr: 'data-service'},
 | 
			
		||||
      {name: 'serviceDuplicate2', attr: 'data-service'},
 | 
			
		||||
      {name: 'status', attr: 'data-status'},
 | 
			
		||||
      {name: 'service-1', attr: 'data-service'},
 | 
			
		||||
      {name: 'service-2', attr: 'data-service'},
 | 
			
		||||
      {name: 'status', attr: 'data-job-status'},
 | 
			
		||||
      'description',
 | 
			
		||||
      'title'
 | 
			
		||||
    ]
 | 
			
		||||
 
 | 
			
		||||
@@ -11,16 +11,16 @@ class JobResultList extends RessourceList {
 | 
			
		||||
    `.trim(),
 | 
			
		||||
    ressourceMapper: jobResult => {
 | 
			
		||||
      return {
 | 
			
		||||
        id: jobResult.id,
 | 
			
		||||
        creationDate: jobResult.creation_date,
 | 
			
		||||
        description: jobResult.description,
 | 
			
		||||
        filename: jobResult.filename
 | 
			
		||||
        'id': jobResult.id,
 | 
			
		||||
        'creation-date': jobResult.creation_date,
 | 
			
		||||
        'description': jobResult.description,
 | 
			
		||||
        'filename': jobResult.filename
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    sortValueName: 'creationDate',
 | 
			
		||||
    sortValueName: 'creation-date',
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      {data: ['id']},
 | 
			
		||||
      {data: ['creationDate']},
 | 
			
		||||
      {data: ['creation-date']},
 | 
			
		||||
      'description',
 | 
			
		||||
      'filename'
 | 
			
		||||
    ]
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ class QueryResultList extends RessourceList {
 | 
			
		||||
    item: `
 | 
			
		||||
      <tr class="hoverable">
 | 
			
		||||
        <td><b class="title"></b><br><i class="description"></i><br></td>
 | 
			
		||||
        <td><span class="corpus_title"></span><br><span class="query"></span></td>
 | 
			
		||||
        <td><span class="corpus-title"></span><br><span class="query"></span></td>
 | 
			
		||||
        <td class="right-align">
 | 
			
		||||
          <a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
          <a class="action-button btn-floating tooltipped waves-effect waves-light" data-action="view" data-position="top" data-tooltip="View"><i class="material-icons">send</i></a>
 | 
			
		||||
@@ -12,19 +12,19 @@ class QueryResultList extends RessourceList {
 | 
			
		||||
    `.trim(),
 | 
			
		||||
    ressourceMapper: queryResult => {
 | 
			
		||||
      return {
 | 
			
		||||
        id: queryResult.id,
 | 
			
		||||
        corpusTitle: queryResult.corpus_title,
 | 
			
		||||
        creationDate: queryResult.creation_date,
 | 
			
		||||
        description: queryResult.description,
 | 
			
		||||
        query: queryResult.query,
 | 
			
		||||
        title: queryResult.title
 | 
			
		||||
        'id': queryResult.id,
 | 
			
		||||
        'corpus-title': queryResult.corpus_title,
 | 
			
		||||
        'creation-date': queryResult.creation_date,
 | 
			
		||||
        'description': queryResult.description,
 | 
			
		||||
        'query': queryResult.query,
 | 
			
		||||
        'title': queryResult.title
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    sortValueName: 'creationDate',
 | 
			
		||||
    sortValueName: 'creation-date',
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      {data: ['id']},
 | 
			
		||||
      {data: ['creationDate']},
 | 
			
		||||
      'corpusTitle',
 | 
			
		||||
      {data: ['creation-date']},
 | 
			
		||||
      'corpus-title',
 | 
			
		||||
      'description',
 | 
			
		||||
      'query',
 | 
			
		||||
      'title'
 | 
			
		||||
@@ -118,7 +118,7 @@ class QueryResultList extends RessourceList {
 | 
			
		||||
          re = new RegExp(`^/users/${this.userId}/query_results/([A-Za-z0-9]*)/(corpus_title|description|query|title)$`);
 | 
			
		||||
          if (re.test(operation.path)) {
 | 
			
		||||
            [match, queryResultId, valueName] = operation.path.match(re);
 | 
			
		||||
            this.replace(queryResultId, valueName, operation.value);
 | 
			
		||||
            this.replace(queryResultId, valueName.replace('_', '-'), operation.value);
 | 
			
		||||
          }
 | 
			
		||||
          break;
 | 
			
		||||
        default:
 | 
			
		||||
 
 | 
			
		||||
@@ -2,10 +2,10 @@ class UserList extends RessourceList {
 | 
			
		||||
  static options = {
 | 
			
		||||
    item: `
 | 
			
		||||
      <tr class="hoverable">
 | 
			
		||||
        <td><span class="idDuplicate"></span></td>
 | 
			
		||||
        <td><span class="id-1"></span></td>
 | 
			
		||||
        <td><span class="username"></span></td>
 | 
			
		||||
        <td><span class="email"></span></td>
 | 
			
		||||
        <td><span class="last_seen"></span></td>
 | 
			
		||||
        <td><span class="last-seen"></span></td>
 | 
			
		||||
        <td><span class="role"></span></td>
 | 
			
		||||
        <td class="right-align">
 | 
			
		||||
          <a class="action-button btn-floating red tooltipped waves-effect waves-light" data-action="delete" data-position="top" data-tooltip="Delete"><i class="material-icons">delete</i></a>
 | 
			
		||||
@@ -16,21 +16,22 @@ class UserList extends RessourceList {
 | 
			
		||||
    `.trim(),
 | 
			
		||||
    ressourceMapper: user => {
 | 
			
		||||
      return {
 | 
			
		||||
        id: user.id,
 | 
			
		||||
        idDuplicate: user.id,
 | 
			
		||||
        username: user.username,
 | 
			
		||||
        email: user.email,
 | 
			
		||||
        last_seen: new Date(user.last_seen).toLocaleString("en-US"),
 | 
			
		||||
        role: user.role.name
 | 
			
		||||
        'id': user.id,
 | 
			
		||||
        'id-1': user.id,
 | 
			
		||||
        'username': user.username,
 | 
			
		||||
        'email': user.email,
 | 
			
		||||
        'last-seen': new Date(user.last_seen).toLocaleString("en-US"),
 | 
			
		||||
        'member-since': user.member_since,
 | 
			
		||||
        'role': user.role.name
 | 
			
		||||
      };
 | 
			
		||||
    },
 | 
			
		||||
    sortValueName: 'memberSince',
 | 
			
		||||
    sortValueName: 'member-since',
 | 
			
		||||
    valueNames: [
 | 
			
		||||
      {data: ['id']},
 | 
			
		||||
      {data: ['memberSince']},
 | 
			
		||||
      {data: ['member-since']},
 | 
			
		||||
      'email',
 | 
			
		||||
      'idDuplicate',
 | 
			
		||||
      'last_seen',
 | 
			
		||||
      'id-1',
 | 
			
		||||
      'last-seen',
 | 
			
		||||
      'role',
 | 
			
		||||
      'username'
 | 
			
		||||
    ]
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user