Fix tag color error with backward compatibility. (#908)

* Get next color from method instead of index.

* Improve getNextColor performance.

* Add method to fill tag color.

* Refactor and implement getNextColor.

* Refactor.

* Support shared token.
This commit is contained in:
SimoTw 2021-03-25 20:00:40 +08:00 коммит произвёл GitHub
Родитель 7e9f700876
Коммит e445dccfcb
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
5 изменённых файлов: 47 добавлений и 29 удалений

Просмотреть файл

@ -334,21 +334,21 @@ export function patch<T, K extends keyof T>(data: T[], diff: T[], key: K, proper
});
}
export function getNextColor(tags: ITag[]) {
for (const color of tagColors) {
let vacancy = true;
for (const tag of tags) {
if (color.toLowerCase() === tag.color.toLowerCase()) {
vacancy = false;
break;
export function getNextColor(tags: ITag[]): string {
if (tags.length <= tagColors.length - 1) {
for (const color of tagColors) {
let vacancy = true;
for (const tag of tags) {
if (color.toLowerCase() === tag.color.toLowerCase()) {
vacancy = false;
break;
}
}
if (vacancy) {
return color;
}
}
if (vacancy) {
return color;
}
}
return tagColors[randomIntInRange(0, tagColors.length - 1)];
}
@ -558,3 +558,15 @@ export class URIUtils {
return params;
}
}
export function fillTagsColor(project: IProject): IProject {
/** Add a color to tags which tag.color == null */
const supportedColors = new Set(tagColors);
return {
...project,
tags: project.tags.map((tag: ITag) => ({
...tag,
color: supportedColors.has(tag.color) ? tag.color : getNextColor(project.tags)
}))
}
}

Просмотреть файл

@ -25,7 +25,7 @@ import {
ErrorCode, AppError, IAppSettings,
} from "../../../../models/applicationState";
import {StorageProviderFactory} from "../../../../providers/storage/storageProviderFactory";
import {decryptProject} from "../../../../common/utils";
import {decryptProject, fillTagsColor} from "../../../../common/utils";
import {toast} from "react-toastify";
import {isElectron} from "../../../../common/hostProcess";
import ProjectService from "../../../../services/projectService";
@ -134,7 +134,7 @@ export default class HomePage extends React.Component<IHomePageProps, IHomePageS
<CloudFilePicker
ref={this.cloudFilePickerRef}
connections={this.props.connections}
onSubmit={(content, sharedToken?) => this.loadSelectedProject(JSON.parse(content), sharedToken)}
onSubmit={this.onCloudPickerClick}
fileExtension={constants.projectFileExtension}
/>
</ul>
@ -266,8 +266,8 @@ export default class HomePage extends React.Component<IHomePageProps, IHomePageS
throw err;
}
}
const selectedProject = {...JSON.parse(projectStr), sourceConnection: project.sourceConnection};
await this.loadSelectedProject(selectedProject);
const selectedProject = { ...JSON.parse(projectStr), sourceConnection: project.sourceConnection };
await this.loadSelectedProject(fillTagsColor(selectedProject));
} catch (err) {
if (err instanceof AppError && err.errorCode === ErrorCode.BlobContainerIONotFound) {
const reason = interpolate(strings.errors.projectNotFound.message, {file: `${project.name}${constants.projectFileExtension}`, container: project.sourceConnection.name});
@ -316,4 +316,9 @@ export default class HomePage extends React.Component<IHomePageProps, IHomePageS
throw error;
}
}
private onCloudPickerClick = (content, sharedToken?) => {
const project = JSON.parse(content);
this.loadSelectedProject(fillTagsColor(project), sharedToken);
}
}

Просмотреть файл

@ -22,7 +22,7 @@ import { bindActionCreators } from "redux";
import { constants } from "../../../../common/constants";
import { interpolate, strings } from "../../../../common/strings";
import { getPrimaryWhiteTheme, getLightGreyTheme } from "../../../../common/themes";
import { poll } from "../../../../common/utils";
import { getNextColor, poll } from "../../../../common/utils";
import { ErrorCode, FieldFormat, FieldType, IApplicationState, IPrebuiltSettings, ITag } from "../../../../models/applicationState";
import IAppTitleActions, * as appTitleActions from "../../../../redux/actions/appTitleActions";
import IAppPrebuiltSettingsActions, * as appPrebuiltSettingsActions from "../../../../redux/actions/prebuiltSettingsActions";
@ -174,7 +174,6 @@ export class PrebuiltPredictPage extends React.Component<IPrebuiltPredictPagePro
private tableHelper: ITableHelper = new TableHelper(this);
private imageMap: ImageMap;
private tagColors = require("../../common/tagColors.json");
public async componentDidMount() {
const { appTitleActions, prebuiltSettings } = this.props;
@ -738,9 +737,10 @@ export class PrebuiltPredictPage extends React.Component<IPrebuiltPredictPagePro
private getTagsForPredictResults(predictions) {
const tags: ITag[] = [];
Object.keys(predictions).forEach((key, index) => {
const color = getNextColor(tags);
tags.push({
name: key,
color: this.tagColors[index],
color,
// use default type
type: FieldType.String,
format: FieldFormat.NotSpecified,

Просмотреть файл

@ -5,8 +5,7 @@ import {ActionTypes} from "../actions/actionTypes";
import {IProject, ITag} from "../../models/applicationState";
import {AnyAction} from "../actions/actionCreators";
import _ from "lodash";
// tslint:disable-next-line:no-var-requires
const tagColors = require("../../react/components/common/tagColors.json");
import { getNextColor } from "../../common/utils";
/**
* Reducer for project. Actions handled:
@ -70,9 +69,10 @@ export const reducer = (state: IProject = null, action: AnyAction): IProject =>
assetTags.forEach((tag) => {
if (!state.tags || state.tags.length === 0 ||
!state.tags.find((projectTag) => tag === projectTag.name)) {
const color = getNextColor(newTags);
newTags.push({
name: tag,
color: tagColors[newTags.length % tagColors.length],
color,
} as ITag);
updateTags = true;
}

Просмотреть файл

@ -21,9 +21,6 @@ import { toast } from "react-toastify";
import clone from "rfdc";
import _ from "lodash";
// tslint:disable-next-line:no-var-requires
const tagColors = require("../react/components/common/tagColors.json");
function normalizeFieldType(type: string): string {
if (type === "checkbox") {
return FieldType.SelectionMark;
@ -305,9 +302,10 @@ export default class ProjectService implements IProjectService {
throw new Error("Invalid label file");
}
tagNameArray.forEach((name, index) => {
const color = getNextColor(tags);
tags.push({
name,
color: tagColors[index],
color,
// use default type
type: FieldType.String,
format: FieldFormat.NotSpecified,
@ -364,9 +362,10 @@ export default class ProjectService implements IProjectService {
return;
}
if (field.fieldType === FieldType.Object) {
const color = getNextColor(tags);
tags.push({
name: field.fieldKey,
color: tagColors[index],
color,
type: normalizeFieldType(field.fieldType),
format: field.fieldFormat,
documentCount: 0,
@ -376,9 +375,10 @@ export default class ProjectService implements IProjectService {
visualizationHint: (field as ITableField).visualizationHint || TableVisualizationHint.Vertical
} as ITableTag);
} else {
const color = getNextColor(tags);
tags.push({
name: field.fieldKey,
color: tagColors[index],
color,
type: normalizeFieldType(field.fieldType),
format: field.fieldFormat,
documentCount: 0,
@ -390,9 +390,10 @@ export default class ProjectService implements IProjectService {
}
} else {
const color = getNextColor(tags);
tags.push({
name: field.fieldKey,
color: tagColors[index],
color,
type: normalizeFieldType(field.fieldType),
format: field.fieldFormat,
documentCount: 0,