Skip to content

Commit f7ebb0c

Browse files
authored
Merge pull request #643 from kbss-cvut/bug#642-custom-iri-with-hashtag
Bug#642 custom iri with hashtag
2 parents bbd4867 + 1adc04b commit f7ebb0c

File tree

9 files changed

+58
-29
lines changed

9 files changed

+58
-29
lines changed

src/component/resource/document/FileContentActions.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,8 @@ const FileContentActions: React.FC<FileContentActionsProps> = ({
5252
["fileName", fileIri.fragment],
5353
]);
5454
const query = new Map<string, string>([
55-
["namespace", vocabularyIri.namespace!],
56-
["fileNamespace", fileIri.namespace!],
55+
["namespace", encodeURIComponent(vocabularyIri.namespace!)],
56+
["fileNamespace", encodeURIComponent(fileIri.namespace!)],
5757
]);
5858
Routing.transitionTo(Routes.annotateFile, { params, query });
5959
};

src/component/term/CreateTerm.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { ThunkDispatch } from "../../util/Types";
66
import { createTerm } from "../../action/AsyncTermActions";
77
import { loadVocabulary } from "../../action/AsyncActions";
88
import TermMetadataCreate from "./TermMetadataCreate";
9-
import Routing from "../../util/Routing";
9+
import Routing, { namespaceQueryParam } from "../../util/Routing";
1010
import Routes from "../../util/Routes";
1111
import IdentifierResolver from "../../util/IdentifierResolver";
1212
import TermItState from "../../model/TermItState";
@@ -54,7 +54,7 @@ export class CreateTerm extends React.Component<CreateTermProps> {
5454
}
5555
const termName = IdentifierResolver.extractNameFromLocation(location);
5656
const params = new Map([["name", vocabularyIri.fragment]]);
57-
const query = new Map([["namespace", vocabularyIri.namespace!]]);
57+
const query = namespaceQueryParam(vocabularyIri.namespace!);
5858
if (newTerm) {
5959
Routing.transitionTo(Routes.createVocabularyTerm, { params, query });
6060
Routing.reload();

src/component/term/Terms.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
consumeNotification,
1414
selectVocabularyTerm,
1515
} from "../../action/SyncActions";
16-
import Routing from "../../util/Routing";
16+
import Routing, { namespaceQueryParam } from "../../util/Routing";
1717
import Routes from "../../util/Routes";
1818
import Term, { TermData } from "../../model/Term";
1919
import { loadTerms } from "../../action/AsyncActions";
@@ -180,7 +180,7 @@ export class Terms extends React.Component<GlossaryTermsProps, TermsState> {
180180
Routing.transitionTo(Routes.createVocabularyTerm, {
181181
params: new Map([["name", vocabularyIri.fragment]]),
182182
query: vocabularyIri.namespace
183-
? new Map([["namespace", vocabularyIri.namespace]])
183+
? namespaceQueryParam(vocabularyIri.namespace)
184184
: undefined,
185185
});
186186
};

src/component/term/__tests__/CreateTerm.test.tsx

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ import { langString } from "../../../model/MultilingualString";
1313
import Constants from "../../../util/Constants";
1414
import { intlFunctions } from "../../../__tests__/environment/IntlUtil";
1515

16-
jest.mock("../../../util/Routing");
16+
jest.mock("../../../util/Routing", () => ({
17+
default: jest.fn(),
18+
namespaceQueryParam: jest.requireActual("../../../util/Routing")
19+
.namespaceQueryParam,
20+
}));
1721

1822
describe("CreateTerm", () => {
1923
const namespace = "http://onto.fel.cvut.cz/ontologies/termit/vocabularies/";
@@ -59,6 +63,8 @@ describe("CreateTerm", () => {
5963
isExact: true,
6064
url: "http://localhost:3000/" + location.pathname,
6165
};
66+
Routing.transitionTo = jest.fn();
67+
Routing.reload = jest.fn();
6268
});
6369

6470
it("invokes on create on create call", () => {
@@ -107,7 +113,9 @@ describe("CreateTerm", () => {
107113
"test-term"
108114
);
109115
expect((call[1].query as Map<string, string>).get("namespace")).toEqual(
110-
"http://onto.fel.cvut.cz/ontologies/termit/vocabularies/"
116+
encodeURIComponent(
117+
"http://onto.fel.cvut.cz/ontologies/termit/vocabularies/"
118+
)
111119
);
112120
});
113121
});
@@ -135,7 +143,9 @@ describe("CreateTerm", () => {
135143
"test-vocabulary"
136144
);
137145
expect((call[1].query as Map<string, string>).get("namespace")).toEqual(
138-
"http://onto.fel.cvut.cz/ontologies/termit/vocabularies/"
146+
encodeURIComponent(
147+
"http://onto.fel.cvut.cz/ontologies/termit/vocabularies/"
148+
)
139149
);
140150
});
141151
});

src/component/term/__tests__/TermLink.test.tsx

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ describe("TermLink", () => {
5454
</MemoryRouter>
5555
).find(Link);
5656
expect((link.props() as any).to).toEqual(
57-
`/vocabularies/${vocFragment}/terms/${termFragment}?namespace=${vocNamespace}`
57+
`/vocabularies/${vocFragment}/terms/${termFragment}?namespace=${encodeURIComponent(
58+
vocNamespace
59+
)}`
5860
);
5961
});
6062

@@ -93,7 +95,9 @@ describe("TermLink", () => {
9395
</MemoryRouter>
9496
).find(Link);
9597
expect((link.props() as any).to).toEqual(
96-
`/public/vocabularies/${vocFragment}/terms/${termFragment}?namespace=${vocNamespace}`
98+
`/public/vocabularies/${vocFragment}/terms/${termFragment}?namespace=${encodeURIComponent(
99+
vocNamespace
100+
)}`
97101
);
98102
});
99103

src/component/vocabulary/__tests__/VocabularyLink.test.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ describe("Vocabulary Link links to correct internal asset", () => {
3131
</MemoryRouter>
3232
).find(Link);
3333
expect((link.props() as any).to).toEqual(
34-
"/vocabularies/" + fragment + "?namespace=" + namespace
34+
"/vocabularies/" +
35+
fragment +
36+
"?namespace=" +
37+
encodeURIComponent(namespace)
3538
);
3639
});
3740

@@ -43,7 +46,10 @@ describe("Vocabulary Link links to correct internal asset", () => {
4346
</MemoryRouter>
4447
).find(Link);
4548
expect((link.props() as any).to).toEqual(
46-
"/public/vocabularies/" + fragment + "?namespace=" + namespace
49+
"/public/vocabularies/" +
50+
fragment +
51+
"?namespace=" +
52+
encodeURIComponent(namespace)
4753
);
4854
});
4955
});

src/util/Routing.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,12 @@ const INSTANCE = new Routing();
219219

220220
export default INSTANCE;
221221

222+
export function namespaceQueryParam(namespace: string) {
223+
return new Map<string, string>([
224+
["namespace", encodeURIComponent(namespace)],
225+
]);
226+
}
227+
222228
export class Terms {
223229
public static getTermRoutingOptions(term: Term | TermData | TermInfo) {
224230
const loggedIn = isLoggedIn(TermItStore.getState().user);
@@ -240,7 +246,7 @@ export class Terms {
240246
["termName", termName],
241247
["timestamp", timestamp],
242248
]),
243-
query: new Map<string, string>([["namespace", namespace]]),
249+
query: namespaceQueryParam(namespace),
244250
};
245251
} else {
246252
const iri = VocabularyUtils.create(term.iri!);
@@ -251,7 +257,7 @@ export class Terms {
251257
["name", vocIri.fragment],
252258
["termName", iri.fragment],
253259
]),
254-
query: new Map<string, string>([["namespace", vocIri.namespace!]]),
260+
query: namespaceQueryParam(vocIri.namespace!),
255261
};
256262
}
257263
}
@@ -304,14 +310,14 @@ export class Vocabularies {
304310
["name", name],
305311
["timestamp", timestamp],
306312
]),
307-
query: new Map<string, string>([["namespace", namespace]]),
313+
query: namespaceQueryParam(namespace),
308314
};
309315
} else {
310316
const iri = VocabularyUtils.create(vocabulary.iri);
311317
return {
312318
route,
313319
params: new Map<string, string>([["name", iri.fragment]]),
314-
query: new Map<string, string>([["namespace", iri.namespace!]]),
320+
query: namespaceQueryParam(iri.namespace!),
315321
};
316322
}
317323
}
@@ -348,7 +354,7 @@ export class Vocabularies {
348354
route,
349355
params: new Map<string, string>([["name", iri.fragment]]),
350356
query: new Map<string, string>([
351-
["namespace", iri.namespace!],
357+
["namespace", encodeURIComponent(iri.namespace!)],
352358
["activeTab", TABS.document],
353359
]),
354360
};

src/util/VocabularyUtils.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,10 @@ const VocabularyUtils = {
200200
create(iri: string): IRIImpl {
201201
const hashFragment = iri.indexOf("#");
202202
const slashFragment = iri.lastIndexOf("/");
203-
const fragment = hashFragment < 0 ? slashFragment : hashFragment;
203+
const fragment =
204+
hashFragment < 0 || hashFragment < slashFragment
205+
? slashFragment
206+
: hashFragment;
204207
return new IRIImpl(
205208
iri.substring(fragment + 1),
206209
iri.substring(0, fragment + 1)

src/util/__tests__/Routing.test.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ describe("Routing", () => {
3535
const name = "test-vocabulary";
3636
const namespace = "http://onto.fel.cvut.cz/ontologies/termit/vocabulary/";
3737
const path = Routing.getTransitionPath(Routes.vocabularies, {
38-
query: new Map([["namespace", namespace]]),
38+
query: new Map([["namespace", encodeURIComponent(namespace)]]),
3939
});
4040
const expectedPath =
4141
Routes.vocabularies.path.replace(":name", name) +
4242
"?namespace=" +
43-
namespace;
43+
encodeURIComponent(namespace);
4444
expect(path).toEqual(expectedPath);
4545
});
4646
});
@@ -58,14 +58,14 @@ describe("Routing", () => {
5858
const iri = namespace + label;
5959

6060
it("transitions to vocabulary summary for a vocabulary", () => {
61-
const vocabulary = new Vocabulary({ iri, label });
61+
const vocabulary = new Vocabulary({ iri, label: langString(label) });
6262
TermItStore.getState().user = Generator.generateUser();
6363

6464
RoutingInstance.transitionToAsset(vocabulary);
6565
expect(historyMock.push).toHaveBeenCalledWith(
6666
Routing.getTransitionPath(Routes.vocabularySummary, {
6767
params: new Map([["name", label]]),
68-
query: new Map([["namespace", namespace]]),
68+
query: new Map([["namespace", encodeURIComponent(namespace)]]),
6969
})
7070
);
7171
});
@@ -87,7 +87,7 @@ describe("Routing", () => {
8787
["name", label],
8888
["timestamp", timestamp],
8989
]),
90-
query: new Map([["namespace", namespace]]),
90+
query: new Map([["namespace", encodeURIComponent(namespace)]]),
9191
})
9292
);
9393
});
@@ -105,7 +105,7 @@ describe("Routing", () => {
105105
["name", label],
106106
["termName", termName],
107107
]),
108-
query: new Map([["namespace", namespace]]),
108+
query: new Map([["namespace", encodeURIComponent(namespace)]]),
109109
})
110110
);
111111
});
@@ -129,7 +129,7 @@ describe("Routing", () => {
129129
["termName", termName],
130130
["timestamp", timestamp],
131131
]),
132-
query: new Map([["namespace", namespace]]),
132+
query: new Map([["namespace", encodeURIComponent(namespace)]]),
133133
})
134134
);
135135
});
@@ -142,12 +142,12 @@ describe("Routing", () => {
142142

143143
it("transitions to public vocabulary summary for a vocabulary", () => {
144144
TermItStore.getState().user = EMPTY_USER;
145-
const vocabulary = new Vocabulary({ iri, label });
145+
const vocabulary = new Vocabulary({ iri, label: langString(label) });
146146
RoutingInstance.transitionToPublicAsset(vocabulary);
147147
expect(historyMock.push).toHaveBeenCalledWith(
148148
Routing.getTransitionPath(Routes.publicVocabularySummary, {
149149
params: new Map([["name", label]]),
150-
query: new Map([["namespace", namespace]]),
150+
query: new Map([["namespace", encodeURIComponent(namespace)]]),
151151
})
152152
);
153153
});
@@ -164,7 +164,7 @@ describe("Routing", () => {
164164
["name", label],
165165
["termName", term.label[Constants.DEFAULT_LANGUAGE]],
166166
]),
167-
query: new Map([["namespace", namespace]]),
167+
query: new Map([["namespace", encodeURIComponent(namespace)]]),
168168
})
169169
);
170170
});

0 commit comments

Comments
 (0)